2 *************************************************************************
\r
4 * PCX_DISP.C - PCX_LIB Library Image Display Functions
\r
8 * History: 91/02/14 - Created
\r
9 * 91/04/01 - Release 1.00A
\r
10 * 91/04/03 - fixed "segread" call.
\r
11 * 91/04/07 - Release 1.00B
\r
13 * Compiler: Microsoft C V6.0
\r
15 * Author: Ian Ashdown, P.Eng.
\r
17 * 620 Ballantree Road
\r
18 * West Vancouver, B.C.
\r
20 * Tel. (604) 922-6148
\r
21 * Fax. (604) 987-7621
\r
23 * Copyright: Public Domain
\r
25 *************************************************************************
\r
29 *************************************************************************
\r
33 * 1. While this program is written in ANSI C, it uses a number of
\r
34 * function calls that are specific to the Microsoft C V6.0 library.
\r
35 * These are documented as follows for the purposes of porting this
\r
36 * program to other compilers and/or processors:
\r
38 * _fmemcpy - "memcpy" for small model / far data
\r
39 * int86 - execute 80x86 interrupt routine
\r
40 * int86x - execute 80x86 interrupt routine (far
\r
42 * _remapallpalette - remap entire video display color palette
\r
43 * _selectpalette - select CGA color palette
\r
44 * outpw - output word to 80x86 I/O port
\r
45 * segread - get current 80x86 segment register
\r
48 * 2. When porting this program to other processors, remember that words
\r
49 * are stored by 80x86-based machines in the big-endian format. That
\r
50 * is, the eight least significant bits (lower byte) are stored
\r
51 * first, followed by the eight most significant bits (upper byte).
\r
52 * If PCX-format files are transferred to little-endian machines
\r
53 * (such as those based on 680x0 and Z8000 processors), the order of
\r
54 * bytes within each word will have to be reversed before they can
\r
55 * be interpreted. (This applies to the file header only, since the
\r
56 * encoded image data and optional 256-color palette are stored as
\r
59 * 3. MS-DOS does not recognize the 720 x 348 graphics mode of the
\r
60 * Hercules monochrome display adapter. Therefore, the constant
\r
61 * PCX_HERC should never be passed as a video mode parameter to any
\r
62 * BIOS service routine.
\r
64 * The Microsoft C compiler includes a "video mode" parameter
\r
65 * definition (_HERCMONO) that is defined as 0x08. This is a
\r
66 * reserved MS-DOS video mode that is apparently used internally by
\r
67 * the ROM BIOS. It can, however, be passed to the Microsoft C
\r
68 * library function "_setvideomode" to force the Hercules display
\r
69 * adapter into graphics mode.
\r
71 * Most other MS-DOS C compilers offer similar library functions to
\r
72 * force the Hercules monochrome display adapter into its 720 x 348
\r
75 *************************************************************************
\r
87 #include "pcx_int.h"
\r
89 /* FORWARD REFERENCES */
\r
91 static BOOL pcx_read_init(PCX_WORKBLK *, int, int);
\r
92 static BOOL pcx_read_extpal(PCX_WORKBLK *);
\r
93 static BOOL pcx_read_header(PCX_WORKBLK *);
\r
94 static BOOL pcx_read_line(PCX_WORKBLK *, unsigned char *, int);
\r
95 static BOOL pcx_set_palette(PCX_PAL *, int);
\r
97 static void pcx_cga_palette(PCX_PAL *, int);
\r
98 static void pcx_put_cga(PCX_WORKBLK *, unsigned char _far *, int);
\r
99 static void pcx_put_ega(PCX_WORKBLK *, unsigned char _far *, int);
\r
100 static void pcx_put_herc(PCX_WORKBLK *, unsigned char _far *, int);
\r
101 static void pcx_put_vga(PCX_WORKBLK *, unsigned char _far *, int);
\r
105 /* PUBLIC FUNCTIONS */
\r
108 *************************************************************************
\r
110 * PCX_READ - Read PCX Image File
\r
112 * Purpose: To read and display a PCX-format image file.
\r
114 * Setup: BOOL pcx_read
\r
121 * Where: fname is a PCX image file name.
\r
122 * vmode is the MS-DOS video mode. Valid values are:
\r
124 * PCX_HERC - 720 x 348 Hercules monochrome
\r
125 * 0x04 - 320 x 200 4-color CGA
\r
126 * 0x05 - 320 x 200 4-color CGA (color burst off)
\r
127 * 0x06 - 640 x 200 2-color CGA
\r
128 * 0x0d - 320 x 200 16-color EGA/VGA
\r
129 * 0x0e - 640 x 200 16-color EGA/VGA
\r
130 * 0x0f - 640 x 350 2-color EGA/VGA
\r
131 * 0x10 - 640 x 350 16-color EGA/VGA
\r
132 * 0x11 - 640 x 480 2-color VGA
\r
133 * 0x12 - 640 x 480 16-color VGA
\r
134 * 0x13 - 320 x 200 256-color VGA
\r
136 * page is the video display page number. Valid values are:
\r
138 * Mode PCX_HERC - 0 or 1
\r
139 * Mode 0x0d - 0 to 7
\r
140 * Mode 0x0e - 0 to 3
\r
141 * Mode 0x0f - 0 or 1
\r
142 * Mode 0x10 - 0 or 1
\r
145 * Return: TRUE if successful; otherwise FALSE.
\r
147 * Note: The video display adapter must be in the appropriate mode
\r
148 * and active page for the image to be displayed.
\r
150 *************************************************************************
\r
160 int bpline; /* Number of bytes per scan line */
\r
161 int line_num; /* Scan line number */
\r
162 int max_lines; /* Maximum number of scan lines */
\r
163 unsigned char *linep; /* PCX scan line buffer pointer */
\r
164 BOOL status = TRUE; /* Return status */
\r
165 PCX_WORKBLK *wbp; /* PCX image file workblock pointer */
\r
167 /* Open a PCX image file workblock */
\r
169 if ((wbp = pcx_open(fname, FALSE)) == (PCX_WORKBLK *) NULL)
\r
172 /* Initialize the workblock for reading */
\r
174 if (pcx_read_init(wbp, vmode, page) == FALSE)
\r
176 (void) pcx_close(wbp); /* Close the PCX workblock */
\r
180 /* Calculate the image height */
\r
182 max_lines = wbp->header.yul + wbp->header.ylr + 1;
\r
184 /* Calculate number of bytes per line (for all color planes) */
\r
186 bpline = wbp->header.bppscan * wbp->header.nplanes;
\r
188 /* Allocate the PCX scan line buffer */
\r
190 if ((linep = (unsigned char *) malloc(bpline)) != (unsigned char *)
\r
193 /* Set the file pointer to the beginning of the encoded image data */
\r
195 if (status == TRUE)
\r
196 if (fseek(wbp->fp, (long) (sizeof(PCX_HDR)), SEEK_SET) != 0)
\r
199 /* Set the video display adapter color palette unless the PCX file */
\r
200 /* is Version 3.0 (i.e. - PC Paintbrush Version 2.8 w/o palette) */
\r
202 if (status == TRUE)
\r
203 if (wbp->header.version != 3)
\r
204 if (pcx_set_palette(wbp->palettep, vmode) == FALSE)
\r
207 /* Read the image line by line */
\r
209 if (status == TRUE)
\r
211 for (line_num = 0; line_num < max_lines; line_num++)
\r
213 /* Read the current scan line */
\r
215 if ((status = pcx_read_line(wbp, linep, bpline)) == FALSE)
\r
221 /* Display the current scan line */
\r
223 wbp->pcx_funcp(wbp, (unsigned char _far *) linep, line_num);
\r
227 free(linep); /* Free the PCX scan line buffer */
\r
232 if (pcx_close(wbp) == FALSE) /* Close the PCX workblock */
\r
238 /* PRIVATE FUNCTIONS */
\r
241 *************************************************************************
\r
243 * PCX_READ_INIT - Initialize PCX Workblock For Reading
\r
245 * Purpose: To initialize a PCX image file workblock for reading.
\r
247 * Setup: static BOOL pcx_read_init
\r
249 * PCX_WORKBLK *wbp,
\r
254 * Where: wbp is a PCX workblock pointer.
\r
255 * vmode is the MS-DOS video mode. Valid values are:
\r
257 * PCX_HERC - 720 x 348 Hercules monochrome
\r
258 * 0x04 - 320 x 200 4-color CGA
\r
259 * 0x05 - 320 x 200 4-color CGA (color burst off)
\r
260 * 0x06 - 640 x 200 2-color CGA
\r
261 * 0x0d - 320 x 200 16-color EGA/VGA
\r
262 * 0x0e - 640 x 200 16-color EGA/VGA
\r
263 * 0x0f - 640 x 350 2-color EGA/VGA
\r
264 * 0x10 - 640 x 350 16-color EGA/VGA
\r
265 * 0x11 - 640 x 480 2-color VGA
\r
266 * 0x12 - 640 x 480 16-color VGA
\r
267 * 0x13 - 320 x 200 256-color VGA
\r
269 * page is the video display page number. Valid values are:
\r
271 * Mode PCX_HERC - 0 or 1
\r
272 * Mode 0x0d - 0 to 7
\r
273 * Mode 0x0e - 0 to 3
\r
274 * Mode 0x0f - 0 or 1
\r
275 * Mode 0x10 - 0 or 1
\r
278 * Return: TRUE if successful; otherwise FALSE.
\r
280 *************************************************************************
\r
283 static BOOL pcx_read_init
\r
290 int width; /* Display width */
\r
291 int leftover; /* Number of unseen bits */
\r
292 BOOL status = TRUE; /* Return status */
\r
294 /* Read the file header */
\r
296 if ((pcx_read_header(wbp)) == FALSE)
\r
299 /* Initialize the workblock color palette pointer */
\r
301 wbp->palettep = wbp->header.palette;
\r
302 wbp->epal_flag = FALSE;
\r
304 /* Read the extended palette (if any) */
\r
306 if (vmode == 0x13 && wbp->header.version == 5)
\r
307 if (pcx_read_extpal(wbp) == FALSE)
\r
310 /* Initialize the display page address offset */
\r
312 wbp->page_offset = (unsigned long) 0L;
\r
314 switch (vmode) /* Select PCX line display function */
\r
316 case PCX_HERC: /* 720 x 348 Hercules monochrome */
\r
318 /* Hercules monochrome display adapter supports 2 pages */
\r
320 wbp->page_offset = 0x08000000L * (unsigned long) page;
\r
322 /* Calculate display width in pixels */
\r
324 width = min((wbp->header.xlr - wbp->header.xul + 1), 720);
\r
326 /* Calculate number of bytes to display */
\r
328 wbp->num_bytes = (width + 7) >> 3;
\r
330 /* Calculate mask for leftover bits */
\r
332 if ((leftover = width & 7) != 0)
\r
333 wbp->mask = (0xff << (8 - leftover)) & 0xff;
\r
337 wbp->pcx_funcp = pcx_put_herc; /* Set the display function ptr */
\r
341 case 0x04: /* 320 x 200 4-color CGA */
\r
342 case 0x05: /* 320 x 200 4-color CGA (color burst off) */
\r
344 /* Calculate display width in pixels */
\r
346 width = min((wbp->header.xlr - wbp->header.xul + 1), 320);
\r
348 /* Calculate number of bytes to display */
\r
350 wbp->num_bytes = (width + 3) >> 2;
\r
352 /* Calculate mask for leftover bits */
\r
354 if ((leftover = (width & 3) << 1) != 0)
\r
355 wbp->mask = (0xff << (8 - leftover)) & 0xff;
\r
359 wbp->pcx_funcp = pcx_put_cga; /* Set the display function ptr */
\r
363 case 0x06: /* 640 x 200 2-color CGA */
\r
365 /* Calculate display width in pixels */
\r
367 width = min((wbp->header.xlr - wbp->header.xul + 1), 640);
\r
369 /* Calculate number of bytes to display */
\r
371 wbp->num_bytes = (width + 7) >> 3;
\r
373 /* Calculate mask for leftover bits */
\r
375 if ((leftover = width & 7) != 0)
\r
376 wbp->mask = (0xff << (8 - leftover)) & 0xff;
\r
380 wbp->pcx_funcp = pcx_put_cga; /* Set the display function ptr */
\r
384 case 0x0d: /* 320 x 200 16-color EGA/VGA */
\r
385 case 0x0e: /* 640 x 200 16-color EGA/VGA */
\r
386 case 0x0f: /* 640 x 350 2-color EGA/VGA */
\r
387 case 0x10: /* 640 x 350 16-color EGA/VGA */
\r
388 case 0x11: /* 640 x 480 2-color VGA */
\r
389 case 0x12: /* 640 x 480 16-color VGA */
\r
391 switch (vmode) /* Initialize the display adapter page offset */
\r
393 case 0x0d: /* 320 x 200 16-color EGA/VGA (8 pages maximum) */
\r
395 wbp->page_offset = 0x02000000L * (unsigned long) page;
\r
399 case 0x0e: /* 640 x 200 16-color EGA/VGA (4 pages maximum) */
\r
401 wbp->page_offset = 0x04000000L * (unsigned long) page;
\r
405 case 0x0f: /* 640 x 350 2-color EGA/VGA (2 pages maximum) */
\r
406 case 0x10: /* 640 x 350 16-color EGA/VGA (2 pages maximum) */
\r
408 wbp->page_offset = 0x08000000L * (unsigned long) page;
\r
412 default: /* All other modes support only one page */
\r
417 /* Calculate display width in pixels */
\r
419 width = min((wbp->header.xlr - wbp->header.xul + 1), 640);
\r
421 /* Calculate number of bytes to display */
\r
423 wbp->num_bytes = (width + 7) >> 3;
\r
425 /* Calculate mask for leftover bits */
\r
427 if ((leftover = width & 7) != 0)
\r
428 wbp->mask = (0xff << (8 - leftover)) & 0xff;
\r
432 wbp->pcx_funcp = pcx_put_ega; /* Set the display function ptr */
\r
436 case 0x13: /* 320 x 200 256-color VGA */
\r
438 /* Calculate number of bytes to display */
\r
440 wbp->num_bytes = min((wbp->header.xlr - wbp->header.xul + 1), 320);
\r
442 wbp->mask = 0; /* Dummy parameter */
\r
444 wbp->pcx_funcp = pcx_put_vga; /* Set the display function ptr */
\r
448 default: /* Other display adapters not supported */
\r
459 *************************************************************************
\r
461 * PCX_READ_HEADER - Read PCX File Header
\r
463 * Purpose: To read and validate a PCX file header.
\r
465 * Setup: static BOOL pcx_read_header
\r
470 * Where: wbp is a PCX image file workblock pointer.
\r
472 * Return: TRUE if successful; otherwise FALSE.
\r
474 * Result: The file header is read into the "header" member of the
\r
477 *************************************************************************
\r
480 static BOOL pcx_read_header
\r
485 BOOL status = TRUE; /* Status flag */
\r
486 PCX_HDR *hdrp; /* PCX file header buffer pointer */
\r
488 hdrp = &(wbp->header); /* Initialize the file header pointer */
\r
490 /* Read the file header */
\r
492 if (fseek(wbp->fp, 0L, SEEK_SET) != 0)
\r
495 if (status == TRUE)
\r
496 if (fread(hdrp, sizeof(PCX_HDR), 1, wbp->fp) != 1)
\r
499 /* Validate the PCX file format */
\r
501 if (status == TRUE)
\r
502 if ((hdrp->pcx_id != 0x0a) || (hdrp->encoding != 1))
\r
509 *************************************************************************
\r
511 * PCX_READ_EXTPAL - Read Extended Palette
\r
513 * Purpose: To read an extended (256-color) palette (if it exists).
\r
515 * Setup: static BOOL pcx_read_extpal
\r
520 * Where: wbp is a PCX image file workblock pointer.
\r
522 * Return: TRUE if successful; otherwise FALSE.
\r
524 * Note: It is possible for a PCX image file without an appended
\r
525 * 256-color palette to have the value 0x0c as the 769th byte
\r
526 * (the location of the extended palette indicator byte) from
\r
527 * the end of the file (i.e. - in the encoded image data
\r
528 * section). This function will misinterpret the following
\r
529 * 768 bytes of encoded image data as an extended palette.
\r
531 * This problem will only occur if an attempt is made to
\r
532 * display a PCX image using the wrong MS-DOS video mode. It
\r
533 * can be detected by decoding the image data and using
\r
534 * "ftell" to note the file position of the end of the
\r
535 * encoded image data section, then comparing it to the file
\r
536 * position of the indicator byte. If the supposed indicator
\r
537 * byte is located within the encoded image data section, the
\r
538 * indicator byte is invalid and so the file header palette
\r
539 * should be used instead.
\r
541 *************************************************************************
\r
544 static BOOL pcx_read_extpal
\r
549 int indicator; /* PCX extended palette indicator */
\r
551 /* Position the file pointer to the extended palette indicator byte */
\r
553 if (fseek(wbp->fp, -769L, SEEK_END) != 0)
\r
556 /* Read the (assumed) extended palette indicator byte */
\r
558 if ((indicator = getc(wbp->fp)) == EOF)
\r
561 if (indicator == PCX_EPAL_FLAG) /* Check for indicator byte */
\r
563 /* Allocate an extended palette buffer */
\r
565 if ((wbp->palettep = (PCX_PAL *) calloc(sizeof(PCX_PAL),
\r
566 PCX_EPAL_SIZE)) == (PCX_PAL *) NULL)
\r
569 /* Read the extended palette */
\r
571 if (fread(wbp->palettep, sizeof(PCX_PAL), PCX_EPAL_SIZE, wbp->fp) !=
\r
574 free(wbp->palettep); /* Free the extended palette buffer */
\r
578 wbp->epal_flag = TRUE; /* Indicate extended palette present */
\r
585 *************************************************************************
\r
587 * PCX_READ_LINE - Read PCX Line
\r
589 * Purpose: To read an encoded line (all color planes) from a PCX-
\r
590 * format image file and write the decoded data to a line
\r
593 * Setup: static BOOL pcx_read_line
\r
595 * PCX_WORKBLK *wbp,
\r
596 * unsigned char *linep,
\r
600 * Where: wbp is a PCX image file workblock pointer.
\r
601 * linep is a PCX scan line buffer pointer.
\r
602 * bpline is the number of bytes per scan line (all color
\r
605 * Return: TRUE if successful; otherwise FALSE.
\r
607 *************************************************************************
\r
610 static BOOL pcx_read_line
\r
613 unsigned char *linep,
\r
617 int data; /* Image data byte */
\r
618 int count; /* Image data byte repeat count */
\r
619 int offset = 0; /* Scan line buffer offset */
\r
621 while (offset < bpline) /* Decode current scan line */
\r
623 if ((data = getc(wbp->fp)) == EOF) /* Get next byte */
\r
626 /* If top two bits of byte are set, lower six bits show how */
\r
627 /* many times to duplicate next byte */
\r
629 if ((data & PCX_COMP_FLAG) == PCX_COMP_FLAG)
\r
631 count = data & PCX_COMP_MASK; /* Mask off repeat count */
\r
633 if ((data = getc(wbp->fp)) == EOF) /* Get next byte */
\r
636 memset(linep, data, count); /* Duplicate byte */
\r
642 *linep++ = (unsigned char) data; /* Copy byte */
\r
651 *************************************************************************
\r
653 * PCX_SET_PALETTE - Set Palette
\r
655 * Purpose: To set the display palette according to a PCX file
\r
658 * Setup: static BOOL pcx_set_palette
\r
660 * PCX_PAL *palettep,
\r
664 * Where: palettep is a pointer to a PCX file palette.
\r
665 * vmode is the MS-DOS video mode. Valid values are:
\r
667 * PCX_HERC - 720 x 348 Hercules monochrome
\r
668 * 0x04 - 320 x 200 4-color CGA
\r
669 * 0x05 - 320 x 200 4-color CGA (color burst off)
\r
670 * 0x06 - 640 x 200 2-color CGA
\r
671 * 0x0d - 320 x 200 16-color EGA/VGA
\r
672 * 0x0e - 640 x 200 16-color EGA/VGA
\r
673 * 0x0f - 640 x 350 2-color EGA/VGA
\r
674 * 0x10 - 640 x 350 16-color EGA/VGA
\r
675 * 0x11 - 640 x 480 2-color VGA
\r
676 * 0x12 - 640 x 480 16-color VGA
\r
677 * 0x13 - 320 x 200 256-color VGA
\r
679 * Return: TRUE if successful; otherwise FALSE.
\r
681 *************************************************************************
\r
684 static BOOL pcx_set_palette
\r
690 int i; /* Scratch counter */
\r
691 int red_lo; /* Low red intensity */
\r
692 int red_hi; /* High red intensity */
\r
693 int green_lo; /* Green low intensity */
\r
694 int green_hi; /* Green high intensity */
\r
695 int blue_lo; /* Blue low intensity */
\r
696 int blue_hi; /* Blue high intensity */
\r
697 unsigned char *ega_palp; /* EGA 16-color palette buffer pointer */
\r
698 unsigned long *vga_palp; /* VGA 256-color palette buffer pointer */
\r
699 BOOL status = TRUE; /* Return status */
\r
700 union REGS regs; /* 80x86 register values */
\r
701 struct SREGS sregs; /* 80x86 segment register values */
\r
705 case PCX_HERC: /* 720 x 348 Hercules monochrome */
\r
709 case 0x04: /* 320 x 200 4-color CGA display */
\r
710 case 0x05: /* 320 x 200 monochrome CGA display (burst off) */
\r
711 case 0x06: /* 640 x 200 2-color CGA display */
\r
713 /* Set the CGA color palette */
\r
715 pcx_cga_palette(palettep, vmode);
\r
719 case 0x0d: /* 320 x 200 16-color EGA/VGA */
\r
720 case 0x0e: /* 640 x 200 16-color EGA/VGA */
\r
721 case 0x0f: /* 640 x 350 2-color EGA/VGA */
\r
722 case 0x10: /* 640 x 350 16-color EGA/VGA */
\r
723 case 0x11: /* 640 x 480 2-color VGA */
\r
724 case 0x12: /* 640 x 480 16-color VGA */
\r
726 if (pcx_isvga() == TRUE) /* Check for VGA display adapter */
\r
728 /* Allocate a 16-color VGA display adapter palette buffer */
\r
730 if ((vga_palp = (unsigned long *) calloc(sizeof(unsigned long),
\r
731 PCX_PAL_SIZE)) == (unsigned long *) NULL)
\r
737 /* Map PCX hardware palette to 16-color VGA palette (each color */
\r
738 /* value is a "long" with the form: */
\r
740 /* 00000000-00BBBBBB-00GGGGGG-00RRRRRR */
\r
742 /* where each color is a 6-bit value. */
\r
744 for (i = 0; i < PCX_PAL_SIZE; i++)
\r
745 vga_palp[i] = (long) (palettep[i].red >> 2) |
\r
746 ((long) (palettep[i].green >> 2)) << 8 |
\r
747 ((long) (palettep[i].blue >> 2)) << 16;
\r
749 (void) _remapallpalette(vga_palp); /* Remap entire palette */
\r
751 free(vga_palp); /* Free the VGA palette buffer */
\r
753 else /* EGA display adapter */
\r
755 /* Allocate an EGA display adapter palette buffer */
\r
757 if ((ega_palp = (unsigned char *) calloc(sizeof(unsigned char),
\r
758 PCX_PAL_SIZE + 1)) == (unsigned char *) NULL)
\r
764 /* Map PCX hardware palette to 16-color EGA palette (each EGA */
\r
765 /* color value is an "unsigned char" with the form: */
\r
767 /* 0 0 R' G' B' R G B */
\r
769 /* where X' is the low-intensity value and X is the high */
\r
770 /* intensity value for the color X.) */
\r
772 /* NOTE: the "_remapallpalette" function could be used to set */
\r
773 /* the palette for EGA display adapters. However, this */
\r
774 /* function does not appear to update the palette */
\r
775 /* register values in the Dynamic Save Area (see the */
\r
776 /* function header for "pcx_init_palette" in PCX_FILE.C) */
\r
777 /* for a detailed explanation). */
\r
779 for (i = 0; i < PCX_PAL_SIZE; i++)
\r
781 /* Extract low and high intensity bits for each color */
\r
783 red_lo = (palettep[i].red >> 6) & 0x01;
\r
784 red_hi = (palettep[i].red >> 6) & 0x02;
\r
785 green_lo = (palettep[i].green >> 6) & 0x01;
\r
786 green_hi = (palettep[i].green >> 6) & 0x02;
\r
787 blue_lo = (palettep[i].blue >> 6) & 0x01;
\r
788 blue_hi = (palettep[i].blue >> 6) & 0x02;
\r
790 /* Combine color intensity bits for EGA palette value */
\r
792 ega_palp[i] = (unsigned char) ((red_lo << 5) | (green_lo << 4) |
\r
793 (blue_lo << 3) | (red_hi << 1) | green_hi | (blue_hi >>
\r
797 /* Set the border (overscan) color to black (BIOS default) */
\r
799 ega_palp[16] = (unsigned char) 0;
\r
801 regs.h.ah = 0x10; /* Select "Set All Palette Registers" */
\r
804 /* Get the EGA palette registers buffer offset value */
\r
806 regs.x.dx = (unsigned int) ega_palp;
\r
808 segread(&sregs); /* Get the current DS segment register value */
\r
810 sregs.es = sregs.ds;
\r
812 int86x(0x10, ®s, ®s, &sregs); /* Call BIOS video service */
\r
814 free(ega_palp); /* Free the EGA palette buffer */
\r
819 case 0x13: /* 320 x 200 256-color VGA display */
\r
821 /* Allocate a 256-color VGA display adapter palette buffer */
\r
823 if ((vga_palp = (unsigned long *) calloc(sizeof(unsigned long),
\r
824 PCX_EPAL_SIZE)) == (unsigned long *) NULL)
\r
830 /* Map PCX extended palette to 256-color VGA palette */
\r
832 for (i = 0; i < PCX_EPAL_SIZE; i++)
\r
833 vga_palp[i] = (long) (palettep[i].red >> 2) |
\r
834 ((long) (palettep[i].green >> 2)) << 8 |
\r
835 ((long) (palettep[i].blue >> 2)) << 16;
\r
837 (void) _remapallpalette(vga_palp); /* Remap entire palette */
\r
839 free(vga_palp); /* Free the VGA palette buffer */
\r
843 default: /* Other modes not supported */
\r
854 *************************************************************************
\r
856 * PCX_CGA_PALETTE - Select CGA Palette
\r
858 * Purpose: To set the Color Graphics Adapter (CGA) display palette
\r
859 * according to a PCX file palette.
\r
861 * Setup: static void pcx_cga_palette
\r
863 * PCX_PAL *palettep,
\r
867 * Where: palettep is a pointer to a PCX file palette.
\r
868 * vmode is the MS-DOS video mode. Valid values are:
\r
870 * 0x04 - 320 x 200 4-color CGA
\r
871 * 0x05 - 320 x 200 4-color CGA (color burst off)
\r
872 * 0x06 - 640 x 200 2-color CGA
\r
874 * Note: ZSoft's PC Paintbrush products no longer support the CGA
\r
875 * color palette. When a CGA color palette is encountered,
\r
876 * PC Paintbrush maps it to a monochrome (black and white)
\r
879 * MS-DOS video mode 0x05 (320 x 200 monochrome CGA display,
\r
880 * color burst off) will only display a monochrome image on
\r
881 * a composite video monitor (typically a television set with
\r
882 * an RF adapter). All other monitors will display a color
\r
883 * palette in this mode (which is different for CGA and EGA
\r
884 * or VGA display adapters).
\r
886 * The "background" color is actually the foreground color
\r
887 * (i.e. - the color of activated pixels) for MS-DOS video
\r
888 * mode 0x06. The background color is black for CGA display
\r
891 *************************************************************************
\r
894 static void pcx_cga_palette
\r
900 short pal_num; /* Palette number */
\r
901 BOOL sel_flag; /* Palette selector bit flag */
\r
902 BOOL int_flag; /* Intensity bit flag */
\r
903 union REGS regs; /* 80x86 register values */
\r
905 /* Set the background color */
\r
907 regs.h.ah = 0x0b; /* Select "Set Color Palette" BIOS routine */
\r
910 regs.h.bl = (unsigned char) PCX_CGA_BKGND(palettep);
\r
912 int86(0x10, ®s, ®s); /* Call BIOS video service */
\r
914 if (vmode != 0x06) /* Select the CGA color palette */
\r
916 /* Check the palette selector bit flag */
\r
918 sel_flag = PCX_CGA_SELECT(palettep) ? TRUE : FALSE;
\r
920 /* Check the intensity bit flag */
\r
922 int_flag = PCX_CGA_INTENSITY(palettep) ? TRUE : FALSE;
\r
924 /* Determine the CGA palette number */
\r
926 if (int_flag == TRUE) /* Intensity = bright */
\r
928 if (sel_flag == TRUE)
\r
929 pal_num = 3; /* Light cyan - light magenta - white */
\r
931 pal_num = 1; /* Cyan - magenta - light grey */
\r
933 else /* Intensity = dim */
\r
935 if (sel_flag == TRUE)
\r
936 pal_num = 2; /* Light green - light red - yellow */
\r
938 pal_num = 0; /* Green - red - brown */
\r
941 /* Select the foreground color palette */
\r
943 (void) _selectpalette(pal_num);
\r
948 *************************************************************************
\r
950 * PCX_PUT_HERC - Display Hercules PCX Line
\r
952 * Purpose: To copy a decoded PCX image scan line to a Hercules
\r
953 * monochrome graphics display adapter buffer.
\r
955 * Setup: static void pcx_put_herc
\r
957 * PCX_WORKBLK *wbp,
\r
958 * unsigned char _far *linep,
\r
962 * Where: wbp is a PCX image file workblock pointer.
\r
963 * linep is a PCX scan line buffer pointer.
\r
964 * line_num is the scan line number.
\r
966 *************************************************************************
\r
972 unsigned char _far *linep,
\r
976 unsigned char _far *displayp; /* Display buffer pointer */
\r
978 /* Mask off unseen pixels */
\r
980 linep[wbp->num_bytes - 1] &= wbp->mask;
\r
982 /* Calculate Hercules display buffer pointer */
\r
984 displayp = (unsigned char _far *) (0xb0000000L + wbp->page_offset) +
\r
985 ((line_num >> 2) * 90) + 0x2000 * (line_num & 3);
\r
987 /* Copy data from the scan line buffer to the Hercules display buffer */
\r
989 (void) _fmemcpy(displayp, linep, wbp->num_bytes);
\r
993 *************************************************************************
\r
995 * PCX_PUT_CGA - Display CGA PCX Line
\r
997 * Purpose: To copy a decoded PCX image scan line to a CGA display
\r
1000 * Setup: static void pcx_put_cga
\r
1002 * PCX_WORKBLK *wbp,
\r
1003 * unsigned char _far *linep,
\r
1007 * Where: wbp is a PCX image file workblock pointer.
\r
1008 * linep is a PCX scan line buffer pointer.
\r
1009 * line_num is the scan line number.
\r
1011 *************************************************************************
\r
1014 static void pcx_put_cga
\r
1017 unsigned char _far *linep,
\r
1021 unsigned char _far *displayp; /* Display buffer pointer */
\r
1023 /* Mask off unseen pixels */
\r
1025 linep[wbp->num_bytes - 1] &= wbp->mask;
\r
1027 /* Calculate CGA display buffer pointer */
\r
1029 displayp = (unsigned char _far *) 0xb8000000L + ((line_num >> 1) * 80)
\r
1030 + 0x2000 * (line_num & 1);
\r
1032 /* Copy data from the scan line buffer to the CGA display buffer */
\r
1034 (void) _fmemcpy(displayp, linep, wbp->num_bytes);
\r
1038 *************************************************************************
\r
1040 * PCX_PUT_EGA - Display EGA/VGA PCX Line
\r
1042 * Purpose: To copy a decoded PCX image scan line to an EGA/VGA
\r
1043 * display adapter buffer.
\r
1045 * Setup: static void pcx_put_ega
\r
1047 * PCX_WORKBLK *wbp,
\r
1048 * unsigned char _far *linep,
\r
1052 * Where: wbp is a PCX image file workblock pointer.
\r
1053 * linep is a PCX scan line buffer pointer.
\r
1054 * line_num is the scan line number.
\r
1056 *************************************************************************
\r
1059 static void pcx_put_ega
\r
1062 unsigned char _far *linep,
\r
1066 int plane_num; /* EGA/VGA color plane number */
\r
1067 int plane_mask; /* EGA/VGA color plane mask */
\r
1068 unsigned char _far *displayp; /* Display buffer pointer */
\r
1070 /* Calculate buffer pointer */
\r
1072 displayp = (unsigned char _far *) (0xa0000000L + wbp->page_offset) +
\r
1075 outpw(0x03ce, 0x0005); /* Select EGA/VGA write mode 0 */
\r
1077 /* Copy PCX scan line data to each color plane */
\r
1079 plane_mask = 0x0100; /* Start with color plane 0 */
\r
1081 for (plane_num = 0; plane_num < (int) wbp->header.nplanes; plane_num++)
\r
1083 /* Mask off unseen pixels */
\r
1085 linep[wbp->num_bytes - 1] &= wbp->mask;
\r
1087 outpw(0x03c4, plane_mask + 2); /* Select current color plane */
\r
1089 /* Copy data from the scan line buffer to the EGA/VGA display */
\r
1091 (void) _fmemcpy(displayp, linep, wbp->num_bytes);
\r
1093 linep += wbp->header.bppscan; /* Increment plane offset */
\r
1095 plane_mask <<= 1; /* Sequence plane mask */
\r
1098 outpw(0x03c4, 0x0f02); /* Select all color planes */
\r
1102 *************************************************************************
\r
1104 * PCX_PUT_VGA - Display VGA PCX Line
\r
1106 * Purpose: To copy a decoded PCX image scan line to a VGA display
\r
1109 * Setup: static void pcx_put_vga
\r
1111 * PCX_WORKBLK *wbp,
\r
1112 * unsigned char _far *linep,
\r
1116 * Where: wbp is a PCX image file workblock pointer.
\r
1117 * linep is a PCX scan line buffer pointer.
\r
1118 * line_num is the scan line number.
\r
1120 *************************************************************************
\r
1123 static void pcx_put_vga
\r
1126 unsigned char _far *linep,
\r
1130 unsigned char _far *displayp; /* Display buffer pointer */
\r
1132 /* Calculate buffer pointer */
\r
1134 displayp = (unsigned char _far *) 0xa0000000L + line_num * 320;
\r
1136 /* Copy data from the scan line buffer to the VGA display buffer */
\r
1138 (void) _fmemcpy(displayp, linep, wbp->num_bytes);
\r