home *** CD-ROM | disk | FTP | other *** search
- /* PCX.c - Graphic Routines that operate on PCX pictures
- */
-
-
- #include <stdio.h>
- #include "lib.h"
- #include "pcx.h"
-
-
- int pcx_init();
- int pcx_clear();
- int pcx_set_point();
- int pcx_clr_point();
- int pcx_xor_point();
- int pcx_write_row();
- int pcx_select_plane();
- int pcx_set_palette();
- int pcx_mode();
- int movmem();
- int pokeb();
- int peekb();
- int pcx_get_point();
-
- static int (*pcx_func[])() = {
- pcx_init, pcx_clear, pcx_set_point, pcx_clr_point,
- pcx_xor_point, pcx_get_point, pcx_write_row, pcx_select_plane,
- pcx_set_palette,pcx_mode, movmem, peekb, pokeb };
-
- PCXPIC *pcx_cpic; /* current picture */
- static int cplane; /* current plane */
- int pcx_md; /* 1 if CGA-type picture, 0 for HERC/EGA */
-
-
- int pcx_init()
- {
- movmem( pcx_func, vgr_func, sizeof(vgr_func) );
-
- VGR_NBPL = VGR_HRES = VGR_VRES = VGR_NCOLORS = cplane = 0;
- if ( pcx_cpic )
- { VGR_HRES = pcx_cpic->hdr.hres;
- VGR_VRES = pcx_cpic->hdr.vres;
- VGR_NBPL = pcx_cpic->hdr.bpl;
- VGR_NCOLORS = pcx_cpic->hdr.bpp > 1 ?
- 0x01 << pcx_cpic->hdr.bpp :
- 0x01 << pcx_cpic->hdr.nplanes;
- };
-
- return OK;
- }
-
-
- int pcx_select_plane( plane )
- int plane;
- {
- return cplane = plane & 0x03;
- }
-
-
- int pcx_write_row( row, prow, nbytes )
- int nbytes, row;
- char *prow;
- {
- int i;
-
- i = pcx_cpic->hdr.hres / 8;
- movmem( prow, (pcx_cpic->rows[cplane][row]),
- nbytes <= i ? nbytes : i );
- }
-
-
- int pcx_clear()
- {
- int plane, row, nplanes, nrows, bytes;
-
- nplanes = pcx_cpic->hdr.nplanes;
- nrows = pcx_cpic->hdr.y2 - pcx_cpic->hdr.y1 +1;
- bytes = pcx_cpic->hdr.bpl;
-
- for ( plane=0; plane < nplanes; plane ++ )
- for ( row=0; row < bytes; row++ )
- setmem( (pcx_cpic->rows[plane][row]), bytes, 0 );
- }
-
-
- int pcx_mode( m )
- int m;
- {
- switch ( m )
- { case MODE_APA0: /* 640x350x16 */
- case MODE_APA1: /* 720x348x02 */
- case MODE_APA2: /* 640x200x02 */
- /* all these modes save color information
- 1 bit per plane.
- */
- pcx_md = 0;
- break;
- case MODE_APA3: /* 320x200x04 */
- /* this mode puts two bits per pixel into the
- same plane.
- */
- pcx_md = 1;
- break;
- default: /* invalid! */
- return ERROR;
- };
-
- return OK;
- }
-
-
- int pcx_xor_point( x, y, color )
- int x, y, color;
- {
- return pcx_set_point( x, y, pcx_get_point( x, y ) ^ color );
- }
-
-
- int pcx_clr_point( x, y )
- int x, y;
- {
- return pcx_set_point( x, y, 0 );
- }
-
-
- int pcx_set_point( x, y, color )
- int x, y, color;
- {
- register unsigned char *p;
- unsigned char plane, b, o, mask;
-
- if ( pcx_md )
- { o = (x & 3) << 1;
- p = (unsigned char *)pcx_cpic->rows[0][y] + (x>>2);
- *p = (*p & ~(0xc0 >> o)) | ((color & 0x03) << (6-o));
- return OK;
- };
-
- o = x >> 3;
- b = (unsigned int)0x80 >> (x & 0x07);
-
- for ( mask=1,plane=0; plane < pcx_cpic->hdr.nplanes; plane++, mask<<=1 )
- { p = (unsigned char *)pcx_cpic->rows[plane][y] + o;
- if ( color & mask )
- *p |= b;
- else *p &= ~b;
- };
-
- return OK;
- }
-
-
- int pcx_get_point( x, y )
- int x, y;
- {
- unsigned char plane, b, o, color;
-
- if ( pcx_md )
- { b = (x & 3) << 1;
- return ( pcx_cpic->rows[0][y][x>>2] & (0xc0 >> b) ) >> (6-b);
- };
-
- o = x >> 3;
- b = (unsigned int)0x80 >> (x & 0x07);
-
- for ( color=plane=0; plane < pcx_cpic->hdr.nplanes; plane++ )
- color |= !!(pcx_cpic->rows[plane][y][o] & b) << plane;
-
- return color;
- }
-
-
- /* PCX Palette Settings.
- */
-
- int pcx_set_palette( reg, red, green, blue )
- unsigned char reg, red, green, blue;
- {
- if ( pcx_md )
- { pcx_cpic->hdr.triple[reg].red = red;
- return OK;
- };
-
- /* why do we multiply by 85? */
- pcx_cpic->hdr.triple[reg].red = red * 85;
- pcx_cpic->hdr.triple[reg].green = green * 85;
- pcx_cpic->hdr.triple[reg].blue = blue * 85;
- return OK;
- }
-
-
- PCXPIC *pcx_init_pic( hres, vres, nplanes )
- unsigned int hres, vres, nplanes;
- {
- int y, p, bpl;
- PCXPIC *pic;
- char *calloc();
- static TRIPLET ega_pal[] = { /* copied from a */
- 0x00, 0x00, 0x00, /* PBRUSH picture file */
- 0x00, 0x00, 0xaa,
- 0x00, 0xaa, 0x00,
- 0x00, 0xaa, 0xaa,
- 0xaa, 0x00, 0x00,
- 0xaa, 0x00, 0xaa,
- 0xaa, 0xaa, 0x00,
- 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55,
- 0x55, 0x55, 0xff,
- 0x55, 0xff, 0x55,
- 0x55, 0xff, 0xff,
- 0xff, 0x55, 0x55,
- 0xff, 0x55, 0xff,
- 0xff, 0xff, 0x55,
- 0xff, 0xff, 0xff };
-
- static TRIPLET cga_pal[] = {
- 0,0,0, 255,0,0,
- 0,0,0, 255,0,0,
- 0,0,0, 255,0,0,
- 0,0,0, 255,0,0,
- 0,0,0, 255,0,0,
- 0,0,0, 255,0,0,
- 0,0,0, 255,0,0,
- 0,0,0, 255,0,0 };
-
- if ( !(pic = (PCXPIC *) calloc( 1, sizeof(PCXPIC) )) )
- return NULL; /* out of memory */
-
- pic->hdr.x2 = hres -1;
- pic->hdr.y2 = vres -1;
-
- pic->hdr.maker = 10;
- pic->hdr.version = 5;
- pic->hdr.code = 1;
- pic->hdr.bpp = 1 + pcx_md;
- pic->hdr.bpl = bpl = (hres * (1+pcx_md)) / 8;
-
- VGR_HRES = pic->hdr.hres = hres;
- VGR_VRES = pic->hdr.vres = vres;
- VGR_NBPL = bpl;
- VGR_NCOLORS = 1 << (pic->hdr.nplanes = nplanes);
-
- movmem( (pcx_md ? cga_pal : ega_pal),
- pic->hdr.triple, sizeof(pic->hdr.triple) );
-
- for ( p=0; p < nplanes; p++ )
- { if ( ! (pic->rows[p] = (uchar **)calloc( 1, sizeof(char *) * vres)) )
- return pcx_free_pic( pic ), (PCXPIC *)0;
- for ( y=0; y < vres; y++ )
- if ( !(pic->rows[p][y] = (uchar *)calloc( 1, bpl )) )
- return pcx_free_pic( pic ), (PCXPIC *)0;
- };
-
- return pic;
- }
-
-
- int pcx_free_pic( pic )
- PCXPIC *pic;
- {
- int row, plane, nrows, nplan;
-
- nrows = pic->hdr.y2 - pic->hdr.y1 +1;
- nplan = pic->hdr.nplanes;
-
- VGR_MODE( MODE_TEXT0 );
- printf("At pcx_free_pic, probably out of memory...\n");
-
- for ( plane = 0; plane < nplan; plane++ )
- { for ( row = 0; row < nrows; row++ )
- allocf( pic->rows[plane][row] );
- allocf( pic->rows[plane] );
- };
-
- allocf( pic );
- return NULL;
- }
-
-
- void map_not( map, len )
- register unsigned int *map, len;
- {
- for ( ; len--; map++ )
- *map = ~ *map;
- }
-
-
- void pcx_invert_pic( pic )
- PCXPIC *pic;
- {
- int p, r, i;
-
- for ( p=0; p < pic->hdr.nplanes; p++ )
- for ( r=0; r < (pic->hdr.y2 - pic->hdr.y1); r++ )
- map_not( pic->rows[p][r], pic->hdr.bpl / 2 );
- }
-
-
- allocf( p )
- char *p;
- {
- if ( !p )
- return OK;
-
- if ( free(p) == -1 )
- CRASH( "heap munged" );
- }
-
- #ifdef MAIN
-
- /* Manx 'C stack/heap size adjustment -
- The vgr_fill() function uses an enourmous amount of stack,
- and we're going to need enough heap space to allocate
- 4 bit maps for the EGA board.
- */
- uint __STKLOW = 0,
- __STKSIZ = 4096,
- __HEAPSIZ = 8192;
-
- int cga_init(), ega_init(), herc_init();
- int board, (*board_init)(), md;
-
- /* This structure is used here to facilitate drawing the
- simple X and complex box that are used to test the
- dot, line and fill functions.
- */
- typedef struct {
- int x,y;
- } OBJ;
-
- static OBJ obj[] = {
- 100, 100, 150, 200, 200, 100, 250, 150, 175, 250, 250, 350, 200, 400, 150, 300,
- 100, 400, 50, 350, 125, 250, 50, 150, 100, 100 };
-
- static OBJ obj2[] = {
- 0, 0,280, 0,280,140,240,140,240, 20,200, 20,200,280,240,280,240,160,
- 280,160,280,300, 0,300, 0,160, 40,160, 40,280, 80,280, 80, 20, 40, 20,
- 40,140, 0,140, 0, 0 };
-
- static OBJ obj3[] = {
- 120,20, 160,20, 160,280, 120,280, 120,20 };
-
-
- main( argc, argv )
- char **argv;
- int argc;
- {
- void pcx_showpic();
- FILE *fp, *fopen();
- int c, h, v, p;
-
- printf("PCX test routine.\n");
- if ( argc == 1 )
- printf("Try \"PCX xx\" for help\n" );
-
- board = vgr_get_board();
-
- if ( argc >= 2 )
- { if ( !strcmp(argv[1], "ega") )
- board = TYPE_EGA;
- else if ( !strcmp(argv[1], "cga") )
- board = TYPE_CGA;
- else if ( !strcmp(argv[1], "herc") )
- board = TYPE_HERC;
- else if ( !strcmp(argv[1], "cga2") )
- board = 9;
- else { printf("\
- usage: PCX\n\
- or PCX <board>\n\
- or PCX <board> <pcx_file_name>\n\n\
- func: Excercises the board & PCX routines.\n\
- <board> may be one of:\n\
- cga - 640x200x2 CGA\n\
- cga2- 320x200x4 CGA\n\
- herc- Hercules Hi-Res\n\
- ega - 640x350x16 EGA\n\
- <pcx_file_name> may be any file name,\n\
- although an extension of .PCX is\n\
- appropriate.\n" );
- exit(1);
- };
- };
-
- switch( board )
- { case TYPE_UNKNOWN:
- case TYPE_MDA:
- CRASH("unable to detect a HERC, CGA or EGA board");
- case TYPE_CGA:
- printf("CGA board detected\n");
- board_init = cga_init;
- md = MODE_APA2, c = 1, h = 640, v=200, p=1;
- break;
- case 9:
- printf("CGA/APA3 Selected\n");
- board_init = cga_init;
- md = MODE_APA3, c = 2, h = 320, v=200, p=1;
- break;
- case TYPE_EGA:
- printf("EGA board detected\n");
- board_init = ega_init;
- md = MODE_APA0, c = 9, h = 640, v=350, p=4;
- break;
- case TYPE_HERC:
- printf("HERC board detected\n");
- board_init = herc_init;
- md = MODE_APA1, c = 1, h = 720, v=348, p=1;
- break;
- default:
- CRASH("bug: invalid board type number");
- };
-
- printf("Hit return to continue:");
- getchar();
-
- /* pcx_init_pic needs to know what mode it's in
- */
- pcx_init();
- pcx_mode( md );
- if ( !(pcx_cpic = pcx_init_pic( h, v, p )) )
- CRASH("out of memory");
-
- pcx_init();
- if ( VGR_MODE( md ) )
- CRASH( "error in mode selection" );
-
- printf("HRES=%d, VRES=%d, NCOLORS=%d, NPLANES=%d, pcx_md=%d\n",
- VGR_HRES, VGR_VRES, VGR_NCOLORS, p, pcx_md );
-
- draw_it( (OBJ *)&obj, NELEMS(obj) , 3, 3, 0, 0, c );
- printf(".");
- draw_it( (OBJ *)&obj2, NELEMS(obj2), 3, 3, 150, 0, c );
- printf(".");
- draw_it( (OBJ *)&obj3, NELEMS(obj3), 3, 3, 150, 0, c );
- printf(".");
-
- vgr_fill( 33, 40, c );
- printf(".");
- vgr_fill( 179, 19, c );
-
- printf("\nhit return to continue, then hit return again:");
- getchar();
-
- if ( (*board_init)() )
- CRASH( "board init failed" );
- if ( VGR_MODE( md ) )
- CRASH( "error in mode selection" );
-
- pcx_showpic( pcx_cpic, 0, 0, 0 );
-
- getchar();
-
- VGR_MODE( MODE_TEXT0 );
-
- if ( argc == 3 )
- { if ( !(fp = fopen( argv[2], "w" )) )
- CRASH( "error opening picture file" );
- if ( pcx_write_pic( pcx_cpic, fp ) )
- CRASH( "error writing picture file" );
- fclose(fp);
- };
-
- exit(0);
- }
-
-
- draw_it( obj, n, divx, divy, ox, oy, c )
- OBJ *obj;
- int n, divx, divy;
- {
- int x;
-
- vgr_point( obj[0].x / divx + ox, obj[0].y / divy + oy, -1 );
- for ( x=1; x < n; x++ )
- vgr_point( obj[x].x / divx + ox, obj[x].y / divy + oy, c );
- }
-
-
- #endif
-
-