]> 4ch.mooo.com Git - 16.git/blob - 16/dos_gfx.cpp
modified: 16/Project 16.bfproject
[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 \r
41 /*\r
42  * We 'require' a large data model simply to get rid of explicit 'far'\r
43  * pointers and compiler specific '_fmemset()' functions and the likes.\r
44  */\r
45 #if !defined(__COMPACT__)\r
46 # if !defined(__LARGE__)\r
47 #  if !defined(__HUGE__)\r
48 #   error Large data model required!  Try compiling with 'wcc -0 -ml lib.c'.\r
49 #  endif\r
50 # endif\r
51 #endif\r
52 \r
53 #include <dos.h>\r
54 #include <mem.h>\r
55 #include <conio.h>\r
56 \r
57 //code from old library!\r
58 /*src\lib\*/\r
59 #include "dos_gfx.h"\r
60 \r
61 int old_mode;\r
62 //color \82Ä\82·\82Æ\r
63 int gq = LGQ;\r
64 //\82Ä\82·\82Æ\r
65 int q = 0;\r
66 int bakax = 0, bakay = 0;\r
67 cord xx = rand()&0%320, yy = rand()&0%240, sx = 0, sy = 0;\r
68 byte coor;\r
69 \r
70 /*\r
71  * Comment out the following #define if you don't want the testing main()\r
72  * to be included.\r
73  */\r
74 #define TESTING\r
75 \r
76 /*\r
77  * Define the port addresses of some VGA registers.\r
78  */\r
79 #define CRTC_ADDR          0x3d4   /* Base port of the CRT Controller (color) */\r
80 \r
81 #define SEQU_ADDR          0x3c4   /* Base port of the Sequencer */\r
82 #define GRAC_ADDR          0x3ce   /* Base port of the Graphics Controller */\r
83 #define STATUS_ADDR     0x3DA\r
84 \r
85 unsigned char *RowsX[600];\r
86 unsigned char write_plane, read_plane;\r
87 unsigned short text_mask[16] = { 0x0002, 0x0102, 0x0202, 0x0302,\r
88                                  0x0402, 0x0502, 0x0602, 0x0702,\r
89                                  0x0802, 0x0902, 0x0A02, 0x0B02,\r
90                                  0x0C02, 0x0D02, 0x0E02, 0x0F02 };\r
91 \r
92 \r
93 /*\r
94  * Make a far pointer to the VGA graphics buffer segment.  Your compiler\r
95  * might not have the MK_FP macro, but you'll figure something out.\r
96  */\r
97 byte *vga = (byte *) MK_FP(0xA000, 0);\r
98 \r
99 \r
100 /*\r
101  * width and height should specify the mode dimensions.  widthBytes\r
102  * specify the width of a line in addressable bytes.\r
103  */\r
104 unsigned width, height, widthBytes;\r
105 \r
106 /*\r
107  * actStart specifies the start of the page being accessed by\r
108  * drawing operations.  visStart specifies the contents of the Screen\r
109  * Start register, i.e. the start of the visible page.\r
110  */\r
111 unsigned actStart, visStart;\r
112 \r
113 /*\r
114  * set320x200x256_X()\r
115  *        sets mode 13h, then turns it into an unchained (planar), 4-page\r
116  *        320x200x256 mode.\r
117  */\r
118 void set320x200x256_X(void)\r
119                 {\r
120                 union REGS r;\r
121 \r
122                 /* Set VGA BIOS mode 13h: */\r
123                 r.x.ax = 0x0013;\r
124                 int86(0x10, &r, &r);\r
125 \r
126                 /* Turn off the Chain-4 bit (bit 3 at index 4, port 0x3c4): */\r
127                 outpw(SEQU_ADDR, 0x0604);\r
128 \r
129                 /* Turn off word mode, by setting the Mode Control register\r
130                 of the CRT Controller (index 0x17, port 0x3d4): */\r
131                 outpw(CRTC_ADDR, 0xE317);\r
132 \r
133                 /* Turn off doubleword mode, by setting the Underline Location\r
134                    register (index 0x14, port 0x3d4): */\r
135                 outpw(CRTC_ADDR, 0x0014);\r
136 \r
137                 /* Clear entire video memory, by selecting all four planes, then\r
138                    writing 0 to entire segment. */\r
139                 outpw(SEQU_ADDR, 0x0F02);\r
140                 memset(vga+1, 0, 0xffff); /* stupid size_t exactly 1 too small */\r
141                 vga[0] = 0;\r
142 \r
143                 /* Update the global variables to reflect dimensions of this\r
144                    mode.  This is needed by most future drawing operations. */\r
145                 width              = 320;\r
146                 height  = 200;\r
147 \r
148                 /* Each byte addresses four pixels, so the width of a scan line\r
149                    in *bytes* is one fourth of the number of pixels on a line. */\r
150                 widthBytes = width / 4;\r
151 \r
152                 /* By default we want screen refreshing and drawing operations\r
153                    to be based at offset 0 in the video segment. */\r
154                 actStart = visStart = 0;\r
155 \r
156                 /*\r
157 --------------------\r
158 HORIZONTAL SCROLLING\r
159 --------------------\r
160 Horizontal scrolling is essentially the same as vertical scrolling, all\r
161 you do is increment or decrement the VGA offset register by 1 instead of\r
162 80 as with vertical scrolling.\r
163 \r
164 However, horizontal scrolling is complicated by two things\r
165 \r
166   1. Incrementing the offset register by one actually scrolls by FOUR\r
167      pixels (and there are FOUR planes on the VGA, what a coincidence)\r
168 \r
169   2. You can't draw the image off the screen and then scroll it on\r
170      because of the way the VGA wraps to the next row every 80 bytes\r
171      (80 bytes * 4 planes = 320 pixels), if you tried it, you would\r
172      actually be drawing to the other side of the screen (which is\r
173      entirely visible)\r
174 \r
175 I'll solve these problems one at a time.\r
176 \r
177 Firstly, to get the VGA to scroll by only one pixel you use the horizontal\r
178 pixel panning (HPP) register. This register resides at\r
179 \r
180   PORT:     3C0H\r
181   INDEX:    13h\r
182 \r
183 and in real life, you use it like this\r
184 \r
185 ----------------- Pixel Panning ---------------\r
186 IN PORT 3DAH (this clears an internal\r
187   flip-flop of the VGA)\r
188 OUT 13H TO PORT 3C0H\r
189 OUT value TO PORT 3C0H (where "value" is the\r
190   number of pixels to offset)\r
191 -----------------------------------------------\r
192 */\r
193 \r
194 mxSetVirtualScreen(480,360);\r
195                 }\r
196 \r
197 /*\r
198  * setActiveStart() tells our graphics operations which address in video\r
199  * memory should be considered the top left corner.\r
200  */\r
201 void setActiveStart(unsigned offset)\r
202                 {\r
203                 actStart = offset;\r
204                 }\r
205 \r
206 /*\r
207  * setVisibleStart() tells the VGA from which byte to fetch the first\r
208  * pixel when starting refresh at the top of the screen.  This version\r
209  * won't look very well in time critical situations (games for\r
210  * instance) as the register outputs are not synchronized with the\r
211  * screen refresh.  This refresh might start when the high byte is\r
212  * set, but before the low byte is set, which produces a bad flicker.\r
213  */\r
214 void setVisibleStart(unsigned offset)\r
215                 {\r
216                 visStart = offset;\r
217                 outpw(CRTC_ADDR, 0x0C);          /* set high byte */\r
218                 outpw(CRTC_ADDR+1, visStart >> 8);\r
219                 outpw(CRTC_ADDR, 0x0D);          /* set low byte */\r
220                 outpw(CRTC_ADDR+1, visStart & 0xff);\r
221                 }\r
222 \r
223 /*\r
224  * setXXXPage() sets the specified page by multiplying the page number\r
225  * with the size of one page at the current resolution, then handing the\r
226  * resulting offset value over to the corresponding setXXXStart()\r
227  * function.  The first page is number 0.\r
228  */\r
229 void setActivePage(int page)\r
230                 {\r
231                 setActiveStart(page * widthBytes * height);\r
232                 }\r
233 \r
234 void setVisiblePage(int page)\r
235                 {\r
236                 setVisibleStart(page * widthBytes * height);\r
237                 }\r
238 \r
239 void putPixel_X(int x, int y, byte color)\r
240                 {\r
241                 /* Each address accesses four neighboring pixels, so set\r
242                    Write Plane Enable according to which pixel we want\r
243                    to modify.  The plane is determined by the two least\r
244                    significant bits of the x-coordinate: */\r
245                 outp(0x3c4, 0x02);\r
246                 outp(0x3c5, 0x01 << (x & 3));\r
247 \r
248                 /* The offset of the pixel into the video segment is\r
249                    offset = (width * y + x) / 4, and write the given\r
250                    color to the plane we selected above.  Heed the active\r
251                    page start selection. */\r
252                 vga[(unsigned)(widthBytes * y) + (x / 4) + actStart] = color;\r
253 \r
254                 }\r
255 \r
256 byte getPixel_X(int x, int y)\r
257                 {\r
258                 /* Select the plane from which we must read the pixel color: */\r
259                 outpw(GRAC_ADDR, 0x04);\r
260                 outpw(GRAC_ADDR+1, x & 3);\r
261 \r
262                 return vga[(unsigned)(widthBytes * y) + (x / 4) + actStart];\r
263 \r
264                 }\r
265 \r
266 void set320x240x256_X(void)\r
267                 {\r
268                 /* Set the unchained version of mode 13h: */\r
269                 set320x200x256_X();\r
270 \r
271                 /* Modify the vertical sync polarity bits in the Misc. Output\r
272                    Register to achieve square aspect ratio: */\r
273                 outp(0x3C2, 0xE3);\r
274 \r
275                 /* Modify the vertical timing registers to reflect the increased\r
276                    vertical resolution, and to center the image as good as\r
277                    possible: */\r
278                 outpw(0x3D4, 0x2C11);              /* turn off write protect */\r
279                 outpw(0x3D4, 0x0D06);              /* vertical total */\r
280                 outpw(0x3D4, 0x3E07);              /* overflow register */\r
281                 outpw(0x3D4, 0xEA10);              /* vertical retrace start */\r
282                 outpw(0x3D4, 0xAC11);              /* vertical retrace end AND wr.prot */\r
283                 outpw(0x3D4, 0xDF12);              /* vertical display enable end */\r
284                 outpw(0x3D4, 0xE715);              /* start vertical blanking */\r
285                 outpw(0x3D4, 0x0616);              /* end vertical blanking */\r
286 \r
287                 /* Update mode info, so future operations are aware of the\r
288                    resolution */\r
289                 height = 240;\r
290 \r
291                 }\r
292 \r
293 \r
294 /*-----------XXXX-------------*/\r
295 \r
296 /////////////////////////////////////////////////////////////////////////////\r
297 //                                                                         //\r
298 // WaitRetrace() - This waits until you are in a Verticle Retrace.         //\r
299 //                                                                         //\r
300 /////////////////////////////////////////////////////////////////////////////\r
301 void wait_for_retrace(void)\r
302 {\r
303     while (!(inp(STATUS_ADDR) & 0x08));\r
304 }\r
305 \r
306 /////////////////////////////////////////////////////////////////////////////\r
307 //                                                                         //\r
308 // MoveTo() - This moves to position X*4 on a chain 4 screen.              //\r
309 //                Note: As soon as I find documentation, this function     //\r
310 //                will be better documented.  - Snowman                    //\r
311 //                                                                         //\r
312 /////////////////////////////////////////////////////////////////////////////\r
313 /*\r
314 void MoveTo (word X, word Y) {\r
315 \r
316 //      word O = Y*SIZE*2+X;\r
317         word O = Y*widthBytes*2+X;\r
318 \r
319   asm {\r
320     mov    bx, [O]\r
321     mov    ah, bh\r
322     mov    al, 0x0C\r
323 \r
324     mov    dx, 0x3D4\r
325     out    dx, ax\r
326 \r
327     mov    ah, bl\r
328     mov    al, 0x0D\r
329     mov    dx, 0x3D4\r
330     out    dx, ax\r
331   }\r
332 \r
333 ;-----------------------------------------------------------\r
334 ;\r
335 ; MXPN.ASM - Panning function\r
336 ; Copyright (c) 1993,1994 by Alessandro Scotti\r
337 ;\r
338 ;-----------------------------------------------------------\r
339 ;WARN    PRO\r
340 INCLUDE MODEX.DEF\r
341 \r
342 PUBLIC  mxPan\r
343 \r
344 EXTRN   mxWaitDisplay   : FAR\r
345 EXTRN   mxStartAddress  : FAR\r
346 \r
347 MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
348                 ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
349 \r
350 EXTRN   mx_BytesPerLine : WORD\r
351 \r
352 ;-----------------------------------------------------------\r
353 ;\r
354 ; Moves the screen.\r
355 ;\r
356 ; Input:\r
357 ;       X, Y    = new X, Y coordinates of view screen\r
358 ; Output:\r
359 ;       none\r
360 ;\r
361 mxPan           PROC    FAR\r
362         ARG     Y:WORD,                 \\r
363                 X:WORD                  = ARG_SIZE\r
364         ASSUME  ds:NOTHING\r
365         .enter  0\r
366 \r
367         mov     ax, [Y]\r
368         mul     [mx_BytesPerLine]\r
369         mov     dx, [X]\r
370         shr     dx, 1\r
371         shr     dx, 1\r
372         add     ax, dx\r
373         push    ax                      ; Push the start address\r
374         call    mxWaitDisplay\r
375         call    mxStartAddress\r
376 \r
377         mov     dx, 03DAh               ; Set the pixel pan register\r
378         in      al, dx\r
379         mov     dx, 03C0h\r
380         mov     al, 33h\r
381         out     dx, al\r
382         mov     al, BYTE PTR [X]\r
383         and     al, 3\r
384         shl     al, 1\r
385         out     dx, al\r
386 \r
387         xor     ax, ax\r
388         .leave  ARG_SIZE\r
389 mxPan           ENDP\r
390 \r
391 MX_TEXT         ENDS\r
392 END\r
393 \r
394 \r
395 }\r
396 \r
397 //Procedure Play;\r
398 void Play()\r
399 {\r
400   int loop1,loop2;\r
401   int xpos,ypos,xdir,ydir;\r
402   //int ch;\r
403 //   for(loop1=1;loop1<=62;loop1++)\r
404      //Pal ((char)loop1,(char)loop1,(char)0,(char)(62-loop1)); // { This sets up the pallette for the pic }\r
405 \r
406    moveto(0,0,Size); // { This moves the view to the top left hand corner }\r
407 \r
408 //   for(loop1=0;loop1<=3;loop1++)\r
409 //     for(loop2=0;loop2<=5;loop2++)\r
410 //       Putpic (loop1*160,loop2*66); // { This places the picture all over the\r
411                                     //  chain-4 screen }\r
412 //   getch();\r
413 //   ch=0x0;\r
414 //   xpos=rand (78)+1;\r
415 //   ypos=rand (198)+1; // { Random start positions for the view }\r
416         xpos=0;\r
417         ypos=0;\r
418    xdir=1;\r
419    ydir=1;\r
420 //   while(1)\r
421 //   {\r
422      WaitRetrace();     //     { Take this out and watch the screen go crazy! }\r
423      moveto (xpos,ypos,Size);\r
424      xpos=xpos+xdir;\r
425      ypos=ypos+ydir;\r
426      if( (xpos>79)  || (xpos<1))xdir=-xdir;\r
427      if( (ypos>199) || (ypos<1))ydir=-ydir; // { Hit a boundry, change\r
428                                             //    direction! }\r
429 //     if(_bios_keybrd(_KEYBRD_READY))ch=getch();\r
430 //       if(ch==0x71)break; // 'q'\r
431 //       if(ch==0x1b)break; // 'ESC'\r
432 //   }\r
433 }\r
434 */\r
435 /*tile*/\r
436 //king_crimson's code\r
437 void putColorBox_X(int x, int y, int w, int h, byte color) {\r
438         outp(0x3c4, 0x02);\r
439 \r
440         int curx, cury;\r
441         unsigned drawptr;\r
442         for (curx=x; curx<(x+w); curx++) {\r
443                 outp(0x3c5, 0x01 << (curx & 3));\r
444                 drawptr = (unsigned)(widthBytes * y) + (curx / 4) + actStart;\r
445                 for (cury=0; cury<h; cury++) {\r
446                         vga[drawptr] = color;\r
447                         drawptr += widthBytes;\r
448                 }\r
449         }\r
450 }\r
451 \r
452 void vScroll(int rows)\r
453 {\r
454         // Scrolling = current start + (rows * bytes in a row)\r
455         setVisibleStart(visStart + (rows * width));\r
456 }\r
457 \r
458 void scrolly(int bongy)\r
459 {\r
460         int boingy=0;\r
461         if(bongy<0)\r
462                 boingy=-1;\r
463         else if(bongy>0)\r
464                 boingy=1;\r
465 \r
466         for(int ti=0;ti<TILEWH;ti++)\r
467         {\r
468                 delay(1);\r
469                 vScroll(boingy);\r
470         }\r
471 }\r
472 \r
473 //king_crimson's code\r
474 void hScroll(int Cols) {\r
475         wait_for_retrace();\r
476         outp(0x3C0, 0x13);\r
477         outp(0x3C0, Cols & 3);\r
478         outp(0x3D4, 0x13);\r
479         outp(0x3D5, Cols >> 2);\r
480         outp(0x3D4, Cols);\r
481         //setVisibleStart(visStart + (Cols * height));\r
482         setVisibleStart(visStart + (Cols * width));\r
483 }\r
484 \r
485 /*To implement smooth horizontal scrolling, you would do the following:\r
486 -------------- Horizontal Scrolling ------------\r
487 FOR X = 0 TO 319 DO\r
488   SET HPP TO ( X MOD 4 )\r
489   SET VGA OFFSET TO ( X/4 )\r
490 END FOR\r
491 ------------------------------------------------\r
492 \r
493 Okay, no problem at all (although I think you might have to fiddle\r
494 around with the HPP a bit to get it right...try different values and\r
495 see what works :).\r
496 \r
497 So, the next problem is with drawing the images off the screen where\r
498 they aren't visible and then scrolling them on!!! As it turns out,\r
499 there's yet ANOTHER register to accomplish this. This one's called the\r
500 offset register (no, not the one I was talking about before, that one\r
501 was actually the "start address" register) and it's at\r
502 \r
503   PORT:     3D4H/3D5H\r
504   OFFSET:   13H\r
505 \r
506 and here's how to use it\r
507 \r
508 -------------- Offset Register ---------------\r
509 OUT 13H TO PORT 3D4H\r
510 OUT value TO PORT 3D5H\r
511 ----------------------------------------------\r
512 \r
513 Now, what my VGA reference says is that this register holds the number\r
514 of bytes (not pixels) difference between the start address of each row.\r
515 So, in X-mode it normally contains the value 80 (as we remember,\r
516 80 bytes * 4 planes = 320 pixels). This register does not affect the\r
517 VISIBLE width of the display, only the difference between addresses on\r
518 each row.\r
519 \r
520 When we scroll horizontally, we need a little bit of extra working space\r
521 so we can draw off the edge of the screen.\r
522 \r
523 Perhaps a little diagram will clarify it. The following picture is of a\r
524 standard X-mode addressing scheme with the OFFSET register set to 80.\r
525 \r
526       ROW    OFFSET\r
527       0         0 ========================\r
528       1        80 [                      ]\r
529       2       160 [                      ]\r
530       ..       .. [       VISIBLE        ]\r
531                   [        SCREEN        ]\r
532                   [                      ]\r
533                   [                      ]\r
534       ..       .. [                      ]\r
535       199   15920 ========================\r
536 \r
537 and the next diagram is of a modified addressing scheme with the OFFSET\r
538 register set to 82 (to give us 4 extra pixels on each side of the screen)\r
539 \r
540 ROW    OFFSET\r
541 0         0 ------========================------\r
542 1        82 |   V [                      ]   V |\r
543 2       164 |   I [                      ]   I |\r
544 ..       .. | N S [      VISIBLE         ] N S |\r
545             | O I [       SCREEN         ] O I |\r
546             | T B [                      ] T B |\r
547             |   L [                      ]   L |\r
548 ..       .. |   E [                      ]   E |\r
549 199   16318 ------========================------\r
550 \r
551 Beautiful!!!\r
552 \r
553 As with vertical scrolling, however, you still have the problem of when\r
554 you reach the bottom of page 4...and it's fixed in the same manner.\r
555 \r
556 I haven't actually managed to get infinite horizontal scrolling working,\r
557 but the method I have just stated will give you a horizontal scrolling\r
558 range of over 200 screens!!!! So if you need more (which is extremely\r
559 unlikely), figure it out yourself.\r
560 \r
561 \r
562 ------------------\r
563 COMBINED SCROLLING\r
564 ------------------\r
565 To do both horizontal and vertical scrolling, all you have to do is combine\r
566 the two methods with a few little extras (it's always the way isn't it).\r
567 \r
568 You have to start off with the original screen on the current page and the\r
569 next page as well. When you scroll horizontally, you have to draw the edge\r
570 that's coming in to the screen to BOTH pages (that means you'll be drawing\r
571 the incoming edge twice, once for each page). You do this so that when you\r
572 have scrolled vertically down through a complete page, you can jump back\r
573 to the first page and it will (hopefully) have an identical copy, and you\r
574 can then continue scrolling again.\r
575 \r
576 I'm sorry about this being so confusing but it's a bit difficult to explain.\r
577 \r
578 \r
579 */\r
580 int loadfontX(char *fname)\r
581 {\r
582         FILE *fp;\r
583 \r
584         fp = fopen(fname, "rb");\r
585 \r
586         if (fp == NULL) {\r
587                 return 0;\r
588         } else {\r
589                 fread(Xfont, 8, 256, fp);\r
590                 fclose(fp);\r
591                 return 1;\r
592         }\r
593 }\r
594 \r
595 void putchX(cord x, cord y, char c, byte color)\r
596 {\r
597         int i;\r
598         byte *vga_ptr;\r
599         byte *font_ptr;\r
600         byte temp;\r
601 \r
602         // 8x8 font\r
603         vga_ptr = RowsX[y << 3] + (x << 1) + actStart;\r
604         write_plane = -1;\r
605 \r
606         font_ptr = Xfont + (c << 3);\r
607 \r
608         i=8;\r
609         while (i--) {\r
610                 temp = *font_ptr++;\r
611                 outpw(SEQU_ADDR, text_mask[temp & 0x0F]);\r
612                 *vga_ptr++ = color;\r
613 \r
614                 outpw(SEQU_ADDR, text_mask[temp >> 4]);\r
615                 *vga_ptr-- = color;\r
616                 vga_ptr += widthBytes;\r
617         }\r
618 }\r
619 \r
620 void putstringX(cord x, cord y, char *str, byte color)\r
621 {\r
622         int i, skip;\r
623         byte *vga_ptr;\r
624         byte *font_ptr;\r
625         byte c, temp;\r
626 \r
627         // 8x8 font\r
628         vga_ptr = RowsX[y << 3] + (x << 1) + actStart;\r
629         write_plane = -1;\r
630 \r
631         skip = 2 - (widthBytes << 3);\r
632 \r
633         while (c = *str++) {\r
634                 font_ptr = Xfont + (c << 3);\r
635 \r
636                 i=8;\r
637                 while (i--) {\r
638                         temp = *font_ptr++;\r
639                         outpw(SEQU_ADDR, text_mask[temp & 0x0F]);\r
640                         *vga_ptr++ = color;\r
641 \r
642                         outpw(SEQU_ADDR, text_mask[temp >> 4]);\r
643                         *vga_ptr-- = color;\r
644                         vga_ptr += widthBytes;\r
645                 }\r
646 \r
647                 vga_ptr += skip;\r
648         }\r
649 }\r
650 \r
651 /////////////////////////////////////////////////////////////////////////////\r
652 //                                                                         //\r
653 // setvideo() - This function Manages the video modes                                     //\r
654 //                                                                         //\r
655 /////////////////////////////////////////////////////////////////////////////\r
656 void setvideo(/*byte mode, */int vq){\r
657                 union REGS in, out;\r
658 \r
659                 if(!vq){ // deinit the video\r
660                                 // change to the video mode we were in before we switched to mode 13h\r
661                                 in.h.ah = 0x00;\r
662                                 in.h.al = old_mode;\r
663                                 int86(0x10, &in, &out);\r
664 \r
665                 }else if(vq == 1){ // init the video\r
666                                 // get old video mode\r
667                                 in.h.ah = 0xf;\r
668                                 int86(0x10, &in, &out);\r
669                                 old_mode = out.h.al;\r
670 \r
671                                 // enter mode\r
672                                 set320x240x256_X();\r
673                 }\r
674 }\r
675 \r
676 /////////////////////////////////////////////////////////////////////////////\r
677 //                                                                                                                                               //\r
678 // cls() - This clears the screen to the specified color, on the VGA or on //\r
679 //               the Virtual screen.                                                                                     //\r
680 //                                                                                                                                               //\r
681 /////////////////////////////////////////////////////////////////////////////\r
682 void cls(byte color, byte *Where){\r
683                 _fmemset(Where, color, width*(height*17));\r
684 }\r
685 \r
686 //color \82Ä\82·\82Æ\r
687 int colortest(){\r
688                 if(gq < NUM_COLORS){\r
689                                 cls(gq, vga);\r
690                                 gq++;\r
691                 }else gq = 0;\r
692                 return gq;\r
693 }\r
694 \r
695 //color \82Ä\82·\82Æ\r
696 int colorz(){\r
697                 if(gq < HGQ){\r
698 //----            cls(gq, vaddr);\r
699                                 cls(gq, vga);\r
700                                 gq++;\r
701                 }else gq = LGQ;\r
702                 return gq;\r
703 }\r
704 \r
705 //slow spectrum down\r
706 void ssd(int svq){\r
707                 if(sy < height+1){\r
708                                 if(sx < width+1){\r
709                                                 //plotpixel(xx, yy, coor, vga);\r
710                                                 //ppf(sx, sy, coor, vga);\r
711                                                 putPixel_X(sx, sy, coor);\r
712                                                 //printf("%d %d %d %d\n", sx, sy, svq, coor);\r
713                                                 sx++;\r
714                                 }else sx = 0;\r
715                                 if(sx == width){\r
716                                                 sy++;\r
717                                                 if(svq == 7) coor++;\r
718                                                 if(sy == height && svq == 8) coor = rand()%NUM_COLORS;\r
719                                 }\r
720                 }else sy = 0;\r
721 }\r
722 \r
723 /*-----------ding-------------*/\r
724 int ding(int q){\r
725 \r
726 //      if(yy<height){\r
727                 setActivePage(0);\r
728                 setVisiblePage(0);\r
729 /*      }\r
730         if((height)<yy<(height*2)){\r
731                 setActivePage(1);\r
732                 setVisiblePage(1);\r
733         }\r
734         if((height*2)<yy<(height*3)){\r
735                 setActivePage(2);\r
736                 setVisiblePage(2);\r
737         }*/\r
738                 int d3y;\r
739 \r
740 //++++  if(q <= 4 && q!=2 && gq == BONK-1) coor = rand()%HGQ;\r
741                 if((q == 2\r
742                 ||q==4\r
743                 ||q==16\r
744                 ) && gq == BONK-1){\r
745                                                 if(coor < HGQ && coor < LGQ) coor = LGQ;\r
746                                                 if(coor < HGQ){\r
747                                                                 coor++;\r
748                                 }else{ coor = LGQ;\r
749                                                 bakax = rand()%3; bakay = rand()%3;\r
750                                 }\r
751                 }\r
752 \r
753                 if(q==8){ colorz(); return gq; }else\r
754                 if(q==10){ ssd(q); /*printf("%d\n", coor);*/ }else\r
755                 if(q==5){ colortest(); return gq; }else\r
756                 if(q==11){ colorz(); delay(100); return gq; }\r
757                 if(q==6){\r
758                                 coor = rand()%NUM_COLORS;\r
759 //----            cls(coor, vaddr);\r
760                                 cls(coor, vga);\r
761                                 //updatevbuff();\r
762                 }\r
763 \r
764                 if(q==7||q==9){\r
765                                 if(gq < HGQ){\r
766                                                 if(q == 7) ssd(q);\r
767                                                 if(q == 9){ ssd(q); coor++; }\r
768                                                 gq++;\r
769                                 }else gq = LGQ;\r
770                 }\r
771                 if((q<5 && gq<BONK) || (q==16 && gq<BONK)){ // the number variable make the colors more noticable\r
772                                 if(q==1){\r
773                                                 if(xx==width){bakax=0;}\r
774                                                 if(xx==0){bakax=1;}\r
775                                                 if(yy==height){bakay=0;}\r
776                                                 if(yy==0){bakay=1;}\r
777                                 }else if(q==3){\r
778                                                 if(xx!=width||yy!=height){\r
779                                                                 if(xx==0){bakax=1;bakay=-1;d3y=1;}\r
780                                                                 if(yy==0){bakax=1;bakay=0;d3y=1;}\r
781                                                                 if(xx==width){bakax=-1;bakay=-1;d3y=1;}\r
782                                                                 if(yy==height){bakax=1;bakay=0;d3y=1;}\r
783                                                 }else if(xx==width&&yy==height) xx=yy=0;\r
784                                 }\r
785                                 if(q==3){\r
786                                                 if(d3y){\r
787                                                                 if(bakay<0){\r
788                                                                                 yy--;\r
789                                                                                 d3y--;\r
790                                                                 }else\r
791                                                                 if(bakay>0){\r
792                                                                                 yy++;\r
793                                                                                 d3y--;\r
794                                                                 }\r
795                                                 }\r
796                                                 if(bakax<0){\r
797                                                                 xx--;\r
798                                                 }else\r
799                                                 if(bakax>0){\r
800                                                                 xx++;\r
801                                                 }\r
802                                 }else{\r
803                                                 if(q==16)\r
804                                                 {\r
805                                                                 if(!bakax){\r
806                                                                                 xx--;//=TILEWH;\r
807                                                                 }else if(bakax>0){\r
808                                                                                 xx++;//=TILEWH;\r
809                                                                 }\r
810                                                                 if(!bakay){\r
811                                                                                 yy--;//=TILEWH;\r
812                                                                 }else if(bakay>0){\r
813                                                                                 yy++;//=TILEWH;\r
814                                                                 }\r
815                                                 }else{\r
816                                                                 if(!bakax){\r
817 //                                                                              xx-=TILEWH;\r
818                                                                                 xx--;\r
819                                                                 }else if(bakax>1){\r
820 //                                                                              xx+=TILEWH;\r
821                                                                                 xx++;\r
822                                                                 }\r
823                                                                 if(!bakay){\r
824 //                                                                              yy-=TILEWH;\r
825                                                                                 yy--;\r
826                                                                 }else if(bakay>1){\r
827 //                                                                              yy+=TILEWH;\r
828                                                                                 yy++;\r
829                                                                 }\r
830                                                 }\r
831                                 }\r
832                                 // fixer\r
833 //                              if(q!=16){\r
834 //if(q!=16)\r
835                                                 if(xx<(0/*-TILEWH*/)) xx=(width/*+TILEWH*/);\r
836                                                 if(yy<0) yy=(height*3);\r
837                                                 if(xx>(width/*+TILEWH*/)) xx=(0/*-TILEWH*/);\r
838                                                 if(yy>(height*3)) yy=0;\r
839 //                              }\r
840 \r
841 //interesting effects\r
842                                 if(q==16)\r
843                                 {\r
844                                 int tx=0,ty=0;\r
845                                 tx+=xx+16;\r
846                                 ty+=yy+16;\r
847                                 putPixel_X(tx, ty, coor);\r
848                                 //drawrect(tx, ty, tx+TILEWH, ty+TILEWH, coor);\r
849                                 //printf("%d %d %d %d %d %d\n", xx, yy, tx, ty, TILEWH);\r
850 \r
851                                 // plot the pixel\r
852 //----            ppf(xx, yy, coor, vga);\r
853                                 }else /*if(xx>=0 && xx<width && yy>=0 && yy<(height*3))*/{\r
854 //                                      putColorBox_X(xx, yy, TILEWH, TILEWH, coor);\r
855 //++++0000\r
856                                         putPixel_X(xx, yy, coor);\r
857                                 } \r
858 \r
859 //----            if(q==2) ppf(rand()%, rand()%height, 0, vga);\r
860 //                              if(q==2) putColorBox_X(rand()%width, rand()%(height*3), TILEWH, TILEWH, 0);\r
861 //++++0000\r
862                                 if(q==2) putPixel_X(rand()%width, rand()%(height*3), 0);\r
863                                 if(q==16) putPixel_X(rand()%width, rand()%(height*3), 0);\r
864                                 if(q==2||q==4||q==16){ bakax = rand()%3; bakay = rand()%3; }\r
865                                 gq++;\r
866 //if(xx<0||xx>320||yy<0||yy>(height*3))\r
867 //        printf("%d %d %d %d %d %d\n", xx, yy, coor, bakax, bakay, getPixel_X(xx,yy));\r
868 //        printf("%d\n", getPixel_X(xx,yy));\r
869 //0000\r
870 //        drawText(0, 0, 15, getPixel_X(xx,yy));\r
871                 }else gq = LGQ;\r
872                 return gq;\r
873 }\r
874 \r
875 \r
876 /*\r
877  * The library testing routines follows below.\r
878  */\r
879 \r
880 \r
881 #ifdef TESTING\r
882 \r
883 #include <stdio.h>\r
884 #include <conio.h>\r
885 \r
886 void doTest(void)\r
887                 {\r
888                 int p, x, y, pages;\r
889 \r
890                 /* This is the way to calculate the number of pages available. */\r
891                 pages = 65536L/(widthBytes*height); // apparently this takes the A000 address\r
892 \r
893                 printf("%d\n", pages);\r
894 \r
895                 for (p = 0; p <= pages; ++p)\r
896                                 {\r
897                                 setActivePage(p);\r
898 \r
899                                 /* On each page draw a single colored border, and dump the palette\r
900                                    onto a small square about the middle of the page. */\r
901 \r
902                                    //{\r
903                                                 for (x = 0; x <= width; ++x)\r
904                                                                 {\r
905                                                                 putPixel_X(x, 0, p+1);\r
906                                                                 if(p!=pages) putPixel_X(x, height-1, p+1);\r
907                                                                                 else putPixel_X(x, 99-1, p+1);\r
908                                                                 }\r
909 \r
910                                                 for (y = 0; y <= height; ++y)\r
911                                                                 {\r
912                                                                 putPixel_X(0, y, p+1);\r
913                                                                 if(p!=pages) putPixel_X(width-1, y, p+1);\r
914                                                                                 else putPixel_X(width-1, y, p+1);\r
915                                                                 }\r
916 \r
917                                                 for (x = 0; x < 16; ++x)\r
918                                                                 for (y = 0; y < 16; ++y)\r
919                                                                                 putPixel_X(x+(p+2)*16, y+(p+2)*16, x + y*16);\r
920                                                 //}\r
921 \r
922 //                              drawText(0, 0, 15, p);\r
923 \r
924                                 }\r
925 \r
926                 /* Each pages will now contain a different image.  Let the user cycle\r
927                    through all the pages by pressing a key. */\r
928                 for (p = 0; p <= pages; ++p)\r
929                                 {\r
930                                 setVisiblePage(p);\r
931                                 //drawText(0, 240, 15, "bakapi");\r
932                                 getch();\r
933                                 }\r
934 \r
935                 }\r
936 \r
937 /*\r
938  * Library test (program) entry point.\r
939  */\r
940 \r
941 int main(void)\r
942                 {\r
943                 int key,d;\r
944                 //short int temp;\r
945                 // main variables\r
946                 d=1; // switch variable\r
947                 key=4; // default screensaver number\r
948 //        puts("First, have a look at the 320x200 mode.  I will draw some rubbish");\r
949 //        puts("on all of the four pages, then let you cycle through them by");\r
950 //        puts("hitting a key on each page.");\r
951 //        puts("Press a key when ready...");\r
952 //        getch();\r
953 \r
954 //        doTest();\r
955 \r
956 //        puts("Then, check out Mode X, 320x240 with 3 (and a half) pages.");\r
957 //        puts("Press a key when ready...");\r
958 //        getch();\r
959 \r
960 //++++0000\r
961                 setvideo(1);\r
962                 /*temp = loadfontX("vga8x8.fnt");\r
963 \r
964                 if (temp) {\r
965                         putstringX(0, 0, "bakapi!", 2);\r
966                 }\r
967                 getch();*/\r
968 // screen savers\r
969 \r
970 /*while(d!=0){ // on!\r
971                                 if(!kbhit()){ // conditions of screen saver\r
972                                                 ding(key);\r
973                                 }else{\r
974                                                 setvideo(0);\r
975                                                 // user imput switch\r
976                                                 printf("Enter 1, 2, 3, 4, or 6 to run a screensaver, or enter 5 to quit.\n", getch());  // prompt the user\r
977                                                 scanf("%d", &key);\r
978                                                 //if(key==3){xx=yy=0;} // crazy screen saver wwww\r
979                                                 if(key==5) d=0;\r
980                                                 setvideo(1);\r
981                                 }\r
982                 }*/ // else off\r
983                 while(!kbhit()){ // conditions of screen saver\r
984                         ding(4);\r
985                 }\r
986                 //end of screen savers\r
987                 doTest();\r
988 //              getch();\r
989 \r
990                 while(!kbhit()){ // conditions of screen saver\r
991 //                      hScroll(1);\r
992 //                      scrolly(1);\r
993                         vScroll(1);\r
994 //                      delay(100);\r
995 //                      Play();\r
996                 }\r
997 //++++0000\r
998                 setvideo(0);\r
999 //mxTerm();\r
1000 //mxGetVersion();\r
1001                 puts("Where to next?  It's your move! wwww");\r
1002                 printf("bakapi ver. 1.04.09.03\nis made by sparky4\81i\81\86\83Ö\81\85\81j feel free to use it ^^\nLicence: GPL v2\n");\r
1003                 return 0;\r
1004                 }\r
1005 \r
1006 #endif\r