+++ /dev/null
-/*\r
- *************************************************************************\r
- *\r
- * PCX_DISP.C - PCX_LIB Library Image Display Functions\r
- *\r
- * Version: 1.00B\r
- *\r
- * History: 91/02/14 - Created\r
- * 91/04/01 - Release 1.00A\r
- * 91/04/03 - fixed "segread" call.\r
- * 91/04/07 - Release 1.00B\r
- *\r
- * Compiler: Microsoft C V6.0\r
- *\r
- * Author: Ian Ashdown, P.Eng.\r
- * byHeart Software\r
- * 620 Ballantree Road\r
- * West Vancouver, B.C.\r
- * Canada V7S 1W3\r
- * Tel. (604) 922-6148\r
- * Fax. (604) 987-7621\r
- *\r
- * Copyright: Public Domain\r
- *\r
- *************************************************************************\r
- */\r
-\f\r
-/*\r
- *************************************************************************\r
- *\r
- * PORTABILITY NOTES\r
- *\r
- * 1. While this program is written in ANSI C, it uses a number of \r
- * function calls that are specific to the Microsoft C V6.0 library.\r
- * These are documented as follows for the purposes of porting this\r
- * program to other compilers and/or processors: \r
- *\r
- * _fmemcpy - "memcpy" for small model / far data\r
- * int86 - execute 80x86 interrupt routine\r
- * int86x - execute 80x86 interrupt routine (far\r
- * data)\r
- * _remapallpalette - remap entire video display color palette\r
- * _selectpalette - select CGA color palette\r
- * outpw - output word to 80x86 I/O port\r
- * segread - get current 80x86 segment register\r
- * values\r
- *\r
- * 2. When porting this program to other processors, remember that words\r
- * are stored by 80x86-based machines in the big-endian format. That\r
- * is, the eight least significant bits (lower byte) are stored\r
- * first, followed by the eight most significant bits (upper byte).\r
- * If PCX-format files are transferred to little-endian machines\r
- * (such as those based on 680x0 and Z8000 processors), the order of\r
- * bytes within each word will have to be reversed before they can \r
- * be interpreted. (This applies to the file header only, since the\r
- * encoded image data and optional 256-color palette are stored as\r
- * bytes.)\r
- *\r
- * 3. MS-DOS does not recognize the 720 x 348 graphics mode of the\r
- * Hercules monochrome display adapter. Therefore, the constant\r
- * PCX_HERC should never be passed as a video mode parameter to any\r
- * BIOS service routine.\r
- *\r
- * The Microsoft C compiler includes a "video mode" parameter\r
- * definition (_HERCMONO) that is defined as 0x08. This is a\r
- * reserved MS-DOS video mode that is apparently used internally by\r
- * the ROM BIOS. It can, however, be passed to the Microsoft C\r
- * library function "_setvideomode" to force the Hercules display\r
- * adapter into graphics mode.\r
- *\r
- * Most other MS-DOS C compilers offer similar library functions to\r
- * force the Hercules monochrome display adapter into its 720 x 348\r
- * graphics mode.\r
- *\r
- ************************************************************************* \r
- */\r
-\f\r
-/* INCLUDE FILES */\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <conio.h>\r
-#include <dos.h>\r
-#include <malloc.h>\r
-#include <graph.h>\r
-#include "pcx_int.h"\r
-\f\r
-/* FORWARD REFERENCES */\r
-\r
-static BOOL pcx_read_init(PCX_WORKBLK *, int, int);\r
-static BOOL pcx_read_extpal(PCX_WORKBLK *);\r
-static BOOL pcx_read_header(PCX_WORKBLK *);\r
-static BOOL pcx_read_line(PCX_WORKBLK *, unsigned char *, int);\r
-static BOOL pcx_set_palette(PCX_PAL *, int);\r
-\r
-static void pcx_cga_palette(PCX_PAL *, int);\r
-static void pcx_put_cga(PCX_WORKBLK *, unsigned char _far *, int);\r
-static void pcx_put_ega(PCX_WORKBLK *, unsigned char _far *, int);\r
-static void pcx_put_herc(PCX_WORKBLK *, unsigned char _far *, int);\r
-static void pcx_put_vga(PCX_WORKBLK *, unsigned char _far *, int);\r
-\f\r
-/* GLOBALS */\r
-\f\r
-/* PUBLIC FUNCTIONS */\r
-\r
-/*\r
- *************************************************************************\r
- *\r
- * PCX_READ - Read PCX Image File\r
- *\r
- * Purpose: To read and display a PCX-format image file.\r
- *\r
- * Setup: BOOL pcx_read\r
- * (\r
- * char *fname,\r
- * int vmode,\r
- * int page\r
- * )\r
- *\r
- * Where: fname is a PCX image file name.\r
- * vmode is the MS-DOS video mode. Valid values are:\r
- *\r
- * PCX_HERC - 720 x 348 Hercules monochrome\r
- * 0x04 - 320 x 200 4-color CGA\r
- * 0x05 - 320 x 200 4-color CGA (color burst off)\r
- * 0x06 - 640 x 200 2-color CGA\r
- * 0x0d - 320 x 200 16-color EGA/VGA\r
- * 0x0e - 640 x 200 16-color EGA/VGA\r
- * 0x0f - 640 x 350 2-color EGA/VGA\r
- * 0x10 - 640 x 350 16-color EGA/VGA\r
- * 0x11 - 640 x 480 2-color VGA\r
- * 0x12 - 640 x 480 16-color VGA\r
- * 0x13 - 320 x 200 256-color VGA\r
- *\r
- * page is the video display page number. Valid values are:\r
- *\r
- * Mode PCX_HERC - 0 or 1\r
- * Mode 0x0d - 0 to 7\r
- * Mode 0x0e - 0 to 3\r
- * Mode 0x0f - 0 or 1\r
- * Mode 0x10 - 0 or 1\r
- * All Other - 0\r
- *\r
- * Return: TRUE if successful; otherwise FALSE.\r
- *\r
- * Note: The video display adapter must be in the appropriate mode\r
- * and active page for the image to be displayed.\r
- *\r
- *************************************************************************\r
- */\r
-\r
-BOOL pcx_read\r
-(\r
- char *fname,\r
- int vmode,\r
- int page\r
-)\r
-{\r
- int bpline; /* Number of bytes per scan line */\r
- int line_num; /* Scan line number */\r
- int max_lines; /* Maximum number of scan lines */\r
- unsigned char *linep; /* PCX scan line buffer pointer */\r
- BOOL status = TRUE; /* Return status */\r
- PCX_WORKBLK *wbp; /* PCX image file workblock pointer */\r
-\r
- /* Open a PCX image file workblock */\r
-\r
- if ((wbp = pcx_open(fname, FALSE)) == (PCX_WORKBLK *) NULL)\r
- return (FALSE);\r
-\r
- /* Initialize the workblock for reading */\r
-\r
- if (pcx_read_init(wbp, vmode, page) == FALSE)\r
- {\r
- (void) pcx_close(wbp); /* Close the PCX workblock */\r
- return (FALSE);\r
- }\r
-\r
- /* Calculate the image height */\r
-\r
- max_lines = wbp->header.yul + wbp->header.ylr + 1;\r
-\r
- /* Calculate number of bytes per line (for all color planes) */\r
-\r
- bpline = wbp->header.bppscan * wbp->header.nplanes;\r
-\r
- /* Allocate the PCX scan line buffer */\r
-\r
- if ((linep = (unsigned char *) malloc(bpline)) != (unsigned char *)\r
- NULL)\r
- {\r
- /* Set the file pointer to the beginning of the encoded image data */\r
-\r
- if (status == TRUE)\r
- if (fseek(wbp->fp, (long) (sizeof(PCX_HDR)), SEEK_SET) != 0)\r
- status = FALSE;\r
-\r
- /* Set the video display adapter color palette unless the PCX file */\r
- /* is Version 3.0 (i.e. - PC Paintbrush Version 2.8 w/o palette) */\r
-\r
- if (status == TRUE)\r
- if (wbp->header.version != 3)\r
- if (pcx_set_palette(wbp->palettep, vmode) == FALSE)\r
- status = FALSE;\r
-\r
- /* Read the image line by line */\r
-\r
- if (status == TRUE)\r
- {\r
- for (line_num = 0; line_num < max_lines; line_num++)\r
- {\r
- /* Read the current scan line */\r
-\r
- if ((status = pcx_read_line(wbp, linep, bpline)) == FALSE)\r
- {\r
- status = FALSE;\r
- break;\r
- }\r
-\r
- /* Display the current scan line */\r
-\r
- wbp->pcx_funcp(wbp, (unsigned char _far *) linep, line_num);\r
- }\r
- }\r
-\r
- free(linep); /* Free the PCX scan line buffer */\r
- }\r
- else\r
- status = FALSE;\r
- \r
- if (pcx_close(wbp) == FALSE) /* Close the PCX workblock */\r
- status = FALSE;\r
-\r
- return (status);\r
-}\r
-\f\r
-/* PRIVATE FUNCTIONS */\r
-\r
-/*\r
- *************************************************************************\r
- *\r
- * PCX_READ_INIT - Initialize PCX Workblock For Reading\r
- *\r
- * Purpose: To initialize a PCX image file workblock for reading.\r
- *\r
- * Setup: static BOOL pcx_read_init\r
- * (\r
- * PCX_WORKBLK *wbp,\r
- * int vmode,\r
- * int page\r
- * )\r
- *\r
- * Where: wbp is a PCX workblock pointer.\r
- * vmode is the MS-DOS video mode. Valid values are:\r
- *\r
- * PCX_HERC - 720 x 348 Hercules monochrome\r
- * 0x04 - 320 x 200 4-color CGA\r
- * 0x05 - 320 x 200 4-color CGA (color burst off)\r
- * 0x06 - 640 x 200 2-color CGA\r
- * 0x0d - 320 x 200 16-color EGA/VGA\r
- * 0x0e - 640 x 200 16-color EGA/VGA\r
- * 0x0f - 640 x 350 2-color EGA/VGA\r
- * 0x10 - 640 x 350 16-color EGA/VGA\r
- * 0x11 - 640 x 480 2-color VGA\r
- * 0x12 - 640 x 480 16-color VGA\r
- * 0x13 - 320 x 200 256-color VGA\r
- *\r
- * page is the video display page number. Valid values are:\r
- *\r
- * Mode PCX_HERC - 0 or 1\r
- * Mode 0x0d - 0 to 7\r
- * Mode 0x0e - 0 to 3\r
- * Mode 0x0f - 0 or 1\r
- * Mode 0x10 - 0 or 1\r
- * All Other - 0\r
- *\r
- * Return: TRUE if successful; otherwise FALSE.\r
- *\r
- *************************************************************************\r
- */\r
-\r
-static BOOL pcx_read_init\r
-(\r
- PCX_WORKBLK *wbp,\r
- int vmode,\r
- int page\r
-)\r
-{\r
- int width; /* Display width */\r
- int leftover; /* Number of unseen bits */\r
- BOOL status = TRUE; /* Return status */\r
-\r
- /* Read the file header */\r
-\r
- if ((pcx_read_header(wbp)) == FALSE)\r
- return (FALSE);\r
-\r
- /* Initialize the workblock color palette pointer */\r
-\r
- wbp->palettep = wbp->header.palette;\r
- wbp->epal_flag = FALSE;\r
-\r
- /* Read the extended palette (if any) */\r
-\r
- if (vmode == 0x13 && wbp->header.version == 5)\r
- if (pcx_read_extpal(wbp) == FALSE)\r
- return (FALSE);\r
-\r
- /* Initialize the display page address offset */\r
-\r
- wbp->page_offset = (unsigned long) 0L;\r
-\r
- switch (vmode) /* Select PCX line display function */\r
- {\r
- case PCX_HERC: /* 720 x 348 Hercules monochrome */\r
-\r
- /* Hercules monochrome display adapter supports 2 pages */\r
-\r
- wbp->page_offset = 0x08000000L * (unsigned long) page;\r
-\r
- /* Calculate display width in pixels */\r
-\r
- width = min((wbp->header.xlr - wbp->header.xul + 1), 720);\r
-\r
- /* Calculate number of bytes to display */\r
-\r
- wbp->num_bytes = (width + 7) >> 3;\r
-\r
- /* Calculate mask for leftover bits */\r
-\r
- if ((leftover = width & 7) != 0)\r
- wbp->mask = (0xff << (8 - leftover)) & 0xff;\r
- else\r
- wbp->mask = 0xff;\r
-\r
- wbp->pcx_funcp = pcx_put_herc; /* Set the display function ptr */\r
-\r
- break;\r
-\r
- case 0x04: /* 320 x 200 4-color CGA */\r
- case 0x05: /* 320 x 200 4-color CGA (color burst off) */\r
- \r
- /* Calculate display width in pixels */\r
-\r
- width = min((wbp->header.xlr - wbp->header.xul + 1), 320);\r
-\r
- /* Calculate number of bytes to display */\r
-\r
- wbp->num_bytes = (width + 3) >> 2;\r
-\r
- /* Calculate mask for leftover bits */\r
-\r
- if ((leftover = (width & 3) << 1) != 0)\r
- wbp->mask = (0xff << (8 - leftover)) & 0xff;\r
- else\r
- wbp->mask = 0xff;\r
-\r
- wbp->pcx_funcp = pcx_put_cga; /* Set the display function ptr */\r
-\r
- break;\r
-\r
- case 0x06: /* 640 x 200 2-color CGA */\r
-\r
- /* Calculate display width in pixels */\r
-\r
- width = min((wbp->header.xlr - wbp->header.xul + 1), 640);\r
-\r
- /* Calculate number of bytes to display */\r
-\r
- wbp->num_bytes = (width + 7) >> 3;\r
-\r
- /* Calculate mask for leftover bits */\r
-\r
- if ((leftover = width & 7) != 0)\r
- wbp->mask = (0xff << (8 - leftover)) & 0xff;\r
- else\r
- wbp->mask = 0xff;\r
-\r
- wbp->pcx_funcp = pcx_put_cga; /* Set the display function ptr */\r
-\r
- break;\r
-\r
- case 0x0d: /* 320 x 200 16-color EGA/VGA */\r
- case 0x0e: /* 640 x 200 16-color EGA/VGA */\r
- case 0x0f: /* 640 x 350 2-color EGA/VGA */\r
- case 0x10: /* 640 x 350 16-color EGA/VGA */\r
- case 0x11: /* 640 x 480 2-color VGA */\r
- case 0x12: /* 640 x 480 16-color VGA */\r
-\r
- switch (vmode) /* Initialize the display adapter page offset */\r
- {\r
- case 0x0d: /* 320 x 200 16-color EGA/VGA (8 pages maximum) */\r
-\r
- wbp->page_offset = 0x02000000L * (unsigned long) page;\r
-\r
- break;\r
-\r
- case 0x0e: /* 640 x 200 16-color EGA/VGA (4 pages maximum) */\r
-\r
- wbp->page_offset = 0x04000000L * (unsigned long) page;\r
-\r
- break;\r
-\r
- case 0x0f: /* 640 x 350 2-color EGA/VGA (2 pages maximum) */\r
- case 0x10: /* 640 x 350 16-color EGA/VGA (2 pages maximum) */\r
-\r
- wbp->page_offset = 0x08000000L * (unsigned long) page;\r
-\r
- break;\r
-\r
- default: /* All other modes support only one page */\r
-\r
- break;\r
- }\r
-\r
- /* Calculate display width in pixels */\r
-\r
- width = min((wbp->header.xlr - wbp->header.xul + 1), 640);\r
-\r
- /* Calculate number of bytes to display */\r
-\r
- wbp->num_bytes = (width + 7) >> 3;\r
-\r
- /* Calculate mask for leftover bits */\r
-\r
- if ((leftover = width & 7) != 0)\r
- wbp->mask = (0xff << (8 - leftover)) & 0xff;\r
- else\r
- wbp->mask = 0xff;\r
-\r
- wbp->pcx_funcp = pcx_put_ega; /* Set the display function ptr */\r
-\r
- break;\r
-\r
- case 0x13: /* 320 x 200 256-color VGA */\r
-\r
- /* Calculate number of bytes to display */\r
-\r
- wbp->num_bytes = min((wbp->header.xlr - wbp->header.xul + 1), 320);\r
-\r
- wbp->mask = 0; /* Dummy parameter */\r
-\r
- wbp->pcx_funcp = pcx_put_vga; /* Set the display function ptr */\r
-\r
- break;\r
-\r
- default: /* Other display adapters not supported */\r
-\r
- status = FALSE;\r
-\r
- break;\r
- }\r
-\r
- return (status);\r
-}\r
-\f\r
-/*\r
- *************************************************************************\r
- *\r
- * PCX_READ_HEADER - Read PCX File Header\r
- *\r
- * Purpose: To read and validate a PCX file header.\r
- *\r
- * Setup: static BOOL pcx_read_header\r
- * (\r
- * PCX_WORKBLK *wbp\r
- * )\r
- *\r
- * Where: wbp is a PCX image file workblock pointer.\r
- *\r
- * Return: TRUE if successful; otherwise FALSE.\r
- *\r
- * Result: The file header is read into the "header" member of the\r
- * PCX workblock.\r
- *\r
- *************************************************************************\r
- */\r
-\r
-static BOOL pcx_read_header\r
-(\r
- PCX_WORKBLK *wbp\r
-)\r
-{\r
- BOOL status = TRUE; /* Status flag */\r
- PCX_HDR *hdrp; /* PCX file header buffer pointer */\r
-\r
- hdrp = &(wbp->header); /* Initialize the file header pointer */\r
-\r
- /* Read the file header */\r
-\r
- if (fseek(wbp->fp, 0L, SEEK_SET) != 0)\r
- status = FALSE;\r
-\r
- if (status == TRUE)\r
- if (fread(hdrp, sizeof(PCX_HDR), 1, wbp->fp) != 1)\r
- status = FALSE;\r
-\r
- /* Validate the PCX file format */\r
-\r
- if (status == TRUE)\r
- if ((hdrp->pcx_id != 0x0a) || (hdrp->encoding != 1))\r
- status = FALSE;\r
-\r
- return (status);\r
-}\r
-\f\r
-/*\r
- *************************************************************************\r
- *\r
- * PCX_READ_EXTPAL - Read Extended Palette\r
- *\r
- * Purpose: To read an extended (256-color) palette (if it exists).\r
- *\r
- * Setup: static BOOL pcx_read_extpal\r
- * (\r
- * PCX_WORKBLK *wbp\r
- * )\r
- *\r
- * Where: wbp is a PCX image file workblock pointer.\r
- *\r
- * Return: TRUE if successful; otherwise FALSE.\r
- *\r
- * Note: It is possible for a PCX image file without an appended\r
- * 256-color palette to have the value 0x0c as the 769th byte\r
- * (the location of the extended palette indicator byte) from \r
- * the end of the file (i.e. - in the encoded image data \r
- * section). This function will misinterpret the following\r
- * 768 bytes of encoded image data as an extended palette.\r
- *\r
- * This problem will only occur if an attempt is made to\r
- * display a PCX image using the wrong MS-DOS video mode. It\r
- * can be detected by decoding the image data and using \r
- * "ftell" to note the file position of the end of the \r
- * encoded image data section, then comparing it to the file\r
- * position of the indicator byte. If the supposed indicator\r
- * byte is located within the encoded image data section, the\r
- * indicator byte is invalid and so the file header palette\r
- * should be used instead.\r
- *\r
- *************************************************************************\r
- */\r
-\r
-static BOOL pcx_read_extpal\r
-(\r
- PCX_WORKBLK *wbp\r
-)\r
-{\r
- int indicator; /* PCX extended palette indicator */\r
-\r
- /* Position the file pointer to the extended palette indicator byte */\r
-\r
- if (fseek(wbp->fp, -769L, SEEK_END) != 0)\r
- return (FALSE);\r
-\r
- /* Read the (assumed) extended palette indicator byte */\r
-\r
- if ((indicator = getc(wbp->fp)) == EOF)\r
- return (FALSE);\r
-\r
- if (indicator == PCX_EPAL_FLAG) /* Check for indicator byte */\r
- {\r
- /* Allocate an extended palette buffer */\r
-\r
- if ((wbp->palettep = (PCX_PAL *) calloc(sizeof(PCX_PAL),\r
- PCX_EPAL_SIZE)) == (PCX_PAL *) NULL)\r
- return (FALSE);\r
-\r
- /* Read the extended palette */\r
-\r
- if (fread(wbp->palettep, sizeof(PCX_PAL), PCX_EPAL_SIZE, wbp->fp) !=\r
- PCX_EPAL_SIZE)\r
- {\r
- free(wbp->palettep); /* Free the extended palette buffer */\r
- return (FALSE);\r
- }\r
-\r
- wbp->epal_flag = TRUE; /* Indicate extended palette present */\r
- }\r
-\r
- return (TRUE);\r
-}\r
-\f\r
-/*\r
- *************************************************************************\r
- *\r
- * PCX_READ_LINE - Read PCX Line\r
- *\r
- * Purpose: To read an encoded line (all color planes) from a PCX-\r
- * format image file and write the decoded data to a line\r
- * buffer.\r
- *\r
- * Setup: static BOOL pcx_read_line\r
- * (\r
- * PCX_WORKBLK *wbp,\r
- * unsigned char *linep,\r
- * int bpline\r
- * )\r
- *\r
- * Where: wbp is a PCX image file workblock pointer.\r
- * linep is a PCX scan line buffer pointer.\r
- * bpline is the number of bytes per scan line (all color\r
- * planes).\r
- *\r
- * Return: TRUE if successful; otherwise FALSE.\r
- *\r
- *************************************************************************\r
- */\r
-\r
-static BOOL pcx_read_line\r
-(\r
- PCX_WORKBLK *wbp,\r
- unsigned char *linep,\r
- int bpline\r
-)\r
-{\r
- int data; /* Image data byte */\r
- int count; /* Image data byte repeat count */\r
- int offset = 0; /* Scan line buffer offset */\r
-\r
- while (offset < bpline) /* Decode current scan line */\r
- {\r
- if ((data = getc(wbp->fp)) == EOF) /* Get next byte */\r
- return (FALSE);\r
-\r
- /* If top two bits of byte are set, lower six bits show how */\r
- /* many times to duplicate next byte */\r
-\r
- if ((data & PCX_COMP_FLAG) == PCX_COMP_FLAG)\r
- {\r
- count = data & PCX_COMP_MASK; /* Mask off repeat count */\r
-\r
- if ((data = getc(wbp->fp)) == EOF) /* Get next byte */\r
- return (FALSE);\r
-\r
- memset(linep, data, count); /* Duplicate byte */\r
- linep += count;\r
- offset += count;\r
- }\r
- else\r
- {\r
- *linep++ = (unsigned char) data; /* Copy byte */\r
- offset++;\r
- }\r
- }\r
-\r
- return (TRUE);\r
-}\r
-\f\r
-/*\r
- *************************************************************************\r
- *\r
- * PCX_SET_PALETTE - Set Palette\r
- *\r
- * Purpose: To set the display palette according to a PCX file\r
- * palette.\r
- *\r
- * Setup: static BOOL pcx_set_palette\r
- * (\r
- * PCX_PAL *palettep,\r
- * int vmode\r
- * )\r
- *\r
- * Where: palettep is a pointer to a PCX file palette.\r
- * vmode is the MS-DOS video mode. Valid values are:\r
- *\r
- * PCX_HERC - 720 x 348 Hercules monochrome\r
- * 0x04 - 320 x 200 4-color CGA\r
- * 0x05 - 320 x 200 4-color CGA (color burst off)\r
- * 0x06 - 640 x 200 2-color CGA\r
- * 0x0d - 320 x 200 16-color EGA/VGA\r
- * 0x0e - 640 x 200 16-color EGA/VGA\r
- * 0x0f - 640 x 350 2-color EGA/VGA\r
- * 0x10 - 640 x 350 16-color EGA/VGA\r
- * 0x11 - 640 x 480 2-color VGA\r
- * 0x12 - 640 x 480 16-color VGA\r
- * 0x13 - 320 x 200 256-color VGA\r
- *\r
- * Return: TRUE if successful; otherwise FALSE.\r
- *\r
- *************************************************************************\r
- */\r
-\r
-static BOOL pcx_set_palette\r
-(\r
- PCX_PAL *palettep,\r
- int vmode\r
-)\r
-{\r
- int i; /* Scratch counter */\r
- int red_lo; /* Low red intensity */\r
- int red_hi; /* High red intensity */\r
- int green_lo; /* Green low intensity */\r
- int green_hi; /* Green high intensity */\r
- int blue_lo; /* Blue low intensity */\r
- int blue_hi; /* Blue high intensity */\r
- unsigned char *ega_palp; /* EGA 16-color palette buffer pointer */\r
- unsigned long *vga_palp; /* VGA 256-color palette buffer pointer */\r
- BOOL status = TRUE; /* Return status */\r
- union REGS regs; /* 80x86 register values */\r
- struct SREGS sregs; /* 80x86 segment register values */\r
-\r
- switch (vmode)\r
- {\r
- case PCX_HERC: /* 720 x 348 Hercules monochrome */\r
-\r
- break;\r
-\r
- case 0x04: /* 320 x 200 4-color CGA display */\r
- case 0x05: /* 320 x 200 monochrome CGA display (burst off) */\r
- case 0x06: /* 640 x 200 2-color CGA display */\r
-\r
- /* Set the CGA color palette */\r
-\r
- pcx_cga_palette(palettep, vmode);\r
-\r
- break;\r
-\r
- case 0x0d: /* 320 x 200 16-color EGA/VGA */\r
- case 0x0e: /* 640 x 200 16-color EGA/VGA */\r
- case 0x0f: /* 640 x 350 2-color EGA/VGA */\r
- case 0x10: /* 640 x 350 16-color EGA/VGA */\r
- case 0x11: /* 640 x 480 2-color VGA */\r
- case 0x12: /* 640 x 480 16-color VGA */\r
-\r
- if (pcx_isvga() == TRUE) /* Check for VGA display adapter */\r
- {\r
- /* Allocate a 16-color VGA display adapter palette buffer */\r
-\r
- if ((vga_palp = (unsigned long *) calloc(sizeof(unsigned long),\r
- PCX_PAL_SIZE)) == (unsigned long *) NULL)\r
- {\r
- status = FALSE;\r
- break;\r
- }\r
-\r
- /* Map PCX hardware palette to 16-color VGA palette (each color */\r
- /* value is a "long" with the form: */\r
- /* */\r
- /* 00000000-00BBBBBB-00GGGGGG-00RRRRRR */\r
- /* */\r
- /* where each color is a 6-bit value. */\r
-\r
- for (i = 0; i < PCX_PAL_SIZE; i++)\r
- vga_palp[i] = (long) (palettep[i].red >> 2) |\r
- ((long) (palettep[i].green >> 2)) << 8 |\r
- ((long) (palettep[i].blue >> 2)) << 16;\r
-\r
- (void) _remapallpalette(vga_palp); /* Remap entire palette */\r
-\r
- free(vga_palp); /* Free the VGA palette buffer */\r
- }\r
- else /* EGA display adapter */\r
- {\r
- /* Allocate an EGA display adapter palette buffer */\r
-\r
- if ((ega_palp = (unsigned char *) calloc(sizeof(unsigned char),\r
- PCX_PAL_SIZE + 1)) == (unsigned char *) NULL)\r
- {\r
- status = FALSE;\r
- break;\r
- }\r
-\r
- /* Map PCX hardware palette to 16-color EGA palette (each EGA */\r
- /* color value is an "unsigned char" with the form: */\r
- /* */\r
- /* 0 0 R' G' B' R G B */\r
- /* */\r
- /* where X' is the low-intensity value and X is the high */\r
- /* intensity value for the color X.) */\r
- /* */\r
- /* NOTE: the "_remapallpalette" function could be used to set */\r
- /* the palette for EGA display adapters. However, this */\r
- /* function does not appear to update the palette */\r
- /* register values in the Dynamic Save Area (see the */\r
- /* function header for "pcx_init_palette" in PCX_FILE.C) */\r
- /* for a detailed explanation). */\r
-\r
- for (i = 0; i < PCX_PAL_SIZE; i++)\r
- {\r
- /* Extract low and high intensity bits for each color */\r
-\r
- red_lo = (palettep[i].red >> 6) & 0x01;\r
- red_hi = (palettep[i].red >> 6) & 0x02;\r
- green_lo = (palettep[i].green >> 6) & 0x01;\r
- green_hi = (palettep[i].green >> 6) & 0x02;\r
- blue_lo = (palettep[i].blue >> 6) & 0x01;\r
- blue_hi = (palettep[i].blue >> 6) & 0x02;\r
-\r
- /* Combine color intensity bits for EGA palette value */\r
-\r
- ega_palp[i] = (unsigned char) ((red_lo << 5) | (green_lo << 4) |\r
- (blue_lo << 3) | (red_hi << 1) | green_hi | (blue_hi >>\r
- 1));\r
- }\r
-\r
- /* Set the border (overscan) color to black (BIOS default) */\r
-\r
- ega_palp[16] = (unsigned char) 0;\r
-\r
- regs.h.ah = 0x10; /* Select "Set All Palette Registers" */\r
- regs.h.al = 0x02;\r
-\r
- /* Get the EGA palette registers buffer offset value */\r
-\r
- regs.x.dx = (unsigned int) ega_palp;\r
-\r
- segread(&sregs); /* Get the current DS segment register value */\r
-\r
- sregs.es = sregs.ds;\r
-\r
- int86x(0x10, ®s, ®s, &sregs); /* Call BIOS video service */\r
-\r
- free(ega_palp); /* Free the EGA palette buffer */\r
- }\r
-\r
- break;\r
-\r
- case 0x13: /* 320 x 200 256-color VGA display */\r
-\r
- /* Allocate a 256-color VGA display adapter palette buffer */\r
-\r
- if ((vga_palp = (unsigned long *) calloc(sizeof(unsigned long),\r
- PCX_EPAL_SIZE)) == (unsigned long *) NULL)\r
- {\r
- status = FALSE;\r
- break;\r
- }\r
-\r
- /* Map PCX extended palette to 256-color VGA palette */\r
-\r
- for (i = 0; i < PCX_EPAL_SIZE; i++)\r
- vga_palp[i] = (long) (palettep[i].red >> 2) |\r
- ((long) (palettep[i].green >> 2)) << 8 |\r
- ((long) (palettep[i].blue >> 2)) << 16;\r
-\r
- (void) _remapallpalette(vga_palp); /* Remap entire palette */\r
-\r
- free(vga_palp); /* Free the VGA palette buffer */\r
-\r
- break;\r
-\r
- default: /* Other modes not supported */\r
-\r
- status = FALSE;\r
-\r
- break;\r
- }\r
-\r
- return (status);\r
-}\r
-\f\r
-/*\r
- *************************************************************************\r
- *\r
- * PCX_CGA_PALETTE - Select CGA Palette\r
- *\r
- * Purpose: To set the Color Graphics Adapter (CGA) display palette\r
- * according to a PCX file palette.\r
- *\r
- * Setup: static void pcx_cga_palette\r
- * (\r
- * PCX_PAL *palettep,\r
- * int vmode\r
- * )\r
- *\r
- * Where: palettep is a pointer to a PCX file palette.\r
- * vmode is the MS-DOS video mode. Valid values are:\r
- *\r
- * 0x04 - 320 x 200 4-color CGA\r
- * 0x05 - 320 x 200 4-color CGA (color burst off)\r
- * 0x06 - 640 x 200 2-color CGA\r
- *\r
- * Note: ZSoft's PC Paintbrush products no longer support the CGA\r
- * color palette. When a CGA color palette is encountered,\r
- * PC Paintbrush maps it to a monochrome (black and white)\r
- * palette.\r
- *\r
- * MS-DOS video mode 0x05 (320 x 200 monochrome CGA display,\r
- * color burst off) will only display a monochrome image on\r
- * a composite video monitor (typically a television set with\r
- * an RF adapter). All other monitors will display a color\r
- * palette in this mode (which is different for CGA and EGA\r
- * or VGA display adapters).\r
- *\r
- * The "background" color is actually the foreground color\r
- * (i.e. - the color of activated pixels) for MS-DOS video\r
- * mode 0x06. The background color is black for CGA display\r
- * adapters.\r
- *\r
- *************************************************************************\r
- */\r
-\r
-static void pcx_cga_palette\r
-(\r
- PCX_PAL *palettep,\r
- int vmode\r
-)\r
-{\r
- short pal_num; /* Palette number */\r
- BOOL sel_flag; /* Palette selector bit flag */\r
- BOOL int_flag; /* Intensity bit flag */\r
- union REGS regs; /* 80x86 register values */\r
-\r
- /* Set the background color */\r
-\r
- regs.h.ah = 0x0b; /* Select "Set Color Palette" BIOS routine */\r
- regs.h.bh = 0;\r
-\r
- regs.h.bl = (unsigned char) PCX_CGA_BKGND(palettep);\r
-\r
- int86(0x10, ®s, ®s); /* Call BIOS video service */\r
-\r
- if (vmode != 0x06) /* Select the CGA color palette */\r
- {\r
- /* Check the palette selector bit flag */\r
-\r
- sel_flag = PCX_CGA_SELECT(palettep) ? TRUE : FALSE;\r
-\r
- /* Check the intensity bit flag */\r
-\r
- int_flag = PCX_CGA_INTENSITY(palettep) ? TRUE : FALSE;\r
-\r
- /* Determine the CGA palette number */\r
-\r
- if (int_flag == TRUE) /* Intensity = bright */\r
- {\r
- if (sel_flag == TRUE)\r
- pal_num = 3; /* Light cyan - light magenta - white */\r
- else\r
- pal_num = 1; /* Cyan - magenta - light grey */\r
- }\r
- else /* Intensity = dim */\r
- {\r
- if (sel_flag == TRUE)\r
- pal_num = 2; /* Light green - light red - yellow */\r
- else\r
- pal_num = 0; /* Green - red - brown */\r
- }\r
-\r
- /* Select the foreground color palette */\r
-\r
- (void) _selectpalette(pal_num);\r
- }\r
-}\r
-\f\r
-/*\r
- *************************************************************************\r
- *\r
- * PCX_PUT_HERC - Display Hercules PCX Line\r
- *\r
- * Purpose: To copy a decoded PCX image scan line to a Hercules\r
- * monochrome graphics display adapter buffer.\r
- *\r
- * Setup: static void pcx_put_herc\r
- * (\r
- * PCX_WORKBLK *wbp,\r
- * unsigned char _far *linep,\r
- * int line_num\r
- * )\r
- *\r
- * Where: wbp is a PCX image file workblock pointer.\r
- * linep is a PCX scan line buffer pointer.\r
- * line_num is the scan line number.\r
- *\r
- *************************************************************************\r
- */\r
-\r
-void pcx_put_herc\r
-(\r
- PCX_WORKBLK *wbp,\r
- unsigned char _far *linep,\r
- int line_num\r
-)\r
-{\r
- unsigned char _far *displayp; /* Display buffer pointer */\r
-\r
- /* Mask off unseen pixels */\r
-\r
- linep[wbp->num_bytes - 1] &= wbp->mask;\r
-\r
- /* Calculate Hercules display buffer pointer */\r
-\r
- displayp = (unsigned char _far *) (0xb0000000L + wbp->page_offset) +\r
- ((line_num >> 2) * 90) + 0x2000 * (line_num & 3);\r
-\r
- /* Copy data from the scan line buffer to the Hercules display buffer */\r
-\r
- (void) _fmemcpy(displayp, linep, wbp->num_bytes);\r
-}\r
-\f\r
-/*\r
- *************************************************************************\r
- *\r
- * PCX_PUT_CGA - Display CGA PCX Line\r
- *\r
- * Purpose: To copy a decoded PCX image scan line to a CGA display\r
- * adapter buffer.\r
- *\r
- * Setup: static void pcx_put_cga\r
- * (\r
- * PCX_WORKBLK *wbp,\r
- * unsigned char _far *linep,\r
- * int line_num\r
- * )\r
- *\r
- * Where: wbp is a PCX image file workblock pointer.\r
- * linep is a PCX scan line buffer pointer.\r
- * line_num is the scan line number.\r
- *\r
- *************************************************************************\r
- */\r
-\r
-static void pcx_put_cga\r
-(\r
- PCX_WORKBLK *wbp,\r
- unsigned char _far *linep,\r
- int line_num\r
-)\r
-{\r
- unsigned char _far *displayp; /* Display buffer pointer */\r
-\r
- /* Mask off unseen pixels */\r
-\r
- linep[wbp->num_bytes - 1] &= wbp->mask;\r
-\r
- /* Calculate CGA display buffer pointer */\r
-\r
- displayp = (unsigned char _far *) 0xb8000000L + ((line_num >> 1) * 80)\r
- + 0x2000 * (line_num & 1);\r
-\r
- /* Copy data from the scan line buffer to the CGA display buffer */\r
-\r
- (void) _fmemcpy(displayp, linep, wbp->num_bytes);\r
-}\r
-\f\r
-/*\r
- *************************************************************************\r
- *\r
- * PCX_PUT_EGA - Display EGA/VGA PCX Line\r
- *\r
- * Purpose: To copy a decoded PCX image scan line to an EGA/VGA\r
- * display adapter buffer.\r
- *\r
- * Setup: static void pcx_put_ega\r
- * (\r
- * PCX_WORKBLK *wbp,\r
- * unsigned char _far *linep,\r
- * int line_num\r
- * )\r
- *\r
- * Where: wbp is a PCX image file workblock pointer.\r
- * linep is a PCX scan line buffer pointer.\r
- * line_num is the scan line number.\r
- *\r
- *************************************************************************\r
- */\r
-\r
-static void pcx_put_ega\r
-(\r
- PCX_WORKBLK *wbp,\r
- unsigned char _far *linep,\r
- int line_num\r
-)\r
-{\r
- int plane_num; /* EGA/VGA color plane number */\r
- int plane_mask; /* EGA/VGA color plane mask */\r
- unsigned char _far *displayp; /* Display buffer pointer */\r
-\r
- /* Calculate buffer pointer */\r
-\r
- displayp = (unsigned char _far *) (0xa0000000L + wbp->page_offset) +\r
- line_num * 80;\r
-\r
- outpw(0x03ce, 0x0005); /* Select EGA/VGA write mode 0 */\r
-\r
- /* Copy PCX scan line data to each color plane */\r
-\r
- plane_mask = 0x0100; /* Start with color plane 0 */\r
-\r
- for (plane_num = 0; plane_num < (int) wbp->header.nplanes; plane_num++)\r
- {\r
- /* Mask off unseen pixels */\r
-\r
- linep[wbp->num_bytes - 1] &= wbp->mask;\r
-\r
- outpw(0x03c4, plane_mask + 2); /* Select current color plane */\r
-\r
- /* Copy data from the scan line buffer to the EGA/VGA display */\r
-\r
- (void) _fmemcpy(displayp, linep, wbp->num_bytes);\r
-\r
- linep += wbp->header.bppscan; /* Increment plane offset */\r
-\r
- plane_mask <<= 1; /* Sequence plane mask */\r
- }\r
-\r
- outpw(0x03c4, 0x0f02); /* Select all color planes */\r
-}\r
-\f\r
-/*\r
- *************************************************************************\r
- *\r
- * PCX_PUT_VGA - Display VGA PCX Line\r
- *\r
- * Purpose: To copy a decoded PCX image scan line to a VGA display\r
- * adapter buffer.\r
- *\r
- * Setup: static void pcx_put_vga\r
- * (\r
- * PCX_WORKBLK *wbp,\r
- * unsigned char _far *linep,\r
- * int line_num\r
- * )\r
- *\r
- * Where: wbp is a PCX image file workblock pointer.\r
- * linep is a PCX scan line buffer pointer.\r
- * line_num is the scan line number.\r
- *\r
- *************************************************************************\r
- */\r
-\r
-static void pcx_put_vga\r
-(\r
- PCX_WORKBLK *wbp,\r
- unsigned char _far *linep,\r
- int line_num\r
-)\r
-{\r
- unsigned char _far *displayp; /* Display buffer pointer */\r
-\r
- /* Calculate buffer pointer */\r
-\r
- displayp = (unsigned char _far *) 0xa0000000L + line_num * 320;\r
-\r
- /* Copy data from the scan line buffer to the VGA display buffer */\r
-\r
- (void) _fmemcpy(displayp, linep, wbp->num_bytes);\r
-}\r
-\r