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