*\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
/*\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
#define STATUS_ADDR 0x3DA\r
\r
unsigned char *RowsX[600];\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
+ union REGS r;\r
\r
- /* Set VGA BIOS mode 13h: */\r
- r.x.ax = 0x0013;\r
- int86(0x10, &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
+ /* 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
+ /* 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
+ /* 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
+ /* 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
+ /* 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
+ /* 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
+ /* 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
HORIZONTAL SCROLLING\r
--------------------\r
-----------------------------------------------\r
*/\r
\r
- }\r
+//mxSetVirtualScreen(480,360);\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
- }\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
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
-//#pragma aux mxSetVirtualScreen "_"\r
-//void mxSetVirtualScreen(unsigned short int width, unsigned short int height);\r
-mxSetVirtualScreen(480,360);\r
- }\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
/////////////////////////////////////////////////////////////////////////////\r
-// //\r
-// WaitRetrace() - This waits until you are in a Verticle Retrace. //\r
-// //\r
+// //\r
+// WaitRetrace() - This waits until you are in a Verticle Retrace. //\r
+// //\r
/////////////////////////////////////////////////////////////////////////////\r
void wait_for_retrace(void)\r
{\r
while (!(inp(STATUS_ADDR) & 0x08));\r
}\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;\r
- 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
-}\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 }\r
- xpos=0;\r
- 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
-*/\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
+ 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
+ // 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
+ 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
- wait_for_retrace();\r
- outp(0x3C0, 0x13);\r
- outp(0x3C0, Cols & 3);\r
- outp(0x3D4, 0x13);\r
- outp(0x3D5, Cols >> 2);\r
- outp(0x3D4, Cols);\r
- //setVisibleStart(visStart + (Cols * height));\r
- setVisibleStart(visStart + (Cols * width));\r
+ wait_for_retrace();\r
+ outp(0x3C0, 0x13);\r
+ outp(0x3C0, Cols & 3);\r
+ outp(0x3D4, 0x13);\r
+ outp(0x3D5, Cols >> 2);\r
+ outp(0x3D4, Cols);\r
+ //setVisibleStart(visStart + (Cols * height));\r
+ setVisibleStart(visStart + (Cols * width));\r
}\r
\r
/*To implement smooth horizontal scrolling, you would do the following:\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
+ 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
+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
int loadfontX(char *fname)\r
{\r
- FILE *fp;\r
+ FILE *fp;\r
\r
- fp = fopen(fname, "rb");\r
+ fp = fopen(fname, "rb");\r
\r
- if (fp == NULL) {\r
- return 0;\r
- } else {\r
- fread(Xfont, 8, 256, fp);\r
- fclose(fp);\r
- return 1;\r
- }\r
+ if (fp == NULL) {\r
+ return 0;\r
+ } else {\r
+ fread(Xfont, 8, 256, fp);\r
+ fclose(fp);\r
+ return 1;\r
+ }\r
}\r
\r
void putchX(cord x, cord y, char c, byte color)\r
{\r
- int i;\r
- byte *vga_ptr;\r
- byte *font_ptr;\r
- byte temp;\r
-\r
- // 8x8 font\r
- vga_ptr = RowsX[y << 3] + (x << 1) + actStart;\r
- write_plane = -1;\r
-\r
- font_ptr = Xfont + (c << 3);\r
-\r
- i=8;\r
- while (i--) {\r
- temp = *font_ptr++;\r
- outpw(SEQU_ADDR, text_mask[temp & 0x0F]);\r
- *vga_ptr++ = color;\r
-\r
- outpw(SEQU_ADDR, text_mask[temp >> 4]);\r
- *vga_ptr-- = color;\r
- vga_ptr += widthBytes;\r
- }\r
+ int i;\r
+ byte *vga_ptr;\r
+ byte *font_ptr;\r
+ byte temp;\r
+\r
+ // 8x8 font\r
+ vga_ptr = RowsX[y << 3] + (x << 1) + actStart;\r
+ write_plane = -1;\r
+\r
+ font_ptr = Xfont + (c << 3);\r
+\r
+ i=8;\r
+ while (i--) {\r
+ temp = *font_ptr++;\r
+ outpw(SEQU_ADDR, text_mask[temp & 0x0F]);\r
+ *vga_ptr++ = color;\r
+\r
+ outpw(SEQU_ADDR, text_mask[temp >> 4]);\r
+ *vga_ptr-- = color;\r
+ vga_ptr += widthBytes;\r
+ }\r
}\r
\r
void putstringX(cord x, cord y, char *str, byte color)\r
{\r
- int i, skip;\r
- byte *vga_ptr;\r
- byte *font_ptr;\r
- byte c, temp;\r
+ int i, skip;\r
+ byte *vga_ptr;\r
+ byte *font_ptr;\r
+ byte c, temp;\r
\r
- // 8x8 font\r
- vga_ptr = RowsX[y << 3] + (x << 1) + actStart;\r
- write_plane = -1;\r
+ // 8x8 font\r
+ vga_ptr = RowsX[y << 3] + (x << 1) + actStart;\r
+ write_plane = -1;\r
\r
- skip = 2 - (widthBytes << 3);\r
+ skip = 2 - (widthBytes << 3);\r
\r
- while (c = *str++) {\r
- font_ptr = Xfont + (c << 3);\r
+ while (c = *str++) {\r
+ font_ptr = Xfont + (c << 3);\r
\r
- i=8;\r
- while (i--) {\r
- temp = *font_ptr++;\r
- outpw(SEQU_ADDR, text_mask[temp & 0x0F]);\r
- *vga_ptr++ = color;\r
+ i=8;\r
+ while (i--) {\r
+ temp = *font_ptr++;\r
+ outpw(SEQU_ADDR, text_mask[temp & 0x0F]);\r
+ *vga_ptr++ = color;\r
\r
- outpw(SEQU_ADDR, text_mask[temp >> 4]);\r
- *vga_ptr-- = color;\r
- vga_ptr += widthBytes;\r
- }\r
+ outpw(SEQU_ADDR, text_mask[temp >> 4]);\r
+ *vga_ptr-- = color;\r
+ vga_ptr += widthBytes;\r
+ }\r
\r
- vga_ptr += skip;\r
- }\r
+ vga_ptr += skip;\r
+ }\r
}\r
\r
/////////////////////////////////////////////////////////////////////////////\r
-// //\r
-// setvideo() - This function Manages the video modes //\r
-// //\r
+// //\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
+ //mxSetMode( MX_TEXT );\r
+ //mxTerm();\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
+ //mxInit();\r
+ //mxSetMode( MX_320x200 );\r
+ //mxSetVirtualScreen( 640, 400 );\r
+ set320x240x256_X();\r
+ //mxSetMode(MX_320x240);\r
+ //mxSetVirtualScreen(560,420);\r
+ //mxSetVirtualScreen((640-TILEWH),(480-TILEWH));\r
+ //mxSetClip( TRUE );\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*17));\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
\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
+// 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){\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==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
-\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) || (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 == 2\r
+ ||q==4\r
+ ||q==16\r
+ ) && gq == BONK){\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==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
+\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) || (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--;\r
+ }else if(bakax>0){\r
+ xx++;\r
+ }\r
+ if(!bakay){\r
+ yy--;\r
+ }else if(bakay>0){\r
+ yy++;\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/2)*/)) xx=(width/*+(TILEWH)*/);\r
- if(yy<0) yy=(height*3);\r
-// if(xx>(width/*+(TILEWH)*/)) xx=(0/*-(TILEWH/2)*/);\r
- if(yy>(height*3)) yy=0;\r
-// }\r
+// if(xx<0) xx=(width-TILEWH);\r
+// if(yy<0) yy=(height-TILEWH);\r
+// if(xx>(width-TILEWH)) xx=0;\r
+// if(yy>(height-TILEWH)) 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
+ 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
+// 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
+//---- 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(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
+// 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
- /* This is the way to calculate the number of pages available. */\r
- pages = 65536L/(widthBytes*height); // apparently this takes the A000 address\r
-// if(height==240) pages++;\r
-\r
-// printf("%d\n", pages);\r
-\r
- for (p = 0; p <= pages; ++p)\r
- {\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 if(height==240) 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 if(height==240) putPixel_X(width-1, y, p+1);\r
- }\r
-\r
- for (x = 0; x < TILEWH; ++x)\r
- for (y = 0; y < TILEWH; ++y)\r
- putPixel_X(x+(p+2)*16, y+(p+2)*TILEWH, x + y*TILEWH);\r
- //}\r
-\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);\r
- getch();\r
- }\r
-\r
- }\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\r
+// if(height==240) pages++;\r
+\r
+// printf("%d\n", pages);\r
+\r
+ for (p = 0; p <= pages; ++p)\r
+ {\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 if(height==240) 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 if(height==240) putPixel_X(width-1, y, p+1);\r
+ }\r
+\r
+ for (x = 0; x < TILEWH; ++x)\r
+ for (y = 0; y < TILEWH; ++y)\r
+ putPixel_X(x+(p+2)*16, y+(p+2)*TILEWH, x + y*TILEWH);\r
+ //}\r
+\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);\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
- //short int temp;\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
+ int key,d,x,y;\r
+ //short int temp;\r
+ // main variables\r
+ d=1; // switch variable\r
+ key=4; // default screensaver number\r
+ x=0;\r
+ y=0;\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
- /*temp = loadfontX("vga8x8.fnt");\r
+ setvideo(1);\r
+ /*temp = loadfontX("vga8x8.fnt");\r
\r
- if (temp) {\r
- putstringX(0, 0, "bakapi!", 2);\r
- }\r
- getch();*/\r
+ if (temp) {\r
+ putstringX(0, 0, "bakapi!", 2);\r
+ }\r
+ getch();*/\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
- }\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
-// vScroll(1);\r
-// delay(100);\r
-// Play();\r
- }\r
-//++++0000\r
- setvideo(0);\r
- printf("Resolution:\n[%d][%d]\n", width,height);\r
-// setvideo(0);\r
-//mxTerm();\r
-\r
-// printf("[%d]\n", 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
+ 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
+// vScroll(1);\r
+// delay(100);
+ /*mxSetVirtualScreen(320,240*2);\r
+ for(int i=0;i<TILEWH;i++){\r
+ mxPan(x,y);\r
+ //mxWaitRetrace();\r
+ y++;\r
+ }*/
+ mxSetVirtualScreen(320*2,240);\r
+ for(int i=0;i<TILEWH;i++){\r
+ mxPan(x,y);\r
+ mxWaitRetrace();\r
+ x++;\r
+ }
+ //delay(100);\r
+ }\r
+ setvideo(0);\r
+ printf("wwww\n%dx%d\n", width,height);\r
+ printf("[%d]\n", mxGetVersion());\r
+ puts("where to next? It's your move! wwww");\r
+ printf("bakapi ver. 1.04.09.04\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
+++ /dev/null
-;-----------------------------------------------------------\r
-;\r
-; MXPT.ASM - Convex polygon fill with texture mapping\r
-; Copyright (c) 1994 by Alessandro Scotti\r
-;\r
-;-----------------------------------------------------------\r
-;WARN PRO\r
-;NOWARN RES\r
-INCLUDE MODEX.DEF\r
-\r
-PUBLIC mxTexturePoly\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; "Local" definitions\r
-;\r
-TPOINT STRUC\r
- X DW ?\r
- Y DW ?\r
-TPOINT ENDS\r
-\r
-; Do NOT change order!\r
-TSCAN STRUC\r
- Y1 DW ?\r
- IX1 DW ?\r
- IY1 DW ?\r
- Y2 DW ?\r
- IX2 DW ?\r
- IY2 DW ?\r
-TSCAN ENDS\r
-\r
-MAXSCANCOLUMNS EQU POLYSCANBUFSIZE / SIZE TSCAN\r
-\r
-MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
- ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
-\r
-EXTRN mx_VideoSegment : WORD\r
-EXTRN mx_CodeSegment : WORD\r
-EXTRN mx_BytesPerLine : WORD\r
-EXTRN mx_ClipX1 : WORD\r
-EXTRN mx_ClipY1 : WORD\r
-EXTRN mx_ClipX2 : WORD\r
-EXTRN mx_ClipY2 : WORD\r
-EXTRN mx_ScanBuffer : NEAR\r
-\r
-; Global variables, to optimize allocation of local space\r
-mx_Texture DD ?\r
-mx_TextureWidth DW ?\r
-mx_XStepLo DW ?\r
-mx_XStepHi DW ?\r
-mx_XBump DW ?\r
-mx_YStepLo DW ?\r
-mx_YStepHi DW ?\r
-mx_YBump DW ?\r
-mx_TempX DW 512 DUP(?)\r
-mx_TempY DW 512 DUP(?)\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Scans an edge using the DDA (digital differential analyzer) algorithm.\r
-; Also saves information for the texture scanner.\r
-;\r
-; Input:\r
-; DS:BX = pointer to start point (X1, Y1)\r
-; DS:SI = pointer to end point (X2, Y2)\r
-; ES:DI = pointer to edge buffer\r
-; Output:\r
-; ES:DI = updated pointer to edge buffer\r
-;\r
-subScan PROC NEAR\r
- mov cx, ds:[si].X\r
- sub cx, ds:[bx].X ; Get width\r
- mov es:[di].IX1, cx ; Save width\r
- jg @@1\r
- ret\r
-@@1:\r
- push bp ; Save BP\r
-\r
- mov ax, ds:[si].Y\r
- mov bx, ds:[bx].Y\r
- sub ax, bx ; Get height\r
- jg @@T2B ; Scan top to bottom\r
- jl @@B2T ; Scan bottom to top\r
-\r
-; Special case: vertical line\r
- mov ax, bx\r
-@@V:\r
- mov es:[di].Y1, ax\r
- add di, SIZE TSCAN\r
- dec cx\r
- jnz @@V\r
- jmp @@Exit\r
-\r
-; Scan top to bottom\r
-@@T2B:\r
- cwd\r
- div cx\r
- mov bp, ax\r
- xor ax, ax\r
- div cx\r
- xchg ax, bx ; BP:BX = fixed 16:16 step\r
- mov dx, 8000h\r
-@@T2BLoop:\r
- mov es:[di].Y1, ax\r
- add di, SIZE TSCAN\r
- add dx, bx\r
- adc ax, bp\r
- dec cx\r
- jnz @@T2BLoop\r
- jmp @@Exit\r
-\r
-; Scan bottom to top\r
-@@B2T:\r
- neg ax\r
- cwd\r
- div cx\r
- mov bp, ax\r
- xor ax, ax\r
- div cx\r
- xchg ax, bx\r
- mov dx, 8000h\r
-@@B2TLoop:\r
- mov es:[di].Y1, ax\r
- add di, SIZE TSCAN\r
- sub dx, bx\r
- sbb ax, bp\r
- dec cx\r
- jnz @@B2TLoop\r
-\r
-@@Exit:\r
- pop bp\r
- ret\r
-subScan ENDP\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Scans a texture edge.\r
-;\r
-; Input:\r
-; DS:BX = pointer to start point (X1, Y1)\r
-; DS:SI = pointer to end point (X2, Y2)\r
-; ES:DI = pointer to edge buffer\r
-; CX = number of steps\r
-; Output:\r
-; ES:DI = updated pointer to edge buffer\r
-;\r
-subScanTexture PROC NEAR\r
- .push bp\r
- .push di, bx, cx ; Save registers\r
- mov ax, ds:[si].X ; Scan X coordinate first\r
- mov bx, ds:[bx].X\r
- sub ax, bx\r
- jg @@XP ; Positive\r
- jl @@XN ; Negative\r
-\r
-; Special case: constant\r
-@@XCLoop:\r
- mov es:[di].IX1, bx\r
- add di, SIZE TSCAN\r
- dec cx\r
- jnz @@XCLoop\r
- jmp @@ScanY\r
-\r
-; Increasing step\r
-@@XP:\r
- cwd\r
- div cx\r
- mov bp, ax\r
- xor ax, ax\r
- div cx\r
- xchg ax, bx\r
- mov dx, 8000h\r
-@@XPLoop:\r
- mov es:[di].IX1, ax\r
- add di, SIZE TSCAN\r
- add dx, bx\r
- adc ax, bp\r
- dec cx\r
- jnz @@XPLoop\r
- jmp @@ScanY\r
-\r
-; Decreasing step\r
-@@XN:\r
- neg ax\r
- cwd\r
- div cx\r
- mov bp, ax\r
- xor ax, ax\r
- div cx\r
- xchg ax, bx\r
- mov dx, 8000h\r
-@@XNLoop:\r
- mov es:[di].IX1, ax\r
- add di, SIZE TSCAN\r
- sub dx, bx\r
- sbb ax, bp\r
- dec cx\r
- jnz @@XNLoop\r
-\r
-; Now scan the Y coordinate\r
-@@ScanY:\r
- .pop di, bx, cx ; Restore registers\r
- mov ax, ds:[si].Y\r
- mov bx, ds:[bx].Y\r
- sub ax, bx\r
- jg @@YP ; Positive\r
- jl @@YN ; Negative\r
-\r
-; Special case: constant\r
- mov ax, cx\r
-@@YCLoop:\r
- mov es:[di].IY1, bx\r
- add di, SIZE TSCAN\r
- dec ax\r
- jnz @@YCLoop\r
- jmp @@Exit\r
-\r
-; Increasing step\r
-@@YP:\r
- cwd\r
- div cx\r
- mov bp, ax\r
- xor ax, ax\r
- div cx\r
- xchg ax, bx\r
- mov dx, 8000h\r
-@@YPLoop:\r
- mov es:[di].IY1, ax\r
- add di, SIZE TSCAN\r
- add dx, bx\r
- adc ax, bp\r
- dec cx\r
- jnz @@YPLoop\r
- jmp @@Exit\r
-\r
-; Decreasing step\r
-@@YN:\r
- neg ax\r
- cwd\r
- div cx\r
- mov bp, ax\r
- xor ax, ax\r
- div cx\r
- xchg ax, bx\r
- mov dx, 8000h\r
-@@YNLoop:\r
- mov es:[di].IY1, ax\r
- add di, SIZE TSCAN\r
- sub dx, bx\r
- sbb ax, bp\r
- dec cx\r
- jnz @@YNLoop\r
-\r
-@@Exit:\r
- .pop bp\r
- ret\r
-subScanTexture ENDP\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Fills a scan column with texture.\r
-;\r
-; Input:\r
-; DS:SI = current TSCAN\r
-; ES:DI = address of top pixel\r
-; CX = number of pixels to write\r
-; Output:\r
-; none\r
-; Notes:\r
-; must preserve DS:SI, texture info in global variables.\r
-;\r
-subFillScan PROC NEAR\r
- ASSUME ds:NOTHING\r
- .push ds, si, bp, cx\r
-\r
- movzx ecx, cx ; Clear high word of ECX\r
-\r
- movzx eax, ds:[si].IX2\r
- movzx ebx, ds:[si].IX1\r
- sub ax, bx\r
- jge @@XP\r
-\r
-;---------------------------------------\r
-; Delta X is negative\r
-@@XN:\r
- neg ax ; Make AX positive\r
- shl eax, 8 ; Convert 8:8 fixed to 16:16\r
- cdq\r
- idiv ecx\r
- ror eax, 16\r
- mov ebp, eax ; Save X step into EBP\r
-\r
- movzx eax, ds:[si].IY2\r
- movzx esi, ds:[si].IY1\r
- sub ax, si\r
- jge @@XNYP\r
-\r
-;-----------------------\r
-; DeltaX < 0, DeltaY < 0\r
-@@XNYN:\r
- neg ax\r
- shl eax, 8\r
- cdq\r
- idiv ecx\r
- ror eax, 16\r
- mov dx, [mx_TextureWidth]\r
- mul dl\r
- xchg eax, esi ; ESI = Y step\r
- ror eax, 8\r
- mul dl\r
- ror ebx, 8\r
- add bx, ax ; BX = start offset in texture\r
- lds dx, [mx_Texture]\r
- movzx edx, dx\r
- add edx, ebx ; EDX = X step lo:texture offset\r
- xchg edx, esi ; EDX = Y step\r
-@@XNYNLoop:\r
- dec cx\r
- jl @@XNYNDone\r
- movzx ax, ds:[si]\r
- mov es:[di], al\r
- add di, [mx_BytesPerLine]\r
- sub esi, ebp\r
- sbb si, 0\r
- sub si, dx\r
- sub eax, edx\r
- jnc @@XNYNLoop\r
- sub si, [mx_TextureWidth]\r
- jmp @@XNYNLoop\r
-@@XNYNDone:\r
- jmp @@Exit\r
-\r
-;-----------------------\r
-; DeltaX < 0, DeltaY > 0\r
-@@XNYP:\r
- shl eax, 8\r
- cdq\r
- idiv ecx\r
- ror eax, 16\r
- mov dx, [mx_TextureWidth]\r
- mul dl\r
- xchg eax, esi ; ESI = Y step\r
- ror eax, 8\r
- mul dl\r
- ror ebx, 8\r
- add bx, ax ; BX = start offset in texture\r
- lds dx, [mx_Texture]\r
- movzx edx, dx\r
- add edx, ebx ; EDX = X step lo:texture offset\r
- xchg edx, esi ; EDX = Y step\r
-@@XNYPLoop:\r
- dec cx\r
- jl @@XNYPDone\r
- movzx ax, ds:[si]\r
- mov es:[di], al\r
- add di, [mx_BytesPerLine]\r
- sub esi, ebp\r
- sbb si, 0\r
- add si, dx\r
- add eax, edx\r
- jnc @@XNYPLoop\r
- add si, [mx_TextureWidth]\r
- jmp @@XNYPLoop\r
-@@XNYPDone:\r
- jmp @@Exit\r
-\r
-;---------------------------------------\r
-; Delta X is positive\r
-@@XP:\r
- shl eax, 8 ; Convert 8:8 fixed to 16:16\r
- cdq\r
- idiv ecx\r
- ror eax, 16\r
- mov ebp, eax ; Save X step into EBP\r
-\r
- movzx eax, ds:[si].IY2\r
- movzx esi, ds:[si].IY1\r
- sub ax, si\r
- jge @@XPYP\r
-\r
-;-----------------------\r
-; DeltaX > 0, DeltaY < 0\r
-@@XPYN:\r
- neg ax\r
- shl eax, 8\r
- cdq\r
- idiv ecx\r
- ror eax, 16\r
- mov dx, [mx_TextureWidth]\r
- mul dl\r
- xchg eax, esi ; ESI = Y step\r
- ror eax, 8\r
- mul dl\r
- ror ebx, 8\r
- add bx, ax ; BX = start offset in texture\r
- lds dx, [mx_Texture]\r
- movzx edx, dx\r
- add edx, ebx ; EDX = X step lo:texture offset\r
- xchg edx, esi ; EDX = Y step\r
-@@XPYNLoop:\r
- dec cx\r
- jl @@XPYNDone\r
- movzx ax, ds:[si]\r
- mov es:[di], al\r
- add di, [mx_BytesPerLine]\r
- add esi, ebp\r
- adc si, 0\r
- sub si, dx\r
- sub eax, edx\r
- jnc @@XPYNLoop\r
- sub si, [mx_TextureWidth]\r
- jmp @@XPYNLoop\r
-@@XPYNDone:\r
- jmp @@Exit\r
-\r
-;-----------------------\r
-; DeltaX > 0, DeltaY > 0\r
-@@XPYP:\r
- shl eax, 8\r
- cdq\r
- idiv ecx\r
- ror eax, 16\r
- mov dx, [mx_TextureWidth]\r
- mul dl\r
- xchg eax, esi ; ESI = Y step\r
- ror eax, 8\r
- mul dl\r
- ror ebx, 8\r
- add bx, ax ; BX = start offset in texture\r
- lds dx, [mx_Texture]\r
- movzx edx, dx\r
- add edx, ebx ; EDX = X step lo:texture offset\r
- xchg edx, esi ; EDX = Y step\r
-@@XPYPLoop:\r
- dec cx\r
- jl @@XPYPDone\r
- movzx ax, ds:[si]\r
- mov es:[di], al\r
- add di, [mx_BytesPerLine]\r
- add esi, ebp\r
- adc si, 0\r
- add si, dx\r
- add eax, edx\r
- jnc @@XPYPLoop\r
- add si, [mx_TextureWidth]\r
- jmp @@XPYPLoop\r
-@@XPYPDone:\r
- jmp @@Exit\r
-\r
-@@Exit:\r
- .pop ds, si, bp, cx\r
- ASSUME ds:NOTHING\r
- ret\r
-subFillScan ENDP\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Fills a convex polygon with the specified color.\r
-; Interpolates pixel colors using the Gouraud algorithm.\r
-;\r
-; Input:\r
-; Count = number of vertexes\r
-; Map = indexes of points and colors (integer)\r
-; Points = array of points (integer X, Y coordinates)\r
-; TPoints = array of points inside texture (fixed 8:8 coordinates)\r
-; Texture = pointer to texture image\r
-; TWidth = texture width in pixels\r
-; Output:\r
-; none\r
-; Notes:\r
-; vertexes must be in counterclockwise order, arrays are 0-based.\r
-;\r
-mxTexturePoly PROC FAR\r
- ARG TWidth:WORD, \\r
- Texture:DWORD, \\r
- TPoints:DWORD, \\r
- Points:DWORD, \\r
- Map:DWORD, \\r
- Count:WORD = ARG_SIZE\r
- LOCAL WritePlane:BYTE:2, \\r
- ScanOffsetT:WORD, \\r
- ScanOffsetB:WORD, \\r
- ScanCount:WORD, \\r
- Holder:WORD, \\r
- Height:WORD, \\r
- MinIdxT:WORD, \\r
- MinIdxB:WORD, \\r
- MaxIdx:WORD, \\r
- Width:WORD, \\r
- BoxX1:WORD, \\r
- BoxY1:WORD, \\r
- BoxX2:WORD, \\r
- BoxY2::WORD = AUTO_SIZE\r
- .enter AUTO_SIZE\r
- .push ds, si, es, di\r
- ASSUME ds:NOTHING\r
-\r
-IF USE386 EQ FALSE\r
- jmp @@Exit\r
-ENDIF\r
-\r
-; Check that at least three vertexes are specified\r
- mov cx, [Count]\r
- cmp cx, 3\r
- jb @@Exit\r
-\r
-;------------------------------\r
-; Find bounding box for polygon\r
- les di, [Map] ; Point to map table\r
- lds si, [Points] ; Point to vertex array\r
- mov [BoxX1], 32767\r
- mov [BoxX2], -32768\r
- mov [BoxY1], 32767\r
- mov [BoxY2], -32768\r
-\r
- xor dx, dx\r
-@@MinMaxLoop:\r
- mov bx, es:[di] ; Get index of vertex\r
- .shl bx, 2 ; Get offset in point array\r
- add bx, si\r
-\r
-; Check X range\r
-@@CheckMinX:\r
- mov ax, ds:[bx].X ; Get X coordinate\r
- cmp ax, [BoxX1]\r
- jge @@CheckMaxX\r
- mov [BoxX1], ax\r
- mov [MinIdxT], dx\r
- mov [MinIdxB], dx\r
-@@CheckMaxX:\r
- cmp ax, [BoxX2]\r
- jle @@CheckMinY\r
- mov [BoxX2], ax\r
- mov [MaxIdx], dx\r
-\r
-; Check Y range\r
-@@CheckMinY:\r
- mov ax, ds:[bx].Y\r
- cmp ax, [BoxY1]\r
- jge @@CheckMaxY\r
- mov [BoxY1], ax\r
-@@CheckMaxY:\r
- cmp ax, [BoxY2]\r
- jle @@CheckDone\r
- mov [BoxY2], ax\r
-\r
-; Repeat thru all points\r
-@@CheckDone:\r
- add di, 2 ; Next map entry\r
- add dx, 2\r
- dec cx\r
- jnz @@MinMaxLoop\r
-\r
-;---------------------------------\r
-; Check if polygon is full clipped\r
- mov ax, [BoxX2]\r
- cmp ax, [mx_ClipX1] ; Is poly full clipped?\r
- jl @@Exit\r
- mov bx, [BoxX1]\r
- cmp bx, [mx_ClipX2] ; Is poly full clipped?\r
- jg @@Exit\r
- sub ax, bx ; Get width\r
- jle @@Exit ; Exit if not positive\r
- mov ax, [BoxY2]\r
- cmp ax, [mx_ClipY1] ; Is poly full clipped?\r
- jl @@Exit\r
- mov bx, [BoxY1]\r
- cmp bx, [mx_ClipY2] ; Is poly full clipped?\r
- jg @@Exit\r
- sub ax, bx ; Get height\r
- jle @@Exit ; Exit if not positive\r
-\r
- dec [Count]\r
- shl [Count], 1 ; We'll work with word offsets\r
-\r
-;----------------------\r
-; Scan top polygon edge\r
- mov es, [mx_CodeSegment]\r
- mov di, OFFSET mx_ScanBuffer\r
- mov si, [MinIdxT] ; Offset of top point index\r
-@@STLoop:\r
- mov dx, si\r
- lds bx, [Map] ; DS:BX -> map table\r
- mov ax, ds:[bx+si] ; Index of top point #1\r
- dec si ; Next top point\r
- dec si\r
- test si, si\r
- jns @@ST1\r
- mov si, [Count]\r
-@@ST1:\r
- mov [MinIdxT], si ; Save new index of bottom point\r
- mov cx, si\r
- mov si, ds:[bx+si] ; Get index of top point #2\r
- .shl ax, 2 ; Convert indexes to offsets\r
- .shl si, 2\r
- shl cx, 1 ; Save map points\r
- shl dx, 1\r
- mov dh, cl\r
- mov es:[di].IY1, dx\r
- lds bx, [Points] ; Get pointer to vertexes\r
- add si, bx\r
- add bx, ax\r
- call subScan ; Scan poly top edge\r
- mov si, [MinIdxT]\r
- cmp si, [MaxIdx] ; Reached last vertex?\r
- jne @@STLoop ; No, continue\r
- mov es:[di].IX1, -1 ; Mark end of scan\r
-\r
-;-------------------------\r
-; Scan bottom polygon edge\r
- mov di, OFFSET mx_ScanBuffer + OFFSET Y2\r
- mov si, [MinIdxB]\r
-@@SBLoop:\r
- mov dx, si\r
- lds bx, [Map] ; DS:BX -> map table\r
- mov ax, ds:[bx+si] ; Index of bottom point #1\r
- inc si ; Next bottom point\r
- inc si\r
- cmp si, [Count]\r
- jbe @@SB1\r
- xor si, si\r
-@@SB1:\r
- mov [MinIdxB], si ; Save new index of bottom point\r
- mov cx, si\r
- mov si, ds:[bx+si] ; Get index of bottom point #2\r
- .shl ax, 2 ; Convert indexes to offsets\r
- .shl si, 2\r
- shl cx, 1 ; Save map points\r
- shl dx, 1\r
- mov dh, cl\r
- mov es:[di].IY1, dx\r
- lds bx, [Points] ; Get pointer to vertexes\r
- add si, bx\r
- add bx, ax\r
- call subScan ; Scan poly bottom edge\r
- mov si, [MinIdxB]\r
- cmp si, [MaxIdx] ; Reached last vertex?\r
- jne @@SBLoop ; No, continue\r
- mov es:[di].IX1, -1 ; Mark end of scan\r
-\r
-;----------------------\r
-; Scan top texture edge\r
- mov di, OFFSET mx_ScanBuffer\r
- mov ds, WORD PTR [TPoints][2]\r
-@@TTLoop:\r
- mov cx, es:[di].IX1\r
- test cx, cx\r
- jle @@TTDone\r
- mov ax, es:[di].IY1\r
- mov dl, ah\r
- xor ah, ah\r
- xor dh, dh\r
- mov si, dx\r
- mov bx, WORD PTR [TPoints][0]\r
- add si, bx\r
- add bx, ax\r
- call subScanTexture ; Scan texture top edge\r
- jmp @@TTLoop\r
-@@TTDone:\r
-\r
-;-------------------------\r
-; Scan bottom texture edge\r
- mov di, OFFSET mx_ScanBuffer + OFFSET Y2\r
-@@TBLoop:\r
- mov cx, es:[di].IX1\r
- test cx, cx\r
- jle @@TBDone\r
- mov ax, es:[di].IY1\r
- mov dl, ah\r
- xor ah, ah\r
- xor dh, dh\r
- mov si, dx\r
- mov bx, WORD PTR [TPoints][0]\r
- add si, bx\r
- add bx, ax\r
- call subScanTexture ; Scan texture top edge\r
- jmp @@TBLoop\r
-@@TBDone:\r
-\r
-;--------------------\r
-; Clip left and right\r
- mov si, OFFSET mx_ScanBuffer\r
- mov ax, [BoxX1]\r
- mov cx, [BoxX2]\r
- sub cx, ax\r
- mov bx, [mx_ClipX1] ; CX = bounding box width\r
- sub bx, ax\r
- jle @@ClipL1 ; No need to clip left\r
- sub cx, bx\r
- add ax, bx ; BoxX1 = mx_ClipX1\r
- mov [BoxX1], ax\r
- .shl bx, 2 ; Warning!!! This is an hand-coded\r
- add si, bx ; multiply by the size of TSCAN\r
- shl bx, 1\r
- add si, bx\r
-@@ClipL1:\r
- mov bx, ax\r
- add bx, cx ; Last scan column\r
- sub bx, [mx_ClipX2]\r
- jle @@ClipL2 ; No need to clip right\r
- sub cx, bx ; Clip right\r
-@@ClipL2:\r
- test cx, cx ; Is clipped width positive?\r
- jle @@Exit ; No, exit\r
- mov [ScanCount], cx ; Save number of columns to draw\r
- mov [ScanOffsetT], si ; Remember offset of (clipped) buffer\r
- mov ds, [mx_CodeSegment] ; DS:SI -> scan buffer\r
-\r
-;------------------------------\r
-; Check if Y clipping is needed\r
- mov ax, [BoxY1]\r
- cmp ax, [mx_ClipY1]\r
- jl @@ClipTB ; Need to clip top\r
- mov ax, [BoxY2]\r
- cmp ax, [mx_ClipY2]\r
- jg @@ClipTB ; Need to clip bottom\r
- jmp @@ClipYExit ; Skip Y clipping\r
-\r
-;--------------------\r
-; Clip top and bottom\r
-@@ClipTB:\r
- mov di, cx ; DI = scan count\r
- inc di ; Increment count for pre-loop test\r
- sub si, SIZE TSCAN\r
-@@ClipYLoop:\r
- dec di ; Any column left?\r
- jz @@ClipYExit ; No, exit\r
- add si, SIZE TSCAN\r
- mov ax, ds:[si].Y1 ; Y1\r
- mov cx, ds:[si].Y2 ; Y2\r
- mov dx, [mx_ClipY2]\r
- cmp ax, dx ; Full clipped?\r
- jg @@ClipYClip ; Yes, skip this column\r
- cmp cx, dx ; Need to clip bottom?\r
- jle @@ClipY1 ; No, continue\r
-; Clip bottom, update texture too\r
- mov ds:[si].Y2, dx\r
- mov bx, cx\r
- sub bx, dx ; Number of pixels to clip\r
- sub cx, ax ; Height\r
- jle @@ClipYClip\r
- mov ax, ds:[si].IX1 ; Update texture\r
- sub ax, ds:[si].IX2\r
- imul bx\r
- idiv cx\r
- add ds:[si].IX2, ax\r
- mov ax, ds:[si].IY1\r
- sub ax, ds:[si].IY2\r
- imul bx\r
- idiv cx\r
- add ds:[si].IY2, ax\r
- mov ax, ds:[si].Y1 ; Reload coordinates\r
- mov cx, ds:[si].Y2 ;\r
-@@ClipY1:\r
- mov dx, [mx_ClipY1]\r
- cmp cx, dx ; Full top clipped?\r
- jl @@ClipYClip ; Yes, skip\r
- sub cx, ax ; Get height\r
- jle @@ClipYClip ; Skip if not positive\r
- cmp ax, dx ; Need to clip top?\r
- jge @@ClipYLoop ; No, continue\r
-; Clip top, update texture too\r
- mov ds:[si].Y1, dx ; Y1 = mx_ClipY1\r
- sub dx, ax ; DX = number of pixels clipped\r
- cmp cx, dx\r
- jbe @@ClipYClip ; Full clipped, skip\r
- mov bx, dx ; Save pixel count\r
- mov ax, ds:[si].IX2\r
- sub ax, ds:[si].IX1\r
- imul bx\r
- idiv cx\r
- add ds:[si].IX1, ax\r
- mov ax, ds:[si].IY2\r
- sub ax, ds:[si].IY1\r
- imul bx\r
- idiv cx\r
- add ds:[si].IY1, ax\r
- jmp @@ClipYLoop\r
-@@ClipYClip:\r
- mov ds:[si].Y1, -1 ; Mark column as clipped\r
- jmp @@ClipYLoop\r
-@@ClipYExit:\r
-\r
-;-------------\r
-; Draw columns\r
- mov es, [mx_VideoSegment]\r
- mov ax, [TWidth]\r
- mov ds:[mx_TextureWidth], ax\r
- mov ax, WORD PTR [Texture][0]\r
- mov dx, WORD PTR [Texture][2]\r
- mov WORD PTR ds:[mx_Texture][0], ax\r
- mov WORD PTR ds:[mx_Texture][2], dx\r
- mov si, [ScanOffsetT]\r
- mov cl, BYTE PTR [BoxX1] ; Init write plane\r
- and cl, 03h\r
- mov al, 11h\r
- shl al, cl\r
- mov [WritePlane], al\r
- .shr [BoxX1], 2\r
-@@DrawLoop:\r
- mov ax, ds:[si].Y1\r
- test ax, ax ; Was column clipped?\r
- js @@DrawNext ; Yes, skip\r
- mov cx, ds:[si].Y2\r
- sub cx, ax ; CX = height\r
- jle @@DrawNext\r
- mul [mx_BytesPerLine] ; Get pixel address\r
- add ax, [BoxX1]\r
- mov di, ax\r
- mov ah, [WritePlane]\r
- mov al, 02h\r
- mov dx, TS\r
- out dx, ax\r
- call subFillScan\r
-@@DrawNext:\r
- rol [WritePlane], 1\r
- adc [BoxX1], 0 ; Bump pointer to video memory if needed\r
- add si, SIZE TSCAN\r
- dec [ScanCount]\r
- jnz @@DrawLoop\r
-\r
-@@Exit:\r
- xor ax, ax\r
- .pop ds, si, es, di\r
- .leave ARG_SIZE\r
-mxTexturePoly ENDP\r
-\r
-MX_TEXT ENDS\r
-END\r