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 #define ror(x,n) ((x >> n)  | (x << (8-n)))
12 
13 #ifdef __STDC__
14 static void mode_1_line(int,int);
15 static void mode_2_line(int,int);
16 #else
17 static void mode_1_line();
18 static void mode_2_line();
19 #endif
20 
21 
22 void
MFBLine(x0,y0,x1,y1)23 MFBLine(x0,y0,x1,y1)
24 
25 int x0, y0, x1, y1;
26 {
27     pc.curx = x0;
28     pc.cury = y0;
29     if (pc.mfbMODE & 2)
30         mode_2_line(x1,y1);
31     else
32         mode_1_line(x1,y1);
33 }
34 
35 
36 void
MFBDrawLineTo(x,y)37 MFBDrawLineTo(x,y)
38 
39 int x, y;
40 {
41     if (pc.mfbMODE & 2)
42         mode_2_line(x,y);
43     else
44         mode_1_line(x,y);
45 }
46 
47 
48 void
MFBMoveTo(x,y)49 MFBMoveTo(x,y)
50 
51 int x, y;
52 {
53     pc.curx = x;
54     pc.cury = y;
55 }
56 
57 
58 int
MFBSetLineStyle(style)59 MFBSetLineStyle(style)
60 
61 int style;
62 {
63     if ((style < 0) || (style >= NSTYLES))
64         return (MFBBADLST);
65     pc.curstyle = style;
66     return (MFBOK);
67 }
68 
69 
70 int
MFBDefineLineStyle(num,mask)71 MFBDefineLineStyle(num, mask)
72 
73 int num, mask;
74 {
75     if ((num < 0) || (num >= NSTYLES))
76         return (MFBBADLST);
77     if (num == 0) return (MFBOK);
78     pc.linestyles[num] = (unsigned char) mask;
79     pc.curstyle = num;
80     return (MFBOK);
81 }
82 
83 
84 static void
mode_1_line(x,y)85 mode_1_line(x,y)
86 int x, y;
87 {
88     int xl, yl, dx, dy, dy2, errterm = 0, next, lcnt;
89     vidmptr rgen;
90     unsigned char cbuf, left, right;
91     union { unsigned short color2; unsigned char c[2]; } c;
92 
93     xl = pc.curx;
94     yl = pc.cury;
95     pc.curx = x;
96     pc.cury = y;
97 
98     c.c[0] = pc.curcolor;
99     c.c[1] = c.c[0];
100 
101     outpw(0x3ce,0x0b05); /* read mode 1, write mode 3 */
102     outpw(0x3ce,c.color2 & 0xff00); /* set/reset */
103     outpw(0x3ce,0x7); /* zero color dont care */
104     outpw(0x3ce,pc.alumode); /* set alu mode */
105 
106     if (y == yl) {
107         if (x < xl) MFBSwapInt(x,xl);
108         x++;
109         left  =  (0xff >> (xl & 7));
110         right = ~(0xff >> (x & 7));
111         dx    = (x >> 3) - (xl >>= 3) - 1;
112         if (dx < 0) { left &= right; dx = 0; right = 0; }
113         rgen = pc.base + xl + (long) (pc.ysize-1-y)*pc.bytpline;
114 
115         cbuf = 0xff;
116         if (pc.curstyle) {
117             cbuf = pc.linestyles[pc.curstyle];
118             left &= cbuf;
119             right &= cbuf;
120         }
121         mfb_trash = *rgen;
122         *rgen = left;
123         rgen++;
124         while (dx--) {
125             mfb_trash = *rgen;
126             *rgen = cbuf;
127             rgen++;
128         }
129         mfb_trash = *rgen;
130         *rgen = right;
131 
132         goto done;
133     }
134 
135     if (x == xl) {
136 
137         if (y < yl) MFBSwapInt(y,yl);
138         yl--;
139         dy = y - yl;
140 
141         cbuf = 0x80 >> (xl & 7);
142 
143         next = pc.bytpline;
144 
145         if (!pc.curstyle) {
146             rgen = pc.base + (x >> 3) + (long) (pc.ysize-1-y)*next;
147             while (dy--) {
148                 mfb_trash = *rgen;
149                 *rgen = cbuf;
150                 rgen += next;
151             }
152         }
153         else {
154             lcnt = pc.ysize-1-y;
155             rgen = pc.base + (x >> 3) + (long) lcnt*next;
156             left = 0x80 >> ((lcnt+xl) & 7);
157             right = pc.linestyles[pc.curstyle];
158 
159             while (dy--) {
160                 if (left & right) {
161                     mfb_trash = *rgen;
162                     *rgen = cbuf;
163                 }
164                 left = ror(left,1);
165                 rgen += next;
166             }
167         }
168         goto done;
169     }
170 
171     if (x < xl) {
172         MFBSwapInt(xl,x);
173         MFBSwapInt(yl,y);
174     }
175     dx = x - xl;
176 
177     next = pc.bytpline;
178     dy = yl - y;
179 
180     if (!pc.curstyle) {
181         rgen = pc.base + (xl >> 3) + (long) (pc.ysize-1-yl)*next;
182         if (yl < y) {
183             next = -next;
184             dy = -dy;
185         }
186 
187         cbuf = 0x80 >> (xl & 7);
188 
189         dy2 = dy;
190         dy++;
191         while (dy--) {
192             errterm += dx;
193             if (errterm <= 0) {
194                 mfb_trash = *rgen;
195                 *rgen = cbuf;
196                 rgen += next;
197                 continue;
198             }
199             while (errterm > 0 && xl <= x) {
200                 mfb_trash = *rgen;
201                 *rgen = cbuf;
202                 cbuf = ror(cbuf,1);
203                 if (cbuf & 0x80) rgen++;
204                 xl++;
205                 errterm -= dy2;
206             }
207             rgen += next;
208         }
209     }
210     else {
211         lcnt = pc.ysize-1-yl;
212         rgen = pc.base + (xl >> 3) + (long) lcnt*next;
213         left = 0x80 >> ((lcnt+xl) & 7);
214         right = pc.linestyles[pc.curstyle];
215 
216         if (yl < y) {
217             next = -next;
218             dy = -dy;
219         }
220 
221         cbuf = 0x80 >> (xl & 7);
222 
223         dy2 = dy;
224         dy++;
225         while (dy--) {
226             errterm += dx;
227             if (errterm <= 0) {
228                 if (left & right) {
229                     mfb_trash = *rgen;
230                     *rgen = cbuf;
231                 }
232                 rgen += next;
233                 left = ror(left,1);
234                 continue;
235             }
236             while (errterm > 0 && xl <= x) {
237                 if (left & right) {
238                     mfb_trash = *rgen;
239                     *rgen = cbuf;
240                 }
241                 left = ror(left,1);
242                 cbuf = ror(cbuf,1);
243                 if (cbuf & 0x80) rgen++;
244                 xl++;
245                 errterm -= dy2;
246             }
247             rgen += next;
248             left = ror(left,1);
249         }
250     }
251 done:
252     outpw(0x3ce,0xff07);
253     outpw(0x3ce,0x5);
254 }
255 
256 
257 #ifndef __GNUC__
258 
259 
260 static void
mode_2_line(x,y)261 mode_2_line(x,y)
262 int x, y;
263 {
264     int xl, yl, dy, dy2, errterm = 0, next, lcnt;
265     unsigned short dx;
266     unsigned char cbuf, left, right;
267     union { unsigned short o[2]; long l; } p1, p2;
268     union { unsigned short color2; unsigned char c[2]; } c;
269     vidmptr rgen;
270 
271     xl = pc.curx;
272     yl = pc.cury;
273     pc.curx = x;
274     pc.cury = y;
275 
276     c.c[0] = pc.curcolor;
277     c.c[1] = c.c[0];
278 
279     outpw(0x3ce,0xff08);     /* set bit mask */
280     outpw(0x3ce,pc.alumode); /* set alu mode */
281 
282     if (y == yl) {
283         if (x < xl) MFBSwapInt(x,xl);
284         x++;
285         dx = x - xl;
286         p1.l = xl + (long) (pc.ysize-1-y)*pc.xsize;
287         p2.l = p1.l + dx;
288         if (p1.o[1] != p2.o[1])
289             dx = ~(p1.o[0]) + 1;
290         cbuf = p1.o[1];
291         cbuf |= (cbuf << 4);
292         outp(0x3cd,cbuf);
293         rgen = pc.base + p1.o[0];
294 
295         if (!pc.curstyle) {
296 
297             if (pc.alumode == 0x3) {
298                 if ((unsigned)rgen & 1) {
299                     *rgen = c.c[0];
300                     rgen++;
301                     dx--;
302                 }
303                 if (dx & 1)
304                     *(rgen + dx - 1) = c.c[0];
305                 dx >>= 1;
306                 while (dx--) {
307                     *(short far *)rgen = c.color2;
308                     rgen += 2;
309                 }
310             }
311             else {
312                 while (dx--) {
313                     mfb_trash = *rgen;
314                     *rgen = c.c[0];
315                     rgen++;
316                 }
317             }
318 
319             if (p1.o[1] != p2.o[1]) {
320                 outp(0x3cd,cbuf + 0x11);
321                 dx = p2.o[0];
322                 rgen = pc.base;
323                 if (pc.alumode == 0x3) {
324                     if (dx & 1)
325                         *(rgen + dx - 1) = c.c[0];
326                     dx >>= 1;
327                     while (dx--) {
328                         *(short far *)rgen = c.color2;
329                         rgen += 2;
330                     }
331                 }
332                 else {
333                     while (dx--) {
334                         mfb_trash = *rgen;
335                         *rgen = c.c[0];
336                         rgen++;
337                     }
338                 }
339             }
340         }
341         else {
342 
343             lcnt = pc.ysize-1-y;
344             p1.l = xl + (long) lcnt*pc.xsize;
345             left = 0x80 >> ((lcnt+xl) & 7);
346             right = pc.linestyles[pc.curstyle];
347 
348             while (dx--) {
349                 if (left & right) {
350                     if (pc.alumode != 3)
351                         mfb_trash = *rgen;
352                     *rgen = c.c[0];
353                 }
354                 left = ror(left,1);
355                 rgen++;
356             }
357 
358             if (p1.o[1] != p2.o[1]) {
359                 outp(0x3cd,cbuf + 0x11);
360                 dx = p2.o[0];
361                 rgen = pc.base;
362                 while (dx--) {
363                     if (left & right) {
364                         if (pc.alumode != 3)
365                             mfb_trash = *rgen;
366                         *rgen = c.c[0];
367                     }
368                     left = ror(left,1);
369                     rgen++;
370                 }
371             }
372         }
373         return;
374     }
375 
376 
377     if (x == xl) {
378         if (y < yl) MFBSwapInt(y,yl);
379         yl--;
380         dy = y - yl;
381         next = pc.xsize;
382         lcnt = pc.ysize-1-y;
383         p1.l = xl + (long) lcnt*next;
384         cbuf = p1.o[1];
385         cbuf |= (cbuf << 4);
386         outp(0x3cd,cbuf);
387 
388         if (!pc.curstyle) {
389             while (dy--) {
390                 rgen = pc.base + p1.o[0];
391                 if (pc.alumode != 3)
392                     mfb_trash = *rgen;
393                 *rgen = c.c[0];
394                 p1.l += next;
395                 if ((cbuf & 0xf) != p1.o[1]) {
396                     cbuf += 0x11;
397                     outp(0x3cd,cbuf);
398                 }
399             }
400         }
401         else {
402             left = 0x80 >> ((lcnt+xl) & 7);
403             right = pc.linestyles[pc.curstyle];
404 
405             while (dy--) {
406                 rgen = pc.base + p1.o[0];
407                 if (left & right) {
408                     if (pc.alumode != 3)
409                         mfb_trash = *rgen;
410                     *rgen = c.c[0];
411                 }
412                 left = ror(left,1);
413                 p1.l += next;
414                 if ((cbuf & 0xf) != p1.o[1]) {
415                     cbuf += 0x11;
416                     outp(0x3cd,cbuf);
417                 }
418             }
419         }
420         return;
421     }
422 
423     cbuf = inp(0x3cd);
424     cbuf |= (cbuf << 4);
425 
426     if (x < xl) {
427         MFBSwapInt(xl,x);
428         MFBSwapInt(yl,y);
429     }
430     dx = x - xl;
431 
432     next = pc.xsize;
433     dy = yl - y;
434 
435     if (!pc.curstyle) {
436         p1.l = xl + (long) (pc.ysize-1-yl)*next;
437 
438         if (yl < y) {
439             next = -next;
440             dy = -dy;
441         }
442 
443         dy2 = dy;
444         dy++;
445         while (dy--) {
446             errterm += dx;
447             if (errterm <= 0) {
448                 if ((cbuf & 0xf) != p1.o[1]) {
449                     cbuf = p1.o[1];
450                     cbuf |= (cbuf << 4);
451                     outp(0x3cd,cbuf);
452                 }
453                 if (pc.alumode != 3)
454                     mfb_trash = *(pc.base + p1.o[0]);
455                 *(pc.base + p1.o[0]) = c.c[0];
456                 p1.l += next;
457                 continue;
458             }
459             while (errterm > 0 && xl <= x) {
460                 if ((cbuf & 0xf) != p1.o[1]) {
461                     cbuf = p1.o[1];
462                     cbuf |= (cbuf << 4);
463                     outp(0x3cd,cbuf);
464                 }
465                 if (pc.alumode != 3)
466                     mfb_trash = *(pc.base + p1.o[0]);
467                 *(pc.base + p1.o[0]) = c.c[0];
468                 p1.l++;
469                 xl++;
470                 errterm -= dy2;
471             }
472             p1.l += next;
473 
474         }
475     }
476     else {
477         lcnt = pc.ysize-1-yl;
478         p1.l = xl + (long) lcnt*next;
479         left = 0x80 >> ((lcnt+xl) & 7);
480         right = pc.linestyles[pc.curstyle];
481 
482         if (yl < y) {
483             next = -next;
484             dy = -dy;
485         }
486 
487         dy2 = dy;
488         dy++;
489         while (dy--) {
490 
491             errterm += dx;
492             if (errterm <= 0) {
493                 if (left & right) {
494                     if ((cbuf & 0xf) != p1.o[1]) {
495                         cbuf = p1.o[1];
496                         cbuf |= (cbuf << 4);
497                         outp(0x3cd,cbuf);
498                     }
499                     if (pc.alumode != 3)
500                         mfb_trash = *(pc.base + p1.o[0]);
501                     *(pc.base + p1.o[0]) = c.color2;
502                 }
503                 p1.l += next;
504                 left = ror(left,1);
505                 continue;
506             }
507             while (errterm > 0 && xl <= x) {
508                 if (left & right) {
509                     if ((cbuf & 0xf) != p1.o[1]) {
510                         cbuf = p1.o[1];
511                         cbuf |= (cbuf << 4);
512                         outp(0x3cd,cbuf);
513                     }
514                     if (pc.alumode != 3)
515                         mfb_trash = *(pc.base + p1.o[0]);
516                     *(pc.base + p1.o[0]) = c.color2;
517                 }
518                 left = ror(left,1);
519                 p1.l++;
520                 xl++;
521                 errterm -= dy2;
522             }
523             p1.l += next;
524             left = ror(left,1);
525 
526         }
527     }
528 }
529 
530 
531 #else /* __GNUC__ */
532 
533 
534 static void
mode_2_line(x,y)535 mode_2_line(x,y)
536 int x, y;
537 {
538     int xl, yl, dx, dy, dy2, errterm = 0, next, lcnt;
539     unsigned left, right;
540     union { unsigned short color2; unsigned char c[2]; } c;
541     vidmptr rgen;
542 
543     xl = pc.curx;
544     yl = pc.cury;
545     pc.curx = x;
546     pc.cury = y;
547 
548     c.c[0] = pc.curcolor;
549     c.c[1] = c.c[0];
550 
551     outpw(0x3ce,0xff08);     /* set bit mask */
552     outpw(0x3ce,pc.alumode); /* set alu mode */
553 
554     if (y == yl) {
555         if (x < xl) MFBSwapInt(x,xl);
556         x++;
557         dx = x - xl;
558         lcnt = pc.ysize-1-y;
559         rgen = pc.base + xl + (long) lcnt*pc.xsize;
560 
561         if (!pc.curstyle) {
562 
563             if (pc.alumode == 0x3) {
564                 if ((unsigned)rgen & 1) {
565                     *rgen = c.c[0];
566                     rgen++;
567                     dx--;
568                 }
569                 if (dx & 1)
570                     *(rgen + dx - 1) = c.c[0];
571                 dx >>= 1;
572                 while (dx--) {
573                     *(short*)rgen = c.color2;
574                     rgen += 2;
575                 }
576             }
577             else {
578                 while (dx--) {
579                     mfb_trash = *rgen;
580                     *rgen = c.c[0];
581                     rgen++;
582                 }
583             }
584         }
585         else {
586 
587             left = 0x80 >> ((lcnt+xl) & 7);
588             right = pc.linestyles[pc.curstyle];
589 
590             while (dx--) {
591                 if (left & right) {
592                     if (pc.alumode != 3)
593                         mfb_trash = *rgen;
594                     *rgen = c.c[0];
595                 }
596                 left = ror(left,1);
597                 rgen++;
598             }
599         }
600         return;
601     }
602 
603 
604     if (x == xl) {
605         if (y < yl) MFBSwapInt(y,yl);
606         yl--;
607         dy = y - yl;
608         next = pc.xsize;
609         lcnt = pc.ysize-1-y;
610         rgen = pc.base + xl + (long) lcnt*next;
611 
612         if (!pc.curstyle) {
613             while (dy--) {
614                 if (pc.alumode != 3)
615                     mfb_trash = *rgen;
616                 *rgen = c.c[0];
617                 rgen += next;
618             }
619         }
620         else {
621             left = 0x80 >> ((lcnt+xl) & 7);
622             right = pc.linestyles[pc.curstyle];
623 
624             while (dy--) {
625                 if (left & right) {
626                     if (pc.alumode != 3)
627                         mfb_trash = *rgen;
628                     *rgen = c.c[0];
629                 }
630                 left = ror(left,1);
631                 rgen += next;
632             }
633         }
634         return;
635     }
636 
637     if (x < xl) {
638         MFBSwapInt(xl,x);
639         MFBSwapInt(yl,y);
640     }
641     dx = x - xl;
642 
643     next = pc.xsize;
644     dy = yl - y;
645     lcnt = pc.ysize-1-yl;
646     rgen = pc.base + xl + (long) lcnt*next;
647 
648     if (!pc.curstyle) {
649 
650         if (yl < y) {
651             next = -next;
652             dy = -dy;
653         }
654 
655         dy2 = dy;
656         dy++;
657         while (dy--) {
658             errterm += dx;
659             if (errterm <= 0) {
660                 if (pc.alumode != 3)
661                     mfb_trash = *rgen;
662                 *rgen = c.c[0];
663                 rgen += next;
664                 continue;
665             }
666             while (errterm > 0 && xl <= x) {
667                 if (pc.alumode != 3)
668                     mfb_trash = *rgen;
669                 *rgen = c.c[0];
670                 rgen++;
671                 xl++;
672                 errterm -= dy2;
673             }
674             rgen += next;
675 
676         }
677     }
678     else {
679         left = 0x80 >> ((lcnt+xl) & 7);
680         right = pc.linestyles[pc.curstyle];
681 
682         if (yl < y) {
683             next = -next;
684             dy = -dy;
685         }
686 
687         dy2 = dy;
688         dy++;
689         while (dy--) {
690 
691             errterm += dx;
692             if (errterm <= 0) {
693                 if (left & right) {
694                     if (pc.alumode != 3)
695                         mfb_trash = *rgen;
696                     *rgen = c.color2;
697                 }
698                 rgen += next;
699                 left = ror(left,1);
700                 continue;
701             }
702             while (errterm > 0 && xl <= x) {
703                 if (left & right) {
704                     if (pc.alumode != 3)
705                         mfb_trash = *rgen;
706                     *rgen = c.color2;
707                 }
708                 left = ror(left,1);
709                 rgen++;
710                 xl++;
711                 errterm -= dy2;
712             }
713             rgen += next;
714             left = ror(left,1);
715 
716         }
717     }
718 }
719 
720 #endif /* __GNUC__ */
721