5 * (C)1993 Ztiff Zox Softwear
\r
7 * Simple graphics library to accompany the article
\r
9 * INTRODUCTION TO MODE X.
\r
11 * This library provides the basic functions for initializing and using
\r
12 * unchained (planar) 256-color VGA modes. Currently supported are:
\r
17 * Functions are provided for:
\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
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
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
32 * Thanks go out to various helpful netters who spotted the 0xE7 bug
\r
33 * in the set320x240x256() function!
\r
35 * Modified by sparky4 so it can be compiled in open watcom ^^
\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
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
57 //code from old library!
\r
59 #include "dos_gfx.h"
\r
60 #include "lib\x\modex.h"
\r
63 //color
\82Ä
\82·
\82Æ
\r
67 int bakax = 0, bakay = 0;
\r
68 cord xx = rand()&0%320, yy = rand()&0%240, sx = 0, sy = 0;
\r
72 * Comment out the following #define if you don't want the testing main()
\r
78 * Define the port addresses of some VGA registers.
\r
80 #define CRTC_ADDR 0x3d4 /* Base port of the CRT Controller (color) */
\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
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
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
98 byte *vga = (byte *) MK_FP(0xA000, 0);
\r
102 * width and height should specify the mode dimensions. widthBytes
\r
103 * specify the width of a line in addressable bytes.
\r
105 unsigned width, height, widthBytes;
\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
112 unsigned actStart, visStart;
\r
115 * set320x200x256_X()
\r
116 * sets mode 13h, then turns it into an unchained (planar), 4-page
\r
117 * 320x200x256 mode.
\r
119 void set320x200x256_X(void)
\r
123 /* Set VGA BIOS mode 13h: */
\r
125 int86(0x10, &r, &r);
\r
127 /* Turn off the Chain-4 bit (bit 3 at index 4, port 0x3c4): */
\r
128 outpw(SEQU_ADDR, 0x0604);
\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
134 /* Turn off doubleword mode, by setting the Underline Location
\r
135 register (index 0x14, port 0x3d4): */
\r
136 outpw(CRTC_ADDR, 0x0014);
\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
144 /* Update the global variables to reflect dimensions of this
\r
145 mode. This is needed by most future drawing operations. */
\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
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
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
165 However, horizontal scrolling is complicated by two things
\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
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
176 I'll solve these problems one at a time.
\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
184 and in real life, you use it like this
\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
195 mxSetVirtualScreen(480,360);
\r
199 * setActiveStart() tells our graphics operations which address in video
\r
200 * memory should be considered the top left corner.
\r
202 void setActiveStart(unsigned offset)
\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
215 void setVisibleStart(unsigned 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
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
230 void setActivePage(int page)
\r
232 setActiveStart(page * widthBytes * height);
\r
235 void setVisiblePage(int page)
\r
237 setVisibleStart(page * widthBytes * height);
\r
240 void putPixel_X(int x, int y, byte color)
\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
247 outp(0x3c5, 0x01 << (x & 3));
\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
257 byte getPixel_X(int x, int y)
\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
263 return vga[(unsigned)(widthBytes * y) + (x / 4) + actStart];
\r
267 void set320x240x256_X(void)
\r
269 /* Set the unchained version of mode 13h: */
\r
270 set320x200x256_X();
\r
272 /* Modify the vertical sync polarity bits in the Misc. Output
\r
273 Register to achieve square aspect ratio: */
\r
276 /* Modify the vertical timing registers to reflect the increased
\r
277 vertical resolution, and to center the image as good as
\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
288 /* Update mode info, so future operations are aware of the
\r
295 /*-----------XXXX-------------*/
\r
297 /////////////////////////////////////////////////////////////////////////////
\r
299 // WaitRetrace() - This waits until you are in a Verticle Retrace. //
\r
301 /////////////////////////////////////////////////////////////////////////////
\r
302 void wait_for_retrace(void)
\r
304 while (!(inp(STATUS_ADDR) & 0x08));
\r
307 /////////////////////////////////////////////////////////////////////////////
\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
313 /////////////////////////////////////////////////////////////////////////////
\r
315 void MoveTo (word X, word Y) {
\r
317 // word O = Y*SIZE*2+X;
\r
318 word O = Y*widthBytes*2+X;
\r
334 ;-----------------------------------------------------------
\r
336 ; MXPN.ASM - Panning function
\r
337 ; Copyright (c) 1993,1994 by Alessandro Scotti
\r
339 ;-----------------------------------------------------------
\r
345 EXTRN mxWaitDisplay : FAR
\r
346 EXTRN mxStartAddress : FAR
\r
348 MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'
\r
349 ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING
\r
351 EXTRN mx_BytesPerLine : WORD
\r
353 ;-----------------------------------------------------------
\r
355 ; Moves the screen.
\r
358 ; X, Y = new X, Y coordinates of view screen
\r
369 mul [mx_BytesPerLine]
\r
374 push ax ; Push the start address
\r
376 call mxStartAddress
\r
378 mov dx, 03DAh ; Set the pixel pan register
\r
383 mov al, BYTE PTR [X]
\r
402 int xpos,ypos,xdir,ydir;
\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
407 moveto(0,0,Size); // { This moves the view to the top left hand corner }
\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
415 // xpos=rand (78)+1;
\r
416 // ypos=rand (198)+1; // { Random start positions for the view }
\r
423 WaitRetrace(); // { Take this out and watch the screen go crazy! }
\r
424 moveto (xpos,ypos,Size);
\r
427 if( (xpos>79) || (xpos<1))xdir=-xdir;
\r
428 if( (ypos>199) || (ypos<1))ydir=-ydir; // { Hit a boundry, change
\r
430 // if(_bios_keybrd(_KEYBRD_READY))ch=getch();
\r
431 // if(ch==0x71)break; // 'q'
\r
432 // if(ch==0x1b)break; // 'ESC'
\r
437 //king_crimson's code
\r
438 void putColorBox_X(int x, int y, int w, int h, byte color) {
\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
453 void vScroll(int rows)
\r
455 // Scrolling = current start + (rows * bytes in a row)
\r
456 setVisibleStart(visStart + (rows * width));
\r
459 void scrolly(int bongy)
\r
467 for(int ti=0;ti<TILEWH;ti++)
\r
474 //king_crimson's code
\r
475 void hScroll(int Cols) {
\r
476 wait_for_retrace();
\r
478 outp(0x3C0, Cols & 3);
\r
480 outp(0x3D5, Cols >> 2);
\r
482 //setVisibleStart(visStart + (Cols * height));
\r
483 setVisibleStart(visStart + (Cols * width));
\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
492 ------------------------------------------------
\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
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
507 and here's how to use it
\r
509 -------------- Offset Register ---------------
\r
510 OUT 13H TO PORT 3D4H
\r
511 OUT value TO PORT 3D5H
\r
512 ----------------------------------------------
\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
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
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
528 0 0 ========================
\r
536 199 15920 ========================
\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
542 0 0 ------========================------
\r
545 .. .. | N S [ VISIBLE ] N S |
\r
546 | O I [ SCREEN ] O I |
\r
550 199 16318 ------========================------
\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
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
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
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
577 I'm sorry about this being so confusing but it's a bit difficult to explain.
\r
581 int loadfontX(char *fname)
\r
585 fp = fopen(fname, "rb");
\r
590 fread(Xfont, 8, 256, fp);
\r
596 void putchX(cord x, cord y, char c, byte color)
\r
604 vga_ptr = RowsX[y << 3] + (x << 1) + actStart;
\r
607 font_ptr = Xfont + (c << 3);
\r
611 temp = *font_ptr++;
\r
612 outpw(SEQU_ADDR, text_mask[temp & 0x0F]);
\r
613 *vga_ptr++ = color;
\r
615 outpw(SEQU_ADDR, text_mask[temp >> 4]);
\r
616 *vga_ptr-- = color;
\r
617 vga_ptr += widthBytes;
\r
621 void putstringX(cord x, cord y, char *str, byte color)
\r
629 vga_ptr = RowsX[y << 3] + (x << 1) + actStart;
\r
632 skip = 2 - (widthBytes << 3);
\r
634 while (c = *str++) {
\r
635 font_ptr = Xfont + (c << 3);
\r
639 temp = *font_ptr++;
\r
640 outpw(SEQU_ADDR, text_mask[temp & 0x0F]);
\r
641 *vga_ptr++ = color;
\r
643 outpw(SEQU_ADDR, text_mask[temp >> 4]);
\r
644 *vga_ptr-- = color;
\r
645 vga_ptr += widthBytes;
\r
652 /////////////////////////////////////////////////////////////////////////////
\r
654 // setvideo() - This function Manages the video modes //
\r
656 /////////////////////////////////////////////////////////////////////////////
\r
657 void setvideo(/*byte mode, */int vq){
\r
658 union REGS in, out;
\r
660 if(!vq){ // deinit the video
\r
661 // change to the video mode we were in before we switched to mode 13h
\r
663 in.h.al = old_mode;
\r
664 int86(0x10, &in, &out);
\r
666 }else if(vq == 1){ // init the video
\r
667 // get old video mode
\r
669 int86(0x10, &in, &out);
\r
670 old_mode = out.h.al;
\r
673 set320x240x256_X();
\r
677 /////////////////////////////////////////////////////////////////////////////
\r
679 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
680 // the Virtual screen. //
\r
682 /////////////////////////////////////////////////////////////////////////////
\r
683 void cls(byte color, byte *Where){
\r
684 _fmemset(Where, color, width*(height*17));
\r
687 //color
\82Ä
\82·
\82Æ
\r
689 if(gq < NUM_COLORS){
\r
696 //color
\82Ä
\82·
\82Æ
\r
699 //---- cls(gq, vaddr);
\r
706 //slow spectrum down
\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
718 if(svq == 7) coor++;
\r
719 if(sy == height && svq == 8) coor = rand()%NUM_COLORS;
\r
724 /*-----------ding-------------*/
\r
731 if((height)<yy<(height*2)){
\r
735 if((height*2)<yy<(height*3)){
\r
741 //++++ if(q <= 4 && q!=2 && gq == BONK-1) coor = rand()%HGQ;
\r
745 ) && gq == BONK-1){
\r
746 if(coor < HGQ && coor < LGQ) coor = LGQ;
\r
750 bakax = rand()%3; bakay = rand()%3;
\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
759 coor = rand()%NUM_COLORS;
\r
760 //---- cls(coor, vaddr);
\r
768 if(q == 9){ ssd(q); coor++; }
\r
772 if((q<5 && gq<BONK) || (q==16 && gq<BONK)){ // the number variable make the colors more noticable
\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
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
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
842 //interesting effects
\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
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
857 putPixel_X(xx, yy, coor);
\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
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
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
871 // drawText(0, 0, 15, getPixel_X(xx,yy));
\r
878 * The library testing routines follows below.
\r
889 int p, x, y, pages;
\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
894 printf("%d\n", pages);
\r
896 for (p = 0; p <= pages; ++p)
\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
904 for (x = 0; x <= width; ++x)
\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
911 for (y = 0; y <= height; ++y)
\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
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
923 // drawText(0, 0, 15, p);
\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
932 //drawText(0, 240, 15, "bakapi");
\r
939 * Library test (program) entry point.
\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
957 // puts("Then, check out Mode X, 320x240 with 3 (and a half) pages.");
\r
958 // puts("Press a key when ready...");
\r
963 /*temp = loadfontX("vga8x8.fnt");
\r
966 putstringX(0, 0, "bakapi!", 2);
\r
971 /*while(d!=0){ // on!
\r
972 if(!kbhit()){ // conditions of screen saver
\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
979 //if(key==3){xx=yy=0;} // crazy screen saver wwww
\r
984 while(!kbhit()){ // conditions of screen saver
\r
987 //end of screen savers
\r
991 while(!kbhit()){ // conditions of screen saver
\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