17dd7cddfSDavid du Colombier /*
27dd7cddfSDavid du Colombier * jmemdos.c
37dd7cddfSDavid du Colombier *
4*593dc095SDavid du Colombier * Copyright (C) 1992-1997, Thomas G. Lane.
57dd7cddfSDavid du Colombier * This file is part of the Independent JPEG Group's software.
67dd7cddfSDavid du Colombier * For conditions of distribution and use, see the accompanying README file.
77dd7cddfSDavid du Colombier *
87dd7cddfSDavid du Colombier * This file provides an MS-DOS-compatible implementation of the system-
97dd7cddfSDavid du Colombier * dependent portion of the JPEG memory manager. Temporary data can be
107dd7cddfSDavid du Colombier * stored in extended or expanded memory as well as in regular DOS files.
117dd7cddfSDavid du Colombier *
127dd7cddfSDavid du Colombier * If you use this file, you must be sure that NEED_FAR_POINTERS is defined
137dd7cddfSDavid du Colombier * if you compile in a small-data memory model; it should NOT be defined if
147dd7cddfSDavid du Colombier * you use a large-data memory model. This file is not recommended if you
157dd7cddfSDavid du Colombier * are using a flat-memory-space 386 environment such as DJGCC or Watcom C.
167dd7cddfSDavid du Colombier * Also, this code will NOT work if struct fields are aligned on greater than
177dd7cddfSDavid du Colombier * 2-byte boundaries.
187dd7cddfSDavid du Colombier *
197dd7cddfSDavid du Colombier * Based on code contributed by Ge' Weijers.
207dd7cddfSDavid du Colombier */
217dd7cddfSDavid du Colombier
227dd7cddfSDavid du Colombier /*
237dd7cddfSDavid du Colombier * If you have both extended and expanded memory, you may want to change the
247dd7cddfSDavid du Colombier * order in which they are tried in jopen_backing_store. On a 286 machine
257dd7cddfSDavid du Colombier * expanded memory is usually faster, since extended memory access involves
267dd7cddfSDavid du Colombier * an expensive protected-mode-and-back switch. On 386 and better, extended
277dd7cddfSDavid du Colombier * memory is usually faster. As distributed, the code tries extended memory
287dd7cddfSDavid du Colombier * first (what? not everyone has a 386? :-).
297dd7cddfSDavid du Colombier *
307dd7cddfSDavid du Colombier * You can disable use of extended/expanded memory entirely by altering these
317dd7cddfSDavid du Colombier * definitions or overriding them from the Makefile (eg, -DEMS_SUPPORTED=0).
327dd7cddfSDavid du Colombier */
337dd7cddfSDavid du Colombier
347dd7cddfSDavid du Colombier #ifndef XMS_SUPPORTED
357dd7cddfSDavid du Colombier #define XMS_SUPPORTED 1
367dd7cddfSDavid du Colombier #endif
377dd7cddfSDavid du Colombier #ifndef EMS_SUPPORTED
387dd7cddfSDavid du Colombier #define EMS_SUPPORTED 1
397dd7cddfSDavid du Colombier #endif
407dd7cddfSDavid du Colombier
417dd7cddfSDavid du Colombier
427dd7cddfSDavid du Colombier #define JPEG_INTERNALS
437dd7cddfSDavid du Colombier #include "jinclude.h"
447dd7cddfSDavid du Colombier #include "jpeglib.h"
457dd7cddfSDavid du Colombier #include "jmemsys.h" /* import the system-dependent declarations */
467dd7cddfSDavid du Colombier
477dd7cddfSDavid du Colombier #ifndef HAVE_STDLIB_H /* <stdlib.h> should declare these */
487dd7cddfSDavid du Colombier extern void * malloc JPP((size_t size));
497dd7cddfSDavid du Colombier extern void free JPP((void *ptr));
507dd7cddfSDavid du Colombier extern char * getenv JPP((const char * name));
517dd7cddfSDavid du Colombier #endif
527dd7cddfSDavid du Colombier
537dd7cddfSDavid du Colombier #ifdef NEED_FAR_POINTERS
547dd7cddfSDavid du Colombier
557dd7cddfSDavid du Colombier #ifdef __TURBOC__
567dd7cddfSDavid du Colombier /* These definitions work for Borland C (Turbo C) */
577dd7cddfSDavid du Colombier #include <alloc.h> /* need farmalloc(), farfree() */
587dd7cddfSDavid du Colombier #define far_malloc(x) farmalloc(x)
597dd7cddfSDavid du Colombier #define far_free(x) farfree(x)
607dd7cddfSDavid du Colombier #else
617dd7cddfSDavid du Colombier /* These definitions work for Microsoft C and compatible compilers */
627dd7cddfSDavid du Colombier #include <malloc.h> /* need _fmalloc(), _ffree() */
637dd7cddfSDavid du Colombier #define far_malloc(x) _fmalloc(x)
647dd7cddfSDavid du Colombier #define far_free(x) _ffree(x)
657dd7cddfSDavid du Colombier #endif
667dd7cddfSDavid du Colombier
677dd7cddfSDavid du Colombier #else /* not NEED_FAR_POINTERS */
687dd7cddfSDavid du Colombier
697dd7cddfSDavid du Colombier #define far_malloc(x) malloc(x)
707dd7cddfSDavid du Colombier #define far_free(x) free(x)
717dd7cddfSDavid du Colombier
727dd7cddfSDavid du Colombier #endif /* NEED_FAR_POINTERS */
737dd7cddfSDavid du Colombier
747dd7cddfSDavid du Colombier #ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
757dd7cddfSDavid du Colombier #define READ_BINARY "r"
767dd7cddfSDavid du Colombier #else
777dd7cddfSDavid du Colombier #define READ_BINARY "rb"
787dd7cddfSDavid du Colombier #endif
797dd7cddfSDavid du Colombier
80*593dc095SDavid du Colombier #ifndef USE_MSDOS_MEMMGR /* make sure user got configuration right */
81*593dc095SDavid du Colombier You forgot to define USE_MSDOS_MEMMGR in jconfig.h. /* deliberate syntax error */
82*593dc095SDavid du Colombier #endif
83*593dc095SDavid du Colombier
847dd7cddfSDavid du Colombier #if MAX_ALLOC_CHUNK >= 65535L /* make sure jconfig.h got this right */
857dd7cddfSDavid du Colombier MAX_ALLOC_CHUNK should be less than 64K. /* deliberate syntax error */
867dd7cddfSDavid du Colombier #endif
877dd7cddfSDavid du Colombier
887dd7cddfSDavid du Colombier
897dd7cddfSDavid du Colombier /*
907dd7cddfSDavid du Colombier * Declarations for assembly-language support routines (see jmemdosa.asm).
917dd7cddfSDavid du Colombier *
927dd7cddfSDavid du Colombier * The functions are declared "far" as are all their pointer arguments;
937dd7cddfSDavid du Colombier * this ensures the assembly source code will work regardless of the
947dd7cddfSDavid du Colombier * compiler memory model. We assume "short" is 16 bits, "long" is 32.
957dd7cddfSDavid du Colombier */
967dd7cddfSDavid du Colombier
977dd7cddfSDavid du Colombier typedef void far * XMSDRIVER; /* actually a pointer to code */
987dd7cddfSDavid du Colombier typedef struct { /* registers for calling XMS driver */
997dd7cddfSDavid du Colombier unsigned short ax, dx, bx;
1007dd7cddfSDavid du Colombier void far * ds_si;
1017dd7cddfSDavid du Colombier } XMScontext;
1027dd7cddfSDavid du Colombier typedef struct { /* registers for calling EMS driver */
1037dd7cddfSDavid du Colombier unsigned short ax, dx, bx;
1047dd7cddfSDavid du Colombier void far * ds_si;
1057dd7cddfSDavid du Colombier } EMScontext;
1067dd7cddfSDavid du Colombier
1077dd7cddfSDavid du Colombier extern short far jdos_open JPP((short far * handle, char far * filename));
1087dd7cddfSDavid du Colombier extern short far jdos_close JPP((short handle));
1097dd7cddfSDavid du Colombier extern short far jdos_seek JPP((short handle, long offset));
1107dd7cddfSDavid du Colombier extern short far jdos_read JPP((short handle, void far * buffer,
1117dd7cddfSDavid du Colombier unsigned short count));
1127dd7cddfSDavid du Colombier extern short far jdos_write JPP((short handle, void far * buffer,
1137dd7cddfSDavid du Colombier unsigned short count));
1147dd7cddfSDavid du Colombier extern void far jxms_getdriver JPP((XMSDRIVER far *));
1157dd7cddfSDavid du Colombier extern void far jxms_calldriver JPP((XMSDRIVER, XMScontext far *));
1167dd7cddfSDavid du Colombier extern short far jems_available JPP((void));
1177dd7cddfSDavid du Colombier extern void far jems_calldriver JPP((EMScontext far *));
1187dd7cddfSDavid du Colombier
1197dd7cddfSDavid du Colombier
1207dd7cddfSDavid du Colombier /*
1217dd7cddfSDavid du Colombier * Selection of a file name for a temporary file.
1227dd7cddfSDavid du Colombier * This is highly system-dependent, and you may want to customize it.
1237dd7cddfSDavid du Colombier */
1247dd7cddfSDavid du Colombier
1257dd7cddfSDavid du Colombier static int next_file_num; /* to distinguish among several temp files */
1267dd7cddfSDavid du Colombier
1277dd7cddfSDavid du Colombier LOCAL(void)
select_file_name(char * fname)1287dd7cddfSDavid du Colombier select_file_name (char * fname)
1297dd7cddfSDavid du Colombier {
1307dd7cddfSDavid du Colombier const char * env;
1317dd7cddfSDavid du Colombier char * ptr;
1327dd7cddfSDavid du Colombier FILE * tfile;
1337dd7cddfSDavid du Colombier
1347dd7cddfSDavid du Colombier /* Keep generating file names till we find one that's not in use */
1357dd7cddfSDavid du Colombier for (;;) {
1367dd7cddfSDavid du Colombier /* Get temp directory name from environment TMP or TEMP variable;
1377dd7cddfSDavid du Colombier * if none, use "."
1387dd7cddfSDavid du Colombier */
1397dd7cddfSDavid du Colombier if ((env = (const char *) getenv("TMP")) == NULL)
1407dd7cddfSDavid du Colombier if ((env = (const char *) getenv("TEMP")) == NULL)
1417dd7cddfSDavid du Colombier env = ".";
1427dd7cddfSDavid du Colombier if (*env == '\0') /* null string means "." */
1437dd7cddfSDavid du Colombier env = ".";
1447dd7cddfSDavid du Colombier ptr = fname; /* copy name to fname */
1457dd7cddfSDavid du Colombier while (*env != '\0')
1467dd7cddfSDavid du Colombier *ptr++ = *env++;
1477dd7cddfSDavid du Colombier if (ptr[-1] != '\\' && ptr[-1] != '/')
1487dd7cddfSDavid du Colombier *ptr++ = '\\'; /* append backslash if not in env variable */
1497dd7cddfSDavid du Colombier /* Append a suitable file name */
1507dd7cddfSDavid du Colombier next_file_num++; /* advance counter */
1517dd7cddfSDavid du Colombier sprintf(ptr, "JPG%03d.TMP", next_file_num);
1527dd7cddfSDavid du Colombier /* Probe to see if file name is already in use */
1537dd7cddfSDavid du Colombier if ((tfile = fopen(fname, READ_BINARY)) == NULL)
1547dd7cddfSDavid du Colombier break;
1557dd7cddfSDavid du Colombier fclose(tfile); /* oops, it's there; close tfile & try again */
1567dd7cddfSDavid du Colombier }
1577dd7cddfSDavid du Colombier }
1587dd7cddfSDavid du Colombier
1597dd7cddfSDavid du Colombier
1607dd7cddfSDavid du Colombier /*
1617dd7cddfSDavid du Colombier * Near-memory allocation and freeing are controlled by the regular library
1627dd7cddfSDavid du Colombier * routines malloc() and free().
1637dd7cddfSDavid du Colombier */
1647dd7cddfSDavid du Colombier
1657dd7cddfSDavid du Colombier GLOBAL(void *)
jpeg_get_small(j_common_ptr cinfo,size_t sizeofobject)1667dd7cddfSDavid du Colombier jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
1677dd7cddfSDavid du Colombier {
1687dd7cddfSDavid du Colombier return (void *) malloc(sizeofobject);
1697dd7cddfSDavid du Colombier }
1707dd7cddfSDavid du Colombier
1717dd7cddfSDavid du Colombier GLOBAL(void)
jpeg_free_small(j_common_ptr cinfo,void * object,size_t sizeofobject)1727dd7cddfSDavid du Colombier jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
1737dd7cddfSDavid du Colombier {
1747dd7cddfSDavid du Colombier free(object);
1757dd7cddfSDavid du Colombier }
1767dd7cddfSDavid du Colombier
1777dd7cddfSDavid du Colombier
1787dd7cddfSDavid du Colombier /*
1797dd7cddfSDavid du Colombier * "Large" objects are allocated in far memory, if possible
1807dd7cddfSDavid du Colombier */
1817dd7cddfSDavid du Colombier
1827dd7cddfSDavid du Colombier GLOBAL(void FAR *)
jpeg_get_large(j_common_ptr cinfo,size_t sizeofobject)1837dd7cddfSDavid du Colombier jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
1847dd7cddfSDavid du Colombier {
1857dd7cddfSDavid du Colombier return (void FAR *) far_malloc(sizeofobject);
1867dd7cddfSDavid du Colombier }
1877dd7cddfSDavid du Colombier
1887dd7cddfSDavid du Colombier GLOBAL(void)
jpeg_free_large(j_common_ptr cinfo,void FAR * object,size_t sizeofobject)1897dd7cddfSDavid du Colombier jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
1907dd7cddfSDavid du Colombier {
1917dd7cddfSDavid du Colombier far_free(object);
1927dd7cddfSDavid du Colombier }
1937dd7cddfSDavid du Colombier
1947dd7cddfSDavid du Colombier
1957dd7cddfSDavid du Colombier /*
1967dd7cddfSDavid du Colombier * This routine computes the total memory space available for allocation.
1977dd7cddfSDavid du Colombier * It's impossible to do this in a portable way; our current solution is
1987dd7cddfSDavid du Colombier * to make the user tell us (with a default value set at compile time).
1997dd7cddfSDavid du Colombier * If you can actually get the available space, it's a good idea to subtract
2007dd7cddfSDavid du Colombier * a slop factor of 5% or so.
2017dd7cddfSDavid du Colombier */
2027dd7cddfSDavid du Colombier
2037dd7cddfSDavid du Colombier #ifndef DEFAULT_MAX_MEM /* so can override from makefile */
2047dd7cddfSDavid du Colombier #define DEFAULT_MAX_MEM 300000L /* for total usage about 450K */
2057dd7cddfSDavid du Colombier #endif
2067dd7cddfSDavid du Colombier
2077dd7cddfSDavid du Colombier GLOBAL(long)
jpeg_mem_available(j_common_ptr cinfo,long min_bytes_needed,long max_bytes_needed,long already_allocated)2087dd7cddfSDavid du Colombier jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
2097dd7cddfSDavid du Colombier long max_bytes_needed, long already_allocated)
2107dd7cddfSDavid du Colombier {
2117dd7cddfSDavid du Colombier return cinfo->mem->max_memory_to_use - already_allocated;
2127dd7cddfSDavid du Colombier }
2137dd7cddfSDavid du Colombier
2147dd7cddfSDavid du Colombier
2157dd7cddfSDavid du Colombier /*
2167dd7cddfSDavid du Colombier * Backing store (temporary file) management.
2177dd7cddfSDavid du Colombier * Backing store objects are only used when the value returned by
2187dd7cddfSDavid du Colombier * jpeg_mem_available is less than the total space needed. You can dispense
2197dd7cddfSDavid du Colombier * with these routines if you have plenty of virtual memory; see jmemnobs.c.
2207dd7cddfSDavid du Colombier */
2217dd7cddfSDavid du Colombier
2227dd7cddfSDavid du Colombier /*
2237dd7cddfSDavid du Colombier * For MS-DOS we support three types of backing storage:
2247dd7cddfSDavid du Colombier * 1. Conventional DOS files. We access these by direct DOS calls rather
2257dd7cddfSDavid du Colombier * than via the stdio package. This provides a bit better performance,
2267dd7cddfSDavid du Colombier * but the real reason is that the buffers to be read or written are FAR.
2277dd7cddfSDavid du Colombier * The stdio library for small-data memory models can't cope with that.
2287dd7cddfSDavid du Colombier * 2. Extended memory, accessed per the XMS V2.0 specification.
2297dd7cddfSDavid du Colombier * 3. Expanded memory, accessed per the LIM/EMS 4.0 specification.
2307dd7cddfSDavid du Colombier * You'll need copies of those specs to make sense of the related code.
2317dd7cddfSDavid du Colombier * The specs are available by Internet FTP from the SIMTEL archives
2327dd7cddfSDavid du Colombier * (oak.oakland.edu and its various mirror sites). See files
2337dd7cddfSDavid du Colombier * pub/msdos/microsoft/xms20.arc and pub/msdos/info/limems41.zip.
2347dd7cddfSDavid du Colombier */
2357dd7cddfSDavid du Colombier
2367dd7cddfSDavid du Colombier
2377dd7cddfSDavid du Colombier /*
2387dd7cddfSDavid du Colombier * Access methods for a DOS file.
2397dd7cddfSDavid du Colombier */
2407dd7cddfSDavid du Colombier
2417dd7cddfSDavid du Colombier
2427dd7cddfSDavid du Colombier METHODDEF(void)
read_file_store(j_common_ptr cinfo,backing_store_ptr info,void FAR * buffer_address,long file_offset,long byte_count)2437dd7cddfSDavid du Colombier read_file_store (j_common_ptr cinfo, backing_store_ptr info,
2447dd7cddfSDavid du Colombier void FAR * buffer_address,
2457dd7cddfSDavid du Colombier long file_offset, long byte_count)
2467dd7cddfSDavid du Colombier {
2477dd7cddfSDavid du Colombier if (jdos_seek(info->handle.file_handle, file_offset))
2487dd7cddfSDavid du Colombier ERREXIT(cinfo, JERR_TFILE_SEEK);
2497dd7cddfSDavid du Colombier /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
2507dd7cddfSDavid du Colombier if (byte_count > 65535L) /* safety check */
2517dd7cddfSDavid du Colombier ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
2527dd7cddfSDavid du Colombier if (jdos_read(info->handle.file_handle, buffer_address,
2537dd7cddfSDavid du Colombier (unsigned short) byte_count))
2547dd7cddfSDavid du Colombier ERREXIT(cinfo, JERR_TFILE_READ);
2557dd7cddfSDavid du Colombier }
2567dd7cddfSDavid du Colombier
2577dd7cddfSDavid du Colombier
2587dd7cddfSDavid du Colombier METHODDEF(void)
write_file_store(j_common_ptr cinfo,backing_store_ptr info,void FAR * buffer_address,long file_offset,long byte_count)2597dd7cddfSDavid du Colombier write_file_store (j_common_ptr cinfo, backing_store_ptr info,
2607dd7cddfSDavid du Colombier void FAR * buffer_address,
2617dd7cddfSDavid du Colombier long file_offset, long byte_count)
2627dd7cddfSDavid du Colombier {
2637dd7cddfSDavid du Colombier if (jdos_seek(info->handle.file_handle, file_offset))
2647dd7cddfSDavid du Colombier ERREXIT(cinfo, JERR_TFILE_SEEK);
2657dd7cddfSDavid du Colombier /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
2667dd7cddfSDavid du Colombier if (byte_count > 65535L) /* safety check */
2677dd7cddfSDavid du Colombier ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
2687dd7cddfSDavid du Colombier if (jdos_write(info->handle.file_handle, buffer_address,
2697dd7cddfSDavid du Colombier (unsigned short) byte_count))
2707dd7cddfSDavid du Colombier ERREXIT(cinfo, JERR_TFILE_WRITE);
2717dd7cddfSDavid du Colombier }
2727dd7cddfSDavid du Colombier
2737dd7cddfSDavid du Colombier
2747dd7cddfSDavid du Colombier METHODDEF(void)
close_file_store(j_common_ptr cinfo,backing_store_ptr info)2757dd7cddfSDavid du Colombier close_file_store (j_common_ptr cinfo, backing_store_ptr info)
2767dd7cddfSDavid du Colombier {
2777dd7cddfSDavid du Colombier jdos_close(info->handle.file_handle); /* close the file */
2787dd7cddfSDavid du Colombier remove(info->temp_name); /* delete the file */
2797dd7cddfSDavid du Colombier /* If your system doesn't have remove(), try unlink() instead.
2807dd7cddfSDavid du Colombier * remove() is the ANSI-standard name for this function, but
2817dd7cddfSDavid du Colombier * unlink() was more common in pre-ANSI systems.
2827dd7cddfSDavid du Colombier */
2837dd7cddfSDavid du Colombier TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name);
2847dd7cddfSDavid du Colombier }
2857dd7cddfSDavid du Colombier
2867dd7cddfSDavid du Colombier
2877dd7cddfSDavid du Colombier LOCAL(boolean)
open_file_store(j_common_ptr cinfo,backing_store_ptr info,long total_bytes_needed)2887dd7cddfSDavid du Colombier open_file_store (j_common_ptr cinfo, backing_store_ptr info,
2897dd7cddfSDavid du Colombier long total_bytes_needed)
2907dd7cddfSDavid du Colombier {
2917dd7cddfSDavid du Colombier short handle;
2927dd7cddfSDavid du Colombier
2937dd7cddfSDavid du Colombier select_file_name(info->temp_name);
2947dd7cddfSDavid du Colombier if (jdos_open((short far *) & handle, (char far *) info->temp_name)) {
2957dd7cddfSDavid du Colombier /* might as well exit since jpeg_open_backing_store will fail anyway */
2967dd7cddfSDavid du Colombier ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
2977dd7cddfSDavid du Colombier return FALSE;
2987dd7cddfSDavid du Colombier }
2997dd7cddfSDavid du Colombier info->handle.file_handle = handle;
3007dd7cddfSDavid du Colombier info->read_backing_store = read_file_store;
3017dd7cddfSDavid du Colombier info->write_backing_store = write_file_store;
3027dd7cddfSDavid du Colombier info->close_backing_store = close_file_store;
3037dd7cddfSDavid du Colombier TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
3047dd7cddfSDavid du Colombier return TRUE; /* succeeded */
3057dd7cddfSDavid du Colombier }
3067dd7cddfSDavid du Colombier
3077dd7cddfSDavid du Colombier
3087dd7cddfSDavid du Colombier /*
3097dd7cddfSDavid du Colombier * Access methods for extended memory.
3107dd7cddfSDavid du Colombier */
3117dd7cddfSDavid du Colombier
3127dd7cddfSDavid du Colombier #if XMS_SUPPORTED
3137dd7cddfSDavid du Colombier
3147dd7cddfSDavid du Colombier static XMSDRIVER xms_driver; /* saved address of XMS driver */
3157dd7cddfSDavid du Colombier
3167dd7cddfSDavid du Colombier typedef union { /* either long offset or real-mode pointer */
3177dd7cddfSDavid du Colombier long offset;
3187dd7cddfSDavid du Colombier void far * ptr;
3197dd7cddfSDavid du Colombier } XMSPTR;
3207dd7cddfSDavid du Colombier
3217dd7cddfSDavid du Colombier typedef struct { /* XMS move specification structure */
3227dd7cddfSDavid du Colombier long length;
3237dd7cddfSDavid du Colombier XMSH src_handle;
3247dd7cddfSDavid du Colombier XMSPTR src;
3257dd7cddfSDavid du Colombier XMSH dst_handle;
3267dd7cddfSDavid du Colombier XMSPTR dst;
3277dd7cddfSDavid du Colombier } XMSspec;
3287dd7cddfSDavid du Colombier
3297dd7cddfSDavid du Colombier #define ODD(X) (((X) & 1L) != 0)
3307dd7cddfSDavid du Colombier
3317dd7cddfSDavid du Colombier
3327dd7cddfSDavid du Colombier METHODDEF(void)
read_xms_store(j_common_ptr cinfo,backing_store_ptr info,void FAR * buffer_address,long file_offset,long byte_count)3337dd7cddfSDavid du Colombier read_xms_store (j_common_ptr cinfo, backing_store_ptr info,
3347dd7cddfSDavid du Colombier void FAR * buffer_address,
3357dd7cddfSDavid du Colombier long file_offset, long byte_count)
3367dd7cddfSDavid du Colombier {
3377dd7cddfSDavid du Colombier XMScontext ctx;
3387dd7cddfSDavid du Colombier XMSspec spec;
3397dd7cddfSDavid du Colombier char endbuffer[2];
3407dd7cddfSDavid du Colombier
3417dd7cddfSDavid du Colombier /* The XMS driver can't cope with an odd length, so handle the last byte
3427dd7cddfSDavid du Colombier * specially if byte_count is odd. We don't expect this to be common.
3437dd7cddfSDavid du Colombier */
3447dd7cddfSDavid du Colombier
3457dd7cddfSDavid du Colombier spec.length = byte_count & (~ 1L);
3467dd7cddfSDavid du Colombier spec.src_handle = info->handle.xms_handle;
3477dd7cddfSDavid du Colombier spec.src.offset = file_offset;
3487dd7cddfSDavid du Colombier spec.dst_handle = 0;
3497dd7cddfSDavid du Colombier spec.dst.ptr = buffer_address;
3507dd7cddfSDavid du Colombier
3517dd7cddfSDavid du Colombier ctx.ds_si = (void far *) & spec;
3527dd7cddfSDavid du Colombier ctx.ax = 0x0b00; /* EMB move */
3537dd7cddfSDavid du Colombier jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
3547dd7cddfSDavid du Colombier if (ctx.ax != 1)
3557dd7cddfSDavid du Colombier ERREXIT(cinfo, JERR_XMS_READ);
3567dd7cddfSDavid du Colombier
3577dd7cddfSDavid du Colombier if (ODD(byte_count)) {
3587dd7cddfSDavid du Colombier read_xms_store(cinfo, info, (void FAR *) endbuffer,
3597dd7cddfSDavid du Colombier file_offset + byte_count - 1L, 2L);
3607dd7cddfSDavid du Colombier ((char FAR *) buffer_address)[byte_count - 1L] = endbuffer[0];
3617dd7cddfSDavid du Colombier }
3627dd7cddfSDavid du Colombier }
3637dd7cddfSDavid du Colombier
3647dd7cddfSDavid du Colombier
3657dd7cddfSDavid du Colombier METHODDEF(void)
write_xms_store(j_common_ptr cinfo,backing_store_ptr info,void FAR * buffer_address,long file_offset,long byte_count)3667dd7cddfSDavid du Colombier write_xms_store (j_common_ptr cinfo, backing_store_ptr info,
3677dd7cddfSDavid du Colombier void FAR * buffer_address,
3687dd7cddfSDavid du Colombier long file_offset, long byte_count)
3697dd7cddfSDavid du Colombier {
3707dd7cddfSDavid du Colombier XMScontext ctx;
3717dd7cddfSDavid du Colombier XMSspec spec;
3727dd7cddfSDavid du Colombier char endbuffer[2];
3737dd7cddfSDavid du Colombier
3747dd7cddfSDavid du Colombier /* The XMS driver can't cope with an odd length, so handle the last byte
3757dd7cddfSDavid du Colombier * specially if byte_count is odd. We don't expect this to be common.
3767dd7cddfSDavid du Colombier */
3777dd7cddfSDavid du Colombier
3787dd7cddfSDavid du Colombier spec.length = byte_count & (~ 1L);
3797dd7cddfSDavid du Colombier spec.src_handle = 0;
3807dd7cddfSDavid du Colombier spec.src.ptr = buffer_address;
3817dd7cddfSDavid du Colombier spec.dst_handle = info->handle.xms_handle;
3827dd7cddfSDavid du Colombier spec.dst.offset = file_offset;
3837dd7cddfSDavid du Colombier
3847dd7cddfSDavid du Colombier ctx.ds_si = (void far *) & spec;
3857dd7cddfSDavid du Colombier ctx.ax = 0x0b00; /* EMB move */
3867dd7cddfSDavid du Colombier jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
3877dd7cddfSDavid du Colombier if (ctx.ax != 1)
3887dd7cddfSDavid du Colombier ERREXIT(cinfo, JERR_XMS_WRITE);
3897dd7cddfSDavid du Colombier
3907dd7cddfSDavid du Colombier if (ODD(byte_count)) {
3917dd7cddfSDavid du Colombier read_xms_store(cinfo, info, (void FAR *) endbuffer,
3927dd7cddfSDavid du Colombier file_offset + byte_count - 1L, 2L);
3937dd7cddfSDavid du Colombier endbuffer[0] = ((char FAR *) buffer_address)[byte_count - 1L];
3947dd7cddfSDavid du Colombier write_xms_store(cinfo, info, (void FAR *) endbuffer,
3957dd7cddfSDavid du Colombier file_offset + byte_count - 1L, 2L);
3967dd7cddfSDavid du Colombier }
3977dd7cddfSDavid du Colombier }
3987dd7cddfSDavid du Colombier
3997dd7cddfSDavid du Colombier
4007dd7cddfSDavid du Colombier METHODDEF(void)
close_xms_store(j_common_ptr cinfo,backing_store_ptr info)4017dd7cddfSDavid du Colombier close_xms_store (j_common_ptr cinfo, backing_store_ptr info)
4027dd7cddfSDavid du Colombier {
4037dd7cddfSDavid du Colombier XMScontext ctx;
4047dd7cddfSDavid du Colombier
4057dd7cddfSDavid du Colombier ctx.dx = info->handle.xms_handle;
4067dd7cddfSDavid du Colombier ctx.ax = 0x0a00;
4077dd7cddfSDavid du Colombier jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
4087dd7cddfSDavid du Colombier TRACEMS1(cinfo, 1, JTRC_XMS_CLOSE, info->handle.xms_handle);
4097dd7cddfSDavid du Colombier /* we ignore any error return from the driver */
4107dd7cddfSDavid du Colombier }
4117dd7cddfSDavid du Colombier
4127dd7cddfSDavid du Colombier
4137dd7cddfSDavid du Colombier LOCAL(boolean)
open_xms_store(j_common_ptr cinfo,backing_store_ptr info,long total_bytes_needed)4147dd7cddfSDavid du Colombier open_xms_store (j_common_ptr cinfo, backing_store_ptr info,
4157dd7cddfSDavid du Colombier long total_bytes_needed)
4167dd7cddfSDavid du Colombier {
4177dd7cddfSDavid du Colombier XMScontext ctx;
4187dd7cddfSDavid du Colombier
4197dd7cddfSDavid du Colombier /* Get address of XMS driver */
4207dd7cddfSDavid du Colombier jxms_getdriver((XMSDRIVER far *) & xms_driver);
4217dd7cddfSDavid du Colombier if (xms_driver == NULL)
4227dd7cddfSDavid du Colombier return FALSE; /* no driver to be had */
4237dd7cddfSDavid du Colombier
4247dd7cddfSDavid du Colombier /* Get version number, must be >= 2.00 */
4257dd7cddfSDavid du Colombier ctx.ax = 0x0000;
4267dd7cddfSDavid du Colombier jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
4277dd7cddfSDavid du Colombier if (ctx.ax < (unsigned short) 0x0200)
4287dd7cddfSDavid du Colombier return FALSE;
4297dd7cddfSDavid du Colombier
4307dd7cddfSDavid du Colombier /* Try to get space (expressed in kilobytes) */
4317dd7cddfSDavid du Colombier ctx.dx = (unsigned short) ((total_bytes_needed + 1023L) >> 10);
4327dd7cddfSDavid du Colombier ctx.ax = 0x0900;
4337dd7cddfSDavid du Colombier jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
4347dd7cddfSDavid du Colombier if (ctx.ax != 1)
4357dd7cddfSDavid du Colombier return FALSE;
4367dd7cddfSDavid du Colombier
4377dd7cddfSDavid du Colombier /* Succeeded, save the handle and away we go */
4387dd7cddfSDavid du Colombier info->handle.xms_handle = ctx.dx;
4397dd7cddfSDavid du Colombier info->read_backing_store = read_xms_store;
4407dd7cddfSDavid du Colombier info->write_backing_store = write_xms_store;
4417dd7cddfSDavid du Colombier info->close_backing_store = close_xms_store;
4427dd7cddfSDavid du Colombier TRACEMS1(cinfo, 1, JTRC_XMS_OPEN, ctx.dx);
4437dd7cddfSDavid du Colombier return TRUE; /* succeeded */
4447dd7cddfSDavid du Colombier }
4457dd7cddfSDavid du Colombier
4467dd7cddfSDavid du Colombier #endif /* XMS_SUPPORTED */
4477dd7cddfSDavid du Colombier
4487dd7cddfSDavid du Colombier
4497dd7cddfSDavid du Colombier /*
4507dd7cddfSDavid du Colombier * Access methods for expanded memory.
4517dd7cddfSDavid du Colombier */
4527dd7cddfSDavid du Colombier
4537dd7cddfSDavid du Colombier #if EMS_SUPPORTED
4547dd7cddfSDavid du Colombier
4557dd7cddfSDavid du Colombier /* The EMS move specification structure requires word and long fields aligned
4567dd7cddfSDavid du Colombier * at odd byte boundaries. Some compilers will align struct fields at even
4577dd7cddfSDavid du Colombier * byte boundaries. While it's usually possible to force byte alignment,
4587dd7cddfSDavid du Colombier * that causes an overall performance penalty and may pose problems in merging
4597dd7cddfSDavid du Colombier * JPEG into a larger application. Instead we accept some rather dirty code
4607dd7cddfSDavid du Colombier * here. Note this code would fail if the hardware did not allow odd-byte
4617dd7cddfSDavid du Colombier * word & long accesses, but all 80x86 CPUs do.
4627dd7cddfSDavid du Colombier */
4637dd7cddfSDavid du Colombier
4647dd7cddfSDavid du Colombier typedef void far * EMSPTR;
4657dd7cddfSDavid du Colombier
4667dd7cddfSDavid du Colombier typedef union { /* EMS move specification structure */
4677dd7cddfSDavid du Colombier long length; /* It's easy to access first 4 bytes */
4687dd7cddfSDavid du Colombier char bytes[18]; /* Misaligned fields in here! */
4697dd7cddfSDavid du Colombier } EMSspec;
4707dd7cddfSDavid du Colombier
4717dd7cddfSDavid du Colombier /* Macros for accessing misaligned fields */
4727dd7cddfSDavid du Colombier #define FIELD_AT(spec,offset,type) (*((type *) &(spec.bytes[offset])))
4737dd7cddfSDavid du Colombier #define SRC_TYPE(spec) FIELD_AT(spec,4,char)
4747dd7cddfSDavid du Colombier #define SRC_HANDLE(spec) FIELD_AT(spec,5,EMSH)
4757dd7cddfSDavid du Colombier #define SRC_OFFSET(spec) FIELD_AT(spec,7,unsigned short)
4767dd7cddfSDavid du Colombier #define SRC_PAGE(spec) FIELD_AT(spec,9,unsigned short)
4777dd7cddfSDavid du Colombier #define SRC_PTR(spec) FIELD_AT(spec,7,EMSPTR)
4787dd7cddfSDavid du Colombier #define DST_TYPE(spec) FIELD_AT(spec,11,char)
4797dd7cddfSDavid du Colombier #define DST_HANDLE(spec) FIELD_AT(spec,12,EMSH)
4807dd7cddfSDavid du Colombier #define DST_OFFSET(spec) FIELD_AT(spec,14,unsigned short)
4817dd7cddfSDavid du Colombier #define DST_PAGE(spec) FIELD_AT(spec,16,unsigned short)
4827dd7cddfSDavid du Colombier #define DST_PTR(spec) FIELD_AT(spec,14,EMSPTR)
4837dd7cddfSDavid du Colombier
4847dd7cddfSDavid du Colombier #define EMSPAGESIZE 16384L /* gospel, see the EMS specs */
4857dd7cddfSDavid du Colombier
4867dd7cddfSDavid du Colombier #define HIBYTE(W) (((W) >> 8) & 0xFF)
4877dd7cddfSDavid du Colombier #define LOBYTE(W) ((W) & 0xFF)
4887dd7cddfSDavid du Colombier
4897dd7cddfSDavid du Colombier
4907dd7cddfSDavid du Colombier METHODDEF(void)
read_ems_store(j_common_ptr cinfo,backing_store_ptr info,void FAR * buffer_address,long file_offset,long byte_count)4917dd7cddfSDavid du Colombier read_ems_store (j_common_ptr cinfo, backing_store_ptr info,
4927dd7cddfSDavid du Colombier void FAR * buffer_address,
4937dd7cddfSDavid du Colombier long file_offset, long byte_count)
4947dd7cddfSDavid du Colombier {
4957dd7cddfSDavid du Colombier EMScontext ctx;
4967dd7cddfSDavid du Colombier EMSspec spec;
4977dd7cddfSDavid du Colombier
4987dd7cddfSDavid du Colombier spec.length = byte_count;
4997dd7cddfSDavid du Colombier SRC_TYPE(spec) = 1;
5007dd7cddfSDavid du Colombier SRC_HANDLE(spec) = info->handle.ems_handle;
5017dd7cddfSDavid du Colombier SRC_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE);
5027dd7cddfSDavid du Colombier SRC_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE);
5037dd7cddfSDavid du Colombier DST_TYPE(spec) = 0;
5047dd7cddfSDavid du Colombier DST_HANDLE(spec) = 0;
5057dd7cddfSDavid du Colombier DST_PTR(spec) = buffer_address;
5067dd7cddfSDavid du Colombier
5077dd7cddfSDavid du Colombier ctx.ds_si = (void far *) & spec;
5087dd7cddfSDavid du Colombier ctx.ax = 0x5700; /* move memory region */
5097dd7cddfSDavid du Colombier jems_calldriver((EMScontext far *) & ctx);
5107dd7cddfSDavid du Colombier if (HIBYTE(ctx.ax) != 0)
5117dd7cddfSDavid du Colombier ERREXIT(cinfo, JERR_EMS_READ);
5127dd7cddfSDavid du Colombier }
5137dd7cddfSDavid du Colombier
5147dd7cddfSDavid du Colombier
5157dd7cddfSDavid du Colombier METHODDEF(void)
write_ems_store(j_common_ptr cinfo,backing_store_ptr info,void FAR * buffer_address,long file_offset,long byte_count)5167dd7cddfSDavid du Colombier write_ems_store (j_common_ptr cinfo, backing_store_ptr info,
5177dd7cddfSDavid du Colombier void FAR * buffer_address,
5187dd7cddfSDavid du Colombier long file_offset, long byte_count)
5197dd7cddfSDavid du Colombier {
5207dd7cddfSDavid du Colombier EMScontext ctx;
5217dd7cddfSDavid du Colombier EMSspec spec;
5227dd7cddfSDavid du Colombier
5237dd7cddfSDavid du Colombier spec.length = byte_count;
5247dd7cddfSDavid du Colombier SRC_TYPE(spec) = 0;
5257dd7cddfSDavid du Colombier SRC_HANDLE(spec) = 0;
5267dd7cddfSDavid du Colombier SRC_PTR(spec) = buffer_address;
5277dd7cddfSDavid du Colombier DST_TYPE(spec) = 1;
5287dd7cddfSDavid du Colombier DST_HANDLE(spec) = info->handle.ems_handle;
5297dd7cddfSDavid du Colombier DST_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE);
5307dd7cddfSDavid du Colombier DST_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE);
5317dd7cddfSDavid du Colombier
5327dd7cddfSDavid du Colombier ctx.ds_si = (void far *) & spec;
5337dd7cddfSDavid du Colombier ctx.ax = 0x5700; /* move memory region */
5347dd7cddfSDavid du Colombier jems_calldriver((EMScontext far *) & ctx);
5357dd7cddfSDavid du Colombier if (HIBYTE(ctx.ax) != 0)
5367dd7cddfSDavid du Colombier ERREXIT(cinfo, JERR_EMS_WRITE);
5377dd7cddfSDavid du Colombier }
5387dd7cddfSDavid du Colombier
5397dd7cddfSDavid du Colombier
5407dd7cddfSDavid du Colombier METHODDEF(void)
close_ems_store(j_common_ptr cinfo,backing_store_ptr info)5417dd7cddfSDavid du Colombier close_ems_store (j_common_ptr cinfo, backing_store_ptr info)
5427dd7cddfSDavid du Colombier {
5437dd7cddfSDavid du Colombier EMScontext ctx;
5447dd7cddfSDavid du Colombier
5457dd7cddfSDavid du Colombier ctx.ax = 0x4500;
5467dd7cddfSDavid du Colombier ctx.dx = info->handle.ems_handle;
5477dd7cddfSDavid du Colombier jems_calldriver((EMScontext far *) & ctx);
5487dd7cddfSDavid du Colombier TRACEMS1(cinfo, 1, JTRC_EMS_CLOSE, info->handle.ems_handle);
5497dd7cddfSDavid du Colombier /* we ignore any error return from the driver */
5507dd7cddfSDavid du Colombier }
5517dd7cddfSDavid du Colombier
5527dd7cddfSDavid du Colombier
5537dd7cddfSDavid du Colombier LOCAL(boolean)
open_ems_store(j_common_ptr cinfo,backing_store_ptr info,long total_bytes_needed)5547dd7cddfSDavid du Colombier open_ems_store (j_common_ptr cinfo, backing_store_ptr info,
5557dd7cddfSDavid du Colombier long total_bytes_needed)
5567dd7cddfSDavid du Colombier {
5577dd7cddfSDavid du Colombier EMScontext ctx;
5587dd7cddfSDavid du Colombier
5597dd7cddfSDavid du Colombier /* Is EMS driver there? */
5607dd7cddfSDavid du Colombier if (! jems_available())
5617dd7cddfSDavid du Colombier return FALSE;
5627dd7cddfSDavid du Colombier
5637dd7cddfSDavid du Colombier /* Get status, make sure EMS is OK */
5647dd7cddfSDavid du Colombier ctx.ax = 0x4000;
5657dd7cddfSDavid du Colombier jems_calldriver((EMScontext far *) & ctx);
5667dd7cddfSDavid du Colombier if (HIBYTE(ctx.ax) != 0)
5677dd7cddfSDavid du Colombier return FALSE;
5687dd7cddfSDavid du Colombier
5697dd7cddfSDavid du Colombier /* Get version, must be >= 4.0 */
5707dd7cddfSDavid du Colombier ctx.ax = 0x4600;
5717dd7cddfSDavid du Colombier jems_calldriver((EMScontext far *) & ctx);
5727dd7cddfSDavid du Colombier if (HIBYTE(ctx.ax) != 0 || LOBYTE(ctx.ax) < 0x40)
5737dd7cddfSDavid du Colombier return FALSE;
5747dd7cddfSDavid du Colombier
5757dd7cddfSDavid du Colombier /* Try to allocate requested space */
5767dd7cddfSDavid du Colombier ctx.ax = 0x4300;
5777dd7cddfSDavid du Colombier ctx.bx = (unsigned short) ((total_bytes_needed + EMSPAGESIZE-1L) / EMSPAGESIZE);
5787dd7cddfSDavid du Colombier jems_calldriver((EMScontext far *) & ctx);
5797dd7cddfSDavid du Colombier if (HIBYTE(ctx.ax) != 0)
5807dd7cddfSDavid du Colombier return FALSE;
5817dd7cddfSDavid du Colombier
5827dd7cddfSDavid du Colombier /* Succeeded, save the handle and away we go */
5837dd7cddfSDavid du Colombier info->handle.ems_handle = ctx.dx;
5847dd7cddfSDavid du Colombier info->read_backing_store = read_ems_store;
5857dd7cddfSDavid du Colombier info->write_backing_store = write_ems_store;
5867dd7cddfSDavid du Colombier info->close_backing_store = close_ems_store;
5877dd7cddfSDavid du Colombier TRACEMS1(cinfo, 1, JTRC_EMS_OPEN, ctx.dx);
5887dd7cddfSDavid du Colombier return TRUE; /* succeeded */
5897dd7cddfSDavid du Colombier }
5907dd7cddfSDavid du Colombier
5917dd7cddfSDavid du Colombier #endif /* EMS_SUPPORTED */
5927dd7cddfSDavid du Colombier
5937dd7cddfSDavid du Colombier
5947dd7cddfSDavid du Colombier /*
5957dd7cddfSDavid du Colombier * Initial opening of a backing-store object.
5967dd7cddfSDavid du Colombier */
5977dd7cddfSDavid du Colombier
5987dd7cddfSDavid du Colombier GLOBAL(void)
jpeg_open_backing_store(j_common_ptr cinfo,backing_store_ptr info,long total_bytes_needed)5997dd7cddfSDavid du Colombier jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
6007dd7cddfSDavid du Colombier long total_bytes_needed)
6017dd7cddfSDavid du Colombier {
6027dd7cddfSDavid du Colombier /* Try extended memory, then expanded memory, then regular file. */
6037dd7cddfSDavid du Colombier #if XMS_SUPPORTED
6047dd7cddfSDavid du Colombier if (open_xms_store(cinfo, info, total_bytes_needed))
6057dd7cddfSDavid du Colombier return;
6067dd7cddfSDavid du Colombier #endif
6077dd7cddfSDavid du Colombier #if EMS_SUPPORTED
6087dd7cddfSDavid du Colombier if (open_ems_store(cinfo, info, total_bytes_needed))
6097dd7cddfSDavid du Colombier return;
6107dd7cddfSDavid du Colombier #endif
6117dd7cddfSDavid du Colombier if (open_file_store(cinfo, info, total_bytes_needed))
6127dd7cddfSDavid du Colombier return;
6137dd7cddfSDavid du Colombier ERREXITS(cinfo, JERR_TFILE_CREATE, "");
6147dd7cddfSDavid du Colombier }
6157dd7cddfSDavid du Colombier
6167dd7cddfSDavid du Colombier
6177dd7cddfSDavid du Colombier /*
6187dd7cddfSDavid du Colombier * These routines take care of any system-dependent initialization and
6197dd7cddfSDavid du Colombier * cleanup required.
6207dd7cddfSDavid du Colombier */
6217dd7cddfSDavid du Colombier
6227dd7cddfSDavid du Colombier GLOBAL(long)
jpeg_mem_init(j_common_ptr cinfo)6237dd7cddfSDavid du Colombier jpeg_mem_init (j_common_ptr cinfo)
6247dd7cddfSDavid du Colombier {
6257dd7cddfSDavid du Colombier next_file_num = 0; /* initialize temp file name generator */
6267dd7cddfSDavid du Colombier return DEFAULT_MAX_MEM; /* default for max_memory_to_use */
6277dd7cddfSDavid du Colombier }
6287dd7cddfSDavid du Colombier
6297dd7cddfSDavid du Colombier GLOBAL(void)
jpeg_mem_term(j_common_ptr cinfo)6307dd7cddfSDavid du Colombier jpeg_mem_term (j_common_ptr cinfo)
6317dd7cddfSDavid du Colombier {
6327dd7cddfSDavid du Colombier /* Microsoft C, at least in v6.00A, will not successfully reclaim freed
6337dd7cddfSDavid du Colombier * blocks of size > 32Kbytes unless we give it a kick in the rear, like so:
6347dd7cddfSDavid du Colombier */
6357dd7cddfSDavid du Colombier #ifdef NEED_FHEAPMIN
6367dd7cddfSDavid du Colombier _fheapmin();
6377dd7cddfSDavid du Colombier #endif
6387dd7cddfSDavid du Colombier }
639