~ubuntu-branches/ubuntu/precise/openarena/precise

« back to all changes in this revision

Viewing changes to code/jpeg-6/jmemdos.c

  • Committer: Bazaar Package Importer
  • Author(s): Bruno "Fuddl" Kleinert
  • Date: 2007-01-20 12:28:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070120122809-2yza5ojt7nqiyiam
Tags: upstream-0.6.0
ImportĀ upstreamĀ versionĀ 0.6.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * jmemdos.c
 
3
 *
 
4
 * Copyright (C) 1992-1994, Thomas G. Lane.
 
5
 * This file is part of the Independent JPEG Group's software.
 
6
 * For conditions of distribution and use, see the accompanying README file.
 
7
 *
 
8
 * This file provides an MS-DOS-compatible implementation of the system-
 
9
 * dependent portion of the JPEG memory manager.  Temporary data can be
 
10
 * stored in extended or expanded memory as well as in regular DOS files.
 
11
 *
 
12
 * If you use this file, you must be sure that NEED_FAR_POINTERS is defined
 
13
 * if you compile in a small-data memory model; it should NOT be defined if
 
14
 * you use a large-data memory model.  This file is not recommended if you
 
15
 * are using a flat-memory-space 386 environment such as DJGCC or Watcom C.
 
16
 * Also, this code will NOT work if struct fields are aligned on greater than
 
17
 * 2-byte boundaries.
 
18
 *
 
19
 * Based on code contributed by Ge' Weijers.
 
20
 */
 
21
 
 
22
/*
 
23
 * If you have both extended and expanded memory, you may want to change the
 
24
 * order in which they are tried in jopen_backing_store.  On a 286 machine
 
25
 * expanded memory is usually faster, since extended memory access involves
 
26
 * an expensive protected-mode-and-back switch.  On 386 and better, extended
 
27
 * memory is usually faster.  As distributed, the code tries extended memory
 
28
 * first (what? not everyone has a 386? :-).
 
29
 *
 
30
 * You can disable use of extended/expanded memory entirely by altering these
 
31
 * definitions or overriding them from the Makefile (eg, -DEMS_SUPPORTED=0).
 
32
 */
 
33
 
 
34
#ifndef XMS_SUPPORTED
 
35
#define XMS_SUPPORTED  1
 
36
#endif
 
37
#ifndef EMS_SUPPORTED
 
38
#define EMS_SUPPORTED  1
 
39
#endif
 
40
 
 
41
 
 
42
#define JPEG_INTERNALS
 
43
#include "jinclude.h"
 
44
#include "jpeglib.h"
 
45
#include "jmemsys.h"            /* import the system-dependent declarations */
 
46
 
 
47
#ifndef HAVE_STDLIB_H           /* <stdlib.h> should declare these */
 
48
extern void * malloc JPP((size_t size));
 
49
extern void free JPP((void *ptr));
 
50
extern char * getenv JPP((const char * name));
 
51
#endif
 
52
 
 
53
#ifdef NEED_FAR_POINTERS
 
54
 
 
55
#ifdef __TURBOC__
 
56
/* These definitions work for Borland C (Turbo C) */
 
57
#include <alloc.h>              /* need farmalloc(), farfree() */
 
58
#define far_malloc(x)   farmalloc(x)
 
59
#define far_free(x)     farfree(x)
 
60
#else
 
61
/* These definitions work for Microsoft C and compatible compilers */
 
62
#include <malloc.h>             /* need _fmalloc(), _ffree() */
 
63
#define far_malloc(x)   _fmalloc(x)
 
64
#define far_free(x)     _ffree(x)
 
65
#endif
 
66
 
 
67
#else /* not NEED_FAR_POINTERS */
 
68
 
 
69
#define far_malloc(x)   malloc(x)
 
70
#define far_free(x)     free(x)
 
71
 
 
72
#endif /* NEED_FAR_POINTERS */
 
73
 
 
74
#ifdef DONT_USE_B_MODE          /* define mode parameters for fopen() */
 
75
#define READ_BINARY     "r"
 
76
#else
 
77
#define READ_BINARY     "rb"
 
78
#endif
 
79
 
 
80
#if MAX_ALLOC_CHUNK >= 65535L   /* make sure jconfig.h got this right */
 
81
  MAX_ALLOC_CHUNK should be less than 64K. /* deliberate syntax error */
 
82
#endif
 
83
 
 
84
 
 
85
/*
 
86
 * Declarations for assembly-language support routines (see jmemdosa.asm).
 
87
 *
 
88
 * The functions are declared "far" as are all pointer arguments;
 
89
 * this ensures the assembly source code will work regardless of the
 
90
 * compiler memory model.  We assume "short" is 16 bits, "long" is 32.
 
91
 */
 
92
 
 
93
typedef void far * XMSDRIVER;   /* actually a pointer to code */
 
94
typedef struct {                /* registers for calling XMS driver */
 
95
        unsigned short ax, dx, bx;
 
96
        void far * ds_si;
 
97
      } XMScontext;
 
98
typedef struct {                /* registers for calling EMS driver */
 
99
        unsigned short ax, dx, bx;
 
100
        void far * ds_si;
 
101
      } EMScontext;
 
102
 
 
103
EXTERN short far jdos_open JPP((short far * handle, char far * filename));
 
104
EXTERN short far jdos_close JPP((short handle));
 
105
EXTERN short far jdos_seek JPP((short handle, long offset));
 
106
EXTERN short far jdos_read JPP((short handle, void far * buffer,
 
107
                                unsigned short count));
 
108
EXTERN short far jdos_write JPP((short handle, void far * buffer,
 
109
                                 unsigned short count));
 
110
EXTERN void far jxms_getdriver JPP((XMSDRIVER far *));
 
111
EXTERN void far jxms_calldriver JPP((XMSDRIVER, XMScontext far *));
 
112
EXTERN short far jems_available JPP((void));
 
113
EXTERN void far jems_calldriver JPP((EMScontext far *));
 
114
 
 
115
 
 
116
/*
 
117
 * Selection of a file name for a temporary file.
 
118
 * This is highly system-dependent, and you may want to customize it.
 
119
 */
 
120
 
 
121
static int next_file_num;       /* to distinguish among several temp files */
 
122
 
 
123
LOCAL void
 
124
select_file_name (char * fname)
 
125
{
 
126
  const char * env;
 
127
  char * ptr;
 
128
  FILE * tfile;
 
129
 
 
130
  /* Keep generating file names till we find one that's not in use */
 
131
  for (;;) {
 
132
    /* Get temp directory name from environment TMP or TEMP variable;
 
133
     * if none, use "."
 
134
     */
 
135
    if ((env = (const char *) getenv("TMP")) == NULL)
 
136
      if ((env = (const char *) getenv("TEMP")) == NULL)
 
137
        env = ".";
 
138
    if (*env == '\0')           /* null string means "." */
 
139
      env = ".";
 
140
    ptr = fname;                /* copy name to fname */
 
141
    while (*env != '\0')
 
142
      *ptr++ = *env++;
 
143
    if (ptr[-1] != '\\' && ptr[-1] != '/')
 
144
      *ptr++ = '\\';            /* append backslash if not in env variable */
 
145
    /* Append a suitable file name */
 
146
    next_file_num++;            /* advance counter */
 
147
    sprintf(ptr, "JPG%03d.TMP", next_file_num);
 
148
    /* Probe to see if file name is already in use */
 
149
    if ((tfile = fopen(fname, READ_BINARY)) == NULL)
 
150
      break;
 
151
    fclose(tfile);              /* oops, it's there; close tfile & try again */
 
152
  }
 
153
}
 
154
 
 
155
 
 
156
/*
 
157
 * Near-memory allocation and freeing are controlled by the regular library
 
158
 * routines malloc() and free().
 
159
 */
 
160
 
 
161
GLOBAL void *
 
162
jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
 
163
{
 
164
  return (void *) malloc(sizeofobject);
 
165
}
 
166
 
 
167
GLOBAL void
 
168
jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
 
169
{
 
170
  free(object);
 
171
}
 
172
 
 
173
 
 
174
/*
 
175
 * "Large" objects are allocated in far memory, if possible
 
176
 */
 
177
 
 
178
GLOBAL void FAR *
 
179
jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
 
180
{
 
181
  return (void FAR *) far_malloc(sizeofobject);
 
182
}
 
183
 
 
184
GLOBAL void
 
185
jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
 
186
{
 
187
  far_free(object);
 
188
}
 
189
 
 
190
 
 
191
/*
 
192
 * This routine computes the total memory space available for allocation.
 
193
 * It's impossible to do this in a portable way; our current solution is
 
194
 * to make the user tell us (with a default value set at compile time).
 
195
 * If you can actually get the available space, it's a good idea to subtract
 
196
 * a slop factor of 5% or so.
 
197
 */
 
198
 
 
199
#ifndef DEFAULT_MAX_MEM         /* so can override from makefile */
 
200
#define DEFAULT_MAX_MEM         300000L /* for total usage about 450K */
 
201
#endif
 
202
 
 
203
GLOBAL long
 
204
jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
 
205
                    long max_bytes_needed, long already_allocated)
 
206
{
 
207
  return cinfo->mem->max_memory_to_use - already_allocated;
 
208
}
 
209
 
 
210
 
 
211
/*
 
212
 * Backing store (temporary file) management.
 
213
 * Backing store objects are only used when the value returned by
 
214
 * jpeg_mem_available is less than the total space needed.  You can dispense
 
215
 * with these routines if you have plenty of virtual memory; see jmemnobs.c.
 
216
 */
 
217
 
 
218
/*
 
219
 * For MS-DOS we support three types of backing storage:
 
220
 *   1. Conventional DOS files.  We access these by direct DOS calls rather
 
221
 *      than via the stdio package.  This provides a bit better performance,
 
222
 *      but the real reason is that the buffers to be read or written are FAR.
 
223
 *      The stdio library for small-data memory models can't cope with that.
 
224
 *   2. Extended memory, accessed per the XMS V2.0 specification.
 
225
 *   3. Expanded memory, accessed per the LIM/EMS 4.0 specification.
 
226
 * You'll need copies of those specs to make sense of the related code.
 
227
 * The specs are available by Internet FTP from the SIMTEL archives 
 
228
 * (oak.oakland.edu and its various mirror sites).  See files
 
229
 * pub/msdos/microsoft/xms20.arc and pub/msdos/info/limems41.zip.
 
230
 */
 
231
 
 
232
 
 
233
/*
 
234
 * Access methods for a DOS file.
 
235
 */
 
236
 
 
237
 
 
238
METHODDEF void
 
239
read_file_store (j_common_ptr cinfo, backing_store_ptr info,
 
240
                 void FAR * buffer_address,
 
241
                 long file_offset, long byte_count)
 
242
{
 
243
  if (jdos_seek(info->handle.file_handle, file_offset))
 
244
    ERREXIT(cinfo, JERR_TFILE_SEEK);
 
245
  /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
 
246
  if (byte_count > 65535L)      /* safety check */
 
247
    ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
 
248
  if (jdos_read(info->handle.file_handle, buffer_address,
 
249
                (unsigned short) byte_count))
 
250
    ERREXIT(cinfo, JERR_TFILE_READ);
 
251
}
 
252
 
 
253
 
 
254
METHODDEF void
 
255
write_file_store (j_common_ptr cinfo, backing_store_ptr info,
 
256
                  void FAR * buffer_address,
 
257
                  long file_offset, long byte_count)
 
258
{
 
259
  if (jdos_seek(info->handle.file_handle, file_offset))
 
260
    ERREXIT(cinfo, JERR_TFILE_SEEK);
 
261
  /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
 
262
  if (byte_count > 65535L)      /* safety check */
 
263
    ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
 
264
  if (jdos_write(info->handle.file_handle, buffer_address,
 
265
                 (unsigned short) byte_count))
 
266
    ERREXIT(cinfo, JERR_TFILE_WRITE);
 
267
}
 
268
 
 
269
 
 
270
METHODDEF void
 
271
close_file_store (j_common_ptr cinfo, backing_store_ptr info)
 
272
{
 
273
  jdos_close(info->handle.file_handle); /* close the file */
 
274
  remove(info->temp_name);      /* delete the file */
 
275
/* If your system doesn't have remove(), try unlink() instead.
 
276
 * remove() is the ANSI-standard name for this function, but
 
277
 * unlink() was more common in pre-ANSI systems.
 
278
 */
 
279
  TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name);
 
280
}
 
281
 
 
282
 
 
283
LOCAL boolean
 
284
open_file_store (j_common_ptr cinfo, backing_store_ptr info,
 
285
                 long total_bytes_needed)
 
286
{
 
287
  short handle;
 
288
 
 
289
  select_file_name(info->temp_name);
 
290
  if (jdos_open((short far *) & handle, (char far *) info->temp_name)) {
 
291
    /* might as well exit since jpeg_open_backing_store will fail anyway */
 
292
    ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
 
293
    return FALSE;
 
294
  }
 
295
  info->handle.file_handle = handle;
 
296
  info->read_backing_store = read_file_store;
 
297
  info->write_backing_store = write_file_store;
 
298
  info->close_backing_store = close_file_store;
 
299
  TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
 
300
  return TRUE;                  /* succeeded */
 
301
}
 
302
 
 
303
 
 
304
/*
 
305
 * Access methods for extended memory.
 
306
 */
 
307
 
 
308
#if XMS_SUPPORTED
 
309
 
 
310
static XMSDRIVER xms_driver;    /* saved address of XMS driver */
 
311
 
 
312
typedef union {                 /* either long offset or real-mode pointer */
 
313
        long offset;
 
314
        void far * ptr;
 
315
      } XMSPTR;
 
316
 
 
317
typedef struct {                /* XMS move specification structure */
 
318
        long length;
 
319
        XMSH src_handle;
 
320
        XMSPTR src;
 
321
        XMSH dst_handle;
 
322
        XMSPTR dst;
 
323
      } XMSspec;
 
324
 
 
325
#define ODD(X)  (((X) & 1L) != 0)
 
326
 
 
327
 
 
328
METHODDEF void
 
329
read_xms_store (j_common_ptr cinfo, backing_store_ptr info,
 
330
                void FAR * buffer_address,
 
331
                long file_offset, long byte_count)
 
332
{
 
333
  XMScontext ctx;
 
334
  XMSspec spec;
 
335
  char endbuffer[2];
 
336
 
 
337
  /* The XMS driver can't cope with an odd length, so handle the last byte
 
338
   * specially if byte_count is odd.  We don't expect this to be common.
 
339
   */
 
340
 
 
341
  spec.length = byte_count & (~ 1L);
 
342
  spec.src_handle = info->handle.xms_handle;
 
343
  spec.src.offset = file_offset;
 
344
  spec.dst_handle = 0;
 
345
  spec.dst.ptr = buffer_address;
 
346
  
 
347
  ctx.ds_si = (void far *) & spec;
 
348
  ctx.ax = 0x0b00;              /* EMB move */
 
349
  jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
 
350
  if (ctx.ax != 1)
 
351
    ERREXIT(cinfo, JERR_XMS_READ);
 
352
 
 
353
  if (ODD(byte_count)) {
 
354
    read_xms_store(cinfo, info, (void FAR *) endbuffer,
 
355
                   file_offset + byte_count - 1L, 2L);
 
356
    ((char FAR *) buffer_address)[byte_count - 1L] = endbuffer[0];
 
357
  }
 
358
}
 
359
 
 
360
 
 
361
METHODDEF void
 
362
write_xms_store (j_common_ptr cinfo, backing_store_ptr info,
 
363
                 void FAR * buffer_address,
 
364
                 long file_offset, long byte_count)
 
365
{
 
366
  XMScontext ctx;
 
367
  XMSspec spec;
 
368
  char endbuffer[2];
 
369
 
 
370
  /* The XMS driver can't cope with an odd length, so handle the last byte
 
371
   * specially if byte_count is odd.  We don't expect this to be common.
 
372
   */
 
373
 
 
374
  spec.length = byte_count & (~ 1L);
 
375
  spec.src_handle = 0;
 
376
  spec.src.ptr = buffer_address;
 
377
  spec.dst_handle = info->handle.xms_handle;
 
378
  spec.dst.offset = file_offset;
 
379
 
 
380
  ctx.ds_si = (void far *) & spec;
 
381
  ctx.ax = 0x0b00;              /* EMB move */
 
382
  jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
 
383
  if (ctx.ax != 1)
 
384
    ERREXIT(cinfo, JERR_XMS_WRITE);
 
385
 
 
386
  if (ODD(byte_count)) {
 
387
    read_xms_store(cinfo, info, (void FAR *) endbuffer,
 
388
                   file_offset + byte_count - 1L, 2L);
 
389
    endbuffer[0] = ((char FAR *) buffer_address)[byte_count - 1L];
 
390
    write_xms_store(cinfo, info, (void FAR *) endbuffer,
 
391
                    file_offset + byte_count - 1L, 2L);
 
392
  }
 
393
}
 
394
 
 
395
 
 
396
METHODDEF void
 
397
close_xms_store (j_common_ptr cinfo, backing_store_ptr info)
 
398
{
 
399
  XMScontext ctx;
 
400
 
 
401
  ctx.dx = info->handle.xms_handle;
 
402
  ctx.ax = 0x0a00;
 
403
  jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
 
404
  TRACEMS1(cinfo, 1, JTRC_XMS_CLOSE, info->handle.xms_handle);
 
405
  /* we ignore any error return from the driver */
 
406
}
 
407
 
 
408
 
 
409
LOCAL boolean
 
410
open_xms_store (j_common_ptr cinfo, backing_store_ptr info,
 
411
                long total_bytes_needed)
 
412
{
 
413
  XMScontext ctx;
 
414
 
 
415
  /* Get address of XMS driver */
 
416
  jxms_getdriver((XMSDRIVER far *) & xms_driver);
 
417
  if (xms_driver == NULL)
 
418
    return FALSE;               /* no driver to be had */
 
419
 
 
420
  /* Get version number, must be >= 2.00 */
 
421
  ctx.ax = 0x0000;
 
422
  jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
 
423
  if (ctx.ax < (unsigned short) 0x0200)
 
424
    return FALSE;
 
425
 
 
426
  /* Try to get space (expressed in kilobytes) */
 
427
  ctx.dx = (unsigned short) ((total_bytes_needed + 1023L) >> 10);
 
428
  ctx.ax = 0x0900;
 
429
  jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
 
430
  if (ctx.ax != 1)
 
431
    return FALSE;
 
432
 
 
433
  /* Succeeded, save the handle and away we go */
 
434
  info->handle.xms_handle = ctx.dx;
 
435
  info->read_backing_store = read_xms_store;
 
436
  info->write_backing_store = write_xms_store;
 
437
  info->close_backing_store = close_xms_store;
 
438
  TRACEMS1(cinfo, 1, JTRC_XMS_OPEN, ctx.dx);
 
439
  return TRUE;                  /* succeeded */
 
440
}
 
441
 
 
442
#endif /* XMS_SUPPORTED */
 
443
 
 
444
 
 
445
/*
 
446
 * Access methods for expanded memory.
 
447
 */
 
448
 
 
449
#if EMS_SUPPORTED
 
450
 
 
451
/* The EMS move specification structure requires word and long fields aligned
 
452
 * at odd byte boundaries.  Some compilers will align struct fields at even
 
453
 * byte boundaries.  While it's usually possible to force byte alignment,
 
454
 * that causes an overall performance penalty and may pose problems in merging
 
455
 * JPEG into a larger application.  Instead we accept some rather dirty code
 
456
 * here.  Note this code would fail if the hardware did not allow odd-byte
 
457
 * word & long accesses, but all 80x86 CPUs do.
 
458
 */
 
459
 
 
460
typedef void far * EMSPTR;
 
461
 
 
462
typedef union {                 /* EMS move specification structure */
 
463
        long length;            /* It's easy to access first 4 bytes */
 
464
        char bytes[18];         /* Misaligned fields in here! */
 
465
      } EMSspec;
 
466
 
 
467
/* Macros for accessing misaligned fields */
 
468
#define FIELD_AT(spec,offset,type)  (*((type *) &(spec.bytes[offset])))
 
469
#define SRC_TYPE(spec)          FIELD_AT(spec,4,char)
 
470
#define SRC_HANDLE(spec)        FIELD_AT(spec,5,EMSH)
 
471
#define SRC_OFFSET(spec)        FIELD_AT(spec,7,unsigned short)
 
472
#define SRC_PAGE(spec)          FIELD_AT(spec,9,unsigned short)
 
473
#define SRC_PTR(spec)           FIELD_AT(spec,7,EMSPTR)
 
474
#define DST_TYPE(spec)          FIELD_AT(spec,11,char)
 
475
#define DST_HANDLE(spec)        FIELD_AT(spec,12,EMSH)
 
476
#define DST_OFFSET(spec)        FIELD_AT(spec,14,unsigned short)
 
477
#define DST_PAGE(spec)          FIELD_AT(spec,16,unsigned short)
 
478
#define DST_PTR(spec)           FIELD_AT(spec,14,EMSPTR)
 
479
 
 
480
#define EMSPAGESIZE     16384L  /* gospel, see the EMS specs */
 
481
 
 
482
#define HIBYTE(W)  (((W) >> 8) & 0xFF)
 
483
#define LOBYTE(W)  ((W) & 0xFF)
 
484
 
 
485
 
 
486
METHODDEF void
 
487
read_ems_store (j_common_ptr cinfo, backing_store_ptr info,
 
488
                void FAR * buffer_address,
 
489
                long file_offset, long byte_count)
 
490
{
 
491
  EMScontext ctx;
 
492
  EMSspec spec;
 
493
 
 
494
  spec.length = byte_count;
 
495
  SRC_TYPE(spec) = 1;
 
496
  SRC_HANDLE(spec) = info->handle.ems_handle;
 
497
  SRC_PAGE(spec)   = (unsigned short) (file_offset / EMSPAGESIZE);
 
498
  SRC_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE);
 
499
  DST_TYPE(spec) = 0;
 
500
  DST_HANDLE(spec) = 0;
 
501
  DST_PTR(spec)    = buffer_address;
 
502
  
 
503
  ctx.ds_si = (void far *) & spec;
 
504
  ctx.ax = 0x5700;              /* move memory region */
 
505
  jems_calldriver((EMScontext far *) & ctx);
 
506
  if (HIBYTE(ctx.ax) != 0)
 
507
    ERREXIT(cinfo, JERR_EMS_READ);
 
508
}
 
509
 
 
510
 
 
511
METHODDEF void
 
512
write_ems_store (j_common_ptr cinfo, backing_store_ptr info,
 
513
                 void FAR * buffer_address,
 
514
                 long file_offset, long byte_count)
 
515
{
 
516
  EMScontext ctx;
 
517
  EMSspec spec;
 
518
 
 
519
  spec.length = byte_count;
 
520
  SRC_TYPE(spec) = 0;
 
521
  SRC_HANDLE(spec) = 0;
 
522
  SRC_PTR(spec)    = buffer_address;
 
523
  DST_TYPE(spec) = 1;
 
524
  DST_HANDLE(spec) = info->handle.ems_handle;
 
525
  DST_PAGE(spec)   = (unsigned short) (file_offset / EMSPAGESIZE);
 
526
  DST_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE);
 
527
  
 
528
  ctx.ds_si = (void far *) & spec;
 
529
  ctx.ax = 0x5700;              /* move memory region */
 
530
  jems_calldriver((EMScontext far *) & ctx);
 
531
  if (HIBYTE(ctx.ax) != 0)
 
532
    ERREXIT(cinfo, JERR_EMS_WRITE);
 
533
}
 
534
 
 
535
 
 
536
METHODDEF void
 
537
close_ems_store (j_common_ptr cinfo, backing_store_ptr info)
 
538
{
 
539
  EMScontext ctx;
 
540
 
 
541
  ctx.ax = 0x4500;
 
542
  ctx.dx = info->handle.ems_handle;
 
543
  jems_calldriver((EMScontext far *) & ctx);
 
544
  TRACEMS1(cinfo, 1, JTRC_EMS_CLOSE, info->handle.ems_handle);
 
545
  /* we ignore any error return from the driver */
 
546
}
 
547
 
 
548
 
 
549
LOCAL boolean
 
550
open_ems_store (j_common_ptr cinfo, backing_store_ptr info,
 
551
                long total_bytes_needed)
 
552
{
 
553
  EMScontext ctx;
 
554
 
 
555
  /* Is EMS driver there? */
 
556
  if (! jems_available())
 
557
    return FALSE;
 
558
 
 
559
  /* Get status, make sure EMS is OK */
 
560
  ctx.ax = 0x4000;
 
561
  jems_calldriver((EMScontext far *) & ctx);
 
562
  if (HIBYTE(ctx.ax) != 0)
 
563
    return FALSE;
 
564
 
 
565
  /* Get version, must be >= 4.0 */
 
566
  ctx.ax = 0x4600;
 
567
  jems_calldriver((EMScontext far *) & ctx);
 
568
  if (HIBYTE(ctx.ax) != 0 || LOBYTE(ctx.ax) < 0x40)
 
569
    return FALSE;
 
570
 
 
571
  /* Try to allocate requested space */
 
572
  ctx.ax = 0x4300;
 
573
  ctx.bx = (unsigned short) ((total_bytes_needed + EMSPAGESIZE-1L) / EMSPAGESIZE);
 
574
  jems_calldriver((EMScontext far *) & ctx);
 
575
  if (HIBYTE(ctx.ax) != 0)
 
576
    return FALSE;
 
577
 
 
578
  /* Succeeded, save the handle and away we go */
 
579
  info->handle.ems_handle = ctx.dx;
 
580
  info->read_backing_store = read_ems_store;
 
581
  info->write_backing_store = write_ems_store;
 
582
  info->close_backing_store = close_ems_store;
 
583
  TRACEMS1(cinfo, 1, JTRC_EMS_OPEN, ctx.dx);
 
584
  return TRUE;                  /* succeeded */
 
585
}
 
586
 
 
587
#endif /* EMS_SUPPORTED */
 
588
 
 
589
 
 
590
/*
 
591
 * Initial opening of a backing-store object.
 
592
 */
 
593
 
 
594
GLOBAL void
 
595
jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
 
596
                         long total_bytes_needed)
 
597
{
 
598
  /* Try extended memory, then expanded memory, then regular file. */
 
599
#if XMS_SUPPORTED
 
600
  if (open_xms_store(cinfo, info, total_bytes_needed))
 
601
    return;
 
602
#endif
 
603
#if EMS_SUPPORTED
 
604
  if (open_ems_store(cinfo, info, total_bytes_needed))
 
605
    return;
 
606
#endif
 
607
  if (open_file_store(cinfo, info, total_bytes_needed))
 
608
    return;
 
609
  ERREXITS(cinfo, JERR_TFILE_CREATE, "");
 
610
}
 
611
 
 
612
 
 
613
/*
 
614
 * These routines take care of any system-dependent initialization and
 
615
 * cleanup required.
 
616
 */
 
617
 
 
618
GLOBAL long
 
619
jpeg_mem_init (j_common_ptr cinfo)
 
620
{
 
621
  next_file_num = 0;            /* initialize temp file name generator */
 
622
  return DEFAULT_MAX_MEM;       /* default for max_memory_to_use */
 
623
}
 
624
 
 
625
GLOBAL void
 
626
jpeg_mem_term (j_common_ptr cinfo)
 
627
{
 
628
  /* Microsoft C, at least in v6.00A, will not successfully reclaim freed
 
629
   * blocks of size > 32Kbytes unless we give it a kick in the rear, like so:
 
630
   */
 
631
#ifdef NEED_FHEAPMIN
 
632
  _fheapmin();
 
633
#endif
 
634
}