*\r
* Simple graphics library to accompany the article\r
* \r
- * INTRODUCTION TO MODE X.\r
+ * INTRODUCTION TO MODE X.\r
* \r
* This library provides the basic functions for initializing and using\r
* unchained (planar) 256-color VGA modes. Currently supported are:\r
*\r
- * - 320x200\r
- * - 320x240\r
+ * - 320x200\r
+ * - 320x240\r
*\r
* Functions are provided for:\r
*\r
- * - initializing one of the available modes\r
- * - setting the start address of the VGA refresh data\r
- * - setting active and visible display pages\r
- * - writing and reading a single pixel to/from video memory\r
+ * - initializing one of the available modes\r
+ * - setting the start address of the VGA refresh data\r
+ * - setting active and visible display pages\r
+ * - writing and reading a single pixel to/from video memory\r
*\r
* The library is provided as a demonstration only, and is not claimed\r
* to be particularly efficient or suited for any purpose. It has only\r
* Thanks go out to various helpful netters who spotted the 0xE7 bug\r
* in the set320x240x256() function!\r
*\r
- * modified by sparky4 so it can be compiled in open watcom ^^\r
+ * Modified by sparky4 so it can be compiled in open watcom ^^\r
*/\r
\r
\r
+\r
+\r
/*\r
* We 'require' a large data model simply to get rid of explicit 'far'\r
* pointers and compiler specific '_fmemset()' functions and the likes.\r
#if !defined(__COMPACT__)\r
# if !defined(__LARGE__)\r
# if !defined(__HUGE__)\r
-# error Large data model required! Try compiling with 'bcc -ml lib.c'.\r
+# error Large data model required! Try compiling with 'wcc -0 -ml lib.c'.\r
# endif\r
# endif\r
#endif\r
//code from old library!\r
/*src\lib\*/\r
#include "dos_gfx.h"\r
+#include "lib\x\modex.h"\r
\r
int old_mode;\r
//color \82Ä\82·\82Æ\r
/*\r
* Define the port addresses of some VGA registers.\r
*/\r
-#define CRTC_ADDR 0x3d4 /* Base port of the CRT Controller (color) */\r
+#define CRTC_ADDR 0x3d4 /* Base port of the CRT Controller (color) */\r
\r
-#define SEQU_ADDR 0x3c4 /* Base port of the Sequencer */\r
-#define GRAC_ADDR 0x3ce /* Base port of the Graphics Controller */\r
+#define SEQU_ADDR 0x3c4 /* Base port of the Sequencer */\r
+#define GRAC_ADDR 0x3ce /* Base port of the Graphics Controller */\r
\r
\r
/*\r
\r
/*\r
* set320x200x256_X()\r
- * sets mode 13h, then turns it into an unchained (planar), 4-page\r
- * 320x200x256 mode.\r
+ * sets mode 13h, then turns it into an unchained (planar), 4-page\r
+ * 320x200x256 mode.\r
*/\r
void set320x200x256_X(void)\r
- {\r
- union REGS r;\r
-\r
- /* Set VGA BIOS mode 13h: */\r
- r.x.ax = 0x0013;\r
- int86(0x10, &r, &r);\r
-\r
- /* Turn off the Chain-4 bit (bit 3 at index 4, port 0x3c4): */\r
- outpw(SEQU_ADDR, 0x0604);\r
-\r
- /* Turn off word mode, by setting the Mode Control register\r
- of the CRT Controller (index 0x17, port 0x3d4): */\r
- outpw(CRTC_ADDR, 0xE317);\r
-\r
- /* Turn off doubleword mode, by setting the Underline Location\r
- register (index 0x14, port 0x3d4): */\r
- outpw(CRTC_ADDR, 0x0014);\r
-\r
- /* Clear entire video memory, by selecting all four planes, then\r
- writing 0 to entire segment. */\r
- outpw(SEQU_ADDR, 0x0F02);\r
- memset(vga+1, 0, 0xffff); /* stupid size_t exactly 1 too small */\r
- vga[0] = 0;\r
-\r
- /* Update the global variables to reflect dimensions of this\r
- mode. This is needed by most future drawing operations. */\r
- width = 320;\r
- height = 200;\r
-\r
- /* Each byte addresses four pixels, so the width of a scan line\r
- in *bytes* is one fourth of the number of pixels on a line. */\r
- widthBytes = width / 4;\r
+ {\r
+ union REGS r;\r
+\r
+ /* Set VGA BIOS mode 13h: */\r
+ r.x.ax = 0x0013;\r
+ int86(0x10, &r, &r);\r
+\r
+ /* Turn off the Chain-4 bit (bit 3 at index 4, port 0x3c4): */\r
+ outpw(SEQU_ADDR, 0x0604);\r
+\r
+ /* Turn off word mode, by setting the Mode Control register\r
+ of the CRT Controller (index 0x17, port 0x3d4): */\r
+ outpw(CRTC_ADDR, 0xE317);\r
+\r
+ /* Turn off doubleword mode, by setting the Underline Location\r
+ register (index 0x14, port 0x3d4): */\r
+ outpw(CRTC_ADDR, 0x0014);\r
+\r
+ /* Clear entire video memory, by selecting all four planes, then\r
+ writing 0 to entire segment. */\r
+ outpw(SEQU_ADDR, 0x0F02);\r
+ memset(vga+1, 0, 0xffff); /* stupid size_t exactly 1 too small */\r
+ vga[0] = 0;\r
+\r
+ /* Update the global variables to reflect dimensions of this\r
+ mode. This is needed by most future drawing operations. */\r
+ width = 320;\r
+ height = 200;\r
+\r
+ /* Each byte addresses four pixels, so the width of a scan line\r
+ in *bytes* is one fourth of the number of pixels on a line. */\r
+ widthBytes = width / 4;\r
+\r
+ /* By default we want screen refreshing and drawing operations\r
+ to be based at offset 0 in the video segment. */\r
+ actStart = visStart = 0;\r
+\r
+ /*\r
+--------------------\r
+HORIZONTAL SCROLLING\r
+--------------------\r
+Horizontal scrolling is essentially the same as vertical scrolling, all\r
+you do is increment or decrement the VGA offset register by 1 instead of\r
+80 as with vertical scrolling.\r
+\r
+However, horizontal scrolling is complicated by two things\r
+\r
+ 1. Incrementing the offset register by one actually scrolls by FOUR\r
+ pixels (and there are FOUR planes on the VGA, what a coincidence)\r
+\r
+ 2. You can't draw the image off the screen and then scroll it on\r
+ because of the way the VGA wraps to the next row every 80 bytes\r
+ (80 bytes * 4 planes = 320 pixels), if you tried it, you would\r
+ actually be drawing to the other side of the screen (which is\r
+ entirely visible)\r
+\r
+I'll solve these problems one at a time.\r
+\r
+Firstly, to get the VGA to scroll by only one pixel you use the horizontal\r
+pixel panning (HPP) register. This register resides at\r
+\r
+ PORT: 3C0H\r
+ INDEX: 13h\r
+\r
+and in real life, you use it like this\r
+\r
+----------------- Pixel Panning ---------------\r
+IN PORT 3DAH (this clears an internal\r
+ flip-flop of the VGA)\r
+OUT 13H TO PORT 3C0H\r
+OUT value TO PORT 3C0H (where "value" is the\r
+ number of pixels to offset)\r
+-----------------------------------------------\r
+*/\r
+//\r
+// inp(0x3DA);\r
+// outp(0x3C0, 0x13);\r
\r
- /* By default we want screen refreshing and drawing operations\r
- to be based at offset 0 in the video segment. */\r
- actStart = visStart = 0;\r
- }\r
+ }\r
\r
/*\r
* setActiveStart() tells our graphics operations which address in video\r
* memory should be considered the top left corner.\r
*/\r
void setActiveStart(unsigned offset)\r
- {\r
- actStart = offset;\r
- }\r
+ {\r
+ actStart = offset;\r
+ }\r
\r
/*\r
* setVisibleStart() tells the VGA from which byte to fetch the first\r
* set, but before the low byte is set, which produces a bad flicker.\r
*/\r
void setVisibleStart(unsigned offset)\r
- {\r
- visStart = offset;\r
- outpw(CRTC_ADDR, 0x0C); /* set high byte */\r
- outpw(CRTC_ADDR+1, visStart >> 8);\r
- outpw(CRTC_ADDR, 0x0D); /* set low byte */\r
- outpw(CRTC_ADDR+1, visStart & 0xff);\r
- }\r
+ {\r
+ visStart = offset;\r
+ outpw(CRTC_ADDR, 0x0C); /* set high byte */\r
+ outpw(CRTC_ADDR+1, visStart >> 8);\r
+ outpw(CRTC_ADDR, 0x0D); /* set low byte */\r
+ outpw(CRTC_ADDR+1, visStart & 0xff);\r
+ }\r
\r
/*\r
* setXXXPage() sets the specified page by multiplying the page number\r
* function. The first page is number 0.\r
*/\r
void setActivePage(int page)\r
- {\r
- setActiveStart(page * widthBytes * height);\r
- }\r
+ {\r
+ setActiveStart(page * widthBytes * height);\r
+ }\r
\r
void setVisiblePage(int page)\r
- {\r
- setVisibleStart(page * widthBytes * height);\r
- }\r
+ {\r
+ setVisibleStart(page * widthBytes * height);\r
+ }\r
\r
void putPixel_X(int x, int y, byte color)\r
- {\r
- /* Each address accesses four neighboring pixels, so set\r
- Write Plane Enable according to which pixel we want\r
- to modify. The plane is determined by the two least\r
- significant bits of the x-coordinate: */\r
- outp(0x3c4, 0x02);\r
- outp(0x3c5, 0x01 << (x & 3));\r
-\r
- /* The offset of the pixel into the video segment is\r
- offset = (width * y + x) / 4, and write the given\r
- color to the plane we selected above. Heed the active\r
- page start selection. */\r
- vga[(unsigned)(widthBytes * y) + (x / 4) + actStart] = color;\r
+ {\r
+ /* Each address accesses four neighboring pixels, so set\r
+ Write Plane Enable according to which pixel we want\r
+ to modify. The plane is determined by the two least\r
+ significant bits of the x-coordinate: */\r
+ outp(0x3c4, 0x02);\r
+ outp(0x3c5, 0x01 << (x & 3));\r
+\r
+ /* The offset of the pixel into the video segment is\r
+ offset = (width * y + x) / 4, and write the given\r
+ color to the plane we selected above. Heed the active\r
+ page start selection. */\r
+ vga[(unsigned)(widthBytes * y) + (x / 4) + actStart] = color;\r
\r
- }\r
+ }\r
\r
byte getPixel_X(int x, int y)\r
- {\r
- /* Select the plane from which we must read the pixel color: */\r
- outpw(GRAC_ADDR, 0x04);\r
- outpw(GRAC_ADDR+1, x & 3);\r
+ {\r
+ /* Select the plane from which we must read the pixel color: */\r
+ outpw(GRAC_ADDR, 0x04);\r
+ outpw(GRAC_ADDR+1, x & 3);\r
\r
- return vga[(unsigned)(widthBytes * y) + (x / 4) + actStart];\r
+ return vga[(unsigned)(widthBytes * y) + (x / 4) + actStart];\r
\r
- }\r
+ }\r
\r
void set320x240x256_X(void)\r
- {\r
- /* Set the unchained version of mode 13h: */\r
- set320x200x256_X();\r
-\r
- /* Modify the vertical sync polarity bits in the Misc. Output\r
- Register to achieve square aspect ratio: */\r
- outp(0x3C2, 0xE3);\r
-\r
- /* Modify the vertical timing registers to reflect the increased\r
- vertical resolution, and to center the image as good as\r
- possible: */\r
- outpw(0x3D4, 0x2C11); /* turn off write protect */\r
- outpw(0x3D4, 0x0D06); /* vertical total */\r
- outpw(0x3D4, 0x3E07); /* overflow register */\r
- outpw(0x3D4, 0xEA10); /* vertical retrace start */\r
- outpw(0x3D4, 0xAC11); /* vertical retrace end AND wr.prot */\r
- outpw(0x3D4, 0xDF12); /* vertical display enable end */\r
- outpw(0x3D4, 0xE715); /* start vertical blanking */\r
- outpw(0x3D4, 0x0616); /* end vertical blanking */\r
-\r
- /* Update mode info, so future operations are aware of the\r
- resolution */\r
- height = 240;\r
+ {\r
+ /* Set the unchained version of mode 13h: */\r
+ set320x200x256_X();\r
+\r
+ /* Modify the vertical sync polarity bits in the Misc. Output\r
+ Register to achieve square aspect ratio: */\r
+ outp(0x3C2, 0xE3);\r
+\r
+ /* Modify the vertical timing registers to reflect the increased\r
+ vertical resolution, and to center the image as good as\r
+ possible: */\r
+ outpw(0x3D4, 0x2C11); /* turn off write protect */\r
+ outpw(0x3D4, 0x0D06); /* vertical total */\r
+ outpw(0x3D4, 0x3E07); /* overflow register */\r
+ outpw(0x3D4, 0xEA10); /* vertical retrace start */\r
+ outpw(0x3D4, 0xAC11); /* vertical retrace end AND wr.prot */\r
+ outpw(0x3D4, 0xDF12); /* vertical display enable end */\r
+ outpw(0x3D4, 0xE715); /* start vertical blanking */\r
+ outpw(0x3D4, 0x0616); /* end vertical blanking */\r
+\r
+ /* Update mode info, so future operations are aware of the\r
+ resolution */\r
+ height = 240;\r
+\r
+ }\r
+\r
+\r
+/*-----------XXXX-------------*/
+
+/////////////////////////////////////////////////////////////////////////////\r
+// //\r
+// WaitRetrace() - This waits until you are in a Verticle Retrace. //\r
+// //\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+void WaitRetrace() {\r
+\r
+// register char qy;\r
+\r
+ in.h.dx = 0x03DA;\r
+ in.h.al = in.h.dx;\r
+ \r
+ in.h.al &= 0x08;\r
+ int86(0x10, &in, &out);\r
+\r
+\r
+ /*l1: asm {\r
+ in al,0x03DA;\r
+ and al,0x08;\r
+ jnz l2;\r
+ }*/\r
+}
+
+/////////////////////////////////////////////////////////////////////////////\r
+// //\r
+// MoveTo() - This moves to position X*4 on a chain 4 screen. //\r
+// Note: As soon as I find documentation, this function //\r
+// will be better documented. - Snowman //\r
+// //\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+void MoveTo (word X, word Y) {\r
+\r
+// word O = Y*SIZE*2+X;
+ word O = Y*widthBytes*2+X;\r
+\r
+ asm {\r
+ mov bx, [O]\r
+ mov ah, bh\r
+ mov al, 0x0C\r
+\r
+ mov dx, 0x3D4\r
+ out dx, ax\r
+\r
+ mov ah, bl\r
+ mov al, 0x0D\r
+ mov dx, 0x3D4\r
+ out dx, ax\r
+ }
+
+;-----------------------------------------------------------\r
+;\r
+; MXPN.ASM - Panning function\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+;WARN PRO\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxPan\r
+\r
+EXTRN mxWaitDisplay : FAR\r
+EXTRN mxStartAddress : FAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Moves the screen.\r
+;\r
+; Input:\r
+; X, Y = new X, Y coordinates of view screen\r
+; Output:\r
+; none\r
+;\r
+mxPan PROC FAR\r
+ ARG Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+\r
+ mov ax, [Y]\r
+ mul [mx_BytesPerLine]\r
+ mov dx, [X]\r
+ shr dx, 1\r
+ shr dx, 1\r
+ add ax, dx\r
+ push ax ; Push the start address\r
+ call mxWaitDisplay\r
+ call mxStartAddress\r
+\r
+ mov dx, 03DAh ; Set the pixel pan register\r
+ in al, dx\r
+ mov dx, 03C0h\r
+ mov al, 33h\r
+ out dx, al\r
+ mov al, BYTE PTR [X]\r
+ and al, 3\r
+ shl al, 1\r
+ out dx, al\r
+\r
+ xor ax, ax\r
+ .leave ARG_SIZE\r
+mxPan ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r
+
+\r
+}
+
+//Procedure Play;\r
+void Play()\r
+{\r
+ int loop1,loop2;\r
+ int xpos,ypos,xdir,ydir;\r
+ //int ch;\r
+// for(loop1=1;loop1<=62;loop1++)\r
+ //Pal ((char)loop1,(char)loop1,(char)0,(char)(62-loop1)); // { This sets up the pallette for the pic }\r
+\r
+ moveto(0,0,Size); // { This moves the view to the top left hand corner }\r
+\r
+/* for(loop1=0;loop1<=3;loop1++)\r
+ for(loop2=0;loop2<=5;loop2++)\r
+ Putpic (loop1*160,loop2*66); // { This places the picture all over the\r
+ // chain-4 screen }\r
+ getch();\r
+ ch=0x0;*/\r
+// xpos=rand (78)+1;\r
+// ypos=rand (198)+1; // { Random start positions for the view }
+ xpos=0;
+ ypos=0;\r
+ xdir=1;\r
+ ydir=1;\r
+// while(1)\r
+// {\r
+ WaitRetrace(); // { Take this out and watch the screen go crazy! }\r
+ moveto (xpos,ypos,Size);\r
+ xpos=xpos+xdir;\r
+ ypos=ypos+ydir;\r
+ if( (xpos>79) || (xpos<1))xdir=-xdir;\r
+ if( (ypos>199) || (ypos<1))ydir=-ydir; // { Hit a boundry, change\r
+ // direction! }\r
+// if(_bios_keybrd(_KEYBRD_READY))ch=getch();\r
+// if(ch==0x71)break; // 'q'\r
+// if(ch==0x1b)break; // 'ESC'\r
+// }\r
+}
+\r
+/*tile*/\r
+//king_crimson's code\r
+void putColorBox_X(int x, int y, int w, int h, byte color) {\r
+ outp(0x3c4, 0x02);\r
+\r
+ int curx, cury;\r
+ unsigned drawptr;\r
+ for (curx=x; curx<(x+w); curx++) {\r
+ outp(0x3c5, 0x01 << (curx & 3));\r
+ drawptr = (unsigned)(widthBytes * y) + (curx / 4) + actStart;\r
+ for (cury=0; cury<h; cury++) {\r
+ vga[drawptr] = color;\r
+ drawptr += widthBytes;\r
+ }\r
+ }\r
+}\r
+\r
+void vScroll(int rows)\r
+{\r
+ // Scrolling = current start + (rows * bytes in a row)\r
+ setVisibleStart(visStart + (rows * width));\r
+}\r
+\r
+void scrolly(int bongy)\r
+{\r
+ int boingy=0;\r
+ if(bongy<0)\r
+ boingy=-1;\r
+ else if(bongy>0)\r
+ boingy=1;\r
\r
+ for(int ti=0;ti<TILEWH;ti++)\r
+ {\r
+ delay(1);\r
+ vScroll(boingy);\r
}\r
+}\r
\r
+//king_crimson's code\r
+void hScroll(int Cols) {\r
+ inp(0x3DA);\r
+ outp(0x3C0, 0x13);\r
+ outp(0x3C0, Cols & 3);\r
+ outp(0x3D4, 0x13);\r
+ outp(0x3D5, Cols/* >> 2*/);\r
+ //setVisibleStart(visStart + (Cols * height));\r
+ setVisibleStart(visStart + (Cols * width));\r
+}\r
\r
-/*-----------XXXX-------------*/\r
+/*To implement smooth horizontal scrolling, you would do the following:\r
+-------------- Horizontal Scrolling ------------\r
+FOR X = 0 TO 319 DO\r
+ SET HPP TO ( X MOD 4 )\r
+ SET VGA OFFSET TO ( X/4 )\r
+END FOR\r
+------------------------------------------------\r
+\r
+Okay, no problem at all (although I think you might have to fiddle\r
+around with the HPP a bit to get it right...try different values and\r
+see what works :).\r
+\r
+So, the next problem is with drawing the images off the screen where\r
+they aren't visible and then scrolling them on!!! As it turns out,\r
+there's yet ANOTHER register to accomplish this. This one's called the\r
+offset register (no, not the one I was talking about before, that one\r
+was actually the "start address" register) and it's at\r
+\r
+ PORT: 3D4H/3D5H\r
+ OFFSET: 13H\r
+\r
+and here's how to use it\r
+\r
+-------------- Offset Register ---------------\r
+OUT 13H TO PORT 3D4H\r
+OUT value TO PORT 3D5H\r
+----------------------------------------------\r
+\r
+Now, what my VGA reference says is that this register holds the number\r
+of bytes (not pixels) difference between the start address of each row.\r
+So, in X-mode it normally contains the value 80 (as we remember,\r
+80 bytes * 4 planes = 320 pixels). This register does not affect the\r
+VISIBLE width of the display, only the difference between addresses on\r
+each row.\r
+\r
+When we scroll horizontally, we need a little bit of extra working space\r
+so we can draw off the edge of the screen.\r
+\r
+Perhaps a little diagram will clarify it. The following picture is of a\r
+standard X-mode addressing scheme with the OFFSET register set to 80.\r
+\r
+ ROW OFFSET\r
+ 0 0 ========================\r
+ 1 80 [ ]\r
+ 2 160 [ ]\r
+ .. .. [ VISIBLE ]\r
+ [ SCREEN ]\r
+ [ ]\r
+ [ ]\r
+ .. .. [ ]\r
+ 199 15920 ========================\r
+\r
+and the next diagram is of a modified addressing scheme with the OFFSET\r
+register set to 82 (to give us 4 extra pixels on each side of the screen)\r
+\r
+ROW OFFSET\r
+0 0 ------========================------\r
+1 82 | V [ ] V |\r
+2 164 | I [ ] I |\r
+.. .. | N S [ VISIBLE ] N S |\r
+ | O I [ SCREEN ] O I |\r
+ | T B [ ] T B |\r
+ | L [ ] L |\r
+.. .. | E [ ] E |\r
+199 16318 ------========================------\r
+\r
+Beautiful!!!\r
+\r
+As with vertical scrolling, however, you still have the problem of when\r
+you reach the bottom of page 4...and it's fixed in the same manner.\r
+\r
+I haven't actually managed to get infinite horizontal scrolling working,\r
+but the method I have just stated will give you a horizontal scrolling\r
+range of over 200 screens!!!! So if you need more (which is extremely\r
+unlikely), figure it out yourself.\r
+\r
+\r
+------------------\r
+COMBINED SCROLLING\r
+------------------\r
+To do both horizontal and vertical scrolling, all you have to do is combine\r
+the two methods with a few little extras (it's always the way isn't it).\r
+\r
+You have to start off with the original screen on the current page and the\r
+next page as well. When you scroll horizontally, you have to draw the edge\r
+that's coming in to the screen to BOTH pages (that means you'll be drawing\r
+the incoming edge twice, once for each page). You do this so that when you\r
+have scrolled vertically down through a complete page, you can jump back\r
+to the first page and it will (hopefully) have an identical copy, and you\r
+can then continue scrolling again.\r
+\r
+I'm sorry about this being so confusing but it's a bit difficult to explain.\r
+\r
+\r
+*/\r
//---------------------------------------------------\r
//\r
// Use the bios to get the address of the 8x8 font\r
//\r
// You need a font if you are going to draw text.\r
//\r
-\r
+/*\r
int far *\r
getFont()\r
{\r
- union REGPACK rg;\r
- int seg;\r
- int off;\r
- memset(&rg, 0, sizeof(rg));\r
-\r
- rg.w.ax = 0x1130;\r
- rg.h.bh = 0x03;\r
- intr(0x10, &rg);\r
- seg = rg.w.es;\r
- off = rg.w.bp;\r
- \r
-\r
- return (int far *)MK_FP(seg, off);\r
+ union REGPACK rg;\r
+ int seg;\r
+ int off;\r
+ memset(&rg, 0, sizeof(rg));\r
+\r
+ rg.w.ax = 0x1130;\r
+ rg.h.bh = 0x03;\r
+ intr(0x10, &rg);\r
+ seg = rg.w.es;\r
+ off = rg.w.bp;\r
+ \r
+\r
+ return (int far *)MK_FP(seg, off);\r
}\r
\r
void drawChar(int x, int y, int color, byte c)\r
{\r
- int i, j;\r
- int mask;\r
- int far *font = getFont() + (c * 8);\r
+ int i, j;\r
+ int mask;\r
+ int far *font = getFont() + (c * 8);\r
\r
- for (i = 0; i < 8; i++)\r
- {\r
- mask = *font;\r
- for (j = 0; j < 8; j++)\r
+ for (i = 0; i < 8; i++)\r
{\r
- if (mask & 0x80)\r
- {\r
- //pixel(x + j, y + i, color);\r
- putPixel_X(x + j, y + i, color);\r
- }\r
- mask <<= 1;\r
+ mask = *font;\r
+ for (j = 0; j < 8; j++)\r
+ {\r
+ if (mask & 0x80)\r
+ {\r
+ //pixel(x + j, y + i, color);\r
+ putPixel_X(x + j, y + i, color);\r
+ }\r
+ mask <<= 1;\r
+ }\r
+ font++;\r
}\r
- font++;\r
- }\r
}\r
\r
void drawText(int x, int y, int color, byte string)\r
{\r
- while (string)\r
- {\r
- drawChar(x, y, color, string);\r
- x += 8;\r
- string++;\r
- }\r
+ while (string)\r
+ {\r
+ drawChar(x, y, color, string);\r
+ x += 8;\r
+ string++;\r
+ }\r
}\r
-\r
+*/\r
/////////////////////////////////////////////////////////////////////////////\r
// //\r
-// setvideo() - This function Manages the video modes //\r
+// setvideo() - This function Manages the video modes //\r
// //\r
/////////////////////////////////////////////////////////////////////////////\r
void setvideo(/*byte mode, */int vq){\r
- union REGS in, out;\r
-\r
- if(!vq){ // deinit the video\r
- // change to the video mode we were in before we switched to mode 13h\r
- in.h.ah = 0x00;\r
- in.h.al = old_mode;\r
- int86(0x10, &in, &out);\r
-\r
- }else if(vq == 1){ // init the video\r
- // get old video mode\r
- in.h.ah = 0xf;\r
- int86(0x10, &in, &out);\r
- old_mode = out.h.al;\r
-\r
- // enter mode\r
- set320x240x256_X();\r
- }\r
+ union REGS in, out;\r
+\r
+ if(!vq){ // deinit the video\r
+ // change to the video mode we were in before we switched to mode 13h\r
+ in.h.ah = 0x00;\r
+ in.h.al = old_mode;\r
+ int86(0x10, &in, &out);\r
+\r
+ }else if(vq == 1){ // init the video\r
+ // get old video mode\r
+ in.h.ah = 0xf;\r
+ int86(0x10, &in, &out);\r
+ old_mode = out.h.al;\r
+\r
+ // enter mode\r
+ set320x240x256_X();\r
+ }\r
}\r
\r
/////////////////////////////////////////////////////////////////////////////\r
-// //\r
+// //\r
// cls() - This clears the screen to the specified color, on the VGA or on //\r
-// the Virtual screen. //\r
-// //\r
+// the Virtual screen. //\r
+// //\r
/////////////////////////////////////////////////////////////////////////////\r
void cls(byte color, byte *Where){\r
- _fmemset(Where, color, width*height);\r
+ _fmemset(Where, color, width*(height*17));\r
}\r
\r
//color \82Ä\82·\82Æ\r
int colortest(){\r
- if(gq < NUM_COLORS){\r
- cls(gq, vga);\r
- gq++;\r
- }else gq = 0;\r
- return gq;\r
+ if(gq < NUM_COLORS){\r
+ cls(gq, vga);\r
+ gq++;\r
+ }else gq = 0;\r
+ return gq;\r
}\r
\r
//color \82Ä\82·\82Æ\r
int colorz(){\r
- if(gq < HGQ){\r
-//---- cls(gq, vaddr);\r
- cls(gq, vga);\r
- gq++;\r
- }else gq = LGQ;\r
- return gq;\r
+ if(gq < HGQ){\r
+//---- cls(gq, vaddr);\r
+ cls(gq, vga);\r
+ gq++;\r
+ }else gq = LGQ;\r
+ return gq;\r
}\r
\r
//slow spectrum down\r
void ssd(int svq){\r
- if(sy < height+1){\r
- if(sx < width+1){\r
- //plotpixel(xx, yy, coor, vga);\r
- //ppf(sx, sy, coor, vga);\r
- putPixel_X(sx, sy, coor);\r
- //printf("%d %d %d %d\n", sx, sy, svq, coor);\r
- sx++;\r
- }else sx = 0;\r
- if(sx == width){\r
- sy++;\r
- if(svq == 7) coor++;\r
- if(sy == height && svq == 8) coor = rand()%NUM_COLORS;\r
- }\r
- }else sy = 0;\r
+ if(sy < height+1){\r
+ if(sx < width+1){\r
+ //plotpixel(xx, yy, coor, vga);\r
+ //ppf(sx, sy, coor, vga);\r
+ putPixel_X(sx, sy, coor);\r
+ //printf("%d %d %d %d\n", sx, sy, svq, coor);\r
+ sx++;\r
+ }else sx = 0;\r
+ if(sx == width){\r
+ sy++;\r
+ if(svq == 7) coor++;\r
+ if(sy == height && svq == 8) coor = rand()%NUM_COLORS;\r
+ }\r
+ }else sy = 0;\r
}\r
\r
/*-----------ding-------------*/\r
int ding(int q){\r
- setActivePage(0);\r
- setVisiblePage(0);\r
- int d3y;\r
-\r
-//++++ if(q <= 4 && q!=2 && gq == BONK-1) coor = rand()%HGQ;\r
- if((q == 2
- ||q==4
- ) && gq == BONK-1){\r
- if(coor < HGQ && coor < LGQ) coor = LGQ;\r
- if(coor < HGQ-1){\r
- coor++;\r
- }else{ coor = LGQ;\r
- bakax = rand()%3; bakay = rand()%3;\r
- }\r
- }\r
\r
- if(q == 5){ colortest(); return gq; }\r
- if(q == 10){ colorz(); return gq; }\r
- if(q == 11){ colorz(); delay(100); return gq; }\r
- if(q == 8){ ssd(q); /*printf("%d\n", coor);*/ }\r
- if(q == 6){\r
- coor = rand()%NUM_COLORS;\r
-//---- cls(coor, vaddr);\r
- cls(coor, vga);\r
- //updatevbuff();\r
+// if(yy<height){\r
+ setActivePage(0);\r
+ setVisiblePage(0);\r
+/* }\r
+ if((height)<yy<(height*2)){\r
+ setActivePage(1);\r
+ setVisiblePage(1);\r
}\r
+ if((height*2)<yy<(height*3)){\r
+ setActivePage(2);\r
+ setVisiblePage(2);\r
+ }*/\r
+ int d3y;\r
+\r
+//++++ if(q <= 4 && q!=2 && gq == BONK-1) coor = rand()%HGQ;\r
+ if((q == 2\r
+ ||q==4\r
+ ||q==16\r
+ ) && gq == BONK-1){\r
+ if(coor < HGQ && coor < LGQ) coor = LGQ;\r
+ if(coor < HGQ){\r
+ coor++;\r
+ }else{ coor = LGQ;\r
+ bakax = rand()%3; bakay = rand()%3;\r
+ }\r
+ }\r
\r
- if(q == 7 || q== 9){\r
- if(gq < HGQ){\r
- if(q == 7) ssd(q);\r
- if(q == 9){ ssd(q); coor++; }\r
- gq++;\r
- }else gq = LGQ;\r
- }\r
- if(q<5 && gq<BONK){ // the number variable make the colors more noticable\r
- if(q==1){\r
- if(xx==width){bakax=0;}\r
- if(xx==0){bakax=1;}\r
- if(yy==height){bakay=0;}\r
- if(yy==0){bakay=1;}\r
- }else if(q==3){\r
- if(xx!=width||yy!=height){\r
- if(xx==0){bakax=1;bakay=-1;d3y=1;}\r
- if(yy==0){bakax=1;bakay=0;d3y=1;}\r
- if(xx==width){bakax=-1;bakay=-1;d3y=1;}\r
- if(yy==height){bakax=1;bakay=0;d3y=1;}\r
- }else if(xx==width&&yy==height) xx=yy=0;\r
+ if(q == 8){ colorz(); return gq; }else\r
+ if(q == 10){ ssd(q); /*printf("%d\n", coor);*/ }else\r
+ if(q == 5){ colortest(); return gq; }else\r
+ if(q == 11){ colorz(); delay(100); return gq; }\r
+ if(q == 6){\r
+ coor = rand()%NUM_COLORS;\r
+//---- cls(coor, vaddr);\r
+ cls(coor, vga);\r
+ //updatevbuff();\r
}\r
- if(q==3){\r
- if(d3y){\r
- if(bakay<0){\r
- yy--;\r
- d3y--;\r
- }else\r
- if(bakay>0){\r
- yy++;\r
- d3y--;\r
- }\r
- }\r
- if(bakax<0){\r
- xx--;\r
- }else\r
- if(bakax>0){\r
- xx++;\r
- }\r
- }else{\r
- if(!bakax){\r
- xx--;\r
- }else if(bakax>1){\r
- xx++;\r
- }\r
- if(!bakay){\r
- yy--;\r
- }else if(bakay>1){\r
- yy++;\r
- }\r
+\r
+ if(q == 7 || q== 9){\r
+ if(gq < HGQ){\r
+ if(q == 7) ssd(q);\r
+ if(q == 9){ ssd(q); coor++; }\r
+ gq++;\r
+ }else gq = LGQ;\r
}\r
- // fixer\r
- if(xx<0) xx=width;\r
- if(yy<0) yy=height;\r
- if(xx>width) xx=0;\r
- if(yy>height) yy=0;\r
-\r
- // plot the pixel\r
-//---- ppf(xx, yy, coor, vga);\r
- putPixel_X(xx, yy, coor);\r
-//---- if(q==2) ppf(rand()%, rand()%height, 0, vga);\r
- if(q==2) putPixel_X(rand()%width, rand()%height, 0);\r
- if(q==2||q==4){ bakax = rand()%3; bakay = rand()%3; }\r
- gq++;\r
-//if(xx<0||xx>320||yy<0||yy>240)\r
-// printf("%d %d %d %d %d %d\n", xx, yy, coor, bakax, bakay, getPixel_X(xx,yy));\r
-// printf("%d\n", getPixel_X(xx,yy));\r
+ if((q<5 && gq<BONK) || (q==16 && gq<BONK)){ // the number variable make the colors more noticable\r
+ if(q==1){\r
+ if(xx==width){bakax=0;}\r
+ if(xx==0){bakax=1;}\r
+ if(yy==height){bakay=0;}\r
+ if(yy==0){bakay=1;}\r
+ }else if(q==3){\r
+ if(xx!=width||yy!=height){\r
+ if(xx==0){bakax=1;bakay=-1;d3y=1;}\r
+ if(yy==0){bakax=1;bakay=0;d3y=1;}\r
+ if(xx==width){bakax=-1;bakay=-1;d3y=1;}\r
+ if(yy==height){bakax=1;bakay=0;d3y=1;}\r
+ }else if(xx==width&&yy==height) xx=yy=0;\r
+ }\r
+ if(q==3){\r
+ if(d3y){\r
+ if(bakay<0){\r
+ yy--;\r
+ d3y--;\r
+ }else\r
+ if(bakay>0){\r
+ yy++;\r
+ d3y--;\r
+ }\r
+ }\r
+ if(bakax<0){\r
+ xx--;\r
+ }else\r
+ if(bakax>0){\r
+ xx++;\r
+ }\r
+ }else{\r
+ if(q==16)\r
+ {\r
+ if(!bakax){\r
+ xx--;//=TILEWH;\r
+ }else if(bakax>0){\r
+ xx++;//=TILEWH;\r
+ }\r
+ if(!bakay){\r
+ yy--;//=TILEWH;\r
+ }else if(bakay>0){\r
+ yy++;//=TILEWH;\r
+ }\r
+ }else{\r
+ if(!bakax){\r
+// xx-=TILEWH;\r
+ xx--;\r
+ }else if(bakax>1){\r
+// xx+=TILEWH;\r
+ xx++;\r
+ }\r
+ if(!bakay){\r
+// yy-=TILEWH;\r
+ yy--;\r
+ }else if(bakay>1){\r
+// yy+=TILEWH;\r
+ yy++;\r
+ }\r
+ }\r
+ }\r
+ // fixer\r
+// if(q!=16){\r
+//if(q!=16)\r
+ if(xx<(0/*-TILEWH*/)) xx=(width/*+TILEWH*/);\r
+ if(yy<0) yy=(height*3);\r
+ if(xx>(width/*+TILEWH*/)) xx=(0/*-TILEWH*/);\r
+ if(yy>(height*3)) yy=0;\r
+// }\r
+\r
+//interesting effects\r
+ if(q==16)\r
+ {\r
+ int tx=0,ty=0;\r
+ tx+=xx+16;\r
+ ty+=yy+16;\r
+ putPixel_X(tx, ty, coor);\r
+ //drawrect(tx, ty, tx+TILEWH, ty+TILEWH, coor);\r
+ //printf("%d %d %d %d %d %d\n", xx, yy, tx, ty, TILEWH);\r
+\r
+ // plot the pixel\r
+//---- ppf(xx, yy, coor, vga);\r
+ }else /*if(xx>=0 && xx<width && yy>=0 && yy<(height*3))*/{\r
+// putColorBox_X(xx, yy, TILEWH, TILEWH, coor);\r
+//++++0000\r
+ putPixel_X(xx, yy, coor);\r
+ } \r
+\r
+//---- if(q==2) ppf(rand()%, rand()%height, 0, vga);\r
+// if(q==2) putColorBox_X(rand()%width, rand()%(height*3), TILEWH, TILEWH, 0);\r
+//++++0000\r
+ if(q==2) putPixel_X(rand()%width, rand()%(height*3), 0);\r
+ if(q==16) putPixel_X(rand()%width, rand()%(height*3), 0);\r
+ if(q==2||q==4||q==16){ bakax = rand()%3; bakay = rand()%3; }\r
+ gq++;\r
+//if(xx<0||xx>320||yy<0||yy>(height*3))\r
+// printf("%d %d %d %d %d %d\n", xx, yy, coor, bakax, bakay, getPixel_X(xx,yy));\r
+// printf("%d\n", getPixel_X(xx,yy));\r
//0000\r
-// drawText(0, 0, 15, getPixel_X(xx,yy));\r
- }else gq = LGQ;\r
- return gq;\r
+// drawText(0, 0, 15, getPixel_X(xx,yy));\r
+ }else gq = LGQ;\r
+ return gq;\r
}\r
\r
\r
#include <conio.h>\r
\r
void doTest(void)\r
- {\r
- int p, x, y, pages;\r
+ {\r
+ int p, x, y, pages;\r
\r
- /* This is the way to calculate the number of pages available. */\r
- pages = 65536L/(widthBytes*height); // apparently this takes the A000 address
+ /* This is the way to calculate the number of pages available. */\r
+ pages = 65536L/(widthBytes*height); // apparently this takes the A000 address\r
\r
- printf("%d\n", pages);
-
- for (p = 0; p <= pages; ++p)\r
- {\r
- setActivePage(p);\r
+ printf("%d\n", pages);\r
\r
- /* On each page draw a single colored border, and dump the palette\r
- onto a small square about the middle of the page. */
-
- //{\r
- for (x = 0; x <= width; ++x)\r
+ for (p = 0; p <= pages; ++p)\r
{\r
- putPixel_X(x, 0, p+1);\r
- if(p!=pages) putPixel_X(x, height-1, p+1);
- else putPixel_X(x, 99-1, p+1);\r
+ setActivePage(p);\r
+\r
+ /* On each page draw a single colored border, and dump the palette\r
+ onto a small square about the middle of the page. */\r
+\r
+ //{\r
+ for (x = 0; x <= width; ++x)\r
+ {\r
+ putPixel_X(x, 0, p+1);\r
+ if(p!=pages) putPixel_X(x, height-1, p+1);\r
+ else putPixel_X(x, 99-1, p+1);\r
+ }\r
+\r
+ for (y = 0; y <= height; ++y)\r
+ {\r
+ putPixel_X(0, y, p+1);\r
+ if(p!=pages) putPixel_X(width-1, y, p+1);\r
+ else putPixel_X(width-1, y, p+1);\r
+ }\r
+\r
+ for (x = 0; x < 16; ++x)\r
+ for (y = 0; y < 16; ++y)\r
+ putPixel_X(x+(p+2)*16, y+(p+2)*16, x + y*16);\r
+ //}\r
+\r
+// drawText(0, 0, 15, p);\r
+\r
}\r
\r
- for (y = 0; y <= height; ++y)\r
+ /* Each pages will now contain a different image. Let the user cycle\r
+ through all the pages by pressing a key. */\r
+ for (p = 0; p <= pages; ++p)\r
{\r
- putPixel_X(0, y, p+1);\r
- if(p!=pages) putPixel_X(width-1, y, p+1);
- else putPixel_X(width-1, y, p+1);\r
+ setVisiblePage(p);\r
+ //drawText(0, 240, 15, "bakapi");\r
+ getch();\r
}\r
\r
- for (x = 0; x < 16; ++x)\r
- for (y = 0; y < 16; ++y)\r
- putPixel_X(x+(p+2)*16, y+(p+2)*16, x + y*16);\r
- //}
-
- drawText(0, 0, 15, p);
-\r
}\r
\r
- /* Each pages will now contain a different image. Let the user cycle\r
- through all the pages by pressing a key. */\r
- for (p = 0; p <= pages; ++p)\r
- {\r
- setVisiblePage(p);
- //drawText(0, 240, 15, "bakapi");\r
- getch();\r
- }\r
-\r
- }\r
-\r
/*\r
* Library test (program) entry point.\r
*/\r
\r
int main(void)\r
- {\r
- int key,d;\r
- // main variables\r
- d=1; // switch variable\r
- key=4; // default screensaver number\r
-// puts("First, have a look at the 320x200 mode. I will draw some rubbish");\r
-// puts("on all of the four pages, then let you cycle through them by");\r
-// puts("hitting a key on each page.");\r
-// puts("Press a key when ready...");\r
-// getch();\r
-\r
-// doTest();\r
-\r
-// puts("Then, check out Mode X, 320x240 with 3 (and a half) pages.");\r
-// puts("Press a key when ready...");\r
-// getch();\r
-\r
- setvideo(1);\r
+ {\r
+ int key,d;\r
+ // main variables\r
+ d=1; // switch variable\r
+ key=4; // default screensaver number\r
+// puts("First, have a look at the 320x200 mode. I will draw some rubbish");\r
+// puts("on all of the four pages, then let you cycle through them by");\r
+// puts("hitting a key on each page.");\r
+// puts("Press a key when ready...");\r
+// getch();\r
+\r
+// doTest();\r
+\r
+// puts("Then, check out Mode X, 320x240 with 3 (and a half) pages.");\r
+// puts("Press a key when ready...");\r
+// getch();\r
+\r
+//++++0000\r
+ setvideo(1);\r
+//mxInit();\r
// screen savers\r
\r
/*while(d!=0){ // on!\r
- if(!kbhit()){ // conditions of screen saver\r
- ding(key);\r
- }else{\r
- setvideo(0);\r
- // user imput switch\r
- printf("Enter 1, 2, 3, 4, or 6 to run a screensaver, or enter 5 to quit.\n", getch()); // prompt the user\r
- scanf("%d", &key);\r
- //if(key==3){xx=yy=0;} // crazy screen saver wwww\r
- if(key==5) d=0;\r
- setvideo(1);\r
+ if(!kbhit()){ // conditions of screen saver\r
+ ding(key);\r
+ }else{\r
+ setvideo(0);\r
+ // user imput switch\r
+ printf("Enter 1, 2, 3, 4, or 6 to run a screensaver, or enter 5 to quit.\n", getch()); // prompt the user\r
+ scanf("%d", &key);\r
+ //if(key==3){xx=yy=0;} // crazy screen saver wwww\r
+ if(key==5) d=0;\r
+ setvideo(1);\r
+ }\r
+ }*/ // else off\r
+ while(!kbhit()){ // conditions of screen saver\r
+ ding(4);\r
+ }\r
+ //end of screen savers\r
+// doTest();\r
+ getch();\r
+\r
+ while(!kbhit()){ // conditions of screen saver\r
+// hScroll(1);\r
+// scrolly(1);\r
+// delay(100);
+ Play();\r
+ }\r
+//++++0000\r
+ setvideo(0);\r
+//mxTerm();\r
+//mxGetVersion();\r
+ puts("Where to next? It's your move! wwww");\r
+ 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
+ return 0;\r
}\r
- }*/ // else off\r
- while(!kbhit()){ // conditions of screen saver\r
- ding(4);
- }
- //end of screen savers
- doTest();\r
- setvideo(0);\r
- puts("Where to next? It's your move! wwww");\r
- printf("bakapi ver. 1.04.09a\nis made by sparky4\81i\81\86\83Ö\81\85\81j feel free to use it ^^\nLicence: GPL v2\n");\r
- return 0;\r
- }\r
\r
#endif\r