xref: /plan9/sys/src/cmd/gs/src/gdevherc.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier /* Copyright (C) 1990, 1991, 1993 Aladdin Enterprises.  All rights reserved.
27dd7cddfSDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
57dd7cddfSDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: gdevherc.c,v 1.5 2002/06/16 05:48:55 lpd Exp $*/
187dd7cddfSDavid du Colombier /* IBM PC-compatible Hercules Graphics display driver */
197dd7cddfSDavid du Colombier /* using direct access to frame buffer */
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier #define FB_RASTER 90
227dd7cddfSDavid du Colombier #define SCREEN_HEIGHT 350
237dd7cddfSDavid du Colombier #define SCREEN_ASPECT_RATIO (54.0/35.0)
247dd7cddfSDavid du Colombier #define VIDEO_MODE 0x07
257dd7cddfSDavid du Colombier #define regen 0xb0000000L
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier #define interrupt			/* patch ANSI incompatibility */
287dd7cddfSDavid du Colombier #include "dos_.h"
297dd7cddfSDavid du Colombier typedef union REGS registers;
307dd7cddfSDavid du Colombier #include "gx.h"
317dd7cddfSDavid du Colombier #include "gsmatrix.h"			/* for gxdevice.h */
327dd7cddfSDavid du Colombier #include "gxbitmap.h"
337dd7cddfSDavid du Colombier #include "gxdevice.h"
347dd7cddfSDavid du Colombier 
357dd7cddfSDavid du Colombier /* outportb is defined in dos_.h */
367dd7cddfSDavid du Colombier #define outport2(port, index, data)\
377dd7cddfSDavid du Colombier   (outportb(port, index), outportb((port)+1, data))
387dd7cddfSDavid du Colombier /* Define the nominal page height in inches. */
397dd7cddfSDavid du Colombier #ifdef A4
407dd7cddfSDavid du Colombier #  define PAGE_HEIGHT_INCHES 11.69
417dd7cddfSDavid du Colombier #else
427dd7cddfSDavid du Colombier #  define PAGE_HEIGHT_INCHES 11.0
437dd7cddfSDavid du Colombier #endif
447dd7cddfSDavid du Colombier 
457dd7cddfSDavid du Colombier /* Dimensions of screen */
467dd7cddfSDavid du Colombier #define screen_size_x (FB_RASTER * 8)
477dd7cddfSDavid du Colombier #define screen_size_y SCREEN_HEIGHT
487dd7cddfSDavid du Colombier /* Other display parameters */
497dd7cddfSDavid du Colombier #define raster_x FB_RASTER
507dd7cddfSDavid du Colombier #define aspect_ratio SCREEN_ASPECT_RATIO
517dd7cddfSDavid du Colombier #define graphics_video_mode VIDEO_MODE
527dd7cddfSDavid du Colombier 
537dd7cddfSDavid du Colombier /* Procedures */
547dd7cddfSDavid du Colombier 
557dd7cddfSDavid du Colombier 	/* See gxdevice.h for the definitions of the procedures. */
567dd7cddfSDavid du Colombier 
577dd7cddfSDavid du Colombier dev_proc_open_device(herc_open);
587dd7cddfSDavid du Colombier dev_proc_close_device(herc_close);
597dd7cddfSDavid du Colombier dev_proc_fill_rectangle(herc_fill_rectangle);
607dd7cddfSDavid du Colombier dev_proc_copy_mono(herc_copy_mono);
617dd7cddfSDavid du Colombier dev_proc_copy_color(herc_copy_color);
627dd7cddfSDavid du Colombier 
637dd7cddfSDavid du Colombier /* The device descriptor */
647dd7cddfSDavid du Colombier private gx_device_procs herc_procs = {
657dd7cddfSDavid du Colombier 	herc_open,
667dd7cddfSDavid du Colombier 	gx_default_get_initial_matrix,
677dd7cddfSDavid du Colombier 	gx_default_sync_output,
687dd7cddfSDavid du Colombier 	gx_default_output_page,
697dd7cddfSDavid du Colombier 	herc_close,
707dd7cddfSDavid du Colombier 	gx_default_map_rgb_color,
717dd7cddfSDavid du Colombier 	gx_default_map_color_rgb,
727dd7cddfSDavid du Colombier 	herc_fill_rectangle,
737dd7cddfSDavid du Colombier 	gx_default_tile_rectangle,
747dd7cddfSDavid du Colombier 	herc_copy_mono,
757dd7cddfSDavid du Colombier 	herc_copy_color
767dd7cddfSDavid du Colombier };
777dd7cddfSDavid du Colombier 
787dd7cddfSDavid du Colombier gx_device far_data gs_herc_device = {
797dd7cddfSDavid du Colombier 	std_device_std_body(gx_device, &herc_procs, "herc",
807dd7cddfSDavid du Colombier 	  screen_size_x, screen_size_y,
817dd7cddfSDavid du Colombier 	/* The following parameters map an appropriate fraction of */
827dd7cddfSDavid du Colombier 	/* the screen to a full-page coordinate space. */
837dd7cddfSDavid du Colombier 	/* This may or may not be what is desired! */
847dd7cddfSDavid du Colombier 	  (screen_size_y * aspect_ratio) / PAGE_HEIGHT_INCHES,	/* x dpi */
857dd7cddfSDavid du Colombier 	  screen_size_y / PAGE_HEIGHT_INCHES		/* y dpi */
867dd7cddfSDavid du Colombier 	)
877dd7cddfSDavid du Colombier };
887dd7cddfSDavid du Colombier 
897dd7cddfSDavid du Colombier 
907dd7cddfSDavid du Colombier /* Forward declarations */
91*593dc095SDavid du Colombier private int herc_get_mode(void);
92*593dc095SDavid du Colombier private void herc_set_mode(int);
937dd7cddfSDavid du Colombier 
947dd7cddfSDavid du Colombier /* Save the HERC mode */
957dd7cddfSDavid du Colombier private int herc_save_mode = -1;
967dd7cddfSDavid du Colombier 
977dd7cddfSDavid du Colombier /* Reinitialize the herc for text mode */
987dd7cddfSDavid du Colombier int
herc_close(gx_device * dev)997dd7cddfSDavid du Colombier herc_close(gx_device *dev)
1007dd7cddfSDavid du Colombier {	if ( herc_save_mode >= 0 ) herc_set_mode(herc_save_mode);
1017dd7cddfSDavid du Colombier 	return 0;
1027dd7cddfSDavid du Colombier }
1037dd7cddfSDavid du Colombier 
1047dd7cddfSDavid du Colombier /* ------ Internal routines ------ */
1057dd7cddfSDavid du Colombier 
1067dd7cddfSDavid du Colombier /* Read the device mode */
1077dd7cddfSDavid du Colombier private int
herc_get_mode(void)1087dd7cddfSDavid du Colombier herc_get_mode(void)
1097dd7cddfSDavid du Colombier {	registers regs;
1107dd7cddfSDavid du Colombier 	regs.h.ah = 0xf;
1117dd7cddfSDavid du Colombier 	int86(0x10, &regs, &regs);
1127dd7cddfSDavid du Colombier 	return regs.h.al;
1137dd7cddfSDavid du Colombier }
1147dd7cddfSDavid du Colombier 
1157dd7cddfSDavid du Colombier /* Set the device mode */
1167dd7cddfSDavid du Colombier private void
herc_set_mode(int mode)1177dd7cddfSDavid du Colombier herc_set_mode(int mode)
1187dd7cddfSDavid du Colombier {	registers regs;
1197dd7cddfSDavid du Colombier 	regs.h.ah = 0;
1207dd7cddfSDavid du Colombier 	regs.h.al = mode;
1217dd7cddfSDavid du Colombier 	int86(0x10, &regs, &regs);
1227dd7cddfSDavid du Colombier }
1237dd7cddfSDavid du Colombier 
1247dd7cddfSDavid du Colombier 
1257dd7cddfSDavid du Colombier /****************************************************************/
1267dd7cddfSDavid du Colombier /* Hercules graphics card functions				*/
1277dd7cddfSDavid du Colombier /*								*/
1287dd7cddfSDavid du Colombier /* -- Taken from Jan/Feb 1988 issue of Micro Cornucopia #39	*/
1297dd7cddfSDavid du Colombier /*								*/
1307dd7cddfSDavid du Colombier /* --rewritten for MSC 5.1 on 02/18/91 by Phillip Conrad	*/
1317dd7cddfSDavid du Colombier /****************************************************************/
1327dd7cddfSDavid du Colombier 
1337dd7cddfSDavid du Colombier 
1347dd7cddfSDavid du Colombier static const char paramg[12] = {0x35, 0x2d, 0x2e, 0x07, 0x5b, 0x02,
1357dd7cddfSDavid du Colombier 			      0x57, 0x57, 0x02, 0x03, 0x00, 0x00};
1367dd7cddfSDavid du Colombier /* (Never used)
1377dd7cddfSDavid du Colombier static const char paramt[12] = {0x61, 0x50, 0x52, 0x0f, 0x19, 0x06,
1387dd7cddfSDavid du Colombier 			      0x19, 0x19, 0x02, 0x0d, 0x0b, 0x0c};
1397dd7cddfSDavid du Colombier */
1407dd7cddfSDavid du Colombier 
1417dd7cddfSDavid du Colombier /* Type and macro for frame buffer pointers. */
1427dd7cddfSDavid du Colombier /*** Intimately tied to the 80x86 (x<2) addressing architecture. ***/
1437dd7cddfSDavid du Colombier typedef byte far *fb_ptr;
1447dd7cddfSDavid du Colombier #  define mk_fb_ptr(x, y)\
1457dd7cddfSDavid du Colombier     (fb_ptr)((regen) + ((0x2000 * ((y) % 4) + (90 * ((y) >> 2))) + ((int)(x) >> 3)))
1467dd7cddfSDavid du Colombier 
1477dd7cddfSDavid du Colombier 
1487dd7cddfSDavid du Colombier /* Structure for operation parameters. */
1497dd7cddfSDavid du Colombier /* Note that this structure is known to assembly code. */
1507dd7cddfSDavid du Colombier /* Not all parameters are used for every operation. */
1517dd7cddfSDavid du Colombier typedef struct rop_params_s {
1527dd7cddfSDavid du Colombier 	fb_ptr dest;			/* pointer to frame buffer */
1537dd7cddfSDavid du Colombier 	int draster;			/* raster of frame buffer */
1547dd7cddfSDavid du Colombier 	const byte far *src;		/* pointer to source data */
1557dd7cddfSDavid du Colombier 	int sraster;			/* source raster */
1567dd7cddfSDavid du Colombier 	int width;			/* width in bytes */
1577dd7cddfSDavid du Colombier 	int height;			/* height in scan lines */
1587dd7cddfSDavid du Colombier 	int shift;			/* amount to right shift source */
1597dd7cddfSDavid du Colombier 	int invert;			/* 0 or -1 to invert source */
1607dd7cddfSDavid du Colombier 	int data;			/* data for fill */
1617dd7cddfSDavid du Colombier 	int x_pos;		/*>>added--2/24/91 */
1627dd7cddfSDavid du Colombier 	int y_pos;
1637dd7cddfSDavid du Colombier } rop_params;
1647dd7cddfSDavid du Colombier 
1657dd7cddfSDavid du Colombier /* Define the device port and register numbers, and the regen map base */
1667dd7cddfSDavid du Colombier #define seq_addr 0x3b4		/* changed for HERC card (6845 ports)*/
1677dd7cddfSDavid du Colombier #define graph_mode 0x3b8
1687dd7cddfSDavid du Colombier #define graph_stat 0x3ba
1697dd7cddfSDavid du Colombier #define graph_config 0x3bf
1707dd7cddfSDavid du Colombier 
1717dd7cddfSDavid du Colombier #ifndef regen
1727dd7cddfSDavid du Colombier #define regen 0xa0000000L
1737dd7cddfSDavid du Colombier #endif
1747dd7cddfSDavid du Colombier 
1757dd7cddfSDavid du Colombier 
1767dd7cddfSDavid du Colombier /* Initialize the display for Hercules graphics mode */
1777dd7cddfSDavid du Colombier int
herc_open(gx_device * dev)1787dd7cddfSDavid du Colombier herc_open(gx_device *dev)
1797dd7cddfSDavid du Colombier {	int i;
1807dd7cddfSDavid du Colombier 	if ( herc_save_mode < 0 ) herc_save_mode = herc_get_mode();
1817dd7cddfSDavid du Colombier /*	herc_set_mode(graphics_video_mode);  */
1827dd7cddfSDavid du Colombier 	outportb(graph_config,3);
1837dd7cddfSDavid du Colombier 	for(i=0;i<sizeof(paramg);i++)
1847dd7cddfSDavid du Colombier 	{
1857dd7cddfSDavid du Colombier 		outport2(seq_addr,i,paramg[i]);
1867dd7cddfSDavid du Colombier 
1877dd7cddfSDavid du Colombier 	}
1887dd7cddfSDavid du Colombier 	outportb(graph_mode,0x0a);	/* set page 0 */
1897dd7cddfSDavid du Colombier 	for(i=0;i<0x3FFFL;i++)	/* clear the screen */
1907dd7cddfSDavid du Colombier 		{
1917dd7cddfSDavid du Colombier 		int far *loc = (int far *)( regen  +(2L*i));
1927dd7cddfSDavid du Colombier 		*loc = 0;
1937dd7cddfSDavid du Colombier 		}
1947dd7cddfSDavid du Colombier 
1957dd7cddfSDavid du Colombier 	return 0;
1967dd7cddfSDavid du Colombier }
1977dd7cddfSDavid du Colombier 
1987dd7cddfSDavid du Colombier /* Macro for testing bit-inclusion */
1997dd7cddfSDavid du Colombier #define bit_included_in(x,y) !((x)&~(y))
2007dd7cddfSDavid du Colombier 
2017dd7cddfSDavid du Colombier /* Copy a monochrome bitmap.  The colors are given explicitly. */
2027dd7cddfSDavid du Colombier /* Color = gx_no_color_index means transparent (no effect on the image). */
2037dd7cddfSDavid du Colombier int
herc_copy_mono(gx_device * dev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index izero,gx_color_index ione)2047dd7cddfSDavid du Colombier herc_copy_mono(gx_device *dev,
2057dd7cddfSDavid du Colombier   const byte *base, int sourcex, int raster, gx_bitmap_id id,
2067dd7cddfSDavid du Colombier   int x, int y, int w, int h, gx_color_index izero, gx_color_index ione)
2077dd7cddfSDavid du Colombier {	rop_params params;
2087dd7cddfSDavid du Colombier #define czero (int)izero
2097dd7cddfSDavid du Colombier #define cone (int)ione
2107dd7cddfSDavid du Colombier 	int dleft, sleft, count;
2117dd7cddfSDavid du Colombier 	int invert, zmask, omask;
2127dd7cddfSDavid du Colombier 	byte mask, rmask;
2137dd7cddfSDavid du Colombier 
2147dd7cddfSDavid du Colombier 	if ( cone == czero )		/* vacuous case */
2157dd7cddfSDavid du Colombier 		return herc_fill_rectangle(dev, x, y, w, h, izero);
2167dd7cddfSDavid du Colombier 
2177dd7cddfSDavid du Colombier 	/* clip */
2187dd7cddfSDavid du Colombier 	fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
2197dd7cddfSDavid du Colombier 	params.dest = mk_fb_ptr(x, y);
2207dd7cddfSDavid du Colombier 	params.draster = raster_x;
2217dd7cddfSDavid du Colombier 	params.src = base + (sourcex >> 3);
2227dd7cddfSDavid du Colombier 	params.sraster = raster;
2237dd7cddfSDavid du Colombier 	params.height = h;
2247dd7cddfSDavid du Colombier 	params.shift = (x - sourcex) & 7;
2257dd7cddfSDavid du Colombier 	params.y_pos = y;
2267dd7cddfSDavid du Colombier 	params.x_pos = x;
2277dd7cddfSDavid du Colombier 	params.width = w;
2287dd7cddfSDavid du Colombier 
2297dd7cddfSDavid du Colombier 	if(czero > cone) params.invert = -1;
2307dd7cddfSDavid du Colombier 
2317dd7cddfSDavid du Colombier 	/* Macros for writing partial bytes. */
2327dd7cddfSDavid du Colombier 	/* bits has already been inverted by xor'ing with invert. */
2337dd7cddfSDavid du Colombier 
2347dd7cddfSDavid du Colombier #define write_byte_masked(ptr, bits, mask)\
2357dd7cddfSDavid du Colombier   *ptr = ((bits | ~mask | zmask) & (*ptr | (bits & mask & omask)))
2367dd7cddfSDavid du Colombier 
2377dd7cddfSDavid du Colombier #define write_byte(ptr, bits)\
2387dd7cddfSDavid du Colombier   *ptr = ((bits | zmask) & (*ptr | (bits & omask)))
2397dd7cddfSDavid du Colombier 
2407dd7cddfSDavid du Colombier 	invert = (czero == 1 || cone == 0 ? -1 : 0);
2417dd7cddfSDavid du Colombier /*	invert = (czero == 1 || cone == 1 ? -1 : 0); */
2427dd7cddfSDavid du Colombier 	zmask = (czero == 0 || cone == 0 ? 0 : -1);
2437dd7cddfSDavid du Colombier 	omask = (czero == 1 || cone == 1 ? -1 : 0);
2447dd7cddfSDavid du Colombier 
2457dd7cddfSDavid du Colombier #undef czero
2467dd7cddfSDavid du Colombier #undef cone
2477dd7cddfSDavid du Colombier 
2487dd7cddfSDavid du Colombier 	/* Actually copy the bits. */
2497dd7cddfSDavid du Colombier 
2507dd7cddfSDavid du Colombier 	sleft = 8 - (sourcex & 7);
2517dd7cddfSDavid du Colombier 	dleft = 8 - (x & 7);
2527dd7cddfSDavid du Colombier 	mask = 0xff >> (8 - dleft);
2537dd7cddfSDavid du Colombier 	count = w;
2547dd7cddfSDavid du Colombier 	if ( w < dleft )
2557dd7cddfSDavid du Colombier 		mask -= mask >> w,
2567dd7cddfSDavid du Colombier 		rmask = 0;
2577dd7cddfSDavid du Colombier 	else
2587dd7cddfSDavid du Colombier 		rmask = 0xff00 >> ((w - dleft) & 7);
2597dd7cddfSDavid du Colombier 
2607dd7cddfSDavid du Colombier 	if (sleft == dleft)		/* optimize the aligned case */
2617dd7cddfSDavid du Colombier 	{
2627dd7cddfSDavid du Colombier 		w -= dleft;
2637dd7cddfSDavid du Colombier 		while ( --h >= 0 )
2647dd7cddfSDavid du Colombier 		{
2657dd7cddfSDavid du Colombier 			register const byte *bptr = params.src;
2667dd7cddfSDavid du Colombier 			register byte *optr = mk_fb_ptr(params.x_pos,params.y_pos);
2677dd7cddfSDavid du Colombier 			register int bits = *bptr ^ invert;	/* first partial byte */
2687dd7cddfSDavid du Colombier 
2697dd7cddfSDavid du Colombier 			count = w;
2707dd7cddfSDavid du Colombier 
2717dd7cddfSDavid du Colombier 			write_byte_masked(optr, bits, mask);
2727dd7cddfSDavid du Colombier 
2737dd7cddfSDavid du Colombier 			/* Do full bytes. */
2747dd7cddfSDavid du Colombier 
2757dd7cddfSDavid du Colombier 			while ((count -= 8) >= 0)
2767dd7cddfSDavid du Colombier 			{
2777dd7cddfSDavid du Colombier 				bits = *++bptr ^ invert;
2787dd7cddfSDavid du Colombier 				params.x_pos += 8;
2797dd7cddfSDavid du Colombier 				optr = mk_fb_ptr(params.x_pos,params.y_pos);
2807dd7cddfSDavid du Colombier 				write_byte(optr, bits);
2817dd7cddfSDavid du Colombier 			}
2827dd7cddfSDavid du Colombier 			/* Do last byte */
2837dd7cddfSDavid du Colombier 
2847dd7cddfSDavid du Colombier 			if (count > -8)
2857dd7cddfSDavid du Colombier 			{
2867dd7cddfSDavid du Colombier 				bits = *++bptr ^ invert;
2877dd7cddfSDavid du Colombier 				params.x_pos += 8;
2887dd7cddfSDavid du Colombier 				optr = mk_fb_ptr(params.x_pos,params.y_pos);
2897dd7cddfSDavid du Colombier 				write_byte_masked(optr, bits, rmask);
2907dd7cddfSDavid du Colombier 			}
2917dd7cddfSDavid du Colombier /*			dest += BPL; */
2927dd7cddfSDavid du Colombier 			params.y_pos++;
2937dd7cddfSDavid du Colombier 			params.x_pos = x;
2947dd7cddfSDavid du Colombier 			params.src += raster;
2957dd7cddfSDavid du Colombier 		}
2967dd7cddfSDavid du Colombier 	}
2977dd7cddfSDavid du Colombier 	else
2987dd7cddfSDavid du Colombier 	{
2997dd7cddfSDavid du Colombier 		int skew = (sleft - dleft) & 7;
3007dd7cddfSDavid du Colombier 		int cskew = 8 - skew;
3017dd7cddfSDavid du Colombier 
3027dd7cddfSDavid du Colombier 		while (--h >= 0)
3037dd7cddfSDavid du Colombier 		{
3047dd7cddfSDavid du Colombier 			const byte *bptr = params.src;
3057dd7cddfSDavid du Colombier 			byte *optr = mk_fb_ptr(params.x_pos,params.y_pos);
3067dd7cddfSDavid du Colombier 			register int bits;
3077dd7cddfSDavid du Colombier 
3087dd7cddfSDavid du Colombier 			count = w;
3097dd7cddfSDavid du Colombier 
3107dd7cddfSDavid du Colombier 			/* Do the first partial byte */
3117dd7cddfSDavid du Colombier 
3127dd7cddfSDavid du Colombier 			if (sleft >= dleft)
3137dd7cddfSDavid du Colombier 			{
3147dd7cddfSDavid du Colombier 				bits = *bptr >> skew;
3157dd7cddfSDavid du Colombier 			}
3167dd7cddfSDavid du Colombier 			else /* ( sleft < dleft ) */
3177dd7cddfSDavid du Colombier 			{
3187dd7cddfSDavid du Colombier 				bits = *bptr++ << cskew;
3197dd7cddfSDavid du Colombier 				if (count > sleft)
3207dd7cddfSDavid du Colombier 					bits += *bptr >> skew;
3217dd7cddfSDavid du Colombier 			}
3227dd7cddfSDavid du Colombier 			bits ^= invert;
3237dd7cddfSDavid du Colombier 			write_byte_masked(optr, bits, mask);
3247dd7cddfSDavid du Colombier 			count -= dleft;
3257dd7cddfSDavid du Colombier 			params.x_pos += 8;
3267dd7cddfSDavid du Colombier 			optr = mk_fb_ptr(params.x_pos,params.y_pos);
3277dd7cddfSDavid du Colombier 
3287dd7cddfSDavid du Colombier 			/* Do full bytes. */
3297dd7cddfSDavid du Colombier 
3307dd7cddfSDavid du Colombier 			while ( count >= 8 )
3317dd7cddfSDavid du Colombier 			{
3327dd7cddfSDavid du Colombier 				bits = *bptr++ << cskew;
3337dd7cddfSDavid du Colombier 				bits += *bptr >> skew;
3347dd7cddfSDavid du Colombier 				bits ^= invert;
3357dd7cddfSDavid du Colombier 				write_byte(optr, bits);
3367dd7cddfSDavid du Colombier 				count -= 8;
3377dd7cddfSDavid du Colombier 				params.x_pos += 8;
3387dd7cddfSDavid du Colombier 				optr = mk_fb_ptr(params.x_pos,params.y_pos);
3397dd7cddfSDavid du Colombier 			}
3407dd7cddfSDavid du Colombier 
3417dd7cddfSDavid du Colombier 			/* Do last byte */
3427dd7cddfSDavid du Colombier 
3437dd7cddfSDavid du Colombier 			if (count > 0)
3447dd7cddfSDavid du Colombier 			{
3457dd7cddfSDavid du Colombier 				bits = *bptr++ << cskew;
3467dd7cddfSDavid du Colombier  				if (count > skew)
3477dd7cddfSDavid du Colombier 					bits += *bptr >> skew;
3487dd7cddfSDavid du Colombier 				bits ^= invert;
3497dd7cddfSDavid du Colombier 				write_byte_masked(optr, bits, rmask);
3507dd7cddfSDavid du Colombier 			}
3517dd7cddfSDavid du Colombier /*			dest += BPL;
3527dd7cddfSDavid du Colombier 			line += raster;
3537dd7cddfSDavid du Colombier */
3547dd7cddfSDavid du Colombier 			params.y_pos++;
3557dd7cddfSDavid du Colombier 			params.x_pos = x;
3567dd7cddfSDavid du Colombier 			params.src += raster;
3577dd7cddfSDavid du Colombier 		}
3587dd7cddfSDavid du Colombier 	}
3597dd7cddfSDavid du Colombier 	return 0;
3607dd7cddfSDavid du Colombier }
3617dd7cddfSDavid du Colombier 
3627dd7cddfSDavid du Colombier /* Copy a color pixelmap.  This is just like a bitmap, */
3637dd7cddfSDavid du Colombier int
herc_copy_color(gx_device * dev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h)3647dd7cddfSDavid du Colombier herc_copy_color(gx_device *dev,
3657dd7cddfSDavid du Colombier   const byte *base, int sourcex, int raster, gx_bitmap_id id,
3667dd7cddfSDavid du Colombier   int x, int y, int w, int h)
3677dd7cddfSDavid du Colombier {	return herc_copy_mono(dev, base, sourcex, raster, id,
3687dd7cddfSDavid du Colombier 		x, y, w, h,(gx_color_index)0, (gx_color_index)1);
3697dd7cddfSDavid du Colombier }
3707dd7cddfSDavid du Colombier 
3717dd7cddfSDavid du Colombier #  define mk_fb_yptr(x, y)\
3727dd7cddfSDavid du Colombier     (fb_ptr)((regen) + ((0x2000 * ((y) % 4) + (90 * ((y) >> 2))) + x))
3737dd7cddfSDavid du Colombier 
3747dd7cddfSDavid du Colombier /* Fill a rectangle. */
3757dd7cddfSDavid du Colombier int
herc_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)3767dd7cddfSDavid du Colombier herc_fill_rectangle(gx_device *dev, int x, int y, int w, int h,
3777dd7cddfSDavid du Colombier   gx_color_index color)
3787dd7cddfSDavid du Colombier {	rop_params params;
3797dd7cddfSDavid du Colombier 
3807dd7cddfSDavid du Colombier 	int x2, y2, xlen;
3817dd7cddfSDavid du Colombier 	byte led, red, d;
3827dd7cddfSDavid du Colombier 	byte far *ptr;
3837dd7cddfSDavid du Colombier 	int xloc;
3847dd7cddfSDavid du Colombier 
3857dd7cddfSDavid du Colombier 	fit_fill(dev, x, y, w, h);
3867dd7cddfSDavid du Colombier 
3877dd7cddfSDavid du Colombier 	params.dest = mk_fb_ptr(x, y);
3887dd7cddfSDavid du Colombier 	params.y_pos = y;
3897dd7cddfSDavid du Colombier 	params.x_pos = x;
3907dd7cddfSDavid du Colombier 
3917dd7cddfSDavid du Colombier 	x2 = x + w - 1;
3927dd7cddfSDavid du Colombier 	y2 = y + h - 1;
3937dd7cddfSDavid du Colombier 
3947dd7cddfSDavid du Colombier 	xlen = (x2 >> 3) - (x >> 3) - 1;
3957dd7cddfSDavid du Colombier 	led = 0xff >> (x & 7);
3967dd7cddfSDavid du Colombier 	red = 0xff << (7 - (x2 & 7));
3977dd7cddfSDavid du Colombier 
3987dd7cddfSDavid du Colombier 	ptr =  mk_fb_ptr(x,y);
3997dd7cddfSDavid du Colombier 
4007dd7cddfSDavid du Colombier 	if (color)
4017dd7cddfSDavid du Colombier 	{
4027dd7cddfSDavid du Colombier 		/* here to set pixels */
4037dd7cddfSDavid du Colombier 
4047dd7cddfSDavid du Colombier 		if (xlen == -1)
4057dd7cddfSDavid du Colombier 		{
4067dd7cddfSDavid du Colombier 			/* special for rectangles that fit in a byte */
4077dd7cddfSDavid du Colombier 
4087dd7cddfSDavid du Colombier 			d = led & red;
4097dd7cddfSDavid du Colombier 			for(; h >= 0; h--, ptr = mk_fb_ptr(x,params.y_pos))
4107dd7cddfSDavid du Colombier 			{
4117dd7cddfSDavid du Colombier 				*ptr |= d;
4127dd7cddfSDavid du Colombier 				params.y_pos++;
4137dd7cddfSDavid du Colombier 			}
4147dd7cddfSDavid du Colombier 			return 0;
4157dd7cddfSDavid du Colombier 		}
4167dd7cddfSDavid du Colombier 
4177dd7cddfSDavid du Colombier 		/* normal fill */
4187dd7cddfSDavid du Colombier 
4197dd7cddfSDavid du Colombier 		xloc = params.x_pos >> 3;
4207dd7cddfSDavid du Colombier 		for(; h >= 0; h--, ptr = mk_fb_ptr(x,params.y_pos))
4217dd7cddfSDavid du Colombier 		{	register int x_count = xlen;
4227dd7cddfSDavid du Colombier 			register byte far *p = ptr;
4237dd7cddfSDavid du Colombier 			*p |= led;
4247dd7cddfSDavid du Colombier /*			 params.x_pos += 8; */
4257dd7cddfSDavid du Colombier 			xloc++;
4267dd7cddfSDavid du Colombier 			 p = mk_fb_yptr(xloc,params.y_pos);
4277dd7cddfSDavid du Colombier 			while ( x_count-- ) {
4287dd7cddfSDavid du Colombier 				 *p = 0xff;
4297dd7cddfSDavid du Colombier /*				 params.x_pos += 8; */
4307dd7cddfSDavid du Colombier 				xloc++;
4317dd7cddfSDavid du Colombier 				 p = mk_fb_yptr(xloc,params.y_pos);
4327dd7cddfSDavid du Colombier 				}
4337dd7cddfSDavid du Colombier 			*p |= red;
4347dd7cddfSDavid du Colombier /*			params.x_pos = x; */
4357dd7cddfSDavid du Colombier 			xloc = params.x_pos >> 3;
4367dd7cddfSDavid du Colombier 			params.y_pos++;
4377dd7cddfSDavid du Colombier 		}
4387dd7cddfSDavid du Colombier 	}
4397dd7cddfSDavid du Colombier 
4407dd7cddfSDavid du Colombier 	/* here to clear pixels */
4417dd7cddfSDavid du Colombier 
4427dd7cddfSDavid du Colombier 	led = ~led;
4437dd7cddfSDavid du Colombier 	red = ~red;
4447dd7cddfSDavid du Colombier 
4457dd7cddfSDavid du Colombier 	if (xlen == -1)
4467dd7cddfSDavid du Colombier 	{
4477dd7cddfSDavid du Colombier 		/* special for rectangles that fit in a byte */
4487dd7cddfSDavid du Colombier 
4497dd7cddfSDavid du Colombier 		d = led | red;
4507dd7cddfSDavid du Colombier 		for(; h >= 0; h--, ptr  = mk_fb_ptr(x,params.y_pos))
4517dd7cddfSDavid du Colombier 			{
4527dd7cddfSDavid du Colombier 			*ptr &= d;
4537dd7cddfSDavid du Colombier 			params.y_pos++;
4547dd7cddfSDavid du Colombier 			}
4557dd7cddfSDavid du Colombier 		return 0;
4567dd7cddfSDavid du Colombier 	}
4577dd7cddfSDavid du Colombier 
4587dd7cddfSDavid du Colombier 	/* normal fill */
4597dd7cddfSDavid du Colombier 
4607dd7cddfSDavid du Colombier 	xloc = x >> 3;
4617dd7cddfSDavid du Colombier 	for(; h >= 0; h--, ptr = mk_fb_ptr(x,params.y_pos))
4627dd7cddfSDavid du Colombier 	{	register int x_count = xlen;
4637dd7cddfSDavid du Colombier 		register byte far *p = ptr;
4647dd7cddfSDavid du Colombier 		*p &= led;
4657dd7cddfSDavid du Colombier /*		 params.x_pos += 8; */
4667dd7cddfSDavid du Colombier 		xloc++;
4677dd7cddfSDavid du Colombier 		 p = mk_fb_yptr(xloc,params.y_pos);
4687dd7cddfSDavid du Colombier 		while ( x_count-- ) {
4697dd7cddfSDavid du Colombier 			 *p = 0x00;
4707dd7cddfSDavid du Colombier /*			 params.x_pos += 8; */
4717dd7cddfSDavid du Colombier 			xloc++;
4727dd7cddfSDavid du Colombier 			 p = mk_fb_yptr(xloc,params.y_pos);
4737dd7cddfSDavid du Colombier 			}
4747dd7cddfSDavid du Colombier 		*p &= red;
4757dd7cddfSDavid du Colombier /*		params.x_pos = x; */
4767dd7cddfSDavid du Colombier 		xloc = params.x_pos >> 3;
4777dd7cddfSDavid du Colombier 		params.y_pos++;
4787dd7cddfSDavid du Colombier 	}
4797dd7cddfSDavid du Colombier 	return 0;
4807dd7cddfSDavid du Colombier }
481