1 /*
2  *  Written by Matthew Parker and released to the public domain.
3  */
4 
5 #ifdef __DJGPP__
6 
7 #include <conio.h>
8 #include <dpmi.h>
9 #include <sys/farptr.h>
10 
11 #define mypokew(a,b,c) _farpokew(a,(b)<<1,c)
12 #define mypeekw(a,b) _farpeekw(a,(b)<<1)
13 
14 #else
15 
16 #ifdef __FLAT__
17 #include <i86.h>
18 #include "rmi.h"
19 extern struct rminfo RMINF;
20 #define MKSEG(a) ((unsigned short *)(a << 4))
21 #else
22 #include <dos.h>
23 #define MKSEG(a) MK_FP(vseg, 0)
24 #endif
25 
26 #ifndef MK_FP
27 #define MK_FP(x,y) ((void *)(((unsigned long)(x) << 16) | (unsigned)(y)))
28 #endif
29 
30 #define mypokew(a,b,c) *((a) + (b)) = (c)
31 #define mypeekw(a,b) *((a) + (b))
32 
33 #endif
34 
35 #include "vio.h"
36 
37 static unsigned short vseg = 0xb000;
38 static unsigned char vmode = 0;
39 static unsigned short x = 0;
40 static unsigned short y = 0;
41 static unsigned char color = 7;
42 static unsigned short ofs = 0;
43 static unsigned char xhite = 8;
44 
45 struct VIOinfo
46 {
47     unsigned char level;
48     unsigned char level1;
49     unsigned short level2;
50     unsigned short flags;
51     unsigned char mode;
52     unsigned char mode1;
53     unsigned short colors;
54     unsigned short pixcol;
55     unsigned short pixrow;
56     unsigned short txtcol;
57     unsigned short txtrow;
58 }
59 info =
60 {
61     0, 0, 14, 1, 0, 0, 2, 0, 0, 80, 25
62 };
63 
VIOheight(void)64 unsigned short VIOheight(void)
65 {
66     return xhite;
67 }
68 
VIOopen(void)69 unsigned short VIOopen(void)
70 {
71 #ifndef __FLAT__
72     struct SREGS s;
73 #endif
74 #ifdef __DJGPP__
75     __dpmi_regs r;
76 #else
77     union REGS r;
78     unsigned short temp;
79 #endif
80 
81 #if defined(__DJGPP__)
82     r.x.ax = 0x0f00;
83     __dpmi_int(0x10, &r);
84 #elif defined(__FLAT__)
85     r.w.ax = 0xf00;
86     int386(0x10, &r, &r);
87 #else
88     r.x.ax = 0xf00;
89     int86(0x10, &r, &r);
90 #endif
91     vmode = r.h.al;
92 
93     if (r.h.al == 7)
94     {
95         return 0;
96     }
97     else
98     {
99         info.txtcol = r.h.ah;
100         vseg = 0xb800;
101 #if defined(__DJGPP__)
102         r.x.ax = 0xfe00;
103         r.x.es = vseg;
104         r.x.di = 0;
105         __dpmi_int(0x10, &r);
106         vseg = r.x.es;
107 #elif defined(__FLAT__)
108         RMINF.EAX = 0xfe00;
109         RMINF.ES = vseg;
110         temp = RMINF.EDI;
111         RMINF.EDI = 0;
112         int86x(0x10);
113         RMINF.EDI = temp;
114         vseg = RMINF.ES;
115 #else
116         r.x.ax = 0xfe00;
117         s.es = vseg;
118         temp = r.x.di;
119         r.x.di = 0;
120         int86x(0x10, &r, &r, &s);
121         r.x.di = temp;
122         vseg = s.es;
123 #endif
124 #if defined(__DJGPP__)
125         r.x.ax = 0x1130;
126         r.h.bh = 0x1;
127         r.x.dx = 0;
128         __dpmi_int(0x10, &r);
129 #elif defined(__FLAT__)
130         r.w.ax = 0x1130;
131         r.h.bh = 0x1;
132         r.w.dx = 0;
133         int386(0x10, &r, &r);
134 #else
135         r.x.ax = 0x1130;
136         r.h.bh = 0x1;
137         r.x.dx = 0;
138         int86(0x10, &r, &r);
139 #endif
140         if (r.h.dl == 0)  /* cga */
141         {
142             info.txtrow = 25;
143             return 0;
144         }
145         xhite = r.h.cl;
146         info.txtrow = r.h.dl + 1;
147     }
148     return 0;
149 }
150 
VIOclose(void)151 void VIOclose(void)
152 {
153 }
154 
VIOcolumns(void)155 unsigned short VIOcolumns(void)
156 {
157     return info.txtcol;
158 }
159 
VIOrows(void)160 unsigned short VIOrows(void)
161 {
162     return info.txtrow;
163 }
164 
VIOmode(void)165 unsigned short VIOmode(void)
166 {
167     return vmode;
168 }
169 
VIOwherex(void)170 unsigned short VIOwherex(void)
171 {
172     return x;
173 }
174 
VIOwherey(void)175 unsigned short VIOwherey(void)
176 {
177     return y;
178 }
179 
VIOscrollright(int x1,int y1,int x2,int y2,int count)180 void VIOscrollright(int x1, int y1, int x2, int y2, int count)
181 {
182 #if defined(__DJGPP__)
183     int vid = __dpmi_segment_to_descriptor(vseg);
184 #else
185     unsigned short *vid = MKSEG(vseg);
186 #endif
187     int far_right = y1 * info.txtcol + x2;
188     int width = x2 - x1;
189     int depth = y2 - y1 + 2;
190     int i, t;
191 
192     while (depth--)
193     {
194         for (i = 0; i < count; i++)
195         {
196             for (t = 0; t < width; t++)
197             {
198                 mypokew(vid, far_right + t, mypeekw(vid, far_right + t - 1));
199             }
200             mypokew(vid, far_right + t, (color << 8) | 0x20);
201         }
202         far_right += info.txtcol;
203     }
204 }
205 
VIOscrollleft(int x1,int y1,int x2,int y2,int count)206 void VIOscrollleft(int x1, int y1, int x2, int y2, int count)
207 {
208 #if defined(__DJGPP__)
209     int vid = __dpmi_segment_to_descriptor(vseg);
210 #else
211     unsigned short *vid = MKSEG(vseg);
212 #endif
213     int far_right = y1 * info.txtcol + x2;
214     int width = x2 - x1;
215     int depth = y2 - y1 + 2;
216     int i, t;
217 
218     while (depth--)
219     {
220         for (i = 0; i < count; i++)
221         {
222             for (t = 0; t < width; t++)
223             {
224                 mypokew(vid, far_right + t - 1, mypeekw(vid, far_right + t));
225             }
226             mypokew(vid, far_right + width, (color << 8) | 0x20);
227         }
228         far_right += info.txtcol;
229     }
230 }
231 
VIOscrollup(int x1,int y1,int x2,int y2,int count)232 void VIOscrollup(int x1, int y1, int x2, int y2, int count)
233 {
234 #if defined(__DJGPP__)
235     int vid = __dpmi_segment_to_descriptor(vseg);
236 #else
237     unsigned short *vid = MKSEG(vseg);
238 #endif
239     int far_right = y1 * info.txtcol + x1;
240     int width = x2 - x1;
241     int depth = y2 - y1;
242     int screen_width = info.txtcol;
243     int i;
244 
245     while (count--)
246     {
247         while (depth--)
248         {
249             for (i = 0; i < width; i++)
250             {
251                 mypokew(vid, far_right + i, mypeekw(vid, far_right + screen_width + i));
252             }
253             far_right += screen_width;
254         }
255 
256         for (i = 0; i < width; i++)
257         {
258             mypokew(vid, far_right + i, (color << 8) | 0x20);
259         }
260     }
261 }
262 
VIOscrolldown(int x1,int y1,int x2,int y2,int count)263 void VIOscrolldown(int x1, int y1, int x2, int y2, int count)
264 {
265 #if defined(__DJGPP__)
266     int vid = __dpmi_segment_to_descriptor(vseg);
267 #else
268     unsigned short *vid = MKSEG(vseg);
269 #endif
270     int far_right = y2 * info.txtcol + x1;
271     int width = x2 - x1;
272     int depth = y2 - y1;
273     int screen_width = info.txtcol;
274     int i;
275 
276     while (count--)
277     {
278         while (depth--)
279         {
280             for (i = 0; i < width; i++)
281             {
282                 mypokew(vid, far_right + i, mypeekw(vid, far_right - screen_width + i));
283             }
284             far_right -= screen_width;
285         }
286 
287         for (i = width; i > 0; i--)
288         {
289             mypokew(vid, far_right + i - 1, (color << 8) | 0x20);
290         }
291     }
292 }
293 
VIOclear(int x1,int y1,int x2,int y2)294 void VIOclear(int x1, int y1, int x2, int y2)
295 {
296 #if defined(__DJGPP__)
297     int vid = __dpmi_segment_to_descriptor(vseg);
298 #else
299     unsigned short *vid = MKSEG(vseg);
300 #endif
301     int far_right = y1 * info.txtcol + x1;
302     int width = x2 - x1 + 1;
303     int depth = y2 - y1 + 1;
304     int i;
305 
306     while (depth--)
307     {
308         for (i = 0; i < width; i++)
309         {
310             mypokew(vid, far_right + i, (color << 8) | 0x20);
311         }
312         far_right += info.txtcol;
313     }
314 }
315 
VIOputc(const char c)316 void VIOputc(const char c)
317 {
318 #if defined(__DJGPP__)
319     int vid = __dpmi_segment_to_descriptor(vseg);
320 #else
321     unsigned short *vid = MKSEG(vseg);
322 #endif
323 
324     mypokew(vid, ofs, c+(color<<8));
325     ofs++;
326     x++;
327 
328     if (x >= info.txtcol)
329     {
330         y++;
331         x = x - info.txtcol;
332     }
333 }
334 
VIOputs(const char * s)335 void VIOputs(const char *s)
336 {
337 #if defined(__DJGPP__)
338     int vid = __dpmi_segment_to_descriptor(vseg);
339 #else
340     unsigned short *vid = MKSEG(vseg);
341 #endif
342 
343     while (*s != '\0')
344     {
345         mypokew(vid, ofs, *s+(color<<8));
346         s++;
347         x++;
348         ofs++;
349     }
350 
351     if (x >= info.txtcol)
352     {
353         y++;
354         x = x - info.txtcol;
355     }
356 }
357 
VIOgetca(const int x,const int y)358 unsigned short VIOgetca(const int x, const int y)
359 {
360 #if defined(__DJGPP__)
361     int vid = __dpmi_segment_to_descriptor(vseg);
362 #else
363     unsigned short *vid = MKSEG(vseg);
364 #endif
365     int far_right = y * info.txtcol + x;
366     return mypeekw(vid, far_right);
367 }
368 
VIOgetra(int x1,int y1,int x2,int y2,unsigned short * b)369 void VIOgetra(int x1, int y1, int x2, int y2, unsigned short *b)
370 {
371 #if defined(__DJGPP__)
372     int vid = __dpmi_segment_to_descriptor(vseg);
373 #else
374     unsigned short *vid = MKSEG(vseg);
375 #endif
376     int far_right = y1 * info.txtcol + x1;
377     int width = x2 - x1 + 1;
378     int depth = y2 - y1 + 1;
379     int i;
380 
381     while (depth--)
382     {
383         for (i = 0; i < width; i++)
384         {
385             *b = mypeekw(vid, far_right + i);
386             b++;
387         }
388         far_right += info.txtcol;
389     }
390 }
391 
VIOputr(int x,int y,int w,int h,unsigned short * b)392 void VIOputr(int x, int y, int w, int h, unsigned short *b)
393 {
394 #if defined(__DJGPP__)
395     int vid = __dpmi_segment_to_descriptor(vseg);
396 #else
397     unsigned short *vid = MKSEG(vseg);
398 #endif
399     int far_right = y * info.txtcol + x;
400     int screen_length = info.txtcol;
401     int i;
402 
403     while (h--)
404     {
405         for (i = 0; i < w; i++)
406         {
407             mypokew(vid, far_right + i, *b);
408             b++;
409         }
410         far_right += screen_length;
411     }
412 }
413 
VIOsetfore(const int c)414 void VIOsetfore(const int c)
415 {
416     color = (unsigned char)((c & 0x0f) | (color & 0xf0));
417 }
418 
VIOsetback(const int c)419 void VIOsetback(const int c)
420 {
421     color = (unsigned char)(((c & 0x0f) << 4) | (color & 0x0f));
422 }
423 
VIOgetfore(void)424 unsigned short VIOgetfore(void)
425 {
426     return (int)(color & 0x0f);
427 }
428 
VIOgetback(void)429 unsigned short VIOgetback(void)
430 {
431     return (int)((color & 0xf0) >> 4);
432 }
433 
VIOgotoxy(int x1,int y1)434 void VIOgotoxy(int x1, int y1)
435 {
436     x = x1;
437     y = y1;
438     ofs = y1 * info.txtcol + x1;
439 }
440 
VIOupdate(void)441 void VIOupdate(void)
442 {
443 #ifdef __DJGPP__
444     __dpmi_regs r;
445 #else
446     union REGS r;
447 #endif
448     r.h.ah = 2;
449     r.h.bh = 0;
450     r.h.dl = x;
451     r.h.dh = y;
452 #if defined(__DJGPP__)
453     __dpmi_int(0x10, &r);
454 #elif defined(__FLAT__)
455     int386(0x10, &r, &r);
456 #else
457     int86(0x10, &r, &r);
458 #endif
459 }
460 
VIOcursor(int * x,int * y,int * shape)461 void VIOcursor(int *x, int *y, int *shape)
462 {
463 #ifdef __DJGPP__
464     __dpmi_regs r;
465 #else
466     union REGS r;
467 #endif
468     r.h.ah = 3;
469     r.h.bh = 0;
470 #if defined(__DJGPP__)
471     __dpmi_int(0x10, &r);
472 #elif defined(__FLAT__)
473     int386(0x10, &r, &r);
474 #else
475     int86(0x10, &r, &r);
476 #endif
477     *x = (unsigned int)r.h.dl;
478     *y = (unsigned int)r.h.dh;
479 #if defined(__FLAT__) && !defined(__DJGPP__)
480     *shape = r.w.cx;
481 #else
482     *shape = r.x.cx;
483 #endif
484 }
485 
VIOsegment(void)486 unsigned short VIOsegment(void)
487 {
488     return vseg;
489 }
490 
VIOsetSegment(unsigned int s)491 void VIOsetSegment(unsigned int s)
492 {
493     vseg = s;
494 }
495 
VIOsetRows(int r)496 void VIOsetRows(int r)
497 {
498     info.txtrow = r;
499 }
500 
VIOsetCols(int c)501 void VIOsetCols(int c)
502 {
503     info.txtcol = c;
504 }
505