xref: /plan9/sys/src/cmd/gs/src/gdevpe.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1989, 1990, 1991, 1994, 1996 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gdevpe.c,v 1.4 2002/02/21 22:24:51 giles Exp $*/
18 /*
19  * Private Eye display driver
20  *
21  * Hacked by Fran Taylor, Reflection Technology Inc.
22  */
23 
24 #include "memory_.h"
25 #include "gx.h"
26 #include "gxdevice.h"
27 
28 char *getenv(char *name);
29 
30 typedef struct gx_device_pe_s {
31 	gx_device_common;
32 	byte *fbaddr;
33 	unsigned regs;
34 } gx_device_pe;
35 #define pedev ((gx_device_pe *)dev)
36 
37 typedef struct {
38 	ushort reg, val;
39 } regval;
40 
41 #define XSIZE 720
42 #define YSIZE 280
43 #define BPL 90
44 #define XPPI 160.0
45 #define YPPI 96.0
46 #define DEFAULT_ADDRESS ((byte *) 0xb8000000)
47 #define DEFAULT_REGISTERS 0x3d0
48 
49 dev_proc_open_device(pe_open);
50 dev_proc_close_device(pe_close);
51 dev_proc_fill_rectangle(pe_fill_rectangle);
52 dev_proc_copy_mono(pe_copy_mono);
53 
54 private gx_device_procs pe_procs =
55 {	pe_open,
56 	NULL,			/* get_initial_matrix */
57 	NULL,			/* sync_output */
58 	NULL,			/* output_page */
59 	pe_close,
60 	NULL,			/* map_rgb_color */
61 	NULL,			/* map_color_rgb */
62 	pe_fill_rectangle,
63 	NULL,			/* tile_rectangle */
64 	pe_copy_mono,
65 	NULL			/* copy_color */
66 };
67 
68 gx_device_pe far_data gs_pe_device =
69 {	std_device_std_body(gx_device_pe, &pe_procs, "pe",
70 	  XSIZE, YSIZE, XPPI, YPPI),
71 	 { 0 },		/* std_procs */
72 	DEFAULT_ADDRESS, DEFAULT_REGISTERS
73 };
74 
75 static regval peinit[] = {{0x04, 0x1e}, {0x05, 0x00},
76 			  {0x04, 0x0c}, {0x05, 0x21},
77 			  {0x04, 0x0d}, {0x05, 0x98},
78 			  {0x08, 0x00}, {0x08, 0x1e},
79 			  {0x04, 0x1e}, {0x05, 0x01}};
80 
81 static regval pedone[] = {{0x04, 0x1e}, {0x05, 0x10},
82 			  {0x04, 0x0a}, {0x05, 0x00},
83 			  {0x04, 0x0b}, {0x05, 0x07},
84 			  {0x04, 0x0c}, {0x05, 0x00},
85 			  {0x04, 0x0d}, {0x05, 0x00},
86 			  {0x04, 0x0e}, {0x05, 0x00},
87 			  {0x04, 0x0f}, {0x05, 0x00},
88 			  {0x08, 0x00}, {0x08, 0x29}};
89 
pe_open(gx_device * dev)90 int pe_open(gx_device *dev)
91 {
92 	char *str;
93 	int i;
94 
95 	if ((str = getenv("PEFBADDR")) != 0)
96 	{
97 		if (!sscanf(str, "%lx", &(pedev->fbaddr)))
98 		{
99 			eprintf("Private Eye: PEFBADDR environment string format error\n");
100 			exit(1);
101 		}
102 	}
103 
104 	if ((str = getenv("PEREGS")) != 0)
105 	{
106 		if (!sscanf(str, "%x", &(pedev->regs)))
107 		{
108 			eprintf("Private Eye: PEREGS environment string format error\n");
109 			exit(1);
110 		}
111 	}
112 
113 	for (i = 0; i < 10; i++)
114 		outportb(pedev->regs + peinit[i].reg, peinit[i].val);
115 
116 	return 0;
117 }
118 
pe_close(gx_device * dev)119 int pe_close(gx_device *dev)
120 {
121 	int i;
122 
123 	/* restore the screen */
124 	for (i = 0; i < 16; i++)
125 		outportb(pedev->regs + pedone[i].reg, pedone[i].val);
126 
127 	/* clear the frame buffer */
128 	memset(pedev->fbaddr, 0, 4000);
129 
130 	return 0;
131 }
132 
pe_fill_rectangle(gx_device * dev,int x1,int y1,int w,int h,gx_color_index color)133 int pe_fill_rectangle(gx_device *dev, int x1, int y1, int w, int h,
134                       gx_color_index color)
135 {
136 	int x2, y2, xlen;
137 	byte led, red, d;
138 	byte *ptr;
139 
140 	/* cull */
141 
142 	if ((w <= 0) || (h <= 0) || (x1 > XSIZE) || (y1 > YSIZE))
143 		return 0;
144 
145 	x2 = x1 + w - 1;
146 	y2 = y1 + h - 1;
147 
148 	/* cull some more */
149 
150 	if ((x2 < 0) || (y2 < 0))
151 		return 0;
152 
153 	/* clip */
154 
155 	if (x1 < 0) x1 = 0;
156 	if (x2 > XSIZE-1) x2 = XSIZE-1;
157 	if (y1 < 0) y1 = 0;
158 	if (y2 > YSIZE-1) y2 = YSIZE-1;
159 
160 	w = x2 - x1 + 1;
161 	h = y2 - y1 + 1;
162 	xlen = (x2 >> 3) - (x1 >> 3) - 1;
163 	led = 0xff >> (x1 & 7);
164 	red = 0xff << (7 - (x2 & 7));
165 
166 	ptr = pedev->fbaddr + (y1 * BPL) + (x1 >> 3);
167 
168 	if (color)
169 	{
170 		/* here to set pixels */
171 
172 		if (xlen == -1)
173 		{
174 			/* special for rectangles that fit in a byte */
175 
176 			d = led & red;
177 			for(; h >= 0; h--, ptr += BPL)
178 				*ptr |= d;
179 			return 0;
180 		}
181 
182 		/* normal fill */
183 
184 		for(; h >= 0; h--, ptr += BPL)
185 		{	register int x = xlen;
186 			register byte *p = ptr;
187 			*p++ |= led;
188 			while ( x-- ) *p++ = 0xff;
189 			*p |= red;
190 		}
191 	}
192 
193 	/* here to clear pixels */
194 
195 	led = ~led;
196 	red = ~red;
197 
198 	if (xlen == -1)
199 	{
200 		/* special for rectangles that fit in a byte */
201 
202 		d = led | red;
203 		for(; h >= 0; h--, ptr += BPL)
204 			*ptr &= d;
205 		return 0;
206 	}
207 
208 	/* normal fill */
209 
210 	for(; h >= 0; h--, ptr += BPL)
211 	{	register int x = xlen;
212 		register byte *p = ptr;
213 		*p++ &= led;
214 		while ( x-- ) *p++ = 0x00;
215 		*p &= red;
216 	}
217 	return 0;
218 }
219 
pe_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 zero,gx_color_index one)220 int pe_copy_mono(gx_device *dev,
221 		 const byte *base, int sourcex, int raster, gx_bitmap_id id,
222                  int x, int y, int w, int h,
223 		 gx_color_index zero, gx_color_index one)
224 {
225 	const byte *line;
226 	int sleft, dleft;
227 	int mask, rmask;
228 	int invert, zmask, omask;
229 	byte *dest;
230 	int offset;
231 
232 #define izero (int)zero
233 #define ione (int)one
234 
235 if ( ione == izero )		/* vacuous case */
236 		return pe_fill_rectangle(dev, x, y, w, h, zero);
237 
238 	/* clip */
239 
240 	if ((x > XSIZE) || (y > YSIZE) || ((x + w) < 0) || ((y + h) < 0))
241 		return 0;
242 
243 	offset = x >> 3;
244 	dest = pedev->fbaddr + (y * BPL) + offset;
245 	line = base + (sourcex >> 3);
246 	sleft = 8 - (sourcex & 7);
247 	dleft = 8 - (x & 7);
248 	mask = 0xff >> (8 - dleft);
249 	if ( w < dleft )
250 		mask -= mask >> w;
251 	else
252 		rmask = 0xff00 >> ((w - dleft) & 7);
253 
254 	/* Macros for writing partial bytes. */
255 	/* bits has already been inverted by xor'ing with invert. */
256 
257 #define write_byte_masked(ptr, bits, mask)\
258   *ptr = ((bits | ~mask | zmask) & *ptr | (bits & mask & omask))
259 
260 #define write_byte(ptr, bits)\
261   *ptr = ((bits | zmask) & *ptr | (bits & omask))
262 
263 /*	if ( dev->invert )
264 	{
265 		if ( izero != (int)gx_no_color_index ) zero ^= 1;
266 		if ( ione != (int)gx_no_color_index ) one ^= 1;
267 	} */
268 	invert = (izero == 1 || ione == 0 ? -1 : 0);
269 	zmask = (izero == 0 || ione == 0 ? 0 : -1);
270 	omask = (izero == 1 || ione == 1 ? -1 : 0);
271 
272 #undef izero
273 #undef ione
274 
275 	if (sleft == dleft)		/* optimize the aligned case */
276 	{
277 		w -= dleft;
278 		while ( --h >= 0 )
279 		{
280 			register const byte *bptr = line;
281 			int count = w;
282 			register byte *optr = dest;
283 			register int bits = *bptr ^ invert;	/* first partial byte */
284 
285 			write_byte_masked(optr, bits, mask);
286 
287 			/* Do full bytes. */
288 
289 			while ((count -= 8) >= 0)
290 			{
291 				bits = *++bptr ^ invert;
292 				++optr;
293 				write_byte(optr, bits);
294 			}
295 
296 			/* Do last byte */
297 
298 			if (count > -8)
299 			{
300 				bits = *++bptr ^ invert;
301 				++optr;
302 				write_byte_masked(optr, bits, rmask);
303 			}
304 			dest += BPL;
305 			line += raster;
306 		}
307 	}
308 	else
309 	{
310 		int skew = (sleft - dleft) & 7;
311 		int cskew = 8 - skew;
312 
313 		while (--h >= 0)
314 		{
315 			const byte *bptr = line;
316 			int count = w;
317 			byte *optr = dest;
318 			register int bits;
319 
320 			/* Do the first partial byte */
321 
322 			if (sleft >= dleft)
323 			{
324 				bits = *bptr >> skew;
325 			}
326 			else /* ( sleft < dleft ) */
327 			{
328 				bits = *bptr++ << cskew;
329 				if (count > sleft)
330 					bits += *bptr >> skew;
331 			}
332 			bits ^= invert;
333 			write_byte_masked(optr, bits, mask);
334 			count -= dleft;
335 			optr++;
336 
337 			/* Do full bytes. */
338 
339 			while ( count >= 8 )
340 			{
341 				bits = *bptr++ << cskew;
342 				bits += *bptr >> skew;
343 				bits ^= invert;
344 				write_byte(optr, bits);
345 				count -= 8;
346 				optr++;
347 			}
348 
349 			/* Do last byte */
350 
351 			if (count > 0)
352 			{
353 				bits = *bptr++ << cskew;
354  				if (count > skew)
355 					bits += *bptr >> skew;
356 				bits ^= invert;
357 				write_byte_masked(optr, bits, rmask);
358 			}
359 			dest += BPL;
360 			line += raster;
361 		}
362 	}
363 	return 0;
364 }
365