OSDN Git Service

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