xref: /freebsd/lib/libvgl/simple.c (revision 4cf49a43559ed9fdad601bdcccd2c55963008675)
1 /*-
2  * Copyright (c) 1991-1997 S�ren Schmidt
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer
10  *    in this position and unchanged.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software withough specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30 
31 #include <signal.h>
32 #include <machine/console.h>
33 #include "vgl.h"
34 
35 static byte VGLSavePaletteRed[256];
36 static byte VGLSavePaletteGreen[256];
37 static byte VGLSavePaletteBlue[256];
38 
39 #define ABS(a)		(((a)<0) ? -(a) : (a))
40 #define SGN(a)		(((a)<0) ? -1 : 1)
41 
42 
43 void
44 VGLSetXY(VGLBitmap *object, int x, int y, byte color)
45 {
46   VGLCheckSwitch();
47   if (x>=0 && x<object->Xsize && y>=0 && y<object->Ysize) {
48     if (!VGLMouseFreeze(x, y, 1, 1, color)) {
49       switch (object->Type) {
50       case MEMBUF:
51       case VIDBUF8:
52         object->Bitmap[y*object->Xsize+x]=(color);
53         break;
54       case VIDBUF8X:
55         outb(0x3c4, 0x02);
56         outb(0x3c5, 0x01 << (x&0x3));
57 	object->Bitmap[(unsigned)(object->Xsize/2*y)+(x/4)] = (color);
58 	break;
59       case VIDBUF4:
60           outb(0x3c4, 0x02); outb(0x3c5, 0x01);
61           outb(0x3ce, 0x04); outb(0x3cf, 0x00);
62 	  object->Bitmap[(y*object->Xsize/8+x/8)&0xffff] =
63             ( object->Bitmap[(y*object->Xsize/8+x/8)&0xffff] & ~(0x80>>(x%8)) )
64              |  ((color & 0x01) ? (0x80>>(x%8)) : 0);
65           outb(0x3c4, 0x02); outb(0x3c5, 0x02);
66           outb(0x3ce, 0x04); outb(0x3cf, 0x01);
67 	  object->Bitmap[(y*object->Xsize/8+x/8)&0xffff] =
68             ( object->Bitmap[(y*object->Xsize/8+x/8)&0xffff] & ~(0x80>>(x%8)) )
69              |  ((color & 0x02) ? (0x80>>(x%8)) : 0);
70           outb(0x3c4, 0x02); outb(0x3c5, 0x04);
71           outb(0x3ce, 0x04); outb(0x3cf, 0x02);
72 	  object->Bitmap[(y*object->Xsize/8+x/8)&0xffff] =
73             ( object->Bitmap[(y*object->Xsize/8+x/8)&0xffff] & ~(0x80>>(x%8)) )
74              |  ((color & 0x04) ? (0x80>>(x%8)) : 0);
75           outb(0x3c4, 0x02); outb(0x3c5, 0x08);
76           outb(0x3ce, 0x04); outb(0x3cf, 0x03);
77 	  object->Bitmap[(y*object->Xsize/8+x/8)&0xffff] =
78             ( object->Bitmap[(y*object->Xsize/8+x/8)&0xffff] & ~(0x80>>(x%8)) )
79              |  ((color & 0x08) ? (0x80>>(x%8)) : 0);
80       }
81     }
82     VGLMouseUnFreeze();
83   }
84 }
85 
86 byte
87 VGLGetXY(VGLBitmap *object, int x, int y)
88 {
89   VGLCheckSwitch();
90   switch (object->Type) {
91     case MEMBUF:
92     case VIDBUF8:
93       return object->Bitmap[((y*object->Xsize)+x)];
94       break;
95     case VIDBUF8X:
96       outb(0x3ce, 0x04); outb(0x3cf, x & 0x3);
97       return object->Bitmap[(unsigned)(object->Xsize/2*y)+(x/4)];
98       break;
99     case VIDBUF4:
100       return (object->Bitmap[((y*object->Xsize/8)+x/8)]&(0x80>>(x%8))) ? 1 : 0;
101       break;
102   }
103   return 0;
104 }
105 
106 void
107 VGLLine(VGLBitmap *object, int x1, int y1, int x2, int y2, byte color)
108 {
109   int d, x, y, ax, ay, sx, sy, dx, dy;
110 
111   dx = x2-x1; ax = ABS(dx)<<1; sx = SGN(dx); x = x1;
112   dy = y2-y1; ay = ABS(dy)<<1; sy = SGN(dy); y = y1;
113 
114   if (ax>ay) {					/* x dominant */
115     d = ay-(ax>>1);
116     for (;;) {
117       VGLSetXY(object, x, y, color);
118       if (x==x2)
119 	break;
120       if (d>=0) {
121 	y += sy; d -= ax;
122       }
123       x += sx; d += ay;
124     }
125   }
126   else {					/* y dominant */
127     d = ax-(ay>>1);
128     for (;;) {
129       VGLSetXY(object, x, y, color);
130       if (y==y2)
131 	break;
132       if (d>=0) {
133 	x += sx; d -= ay;
134       }
135       y += sy; d += ax;
136     }
137   }
138 }
139 
140 void
141 VGLBox(VGLBitmap *object, int x1, int y1, int x2, int y2, byte color)
142 {
143   VGLLine(object, x1, y1, x2, y1, color);
144   VGLLine(object, x2, y1, x2, y2, color);
145   VGLLine(object, x2, y2, x1, y2, color);
146   VGLLine(object, x1, y2, x1, y1, color);
147 }
148 
149 void
150 VGLFilledBox(VGLBitmap *object, int x1, int y1, int x2, int y2, byte color)
151 {
152   int y;
153 
154   for (y=y1; y<=y2; y++) VGLLine(object, x1, y, x2, y, color);
155 }
156 
157 void
158 inline set4pixels(VGLBitmap *object, int x, int y, int xc, int yc, byte color)
159 {
160   if (x!=0) {
161     VGLSetXY(object, xc+x, yc+y, color);
162     VGLSetXY(object, xc-x, yc+y, color);
163     if (y!=0) {
164       VGLSetXY(object, xc+x, yc-y, color);
165       VGLSetXY(object, xc-x, yc-y, color);
166     }
167   }
168   else {
169     VGLSetXY(object, xc, yc+y, color);
170     if (y!=0)
171       VGLSetXY(object, xc, yc-y, color);
172   }
173 }
174 
175 void
176 VGLEllipse(VGLBitmap *object, int xc, int yc, int a, int b, byte color)
177 {
178   int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b;
179   int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b;
180 
181   while (dx<dy) {
182     set4pixels(object, x, y, xc, yc, color);
183     if (d>0) {
184       y--; dy-=asq2; d-=dy;
185     }
186     x++; dx+=bsq2; d+=bsq+dx;
187   }
188   d+=(3*(asq-bsq)/2-(dx+dy))/2;
189   while (y>=0) {
190     set4pixels(object, x, y, xc, yc, color);
191     if (d<0) {
192       x++; dx+=bsq2; d+=dx;
193     }
194     y--; dy-=asq2; d+=asq-dy;
195   }
196 }
197 
198 void
199 inline set2lines(VGLBitmap *object, int x, int y, int xc, int yc, byte color)
200 {
201   if (x!=0) {
202     VGLLine(object, xc+x, yc+y, xc-x, yc+y, color);
203     if (y!=0)
204       VGLLine(object, xc+x, yc-y, xc-x, yc-y, color);
205   }
206   else {
207     VGLLine(object, xc, yc+y, xc, yc-y, color);
208   }
209 }
210 
211 void
212 VGLFilledEllipse(VGLBitmap *object, int xc, int yc, int a, int b, byte color)
213 {
214   int x = 0, y = b, asq = a*a, asq2 = a*a*2, bsq = b*b;
215   int bsq2 = b*b*2, d = bsq-asq*b+asq/4, dx = 0, dy = asq2*b;
216 
217   while (dx<dy) {
218     set2lines(object, x, y, xc, yc, color);
219     if (d>0) {
220       y--; dy-=asq2; d-=dy;
221     }
222     x++; dx+=bsq2; d+=bsq+dx;
223   }
224   d+=(3*(asq-bsq)/2-(dx+dy))/2;
225   while (y>=0) {
226     set2lines(object, x, y, xc, yc, color);
227     if (d<0) {
228       x++; dx+=bsq2; d+=dx;
229     }
230     y--; dy-=asq2; d+=asq-dy;
231   }
232 }
233 
234 void
235 VGLClear(VGLBitmap *object, byte color)
236 {
237   VGLCheckSwitch();
238   VGLMouseFreeze(0, 0, object->Xsize, object->Ysize, color);
239   switch (object->Type) {
240   case MEMBUF:
241   case VIDBUF8:
242     memset(object->Bitmap, color, object->Xsize*object->Ysize);
243     break;
244   case VIDBUF8X:
245     /* XXX works only for Xsize % 4 = 0 */
246     outb(0x3c4, 0x02); outb(0x3c5, 0x0f);
247     memset(object->Bitmap, color, object->Xsize*object->Ysize/4);
248     break;
249 
250   case VIDBUF4:
251     /* XXX works only for Xsize % 8 = 0 */
252     memset(object->Bitmap, color, object->Xsize/8*object->Ysize);
253     break;
254   }
255   VGLMouseUnFreeze();
256 }
257 
258 void
259 VGLRestorePalette()
260 {
261   int i;
262 
263   outb(0x3C6, 0xFF);
264   inb(0x3DA);
265   outb(0x3C8, 0x00);
266   for (i=0; i<256; i++) {
267     outb(0x3C9, VGLSavePaletteRed[i]);
268     inb(0x84);
269     outb(0x3C9, VGLSavePaletteGreen[i]);
270     inb(0x84);
271     outb(0x3C9, VGLSavePaletteBlue[i]);
272     inb(0x84);
273   }
274   inb(0x3DA);
275   outb(0x3C0, 0x20);
276 }
277 
278 void
279 VGLSavePalette()
280 {
281   int i;
282 
283   outb(0x3C6, 0xFF);
284   inb(0x3DA);
285   outb(0x3C7, 0x00);
286   for (i=0; i<256; i++) {
287     VGLSavePaletteRed[i] = inb(0x3C9);
288     inb(0x84);
289     VGLSavePaletteGreen[i] = inb(0x3C9);
290     inb(0x84);
291     VGLSavePaletteBlue[i] = inb(0x3C9);
292     inb(0x84);
293   }
294   inb(0x3DA);
295   outb(0x3C0, 0x20);
296 }
297 
298 void
299 VGLSetPalette(byte *red, byte *green, byte *blue)
300 {
301   int i;
302 
303   for (i=0; i<256; i++) {
304     VGLSavePaletteRed[i] = red[i];
305     VGLSavePaletteGreen[i] = green[i];
306     VGLSavePaletteBlue[i] = blue[i];
307   }
308   VGLCheckSwitch();
309   outb(0x3C6, 0xFF);
310   inb(0x3DA);
311   outb(0x3C8, 0x00);
312   for (i=0; i<256; i++) {
313     outb(0x3C9, VGLSavePaletteRed[i]);
314     inb(0x84);
315     outb(0x3C9, VGLSavePaletteGreen[i]);
316     inb(0x84);
317     outb(0x3C9, VGLSavePaletteBlue[i]);
318     inb(0x84);
319   }
320   inb(0x3DA);
321   outb(0x3C0, 0x20);
322 }
323 
324 void
325 VGLSetPaletteIndex(byte color, byte red, byte green, byte blue)
326 {
327   VGLSavePaletteRed[color] = red;
328   VGLSavePaletteGreen[color] = green;
329   VGLSavePaletteBlue[color] = blue;
330   VGLCheckSwitch();
331   outb(0x3C6, 0xFF);
332   inb(0x3DA);
333   outb(0x3C8, color);
334   outb(0x3C9, red); outb(0x3C9, green); outb(0x3C9, blue);
335   inb(0x3DA);
336   outb(0x3C0, 0x20);
337 }
338 
339 void
340 VGLSetBorder(byte color)
341 {
342   VGLCheckSwitch();
343   inb(0x3DA);
344   outb(0x3C0,0x11); outb(0x3C0, color);
345   inb(0x3DA);
346   outb(0x3C0, 0x20);
347 }
348 
349 void
350 VGLBlankDisplay(int blank)
351 {
352   byte val;
353 
354   VGLCheckSwitch();
355   outb(0x3C4, 0x01); val = inb(0x3C5); outb(0x3C4, 0x01);
356   outb(0x3C5, ((blank) ? (val |= 0x20) : (val &= 0xDF)));
357 }
358