#include #include #include #ifndef XFRACT #include #include #else #include #endif #include #include "port.h" #include "prototyp.h" /* Memory allocation routines. */ #if 1 /* For extra seg memory: */ #define EXTRA_RESERVE 4096L /* amount of extra mem we will leave avail. */ /* For far memory: */ #define FAR_RESERVE 8192L /* amount of far mem we will leave avail. */ /* For expanded memory: */ #define EXPWRITELEN 16384L /* max # bytes transferred to/from expanded mem at once */ /* For extended memory: */ #define XMMWRITELEN 8192L /* max # bytes transferred to/from extended mem at once */ /* For disk memory: */ #define DISKWRITELEN 2048L /* max # bytes transferred to/from disk mem at once */ BYTE far *charbuf = NULL; int numEXThandles; long ext_xfer_size; U16 start_avail_extra = 0; #endif #define MAXHANDLES 256 /* arbitrary #, suitably big */ char memfile[] = "handle.$$$"; int numTOTALhandles; #ifndef XFRACT char memstr[6][9] = {"nowhere", "extraseg", "far", "expanded", "extended", "disk"}; #endif #ifdef XFRACT char memstr[3][9] = {{"nowhere"}, {"far"}, {"disk"}}; #endif struct nowhere { enum stored_at_values stored_at; /* first 2 entries must be the same */ long size; /* for each of these data structures */ }; struct farmem { enum stored_at_values stored_at; long size; BYTE far *farmemory; }; struct disk { enum stored_at_values stored_at; long size; FILE *file; }; #ifndef XFRACT struct extra { enum stored_at_values stored_at; long size; BYTE far *extramemory; }; struct expanded { enum stored_at_values stored_at; long size; int oldexppage; int mempages; int emmhandle; BYTE far *expmemory; }; struct extended { enum stored_at_values stored_at; long size; int mempages; int xmmhandle; }; #endif union mem { struct nowhere Nowhere; struct farmem Farmem; struct disk Disk; #ifndef XFRACT struct extra Extra; struct expanded Expanded; struct extended Extended; #endif }; union mem far handletable[MAXHANDLES]; /* Routines in this module */ #ifndef XFRACT U32 GetDiskSpace(void); static void _fastcall near exp_seek(U16 handle, int page); /* expanded mem seek */ #endif static int _fastcall near CheckDiskSpace(long howmuch); static int check_for_mem(int stored_at, long howmuch); static U16 next_handle(void); static int CheckBounds (long start, long length, U16 handle); static void WhichDiskError(int); static void DisplayError(int stored_at, long howmuch); /* Routines in this module, visible to outside routines */ void DisplayMemory (void); void DisplayHandle (U16 handle); int MemoryType (U16 handle); void InitMemory (void); void ExitCheck (void); U16 MemoryAlloc(U16 size, long count, int stored_at); void MemoryRelease(U16 handle); int MoveToMemory(BYTE far *buffer,U16 size,long count,long offset,U16 handle); int MoveFromMemory(BYTE far *buffer,U16 size,long count,long offset,U16 handle); int SetMemory(int value,U16 size,long count,long offset,U16 handle); /* Memory handling support routines */ #ifndef XFRACT U32 GetDiskSpace(void) { /* Returns the number of bytes available on the current disk drive. */ U32 available = 0; union REGS regs; regs.h.ah = 0x36; /* Function 36, Get Disk Free Space */ regs.h.dl = 0; /* Check the default drive */ intdos(®s, ®s); if (regs.x.ax != 0xFFFF) /* Drive is valid */ available = (U32)regs.x.ax * regs.x.bx * regs.x.cx; return (available); } #endif static int _fastcall near CheckDiskSpace(long howmuch) { int EnoughSpace = FALSE; #ifndef XFRACT U32 available; available = GetDiskSpace(); if (available > (U32)howmuch) EnoughSpace = TRUE; #endif #ifdef XFRACT /* This will need to be fixed for XFRACT ????? */ EnoughSpace = TRUE; #endif return(EnoughSpace); } static void WhichDiskError(int I_O) { /* Set I_O == 1 after a file create, I_O == 2 after a file set value */ /* Set I_O == 3 after a file write, I_O == 4 after a file read */ #ifndef XFRACT char buf[MSGLEN]; char nmsg[MSGLEN]; static FCODE fmsg1[] = {"Disk file creation error"}; static FCODE fmsg2[] = {"Disk file set error"}; static FCODE fmsg3[] = {"Disk file write error"}; static FCODE fmsg4[] = {"Disk file read error"}; /* The following and the associated sprintf eat up 432 bytes of near memory. Only marginally useful for debugging purposes. static FCODE fmsg1[] = {"Create file error %d: %s"}; static FCODE fmsg2[] = {"Set file error %d: %s"}; static FCODE fmsg3[] = {"Write file error %d: %s"}; static FCODE fmsg4[] = {"Read file error %d: %s"}; */ switch (I_O) { default: case 1: far_strcpy(nmsg,fmsg1); break; case 2: far_strcpy(nmsg,fmsg2); break; case 3: far_strcpy(nmsg,fmsg3); break; case 4: far_strcpy(nmsg,fmsg4); break; } sprintf(buf,nmsg); /* sprintf(buf,nmsg,errno,strerror(errno)); */ if (debugflag == 10000) if(stopmsg(6,(char far *)buf) == -1) goodbye(); /* bailout if ESC */ #endif } #ifndef XFRACT static void _fastcall near exp_seek(U16 handle, int page) /* expanded mem seek */ { static U16 lasthandle = 0; if (page != handletable[handle].Expanded.oldexppage || page == 0 || lasthandle != handle) { /* time to get a new page? */ handletable[handle].Expanded.oldexppage = page; lasthandle = handle; emmgetpage(page, handletable[handle].Expanded.emmhandle); } } #endif int MemoryType (U16 handle) { return (handletable[handle].Nowhere.stored_at); } static void DisplayError(int stored_at, long howmuch) { /* This routine is used to display an error message when the requested */ /* memory type cannot be allocated due to insufficient memory, AND there */ /* is also insufficient disk space to use as memory. */ char buf[MSGLEN*2]; char nmsg[MSGLEN*2]; static FCODE fmsg[] = {"Allocating %ld Bytes of %s memory failed.\nAlternate disk space is also insufficient. Goodbye"}; far_strcpy(nmsg,fmsg); sprintf(buf,nmsg,howmuch,memstr[stored_at]); stopmsg(0,(char far *)buf); } static int check_for_mem(int stored_at, long howmuch) { /* This function returns an adjusted stored_at value. */ /* This is where the memory requested can be allocated. */ #ifndef XFRACT long usedmem, totalmem; long longtmp; int counter; #endif long maxmem; BYTE far *temp; int use_this_type; use_this_type = NOWHERE; maxmem = (long)USHRT_MAX; /* limit EXTRA and FARMEM to 64K */ /* limit EXPANDED and EXTENDED to 64K blocks */ if (debugflag == 420) stored_at = DISK; if (debugflag == 422) stored_at = EXTENDED; switch (stored_at) { #ifndef XFRACT case EXTRA: /* check_for_mem */ usedmem = 0L; for(counter = 0; counter < MAXHANDLES; counter++) if (handletable[counter].Nowhere.stored_at == EXTRA) usedmem += handletable[counter].Extra.size; if ((maxmem - usedmem) > howmuch) { use_this_type = EXTRA; break; } /* failed, fall through and try far memory */ #endif case FARMEM: /* check_for_mem */ if (maxmem > howmuch) { temp = farmemalloc(howmuch + FAR_RESERVE); if (temp != NULL) { /* minimum free space + requested amount */ farmemfree(temp); use_this_type = FARMEM; break; } } #ifndef XFRACT /* Failed, fall through and try expanded memory */ case EXPANDED: /* check_for_mem */ totalmem = (howmuch + 16383) >> 14; /* # of 16 KB blocks */ if ((totalmem < (long)USHRT_MAX) && (emmquery() != NULL)) { maxmem = emmgetfree(); /* reuse maxmem, so may not be good below */ if (maxmem > totalmem) { use_this_type = EXPANDED; break; } } /* Failed, fall through and try extended memory */ case EXTENDED: /* check_for_mem */ longtmp = (howmuch + 1023) >> 10; /* # of 1 KB blocks */ if (longtmp <= 0) longtmp = 1; if (xmmquery() != 0) if ((longtmp < (long)USHRT_MAX) && ((long)xmmfree() > longtmp)) { use_this_type = EXTENDED; break; } /* failed, fall through and try disk memory */ #endif case DISK: /* check_for_mem */ default: /* just in case a nonsense number gets used */ if (CheckDiskSpace(howmuch)) { use_this_type = DISK; break; } /* failed, fall through, no memory available */ case NOWHERE: /* check_for_mem */ use_this_type = NOWHERE; break; } /* end of switch */ return(use_this_type); } static U16 next_handle() { U16 counter = 1; /* don't use handle 0 */ while(handletable[counter].Nowhere.stored_at != NOWHERE && counter < MAXHANDLES) counter++; return (counter); } static int CheckBounds (long start, long length, U16 handle) { if(handletable[handle].Nowhere.size - start - length < 0) { static FCODE msg[] = {"Memory reference out of bounds."}; stopmsg(20,msg); DisplayHandle(handle); return (1); } if(length > (long)USHRT_MAX) { static FCODE msg[] = {"Tried to move > 65,535 bytes."}; stopmsg(20,msg); DisplayHandle(handle); return (1); } if(handletable[handle].Nowhere.stored_at == DISK && (stackavail() <= DISKWRITELEN) ) { static FCODE msg[] = {"Stack space insufficient for disk memory."}; stopmsg(20,msg); DisplayHandle(handle); return (1); } if(length <= 0) { static FCODE msg[] = {"Zero or negative length."}; stopmsg(20,msg); DisplayHandle(handle); return (1); } if(start < 0) { static FCODE msg[] = {"Negative offset."}; stopmsg(20,msg); DisplayHandle(handle); return (1); } return (0); } void DisplayMemory (void) { #ifndef XFRACT long tmpfar; U32 tmpdisk; char buf[MSGLEN]; char nmsg[MSGLEN]; /* #ifdef XFRACT static FCODE fmsg[] = {"far=%ld, disk=%lu"}; */ static FCODE fmsg[] = {"extra=%ld, far=%ld, expanded=%ld,\nextended=%ld, disk=%lu"}; long tmpextra, tmpexp, tmpext; tmpextra = USHRT_MAX - start_avail_extra; if (emmquery() != NULL) tmpexp = (long)emmgetfree() * 16L * 1024L; else tmpexp = 0; if (xmmquery() != 0) tmpext = (long)xmmfree() * 1024L; else tmpext = 0; tmpdisk = GetDiskSpace(); /* fix this for XFRACT ????? */ tmpfar = fr_farfree(); far_strcpy(nmsg,fmsg); sprintf(buf,nmsg,tmpextra,tmpfar,tmpexp,tmpext,tmpdisk); stopmsg(20,(char far *)buf); #endif } void DisplayHandle (U16 handle) { char buf[MSGLEN]; char nmsg[MSGLEN]; static FCODE fmsg[] = {"Handle %u, type %s, size %li"}; far_strcpy(nmsg,fmsg); sprintf(buf,nmsg,handle,memstr[handletable[handle].Nowhere.stored_at], handletable[handle].Nowhere.size); if(stopmsg(6,(char far *)buf) == -1) goodbye(); /* bailout if ESC, it's messy, but should work */ } void InitMemory (void) { int counter; #ifndef XFRACT long longtmp; #endif numTOTALhandles = 0; for (counter = 0; counter < MAXHANDLES; counter++) { handletable[counter].Nowhere.stored_at = NOWHERE; handletable[counter].Nowhere.size = 0; } #ifndef XFRACT numEXThandles = 0; longtmp = fr_farfree(); ext_xfer_size = XMMWRITELEN; /* 8192 */ if (longtmp < (long)XMMWRITELEN * 8) ext_xfer_size = XMMWRITELEN / 2; /* 4096 */ if (longtmp < (long)XMMWRITELEN) ext_xfer_size = XMMWRITELEN / 8; /* 1024, won't work, try anyway */ #endif } void ExitCheck (void) { U16 i; if(/*charbuf != NULL ||*/ numEXThandles != 0 || numTOTALhandles != 0) { static FCODE msg[] = {"Error - not all memory released, I'll get it."}; stopmsg(0,msg); for (i = 1; i < MAXHANDLES; i++) if (handletable[i].Nowhere.stored_at != NOWHERE) { char buf[MSGLEN]; char nmsg[MSGLEN]; static FCODE fmsg[] = {"Memory type %s still allocated. Handle = %i."}; far_strcpy(nmsg,fmsg); sprintf(buf,nmsg,memstr[handletable[i].Nowhere.stored_at],i); stopmsg(0,(char far *)buf); MemoryRelease(i); } } } /* * * * * */ /* Memory handling routines */ U16 MemoryAlloc(U16 size, long count, int stored_at) { /* Returns handle number if successful, 0 or NULL if failure */ U16 handle = 0; int success, use_this_type; long toallocate; #ifndef XFRACT BYTE far *temp; long longtmp; int mempages = 0; struct XMM_Move MoveStruct; #endif success = FALSE; toallocate = count * size; if (toallocate <= 0) /* we failed, can't allocate > 2,147,483,647 */ return((U16)success); /* or it wraps around to negative */ /* check structure for requested memory type (add em up) to see if sufficient amount is available to grant request */ use_this_type = check_for_mem(stored_at, toallocate); if (use_this_type == NOWHERE) { DisplayError(stored_at, toallocate); goodbye(); } /* get next available handle */ handle = next_handle(); if (handle >= MAXHANDLES || handle <= 0) { DisplayHandle(handle); return((U16)success); /* Oops, do something about this! ????? */ } /* attempt to allocate requested memory type */ switch (use_this_type) { default: case NOWHERE: /* MemoryAlloc */ use_this_type = NOWHERE; /* in case nonsense value is passed */ break; #ifndef XFRACT case EXTRA: /* MemoryAlloc */ handletable[handle].Extra.size = toallocate; handletable[handle].Extra.stored_at = EXTRA; handletable[handle].Extra.extramemory = (BYTE far *)MK_FP(extraseg,start_avail_extra); start_avail_extra += (U16)toallocate; numTOTALhandles++; success = TRUE; break; #endif case FARMEM: /* MemoryAlloc */ /* Availability of far memory checked in check_for_mem() */ handletable[handle].Farmem.farmemory = farmemalloc(toallocate); handletable[handle].Farmem.size = toallocate; handletable[handle].Farmem.stored_at = FARMEM; numTOTALhandles++; success = TRUE; break; #ifndef XFRACT case EXPANDED: /* MemoryAlloc */ mempages = (int)((toallocate + 16383) >> 14); if (emmquery() != NULL) { handletable[handle].Expanded.mempages = mempages; handletable[handle].Expanded.expmemory = emmquery(); if ((handletable[handle].Expanded.emmhandle = emmallocate(mempages)) != 0) { handletable[handle].Expanded.oldexppage = 0; handletable[handle].Expanded.size = toallocate; handletable[handle].Expanded.stored_at = EXPANDED; numTOTALhandles++; success = TRUE; break; } } case EXTENDED: /* MemoryAlloc */ /* This is ugly! Need far memory to use extended memory. */ if (charbuf == NULL) { /* first time through, allocate buffer */ temp = farmemalloc((long)ext_xfer_size + FAR_RESERVE); if (temp != NULL) /* minimum free space + requested amount */ { farmemfree(temp); charbuf = farmemalloc((long)ext_xfer_size); } else goto dodisk; } if (toallocate < ext_xfer_size) longtmp = (ext_xfer_size + 1023) >> 10; else longtmp = (toallocate + 1023) >> 10; if (xmmquery() != 0 && (handletable[handle].Extended.xmmhandle = xmmallocate((U16)(longtmp))) != 0) { longtmp /= (ext_xfer_size >> 10); handletable[handle].Extended.mempages = (int)longtmp; far_memset(charbuf, 0, (int)ext_xfer_size); /* zero the buffer */ MoveStruct.SourceHandle = 0; /* Source is in conventional memory */ MoveStruct.SourceOffset = (U32)charbuf; MoveStruct.DestHandle = handletable[handle].Extended.xmmhandle; MoveStruct.DestOffset = 0; MoveStruct.Length = (long)ext_xfer_size; while (--longtmp >= 0) { if ((success = xmmmoveextended(&MoveStruct)) == 0) break; MoveStruct.DestOffset += ext_xfer_size; } if (success) { /* put in structure */ success = TRUE; handletable[handle].Extended.size = toallocate; handletable[handle].Extended.stored_at = EXTENDED; numTOTALhandles++; numEXThandles++; break; } xmmdeallocate(handletable[handle].Extended.xmmhandle); /* Clear the memory */ handletable[handle].Extended.xmmhandle = 0; /* Signal same */ } /* need to fall through and use disk memory, or will crash fractint */ dodisk: #endif case DISK: /* MemoryAlloc */ memfile[9] = (char)(handle % 10 + (int)'0'); memfile[8] = (char)((handle % 100) / 10 + (int)'0'); memfile[7] = (char)((handle % 1000) / 100 + (int)'0'); if (disktarga) handletable[handle].Disk.file = dir_fopen(workdir,light_name, "a+b"); else handletable[handle].Disk.file = dir_fopen(tempdir,memfile, "w+b"); rewind(handletable[handle].Disk.file); if (fseek(handletable[handle].Disk.file,toallocate,SEEK_SET) != 0) handletable[handle].Disk.file = NULL; if (handletable[handle].Disk.file == NULL) { handletable[handle].Disk.stored_at = NOWHERE; use_this_type = NOWHERE; WhichDiskError(1); DisplayMemory(); buzzer(3); break; } numTOTALhandles++; success = TRUE; fclose(handletable[handle].Disk.file); /* so clusters aren't lost if we crash while running */ if (disktarga) handletable[handle].Disk.file = dir_fopen(workdir,light_name, "r+b"); else handletable[handle].Disk.file = dir_fopen(tempdir,memfile,"r+b"); /* reopen */ rewind(handletable[handle].Disk.file); handletable[handle].Disk.size = toallocate; handletable[handle].Disk.stored_at = DISK; use_this_type = DISK; break; } /* end of switch */ if (stored_at != use_this_type && debugflag == 10000) { char buf[MSGLEN]; char nmsg[MSGLEN]; static FCODE fmsg[] = {"Asked for %s, allocated %lu bytes of %s, handle = %u."}; far_strcpy(nmsg,fmsg); sprintf(buf,nmsg,memstr[stored_at],toallocate,memstr[use_this_type],handle); stopmsg(20,(char far *)buf); DisplayMemory(); } if (success) return (handle); else /* return 0 if failure */ return 0; } void MemoryRelease(U16 handle) { switch(handletable[handle].Nowhere.stored_at) { case NOWHERE: /* MemoryRelease */ break; #ifndef XFRACT case EXTRA: /* MemoryRelease */ /* Deallocate in the reverse order of allocation. */ start_avail_extra -= (U16)handletable[handle].Extra.size; handletable[handle].Extra.size = 0; handletable[handle].Extra.stored_at = NOWHERE; handletable[handle].Extra.extramemory = NULL; numTOTALhandles--; break; #endif case FARMEM: /* MemoryRelease */ farmemfree(handletable[handle].Farmem.farmemory); handletable[handle].Farmem.farmemory = NULL; handletable[handle].Farmem.size = 0; handletable[handle].Farmem.stored_at = NOWHERE; numTOTALhandles--; break; #ifndef XFRACT case EXPANDED: /* MemoryRelease */ emmdeallocate(handletable[handle].Expanded.emmhandle); handletable[handle].Expanded.emmhandle = 0; handletable[handle].Expanded.size = 0; handletable[handle].Expanded.stored_at = NOWHERE; numTOTALhandles--; break; case EXTENDED: /* MemoryRelease */ /* far memory allocated for this must be released */ numEXThandles--; xmmdeallocate(handletable[handle].Extended.xmmhandle); if (numEXThandles == 0) { farmemfree(charbuf); charbuf = NULL; } handletable[handle].Extended.xmmhandle = 0; handletable[handle].Extended.size = 0; handletable[handle].Extended.stored_at = NOWHERE; numTOTALhandles--; break; #endif case DISK: /* MemoryRelease */ memfile[9] = (char)(handle % 10 + (int)'0'); memfile[8] = (char)((handle % 100) / 10 + (int)'0'); memfile[7] = (char)((handle % 1000) / 100 + (int)'0'); fclose(handletable[handle].Disk.file); dir_remove(tempdir,memfile); handletable[handle].Disk.file = NULL; handletable[handle].Disk.size = 0; handletable[handle].Disk.stored_at = NOWHERE; numTOTALhandles--; break; } /* end of switch */ } int MoveToMemory(BYTE far *buffer,U16 size,long count,long offset,U16 handle) { /* buffer is a pointer to local memory */ /* Always start moving from the beginning of buffer */ /* offset is the number of units from the start of the allocated "Memory" */ /* to start moving the contents of buffer to */ /* size is the size of the unit, count is the number of units to move */ /* Returns TRUE if successful, FALSE if failure */ #ifndef XFRACT int currpage; long tmplength; struct XMM_Move MoveStruct; #endif BYTE diskbuf[DISKWRITELEN]; long start; /* offset to first location to move to */ long tomove; /* number of bytes to move */ U16 numwritten, i; int success; success = FALSE; start = (long)offset * size; tomove = (long)count * size; if (debugflag == 10000) if (CheckBounds(start, tomove, handle)) return(success); /* out of bounds, don't do it */ switch(handletable[handle].Nowhere.stored_at) { case NOWHERE: /* MoveToMemory */ DisplayHandle(handle); break; #ifndef XFRACT case EXTRA: /* MoveToMemory */ far_memcpy(handletable[handle].Extra.extramemory+start, buffer, (U16)tomove); success = TRUE; /* No way to gauge success or failure */ break; #endif case FARMEM: /* MoveToMemory */ for(i=0;i tomove) tmplength = tomove; far_memcpy(handletable[handle].Expanded.expmemory+start, buffer, (U16)tmplength); buffer += tmplength; tomove -= tmplength; /* At a page boundary, move until less than a page left */ while (tomove >= EXPWRITELEN) { currpage++; exp_seek(handle, currpage); far_memcpy(handletable[handle].Expanded.expmemory, buffer, (U16)EXPWRITELEN); buffer += EXPWRITELEN; tomove -= EXPWRITELEN; } /* Less than a page left, move it */ if (tomove > 0) /* still some left */ { currpage++; exp_seek(handle, currpage); far_memcpy(handletable[handle].Expanded.expmemory, buffer, (U16)tomove); } exp_seek(handle, 0); /* flush the last page out of the page frame */ success = TRUE; /* No way to gauge success or failure */ break; case EXTENDED: /* MoveToMemory */ MoveStruct.Length = ext_xfer_size; MoveStruct.SourceHandle = 0; /* Source is conventional memory */ MoveStruct.SourceOffset = (U32)charbuf; MoveStruct.DestHandle = handletable[handle].Extended.xmmhandle; MoveStruct.DestOffset = (U32)start; while (tomove > ext_xfer_size) { far_memcpy(charbuf,buffer,(int)ext_xfer_size); xmmmoveextended(&MoveStruct); start += ext_xfer_size; tomove -= ext_xfer_size; buffer += ext_xfer_size; MoveStruct.DestOffset = (U32)(start); } far_memcpy(charbuf,buffer,(U16)tomove); MoveStruct.Length = (tomove % 2) ? tomove + 1 : tomove; /* must be even */ success = xmmmoveextended(&MoveStruct); break; #endif case DISK: /* MoveToMemory */ rewind(handletable[handle].Disk.file); fseek(handletable[handle].Disk.file,start,SEEK_SET); while (tomove > DISKWRITELEN) { far_memcpy(diskbuf,buffer,(U16)DISKWRITELEN); numwritten = (U16)write1(diskbuf,(U16)DISKWRITELEN,1,handletable[handle].Disk.file); if (numwritten != 1) { WhichDiskError(3); goto diskerror; } tomove -= DISKWRITELEN; buffer += DISKWRITELEN; } far_memcpy(diskbuf,buffer,(U16)tomove); numwritten = (U16)write1(diskbuf,(U16)tomove,1,handletable[handle].Disk.file); if (numwritten != 1) { WhichDiskError(3); break; } success = TRUE; diskerror: break; } /* end of switch */ if (!success && debugflag == 10000) DisplayHandle(handle); return (success); } int MoveFromMemory(BYTE far *buffer,U16 size,long count,long offset,U16 handle) { /* buffer points is the location to move the data to */ /* offset is the number of units from the beginning of buffer to start moving */ /* size is the size of the unit, count is the number of units to move */ /* Returns TRUE if successful, FALSE if failure */ #ifndef XFRACT int currpage; long tmplength; struct XMM_Move MoveStruct; #endif BYTE diskbuf[DISKWRITELEN]; long start; /* first location to move */ long tomove; /* number of bytes to move */ U16 numread, i; int success; success = FALSE; start = (long)offset * size; tomove = (long)count * size; if (debugflag == 10000) if (CheckBounds(start, tomove, handle)) return(success); /* out of bounds, don't do it */ switch(handletable[handle].Nowhere.stored_at) { case NOWHERE: /* MoveFromMemory */ DisplayHandle(handle); break; #ifndef XFRACT case EXTRA: /* MoveFromMemory */ far_memcpy(buffer, handletable[handle].Extra.extramemory+start, (U16)tomove); success = TRUE; /* No way to gauge success or failure */ break; #endif case FARMEM: /* MoveFromMemory */ for(i=0;i tomove) tmplength = tomove; far_memcpy(buffer, handletable[handle].Expanded.expmemory+start, (U16)tmplength); buffer += tmplength; tomove -= tmplength; /* At a page boundary, move until less than a page left */ while (tomove >= EXPWRITELEN) { currpage++; exp_seek(handle, currpage); far_memcpy(buffer, handletable[handle].Expanded.expmemory, (U16)EXPWRITELEN); buffer += EXPWRITELEN; tomove -= EXPWRITELEN; } /* Less than a page left, move it */ if (tomove > 0) /* still some left */ { currpage++; exp_seek(handle, currpage); far_memcpy(buffer, handletable[handle].Expanded.expmemory, (U16)tomove); } exp_seek(handle, 0); /* flush the last page out of the page frame */ success = TRUE; /* No way to gauge success or failure */ break; case EXTENDED: /* MoveFromMemory */ MoveStruct.Length = ext_xfer_size; MoveStruct.SourceHandle = handletable[handle].Extended.xmmhandle; MoveStruct.SourceOffset = (U32)start; MoveStruct.DestHandle = 0; /* Destination is conventional memory */ MoveStruct.DestOffset = (U32)charbuf; while (tomove > ext_xfer_size) { xmmmoveextended(&MoveStruct); far_memcpy(buffer,charbuf,(int)ext_xfer_size); buffer += ext_xfer_size; tomove -= ext_xfer_size; start += ext_xfer_size; MoveStruct.SourceOffset = (U32)start; } MoveStruct.Length = (tomove % 2) ? tomove + 1 : tomove; /* must be even */ success = xmmmoveextended(&MoveStruct); far_memcpy(buffer,charbuf,(U16)tomove); break; #endif case DISK: /* MoveFromMemory */ rewind(handletable[handle].Disk.file); fseek(handletable[handle].Disk.file,start,SEEK_SET); while (tomove > DISKWRITELEN) { numread = (U16)fread(diskbuf,(U16)DISKWRITELEN,1,handletable[handle].Disk.file); if (numread != 1 && !feof(handletable[handle].Disk.file)) { WhichDiskError(4); goto diskerror; } far_memcpy(buffer,diskbuf,(U16)DISKWRITELEN); tomove -= DISKWRITELEN; buffer += DISKWRITELEN; } numread = (U16)fread(diskbuf,(U16)tomove,1,handletable[handle].Disk.file); if (numread != 1 && !feof(handletable[handle].Disk.file)) { WhichDiskError(4); break; } far_memcpy(buffer,diskbuf,(U16)tomove); success = TRUE; diskerror: break; } /* end of switch */ if (!success && debugflag == 10000) DisplayHandle(handle); return (success); } int SetMemory(int value,U16 size,long count,long offset,U16 handle) { /* value is the value to set memory to */ /* offset is the number of units from the start of allocated memory */ /* size is the size of the unit, count is the number of units to set */ /* Returns TRUE if successful, FALSE if failure */ #ifndef XFRACT int currpage; long tmplength; struct XMM_Move MoveStruct; #endif BYTE diskbuf[DISKWRITELEN]; long start; /* first location to set */ long tomove; /* number of bytes to set */ U16 numwritten, i; int success; success = FALSE; start = (long)offset * size; tomove = (long)count * size; if (debugflag == 10000) if (CheckBounds(start, tomove, handle)) return(success); /* out of bounds, don't do it */ switch(handletable[handle].Nowhere.stored_at) { case NOWHERE: /* SetMemory */ DisplayHandle(handle); break; #ifndef XFRACT case EXTRA: /* SetMemory */ far_memset(handletable[handle].Extra.extramemory+start, value, (U16)tomove); success = TRUE; /* No way to gauge success or failure */ break; #endif case FARMEM: /* SetMemory */ for(i=0;i tomove) tmplength = tomove; far_memset(handletable[handle].Expanded.expmemory+start, value, (U16)tmplength); tomove -= tmplength; /* At a page boundary, move until less than a page left */ while (tomove >= EXPWRITELEN) { currpage++; exp_seek(handle, currpage); far_memcpy(handletable[handle].Expanded.expmemory, &value, (U16)EXPWRITELEN); tomove -= EXPWRITELEN; } /* Less than a page left, move it */ if (tomove > 0) /* still some left */ { currpage++; exp_seek(handle, currpage); far_memcpy(handletable[handle].Expanded.expmemory, &value, (U16)tomove); } exp_seek(handle, 0); /* flush the last page out of the page frame */ success = TRUE; /* No way to gauge success or failure */ break; case EXTENDED: /* SetMemory */ MoveStruct.Length = ext_xfer_size; MoveStruct.SourceHandle = 0; /* Source is conventional memory */ MoveStruct.SourceOffset = (U32)charbuf; MoveStruct.DestHandle = handletable[handle].Extended.xmmhandle; MoveStruct.DestOffset = (U32)start; far_memset(charbuf, value, (int)ext_xfer_size); while (tomove > ext_xfer_size) { xmmmoveextended(&MoveStruct); start += ext_xfer_size; tomove -= ext_xfer_size; MoveStruct.DestOffset = (U32)(start); } MoveStruct.Length = (tomove % 2) ? tomove + 1 : tomove; /* must be even */ success = xmmmoveextended(&MoveStruct); break; #endif case DISK: /* SetMemory */ far_memset(diskbuf, value, (U16)DISKWRITELEN); rewind(handletable[handle].Disk.file); fseek(handletable[handle].Disk.file,start,SEEK_SET); while (tomove > DISKWRITELEN) { numwritten = (U16)write1(diskbuf,(U16)DISKWRITELEN,1,handletable[handle].Disk.file); if (numwritten != 1) { WhichDiskError(2); goto diskerror; } tomove -= DISKWRITELEN; } numwritten = (U16)write1(diskbuf,(U16)tomove,1,handletable[handle].Disk.file); if (numwritten != 1) { WhichDiskError(2); break; } success = TRUE; diskerror: break; } /* end of switch */ if (!success && debugflag == 10000) DisplayHandle(handle); return (success); }