mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 22:02:49 -06:00
1379 lines
48 KiB
C++
1379 lines
48 KiB
C++
/*
|
|
*************************************************************************
|
|
*
|
|
* PCX_FILE.C - PCX_LIB Library Image File 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:
|
|
*
|
|
* _ffree - "free" for small model / far data
|
|
* _fmalloc - "malloc" for small model / far data
|
|
* _fmemcpy - "memcpy" for small model / far data
|
|
* int86 - execute 80x86 interrupt routine
|
|
* int86x - execute 80x86 interrupt routine (far data)
|
|
* 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <conio.h>
|
|
#include <malloc.h>
|
|
#include <dos.h>
|
|
#include <graph.h>
|
|
#include "pcx_int.h"
|
|
|
|
/* FORWARD REFERENCES */
|
|
|
|
static BOOL pcx_encode(int, int, FILE *);
|
|
static BOOL pcx_init_palette(PCX_PAL *, int);
|
|
static BOOL pcx_write_extpal(FILE *);
|
|
static BOOL pcx_write_line(unsigned char *, int, FILE *);
|
|
static BOOL pcx_write_init(PCX_WORKBLK *, int, int, int, int);
|
|
|
|
static void pcx_get_cga(PCX_WORKBLK *, unsigned char _far *, int);
|
|
static void pcx_get_ega(PCX_WORKBLK *, unsigned char _far *, int);
|
|
static void pcx_get_herc(PCX_WORKBLK *, unsigned char _far *, int);
|
|
static void pcx_get_vga(PCX_WORKBLK *, unsigned char _far *, int);
|
|
|
|
/* GLOBALS */
|
|
|
|
/* Default EGA palette register values */
|
|
|
|
static BYTE pcx_EGA_DefPal_1[16] = /* Modes 0x0d and 0x0e */
|
|
{
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
|
|
0x14, 0x15, 0x16, 0x17
|
|
};
|
|
|
|
static BYTE pcx_EGA_DefPal_2[16] = /* Mode 0x0f */
|
|
{
|
|
0x00, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
|
|
0x00, 0x18, 0x00, 0x00
|
|
};
|
|
|
|
static BYTE pcx_EGA_DefPal_3[16] = /* Mode 0x10 */
|
|
{
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a, 0x3b,
|
|
0x3c, 0x3d, 0x3e, 0x3f
|
|
};
|
|
|
|
/* PUBLIC FUNCTIONS */
|
|
|
|
/*
|
|
*************************************************************************
|
|
*
|
|
* PCX_WRITE - Write PCX File
|
|
*
|
|
* Purpose: To write a PCX-format image file from an image stored in
|
|
* a video buffer. The image is assumed to start in the
|
|
* upper left corner of the screen.
|
|
*
|
|
* Setup: BOOL pcx_write
|
|
* (
|
|
* char *fname,
|
|
* int vmode,
|
|
* int page,
|
|
* int width,
|
|
* int height,
|
|
* )
|
|
*
|
|
* 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
|
|
*
|
|
* width is the image width in pixels.
|
|
* height is the image height in pixels.
|
|
*
|
|
* Return: TRUE if successful; otherwise FALSE.
|
|
*
|
|
*************************************************************************
|
|
*/
|
|
|
|
BOOL pcx_write
|
|
(
|
|
char *fname,
|
|
int vmode,
|
|
int page,
|
|
int width,
|
|
int height
|
|
)
|
|
{
|
|
int bpline; /* Number of bytes per scan line */
|
|
int line_num; /* Scan line number */
|
|
unsigned char *linep; /* Image 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, TRUE)) == (PCX_WORKBLK *) NULL)
|
|
return (FALSE);
|
|
|
|
/* Initialize the workblock for writing */
|
|
|
|
if (pcx_write_init(wbp, vmode, page, width, height) == FALSE)
|
|
status = FALSE;
|
|
|
|
/* Calculate number of bytes per line (for all color planes) */
|
|
|
|
bpline = wbp->header.bppscan * wbp->header.nplanes;
|
|
|
|
/* Allocate a scan line buffer */
|
|
|
|
if (status == TRUE)
|
|
if ((linep = (unsigned char *) malloc(bpline)) == (unsigned char *)
|
|
NULL)
|
|
status = FALSE;
|
|
|
|
/* Write the file header to the file */
|
|
|
|
if (status == TRUE)
|
|
if (fwrite(&(wbp->header), sizeof(PCX_HDR), 1, wbp->fp) != 1)
|
|
status = FALSE;
|
|
|
|
/* Write the encoded image data to the file */
|
|
|
|
if (status == TRUE)
|
|
{
|
|
for (line_num = 0; line_num <= (int) wbp->header.ylr; line_num++)
|
|
{
|
|
/* Get the current video buffer scan line */
|
|
|
|
wbp->pcx_funcp(wbp, (unsigned char _far *) linep, line_num);
|
|
|
|
/* Encode the scan line and write it to the file */
|
|
|
|
if (pcx_write_line(linep, bpline, wbp->fp) == FALSE)
|
|
{
|
|
status = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (vmode == 0x13) /* Is a 256-color palette supported ? */
|
|
{
|
|
/* Write the extended palette to the file */
|
|
|
|
if (status == TRUE)
|
|
if (pcx_write_extpal(wbp->fp) == FALSE)
|
|
status = FALSE;
|
|
}
|
|
|
|
if (pcx_close(wbp) == FALSE) /* Close the PCX workblock */
|
|
status = FALSE;
|
|
|
|
free(linep); /* Free the scan line buffer */
|
|
|
|
/* Remove the PCX image file if an error occurred */
|
|
|
|
if (status == FALSE)
|
|
(void) remove(fname);
|
|
|
|
return (status);
|
|
}
|
|
|
|
/*
|
|
*************************************************************************
|
|
*
|
|
* PCX_INIT_DSA - Initialize Dynamic Save Area
|
|
*
|
|
* Purpose: To set up a Video Services Primary Pointer Table and an
|
|
* associated Dynamic Save Area where BIOS service "Set All
|
|
* Palette Registers" (function 0x02) can store the EGA color
|
|
* palette registers settings after it updates them.
|
|
*
|
|
* Setup: BOOL pcx_init_dsa
|
|
* (
|
|
* PCX_VSB **vsbpp
|
|
* )
|
|
*
|
|
* Where: vsbp is a pointer to where a pointer to an instantiated
|
|
* PCX_VSB structure is to be returned.
|
|
*
|
|
* Return: TRUE if successful; otherwise FALSE.
|
|
*
|
|
* Note: The EGA display adapter color palette registers are
|
|
* write-only. In order to save the current color palette
|
|
* with a PCX-format image file by calling "pcx_write", you
|
|
* must call this function BEFORE you display the image in
|
|
* the following MS-DOS video modes:
|
|
*
|
|
* 0x0d - 320 x 200 16-color EGA
|
|
* 0x0e - 640 x 200 16-color EGA
|
|
* 0x0f - 640 x 350 2-color EGA
|
|
* 0x10 - 640 x 350 16-color EGA
|
|
*
|
|
* You MUST call "pcx_free_dsa" upon completion of your
|
|
* program. See the function header of "pcx_init_palette"
|
|
* for more information.
|
|
*
|
|
*************************************************************************
|
|
*/
|
|
|
|
BOOL pcx_init_dsa
|
|
(
|
|
PCX_VSB **vsbpp
|
|
)
|
|
{
|
|
unsigned char _far *dsap; /* Dynamic Save Area pointer */
|
|
PCX_VSB *vsbp; /* Video services data save buffer ptr */
|
|
|
|
*vsbpp = (PCX_VSB *) NULL; /* Initialize returned pointer */
|
|
|
|
/* Allocate a Dynamic Save Area buffer */
|
|
|
|
if ((dsap = (unsigned char _far *) _fmalloc(sizeof(unsigned char) *
|
|
256)) == (unsigned char _far *) NULL)
|
|
return (FALSE);
|
|
|
|
/* Allocate a BIOS video services data save buffer */
|
|
|
|
if ((vsbp = (PCX_VSB *) malloc(sizeof(PCX_VSB))) == (PCX_VSB *) NULL)
|
|
{
|
|
_ffree(dsap); /* Free the Dynamic Save Area buffer */
|
|
return (FALSE);
|
|
}
|
|
|
|
/* Save the existing Primary Pointer Table pointer */
|
|
|
|
vsbp->prev_pptp = *((struct pcx_ppt _far * _far *) 0x004000a8L);
|
|
|
|
/* Copy the existing Primary Pointer Table into the buffer */
|
|
|
|
(void) _fmemcpy((struct pcx_ppt _far *) &(vsbp->pcx_ppt),
|
|
vsbp->prev_pptp, sizeof(struct pcx_ppt));
|
|
|
|
vsbp->pcx_ppt.dsap = dsap; /* Update the Dynamic Save Area ptr */
|
|
|
|
/* Update the Primary Pointer Table pointer in the Video Save Table */
|
|
|
|
*((struct pcx_ppt _far * _far *) 0x004000a8L) = &(vsbp->pcx_ppt);
|
|
|
|
*vsbpp = vsbp; /* Return Video Services data save buffer ptr */
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
/*
|
|
*************************************************************************
|
|
*
|
|
* PCX_FREE_DSA - Release Dynamic Save Area
|
|
*
|
|
* Purpose: To release memory allocated to the Video Services Primary
|
|
* Pointer Table and associated Dynamic Save Area and reset
|
|
* the pointer in the Video Save Table.
|
|
*
|
|
* Setup: void pcx_free_dsa
|
|
* (
|
|
* PCX_VSB *vsbp
|
|
* )
|
|
*
|
|
* Where: vsbp is a pointer to a PCX_VSB structure that was
|
|
* previously allocated and initialized by "pcx_init_dsa".
|
|
*
|
|
* Note: You MUST call this function on completion of your program
|
|
* if you previously called "pcx_init_dsa". Failure to do so
|
|
* will leave the system in an unstable state. See the
|
|
* function header of "pcx_init_palette" for more
|
|
* information.
|
|
*
|
|
*************************************************************************
|
|
*/
|
|
|
|
void pcx_free_dsa
|
|
(
|
|
PCX_VSB *vsbp
|
|
)
|
|
{
|
|
/* Restore the previous primary pointer table pointer */
|
|
|
|
*((struct pcx_ppt _far * _far *) 0x004000a8L) = vsbp->prev_pptp;
|
|
|
|
_ffree(vsbp->pcx_ppt.dsap); /* Free the Dynamic Save Area */
|
|
|
|
free(vsbp); /* Free the Video Services data save buffer */
|
|
}
|
|
|
|
/* PRIVATE FUNCTIONS */
|
|
|
|
/*
|
|
*************************************************************************
|
|
*
|
|
* PCX_WRITE_INIT - Initialize PCX Workblock For Writing
|
|
*
|
|
* Purpose: To initialize a PCX image file workblock for writing.
|
|
*
|
|
* Setup: static BOOL pcx_write_init
|
|
* (
|
|
* PCX_WORKBLK *wbp,
|
|
* int vmode,
|
|
* int page,
|
|
* int width,
|
|
* int height
|
|
* )
|
|
*
|
|
* Where: wbp is a PCX workblock pointer.
|
|
* 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
|
|
* Ox07 - 720 x 348 Hercules monochrome
|
|
* 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
|
|
*
|
|
* width is the image width in pixels.
|
|
* height is the image height in pixels.
|
|
*
|
|
* Return: TRUE if successful; otherwise FALSE.
|
|
*
|
|
*************************************************************************
|
|
*/
|
|
|
|
static BOOL pcx_write_init
|
|
(
|
|
PCX_WORKBLK *wbp,
|
|
int vmode,
|
|
int page,
|
|
int width,
|
|
int height
|
|
)
|
|
{
|
|
int max_width; /* Maximum image width */
|
|
int max_height; /* Maximum image height */
|
|
int shift; /* Mask shift value */
|
|
BOOL status = TRUE; /* Return status */
|
|
PCX_HDR *hdrp; /* File header buffer pointer */
|
|
|
|
/* Initialize the display page address offset */
|
|
|
|
wbp->page_offset = (unsigned long) 0L;
|
|
|
|
hdrp = &(wbp->header); /* Initialize the file header pointer */
|
|
|
|
/* Initialize the header constants */
|
|
|
|
hdrp->pcx_id = 0x0a; /* PCX format identifier */
|
|
hdrp->version = 5; /* Version number */
|
|
hdrp->encoding = 1; /* Encoding format (run-length) */
|
|
hdrp->xul = 0; /* Upper left x-position */
|
|
hdrp->yul = 0; /* Upper left y-position */
|
|
hdrp->reserved = 0; /* (Used to be video mode) */
|
|
hdrp->palette_type = 1; /* Color or b&w palette type */
|
|
|
|
memset(hdrp->filler, 0, sizeof(hdrp->filler)); /* Padding */
|
|
|
|
/* Initialize the video mode-dependent parameters */
|
|
|
|
switch (vmode)
|
|
{
|
|
case PCX_HERC: /* 720 x 348 Hercules monochrome */
|
|
|
|
max_width = min(width, 720); /* Maximum image width */
|
|
max_height = min(height, 348); /* Maximum image height */
|
|
|
|
hdrp->bppixel = 1; /* Bits per pixel */
|
|
hdrp->horz_res = 720; /* Horizontal resolution */
|
|
hdrp->vert_res = 348; /* Vertical resolution */
|
|
hdrp->nplanes = 1; /* Number of color planes */
|
|
|
|
/* Maximum two pages supported */
|
|
|
|
wbp->page_offset = 0x08000000L * (unsigned long) page;
|
|
|
|
/* Calculate number of bytes to copy */
|
|
|
|
wbp->num_bytes = (max_width + 7) >> 3;
|
|
|
|
shift = (max_width & 7); /* Calculate mask shift value */
|
|
|
|
wbp->pcx_funcp = pcx_get_herc; /* Set display capture fcn ptr */
|
|
|
|
break;
|
|
|
|
case 0x04: /* 320 x 200 4-color CGA */
|
|
case 0x05: /* 320 x 200 4-color CGA (color burst off) */
|
|
|
|
max_width = min(width, 320); /* Maximum image width */
|
|
max_height = min(height, 200); /* Maximum image height */
|
|
|
|
hdrp->bppixel = 2; /* Bits per pixel */
|
|
hdrp->horz_res = 320; /* Horizontal resolution */
|
|
hdrp->vert_res = 200; /* Vertical resolution */
|
|
hdrp->nplanes = 1; /* Number of color planes */
|
|
|
|
/* Calculate number of bytes to copy */
|
|
|
|
wbp->num_bytes = (max_width + 3) >> 2;
|
|
|
|
shift = (max_width & 3) << 1; /* Calculate mask shift value */
|
|
|
|
wbp->pcx_funcp = pcx_get_cga; /* Set display capture fcn ptr */
|
|
|
|
break;
|
|
|
|
case 0x06: /* 640 x 200 2-color CGA */
|
|
|
|
max_width = min(width, 640); /* Maximum image width */
|
|
max_height = min(height, 200); /* Maximum image height */
|
|
|
|
hdrp->bppixel = 1; /* Bits per pixel */
|
|
hdrp->horz_res = 640; /* Horizontal resolution */
|
|
hdrp->vert_res = 200; /* Vertical resolution */
|
|
hdrp->nplanes = 1; /* Number of color planes */
|
|
|
|
/* Calculate number of bytes to copy */
|
|
|
|
wbp->num_bytes = (max_width + 7) >> 3;
|
|
|
|
shift = (max_width & 7); /* Calculate mask shift value */
|
|
|
|
wbp->pcx_funcp = pcx_get_cga; /* Set display capture fcn ptr */
|
|
|
|
break;
|
|
|
|
case 0x0d: /* 320 x 200 16-color EGA/VGA */
|
|
|
|
max_width = min(width, 320); /* Maximum image width */
|
|
max_height = min(height, 200); /* Maximum image height */
|
|
|
|
hdrp->bppixel = 1; /* Bits per pixel */
|
|
hdrp->horz_res = 320; /* Horizontal resolution */
|
|
hdrp->vert_res = 200; /* Vertical resolution */
|
|
hdrp->nplanes = 4; /* Number of color planes */
|
|
|
|
/* Maximum eight display pages supported */
|
|
|
|
wbp->page_offset = 0x02000000L * (unsigned long) page;
|
|
|
|
/* Calculate number of bytes to copy */
|
|
|
|
wbp->num_bytes = (max_width + 7) >> 3;
|
|
|
|
shift = (max_width & 7); /* Calculate mask shift value */
|
|
|
|
wbp->pcx_funcp = pcx_get_ega; /* Set display capture fcn ptr */
|
|
|
|
break;
|
|
|
|
case 0x0e: /* 640 x 200 16-color EGA/VGA */
|
|
|
|
max_width = min(width, 640); /* Maximum image width */
|
|
max_height = min(height, 200); /* Maximum image height */
|
|
|
|
hdrp->bppixel = 1; /* Bits per pixel */
|
|
hdrp->horz_res = 640; /* Horizontal resolution */
|
|
hdrp->vert_res = 200; /* Vertical resolution */
|
|
hdrp->nplanes = 4; /* Number of color planes */
|
|
|
|
/* Maximum four display pages supported */
|
|
|
|
wbp->page_offset = 0x04000000L * (unsigned long) page;
|
|
|
|
/* Calculate number of bytes to copy */
|
|
|
|
wbp->num_bytes = (max_width + 7) >> 3;
|
|
|
|
shift = (max_width & 7); /* Calculate mask shift value */
|
|
|
|
wbp->pcx_funcp = pcx_get_ega; /* Set display capture fcn ptr */
|
|
|
|
break;
|
|
|
|
case 0x0f: /* 640 x 350 2-color EGA/VGA */
|
|
|
|
max_width = min(width, 640); /* Maximum image width */
|
|
max_height = min(height, 350); /* Maximum image height */
|
|
|
|
hdrp->bppixel = 1; /* Bits per pixel */
|
|
hdrp->horz_res = 640; /* Horizontal resolution */
|
|
hdrp->vert_res = 350; /* Vertical resolution */
|
|
hdrp->nplanes = 2; /* Number of color planes */
|
|
|
|
/* Maximum two display pages supported */
|
|
|
|
wbp->page_offset = 0x08000000L * (unsigned long) page;
|
|
|
|
/* Calculate number of bytes to copy */
|
|
|
|
wbp->num_bytes = (max_width + 7) >> 3;
|
|
|
|
shift = (max_width & 7); /* Calculate mask shift value */
|
|
|
|
wbp->pcx_funcp = pcx_get_ega; /* Set display capture fcn ptr */
|
|
|
|
break;
|
|
|
|
case 0x10: /* 640 x 350 16-color EGA/VGA */
|
|
|
|
max_width = min(width, 640); /* Maximum image width */
|
|
max_height = min(height, 350); /* Maximum image height */
|
|
|
|
hdrp->bppixel = 1; /* Bits per pixel */
|
|
hdrp->horz_res = 640; /* Horizontal resolution */
|
|
hdrp->vert_res = 350; /* Vertical resolution */
|
|
hdrp->nplanes = 4; /* Number of color planes */
|
|
|
|
/* Maximum two display pages supported */
|
|
|
|
wbp->page_offset = 0x08000000L * (unsigned long) page;
|
|
|
|
/* Calculate number of bytes to copy */
|
|
|
|
wbp->num_bytes = (max_width + 7) >> 3;
|
|
|
|
shift = (max_width & 7); /* Calculate mask shift value */
|
|
|
|
wbp->pcx_funcp = pcx_get_ega; /* Set display capture fcn ptr */
|
|
|
|
break;
|
|
|
|
case 0x11: /* 640 x 480 2-color VGA */
|
|
|
|
max_width = min(width, 640); /* Maximum image width */
|
|
max_height = min(height, 480); /* Maximum image height */
|
|
|
|
hdrp->bppixel = 1; /* Bits per pixel */
|
|
hdrp->horz_res = 640; /* Horizontal resolution */
|
|
hdrp->vert_res = 480; /* Vertical resolution */
|
|
hdrp->nplanes = 1; /* Number of color planes */
|
|
|
|
/* Calculate number of bytes to copy */
|
|
|
|
wbp->num_bytes = (max_width + 7) >> 3;
|
|
|
|
shift = (max_width & 7); /* Calculate mask shift value */
|
|
|
|
wbp->pcx_funcp = pcx_get_ega; /* Set display capture fcn ptr */
|
|
|
|
break;
|
|
|
|
case 0x12: /* 640 x 480 16-color VGA */
|
|
|
|
max_width = min(width, 640); /* Maximum image width */
|
|
max_height = min(height, 480); /* Maximum image height */
|
|
|
|
hdrp->bppixel = 1; /* Bits per pixel */
|
|
hdrp->horz_res = 640; /* Horizontal resolution */
|
|
hdrp->vert_res = 480; /* Vertical resolution */
|
|
hdrp->nplanes = 4; /* Number of color planes */
|
|
|
|
/* Calculate number of bytes to copy */
|
|
|
|
wbp->num_bytes = (max_width + 7) >> 3;
|
|
|
|
shift = (max_width & 7); /* Calculate mask shift value */
|
|
|
|
wbp->pcx_funcp = pcx_get_ega; /* Set display capture fcn ptr */
|
|
|
|
break;
|
|
|
|
case 0x13: /* 320 x 200 256-color VGA */
|
|
|
|
max_width = min(width, 320); /* Maximum image width */
|
|
max_height = min(height, 200); /* Maximum image height */
|
|
|
|
hdrp->bppixel = 8; /* Bits per pixel */
|
|
hdrp->horz_res = 320; /* Horizontal resolution */
|
|
hdrp->vert_res = 200; /* Vertical resolution */
|
|
hdrp->nplanes = 1; /* Number of color planes */
|
|
|
|
/* Calculate number of bytes to copy */
|
|
|
|
wbp->num_bytes = max_width;
|
|
|
|
shift = 0; /* Dummy parameter */
|
|
|
|
wbp->pcx_funcp = pcx_get_vga; /* Set display capture fcn ptr */
|
|
|
|
break;
|
|
|
|
default: /* Other modes not supported */
|
|
|
|
status = FALSE;
|
|
|
|
break;
|
|
}
|
|
|
|
/* Initialize common video mode-dependent parameters */
|
|
|
|
hdrp->xlr = max_width - 1; /* Lower right x-position */
|
|
hdrp->ylr = max_height - 1; /* Lower right y-position */
|
|
hdrp->scrn_width = hdrp->horz_res; /* Screen width */
|
|
hdrp->scrn_height = hdrp->vert_res; /* Screen height */
|
|
|
|
/* Calculate mask for "white" data */
|
|
|
|
if (shift != 0)
|
|
wbp->mask = 0xff >> shift;
|
|
else
|
|
wbp->mask = 0x00;
|
|
|
|
/* Initialize the file header palette */
|
|
|
|
status = pcx_init_palette(hdrp->palette, vmode);
|
|
|
|
/* Calculate number of bytes per color plane scan line (must be an */
|
|
/* even number of bytes) */
|
|
|
|
hdrp->bppscan = 2 * (((((hdrp->xlr * hdrp->bppixel) + 7) / 8) + 1) / 2);
|
|
|
|
return (status);
|
|
}
|
|
|
|
/*
|
|
*************************************************************************
|
|
*
|
|
* PCX_INIT_PALETTE - Initialize File Header Palette
|
|
*
|
|
* Purpose: To initialize the file header 16-color palette.
|
|
*
|
|
* Setup: static BOOL pcx_init_palette
|
|
* (
|
|
* PCX_PAL *palettep,
|
|
* int vmode
|
|
* )
|
|
*
|
|
* Where: palettep is a pointer to the PCX file header buffer
|
|
* "palette" member.
|
|
* 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
|
|
* Ox07 - 720 x 348 Hercules monochrome
|
|
* 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.
|
|
*
|
|
* Note: The CGA color palette is not supported.
|
|
*
|
|
* If a VGA display adapter is present, the color palette
|
|
* registers can be read directly from the adapter using the
|
|
* BIOS routine "Read All Palette Registers" (function 0x09).
|
|
*
|
|
* Unfortunately, the EGA display adapter color palette
|
|
* registers are write-only. This means that the current
|
|
* color palette for EGA displays cannot in general be read.
|
|
*
|
|
* The BIOS routine "Set All Palette Registers" (function
|
|
* 0x02) will write the current palette register values to a
|
|
* buffer called the Dynamic Save Area. The EGA color
|
|
* palette can be read from the first 16 bytes of this 256-
|
|
* byte RAM block.
|
|
*
|
|
* The Dynamic Save Area is not statically allocated; it must
|
|
* be supplied by the user. The BIOS video services data in
|
|
* segment 0x40 includes a pointer at address 0040:00a8 that
|
|
* references the Video Services Primary Pointer Table in the
|
|
* EGA/VGA BIOS. This table contains seven pointers, the
|
|
* second of which is used by the "Set All Palette Registers"
|
|
* routine to reference the Dynamic Save Area. Since the
|
|
* Dynamic Save Area does not exist at system initialization,
|
|
* the value of this pointer is 0000:0000 (in which case the
|
|
* the updated palette register values are not saved to RAM
|
|
* when they are updated).
|
|
*
|
|
* To utilize the EGA palette register save feature, the
|
|
* user must perform the following:
|
|
*
|
|
* 1. Save a copy of the pointer at address 0040:00a8.
|
|
* 2. Allocate a buffer for a new Primary Pointer Table.
|
|
* 3. Copy the existing Primary Pointer Table to the
|
|
* allocated buffer.
|
|
* 4. Allocate a 256-byte buffer for a Dynamic Save Area.
|
|
* 5. Initialize the second pointer of the Primary Pointer
|
|
* Table to point to the Dynamic Save Area buffer.
|
|
*
|
|
* Before the program finishes, the user must also restore
|
|
* the saved Primary Pointer Table pointer to address
|
|
* 0040:00a8. Failure to do so will mean that subsequent
|
|
* calls by other programs to the "Set All Palette
|
|
* Registers" routine will result in the color palette
|
|
* registers values being written to unallocated memory (or
|
|
* memory that has been allocated for another purpose).
|
|
*
|
|
* The function "pcx_init_dsa" performs the five steps
|
|
* outlined above, while the function "pcx_free_dsa" restores
|
|
* the saved pointer on completion of your program.
|
|
*
|
|
* If the Dynamic Save Area pointer is 0000:0000 (the default
|
|
* value at system initialization), the BIOS default color
|
|
* palette settings for the appropriate mode are stored in
|
|
* the file header color palette.
|
|
*
|
|
*************************************************************************
|
|
*/
|
|
|
|
static BOOL pcx_init_palette
|
|
(
|
|
PCX_PAL *palettep,
|
|
int vmode
|
|
)
|
|
{
|
|
int i; /* Scratch counter */
|
|
int val; /* Current palette register value */
|
|
int red; /* Temporary value */
|
|
int green; /* Temporary value */
|
|
int blue; /* Temporary value */
|
|
unsigned char *ega_palp; /* EGA/VGA palette buffer pointer */
|
|
unsigned char _far *dsap; /* Dynamic Save Area pointer */
|
|
union REGS regs; /* 80x86 register values */
|
|
struct SREGS sregs; /* 80x86 segment register values */
|
|
|
|
if (vmode < 0x0d || vmode > 0x12)
|
|
{
|
|
/* Clear the file header palette */
|
|
|
|
memset(palettep, 0, sizeof(PCX_PAL) * PCX_PAL_SIZE);
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
/* Allocate a 16-color (plus border color) EGA/VGA palette buffer */
|
|
|
|
if ((ega_palp = (unsigned char *) calloc(sizeof(unsigned char),
|
|
(PCX_PAL_SIZE + 1))) == (unsigned char *) NULL)
|
|
return (FALSE);
|
|
|
|
if (pcx_isvga() == TRUE) /* Check for VGA display adapter */
|
|
{
|
|
/* Read the EGA/VGA palette registers */
|
|
|
|
regs.h.ah = 0x10; /* Select "Read All Palette Registers" routine */
|
|
regs.h.al = 0x09;
|
|
|
|
/* Get the EGA/VGA palette 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 */
|
|
}
|
|
else
|
|
{
|
|
/* Check for a Dynamic Save Area buffer */
|
|
|
|
dsap = *(*((unsigned char _far * _far * _far *) 0x004000a8L) + 1);
|
|
|
|
if (dsap != (unsigned char _far *) NULL)
|
|
{
|
|
/* Copy the current palette into the local EGA/VGA palette buffer */
|
|
|
|
(void) _fmemcpy((unsigned char _far *) ega_palp, dsap,
|
|
PCX_PAL_SIZE);
|
|
}
|
|
else
|
|
{
|
|
/* Copy the appropriate default palette settings */
|
|
|
|
switch (vmode)
|
|
{
|
|
case 0x0d: /* 320 x 200 16-color EGA */
|
|
case 0x0e: /* 640 x 200 16-color EGA */
|
|
|
|
memcpy(ega_palp, pcx_EGA_DefPal_1, PCX_PAL_SIZE);
|
|
|
|
break;
|
|
|
|
case 0x0f: /* 640 x 350 2-color EGA */
|
|
|
|
memcpy(ega_palp, pcx_EGA_DefPal_2, PCX_PAL_SIZE);
|
|
|
|
break;
|
|
|
|
case 0x10: /* 640 x 350 16-color EGA */
|
|
|
|
memcpy(ega_palp, pcx_EGA_DefPal_3, PCX_PAL_SIZE);
|
|
|
|
break;
|
|
|
|
default: /* (Should never reach here) */
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Map the EGA/VGA palette to the PCX file header palette */
|
|
|
|
for (i = 0; i < PCX_PAL_SIZE; i++)
|
|
{
|
|
val = (int) ega_palp[i]; /* Get current color palette value */
|
|
|
|
/* Extract color values */
|
|
|
|
red = ((val & 0x20) >> 5) | ((val & 0x04) >> 1);
|
|
green = ((val & 0x10) >> 4) | (val & 0x02);
|
|
blue = ((val & 0x08) >> 3) | ((val & 0x01) << 1);
|
|
|
|
/* Map each color to a 6-bit value. Only the top two bits are */
|
|
/* significant for EGA displays. The lower four bits (which */
|
|
/* repeat the top two bits) are significant when the image is */
|
|
/* presented on a VGA display emulating an EGA display. */
|
|
|
|
palettep[i].red = (BYTE) ((red << 6) | (red << 4) | (red << 2));
|
|
palettep[i].green = (BYTE) ((green << 6) | (green << 4) | (green <<
|
|
2));
|
|
palettep[i].blue = (BYTE) ((blue << 6) | (blue << 4) | (blue << 2));
|
|
}
|
|
}
|
|
|
|
free(ega_palp); /* Free the EGA/VGA palette buffer */
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
/*
|
|
*************************************************************************
|
|
*
|
|
* PCX_WRITE_LINE - Write PCX Line
|
|
*
|
|
* Purpose: To write an image scan line to a PCX-format image file.
|
|
*
|
|
* Setup: static BOOL pcx_write_line
|
|
* (
|
|
* unsigned char *linep,
|
|
* int buflen,
|
|
* FILE *fp
|
|
* )
|
|
*
|
|
* Where: linep is a PCX scan line buffer pointer.
|
|
* buflen is the length of the image scan line buffer in
|
|
* bytes.
|
|
* fp is a file pointer.
|
|
*
|
|
* Return: TRUE if successful; otherwise FALSE.
|
|
*
|
|
* Note: The PCX scan line buffer is assumed to contain the color
|
|
* plane scan lines in sequence, with padding for an even
|
|
* number of bytes and trailing "white" data for each line as
|
|
* appropriate.
|
|
*
|
|
*************************************************************************
|
|
*/
|
|
|
|
static BOOL pcx_write_line
|
|
(
|
|
unsigned char *linep,
|
|
int buflen,
|
|
FILE *fp
|
|
)
|
|
{
|
|
int curr_data; /* Current data byte */
|
|
int prev_data; /* Previous data byte */
|
|
int data_count; /* Data repeat count */
|
|
int line_count; /* Scan line byte count */
|
|
|
|
prev_data = *linep++; /* Initialize the previous data byte */
|
|
data_count = 1;
|
|
line_count = 1;
|
|
|
|
while (line_count < buflen) /* Encode scan line */
|
|
{
|
|
curr_data = *linep++; /* Get the current data byte */
|
|
line_count++; /* Increment the scan line counter */
|
|
|
|
if (curr_data == prev_data) /* Repeating data bytes ? */
|
|
{
|
|
data_count++; /* Increment the data repeat count */
|
|
|
|
/* Check for maximum allowable repeat count */
|
|
|
|
if (data_count == PCX_COMP_MASK)
|
|
{
|
|
/* Encode the data */
|
|
|
|
if (pcx_encode(prev_data, data_count, fp) == FALSE)
|
|
return (FALSE);
|
|
|
|
data_count = 0; /* Reset the data repeat count */
|
|
}
|
|
}
|
|
else /* End of repeating data bytes */
|
|
{
|
|
if (data_count > 0)
|
|
{
|
|
/* Encode the data */
|
|
|
|
if (pcx_encode(prev_data, data_count, fp) == FALSE)
|
|
return (FALSE);
|
|
}
|
|
|
|
prev_data = curr_data; /* Current data byte now previous */
|
|
data_count = 1;
|
|
}
|
|
}
|
|
|
|
if (data_count > 0) /* Any remaining data ? */
|
|
{
|
|
/* Encode the data */
|
|
|
|
if (pcx_encode(prev_data, data_count, fp) == FALSE)
|
|
return (FALSE);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
/*
|
|
*************************************************************************
|
|
*
|
|
* PCX_ENCODE - Encode Byte Pair
|
|
*
|
|
* Purpose: To write an encoded byte pair (or a single unencoded
|
|
* byte) to a PCX-format image file.
|
|
*
|
|
* Setup: static BOOL pcx_encode
|
|
* (
|
|
* int data,
|
|
* int count,
|
|
* FILE *fp
|
|
* )
|
|
*
|
|
* Where: data is the data byte to be encoded (if necessary).
|
|
* count is the number of times the data byte is repeated in
|
|
* the image data.
|
|
* fp is a pointer to the PCX-format file the encoded byte
|
|
* pair or single byte is to be written to.
|
|
*
|
|
* Return: TRUE if successful; otherwise FALSE.
|
|
*
|
|
*************************************************************************
|
|
*/
|
|
|
|
static BOOL pcx_encode
|
|
(
|
|
int data,
|
|
int count,
|
|
FILE *fp
|
|
)
|
|
{
|
|
if (((data & PCX_COMP_FLAG) == PCX_COMP_FLAG) || count > 1)
|
|
{
|
|
/* Write the count byte */
|
|
|
|
if (putc(PCX_COMP_FLAG | count, fp) == EOF)
|
|
return (FALSE);
|
|
}
|
|
|
|
/* Write the data byte */
|
|
|
|
if (putc(data, fp) == EOF)
|
|
return (FALSE);
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
/*
|
|
*************************************************************************
|
|
*
|
|
* PCX_WRITE_EXTPAL - Write Extended Palette
|
|
*
|
|
* Purpose: To read the current 256-color VGA palette and write an
|
|
* equivalent extended PCX palette to a PCX-format image
|
|
* file.
|
|
*
|
|
* Setup: static BOOL pcx_write_extpal
|
|
* (
|
|
* FILE *fp
|
|
* )
|
|
*
|
|
* Where: fp is a file pointer.
|
|
*
|
|
* Return: TRUE if successful; otherwise FALSE.
|
|
*
|
|
*************************************************************************
|
|
*/
|
|
|
|
static BOOL pcx_write_extpal
|
|
(
|
|
FILE *fp
|
|
)
|
|
{
|
|
int i; /* Scratch counter */
|
|
BOOL status = TRUE; /* Return status */
|
|
PCX_PAL *palettep; /* Extended PCX palette buffer pointer */
|
|
unsigned char *vga_palp; /* 256-color VGA palette buffer pointer */
|
|
union REGS regs; /* 80x86 register values */
|
|
struct SREGS sregs; /* 80x86 segment register values */
|
|
|
|
/* Allocate an extended PCX palette buffer */
|
|
|
|
if ((palettep = (PCX_PAL *) calloc(sizeof(PCX_PAL), PCX_EPAL_SIZE)) ==
|
|
(PCX_PAL *) NULL)
|
|
return (FALSE);
|
|
|
|
/* Allocate a 256-color VGA palette buffer */
|
|
|
|
if ((vga_palp = (unsigned char *) calloc(sizeof(unsigned char), 768))
|
|
== (unsigned char *) NULL)
|
|
{
|
|
free(palettep); /* Free the extended PCX palette buffer */
|
|
return (FALSE);
|
|
}
|
|
|
|
/* Read the current VGA palette (DAC registers) */
|
|
|
|
regs.h.ah = 0x10; /* Select "Read DAC Registers" BIOS routine */
|
|
regs.h.al = 0x17;
|
|
regs.x.bx = 0; /* Read all 256 DAC registers */
|
|
regs.x.cx = 256;
|
|
|
|
/* Get the VGA palette buffer offset value */
|
|
|
|
regs.x.dx = (unsigned int) vga_palp;
|
|
|
|
segread(&sregs); /* Get the current DS segment register value */
|
|
|
|
sregs.es = sregs.ds;
|
|
|
|
int86x(0x10, ®s, ®s, &sregs); /* Call BIOS video service */
|
|
|
|
/* Map the VGA palette to an extended PCX palette */
|
|
|
|
for (i = 0; i < PCX_EPAL_SIZE; i++)
|
|
{
|
|
palettep[i].red = (BYTE) (vga_palp[i * 3] << 2);
|
|
palettep[i].green = (BYTE) (vga_palp[i * 3 + 1] << 2);
|
|
palettep[i].blue = (BYTE) (vga_palp[i * 3 + 2] << 2);
|
|
}
|
|
|
|
/* Write the extended PCX palette indicator byte to the file */
|
|
|
|
if (status == TRUE)
|
|
if (fputc(PCX_EPAL_FLAG, fp) == EOF)
|
|
status = FALSE;
|
|
|
|
/* Write the extended PCX palette to the file */
|
|
|
|
if (status == TRUE)
|
|
if (fwrite(palettep, sizeof(PCX_PAL), PCX_EPAL_SIZE, fp) !=
|
|
PCX_EPAL_SIZE)
|
|
status = FALSE;
|
|
|
|
free(palettep); /* Free the extended PCX palette buffer */
|
|
|
|
free(vga_palp); /* Free the VGA palette buffer */
|
|
|
|
return (status);
|
|
}
|
|
|
|
/*
|
|
*************************************************************************
|
|
*
|
|
* PCX_GET_HERC - Get Hercules Scan Line
|
|
*
|
|
* Purpose: To read a Hercules monochrome graphics display adapter
|
|
* scan line into a buffer.
|
|
*
|
|
* Setup: static void pcx_get_herc
|
|
* (
|
|
* PCX_WORKBLK *wbp,
|
|
* unsigned char _far *linep,
|
|
* int line_num
|
|
* )
|
|
*
|
|
* Where: wbp is a PCX workblock pointer.
|
|
* linep is a pointer to where the scan line is to be
|
|
* returned.
|
|
* line_num is the scan line number.
|
|
*
|
|
*************************************************************************
|
|
*/
|
|
|
|
static void pcx_get_herc
|
|
(
|
|
PCX_WORKBLK *wbp,
|
|
unsigned char _far *linep,
|
|
int line_num
|
|
)
|
|
{
|
|
unsigned char _far *displayp; /* Display buffer pointer */
|
|
|
|
/* 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 Hercules display buffer to the scan line buffer */
|
|
|
|
(void) _fmemcpy(linep, displayp, wbp->num_bytes);
|
|
|
|
/* Mask off unseen pixels */
|
|
|
|
linep[wbp->num_bytes - 1] |= wbp->mask;
|
|
|
|
/* Pad scan line with "white" data byte (if necessary) */
|
|
|
|
if (wbp->num_bytes & 1)
|
|
linep[wbp->num_bytes] = 0xff;
|
|
}
|
|
|
|
/*
|
|
*************************************************************************
|
|
*
|
|
* PCX_GET_CGA - Get CGA Scan Line
|
|
*
|
|
* Purpose: To read a CGA display adapter scan line into a buffer.
|
|
*
|
|
* Setup: static void pcx_get_cga
|
|
* (
|
|
* PCX_WORKBLK *wbp,
|
|
* unsigned char _far *linep,
|
|
* int line_num
|
|
* )
|
|
*
|
|
* Where: wbp is a PCX workblock pointer.
|
|
* linep is a pointer to where the scan line is to be
|
|
* returned.
|
|
* line_num is the scan line number.
|
|
*
|
|
*************************************************************************
|
|
*/
|
|
|
|
static void pcx_get_cga
|
|
(
|
|
PCX_WORKBLK *wbp,
|
|
unsigned char _far *linep,
|
|
int line_num
|
|
)
|
|
{
|
|
unsigned char _far *displayp; /* Display buffer pointer */
|
|
|
|
/* Calculate CGA display buffer pointer */
|
|
|
|
displayp = (unsigned char _far *) 0xb8000000L + ((line_num >> 1) * 80)
|
|
+ 0x2000 * (line_num & 1);
|
|
|
|
/* Copy data from the CGA display buffer to the scan line buffer */
|
|
|
|
(void) _fmemcpy(linep, displayp, wbp->num_bytes);
|
|
|
|
/* Mask off unseen pixels */
|
|
|
|
linep[wbp->num_bytes - 1] |= wbp->mask;
|
|
|
|
/* Pad scan line with "white" data byte (if necessary) */
|
|
|
|
if (wbp->num_bytes & 1)
|
|
linep[wbp->num_bytes] = 0xff;
|
|
}
|
|
|
|
/*
|
|
*************************************************************************
|
|
*
|
|
* PCX_GET_EGA - Get EGA/VGA Scan Line
|
|
*
|
|
* Purpose: To read an EGA/VGA display adapter scan line into a
|
|
* buffer.
|
|
*
|
|
* Setup: static void pcx_get_ega
|
|
* (
|
|
* PCX_WORKBLK *wbp,
|
|
* unsigned char _far *linep,
|
|
* int line_num
|
|
* )
|
|
*
|
|
* Where: wbp is a PCX workblock pointer.
|
|
* linep is a pointer to where the scan line is to be
|
|
* returned.
|
|
* line_num is the scan line number.
|
|
*
|
|
*************************************************************************
|
|
*/
|
|
|
|
static void pcx_get_ega
|
|
(
|
|
PCX_WORKBLK *wbp,
|
|
unsigned char _far *linep,
|
|
int line_num
|
|
)
|
|
{
|
|
int plane_num; /* EGA/VGA color plane number */
|
|
unsigned char _far *displayp; /* Display buffer pointer */
|
|
|
|
/* Calculate buffer pointer */
|
|
|
|
displayp = (unsigned char _far *) (0xa0000000L + wbp->page_offset) +
|
|
line_num * 80;
|
|
|
|
/* Copy PCX scan line data from each color plane */
|
|
|
|
for (plane_num = 0; plane_num < (int) wbp->header.nplanes; plane_num++)
|
|
{
|
|
/* Select the current color plane in EGA/VGA Read Mode 0 */
|
|
|
|
outpw(0x03ce, (plane_num << 8) | 0x04);
|
|
|
|
/* Copy data from the EGA/VGA display to the scan line buffer */
|
|
|
|
(void) _fmemcpy(linep, displayp, wbp->num_bytes);
|
|
|
|
/* Mask off unseen pixels */
|
|
|
|
linep[wbp->num_bytes - 1] |= wbp->mask;
|
|
|
|
/* Pad plane scan line with "white" data byte (if necessary) */
|
|
|
|
if (wbp->num_bytes & 1)
|
|
linep[wbp->num_bytes] = 0xff;
|
|
|
|
linep += wbp->header.bppscan; /* Increment plane offset */
|
|
}
|
|
|
|
/* Select EGA/VGA Write Mode 0 with all color planes enabled */
|
|
|
|
outpw(0x03c4, 0x0f02);
|
|
}
|
|
|
|
/*
|
|
*************************************************************************
|
|
*
|
|
* PCX_GET_VGA - Get VGA Scan Line
|
|
*
|
|
* Purpose: To read a VGA display adapter scan line into a buffer.
|
|
*
|
|
* Setup: static void pcx_get_vga
|
|
* (
|
|
* PCX_WORKBLK *wbp,
|
|
* unsigned char _far *linep,
|
|
* int line_num
|
|
* )
|
|
*
|
|
* Where: wbp is a PCX workblock pointer.
|
|
* linep is a pointer to where the scan line is to be
|
|
* returned.
|
|
* line_num is the scan line number.
|
|
*
|
|
*************************************************************************
|
|
*/
|
|
|
|
static void pcx_get_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 VGA display buffer to the scan line buffer */
|
|
|
|
(void) _fmemcpy(linep, displayp, wbp->num_bytes);
|
|
|
|
/* Pad scan line with "white" data byte (if necessary) */
|
|
|
|
if (wbp->num_bytes & 1)
|
|
linep[wbp->num_bytes] = 0xff;
|
|
}
|
|
|