]> 4ch.mooo.com Git - 16.git/blob - 16/dos_gfx.cpp
5e0abde8416cb123bdf3a21f63292f224ecd8036
[16.git] / 16 / dos_gfx.cpp
1 /*\r
2  * LIB.C v1.2a\r
3  *\r
4  * by Robert Schmidt\r
5  * (C)1993 Ztiff Zox Softwear\r
6  *\r
7  * Simple graphics library to accompany the article\r
8  * \r
9  *                      INTRODUCTION TO MODE X.\r
10  * \r
11  * This library provides the basic functions for initializing and using\r
12  * unchained (planar) 256-color VGA modes.  Currently supported are:\r
13  *\r
14  *      - 320x200\r
15  *      - 320x240\r
16  *\r
17  * Functions are provided for:\r
18  *\r
19  *      - initializing one of the available modes\r
20  *      - setting the start address of the VGA refresh data\r
21  *      - setting active and visible display pages\r
22  *      - writing and reading a single pixel to/from video memory\r
23  *\r
24  * The library is provided as a demonstration only, and is not claimed\r
25  * to be particularly efficient or suited for any purpose.  It has only\r
26  * been tested with Borland C++ 3.1 by the author.  Comments on success\r
27  * or disaster with other compilers are welcome.\r
28  *\r
29  * This file is public domain.  Do with it whatever you'd like, but\r
30  * please don't distribute it without the article.\r
31  *\r
32  * Thanks go out to various helpful netters who spotted the 0xE7 bug\r
33  * in the set320x240x256() function!\r
34  *\r
35  * modified by sparky4 so it can be compiled in open watcom ^^\r
36  */\r
37 \r
38 \r
39 /*\r
40  * We 'require' a large data model simply to get rid of explicit 'far'\r
41  * pointers and compiler specific '_fmemset()' functions and the likes.\r
42  */\r
43 #if !defined(__COMPACT__)\r
44 # if !defined(__LARGE__)\r
45 #  if !defined(__HUGE__)\r
46 #   error Large data model required!  Try compiling with 'bcc -ml lib.c'.\r
47 #  endif\r
48 # endif\r
49 #endif\r
50 \r
51 #include <dos.h>\r
52 #include <mem.h>\r
53 #include <conio.h>\r
54 \r
55 //code from old library!\r
56 /*src\lib\*/\r
57 #include "dos_gfx.h"\r
58 \r
59 int old_mode;\r
60 //color \82Ä\82·\82Æ\r
61 int gq = LGQ;\r
62 //\82Ä\82·\82Æ\r
63 int q = 0;\r
64 int bakax = 0, bakay = 0;\r
65 int xx = rand()&0%320, yy = rand()&0%240, sx = 0, sy = 0;\r
66 byte coor;\r
67 \r
68 /*\r
69  * Comment out the following #define if you don't want the testing main()\r
70  * to be included.\r
71  */\r
72 #define TESTING\r
73 \r
74 /*\r
75  * Define the port addresses of some VGA registers.\r
76  */\r
77 #define CRTC_ADDR       0x3d4   /* Base port of the CRT Controller (color) */\r
78 \r
79 #define SEQU_ADDR       0x3c4   /* Base port of the Sequencer */\r
80 #define GRAC_ADDR       0x3ce   /* Base port of the Graphics Controller */\r
81 \r
82 \r
83 /*\r
84  * Make a far pointer to the VGA graphics buffer segment.  Your compiler\r
85  * might not have the MK_FP macro, but you'll figure something out.\r
86  */\r
87 byte *vga = (byte *) MK_FP(0xA000, 0);\r
88 \r
89 //fontAddr = getFont();\r
90 \r
91 /*\r
92  * width and height should specify the mode dimensions.  widthBytes\r
93  * specify the width of a line in addressable bytes.\r
94  */\r
95 unsigned width, height, widthBytes;\r
96 \r
97 /*\r
98  * actStart specifies the start of the page being accessed by\r
99  * drawing operations.  visStart specifies the contents of the Screen\r
100  * Start register, i.e. the start of the visible page.\r
101  */\r
102 unsigned actStart, visStart;\r
103 \r
104 /*\r
105  * set320x200x256_X()\r
106  *      sets mode 13h, then turns it into an unchained (planar), 4-page\r
107  *      320x200x256 mode.\r
108  */\r
109 void set320x200x256_X(void)\r
110         {\r
111         union REGS r;\r
112 \r
113         /* Set VGA BIOS mode 13h: */\r
114         r.x.ax = 0x0013;\r
115         int86(0x10, &r, &r);\r
116 \r
117         /* Turn off the Chain-4 bit (bit 3 at index 4, port 0x3c4): */\r
118         outpw(SEQU_ADDR, 0x0604);\r
119 \r
120         /* Turn off word mode, by setting the Mode Control register\r
121         of the CRT Controller (index 0x17, port 0x3d4): */\r
122         outpw(CRTC_ADDR, 0xE317);\r
123 \r
124         /* Turn off doubleword mode, by setting the Underline Location\r
125            register (index 0x14, port 0x3d4): */\r
126         outpw(CRTC_ADDR, 0x0014);\r
127 \r
128         /* Clear entire video memory, by selecting all four planes, then\r
129            writing 0 to entire segment. */\r
130         outpw(SEQU_ADDR, 0x0F02);\r
131         memset(vga+1, 0, 0xffff); /* stupid size_t exactly 1 too small */\r
132         vga[0] = 0;\r
133 \r
134         /* Update the global variables to reflect dimensions of this\r
135            mode.  This is needed by most future drawing operations. */\r
136         width           = 320;\r
137         height  = 200;\r
138 \r
139         /* Each byte addresses four pixels, so the width of a scan line\r
140            in *bytes* is one fourth of the number of pixels on a line. */\r
141         widthBytes = width / 4;\r
142 \r
143         /* By default we want screen refreshing and drawing operations\r
144            to be based at offset 0 in the video segment. */\r
145         actStart = visStart = 0;\r
146         }\r
147 \r
148 /*\r
149  * setActiveStart() tells our graphics operations which address in video\r
150  * memory should be considered the top left corner.\r
151  */\r
152 void setActiveStart(unsigned offset)\r
153         {\r
154         actStart = offset;\r
155         }\r
156 \r
157 /*\r
158  * setVisibleStart() tells the VGA from which byte to fetch the first\r
159  * pixel when starting refresh at the top of the screen.  This version\r
160  * won't look very well in time critical situations (games for\r
161  * instance) as the register outputs are not synchronized with the\r
162  * screen refresh.  This refresh might start when the high byte is\r
163  * set, but before the low byte is set, which produces a bad flicker.\r
164  */\r
165 void setVisibleStart(unsigned offset)\r
166         {\r
167         visStart = offset;\r
168         outpw(CRTC_ADDR, 0x0C);         /* set high byte */\r
169         outpw(CRTC_ADDR+1, visStart >> 8);\r
170         outpw(CRTC_ADDR, 0x0D);         /* set low byte */\r
171         outpw(CRTC_ADDR+1, visStart & 0xff);\r
172         }\r
173 \r
174 /*\r
175  * setXXXPage() sets the specified page by multiplying the page number\r
176  * with the size of one page at the current resolution, then handing the\r
177  * resulting offset value over to the corresponding setXXXStart()\r
178  * function.  The first page is number 0.\r
179  */\r
180 void setActivePage(int page)\r
181         {\r
182         setActiveStart(page * widthBytes * height);\r
183         }\r
184 \r
185 void setVisiblePage(int page)\r
186         {\r
187         setVisibleStart(page * widthBytes * height);\r
188         }\r
189 \r
190 void putPixel_X(int x, int y, byte color)\r
191         {\r
192         /* Each address accesses four neighboring pixels, so set\r
193            Write Plane Enable according to which pixel we want\r
194            to modify.  The plane is determined by the two least\r
195            significant bits of the x-coordinate: */\r
196         outp(0x3c4, 0x02);\r
197         outp(0x3c5, 0x01 << (x & 3));\r
198 \r
199         /* The offset of the pixel into the video segment is\r
200            offset = (width * y + x) / 4, and write the given\r
201            color to the plane we selected above.  Heed the active\r
202            page start selection. */\r
203         vga[(unsigned)(widthBytes * y) + (x / 4) + actStart] = color;\r
204 \r
205         }\r
206 \r
207 byte getPixel_X(int x, int y)\r
208         {\r
209         /* Select the plane from which we must read the pixel color: */\r
210         outpw(GRAC_ADDR, 0x04);\r
211         outpw(GRAC_ADDR+1, x & 3);\r
212 \r
213         return vga[(unsigned)(widthBytes * y) + (x / 4) + actStart];\r
214 \r
215         }\r
216 \r
217 void set320x240x256_X(void)\r
218         {\r
219         /* Set the unchained version of mode 13h: */\r
220         set320x200x256_X();\r
221 \r
222         /* Modify the vertical sync polarity bits in the Misc. Output\r
223            Register to achieve square aspect ratio: */\r
224         outp(0x3C2, 0xE3);\r
225 \r
226         /* Modify the vertical timing registers to reflect the increased\r
227            vertical resolution, and to center the image as good as\r
228            possible: */\r
229         outpw(0x3D4, 0x2C11);           /* turn off write protect */\r
230         outpw(0x3D4, 0x0D06);           /* vertical total */\r
231         outpw(0x3D4, 0x3E07);           /* overflow register */\r
232         outpw(0x3D4, 0xEA10);           /* vertical retrace start */\r
233         outpw(0x3D4, 0xAC11);           /* vertical retrace end AND wr.prot */\r
234         outpw(0x3D4, 0xDF12);           /* vertical display enable end */\r
235         outpw(0x3D4, 0xE715);           /* start vertical blanking */\r
236         outpw(0x3D4, 0x0616);           /* end vertical blanking */\r
237 \r
238         /* Update mode info, so future operations are aware of the\r
239            resolution */\r
240         height = 240;\r
241 \r
242         }\r
243 \r
244 \r
245 /*-----------XXXX-------------*/\r
246 //---------------------------------------------------\r
247 //\r
248 // Use the bios to get the address of the 8x8 font\r
249 //\r
250 // You need a font if you are going to draw text.\r
251 //\r
252 \r
253 int far *\r
254 getFont()\r
255 {\r
256     union REGPACK rg;\r
257     int seg;\r
258     int off;\r
259     memset(&rg, 0, sizeof(rg));\r
260 \r
261     rg.w.ax = 0x1130;\r
262     rg.h.bh = 0x03;\r
263     intr(0x10, &rg);\r
264     seg = rg.w.es;\r
265     off = rg.w.bp;\r
266     \r
267 \r
268     return (int far *)MK_FP(seg, off);\r
269 }\r
270 \r
271 void drawChar(int x, int y, int color, byte c)\r
272 {\r
273         int i, j;\r
274         int mask;\r
275         int far *font = getFont() + (c * 8);\r
276 \r
277         for (i = 0; i < 8; i++)\r
278         {\r
279                 mask = *font;\r
280                 for (j = 0; j < 8; j++)\r
281                 {\r
282                         if (mask & 0x80)\r
283                         {\r
284                                 //pixel(x + j, y + i, color);\r
285                                 putPixel_X(x + j, y + i, color);\r
286                         }\r
287                         mask <<= 1;\r
288                 }\r
289                 font++;\r
290         }\r
291 }\r
292 \r
293 void drawText(int x, int y, int color, byte string)\r
294 {\r
295         while (string)\r
296         {\r
297                 drawChar(x, y, color, string);\r
298                 x += 8;\r
299                 string++;\r
300         }\r
301 }\r
302 \r
303 /////////////////////////////////////////////////////////////////////////////\r
304 //                                                                         //\r
305 // setvideo() - This function Manages the video modes                      //\r
306 //                                                                         //\r
307 /////////////////////////////////////////////////////////////////////////////\r
308 void setvideo(/*byte mode, */int vq){\r
309         union REGS in, out;\r
310 \r
311         if(!vq){ // deinit the video\r
312                 // change to the video mode we were in before we switched to mode 13h\r
313                 in.h.ah = 0x00;\r
314                 in.h.al = old_mode;\r
315                 int86(0x10, &in, &out);\r
316 \r
317         }else if(vq == 1){ // init the video\r
318                 // get old video mode\r
319                 in.h.ah = 0xf;\r
320                 int86(0x10, &in, &out);\r
321                 old_mode = out.h.al;\r
322 \r
323                 // enter mode\r
324                 set320x240x256_X();\r
325         }\r
326 }\r
327 \r
328 /////////////////////////////////////////////////////////////////////////////\r
329 //                                                                         //\r
330 // cls() - This clears the screen to the specified color, on the VGA or on //\r
331 //         the Virtual screen.                                             //\r
332 //                                                                         //\r
333 /////////////////////////////////////////////////////////////////////////////\r
334 void cls(byte color, byte *Where){\r
335         _fmemset(Where, color, width*height);\r
336 }\r
337 \r
338 //color \82Ä\82·\82Æ\r
339 int colortest(){\r
340         if(gq < NUM_COLORS){\r
341                 cls(gq, vga);\r
342                 gq++;\r
343         }else gq = 0;\r
344         return gq;\r
345 }\r
346 \r
347 //color \82Ä\82·\82Æ\r
348 int colorz(){\r
349         if(gq < HGQ){\r
350 //----          cls(gq, vaddr);\r
351                 cls(gq, vga);\r
352                 gq++;\r
353         }else gq = LGQ;\r
354         return gq;\r
355 }\r
356 \r
357 //slow spectrum down\r
358 void ssd(int svq){\r
359         if(sy < height+1){\r
360                 if(sx < width+1){\r
361                         //plotpixel(xx, yy, coor, vga);\r
362                         //ppf(sx, sy, coor, vga);\r
363                         putPixel_X(sx, sy, coor);\r
364                         //printf("%d %d %d %d\n", sx, sy, svq, coor);\r
365                         sx++;\r
366                 }else sx = 0;\r
367                 if(sx == width){\r
368                         sy++;\r
369                         if(svq == 7) coor++;\r
370                         if(sy == height && svq == 8) coor = rand()%NUM_COLORS;\r
371                 }\r
372         }else sy = 0;\r
373 }\r
374 \r
375 /*-----------ding-------------*/\r
376 int ding(int q){\r
377         setActivePage(0);\r
378         setVisiblePage(0);\r
379         int d3y;\r
380 \r
381 //++++  if(q <= 4 && q!=2 && gq == BONK-1) coor = rand()%HGQ;\r
382         if((q == 2
383         ||q==4
384         ) && gq == BONK-1){\r
385                         if(coor < HGQ && coor < LGQ) coor = LGQ;\r
386                         if(coor < HGQ-1){\r
387                                 coor++;\r
388                 }else{ coor = LGQ;\r
389                         bakax = rand()%3; bakay = rand()%3;\r
390                 }\r
391         }\r
392 \r
393         if(q == 5){ colortest(); return gq; }\r
394         if(q == 10){ colorz(); return gq; }\r
395         if(q == 11){ colorz(); delay(100); return gq; }\r
396         if(q == 8){ ssd(q); /*printf("%d\n", coor);*/ }\r
397         if(q == 6){\r
398                 coor = rand()%NUM_COLORS;\r
399 //----          cls(coor, vaddr);\r
400                 cls(coor, vga);\r
401                 //updatevbuff();\r
402         }\r
403 \r
404         if(q == 7 || q== 9){\r
405                 if(gq < HGQ){\r
406                         if(q == 7) ssd(q);\r
407                         if(q == 9){ ssd(q); coor++; }\r
408                         gq++;\r
409                 }else gq = LGQ;\r
410         }\r
411         if(q<5 && gq<BONK){ // the number variable make the colors more noticable\r
412                 if(q==1){\r
413                         if(xx==width){bakax=0;}\r
414                         if(xx==0){bakax=1;}\r
415                         if(yy==height){bakay=0;}\r
416                         if(yy==0){bakay=1;}\r
417                 }else if(q==3){\r
418                         if(xx!=width||yy!=height){\r
419                                 if(xx==0){bakax=1;bakay=-1;d3y=1;}\r
420                                 if(yy==0){bakax=1;bakay=0;d3y=1;}\r
421                                 if(xx==width){bakax=-1;bakay=-1;d3y=1;}\r
422                                 if(yy==height){bakax=1;bakay=0;d3y=1;}\r
423                         }else if(xx==width&&yy==height) xx=yy=0;\r
424                 }\r
425                 if(q==3){\r
426                         if(d3y){\r
427                                 if(bakay<0){\r
428                                         yy--;\r
429                                         d3y--;\r
430                                 }else\r
431                                 if(bakay>0){\r
432                                         yy++;\r
433                                         d3y--;\r
434                                 }\r
435                         }\r
436                         if(bakax<0){\r
437                                 xx--;\r
438                         }else\r
439                         if(bakax>0){\r
440                                 xx++;\r
441                         }\r
442                 }else{\r
443                         if(!bakax){\r
444                                 xx--;\r
445                         }else if(bakax>1){\r
446                                 xx++;\r
447                         }\r
448                         if(!bakay){\r
449                                 yy--;\r
450                         }else if(bakay>1){\r
451                                 yy++;\r
452                         }\r
453                 }\r
454                 // fixer\r
455                 if(xx<0) xx=width;\r
456                 if(yy<0) yy=height;\r
457                 if(xx>width) xx=0;\r
458                 if(yy>height) yy=0;\r
459 \r
460                 // plot the pixel\r
461 //----          ppf(xx, yy, coor, vga);\r
462                 putPixel_X(xx, yy, coor);\r
463 //----          if(q==2) ppf(rand()%, rand()%height, 0, vga);\r
464                 if(q==2) putPixel_X(rand()%width, rand()%height, 0);\r
465                 if(q==2||q==4){ bakax = rand()%3; bakay = rand()%3; }\r
466                 gq++;\r
467 //if(xx<0||xx>320||yy<0||yy>240)\r
468 //      printf("%d %d %d %d %d %d\n", xx, yy, coor, bakax, bakay, getPixel_X(xx,yy));\r
469 //      printf("%d\n", getPixel_X(xx,yy));\r
470 //0000\r
471 //      drawText(0, 0, 15, getPixel_X(xx,yy));\r
472         }else gq = LGQ;\r
473         return gq;\r
474 }\r
475 \r
476 \r
477 /*\r
478  * The library testing routines follows below.\r
479  */\r
480 \r
481 \r
482 #ifdef TESTING\r
483 \r
484 #include <stdio.h>\r
485 #include <conio.h>\r
486 \r
487 void doTest(void)\r
488         {\r
489         int p, x, y, pages;\r
490 \r
491         /* This is the way to calculate the number of pages available. */\r
492         pages = 65536L/(widthBytes*height); // apparently this takes the A000 address
493 \r
494         printf("%d\n", pages);
495
496         for (p = 0; p <= pages; ++p)\r
497                 {\r
498                 setActivePage(p);\r
499 \r
500                 /* On each page draw a single colored border, and dump the palette\r
501                    onto a small square about the middle of the page. */
502                    
503                    //{\r
504                         for (x = 0; x <= width; ++x)\r
505                                 {\r
506                                 putPixel_X(x, 0, p+1);\r
507                                 if(p!=pages) putPixel_X(x, height-1, p+1);
508                                         else putPixel_X(x, 99-1, p+1);\r
509                                 }\r
510 \r
511                         for (y = 0; y <= height; ++y)\r
512                                 {\r
513                                 putPixel_X(0, y, p+1);\r
514                                 if(p!=pages) putPixel_X(width-1, y, p+1);
515                                         else putPixel_X(width-1, y, p+1);\r
516                                 }\r
517 \r
518                         for (x = 0; x < 16; ++x)\r
519                                 for (y = 0; y < 16; ++y)\r
520                                         putPixel_X(x+(p+2)*16, y+(p+2)*16, x + y*16);\r
521                         //}
522
523                 drawText(0, 0, 15, p);
524 \r
525                 }\r
526 \r
527         /* Each pages will now contain a different image.  Let the user cycle\r
528            through all the pages by pressing a key. */\r
529         for (p = 0; p <= pages; ++p)\r
530                 {\r
531                 setVisiblePage(p);
532                 //drawText(0, 240, 15, "bakapi");\r
533                 getch();\r
534                 }\r
535 \r
536         }\r
537 \r
538 /*\r
539  * Library test (program) entry point.\r
540  */\r
541 \r
542 int main(void)\r
543         {\r
544         int key,d;\r
545         // main variables\r
546         d=1; // switch variable\r
547         key=4; // default screensaver number\r
548 //      puts("First, have a look at the 320x200 mode.  I will draw some rubbish");\r
549 //      puts("on all of the four pages, then let you cycle through them by");\r
550 //      puts("hitting a key on each page.");\r
551 //      puts("Press a key when ready...");\r
552 //      getch();\r
553 \r
554 //      doTest();\r
555 \r
556 //      puts("Then, check out Mode X, 320x240 with 3 (and a half) pages.");\r
557 //      puts("Press a key when ready...");\r
558 //      getch();\r
559 \r
560         setvideo(1);\r
561 // screen savers\r
562 \r
563 /*while(d!=0){ // on!\r
564                 if(!kbhit()){ // conditions of screen saver\r
565                         ding(key);\r
566                 }else{\r
567                         setvideo(0);\r
568                         // user imput switch\r
569                         printf("Enter 1, 2, 3, 4, or 6 to run a screensaver, or enter 5 to quit.\n", getch());  // prompt the user\r
570                         scanf("%d", &key);\r
571                         //if(key==3){xx=yy=0;} // crazy screen saver wwww\r
572                         if(key==5) d=0;\r
573                         setvideo(1);\r
574                 }\r
575         }*/ // else off\r
576         while(!kbhit()){ // conditions of screen saver\r
577                 ding(4);
578         }
579         //end of screen savers
580         doTest();\r
581         setvideo(0);\r
582         puts("Where to next?  It's your move! wwww");\r
583         printf("bakapi ver. 1.04.09a\nis made by sparky4\81i\81\86\83Ö\81\85\81j feel free to use it ^^\nLicence: GPL v2\n");\r
584         return 0;\r
585         }\r
586 \r
587 #endif\r