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