]> 4ch.mooo.com Git - 16.git/blob - 16/tweak16/VGALIB.CPP
Merge branch 'master' of https://github.com/sparky4/16
[16.git] / 16 / tweak16 / VGALIB.CPP
1 #include <dos.h>\r
2 #include <conio.h>\r
3 #include <string.h>\r
4 \r
5 #include "misc.hpp"\r
6 #include "screen.hpp"\r
7 #include "vgalib.hpp"\r
8 \r
9 \r
10 GraphicsAPI::GraphicsAPI(int xr, int yr, int vxr, int vyr, int clrs)\r
11         {\r
12         int segm, offs;\r
13         xres = xr;\r
14         yres = yr;\r
15         vxres = vxr;\r
16         vyres = vyr;\r
17         colors = clrs;\r
18         libID = "Generic Graphics";\r
19         asm     {\r
20                 push    bp\r
21                 mov             ax, 1130h\r
22                 mov             bh, 03h\r
23                 int             10h\r
24                 mov             ax, bp\r
25                 pop             bp\r
26                 mov             [segm], es\r
27                 mov             [offs], ax\r
28                 }\r
29         font = (unsigned char *)MK_FP(segm, offs);\r
30         fontHeight = fontWidth = 8;\r
31         }\r
32 \r
33 void GraphicsAPI::hLine(int x, int y, int l)\r
34         {\r
35         while (l--)\r
36                 putPixel(x++, y);\r
37         }\r
38 \r
39 void GraphicsAPI::vLine(int x, int y, int l)\r
40         {\r
41         while (l--)\r
42                 putPixel(x, y++);\r
43         }\r
44 \r
45 /*\r
46  *      Generic line drawing routine, using Bresenham's algorithm.\r
47  *      Taken from Richard Wilton: "PC & PS/2 Video Systems" p. 166-7\r
48  */\r
49 \r
50 void GraphicsAPI::line(int x1, int y1, int x2, int y2)\r
51         {\r
52         if (x1==x2)\r
53                 {\r
54                 sort(y1, y2);\r
55                 vLine(x1, y1, y2-y1+1);\r
56                 return;\r
57                 }\r
58         if (y1==y2)\r
59                 {\r
60                 sort(x1, x2);\r
61                 hLine(x1, y1, x2-x1+1);\r
62                 }\r
63         int dx = absolute(x2-x1);\r
64         int dy = absolute(y2-y1);\r
65         if (dx >= dy)\r
66                 {\r
67                 if (x1>x2)\r
68                         {\r
69                         swap(x1, x2);\r
70                         swap(y1, y2);\r
71                         }\r
72                 int yincr = 1;\r
73                 if (y2<y1)\r
74                         yincr = -yincr;\r
75                 int d = 2 * dy - dx;\r
76                 int aincr = 2 * (dy - dx);\r
77                 int bincr = 2 * dy;\r
78                 int x = x1;\r
79                 int y = y1;\r
80                 putPixel(x, y);\r
81                 while (++x <= x2)\r
82                         {\r
83                         if (d >= 0)\r
84                                 {\r
85                                 y += yincr;\r
86                                 d += aincr;\r
87                                 }\r
88                         else\r
89                                 d += bincr;\r
90                         putPixel(x, y);\r
91                         }\r
92                 }\r
93         else\r
94                 {\r
95                 if (y1>y2)\r
96                         {\r
97                         swap(x1, x2);\r
98                         swap(y1, y2);\r
99                         }                           \r
100                 int xincr = 1;\r
101                 if (x2<x1)\r
102                         xincr = -xincr;\r
103                 int d = 2*dx - dy;\r
104                 int aincr = 2 * (dx - dy);\r
105                 int bincr = 2 * dx;\r
106                 int x = x1;\r
107                 int y = y1;\r
108                 putPixel(x, y);\r
109                 while (++y <= y2)\r
110                         {\r
111                         if (d >= 0)\r
112                                 {\r
113                                 x += xincr;\r
114                                 d += aincr;\r
115                                 }\r
116                         else\r
117                                 d += bincr;\r
118                         putPixel(x, y);\r
119                         }\r
120                 }\r
121         }\r
122 \r
123 void GraphicsAPI::rectangle(int x1, int y1, int x2, int y2)\r
124         {\r
125         sort(x1, x2);\r
126         sort(y1, y2);\r
127         hLine(x1, y1, x2-x1);\r
128         hLine(x1, y2, x2-x1);\r
129         vLine(x1, y1, y2-y1);\r
130         vLine(x2, y1, y2-y1);\r
131         }\r
132 \r
133 void GraphicsAPI::bar(int x1, int y1, int x2, int y2)\r
134         {\r
135         int width = x2-x1+1;\r
136         for (int y = y1; y < y2; ++y)\r
137                 hLine(x1, y, width);\r
138         }\r
139 \r
140 void GraphicsAPI::wipe()\r
141         {\r
142         bar(0, 0, vxres, vyres);\r
143         }\r
144 \r
145 void GraphicsAPI::putChar(int x, int y, int ch)\r
146         {\r
147         unsigned char *fptr = font + fontHeight*ch;\r
148         for (int j=0; j<fontHeight; ++j, ++fptr)\r
149                 {\r
150                 char mask = *fptr;\r
151                 for (int i=0; i<fontWidth; ++i)\r
152                         {\r
153                         asm shl         [mask], 1;\r
154                         asm jnc         skip\r
155                                 putPixel(x+i, y+j, color);\r
156                         skip:\r
157                         }\r
158                 }\r
159         }\r
160 \r
161 void GraphicsAPI::putText(int x, int y, char *txt)\r
162         {\r
163         switch (hJustify)\r
164                 {\r
165                 case HCENTER:\r
166                         x -= fontWidth * strlen(txt) / 2;\r
167                         break;\r
168                 case RIGHT:\r
169                         x -= fontWidth * strlen(txt);\r
170                         break;\r
171                 }\r
172         switch (vJustify)\r
173                 {\r
174                 case VCENTER:\r
175                         y -= fontHeight / 2;\r
176                         break;\r
177                 case BOTTOM:\r
178                         y -= fontHeight;\r
179                         break;\r
180                 }\r
181 \r
182         while (*txt)\r
183                 {\r
184                 putChar(x, y, *(txt++));\r
185                 x += fontWidth;\r
186                 }\r
187         }\r
188 \r
189 void GraphicsAPI::setTextJustify(HJustify h, VJustify v)\r
190         {\r
191         hJustify = h;\r
192         vJustify = v;\r
193         }\r
194 \r
195 \r
196 /*\r
197  *      VGAGraphicsAPI\r
198  */\r
199 \r
200 unsigned char *VGAGraphicsAPI::videoBuf =\r
201         (unsigned char *)MK_FP(0xa000,0);\r
202 \r
203 VGAGraphicsAPI::VGAGraphicsAPI(int xr, int yr, int vxr, int xb, int clrs)\r
204         : GraphicsAPI(xr, yr, vxr, 65536L/xb, clrs), xbytes(xb)\r
205         {\r
206         libID = "VGA Graphics";\r
207         outp(0x3ce, 0x05);\r
208         int t = inp(0x3cf);\r
209         outpw(0x3ce, 0x05 | (t & 0xfc) << 8);   // write mode 0\r
210         outpw(0x3c4, 0x0f02);                                   // enable all planes\r
211         }\r
212 \r
213 \r
214 void VGAGraphicsAPI::syncWithRefresh()\r
215         {\r
216         while (inp(0x3da)&0x8);\r
217         while (!(inp(0x3da)&0x8));\r
218         }\r
219 \r
220 unsigned VGAGraphicsAPI::getOffset(int x, int y)\r
221         {\r
222         return y * xbytes + x/(vxres/xbytes);\r
223         }\r
224 \r
225 void VGAGraphicsAPI::setBase(int x=0, int y=0)\r
226         {\r
227         unsigned offset = getOffset(x,y);\r
228         inp(0x3da);\r
229         outp(0x3c0, 0x33);\r
230         outp(0x3c0, getPelPan(x));\r
231         outpw(0x3d4, 0x0c | (offset & 0xff00));\r
232         outpw(0x3d4, 0x0d | (offset & 0x00ff)<<8);\r
233         syncWithRefresh();\r
234         }\r
235 \r
236 \r
237 /*\r
238  *      Planar16\r
239  */\r
240 \r
241 Planar16::Planar16(int xr, int yr, int vxr)\r
242         : VGAGraphicsAPI(xr, yr, vxr, vxr>>3, 16)\r
243         {\r
244         libID = "4-plane 16-color mode";\r
245         outpw(0x3ce, 0x0f01);                                   // enable set/reset\r
246         }\r
247 \r
248 void Planar16::putPixel(int x, int y, int c)\r
249         {\r
250         outpw(0x3ce, 0x00 | (c<<8));            // set/reset to select color\r
251         outpw(0x3ce, 0x08 | 0x8000>>(x&7));     // bit mask to select bit\r
252         unsigned char *pos = graphScr+y*xbytes+(x>>3);\r
253         *pos = *pos;\r
254         }\r
255 \r
256 int Planar16::getPixel(int x, int y)\r
257         {\r
258         return videoBuf[y*xbytes+x];\r
259         }\r
260 \r
261 void Planar16::hLine(int x, int y, int l)\r
262         {\r
263         outpw(0x3ce, 0x00 | (color<<8));        // set/reset to select color\r
264         unsigned char *pos = graphScr+y*xbytes+(x>>3);\r
265         int mask;\r
266         int shift = x & 7;\r
267         if (shift > 0)\r
268                 {\r
269                 mask = 0x00ff >> shift;\r
270                 l -= 8 - shift;\r
271                 if (l<0)\r
272                         mask &= 0xff << -l;\r
273                 outpw(0x3ce, 0x08 | mask << 8); // bit mask to select first bits\r
274                 *pos = *pos;\r
275                 ++pos;\r
276                 }\r
277         if (l >= 8)\r
278                 {\r
279                 outpw(0x3ce, 0xff08);                   // bit mask to select 8 bits\r
280                 memset(pos, 0, l>>3);\r
281                 pos += l>>3;\r
282                 l -= l & 0xf8;\r
283                 }\r
284         if (l >= 0)\r
285                 {\r
286                 mask = 0xff00 << (8-l);\r
287                 outpw(0x3ce, 0x08 | mask);              // bit mask to select last bits\r
288                 *pos = *pos;\r
289                 }\r
290         }\r
291 \r
292 int Planar16::getPelPan(int x)\r
293         {\r
294         return x & 7;\r
295         }\r
296 \r
297 /*\r
298  *      Chained256\r
299  */\r
300 \r
301 Chained256::Chained256(int xr, int yr, int vxr)\r
302         : VGAGraphicsAPI(xr, yr, vxr, vxr, 256)\r
303         {\r
304         libID = "Chained 256-color mode";\r
305         }\r
306 \r
307 void Chained256::putPixel(int x, int y, int c)\r
308         {\r
309         videoBuf[y*xbytes+x] = c;\r
310         }\r
311 \r
312 int Chained256::getPixel(int x, int y)\r
313         {\r
314         return videoBuf[y*xbytes+x];\r
315         }\r
316 \r
317 void Chained256::hLine(int x, int y, int l)\r
318         {\r
319         memset(graphScr+y*xbytes+x, color, l);\r
320         }\r
321 \r
322 unsigned Chained256::getOffset(int x, int y)\r
323         {\r
324         return (y * xbytes + x/(vxres/xbytes)) >> 2; \r
325         }\r
326 \r
327 int Chained256::getPelPan(int x)\r
328         {\r
329         return 2*(x & 3);\r
330         }\r
331 \r
332 \r
333 /*\r
334  *      Unchained256\r
335  */\r
336 \r
337 Unchained256::Unchained256(int xr, int yr, int vxr)\r
338         : VGAGraphicsAPI(xr, yr, vxr, vxr>>2, 256)\r
339         {\r
340         libID = "Unchained 256-color mode";\r
341         }\r
342 \r
343 void Unchained256::putPixel(int x, int y, int c)\r
344         {\r
345         outpw(0x3c4, 0x02 | 0x0100<<(x&3));\r
346         videoBuf[y*xbytes+(x>>2)] = c;\r
347         }\r
348 \r
349 int Unchained256::getPixel(int x, int y)\r
350         {\r
351         return videoBuf[y*xbytes+x];\r
352         }\r
353 \r
354 void Unchained256::hLine(int x, int y, int l)\r
355         {\r
356         unsigned char *pos = graphScr+y*xbytes+(x>>2);\r
357         int mask;\r
358         int shift = x & 3;\r
359         if (shift > 0)\r
360                 {\r
361                 mask = 0x000f << shift & 0x000f;\r
362                 l -= 4-shift;\r
363                 if (l<0)\r
364                         mask &= 0x0f >> -l;\r
365                 outpw(0x3c4, 0x02 | mask << 8); // write enable first pixels\r
366                 *(pos++) = color;\r
367                 }\r
368         if (l >= 4)\r
369                 {\r
370                 outpw(0x3c4, 0x0f02);                   // write enable 4 pixels\r
371                 memset(pos, color, l>>2);\r
372                 pos += l>>2;\r
373                 l -= l & 0xfc;\r
374                 }\r
375         if (l >= 0)\r
376                 {\r
377                 mask = 0x0f00 >> (4-l) & 0x0f00;\r
378                 outpw(0x3c4, 0x02 | mask);              // write enable last pixels\r
379                 *pos = color;\r
380                 }\r
381         }\r
382 \r
383 int Unchained256::getPelPan(int x)\r
384         {\r
385         return 2*(x & 3);\r
386         }\r