1 /*************************************************************************
2  MFB graphics and miscellaneous library
3  Copyright (c) Stephen R. Whiteley 1992
4  Author: Stephen R. Whiteley
5  *************************************************************************/
6 
7 #include "mfb.h"
8 #include "mfbP.h"
9 #include <dos.h>
10 
11 /* in real mode, the mode_?_... functions are used in the dp driver */
12 #ifdef __STDC__
13 extern void mode_1_mark(int,int);
14 extern void mode_2_mark(int,int);
15 extern void mode_1_clear(int,int);
16 extern void mode_2_clear(int,int);
17 #else
18 extern void mode_1_mark();
19 extern void mode_2_mark();
20 extern void mode_1_clear();
21 extern void mode_2_clear();
22 #endif
23 
24 
25 void
MFBDrawCursor(x,y)26 MFBDrawCursor(x,y)
27 
28 /* draw cursor */
29 int x,y;
30 {
31     int oldalu;
32 
33     if (pc.drawghost) {
34         /* draw any rubber-banding */
35         oldalu = pc.alumode;
36         pc.alumode = 0x1803;
37         (*pc.drawghost)(x+8,y-7,pc.refx,pc.refy);
38         pc.alumode = oldalu;
39     }
40     if (pc.mfbMODE & 2)
41         mode_2_mark(x,y);
42     else
43         mode_1_mark(x,y);
44 }
45 
46 
47 void
MFBEraseCursor(x,y)48 MFBEraseCursor(x,y)
49 
50 /* erase cursor */
51 int x,y;
52 {
53     int oldalu;
54 
55     if (pc.mfbMODE & 2)
56         mode_2_clear(x,y);
57     else
58         mode_1_clear(x,y);
59     if (pc.drawghost) {
60         /* undraw any rubber-banding */
61         oldalu = pc.alumode;
62         pc.alumode = 0x1803;
63         (*pc.drawghost)(x+8,y-7,pc.refx,pc.refy);
64         pc.alumode = oldalu;
65     }
66 }
67 
68 
69 void
mode_1_mark(x,y)70 mode_1_mark(x,y)
71 
72 /* display cursor 16 color modes */
73 int x, y;
74 {
75     int i, j, next;
76     unsigned short *amap, *xmap;
77     unsigned char bitmask, mode, datarot, esetreset, cdontcare;
78     unsigned char readplane, planemask, rem, *px;
79     vidmptr rgen, rgen0;
80     union {long l; unsigned short i; char s[4]; } afld, xfld;
81     int stop;
82 
83     outp(0x3ce,0x5);        /* read mode 0, write mode 0 */
84     mode = inp(0x3cf);
85     outp(0x3cf,0);
86 
87     outp(0x3ce,0x4);        /* read plane */
88     readplane = inp(0x3cf);
89 
90     amap = (unsigned short *) vgacur.map;
91     xmap = amap + 16;
92 
93     px = vgacur.pbs;
94 
95     rem = x & 7;
96     x >>= 3;
97     next = pc.bytpline;
98     rgen0 = pc.base + x + (long) (pc.ysize-1-y)*next;
99     stop = 16;
100     while (rgen0 < pc.base) {
101         rgen0 += next;
102         amap++;
103         xmap++;
104         stop--;
105     }
106     next -= 2;
107 
108     /* store background */
109     for (j = 0; j < 4; j++) {
110         rgen = rgen0;
111         outp(0x3cf,j);     /* read plane select */
112         for (i = 0; i < stop; i++) {
113             *px++ = *rgen++;
114             *px++ = *rgen++;
115             *px++ = *rgen;
116             rgen += next;
117         }
118         px += 16;
119     }
120     next += 2;
121 
122     outp(0x3c4,0x2);        /* write plane enable */
123     planemask = inp(0x3c5);
124 
125     outp(0x3ce,0x1);        /* enable set reset */
126     esetreset = inp(0x3cf);
127     outp(0x3cf,0x0);
128 
129     outp(0x3ce,0x8);        /* bit mask */
130     bitmask = inp(0x3cf);
131     outp(0x3cf,0xff);
132 
133     outp(0x3ce,0x7);        /* color dont care */
134     cdontcare = inp(0x3cf);
135     outp(0x3cf,0x00);
136 
137     outp(0x3ce,0x5);        /* read mode 1, write mode 0 */
138     outp(0x3cf,8);
139 
140     outp(0x3ce,0x3);        /* data rotate */
141     datarot = inp(0x3cf);
142 
143     rgen = rgen0;
144 
145     for (i = 0; i < stop; i++) {
146         afld.i = *(amap++);
147         afld.s[2] = 0xff;
148         afld.l <<=  8-rem;
149         afld.s[0] |= 0xff >> rem;
150 
151         xfld.i = *(xmap++);
152         xfld.s[2] = 0;
153         xfld.l <<= 8-rem;
154 
155         /* xcnt is unsigned */
156         if ((unsigned) x+2 >= next) {
157             afld.s[0] = 0xff;
158             xfld.s[0] = 0x0;
159         }
160         if ((unsigned) x+1 >= next) {
161             afld.s[1] = 0xff;
162             xfld.s[1] = 0x0;
163         }
164         if ((unsigned) x   >= next) {
165             afld.s[2] = 0xff;
166             xfld.s[2] = 0x0;
167         }
168 
169         outp(0x3c5,0xf);
170         outp(0x3cf,0x08); /* AND */
171         *rgen &= afld.s[2];
172         rgen++;
173         *rgen &= afld.s[1];
174         rgen++;
175         *rgen &= afld.s[0];
176         rgen -= 2;
177 
178         outp(0x3c5,pc.cursor_color);
179         outp(0x3cf,0x18); /* XOR */
180         *rgen &= xfld.s[2];
181         rgen++;
182         *rgen &= xfld.s[1];
183         rgen++;
184         *rgen &= xfld.s[0];
185         rgen += next - 2;
186     }
187     outp(0x3c5,planemask);
188     outp(0x3ce,0x1); outp(0x3cf,esetreset); /* enable set reset */
189     outp(0x3ce,0x3); outp(0x3cf,datarot);   /* data rotate */
190     outp(0x3ce,0x4); outp(0x3cf,readplane); /* read plane */
191     outp(0x3ce,0x5); outp(0x3cf,mode);      /* write mode */
192     outp(0x3ce,0x7); outp(0x3cf,cdontcare); /* color dont care */
193     outp(0x3ce,0x8); outp(0x3cf,bitmask);   /* bit mask */
194 }
195 
196 
197 #ifndef __GNUC__
198 
199 
200 void
mode_2_mark(x,y)201 mode_2_mark(x,y)
202 
203 /* display cursor 256 color modes */
204 int x, y;
205 {
206     int i, j, next;
207     unsigned short xcnt, *amap, *xmap;
208     unsigned char cbuf, pix, color, segsel, *px;
209     union {long l; unsigned short i; char s[4]; } afld, xfld;
210     union { unsigned short o[2]; long l; } p1;
211 
212     segsel = inp(0x3cd);        /* Tseng Labs segment selector */
213 
214     amap = (unsigned short *) vgacur.map;
215     xmap = amap + 16;
216 
217     px = vgacur.pbs;
218     next = pc.xsize;
219     p1.l = x + (long) (pc.ysize-1-y)*next;
220 
221     cbuf = p1.o[1];
222     outp(0x3cd,(cbuf << 4) | cbuf);
223     color = pc.cursor_color;
224     outpw(0x3ce,0x3); /* set alu mode */
225 
226     j = x;
227     i = 16;
228     while (i--) {
229 
230         afld.i = *(amap++);
231         xfld.i = *(xmap++);
232 
233         xcnt = 0x8000;
234         while (xcnt) {
235             if (p1.o[1] != cbuf) {
236                 cbuf = p1.o[1];
237                 outp(0x3cd,(cbuf << 4) | cbuf);
238             }
239             pix = *(pc.base + p1.o[0]);
240             *px++ = pix;
241             if (j < 0 || j >= next)
242                 goto skip;
243             if (afld.i & xfld.i & xcnt)
244                 *(pc.base+p1.o[0]) = color ^ pix;
245             else if (~afld.i & xfld.i & xcnt)
246                 *(pc.base+p1.o[0]) = color;
247             else if (~afld.i & ~xfld.i & xcnt)
248                 *(pc.base+p1.o[0]) = 0;
249 skip:
250             p1.l++;
251             j++;
252             xcnt >>= 1;
253         }
254         j -= 16;
255         p1.l += next - 16;
256     }
257     outp(0x3cd,segsel);
258 }
259 
260 
261 #else /* __GNUC__ */
262 
263 
264 void
mode_2_mark(x,y)265 mode_2_mark(x,y)
266 
267 /* display cursor 256 color modes */
268 int x, y;
269 {
270     int i, next;
271     unsigned short xcnt, *amap, *xmap;
272     unsigned char pix, color, *px;
273     union {long l; unsigned short i; char s[4]; } afld, xfld;
274     vidmptr rgen;
275 
276     amap = (unsigned short *) vgacur.map;
277     xmap = amap + 16;
278 
279     px = vgacur.pbs;
280     next = pc.xsize;
281     rgen = pc.base + x + (long) (pc.ysize-1-y)*next;
282 
283     color = pc.cursor_color;
284     outpw(0x3ce,0x3); /* set alu mode */
285 
286     i = 16;
287     while (i--) {
288 
289         afld.i = *(amap++);
290         xfld.i = *(xmap++);
291 
292         xcnt = 0x8000;
293         while (xcnt) {
294 
295             if (rgen >= pc.base) {
296                 pix = *rgen;
297                 if (x >= 0 && x < next) {
298                     if (afld.i & xfld.i & xcnt)
299                         *rgen = color ^ pix;
300                     else if (~afld.i & xfld.i & xcnt)
301                         *rgen = color;
302                     else if (~afld.i & ~xfld.i & xcnt)
303                         *rgen = 0;
304                 }
305                 *px++ = pix;
306             }
307             else
308                 *px++ = 0;
309             rgen++;
310             x++;
311             xcnt >>= 1;
312         }
313         x -= 16;
314         rgen += next - 16;
315     }
316 }
317 
318 
319 #endif /* __GNUC__ */
320 
321 
322 void
mode_1_clear(x,y)323 mode_1_clear(x,y)
324 
325 /* overwrite cursor 16 color modes */
326 int x, y;
327 {
328     int i, next;
329     unsigned char bitmask, mode, datarot, esetreset, planemask, rem, *px;
330     vidmptr rgen, rgen0;
331     int stop;
332 
333     outp(0x3ce,0x5);
334     mode = inp(0x3cf);
335     outp(0x3cf,0x0);         /* write mode 0 */
336 
337     outp(0x3ce,0x3);
338     datarot = inp(0x3cf);
339     outp(0x3cf,0x0);         /* straight thru */
340 
341     outp(0x3ce,0x1);
342     esetreset = inp(0x3cf);
343     outp(0x3cf,0x0);         /* enable set reset */
344 
345     outp(0x3ce,0x8);
346     bitmask = inp(0x3cf);
347     outp(0x3cf,0xff);        /* bit mask */
348 
349     outp(0x3c4,0x2);
350     planemask = inp(0x3c5);
351 
352     px = vgacur.pbs;
353 
354     next = pc.bytpline;
355     rgen0 = pc.base + (x >> 3) + (long) (pc.ysize-y-1)*next;
356     stop = 16;
357     while (rgen0 < pc.base) {
358         rgen0 += next;
359         stop--;
360     }
361     next -= 2;
362 
363     rem = 1;
364     while (rem & 0xf) {
365         rgen = rgen0;
366         outp(0x3c5,rem); /* write plane select */
367         for (i = 0; i < stop; i++) {
368 
369             *rgen++ = *px++;
370             *rgen++ = *px++;
371             *rgen   = *px++;
372 
373             rgen += next;
374         }
375         px += 16;
376         rem <<= 1;
377     }
378 
379     outp(0x3c5,planemask);                  /* write plane */
380     outp(0x3ce,0x1); outp(0x3cf,esetreset); /* enable set reset */
381     outp(0x3ce,0x3); outp(0x3cf,datarot);   /* data rotate */
382     outp(0x3ce,0x5); outp(0x3cf,mode);      /* write mode */
383     outp(0x3ce,0x8); outp(0x3cf,bitmask);   /* bit mask */
384 }
385 
386 
387 #ifndef __GNUC__
388 
389 
390 void
mode_2_clear(x,y)391 mode_2_clear(x,y)
392 
393 /* overwrite cursor 256 color modes */
394 int x, y;
395 {
396     int i, j, next;
397     unsigned char segsel, cbuf, *px;
398     union { unsigned short o[2]; long l; } p1;
399 
400     segsel = inp(0x3cd);        /* Tseng Labs segment selector */
401 
402     px = vgacur.pbs;
403 
404     next = pc.xsize;
405     p1.l = x + (long) (pc.ysize-1-y)*next;
406     next -= 16;
407 
408     outp(0x3cd,cbuf = p1.o[1]);
409     outpw(0x3ce,0x3); /* set alu mode */
410     for (i = 0; i < 16; i++) {
411         for (j = 0; j < 16; j++) {
412             if (cbuf != p1.o[1])
413                 outp(0x3cd,cbuf = p1.o[1]);
414             *(pc.base + p1.o[0]) = *px++;
415             p1.l++;
416         }
417         p1.l += next;
418     }
419     outp(0x3cd,segsel);
420 }
421 
422 
423 #else /* __GNUC__ */
424 
425 
426 void
mode_2_clear(x,y)427 mode_2_clear(x,y)
428 
429 /* overwrite cursor 256 color modes */
430 int x, y;
431 {
432     int i, j, next;
433     unsigned char *px;
434     vidmptr rgen;
435 
436     px = vgacur.pbs;
437     next = pc.xsize;
438     rgen = pc.base + x + (long) (pc.ysize-1-y)*next;
439     next -= 16;
440 
441     outpw(0x3ce,0x3); /* set alu mode */
442 
443     i = 16;
444     while (i--) {
445         j = 16;
446         while (j--) {
447             if (rgen >= pc.base)
448                 *rgen = *px;
449             px++;
450             rgen++;
451         }
452         rgen += next;
453     }
454 }
455 
456 #endif /* __GNUC__ */
457