c2e.convert_special: 0
e2c.convert_num: 0
-openfiles: /dos/z/16/16/dos_gfx.cpp:16147:15298:1:
+openfiles: /dos/z/16/16/dos_gfx.cpp:19173:18568:0:
openfiles: /dos/z/16/16/dos_gfx.h:141:0:0:
openfiles: /dos/z/16/16/dos_kb.c:892:395:0:
openfiles: /dos/z/16/16/dos_kb.h:60:0:0:
openfiles: /dos/z/16/16/lib/lib_com.cpp:0:0:0:
-openfiles: /dos/z/16/16/lib/lib_com.h:2553:1575:0:
+openfiles: /dos/z/16/16/lib/lib_com.h:2553:1416:0:
openfiles: /dos/z/16/16/scroll.txt:5307:5080:0:
openfiles: /dos/z/16/16/project16.txt:1675:950:0:
openfiles: /dos/z/16/16/16.txt:0:0:0:
-openfiles: /dos/z/16/16/lib/x/MODEX.H:1569:1079:0:
-openfiles: /dos/z/16/16/lib/x/MXVS.ASM:260:0:0:
-openfiles: /dos/z/16/16/lib/x/MXPN.ASM:241:0:0:
-openfiles: /dos/z/16/16/x.bat:71:0:0:
-openfiles: /dos/z/16/16/xx.bat:16:0:0:
+openfiles: /dos/z/16/16/lib/x/MODEX.H:2945:2439:0:
openfiles: /dos/z/16/16/lib/x/MODEX.DEF:4471:3131:0:
openfiles: /dos/z/16/16/lib/x/MAKEFILE:1186:782:0:
+openfiles: /dos/z/4x4_16/modex/DEMO07.PAS:1095:490:0:
snr_recursion_level: 0
convertcolumn_horizontally: 0
adv_open_matchname: 0
default_mime_type: text/plain
e2c.convert_xml: 1
c2e.convert_iso: 0
-opendir: file:///dos/z/16/16/lib/x
+opendir: file:///dos/z/4x4_16/modex
wrap_text_default: 0
bookmarks_filename_mode: 1
-ssearch_text: virtual
+ssearch_text: mxSetClip(
snr_casesens: 0
view_blocks: 1
name: project 16
recent_files: file:///dos/z/16/16/w_modex/TEST.CPP
recent_files: file:///dos/z/16/16/Project%2016.bfproject
recent_files: file:///dos/z/16/16/lib/x/compile.bat
+recent_files: file:///dos/z/16/16/x.bat
+recent_files: file:///dos/z/16/16/xx.bat
+recent_files: file:///dos/z/16/16/lib/x/MXVS.ASM
+recent_files: file:///dos/z/16/16/lib/x/MXPN.ASM
recent_files: file:///dos/z/16/16/dos_gfx.cpp
+recent_files: file:///dos/z/16/16/lib/lib_com.cpp
recent_files: file:///dos/z/16/16/dos_gfx.h
-recent_files: file:///dos/z/16/16/dos_kb.c
+recent_files: file:///dos/z/16/16/project16.txt
recent_files: file:///dos/z/16/16/dos_kb.h
-recent_files: file:///dos/z/16/16/lib/lib_com.h
-recent_files: file:///dos/z/16/16/lib/lib_com.cpp
+recent_files: file:///dos/z/16/16/dos_kb.c
recent_files: file:///dos/z/16/16/scroll.txt
-recent_files: file:///dos/z/16/16/project16.txt
-recent_files: file:///dos/z/16/16/x.bat
-recent_files: file:///dos/z/16/16/xx.bat
+recent_files: file:///dos/z/16/16/lib/x/MODEX.DEF
recent_files: file:///dos/z/16/16/16.txt
recent_files: file:///dos/z/16/16/lib/x/MODEX.H
-recent_files: file:///dos/z/16/16/lib/x/MXVS.ASM
-recent_files: file:///dos/z/16/16/lib/x/MODEX.DEF
-recent_files: file:///dos/z/16/16/lib/x/MXPN.ASM
+recent_files: file:///dos/z/16/16/lib/lib_com.h
+recent_files: file:///dos/z/4x4_16/modex/DEMO07.PAS
recent_files: file:///dos/z/16/16/lib/x/MAKEFILE
snr_replacetype: 0
savedir: file:///dos/z/16/16
htmlbar_view: 0
spell_lang: en
ssearch_dotmatchall: 0
-searchlist: mss
-searchlist: mxset
searchlist: mspai
searchlist: mspan
searchlist: mspab
searchlist: GetVers
searchlist: setvir
searchlist: virtual
+searchlist: STEPS
+searchlist: mxSetClip( TRUE );
autocomplete: 1
outputb_show_all_output: 0
bookmarks_show_mode: 0
#define GRAC_ADDR 0x3ce /* Base port of the Graphics Controller */\r
#define STATUS_ADDR 0x3DA\r
\r
-unsigned char *RowsX[600];\r
-unsigned char write_plane, read_plane;\r
-unsigned short text_mask[16] = { 0x0002, 0x0102, 0x0202, 0x0302,\r
- 0x0402, 0x0502, 0x0602, 0x0702,\r
- 0x0802, 0x0902, 0x0A02, 0x0B02,\r
- 0x0C02, 0x0D02, 0x0E02, 0x0F02 };\r
-\r
\r
/*\r
* Make a far pointer to the VGA graphics buffer segment. Your compiler\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
-//mxSetVirtualScreen(480,360);\r
}\r
\r
/*\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
- //in.h.ah = 0x00;\r
- //in.h.al = old_mode;\r
- //int86(0x10, &in, &out);
+ //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
+ in.h.ah = 0xf;\r
+ int86(0x10, &in, &out);\r
+ old_mode = out.h.al;\r
\r
// enter mode\r
mxInit();\r
mxSetMode( MX_320x240 );\r
- mxSetVirtualScreen( 480, 360 );\r
+ width=320;\r
+ height=240;\r
+// mxSetVirtualScreen(width+(width/4), height+(height/4));\r
+// mxSetVirtualScreen(width*2, height*2);\r
//set320x240x256_X();\r
- //mxSetMode(MX_320x240);\r
- //mxSetVirtualScreen(560,420);\r
- //mxSetVirtualScreen((640-TILEWH),(480-TILEWH));\r
- //mxSetClip( TRUE );\r
+ mxSetVirtualScreen(560,420);\r
+// mxSetVirtualScreen((640-(TILEWH*2)),(480-(TILEWH*2)));\r
+ mxSetClip(0);\r
+ //mxSetClipRegion(0, 0, width, height);\r
}\r
}\r
\r
}\r
// fixer\r
// if(q!=16){\r
-//if(q!=16)\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
+ if(xx<0) xx=(560/*-TILEWH*/);\r
+ if(yy<0) yy=(420/*-TILEWH*/);\r
+ if(xx>(560/*-TILEWH*/)) xx=0;\r
+ if(yy>(420/*-TILEWH*/)) yy=0;\r
// }\r
\r
//interesting effects\r
int tx=0,ty=0;\r
tx+=xx+16;\r
ty+=yy+16;\r
- putPixel_X(tx, ty, coor);\r
+ mxPutPixel(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
+// mxFillBox(xx, yy, TILEWH, TILEWH, coor, 0);\r
//++++0000\r
-// putPixel_X(xx, yy, coor);
+// putPixel_X(xx, yy, coor);\r
mxPutPixel(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) mxPutPixel(rand()%width, rand()%(height*3), 0);\r
+ if(q==16) mxPutPixel(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
}\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
+// putPixel_X(x, 0, p+1);\r
+ mxPutPixel(x, 0, p+1);\r
+ if(p!=pages) mxPutPixel(x, height-1, p+1);\r
+ else if(height==240) mxPutPixel(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
+ mxPutPixel(0, y, p+1);\r
+ if(p!=pages) mxPutPixel(width-1, y, p+1);\r
+ else if(height==240) mxPutPixel(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
+ mxPutPixel(x+(p+2)*16, y+(p+2)*TILEWH, x + y*TILEWH);\r
//}\r
\r
}\r
\r
int main(void)\r
{\r
- int key,d,x,y;\r
+ int key,d,xpos,ypos,xdir,ydir;\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
+ xpos=0;\r
+ ypos=0;
+ xdir=1;\r
+ ydir=1;\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
\r
//++++0000\r
setvideo(1);\r
- /*temp = loadfontX("vga8x8.fnt");\r
-\r
- if (temp) {\r
- putstringX(0, 0, "bakapi!", 2);\r
- }\r
- getch();*/\r
// screen savers\r
\r
/*while(d!=0){ // on!\r
}\r
}*/ // else off\r
while(!kbhit()){ // conditions of screen saver\r
- ding(4);\r
+ ding(key);\r
}\r
//end of screen savers\r
//doTest();\r
+ for (int x = 0; x < width; ++x)\r
+ {\r
+ mxPutPixel(x, 0, 15);\r
+ mxPutPixel(x, height-1, 15);\r
+ }\r
+ for (int y = 0; y < height; ++y)\r
+ {\r
+ mxPutPixel(0, y, 15);\r
+ mxPutPixel(width-1, y, 15);\r
+ }\r
getch();\r
-\r
- while(!kbhit()){ // conditions of screen saver\r
+ while(!kbhit()){\r
// hScroll(1);\r
// scrolly(1);\r
// vScroll(1);\r
-// delay(100);
- for(int i=0;i<TILEWH;i++){\r
- mxPan(x,y);\r
+// delay(100);\r
+ //for(int i=0;i<TILEWH;i++){\r
+ ding(key);\r
+ mxPan(xpos,ypos);\r
mxWaitRetrace();\r
- x++;
- y++;\r
- }
- //delay(100);\r
+ xpos=xpos+xdir;\r
+ ypos=ypos+ydir;\r
+ if( (xpos>239) || (xpos<1))xdir=-xdir;\r
+ if( (ypos>179) || (ypos<1))ydir=-ydir; // { Hit a boundry, change\r
+ // direction! }\r
+ //}\r
}\r
setvideo(0);\r
printf("wwww\n%dx%d\n", width,height);\r
+++ /dev/null
-Error! E2028: mxGetVersion_ is an undefined reference\r
-creating a DOS executable\r
-file dos_gfx.obj(C:\Z\16\16\dos_gfx.cpp): undefined symbol mxGetVersion_\r
--- /dev/null
+/*\r
+ * The library testing routines follows below.\r
+ */\r
+\r
+\r
+#ifdef TESTING\r
+\r
+#include <stdio.h>\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
+ mxPutPixel(x, 0, p+1);\r
+ if(p!=pages) mxPutPixel(x, height-1, p+1);\r
+ else if(height==240) mxPutPixel(x, 99-1, p+1);\r
+ }\r
+\r
+ for (y = 0; y <= height; ++y)\r
+ {\r
+ mxPutPixel(0, y, p+1);\r
+ if(p!=pages) mxPutPixel(width-1, y, p+1);\r
+ else if(height==240) mxPutPixel(width-1, y, p+1);\r
+ }\r
+\r
+ for (x = 0; x < TILEWH; ++x)\r
+ for (y = 0; y < TILEWH; ++y)\r
+ mxPutPixel(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,xpos,ypos,xdir,ydir;\r
+ //short int temp;\r
+ // main variables\r
+ d=1; // switch variable\r
+ key=4; // default screensaver number\r
+ xpos=0;\r
+ ypos=0;
+ xdir=1;\r
+ ydir=1;\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
+// 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(key);\r
+ }\r
+ //end of screen savers\r
+ //doTest();\r
+ for (int x = 0; x < width; ++x)\r
+ {\r
+ mxPutPixel(x, 0, 15);\r
+ mxPutPixel(x, height-1, 15);\r
+ }\r
+ for (int y = 0; y < height; ++y)\r
+ {\r
+ mxPutPixel(0, y, 15);\r
+ mxPutPixel(width-1, y, 15);\r
+ }\r
+ getch();\r
+ while(!kbhit()){\r
+// hScroll(1);\r
+// scrolly(1);\r
+// vScroll(1);\r
+// delay(100);\r
+ //for(int i=0;i<TILEWH;i++){\r
+ ding(key);\r
+ mxPan(xpos,ypos);\r
+ mxWaitRetrace();\r
+ xpos=xpos+xdir;\r
+ ypos=ypos+ydir;\r
+ if( (xpos>239) || (xpos<1))xdir=-xdir;\r
+ if( (ypos>179) || (ypos<1))ydir=-ydir; // { Hit a boundry, change\r
+ // direction! }\r
+ //}\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(≧ω≦) feel free to use it ^^¥nLicence: GPL v2¥n");\r
+ return 0;\r
+ }\r
+\r
+#endif\r
+#endif
\ No newline at end of file
+++ /dev/null
-MASM modex,modex,modex,nul
\ No newline at end of file
+++ /dev/null
-DEFINT A-Z\r
-DECLARE SUB PRINT.STRING (Text$, Xpos%, Ypos%, Colour%)\r
-DECLARE FUNCTION MakePal$ (Red%, Green%, Blue%)\r
-DECLARE SUB LOAD.FONT (FontFile$, FontNum%)\r
-DECLARE SUB ERROR.OUT (Text$)\r
-\r
- REM $INCLUDE: 'MODEX.BI'\r
-\r
- REM $INCLUDE: 'UTILS.BI'\r
-\r
-TYPE FONT\r
- SetData AS STRING * 1024\r
-END TYPE\r
-\r
-\r
-TYPE VGAPalette\r
- PalData AS STRING * 768\r
-END TYPE\r
-\r
-\r
- ' Alternate form of LOAD_DAC_REGISTERS so we can pass an offset into\r
- ' a String instead of the Address of the String\r
-\r
-DECLARE SUB LOAD.DACS ALIAS "LOAD_DAC_REGISTERS" (BYVAL Addr&, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%)\r
-\r
-\r
- '\r
- 'MODE X DEMO of Multiple Character Sets and Block Color Cycling\r
- '\r
- 'By Matt Pritchard\r
- '\r
-\r
-COMMON SHARED CharSet() AS FONT\r
-\r
-DIM Pal AS VGAPalette\r
-\r
- REM $DYNAMIC\r
-\r
-DIM SHARED CharSet(0 TO 3) AS FONT\r
-\r
-\r
- LOAD.FONT "SYSTEM.FNT", 0\r
- LOAD.FONT "ROM_8x8.FNT", 1\r
- LOAD.FONT "SPACEAGE.FNT", 2\r
-\r
-\r
- IF SET.MODEX(Mode320x240) = False THEN\r
- ERROR.OUT "ERROR SETTING MODE X"\r
- END IF\r
-\r
-\r
- A$ = "": B$ = ""\r
- FOR X = 0 TO 31: A$ = A$ + MakePal$(31 - X, X, 0): NEXT X\r
- FOR X = 0 TO 31: A$ = A$ + MakePal$(0, 31 - X, X): NEXT X\r
- FOR X = 0 TO 31: A$ = A$ + MakePal$(X, 0, 31 - X): NEXT X\r
- \r
- FOR X = 0 TO 31: B$ = B$ + MakePal$(31 - X, X, X): NEXT X\r
- FOR X = 0 TO 31: B$ = B$ + MakePal$(X, 31 - X, X): NEXT X\r
- FOR X = 0 TO 31: B$ = B$ + MakePal$(X, X, 31 - X): NEXT X\r
-\r
- Black$ = STRING$(192, 0)\r
- White$ = STRING$(128 * 3, 48)\r
-\r
- Pal1$ = Black$ + A$ + A$ + B$ + B$ + A$\r
-\r
- LOAD.DACS SSEGADD(Black$), 64, 127, 1\r
- LOAD.DACS SSEGADD(Black$), 20, 63, 0\r
-\r
- LOAD.DACS SSEGADD(White$), 128, 255, 0\r
-\r
- '*** Background ***\r
-\r
- FOR X = 0 TO 319\r
- FOR Y = 0 TO 239\r
- IF ((X + Y) AND 1) = 1 THEN SET.POINT X, Y, 64 + X \ 5 ELSE SET.POINT X, Y, 20 + Y \ 6\r
- NEXT Y\r
- NEXT X\r
-\r
- '*** Draw Font Displays ***\r
-\r
- PRINT.STRING "FONT: SYSTEM.FNT", 11, 7, 15\r
- PRINT.STRING "FONT: ROM_8x8.FNT", 11, 17, 15\r
- PRINT.STRING "FONT: SPACEAGE.FNT", 11, 27, 15\r
- PRINT.STRING "PRESS ANY KEY TO CONTINUE", 8, 29, 14\r
- \r
-\r
- FOR F = 0 TO 2\r
- SET.DISPLAY.FONT CharSet(F), 1\r
- Yp = F * 80 + 10\r
- FOR Y = 0 TO 96 STEP 32\r
- FOR X = 0 TO 31\r
- TGPRINTC 128 + Y + X, X * 10 + 1, Yp, 128 + Y\r
- NEXT X\r
- Yp = Yp + 10\r
- NEXT Y\r
- NEXT F\r
-\r
- DO\r
- LOOP UNTIL SCAN.KEYBOARD\r
-\r
- Offset = 0\r
- Restart = 192\r
- MaxOfs = 192 + 96 * 6\r
-\r
- Delay = 100\r
-\r
- Offset2 = 0\r
- Offset2Dir = 3\r
- Offset2Min = 192\r
- Offset2Max = Offset2Min + 192 * 6\r
-\r
- DO\r
- LOAD.DACS SSEGADD(Pal1$) + Offset, 64, 127, 1\r
- Offset = Offset + 3\r
- IF Offset >= MaxOfs THEN Offset = Restart\r
- IF Delay THEN\r
- Delay = Delay - 1\r
- ELSE\r
- LOAD.DACS SSEGADD(Pal1$) + Offset2, 20, 60, 0\r
- IF Offset2 = Offset2Max THEN Offset2Dir = -3\r
- IF Offset2 = Offset2Min THEN Offset2Dir = 3\r
- Offset2 = Offset2 + Offset2Dir\r
- END IF\r
-\r
- LOOP UNTIL SCAN.KEYBOARD\r
-\r
- ERROR.OUT "DEMO OVER"\r
-\r
-REM $STATIC\r
-SUB ERROR.OUT (Text$)\r
-\r
- SET.VIDEO.MODE 3\r
-\r
- DOS.PRINT Text$\r
-\r
- END\r
-\r
-END SUB\r
-\r
-SUB LOAD.FONT (FontFile$, FontNum) STATIC\r
-\r
- IF LEN(DIR$(FontFile$)) = 0 THEN ERROR.OUT "FILE NOT FOUND: " + FontFile$\r
-\r
- OPEN FontFile$ FOR BINARY AS #1\r
-\r
- SEEK #1, 1\r
- GET #1, , CharSet(FontNum)\r
-\r
- CLOSE #1\r
-\r
-END SUB\r
-\r
-FUNCTION MakePal$ (Red, Green, Blue) STATIC\r
-\r
- MakePal$ = CHR$(Red) + CHR$(Green) + CHR$(Blue)\r
-\r
-END FUNCTION\r
-\r
-SUB PRINT.STRING (Text$, Xpos, Ypos, Colour)\r
-\r
- TPRINT.STR SSEG(Text$), SADD(Text$), LEN(Text$), Xpos * 8, Ypos * 8, Colour\r
-\r
-END SUB\r
-\r
+++ /dev/null
-ECHO ... Building MODEX.QLB for BASIC PDS 7.1\r
-LIB MODEX -+MODEX,,\r
-LIB MODEX -+UTILS,,\r
-DEL MODEX.BAK\r
-LINK /Q MODEX+UTILS, MODEX.QLB, NUL, C:\BC7\LIB\QBXQLB.LIB;\1a\r
+++ /dev/null
- \r
- ' ===== SCREEN RESOLUTIONS =====\r
- \r
-CONST Mode320x200 = 0, Mode320x400 = 1\r
-CONST Mode360x200 = 2, Mode360x400 = 3\r
-CONST Mode320x240 = 4, Mode320x480 = 5\r
-CONST Mode360x240 = 6, Mode360x480 = 7\r
- \r
- ' ===== MODE X SETUP ROUTINES =====\r
- \r
-DECLARE FUNCTION SET.VGA.MODEX% ALIAS "SET_VGA_MODEX" (BYVAL ModeType%, BYVAL MaxXpos%, BYVAL MaxYpos%, BYVAL Pages%)\r
-DECLARE FUNCTION SET.MODEX% ALIAS "SET_MODEX" (BYVAL Mode%)\r
- \r
- ' ===== BASIC GRAPHICS PRIMITIVES =====\r
- \r
-DECLARE SUB CLEAR.VGA.SCREEN ALIAS "CLEAR_VGA_SCREEN" (BYVAL ColorNum%)\r
-DECLARE SUB SET.POINT ALIAS "SET_POINT" (BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorNum%)\r
-DECLARE FUNCTION READ.POINT% ALIAS "READ_POINT" (BYVAL Xpos%, BYVAL Ypos%)\r
-DECLARE SUB FILL.BLOCK ALIAS "FILL_BLOCK" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
-DECLARE SUB DRAW.LINE ALIAS "DRAW_LINE" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
- \r
- ' ===== DAC COLOR REGISTER ROUTINES =====\r
- \r
-DECLARE SUB SET.DAC.REGISTER ALIAS "SET_DAC_REGISTER" (BYVAL RegNo%, BYVAL Red%, BYVAL Green%, BYVAL Blue%)\r
-DECLARE SUB GET.DAC.REGISTER ALIAS "GET_DAC_REGISTER" (BYVAL RegNo%, Red%, Green%, Blue%)\r
-DECLARE SUB LOAD.DAC.REGISTERS ALIAS "LOAD_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%)\r
-DECLARE SUB READ.DAC.REGISTERS ALIAS "READ_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%)\r
- \r
- \r
- ' ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
- \r
-DECLARE SUB SET.ACTIVE.PAGE ALIAS "SET_ACTIVE_PAGE" (BYVAL PageNo%)\r
-DECLARE FUNCTION GET.ACTIVE.PAGE% ALIAS "GET_ACTIVE_PAGE"\r
-DECLARE SUB SET.DISPLAY.PAGE ALIAS "SET_DISPLAY_PAGE" (BYVAL PageNo%)\r
-DECLARE FUNCTION GET.DISPLAY.PAGE% ALIAS "GET_DISPLAY_PAGE"\r
-DECLARE SUB SET.WINDOW ALIAS "SET_WINDOW" (BYVAL DisplayPage%, BYVAL XOffset%, BYVAL YOffset%)\r
-DECLARE FUNCTION GET.X.OFFSET% ALIAS "GET_X_OFFSET" ()\r
-DECLARE FUNCTION GET.Y.OFFSET% ALIAS "GET_Y_OFFSET" ()\r
-DECLARE SUB SYNC.DISPLAY ALIAS "SYNC_DISPLAY"\r
- \r
- ' ===== TEXT DISPLAY ROUTINES =====\r
- \r
-DECLARE SUB GPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
-DECLARE SUB TGPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
-DECLARE SUB PRINT.STR ALIAS "PRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
-DECLARE SUB TPRINT.STR ALIAS "TPRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
-DECLARE SUB SET.DISPLAY.FONT ALIAS "SET_DISPLAY_FONT" (SEG FontData AS ANY, BYVAL FontNumber%)\r
- \r
- ' ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
- \r
-DECLARE SUB DRAW.BITMAP ALIAS "DRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
-DECLARE SUB TDRAW.BITMAP ALIAS "TDRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
- \r
- ' ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
- \r
-DECLARE SUB COPY.PAGE ALIAS "COPY_PAGE" (BYVAL SourcePage%, BYVAL DestPage%)\r
-DECLARE SUB COPY.BITMAP ALIAS "COPY_BITMAP" (BYVAL SourcePage%, BYVAL X1%, BYVAL Y1%, BYVAL X2%, BYVAL Y2%, BYVAL DestPage%, BYVAL DestX1%, BYVAL DestY1%)\r
- \r
- \r
- \r
- \r
- \r
- \r
+++ /dev/null
-'File: TEST6.BAS\r
-'Descp.: A Mode "X" demonstration\r
-'Author: Matt Pritchard\r
-'Date: 14 April, 1993\r
-'\r
-DECLARE SUB DEMO.RES (Mode%, Xmax%, Ymax%)\r
-DECLARE SUB ERROR.OUT (Message$)\r
-DECLARE FUNCTION GET.KEY% ()\r
-DECLARE SUB LOAD.SHAPES ()\r
-DECLARE SUB PAGE.DEMO ()\r
-DECLARE SUB PRINT.TEXT (Text$, Xpos%, Ypos%, ColorF%, ColorB%)\r
-DECLARE SUB TPRINT.TEXT (Text$, Xpos%, Ypos%, ColorF%)\r
-DEFINT A-Z\r
-\r
-\r
-TYPE ShapeType\r
- ImgData AS STRING * 512\r
- xWidth AS INTEGER\r
- yWidth AS INTEGER\r
-END TYPE\r
-\r
-TYPE Sprite\r
- Xpos AS INTEGER\r
- Ypos AS INTEGER\r
- XDir AS INTEGER\r
- YDir AS INTEGER\r
- Shape AS INTEGER\r
-END TYPE\r
-\r
-\r
-CONST MaxShapes = 32\r
-\r
- REM $INCLUDE: 'UTILS.BI'\r
- REM $INCLUDE: 'MODEX.BI'\r
-\r
-DIM SHARED Img(32) AS ShapeType\r
-COMMON SHARED Img() AS ShapeType\r
-\r
-\r
- CALL INIT.RANDOM\r
-\r
- CALL LOAD.SHAPES\r
-\r
- CALL DEMO.RES(Mode320x200, 320, 200)\r
- CALL DEMO.RES(Mode320x400, 320, 400)\r
-\r
- CALL DEMO.RES(Mode360x200, 360, 200)\r
- CALL DEMO.RES(Mode360x400, 360, 400)\r
-\r
- CALL DEMO.RES(Mode320x240, 320, 240)\r
- CALL DEMO.RES(Mode320x480, 320, 480)\r
-\r
- CALL DEMO.RES(Mode360x240, 360, 240)\r
- CALL DEMO.RES(Mode360x480, 360, 480)\r
-\r
- CALL PAGE.DEMO\r
-\r
- SET.VIDEO.MODE 3\r
- DOS.PRINT "THIS MODE X DEMO IS FINISHED"\r
- END\r
-\r
-SUB DEMO.RES (Mode, Xmax, Ymax)\r
-\r
- IF SET.MODEX%(Mode) = 0 THEN\r
- ERROR.OUT "Unable to SET_MODEX" + STR$(Mode)\r
- END IF\r
-\r
- XCenter = Xmax \ 2\r
- \r
- X1 = 10\r
- Y1 = 10\r
- X2 = Xmax - 1\r
- Y2 = Ymax - 1\r
-\r
- FOR Z = 0 TO 3\r
- Colr = 31 - Z * 2\r
- DRAW.LINE X1 + Z, Y1 + Z, X2 - Z, Y1 + Z, Colr\r
- DRAW.LINE X1 + Z, Y1 + Z, X1 + Z, Y2 - Z, Colr\r
- DRAW.LINE X1 + Z, Y2 - Z, X2 - Z, Y2 - Z, Colr\r
- DRAW.LINE X2 - Z, Y1 + Z, X2 - Z, Y2 - Z, Colr\r
- NEXT Z\r
-\r
- XChars = Xmax \ 10\r
- YChars = Ymax \ 10\r
-\r
- FOR X = 0 TO XChars - 1\r
- TGPRINTC 48 + ((X + 1) MOD 10), X * 10 + 1, 1, 9 + ((X \ 8) MOD 7)\r
- DRAW.LINE X * 10 + 9, 0, X * 10 + 9, 3, 15\r
- NEXT X\r
-\r
- FOR Y = 0 TO YChars - 1\r
- TGPRINTC 48 + ((Y + 1) MOD 10), 1, Y * 10 + 1, 9 + ((Y \ 10) MOD 7)\r
- DRAW.LINE 0, Y * 10 + 9, 3, Y * 10 + 9, 15\r
- NEXT Y\r
-\r
- ' Draw Lines\r
-\r
- FOR X = 0 TO 63\r
- N = 15 + X * .75\r
- SET.DAC.REGISTER 64 + X, N, N, N\r
- SET.DAC.REGISTER 128 + X, 0, N, N\r
-\r
- DRAW.LINE 103 - X, 60, 40 + X, 123, 64 + X\r
- DRAW.LINE 40, 60 + X, 103, 123 - X, 128 + X\r
-\r
- NEXT X\r
- TPRINT.TEXT "LINE TEST", 37, 130, c.BLUE\r
-\r
- Y = 60: Gap = 0\r
- FOR X = 0 TO 9\r
- FILL.BLOCK 120, Y, 120 + X, Y + Gap, 64 + X\r
- FILL.BLOCK 140 - (15 - X), Y, 150 + X, Y + Gap, 230 + X\r
- FILL.BLOCK 170 - (15 - X), Y, 170, Y + Gap, 128 + X\r
- Y = Y + Gap + 2\r
- Gap = Gap + 1\r
- NEXT X\r
- TPRINT.TEXT "FILL TEST", 110, 46, c.GREEN\r
-\r
-\r
- FOR X = 190 TO 250 STEP 2\r
- FOR Y = 60 TO 122 STEP 2\r
- SET.POINT X, Y, X + Y + X + Y\r
- NEXT Y\r
- NEXT X\r
-\r
- TPRINT.TEXT "PIXEL TEST", 182, 130, c.RED\r
-\r
- FOR X = 190 TO 250 STEP 2\r
- FOR Y = 60 TO 122 STEP 2\r
- IF READ.POINT(X, Y) <> ((X + Y + X + Y) AND 255) THEN\r
- ERROR.OUT "READ.PIXEL Failure"\r
- END IF\r
- NEXT Y\r
- NEXT X\r
-\r
-\r
-\r
- Msg$ = " This is a MODE X demo "\r
- PRINT.TEXT Msg$, XCenter - (LEN(Msg$) * 4), 20, c.bRED, c.BLUE\r
- Msg$ = "Screen Resolution is by "\r
- Xp = XCenter - (LEN(Msg$) * 4)\r
- PRINT.TEXT Msg$, Xp, 30, c.bGREEN, c.BLACK\r
-\r
- PRINT.TEXT LTRIM$(STR$(Xmax)), Xp + 8 * 21, 30, c.bPURPLE, c.BLACK\r
- PRINT.TEXT LTRIM$(STR$(Ymax)), Xp + 8 * 28, 30, c.bWHITE, c.BLACK\r
-\r
- FOR X = 0 TO 15\r
- SET.DAC.REGISTER 230 + X, 63 - X * 4, 0, 15 + X * 3\r
- DRAW.LINE 30 + X, Ymax - 6 - X, Xmax - 20 - X, Ymax - 6 - X, 230 + X\r
- NEXT X\r
- TPRINT.TEXT "Press <ANY KEY> to Continue", XCenter - (26 * 4), Ymax - 18, c.YELLOW\r
-\r
- X = GET.KEY%\r
- IF X = KyESC THEN ERROR.OUT "ABORT"\r
-\r
-END SUB\r
-\r
-SUB ERROR.OUT (Message$)\r
-\r
- SET.VIDEO.MODE 3\r
- DOS.PRINT Message$\r
- END\r
-\r
-END SUB\r
-\r
-FUNCTION GET.KEY%\r
-\r
- DO\r
- X = SCAN.KEYBOARD\r
- LOOP UNTIL X\r
-\r
- GET.KEY% = X\r
-\r
-END FUNCTION\r
-\r
-SUB LOAD.SHAPES\r
-\r
-DIM Grid(1 TO 32, 1 TO 32)\r
-\r
- FOR Shape = 0 TO MaxShapes - 1\r
-\r
- FOR Y = 1 TO 32\r
- FOR X = 1 TO 32\r
- Grid(X, Y) = 0\r
- NEXT X\r
- NEXT Y\r
-\r
- Style = RANDOM.INT(6)\r
- Colour = 1 + RANDOM.INT(15)\r
- \r
- SELECT CASE Style\r
-\r
- CASE 0: ' Solid Box\r
-\r
- DO\r
- xWidth = 3 + RANDOM.INT(30)\r
- yWidth = 3 + RANDOM.INT(30)\r
- LOOP UNTIL ((xWidth * yWidth) <= 512)\r
-\r
- FOR Y = 1 TO yWidth\r
- FOR X = 1 TO xWidth\r
- Grid(X, Y) = Colour\r
- NEXT X\r
- NEXT Y\r
-\r
- CASE 1: ' Hollow Box\r
-\r
- DO\r
- xWidth = 5 + RANDOM.INT(28)\r
- yWidth = 5 + RANDOM.INT(28)\r
- LOOP UNTIL ((xWidth * yWidth) <= 512)\r
-\r
- FOR Y = 1 TO yWidth\r
- FOR X = 1 TO xWidth\r
- Grid(X, Y) = Colour\r
- NEXT X\r
- NEXT Y\r
-\r
- HollowX = 1 + RANDOM.INT(xWidth \ 2 - 1)\r
- HollowY = 1 + RANDOM.INT(yWidth \ 2 - 1)\r
-\r
- FOR Y = HollowY + 1 TO yWidth - HollowY\r
- FOR X = HollowX + 1 TO xWidth - HollowX\r
- Grid(X, Y) = nil\r
- NEXT X\r
- NEXT Y\r
-\r
- CASE 2: ' Solid Diamond\r
-\r
- xWidth = 3 + 2 * RANDOM.INT(10)\r
- yWidth = xWidth\r
- Centre = xWidth \ 2\r
-\r
- FOR Y = 0 TO Centre\r
- FOR X = 0 TO Y\r
- Grid(Centre - X + 1, Y + 1) = Colour\r
- Grid(Centre + X + 1, Y + 1) = Colour\r
- Grid(Centre - X + 1, yWidth - Y) = Colour\r
- Grid(Centre + X + 1, yWidth - Y) = Colour\r
- NEXT X\r
- NEXT Y\r
-\r
-\r
- CASE 3: ' Hollow Diamond\r
-\r
-\r
- xWidth = 3 + 2 * RANDOM.INT(10)\r
- yWidth = xWidth\r
- Centre = xWidth \ 2\r
- sWidth = RANDOM.INT(Centre)\r
-\r
- FOR Y = 0 TO Centre\r
- FOR X = 0 TO Y\r
- IF X + (Centre - Y) >= sWidth THEN\r
- Grid(Centre - X + 1, Y + 1) = Colour\r
- Grid(Centre + X + 1, Y + 1) = Colour\r
- Grid(Centre - X + 1, yWidth - Y) = Colour\r
- Grid(Centre + X + 1, yWidth - Y) = Colour\r
- END IF\r
- NEXT X\r
- NEXT Y\r
-\r
- CASE 4: ' Ball\r
-\r
- xWidth = 7 + 2 * RANDOM.INT(8)\r
- yWidth = xWidth\r
- Centre = 1 + xWidth \ 2\r
-\r
- FOR Y = 1 TO yWidth\r
- FOR X = 1 TO xWidth\r
- D = SQR(((Centre - X) * (Centre - X)) + ((Centre - Y) * (Centre - Y)))\r
- IF D < Centre THEN Grid(X, Y) = 150 + Colour * 2 + D * 3\r
- NEXT X\r
- NEXT Y\r
-\r
- CASE 5: ' Ball\r
-\r
-\r
- xWidth = 7 + 2 * RANDOM.INT(8)\r
- yWidth = xWidth\r
- Centre = 1 + xWidth \ 2\r
- sWidth = RANDOM.INT(xWidth)\r
-\r
- FOR Y = 1 TO yWidth\r
- FOR X = 1 TO xWidth\r
- D = SQR(((Centre - X) * (Centre - X)) + ((Centre - Y) * (Centre - Y)))\r
- IF D < Centre AND D >= sWidth THEN Grid(X, Y) = 150 + Colour * 2 + D * 3\r
- NEXT X\r
- NEXT Y\r
-\r
- END SELECT\r
-\r
- Img(Shape).xWidth = xWidth\r
- Img(Shape).yWidth = yWidth\r
-\r
- A$ = STRING$(xWidth * yWidth, nil)\r
-\r
- c = 1\r
- FOR Y = 1 TO yWidth\r
- FOR X = 1 TO xWidth\r
- MID$(A$, c, 1) = CHR$(Grid(X, Y))\r
- c = c + 1\r
- NEXT X\r
- NEXT Y\r
-\r
- Img(Shape).ImgData = A$\r
- \r
-\r
- NEXT Shape\r
-\r
-END SUB\r
-\r
-SUB PAGE.DEMO\r
-\r
-CONST MaxSprites = 64\r
-\r
-DIM Obj(MaxSprites) AS Sprite\r
-DIM LastX(MaxSprites, 1), LastY(MaxSprites, 1)\r
-DIM LastObjects(1)\r
-\r
- ScreenX = 360: ScreenY = 240\r
-\r
- IF SET.VGA.MODEX%(Mode320x200, ScreenX, ScreenY, 3) = 0 THEN\r
- ERROR.OUT "Unable to SET_VGA_MODEX" + STR$(Mode)\r
- END IF\r
-\r
- SET.ACTIVE.PAGE 0\r
-\r
- CLEAR.VGA.SCREEN c.BLACK\r
- \r
- PRINT.TEXT "This is a Test of the Following Functions:", 10, 9, c.bWHITE, c.BLACK\r
-\r
- DRAW.LINE 10, 18, 350, 18, c.YELLOW\r
- PRINT.TEXT "SET_ACTIVE_PAGE", 10, 20, c.bBLUE, c.BLACK\r
- PRINT.TEXT "SET_DISPLAY_PAGE", 10, 30, c.GREEN, c.BLACK\r
- PRINT.TEXT "SET_DAC_REGISTER", 10, 40, c.RED, c.BLACK\r
- PRINT.TEXT "CLEAR_VGA_SCREEN", 10, 50, c.CYAN, c.BLACK\r
-\r
- PRINT.TEXT "TDRAW_BITMAP", 10, 60, c.PURPLE, c.BLACK\r
- PRINT.TEXT "COPY_PAGE", 10, 70, c.GREEN, c.BLACK\r
- PRINT.TEXT "COPY_BITMAP", 10, 80, c.CYAN, c.BLACK\r
-\r
- PRINT.TEXT "GPRINTC", 10, 90, c.BLUE, c.BLACK\r
- PRINT.TEXT "TGPRINTC", 10, 100, c.GREEN, c.BLACK\r
- PRINT.TEXT "SET_WINDOW", 10, 110, c.RED, c.BLACK\r
-\r
- PRINT.TEXT "VIRTUAL SCREEN SIZES", 190, 20, c.bBLUE, c.BLACK\r
- PRINT.TEXT " SMOOTH SCROLLING", 190, 30, c.GREEN, c.BLACK\r
- PRINT.TEXT " SPRITE ANIMATION", 190, 40, c.CYAN, c.BLACK\r
- PRINT.TEXT " PAGE FLIPPING", 190, 50, c.RED, c.BLACK\r
- PRINT.TEXT " COLOR CYCLING", 190, 60, c.PURPLE, c.BLACK\r
-\r
-\r
- FOR X = 0 TO 60\r
- SET.DAC.REGISTER 50 + X, 3 + X, 0, 60 - X\r
- SET.DAC.REGISTER 150 + X, 3 + X, 0, 60 - X\r
- NEXT X\r
-\r
- c = 0: DC = 1\r
- FOR X = 0 TO ScreenX \ 2\r
- DRAW.LINE ScreenX \ 2 - 1, ScreenY \ 4, X, ScreenY - 1, c + 50\r
- DRAW.LINE ScreenX \ 2, ScreenY \ 4, ScreenX - X - 1, ScreenY - 1, c + 50\r
- c = c + DC\r
- IF c = 0 OR c = 60 THEN DC = -DC\r
- NEXT X\r
- \r
- TPRINT.TEXT "Press <ANY KEY> to Continue", 72, 190, c.bWHITE\r
- TPRINT.TEXT "< > = Faster < > = Slower", 72, 204, c.bGREEN\r
- TPRINT.TEXT "< > = Fewer Shapes < > = More Shapes", 32, 218, c.bCYAN\r
-\r
- TGPRINTC 43, 80, 204, c.YELLOW\r
- TGPRINTC 45, 200, 204, c.YELLOW\r
-\r
- TGPRINTC 25, 40, 218, c.YELLOW\r
- TGPRINTC 24, 200, 218, c.YELLOW\r
-\r
- COPY.PAGE 0, 1\r
- COPY.PAGE 0, 2\r
-\r
- FOR X = 1 TO MaxSprites\r
- DO\r
- Obj(X).XDir = RANDOM.INT(7) - 3\r
- Obj(X).YDir = RANDOM.INT(7) - 3\r
- LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
-\r
- Obj(X).Shape = X MOD MaxShapes\r
-\r
- SpriteX = Img(Obj(X).Shape).xWidth\r
- SpriteY = Img(Obj(X).Shape).yWidth\r
-\r
- Obj(X).Xpos = 1 + RANDOM.INT(ScreenX - SpriteX - 2)\r
- Obj(X).Ypos = 1 + RANDOM.INT(ScreenY - SpriteY - 2)\r
-\r
- LastX(X, 0) = Obj(X).Xpos\r
- LastX(X, 1) = Obj(X).Xpos\r
- LastY(X, 0) = Obj(X).Ypos\r
- LastY(X, 1) = Obj(X).Ypos\r
- NEXT X\r
-\r
- CurrentPage = 0\r
-\r
- 'View Shift...\r
-\r
- ViewX = 0\r
- ViewY = 0\r
- ViewMax = 3\r
- ViewCnt = 0\r
- ViewXD = 1\r
- ViewYD = 1\r
-\r
- SetColor = 3: SDir = 1\r
- PrevColor = 0: PDir = 1\r
-\r
- VisObjects = MaxSprites \ 2\r
- LastObjects(0) = 0\r
- LastObjects(1) = 0\r
-\r
-DRAW.LOOP:\r
-\r
-\r
- SET.ACTIVE.PAGE CurrentPage\r
-\r
- ' Erase Old Images\r
-\r
- FOR X = 1 TO LastObjects(CurrentPage)\r
- \r
- X1 = LastX(X, CurrentPage) AND &HFFFC\r
- Y1 = LastY(X, CurrentPage)\r
- X2 = ((LastX(X, CurrentPage) + Img(Obj(X).Shape).xWidth)) OR 3\r
- Y2 = Y1 + Img(Obj(X).Shape).yWidth - 1\r
-\r
- COPY.BITMAP 2, X1, Y1, X2, Y2, CurrentPage, X1, Y1\r
- \r
- NEXT X\r
-\r
- ' Draw new images\r
-\r
- FOR X = 1 TO VisObjects\r
-\r
- SpriteX = Img(Obj(X).Shape).xWidth\r
- SpriteY = Img(Obj(X).Shape).yWidth\r
-\r
- ' Move Sprite\r
-\r
-REDOX:\r
- NewX = Obj(X).Xpos + Obj(X).XDir\r
- IF NewX < 0 OR NewX + SpriteX > ScreenX THEN\r
- Obj(X).XDir = -Obj(X).XDir\r
- IF RANDOM.INT(20) = 1 THEN\r
- DO\r
- Obj(X).XDir = RANDOM.INT(7) - 3\r
- Obj(X).YDir = RANDOM.INT(7) - 3\r
- LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
- GOTO REDOX\r
- END IF\r
- END IF\r
- Obj(X).Xpos = Obj(X).Xpos + Obj(X).XDir\r
-\r
-REDOY:\r
- NewY = Obj(X).Ypos + Obj(X).YDir\r
- IF NewY < 0 OR NewY + SpriteY > ScreenY THEN\r
- Obj(X).YDir = -Obj(X).YDir\r
- IF RANDOM.INT(20) = 1 THEN\r
- DO\r
- Obj(X).XDir = RANDOM.INT(7) - 3\r
- Obj(X).YDir = RANDOM.INT(7) - 3\r
- LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
- GOTO REDOY\r
- END IF\r
- END IF\r
- Obj(X).Ypos = Obj(X).Ypos + Obj(X).YDir\r
-\r
- 'Draw Sprite\r
-\r
- TDRAW.BITMAP Img(Obj(X).Shape), Obj(X).Xpos, Obj(X).Ypos, SpriteX, SpriteY\r
-\r
- LastX(X, CurrentPage) = Obj(X).Xpos\r
- LastY(X, CurrentPage) = Obj(X).Ypos\r
-\r
- NEXT X\r
-\r
- LastObjects(CurrentPage) = VisObjects\r
-\r
- ' Pan Screen Back & Forth\r
-\r
- ViewCnt = ViewCnt + 1\r
- IF ViewCnt >= ViewMax THEN\r
- ViewX = ViewX + ViewXD\r
- IF ViewX = 0 OR ViewX = 39 THEN ViewXD = -ViewXD\r
- IF ViewXD < 0 THEN\r
- ViewY = ViewY + ViewYD\r
- IF ViewY = 0 OR ViewY = 39 THEN ViewYD = -ViewYD\r
- END IF\r
- \r
- SET.WINDOW CurrentPage, ViewX, ViewY\r
-\r
- ViewCnt = 0\r
- ELSE\r
- SET.DISPLAY.PAGE CurrentPage\r
- END IF\r
-\r
- ' Cycle Colors\r
-\r
- SET.DAC.REGISTER 50 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor\r
- SET.DAC.REGISTER 50 + SetColor, SetColor, 10, 63 - SetColor\r
-\r
- SET.DAC.REGISTER 150 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor\r
- SET.DAC.REGISTER 150 + SetColor, 63, 63, SetColor\r
-\r
- SetColor = SetColor + SDir\r
- IF SetColor = 60 OR SetColor = 0 THEN SDir = -SDir\r
-\r
- PrevColor = PrevColor + PDir\r
- IF PrevColor = 60 OR PrevColor = 0 THEN PDir = -PDir\r
-\r
- CurrentPage = 1 - CurrentPage\r
-\r
- Code = SCAN.KEYBOARD\r
-\r
- IF Code = False THEN GOTO DRAW.LOOP\r
-\r
- IF Code = KyPlus THEN\r
- IF ViewMax < 12 THEN ViewMax = ViewMax + 1\r
- GOTO DRAW.LOOP\r
- END IF\r
-\r
- IF Code = KyMinus THEN\r
- IF ViewMax > 1 THEN ViewMax = ViewMax - 1\r
- IF ViewCnt >= ViewMax THEN ViewCnt = 0\r
- GOTO DRAW.LOOP\r
- END IF\r
-\r
- IF Code = KyUp THEN\r
- IF VisObjects < MaxSprites THEN VisObjects = VisObjects + 1\r
- GOTO DRAW.LOOP\r
- END IF\r
- \r
- IF Code = KyDown THEN\r
- IF VisObjects > 1 THEN VisObjects = VisObjects - 1\r
- GOTO DRAW.LOOP\r
- END IF\r
-\r
-\r
-END SUB\r
-\r
-SUB PRINT.TEXT (Text$, Xpos, Ypos, ColorF, ColorB)\r
-\r
- IF LEN(Text$) = 0 THEN EXIT SUB\r
-\r
- PRINT.STR SSEG(Text$), SADD(Text$), LEN(Text$), Xpos, Ypos, ColorF, ColorB\r
-\r
-\r
-END SUB\r
-\r
-SUB TPRINT.TEXT (Text$, Xpos, Ypos, ColorF)\r
-\r
- IF LEN(Text$) = 0 THEN EXIT SUB\r
-\r
- TPRINT.STR SSEG(Text$), SADD(Text$), LEN(Text$), Xpos, Ypos, ColorF\r
-\r
-END SUB\r
-\r
+++ /dev/null
-MASM /DFARSTRINGS utils, utils, utils, nul;
\ No newline at end of file
+++ /dev/null
-;=======================================================\r
-;=== UTILS.ASM - Asm Utilities for QuickBasic/BC7 ===\r
-;=======================================================\r
-\r
- PAGE 255, 132\r
-\r
- .MODEL Medium\r
- .286\r
-\r
- ; ==== MACROS ====\r
-\r
- ; macros to PUSH and POP multiple registers\r
-\r
-PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
- IFNB <R1>\r
- push R1 ; Save R1\r
- PUSHx R2, R3, R4, R5, R6, R7, R8\r
- ENDIF\r
-ENDM\r
-\r
-POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
- IFNB <R1>\r
- pop R1 ; Restore R1\r
- POPx R2, R3, R4, R5, R6, R7, R8\r
- ENDIF\r
-ENDM\r
-\r
- ; Macro to Clear a Register to 0\r
-\r
-CLR MACRO Register\r
- xor Register, Register ; Set Register = 0\r
-ENDM\r
-\r
- ; Macros to Decrement Counter & Jump on Condition\r
-\r
-LOOPx MACRO Register, Destination\r
- dec Register ; Counter--\r
- jnz Destination ; Jump if not 0\r
-ENDM\r
-\r
-LOOPjz MACRO Register, Destination\r
- dec Register ; Counter--\r
- jz Destination ; Jump if 0\r
-ENDM\r
-\r
-\r
- ; ==== General Constants ====\r
-\r
- False EQU 0\r
- True EQU -1\r
- nil EQU 0\r
-\r
- b EQU BYTE PTR\r
- w EQU WORD PTR\r
- d EQU DWORD PTR\r
- o EQU OFFSET\r
- f EQU FAR PTR\r
- s EQU SHORT\r
- ?x4 EQU <?,?,?,?>\r
- ?x3 EQU <?,?,?>\r
-\r
-\r
-IFDEF FARSTRINGS\r
-\r
- EXTRN stringaddress:far\r
- EXTRN stringlength:far\r
-\r
-ENDIF\r
-\r
-\r
- .Data\r
-\r
- EVEN\r
-\r
-RND_Seed DW 7397, 29447, 802\r
-RND_Mult DW 179, 183, 182\r
-RND_ModV DW 32771, 32779, 32783\r
-\r
-CR_LF DB 13, 10 ; the CRLF data\r
-\r
- .Code\r
-\r
-;=================\r
-;DOS_PRINT (Text$)\r
-;=================\r
-;\r
-; Prints Text Directly to DOS console w/ CR/LF\r
-;\r
-\r
- PUBLIC DOS_PRINT\r
-\r
-DP_Stack STRUC\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- DP_Text DW ? ; Address of Text$ Descriptor\r
-DP_Stack ENDS\r
-\r
-\r
-DOS_PRINT PROC FAR\r
-\r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- mov SI, [BP].DP_Text ; Get Addr of Text$ descriptor\r
-\r
-IFDEF FARSTRINGS\r
- push SI ; Push Addr of BC7 Decriptor Ptr\r
- call stringaddress ; Get Address + Len of string!!!\r
- ; DX:AX = Addr CX = Len\r
- mov DS, DX ; DS = DX = Segment of string\r
- mov DX, AX ; DX = AX = Offset of String\r
-ELSE\r
- mov CX, [SI] ; put its length into CX\r
- mov DX, [SI+02] ; now DS:DX points to the String\r
-ENDIF\r
-\r
- jcxz @No_Print ; Don't Print if empty\r
-\r
- mov BX, 1 ; 1= DOS Handle for Display\r
- mov AH, 40h ; Write Text Function\r
- int 21h ; Call DOS to do it\r
-\r
-@No_Print:\r
- mov AX, SEG DGROUP ; Restore DGroup\r
- mov DS, AX\r
-\r
- mov DX, o CR_LF ; Get Addr of CR/LF pair\r
- mov CX, 2 ; 2 Characters to Write \r
- mov BX, 1 ; 1= DOS Handle for Display\r
-\r
- mov AH, 40h ; Write Text Function\r
- int 21h ; Call DOS to do it\r
-\r
- cld ; Reset Direction Flag \r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- ret 2 ; Exit & Clean Up Stack\r
-\r
-DOS_PRINT ENDP\r
-\r
-\r
-;==================\r
-;DOS_PRINTS (Text$)\r
-;==================\r
-; \r
-; Print Text$ Directly to DOS console \r
-; without a trailing CR/LF\r
-;\r
-\r
- PUBLIC DOS_PRINTS\r
-\r
-DOS_PRINTS PROC FAR\r
-\r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- mov SI, [BP].DP_Text ; Get Addr of Text$ descriptor\r
-\r
-IFDEF FARSTRINGS\r
- push SI ; Push Addr of BC7 Decriptor Ptr\r
- call stringaddress ; Get Address + Len of string!!!\r
- ; DX:AX = Addr CX = Len\r
- mov DS, DX ; DS = DX = Segment of string\r
- mov DX, AX ; DX = AX = Offset of String\r
-ELSE\r
- mov CX, [SI] ; put its length into CX\r
- mov DX, [SI+02] ; now DS:DX points to the String\r
-ENDIF\r
-\r
- jcxz @DPS_Exit ; Don't Print if empty\r
-\r
- mov BX, 1 ; 1= DOS Handle for Display\r
- mov AH, 40h ; Write Text Function\r
- int 21h ; Call DOS to do it\r
-\r
-@DPS_Exit:\r
- cld ; Reset Direction Flag \r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- ret 2 ; Exit & Clean Up Stack\r
-\r
-DOS_PRINTS ENDP\r
-\r
-\r
-;======================\r
-;SET_VIDEO_MODE (Mode%) \r
-;======================\r
-;\r
-; Sets the Video Mode through the BIOS\r
-;\r
-\r
- PUBLIC SET_VIDEO_MODE\r
-\r
-SVM_Stack STRUC\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- SVM_Mode DB ?,? ; Desired Video Mode\r
-SVM_Stack ENDS\r
-\r
-\r
-SET_VIDEO_MODE PROC FAR\r
-\r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- CLR AH ; Function 0\r
- mov AL, [BP].SVM_Mode ; Get Mode #\r
-\r
- int 10H ; Change Video Modes\r
-\r
-@SVM_Exit:\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- ret 2 ; Exit & Clean Up Stack\r
-\r
-SET_VIDEO_MODE ENDP\r
-\r
-\r
-;==============\r
-;SCAN_KEYBOARD%\r
-;==============\r
-;\r
-; Function to scan keyboard for a pressed key\r
-;\r
-\r
- PUBLIC SCAN_KEYBOARD\r
-\r
-SCAN_KEYBOARD PROC FAR\r
-\r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
-\r
- mov AH, 01H ; Function #1\r
- int 16H ; Call Keyboard Driver\r
- jz @SK_NO_KEY ; Exit if Zero flag set\r
-\r
- mov AH, 00H ; Remove Key from Buffer\r
- int 16H ; Get Keycode in AX\r
-\r
- or AL, AL ; Low Byte Set (Ascii?)\r
- jz @SK_Exit ; if not, it's a F-Key\r
-\r
- CLR AH ; Clear ScanCode if Ascii\r
- jmp s @SK_Exit ; Return Key in AX\r
-\r
-@SK_NO_KEY:\r
- CLR AX ; Return Nil (no Keypress)\r
-\r
-@SK_Exit:\r
- cld ; Reset Direction Flag \r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- ret ; Exit & Clean Up Stack\r
-\r
-SCAN_KEYBOARD ENDP\r
-\r
-\r
-;====================\r
-;RANDOM_INT (MaxInt%)\r
-;====================\r
-;\r
-; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
-;\r
-\r
-\r
- PUBLIC RANDOM_INT\r
-\r
-RI_Stack STRUC\r
- DW ? ; BP\r
- DD ? ; Caller\r
- RI_MaxVal DW ? ; Maximum Value to Return + 1\r
-RI_Stack ENDS\r
-\r
-\r
-RANDOM_INT PROC FAR\r
-\r
- push BP ; Preserve Important Registers\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- CLR BX ; BX is the data index\r
- CLR CX ; CX is the accumulator\r
-\r
-REPT 3\r
- mov AX, RND_Seed[BX] ; load the initial seed\r
- mul RND_Mult[BX] ; multiply it\r
- div RND_ModV[BX] ; and obtain the Mod value\r
- mov RND_Seed[BX], DX ; save that for the next time\r
-\r
- add CX, DX ; add it into the accumulator\r
- inc BX\r
- inc BX ; point to the next set of values\r
-ENDM\r
-\r
- mov AX, CX ; AX = Random #\r
- CLR DX ; DX = 0\r
- div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder\r
-\r
- mov AX, DX\r
-\r
- pop BP ; Restore BP\r
- ret 2 ; back to BASIC with AX holding the result\r
-\r
-RANDOM_INT ENDP\r
-\r
-\r
-;===========\r
-;INIT_RANDOM\r
-;===========\r
-;\r
-; Scrambles the psuedo-random number sequence\r
-; (XOR's the seed value with the timer)\r
-;\r
-\r
- PUBLIC INIT_RANDOM\r
-\r
-INIT_RANDOM PROC FAR\r
-\r
- clr AX ; Segment = 0000\r
- mov ES, AX\r
- mov AX, ES:[046Ch] ; Get Timer Lo Word\r
-\r
- xor RND_Seed, AX ; Scramble 1st Seed\r
-\r
- ret ; Exit & Clean Up Stack\r
-\r
-INIT_RANDOM ENDP\r
-\r
-\r
-;====================\r
-;INT_SQR (X%, Round%)\r
-;====================\r
-;\r
-; Returns the Integer Square Root of (X)\r
-; Round allows the return value to be rounded to the \r
-; nearest integer value by passing 0x80. Passing 0\r
-; return the Integer Portion only. The rounding amound is\r
-; a number from 0 to 1 multiplied by 256, thus \r
-; 0.5 * 0x100 = 0x80!\r
-;\r
-\r
-ISQ_Stack STRUC\r
- DW ?,? ; BP, DI\r
- DD ? ; Caller\r
- ISQ_Round DW ? ; Amount to Round Result * 256\r
- ISQ_X DW ? ; "X"\r
-ISQ_Stack ENDS\r
-\r
- PUBLIC INT_SQR\r
-\r
-INT_SQR PROC FAR\r
-\r
- PUSHx BP, DI ; Save BP\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- xor AX, AX ; {xor eax,eax}\r
- xor DX, DX ; {xor edx,edx}\r
- mov DI, [BP].ISQ_X ; {mov edi,x}\r
-\r
- mov CX, 16 ; {mov cx, 32}\r
-\r
-@ISQ_L:\r
-\r
- shl DI, 1 ; {shl edi,1}\r
- rcl DX, 1 ; {rcl edx,1}\r
- shl DI, 1 ; {shl edi,1}\r
- rcl DX, 1 ; {rcl edx,1}\r
- shl AX, 1 ; {shl eax,1}\r
- mov BX, AX ; {mov ebx,eax}\r
- shl BX, 1 ; {shl ebx,1}\r
- inc BX ; {inc ebx}\r
- cmp DX, BX ; {cmp edx,ebx}\r
- jl @ISQ_S\r
-\r
- sub DX, BX ; {sub edx,ebx}\r
- inc AX ; {inc eax}\r
-\r
-@ISQ_S: \r
- loop @ISQ_L\r
-\r
- add ax, [BP].ISQ_Round ; {add eax,$00008000} \r
- ; {*round* result in hi word: ie. +0.5}\r
- shr ax, 8 ; {shr eax,16} {to ax (result)}\r
-\r
- POPx DI, BP ; Restore Registers \r
- ret 4 ; Exit\r
-\r
-INT_SQR ENDP\r
-\r
-\r
-;============\r
-;TIMER_COUNT&\r
-;============\r
-;\r
-; Returns the current timer value as an integer/long integer\r
-;\r
-\r
-\r
- PUBLIC TIMER_COUNT\r
-\r
-TIMER_COUNT PROC FAR\r
-\r
- clr AX ; Segment = 0000\r
- mov ES, AX ; use ES to get at data\r
- mov AX, ES:[046Ch] ; Get Timer Lo Word\r
- mov DX, ES:[046Eh] ; Get Timer Hi Word\r
- ret ; Exit & Return value in DX:AX\r
-\r
-TIMER_COUNT ENDP\r
-\r
-\r
- END\r
+++ /dev/null
-\r
- ' Misc Constants\r
-\r
-CONST True = -1, False = 0, nil = 0\r
-\r
- ' Keyboard Codes: Extended\r
-\r
-CONST KyF1 = &H3B00, KyF2 = &H3C00, KyF3 = &H3D00, KyF4 = &H3E00, KyF5 = &H3F00\r
-CONST KyF6 = &H4000, KyF7 = &H4100, KyF8 = &H4200, KyF9 = &H4300, KyF10 = &H4400\r
-\r
-CONST KyUp = &H4800, KyLeft = &H4B00, KyRight = &H4D00, KyDown = &H5000\r
-CONST KySLeft = &HCB00, KySRight = &HCD00, KySUp = &HC800, KySDown = &HD000\r
-\r
-CONST KyHome = &H4700, KyPgUp = &H4900, KyEnd = &H4F00, KyPgDn = &H5100\r
-CONST KySHome = &HC700, KySPgUp = &HC900, KySEnd = &HCF00, KySPgDn = &HD100\r
-\r
-CONST KyIns = &H5200, KyDel = &H5300, KyRvsTab = &H8F00\r
-CONST KySIns = &HC200, KySDel = &HC300\r
-\r
-CONST KyAltA = &H1E00, KyAltB = &H3000, KyAltC = &H2E00, KyAltD = &H2000\r
-CONST KyAltE = &H1200, KyAltF = &H2100, KyAltG = &H2200, KyAltH = &H2300\r
-CONST KyAltI = &H1700, KyAltJ = &H2400, KyAltK = &H2500, KyAltL = &H2600\r
-CONST KyAltM = &H3200, KyAltN = &H3100, KyAltO = &H1800, KyAltP = &H1900\r
-CONST KyAltQ = &H1000, KyAltR = &H1300, KyAltS = &H1F00, KyAltT = &H1400\r
-CONST KyAltU = &H1600, KyAltV = &H2F00, KyAltW = &H1100, KyAltX = &H2D00\r
-CONST KyAltY = &H1500, KyAltZ = &H2C00\r
-\r
- ' Keyboard Codes: Ascii\r
-\r
-CONST KyBS = 8, KyTab = 9, KyCR = 13, KyESC = &H1B, KyClr = &H7F\r
-CONST KyPlus = 45, KyMinus = 43\r
-\r
- ' Color Constants\r
-\r
-CONST c.BLACK = 0, c.BLUE = 1, c.GREEN = 2, c.CYAN = 3\r
-CONST c.RED = 4, c.PURPLE = 5, c.BROWN = 6, c.WHITE = 7\r
-CONST c.GREY = 8, c.bBLUE = 9, c.bGREEN = 10, c.bCYAN = 11\r
-CONST c.bRED = 12, c.bPURPLE = 13, c.YELLOW = 14, c.bWHITE = 15\r
-CONST c.BRIGHT = 8\r
-\r
- ' From UTILS.ASM\r
-\r
-DECLARE SUB DOS.PRINT ALIAS "DOS_PRINT" (Text$)\r
-DECLARE SUB DOS.PRINTS ALIAS "DOS_PRINTS" (Text$)\r
-DECLARE SUB SET.VIDEO.MODE ALIAS "SET_VIDEO_MODE" (BYVAL Mode%)\r
-DECLARE FUNCTION SCAN.KEYBOARD% ALIAS "SCAN_KEYBOARD"\r
-DECLARE FUNCTION RANDOM.INT ALIAS "RANDOM_INT" (BYVAL MaxInt%)\r
-DECLARE SUB INIT.RANDOM ALIAS "INIT_RANDOM"\r
-DECLARE FUNCTION TIMER.COUNT& ALIAS "TIMER_COUNT"\r
-DECLARE FUNCTION INT.SQR ALIAS "INT_SQR" (BYVAL X%, BYVAL Round%)\r
-\r
+++ /dev/null
-;=======================================================\r
-;=== C_UTILS.ASM - Asm Utilities for C/C++ ===\r
-;=======================================================\r
-\r
- PAGE 255, 132\r
-\r
- .MODEL Medium\r
- .286\r
-\r
- ; ==== MACROS ====\r
-\r
- ; macros to PUSH and POP multiple registers\r
-\r
-PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
- IFNB <R1>\r
- push R1 ; Save R1\r
- PUSHx R2, R3, R4, R5, R6, R7, R8\r
- ENDIF\r
-ENDM\r
-\r
-POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
- IFNB <R1>\r
- pop R1 ; Restore R1\r
- POPx R2, R3, R4, R5, R6, R7, R8\r
- ENDIF\r
-ENDM\r
-\r
- ; Macro to Clear a Register to 0\r
-\r
-CLR MACRO Register\r
- xor Register, Register ; Set Register = 0\r
-ENDM\r
-\r
- ; Macros to Decrement Counter & Jump on Condition\r
-\r
-LOOPx MACRO Register, Destination\r
- dec Register ; Counter--\r
- jnz Destination ; Jump if not 0\r
-ENDM\r
-\r
-LOOPjz MACRO Register, Destination\r
- dec Register ; Counter--\r
- jz Destination ; Jump if 0\r
-ENDM\r
-\r
-\r
- ; ==== General Constants ====\r
-\r
- False EQU 0\r
- True EQU -1\r
- nil EQU 0\r
-\r
- b EQU BYTE PTR\r
- w EQU WORD PTR\r
- d EQU DWORD PTR\r
- o EQU OFFSET\r
- f EQU FAR PTR\r
- s EQU SHORT\r
- ?x4 EQU <?,?,?,?>\r
- ?x3 EQU <?,?,?>\r
-\r
-\r
- .Data\r
-\r
- EVEN\r
-\r
-RND_Seed DW 7397, 29447, 802\r
-RND_Mult DW 179, 183, 182\r
-RND_ModV DW 32771, 32779, 32783\r
-\r
-CR_LF DB 13, 10 ; the CRLF data\r
-\r
- .Code\r
-\r
-;===========================================\r
-;void far pascal dos_print (far char *Text)\r
-;===========================================\r
-;\r
-; - Print Text Directly to DOS console w/ CR/LF\r
-;\r
-\r
- PUBLIC DOS_PRINT\r
-\r
-DP_Stack STRUC\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- DP_Text DD ? ; Far Address of Text to print\r
-DP_Stack ENDS\r
-\r
-\r
-DOS_PRINT PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor\r
-\r
- ; Compute Length of string\r
-\r
- CLR CX ; Length = 0\r
- mov SI, DX ; DS:SI = String data\r
-\r
-@@DP_Scan_it:\r
- \r
- cmp b [SI], 0 ; Null Byte found?\r
- je @@DP_Got_Len ; exit loop if so\r
-\r
- inc CX ; Len++\r
- inc SI ; Point to next char\r
- jmp s @@DP_Scan_it ; check again...\r
-\r
-@@DP_Got_len:\r
-\r
- jcxz @No_Print ; Don't Print if empty\r
-\r
- mov BX, 1 ; 1= DOS Handle for Display\r
- mov AH, 40h ; Write Text Function\r
- int 21h ; Call DOS to do it\r
-\r
-@No_Print:\r
- mov AX, SEG DGROUP ; Restore DGroup\r
- mov DS, AX\r
-\r
- mov DX, o CR_LF ; Get Addr of CR/LF pair\r
- mov CX, 2 ; 2 Characters to Write \r
- mov BX, 1 ; 1= DOS Handle for Display\r
-\r
- mov AH, 40h ; Write Text Function\r
- int 21h ; Call DOS to do it\r
-\r
- cld ; Reset Direction Flag \r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- ret 4 ; Exit & Clean Up Stack\r
-\r
-DOS_PRINT ENDP\r
-\r
-\r
-;===========================================\r
-;void far pascal dos_prints (char far *Text)\r
-;===========================================\r
-; \r
-; Print Text Directly to DOS console \r
-; without a trailing CR/LF\r
-;\r
-\r
- PUBLIC DOS_PRINTS\r
-\r
-DOS_PRINTS PROC FAR\r
-\r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- lds DX, [BP].DP_Text ; Get Addr of Text$ descriptor\r
-\r
- ; Compute Length of string\r
-\r
- CLR CX ; Length = 0\r
- mov SI, DX ; DS:SI = String data\r
-\r
-@@DPS_Scan_it:\r
- \r
- cmp b [SI], 0 ; Null Byte found?\r
- je @@DPS_Got_Len ; exit loop if so\r
-\r
- inc CX ; Len++\r
- inc SI ; Point to next char\r
- jmp s @@DPS_Scan_it ; check again...\r
-\r
-@@DPS_Got_len:\r
-\r
- jcxz @DPS_Exit ; Don't Print if empty\r
-\r
- mov BX, 1 ; 1= DOS Handle for Display\r
- mov AH, 40h ; Write Text Function\r
- int 21h ; Call DOS to do it\r
-\r
-@DPS_Exit:\r
- cld ; Reset Direction Flag \r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- ret 2 ; Exit & Clean Up Stack\r
-\r
-DOS_PRINTS ENDP\r
-\r
-\r
-;=========================================\r
-;void far pascal set_video_mode (int Mode)\r
-;=========================================\r
-;\r
-; Sets the Video Mode through the BIOS\r
-;\r
-\r
- PUBLIC SET_VIDEO_MODE\r
-\r
-SVM_Stack STRUC\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- SVM_Mode DB ?,? ; Desired Video Mode\r
-SVM_Stack ENDS\r
-\r
-\r
-SET_VIDEO_MODE PROC FAR\r
-\r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- CLR AH ; Function 0\r
- mov AL, [BP].SVM_Mode ; Get Mode #\r
-\r
- int 10H ; Change Video Modes\r
-\r
-@SVM_Exit:\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- ret 2 ; Exit & Clean Up Stack\r
-\r
-SET_VIDEO_MODE ENDP\r
-\r
-\r
-;===================================\r
-;int far pascal scan_keyboard (void)\r
-;===================================\r
-;\r
-; Function to scan keyboard for a pressed key\r
-;\r
-\r
- PUBLIC SCAN_KEYBOARD\r
-\r
-SCAN_KEYBOARD PROC FAR\r
-\r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
-\r
- mov AH, 01H ; Function #1\r
- INT 16H ; Call Keyboard Driver\r
- JZ @SK_NO_KEY ; Exit if Zero flag set\r
-\r
- mov AH, 00H ; Remove Key from Buffer\r
- INT 16H ; Get Keycode in AX\r
-\r
- OR AL, AL ; Low Byte Set (Ascii?)\r
- JZ @SK_Exit ; if not, it's a F-Key\r
-\r
- CLR AH ; Clear ScanCode if Ascii\r
- JMP s @SK_Exit ; Return Key in AX\r
-\r
-@SK_NO_KEY:\r
- CLR AX ; Return Nil (no Keypress)\r
-\r
-@SK_Exit:\r
- cld ; Reset Direction Flag \r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- ret ; Exit & Clean Up Stack\r
-\r
-SCAN_KEYBOARD ENDP\r
-\r
-\r
-;========================================\r
-;int far pascal random_int (int MaxValue)\r
-;========================================\r
-;\r
-; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
-;\r
-\r
-\r
- PUBLIC RANDOM_INT\r
-\r
-RI_Stack STRUC\r
- DW ? ; BP\r
- DD ? ; Caller\r
- RI_MaxVal DW ? ; Maximum Value to Return + 1\r
-RI_Stack ENDS\r
-\r
-\r
-RANDOM_INT PROC FAR\r
-\r
- push BP ; Preserve Important Registers\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- CLR BX ; BX is the data index\r
- CLR CX ; CX is the accumulator\r
-\r
-REPT 3\r
- mov AX, RND_Seed[BX] ; load the initial seed\r
- mul RND_Mult[BX] ; multiply it\r
- div RND_ModV[BX] ; and obtain the Mod value\r
- mov RND_Seed[BX], DX ; save that for the next time\r
-\r
- add CX, DX ; add it into the accumulator\r
- inc BX\r
- inc BX ; point to the next set of values\r
-ENDM\r
-\r
- mov AX, CX ; AX = Random #\r
- CLR DX ; DX = 0\r
- div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder\r
-\r
- mov AX, DX\r
-\r
- pop BP ; Restore BP\r
- ret 2 ; back to BASIC with AX holding the result\r
-\r
-RANDOM_INT ENDP\r
-\r
-\r
-;==================================\r
-;void far pascal init_random (void)\r
-;==================================\r
-;\r
-; Scrambles the psuedo-random number sequence\r
-; (XOR's the seed value with the timer)\r
-;\r
-\r
- PUBLIC INIT_RANDOM\r
-\r
-INIT_RANDOM PROC FAR\r
-\r
- CLR AX ; Segment = 0000\r
- mov ES, AX\r
- mov AX, ES:[046Ch] ; Get Timer Lo Word\r
-\r
- xor RND_Seed, AX ; Scramble 1st Seed\r
-\r
- ret ; Exit & Clean Up Stack\r
-\r
-INIT_RANDOM ENDP\r
-\r
-;=========================================\r
-;int far pascal int_sqr (int X, int Round)\r
-;=========================================\r
-;\r
-; Returns the Integer Square Root of (X)\r
-; Round allows the return value to be rounded to the \r
-; nearest integer value by passing 0x80. Passing 0\r
-; return the Integer Portion only. The rounding amound is\r
-; a number from 0 to 1 multiplied by 256, thus \r
-; 0.5 * 0x100 = 0x80!\r
-;\r
-\r
-ISQ_Stack STRUC\r
- DW ?,? ; BP, DI\r
- DD ? ; Caller\r
- ISQ_Round DW ? ; Amount to Round Result * 256\r
- ISQ_X DW ? ; "X"\r
-ISQ_Stack ENDS\r
-\r
- PUBLIC INT_SQR\r
-\r
-INT_SQR PROC FAR\r
-\r
- PUSHx BP, DI ; Save BP\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- xor AX, AX ; {xor eax,eax}\r
- xor DX, DX ; {xor edx,edx}\r
- mov DI, [BP].ISQ_X ; {mov edi,x}\r
-\r
- mov CX, 16 ; {mov cx, 32}\r
-\r
-@ISQ_L:\r
-\r
- shl DI, 1 ; {shl edi,1}\r
- rcl DX, 1 ; {rcl edx,1}\r
- shl DI, 1 ; {shl edi,1}\r
- rcl DX, 1 ; {rcl edx,1}\r
- shl AX, 1 ; {shl eax,1}\r
- mov BX, AX ; {mov ebx,eax}\r
- shl BX, 1 ; {shl ebx,1}\r
- inc BX ; {inc ebx}\r
- cmp DX, BX ; {cmp edx,ebx}\r
- jl @ISQ_S\r
-\r
- sub DX, BX ; {sub edx,ebx}\r
- inc AX ; {inc eax}\r
-\r
-@ISQ_S: \r
- loop @ISQ_L\r
-\r
- add ax, [BP].ISQ_Round ; {add eax,$00008000} \r
- ; {*round* result in hi word: ie. +0.5}\r
- shr ax, 8 ; {shr eax,16} {to ax (result)}\r
-\r
- POPx DI, BP ; Restore Registers \r
- ret 4 ; Exit\r
-\r
-INT_SQR ENDP\r
-\r
-;=================================\r
-;int far pascal timer_count (void)\r
-;=================================\r
-;\r
-; Returns the current timer value as an integer/long integer\r
-;\r
-\r
- PUBLIC TIMER_COUNT\r
-\r
-TIMER_COUNT PROC FAR\r
-\r
- CLR AX ; Segment = 0000\r
- mov ES, AX\r
- mov AX, ES:[046Ch] ; Get Timer Lo Word\r
- mov DX, ES:[046Eh] ; Get Timer Hi Word\r
- ret ; Exit & Clean Up Stack\r
-\r
-TIMER_COUNT ENDP\r
-\r
-\r
- END\r
+++ /dev/null
-\r
-#ifndef __C_UTILS_H\r
-#define __C_UTILS_H\r
-\r
-\r
- /* Misc Constants */\r
-\r
-#define True -1\r
-#define False 0\r
-#define nil 0\r
-\r
- /* Color Constants */\r
-\r
-#define c_BLACK 0\r
-#define c_BLUE 1\r
-#define c_GREEN 2\r
-#define c_CYAN 3\r
-#define c_RED 4\r
-#define c_PURPLE 5\r
-#define c_BROWN 6\r
-#define c_WHITE 7\r
-#define c_GREY 8\r
-#define c_bBLUE 9\r
-#define c_bGREEN 10\r
-#define c_bCYAN 11\r
-#define c_bRED 12\r
-#define c_bPURPLE 13\r
-#define c_YELLOW 14\r
-#define c_bWHITE 15\r
-#define c_BRIGHT 16\r
-\r
-\r
-#define Ky_F1 0x3B00\r
-#define Ky_F2 0x3C00\r
-#define Ky_F3 0x3D00\r
-#define Ky_F4 0x3E00\r
-#define Ky_F5 0x3F00\r
-#define Ky_F6 0x4000\r
-#define Ky_F7 0x4100\r
-#define Ky_F8 0x4200\r
-#define Ky_F9 0x4300\r
-#define Ky_F10 0x4400\r
-\r
-#define Ky_Up 0x4800\r
-#define Ky_Left 0x4B00\r
-#define Ky_Right 0x4D00\r
-#define Ky_Down 0x5000\r
-#define Ky_SUp 0xC800\r
-#define Ky_SLeft 0xCB00\r
-#define Ky_SRight 0xCD00\r
-#define Ky_SDown 0xD000\r
-\r
-#define Ky_Home 0x4700\r
-#define Ky_End 0x4F00\r
-#define Ky_PgUp 0x4900\r
-#define Ky_PgDn 0x5100\r
-#define Ky_SHome 0xC700\r
-#define Ky_SEnd 0xCF00\r
-#define Ky_SPgUp 0xC900\r
-#define Ky_SPgDn 0xD100\r
-\r
-#define Ky_Ins 0x5200\r
-#define Ky_Del 0x5300\r
-#define Ky_SIns 0xC200\r
-#define Ky_SDel 0xC300\r
-\r
-#define Ky_Tab 0x0009\r
-#define Ky_RvsTab 0x8F00\r
-#define Ky_STab 0x8F00\r
-\r
-#define Ky_BS 0x0008\r
-#define Ky_CR 0x000D\r
-#define Ky_ESC 0x001B\r
-#define Ky_Clr 0x007F\r
-\r
-#define Ky_Plus 0x002D\r
-#define Ky_Minus 0x002B\r
-\r
-#define Ky_AltA 0x1E00\r
-#define Ky_AltB 0x3000\r
-#define Ky_AltC 0x2E00\r
-#define Ky_AltD 0x2000\r
-#define Ky_AltE 0x1200\r
-#define Ky_AltF 0x2100\r
-#define Ky_AltG 0x2200\r
-#define Ky_AltH 0x2300\r
-#define Ky_AltI 0x1700\r
-#define Ky_AltJ 0x2400\r
-#define Ky_AltK 0x2500\r
-#define Ky_AltL 0x2600\r
-#define Ky_AltM 0x3200\r
-#define Ky_AltN 0x3100\r
-#define Ky_AltO 0x1800\r
-#define Ky_AltP 0x1900\r
-#define Ky_AltQ 0x1000\r
-#define Ky_AltR 0x1300\r
-#define Ky_AltS 0x1F00\r
-#define Ky_AltT 0x1400\r
-#define Ky_AltU 0x1600\r
-#define Ky_AltV 0x2F00\r
-#define Ky_AltW 0x1100\r
-#define Ky_AltX 0x2D00\r
-#define Ky_AltY 0x1500\r
-#define Ky_AltZ 0x2C00\r
-\r
- /* .ASM Functions From C_UTILS.ASM */\r
-\r
-void far pascal dos_print (char far *Text);\r
-void far pascal dos_prints (char far *Text);\r
-void far pascal set_video_mode (int Mode);\r
-int far pascal scan_keyboard (void);\r
-int far pascal random_int (int MaxValue);\r
-void far pascal init_random (void);\r
-int far pascal int_sqr (int X, int Round);\r
-int far pascal timer_count (void);\r
-\r
-#endif\r
-\r
+++ /dev/null
-;========================================================\r
-; MODEX.ASM - A Complete Mode X Library\r
-;\r
-; Version 1.04 Release, 3 May 1993, By Matt Pritchard\r
-; With considerable input from Michael Abrash\r
-;\r
-; The following information is donated to the public domain in\r
-; the hopes that save other programmers much frustration.\r
-;\r
-; If you do use this code in a product, it would be nice if\r
-; you include a line like "Mode X routines by Matt Pritchard"\r
-; in the credits.\r
-;\r
-; =========================================================\r
-;\r
-; All of this code is designed to be assembled with MASM 5.10a\r
-; but TASM 3.0 could be used as well.\r
-;\r
-; The routines contained are designed for use in a MEDIUM model\r
-; program. All Routines are FAR, and is assumed that a DGROUP\r
-; data segment exists and that DS will point to it on entry.\r
-;\r
-; For all routines, the AX, BX, CX, DX, ES and FLAGS registers\r
-; will not be preserved, while the DS, BP, SI and DI registers\r
-; will be preserved.\r
-;\r
-; Unless specifically noted, All Parameters are assumed to be\r
-; "PASSED BY VALUE". That is, the actual value is placed on\r
-; the stack. When a reference is passed it is assumed to be\r
-; a near pointer to a variable in the DGROUP segment.\r
-;\r
-; Routines that return a single 16-Bit integer value will\r
-; return that value in the AX register.\r
-;\r
-; This code will *NOT* run on an 8086/8088 because 80286+\r
-; specific instructions are used. If you have an 8088/86\r
-; and VGA, you can buy an 80386-40 motherboard for about\r
-; $160 and move into the 90's.\r
-;\r
-; This code is reasonably optimized: Most drawing loops have\r
-; been unrolled once and memory references are minimized by\r
-; keeping stuff in registers when possible.\r
-;\r
-; Error Trapping varies by Routine. No Clipping is performed\r
-; so the caller should verify that all coordinates are valid.\r
-;\r
-; Several Macros are used to simplify common 2 or 3 instruction\r
-; sequences. Several Single letter Text Constants also\r
-; simplify common assembler expressions like "WORD PTR".\r
-;\r
-; ------------------ Mode X Variations ------------------\r
-;\r
-; Mode # Screen Size Max Pages Aspect Ratio (X:Y)\r
-;\r
-; 0 320 x 200 4 Pages 1.2:1\r
-; 1 320 x 400 2 Pages 2.4:1\r
-; 2 360 x 200 3 Pages 1.35:1\r
-; 3 360 x 400 1 Page 2.7:1\r
-; 4 320 x 240 3 Pages 1:1\r
-; 5 320 x 480 1 Page 2:1\r
-; 6 360 x 240 3 Pages 1.125:1\r
-; 7 360 x 480 1 Page 2.25:1\r
-;\r
-; -------------------- The Legal Stuff ------------------\r
-;\r
-; No warranty, either written or implied, is made as to\r
-; the accuracy and usability of this code product. Use\r
-; at your own risk. Batteries not included. Pepperoni\r
-; and extra cheese available for an additional charge.\r
-;\r
-; ----------------------- The Author --------------------\r
-;\r
-; Matt Pritchard is a paid programmer who'd rather be\r
-; writing games. He can be reached at: P.O. Box 140264,\r
-; Irving, TX 75014 USA. Michael Abrash is a living\r
-; god, who now works for Bill Gates (Microsoft).\r
-;\r
-; -------------------- Revision History -----------------\r
-; 4-12-93: v1.02 - SET_POINT & READ_POINT now saves DI\r
-; SET_MODEX now saves SI\r
-; 5-3-93: v1.04 - added LOAD_DAC_REGISTERS and\r
-; READ_DAC_REGISTERS. Expanded CLR Macro\r
-; to handle multiple registers\r
-;\r
- \r
- PAGE 255, 132\r
- \r
- .MODEL Medium\r
- .286\r
- \r
- ; ===== MACROS =====\r
- \r
- ; Macro to OUT a 16 bit value to an I/O port\r
- \r
-OUT_16 MACRO Register, Value\r
- IFDIFI <Register>, <DX> ; If DX not setup\r
- MOV DX, Register ; then Select Register\r
- ENDIF\r
- IFDIFI <Value>, <AX> ; If AX not setup\r
- MOV AX, Value ; then Get Data Value\r
- ENDIF\r
- OUT DX, AX ; Set I/O Register(s)\r
-ENDM\r
- \r
- ; Macro to OUT a 8 bit value to an I/O Port\r
- \r
-OUT_8 MACRO Register, Value\r
- IFDIFI <Register>, <DX> ; If DX not setup\r
- MOV DX, Register ; then Select Register\r
- ENDIF\r
- IFDIFI <Value>, <AL> ; If AL not Setup\r
- MOV AL, Value ; then Get Data Value\r
- ENDIF\r
- OUT DX, AL ; Set I/O Register\r
-ENDM\r
- \r
- ; macros to PUSH and POP multiple registers\r
- \r
-PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
- IFNB <R1>\r
- PUSH R1 ; Save R1\r
- PUSHx R2, R3, R4, R5, R6, R7, R8\r
- ENDIF\r
-ENDM\r
- \r
-POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
- IFNB <R1>\r
- POP R1 ; Restore R1\r
- POPx R2, R3, R4, R5, R6, R7, R8\r
- ENDIF\r
-ENDM\r
- \r
- ; Macro to Clear Registers to 0\r
- \r
-CLR MACRO Register, R2, R3, R4, R5, R6\r
- IFNB <Register>\r
- XOR Register, Register ; Set Register = 0\r
- CLR R2, R3, R4, R5, R6\r
- ENDIF\r
-ENDM\r
- \r
- ; Macros to Decrement Counter & Jump on Condition\r
- \r
-LOOPx MACRO Register, Destination\r
- DEC Register ; Counter--\r
- JNZ Destination ; Jump if not 0\r
-ENDM\r
- \r
-LOOPjz MACRO Register, Destination\r
- DEC Register ; Counter--\r
- JZ Destination ; Jump if 0\r
-ENDM\r
- \r
- \r
- ; ===== General Constants =====\r
- \r
- False EQU 0\r
- True EQU -1\r
- nil EQU 0\r
- \r
- b EQU BYTE PTR\r
- w EQU WORD PTR\r
- d EQU DWORD PTR\r
- o EQU OFFSET\r
- f EQU FAR PTR\r
- s EQU SHORT\r
- ?x4 EQU <?,?,?,?>\r
- ?x3 EQU <?,?,?>\r
- \r
- ; ===== VGA Register Values =====\r
- \r
- VGA_Segment EQU 0A000h ; Vga Memory Segment\r
- \r
- ATTRIB_Ctrl EQU 03C0h ; VGA Attribute Controller\r
- GC_Index EQU 03CEh ; VGA Graphics Controller\r
- SC_Index EQU 03C4h ; VGA Sequencer Controller\r
- SC_Data EQU 03C5h ; VGA Sequencer Data Port\r
- CRTC_Index EQU 03D4h ; VGA CRT Controller\r
- CRTC_Data EQU 03D5h ; VGA CRT Controller Data\r
- MISC_OUTPUT EQU 03C2h ; VGA Misc Register\r
- INPUT_1 EQU 03DAh ; Input Status #1 Register\r
- \r
- DAC_WRITE_ADDR EQU 03C8h ; VGA DAC Write Addr Register\r
- DAC_READ_ADDR EQU 03C7h ; VGA DAC Read Addr Register\r
- PEL_DATA_REG EQU 03C9h ; VGA DAC/PEL data Register R/W\r
- \r
- PIXEL_PAN_REG EQU 033h ; Attrib Index: Pixel Pan Reg\r
- MAP_MASK EQU 002h ; Sequ Index: Write Map Mask reg\r
- READ_MAP EQU 004h ; GC Index: Read Map Register\r
- START_DISP_HI EQU 00Ch ; CRTC Index: Display Start Hi\r
- START_DISP_LO EQU 00Dh ; CRTC Index: Display Start Lo\r
- \r
- MAP_MASK_PLANE1 EQU 00102h ; Map Register + Plane 1\r
- MAP_MASK_PLANE2 EQU 01102h ; Map Register + Plane 1\r
- ALL_PLANES_ON EQU 00F02h ; Map Register + All Bit Planes\r
- \r
- CHAIN4_OFF EQU 00604h ; Chain 4 mode Off\r
- ASYNC_RESET EQU 00100h ; (A)synchronous Reset\r
- SEQU_RESTART EQU 00300h ; Sequencer Restart\r
- \r
- LATCHES_ON EQU 00008h ; Bit Mask + Data from Latches\r
- LATCHES_OFF EQU 0FF08h ; Bit Mask + Data from CPU\r
- \r
- VERT_RETRACE EQU 08h ; INPUT_1: Vertical Retrace Bit\r
- PLANE_BITS EQU 03h ; Bits 0-1 of Xpos = Plane #\r
- ALL_PLANES EQU 0Fh ; All Bit Planes Selected\r
- CHAR_BITS EQU 0Fh ; Bits 0-3 of Character Data\r
- \r
- GET_CHAR_PTR EQU 01130h ; VGA BIOS Func: Get Char Set\r
- ROM_8x8_Lo EQU 03h ; ROM 8x8 Char Set Lo Pointer\r
- ROM_8x8_Hi EQU 04h ; ROM 8x8 Char Set Hi Pointer\r
- \r
- ; Constants Specific for these routines\r
- \r
- NUM_MODES EQU 8 ; # of Mode X Variations\r
- \r
- ; Specific Mode Data Table format...\r
- \r
-Mode_Data_Table STRUC\r
- M_MiscR DB ? ; Value of MISC_OUTPUT register\r
- M_Pages DB ? ; Maximum Possible # of pages\r
- M_XSize DW ? ; X Size Displayed on screen\r
- M_YSize DW ? ; Y Size Displayed on screen\r
- M_XMax DW ? ; Maximum Possible X Size\r
- M_YMax DW ? ; Maximum Possible Y Size\r
- M_CRTC DW ? ; Table of CRTC register values\r
-Mode_Data_Table ENDS\r
- \r
- ; ===== DGROUP STORAGE NEEDED (42 BYTES) =====\r
- \r
- .DATA?\r
- \r
-SCREEN_WIDTH DW 0 ; Width of a line in Bytes\r
-SCREEN_HEIGHT DW 0 ; Vertical Height in Pixels\r
- \r
-LAST_PAGE DW 0 ; # of Display Pages\r
-PAGE_ADDR DW 4 DUP (0) ; Offsets to start of each page\r
- \r
-PAGE_SIZE DW 0 ; Size of Page in Addr Bytes\r
- \r
-DISPLAY_PAGE DW 0 ; Page # currently displayed\r
-ACTIVE_PAGE DW 0 ; Page # currently active\r
- \r
-CURRENT_PAGE DW 0 ; Offset of current Page\r
-CURRENT_SEGMENT DW 0 ; Segment of VGA memory\r
- \r
-CURRENT_XOFFSET DW 0 ; Current Display X Offset\r
-CURRENT_YOFFSET DW 0 ; Current Display Y Offset\r
- \r
-CURRENT_MOFFSET DW 0 ; Current Start Offset\r
- \r
-MAX_XOFFSET DW 0 ; Current Display X Offset\r
-MAX_YOFFSET DW 0 ; Current Display Y Offset\r
- \r
-CHARSET_LOW DW 0, 0 ; Far Ptr to Char Set: 0-127\r
-CHARSET_HI DW 0, 0 ; Far Ptr to Char Set: 128-255\r
- \r
- .CODE\r
- \r
- ; ===== DATA TABLES =====\r
- \r
- ; Data Tables, Put in Code Segment for Easy Access\r
- ; (Like when all the other Segment Registers are in\r
- ; use!!) and reduced DGROUP requirements...\r
- \r
- ; Bit Mask Tables for Left/Right/Character Masks\r
- \r
-Left_Clip_Mask DB 0FH, 0EH, 0CH, 08H\r
- \r
-Right_Clip_Mask DB 01H, 03H, 07H, 0FH\r
- \r
- ; Bit Patterns for converting character fonts\r
- \r
-Char_Plane_Data DB 00H,08H,04H,0CH,02H,0AH,06H,0EH\r
- DB 01H,09H,05H,0DH,03H,0BH,07H,0FH\r
- \r
- ; CRTC Register Values for Various Configurations\r
- \r
-MODE_Single_Line: ; CRTC Setup Data for 400/480 Line modes\r
- DW 04009H ; Cell Height (1 Scan Line)\r
- DW 00014H ; Dword Mode off\r
- DW 0E317H ; turn on Byte Mode\r
- DW nil ; End of CRTC Data for 400/480 Line Mode\r
- \r
-MODE_Double_Line: ; CRTC Setup Data for 200/240 Line modes\r
- DW 04109H ; Cell Height (2 Scan Lines)\r
- DW 00014H ; Dword Mode off\r
- DW 0E317H ; turn on Byte Mode\r
- DW nil ; End of CRTC Data for 200/240 Line Mode\r
- \r
-MODE_320_Wide: ; CRTC Setup Data for 320 Horz Pixels\r
- DW 05F00H ; Horz total\r
- DW 04F01H ; Horz Displayed\r
- DW 05002H ; Start Horz Blanking\r
- DW 08203H ; End Horz Blanking\r
- DW 05404H ; Start H Sync\r
- DW 08005H ; End H Sync\r
- DW nil ; End of CRTC Data for 320 Horz pixels\r
- \r
-MODE_360_Wide: ; CRTC Setup Data for 360 Horz Pixels\r
- DW 06B00H ; Horz total\r
- DW 05901H ; Horz Displayed\r
- DW 05A02H ; Start Horz Blanking\r
- DW 08E03H ; End Horz Blanking\r
- DW 05E04H ; Start H Sync\r
- DW 08A05H ; End H Sync\r
- DW nil ; End of CRTC Data for 360 Horz pixels\r
- \r
-MODE_200_Tall:\r
-MODE_400_Tall: ; CRTC Setup Data for 200/400 Line modes\r
- DW 0BF06H ; Vertical Total\r
- DW 01F07H ; Overflow\r
- DW 09C10H ; V Sync Start\r
- DW 08E11H ; V Sync End/Prot Cr0 Cr7\r
- DW 08F12H ; Vertical Displayed\r
- DW 09615H ; V Blank Start\r
- DW 0B916H ; V Blank End\r
- DW nil ; End of CRTC Data for 200/400 Lines\r
- \r
-MODE_240_Tall:\r
-MODE_480_Tall: ; CRTC Setup Data for 240/480 Line modes\r
- DW 00D06H ; Vertical Total\r
- DW 03E07H ; Overflow\r
- DW 0EA10H ; V Sync Start\r
- DW 08C11H ; V Sync End/Prot Cr0 Cr7\r
- DW 0DF12H ; Vertical Displayed\r
- DW 0E715H ; V Blank Start\r
- DW 00616H ; V Blank End\r
- DW nil ; End of CRTC Data for 240/480 Lines\r
- \r
- ; Table of Display Mode Tables\r
- \r
-MODE_TABLE:\r
- DW o MODE_320x200, o MODE_320x400\r
- DW o MODE_360x200, o MODE_360x400\r
- DW o MODE_320x240, o MODE_320x480\r
- DW o MODE_360x240, o MODE_360x480\r
- \r
- ; Table of Display Mode Components\r
- \r
-MODE_320x200: ; Data for 320 by 200 Pixels\r
- \r
- DB 063h ; 400 scan Lines & 25 Mhz Clock\r
- DB 4 ; Maximum of 4 Pages\r
- DW 320, 200 ; Displayed Pixels (X,Y)\r
- DW 1302, 816 ; Max Possible X and Y Sizes\r
- \r
- DW o MODE_320_Wide, o MODE_200_Tall\r
- DW o MODE_Double_Line, nil\r
- \r
-MODE_320x400: ; Data for 320 by 400 Pixels\r
- \r
- DB 063h ; 400 scan Lines & 25 Mhz Clock\r
- DB 2 ; Maximum of 2 Pages\r
- DW 320, 400 ; Displayed Pixels X,Y\r
- DW 648, 816 ; Max Possible X and Y Sizes\r
- \r
- DW o MODE_320_Wide, o MODE_400_Tall\r
- DW o MODE_Single_Line, nil\r
- \r
-MODE_360x240: ; Data for 360 by 240 Pixels\r
- \r
- DB 0E7h ; 480 scan Lines & 28 Mhz Clock\r
- DB 3 ; Maximum of 3 Pages\r
- DW 360, 240 ; Displayed Pixels X,Y\r
- DW 1092, 728 ; Max Possible X and Y Sizes\r
- \r
- DW o MODE_360_Wide, o MODE_240_Tall\r
- DW o MODE_Double_Line , nil\r
- \r
-MODE_360x480: ; Data for 360 by 480 Pixels\r
- \r
- DB 0E7h ; 480 scan Lines & 28 Mhz Clock\r
- DB 1 ; Only 1 Page Possible\r
- DW 360, 480 ; Displayed Pixels X,Y\r
- DW 544, 728 ; Max Possible X and Y Sizes\r
- \r
- DW o MODE_360_Wide, o MODE_480_Tall\r
- DW o MODE_Single_Line , nil\r
- \r
-MODE_320x240: ; Data for 320 by 240 Pixels\r
- \r
- DB 0E3h ; 480 scan Lines & 25 Mhz Clock\r
- DB 3 ; Maximum of 3 Pages\r
- DW 320, 240 ; Displayed Pixels X,Y\r
- DW 1088, 818 ; Max Possible X and Y Sizes\r
- \r
- DW o MODE_320_Wide, o MODE_240_Tall\r
- DW o MODE_Double_Line, nil\r
- \r
-MODE_320x480: ; Data for 320 by 480 Pixels\r
- \r
- DB 0E3h ; 480 scan Lines & 25 Mhz Clock\r
- DB 1 ; Only 1 Page Possible\r
- DW 320, 480 ; Displayed Pixels X,Y\r
- DW 540, 818 ; Max Possible X and Y Sizes\r
- \r
- DW o MODE_320_WIDE, o MODE_480_Tall\r
- DW o MODE_Single_Line, nil\r
- \r
-MODE_360x200: ; Data for 360 by 200 Pixels\r
- \r
- DB 067h ; 400 scan Lines & 28 Mhz Clock\r
- DB 3 ; Maximum of 3 Pages\r
- DW 360, 200 ; Displayed Pixels (X,Y)\r
- DW 1302, 728 ; Max Possible X and Y Sizes\r
- \r
- DW o MODE_360_Wide, MODE_200_Tall\r
- DW o MODE_Double_Line, nil\r
- \r
-MODE_360x400: ; Data for 360 by 400 Pixels\r
- \r
- DB 067h ; 400 scan Lines & 28 Mhz Clock\r
- DB 1 ; Maximum of 1 Pages\r
- DW 360, 400 ; Displayed Pixels X,Y\r
- DW 648, 816 ; Max Possible X and Y Sizes\r
- \r
- DW o MODE_360_Wide, MODE_400_Tall\r
- DW o MODE_Single_Line, nil\r
- \r
- \r
- ; ===== MODE X SETUP ROUTINES =====\r
- \r
-;======================================================\r
-;SET_VGA_MODEX% (ModeType%, MaxXPos%, MaxYpos%, Pages%)\r
-;======================================================\r
-;\r
-; Sets Up the specified version of Mode X. Allows for\r
-; the setup of multiple video pages, and a virtual\r
-; screen which can be larger than the displayed screen\r
-; (which can then be scrolled a pixel at a time)\r
-;\r
-; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
-;\r
-; 0 = 320 x 200, 4 Pages max, 1.2:1 Aspect Ratio\r
-; 1 = 320 x 400, 2 Pages max, 2.4:1 Aspect Ratio\r
-; 2 = 360 x 200, 3 Pages max, 1.35:1 Aspect Ratio\r
-; 3 = 360 x 400, 1 Page max, 2.7:1 Aspect Ratio\r
-; 4 = 320 x 240, 3 Pages max, 1:1 Aspect Ratio\r
-; 5 = 320 x 480, 1 Page max, 2:1 Aspect Ratio\r
-; 6 = 360 x 240, 3 Pages max, 1.125:1 Aspect Ratio\r
-; 7 = 360 x 480, 1 Page max, 2.25:1 Aspect Ratio\r
-;\r
-; MaxXpos = The Desired Virtual Screen Width\r
-; MaxYpos = The Desired Virtual Screen Height\r
-; Pages = The Desired # of Video Pages\r
-;\r
-; EXIT: AX = Success Flag: 0 = Failure / -1= Success\r
-;\r
- \r
-SVM_STACK STRUC\r
- SVM_Table DW ? ; Offset of Mode Info Table\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- SVM_Pages DW ? ; # of Screen Pages desired\r
- SVM_Ysize DW ? ; Vertical Screen Size Desired\r
- SVM_Xsize DW ? ; Horizontal Screen Size Desired\r
- SVM_Mode DW ? ; Display Resolution Desired\r
-SVM_STACK ENDS\r
- \r
- PUBLIC SET_VGA_MODEX\r
- \r
-SET_VGA_MODEX PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- SUB SP, 2 ; Allocate workspace\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- ; Check Legality of Mode Request....\r
- \r
- MOV BX, [BP].SVM_Mode ; Get Requested Mode #\r
- CMP BX, NUM_MODES ; Is it 0..7?\r
- JAE @SVM_BadModeSetup ; If Not, Error out\r
- \r
- SHL BX, 1 ; Scale BX\r
- MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info\r
- MOV [BP].SVM_Table, SI ; Save ptr for later use\r
- \r
- ; Check # of Requested Display Pages\r
- \r
- MOV CX, [BP].SVM_Pages ; Get # of Requested Pages\r
- CLR CH ; Set Hi Word = 0!\r
- CMP CL, CS:[SI].M_Pages ; Check # Pages for mode\r
- JA @SVM_BadModeSetup ; Report Error if too Many Pages\r
- JCXZ @SVM_BadModeSetup ; Report Error if 0 Pages\r
- \r
- ; Check Validity of X Size\r
- \r
- AND [BP].SVM_XSize, 0FFF8h ; X size Mod 8 Must = 0\r
- \r
- MOV AX, [BP].SVM_XSize ; Get Logical Screen Width\r
- CMP AX, CS:[SI].M_XSize ; Check against Displayed X\r
- JB @SVM_BadModeSetup ; Report Error if too small\r
- CMP AX, CS:[SI].M_XMax ; Check against Max X\r
- JA @SVM_BadModeSetup ; Report Error if too big\r
- \r
- ; Check Validity of Y Size\r
- \r
- MOV BX, [BP].SVM_YSize ; Get Logical Screen Height\r
- CMP BX, CS:[SI].M_YSize ; Check against Displayed Y\r
- JB @SVM_BadModeSetup ; Report Error if too small\r
- CMP BX, CS:[SI].M_YMax ; Check against Max Y\r
- JA @SVM_BadModeSetup ; Report Error if too big\r
- \r
- ; Enough memory to Fit it all?\r
- \r
- SHR AX, 2 ; # of Bytes:Line = XSize/4\r
- MUL CX ; AX = Bytes/Line * Pages\r
- MUL BX ; DX:AX = Total VGA mem needed\r
- JNO @SVM_Continue ; Exit if Total Size > 256K\r
- \r
- DEC DX ; Was it Exactly 256K???\r
- OR DX, AX ; (DX = 1, AX = 0000)\r
- JZ @SVM_Continue ; if so, it's valid...\r
- \r
-@SVM_BadModeSetup:\r
- \r
- CLR AX ; Return Value = False\r
- JMP @SVM_Exit ; Normal Exit\r
- \r
-@SVM_Continue:\r
- \r
- MOV AX, 13H ; Start with Mode 13H\r
- INT 10H ; Let BIOS Set Mode\r
- \r
- OUT_16 SC_INDEX, CHAIN4_OFF ; Disable Chain 4 Mode\r
- OUT_16 SC_INDEX, ASYNC_RESET ; (A)synchronous Reset\r
- OUT_8 MISC_OUTPUT, CS:[SI].M_MiscR ; Set New Timing/Size\r
- OUT_16 SC_INDEX, SEQU_RESTART ; Restart Sequencer ...\r
- \r
- OUT_8 CRTC_INDEX, 11H ; Select Vert Retrace End Register\r
- INC DX ; Point to Data\r
- IN AL, DX ; Get Value, Bit 7 = Protect\r
- AND AL, 7FH ; Mask out Write Protect\r
- OUT DX, AL ; And send it back\r
- \r
- MOV DX, CRTC_INDEX ; Vga Crtc Registers\r
- ADD SI, M_CRTC ; SI -> CRTC Parameter Data\r
- \r
- ; Load Tables of CRTC Parameters from List of Tables\r
- \r
-@SVM_Setup_Table:\r
- \r
- MOV DI, CS:[SI] ; Get Pointer to CRTC Data Tbl\r
- ADD SI, 2 ; Point to next Ptr Entry\r
- OR DI, DI ; A nil Ptr means that we have\r
- JZ @SVM_Set_Data ; finished CRTC programming\r
- \r
-@SVM_Setup_CRTC:\r
- MOV AX, CS:[DI] ; Get CRTC Data from Table\r
- ADD DI, 2 ; Advance Pointer\r
- OR AX, AX ; At End of Data Table?\r
- JZ @SVM_Setup_Table ; If so, Exit & get next Table\r
- \r
- OUT DX, AX ; Reprogram VGA CRTC reg\r
- JMP s @SVM_Setup_CRTC ; Process Next Table Entry\r
- \r
- ; Initialize Page & Scroll info, DI = 0\r
- \r
-@SVM_Set_Data:\r
- MOV DISPLAY_PAGE, DI ; Display Page = 0\r
- MOV ACTIVE_PAGE, DI ; Active Page = 0\r
- MOV CURRENT_PAGE, DI ; Current Page (Offset) = 0\r
- MOV CURRENT_XOFFSET, DI ; Horz Scroll Index = 0\r
- MOV CURRENT_YOFFSET, DI ; Vert Scroll Index = 0\r
- MOV CURRENT_MOFFSET, DI ; Memory Scroll Index = 0\r
- \r
- MOV AX, VGA_SEGMENT ; Segment for VGA memory\r
- MOV CURRENT_SEGMENT, AX ; Save for Future LES's\r
- \r
- ; Set Logical Screen Width, X Scroll and Our Data\r
- \r
- MOV SI, [BP].SVM_Table ; Get Saved Ptr to Mode Info\r
- MOV AX, [BP].SVM_Xsize ; Get Display Width\r
- \r
- MOV CX, AX ; CX = Logical Width\r
- SUB CX, CS:[SI].M_XSize ; CX = Max X Scroll Value\r
- MOV MAX_XOFFSET, CX ; Set Maximum X Scroll\r
- \r
- SHR AX, 2 ; Bytes = Pixels / 4\r
- MOV SCREEN_WIDTH, AX ; Save Width in Pixels\r
- \r
- SHR AX, 1 ; Offset Value = Bytes / 2\r
- MOV AH, 13h ; CRTC Offset Register Index\r
- XCHG AL, AH ; Switch format for OUT\r
- OUT DX, AX ; Set VGA CRTC Offset Reg\r
- \r
- ; Setup Data table, Y Scroll, Misc for Other Routines\r
- \r
- MOV AX, [BP].SVM_Ysize ; Get Logical Screen Height\r
- \r
- MOV CX, AX ; CX = Logical Height\r
- SUB BX, CS:[SI].M_YSize ; CX = Max Y Scroll Value\r
- MOV MAX_YOFFSET, CX ; Set Maximum Y Scroll\r
- \r
- MOV SCREEN_HEIGHT, AX ; Save Height in Pixels\r
- MUL SCREEN_WIDTH ; AX = Page Size in Bytes,\r
- MOV PAGE_SIZE, AX ; Save Page Size\r
- \r
- MOV CX, [BP].SVM_Pages ; Get # of Pages\r
- MOV LAST_PAGE, CX ; Save # of Pages\r
- \r
- CLR BX ; Page # = 0\r
- MOV DX, BX ; Page 0 Offset = 0\r
- \r
-@SVM_Set_Pages:\r
- \r
- MOV PAGE_ADDR[BX], DX ; Set Page #(BX) Offset\r
- ADD BX, 2 ; Page#++\r
- ADD DX, AX ; Compute Addr of Next Page\r
- LOOPx CX, @SVM_Set_Pages ; Loop until all Pages Set\r
- \r
- ; Clear VGA Memory\r
- \r
- OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes\r
- LES DI, d CURRENT_PAGE ; -> Start of VGA memory\r
- \r
- CLR AX ; AX = 0\r
- CLD ; Block Xfer Forwards\r
- MOV CX, 8000H ; 32K * 4 * 2 = 256K\r
- REP STOSW ; Clear dat memory!\r
- \r
- ; Setup Font Pointers\r
- \r
- MOV BH, ROM_8x8_Lo ; Ask for 8x8 Font, 0-127\r
- MOV AX, GET_CHAR_PTR ; Service to Get Pointer\r
- INT 10h ; Call VGA BIOS\r
- \r
- MOV CHARSET_LOW, BP ; Save Char Set Offset\r
- MOV CHARSET_LOW+2, ES ; Save Char Set Segment\r
- \r
- MOV BH, ROM_8x8_Hi ; Ask for 8x8 Font, 128-255\r
- MOV AX, GET_CHAR_PTR ; Service to Get Pointer\r
- INT 10h ; Call VGA BIOS\r
- \r
- MOV CHARSET_HI, BP ; Save Char Set Offset\r
- MOV CHARSET_HI+2, ES ; Save Char Set Segment\r
- \r
- MOV AX, True ; Return Success Code\r
- \r
-@SVM_EXIT:\r
- ADD SP, 2 ; Deallocate workspace\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 8 ; Exit & Clean Up Stack\r
- \r
-SET_VGA_MODEX ENDP\r
- \r
- \r
-;==================\r
-;SET_MODEX% (Mode%)\r
-;==================\r
-;\r
-; Quickie Mode Set - Sets Up Mode X to Default Configuration\r
-;\r
-; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
-; (See SET_VGA_MODEX for list)\r
-;\r
-; EXIT: AX = Success Flag: 0 = Failure / -1= Success\r
-;\r
- \r
-SM_STACK STRUC\r
- DW ?,? ; BP, SI\r
- DD ? ; Caller\r
- SM_Mode DW ? ; Desired Screen Resolution\r
-SM_STACK ENDS\r
- \r
- PUBLIC SET_MODEX\r
- \r
-SET_MODEX PROC FAR\r
- \r
- PUSHx BP, SI ; Preserve Important registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- CLR AX ; Assume Failure\r
- MOV BX, [BP].SM_Mode ; Get Desired Mode #\r
- CMP BX, NUM_MODES ; Is it a Valid Mode #?\r
- JAE @SMX_Exit ; If Not, don't Bother\r
- \r
- PUSH BX ; Push Mode Parameter\r
- \r
- SHL BX, 1 ; Scale BX to word Index\r
- MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info\r
- \r
- PUSH CS:[SI].M_XSize ; Push Default X Size\r
- PUSH CS:[SI].M_Ysize ; Push Default Y size\r
- MOV AL, CS:[SI].M_Pages ; Get Default # of Pages\r
- CLR AH ; Hi Byte = 0\r
- PUSH AX ; Push # Pages\r
- \r
- CALL f SET_VGA_MODEX ; Set up Mode X!\r
- \r
-@SMX_Exit:\r
- POPx SI, BP ; Restore Registers\r
- RET 2 ; Exit & Clean Up Stack\r
- \r
-SET_MODEX ENDP\r
- \r
- \r
- ; ===== BASIC GRAPHICS PRIMITIVES =====\r
- \r
-;============================\r
-;CLEAR_VGA_SCREEN (ColorNum%)\r
-;============================\r
-;\r
-; Clears the active display page\r
-;\r
-; ENTRY: ColorNum = Color Value to fill the page with\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-CVS_STACK STRUC\r
- DW ?,? ; DI, BP\r
- DD ? ; Caller\r
- CVS_COLOR DB ?,? ; Color to Set Screen to\r
-CVS_STACK ENDS\r
- \r
- PUBLIC CLEAR_VGA_SCREEN\r
- \r
-CLEAR_VGA_SCREEN PROC FAR\r
- \r
- PUSHx BP, DI ; Preserve Important Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes\r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- \r
- MOV AL, [BP].CVS_COLOR ; Get Color\r
- MOV AH, AL ; Copy for Word Write\r
- CLD ; Block fill Forwards\r
- \r
- MOV CX, PAGE_SIZE ; Get Size of Page\r
- SHR CX, 1 ; Divide by 2 for Words\r
- REP STOSW ; Block Fill VGA memory\r
- \r
- POPx DI, BP ; Restore Saved Registers\r
- RET 2 ; Exit & Clean Up Stack\r
- \r
-CLEAR_VGA_SCREEN ENDP\r
- \r
- \r
-;===================================\r
-;SET_POINT (Xpos%, Ypos%, ColorNum%)\r
-;===================================\r
-;\r
-; Plots a single Pixel on the active display page\r
-;\r
-; ENTRY: Xpos = X position to plot pixel at\r
-; Ypos = Y position to plot pixel at\r
-; ColorNum = Color to plot pixel with\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-SP_STACK STRUC\r
- DW ?,? ; BP, DI\r
- DD ? ; Caller\r
- SETP_Color DB ?,? ; Color of Point to Plot\r
- SETP_Ypos DW ? ; Y pos of Point to Plot\r
- SETP_Xpos DW ? ; X pos of Point to Plot\r
-SP_STACK ENDS\r
- \r
- PUBLIC SET_POINT\r
- \r
-SET_POINT PROC FAR\r
- \r
- PUSHx BP, DI ; Preserve Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- \r
- MOV AX, [BP].SETP_Ypos ; Get Line # of Pixel\r
- MUL SCREEN_WIDTH ; Get Offset to Start of Line\r
- \r
- MOV BX, [BP].SETP_Xpos ; Get Xpos\r
- MOV CX, BX ; Copy to extract Plane # from\r
- SHR BX, 2 ; X offset (Bytes) = Xpos/4\r
- ADD BX, AX ; Offset = Width*Ypos + Xpos/4\r
- \r
- MOV AX, MAP_MASK_PLANE1 ; Map Mask & Plane Select Register\r
- AND CL, PLANE_BITS ; Get Plane Bits\r
- SHL AH, CL ; Get Plane Select Value\r
- OUT_16 SC_Index, AX ; Select Plane\r
- \r
- MOV AL,[BP].SETP_Color ; Get Pixel Color\r
- MOV ES:[DI+BX], AL ; Draw Pixel\r
- \r
- POPx DI, BP ; Restore Saved Registers\r
- RET 6 ; Exit and Clean up Stack\r
- \r
-SET_POINT ENDP\r
- \r
- \r
-;==========================\r
-;READ_POINT% (Xpos%, Ypos%)\r
-;==========================\r
-;\r
-; Read the color of a pixel from the Active Display Page\r
-;\r
-; ENTRY: Xpos = X position of pixel to read\r
-; Ypos = Y position of pixel to read\r
-;\r
-; EXIT: AX = Color of Pixel at (Xpos, Ypos)\r
-;\r
- \r
-RP_STACK STRUC\r
- DW ?,? ; BP, DI\r
- DD ? ; Caller\r
- RP_Ypos DW ? ; Y pos of Point to Read\r
- RP_Xpos DW ? ; X pos of Point to Read\r
-RP_STACK ENDS\r
- \r
- PUBLIC READ_POINT\r
- \r
-READ_POINT PROC FAR\r
- \r
- PUSHx BP, DI ; Preserve Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- \r
- MOV AX, [BP].RP_Ypos ; Get Line # of Pixel\r
- MUL SCREEN_WIDTH ; Get Offset to Start of Line\r
- \r
- MOV BX, [BP].RP_Xpos ; Get Xpos\r
- MOV CX, BX\r
- SHR BX, 2 ; X offset (Bytes) = Xpos/4\r
- ADD BX, AX ; Offset = Width*Ypos + Xpos/4\r
- \r
- MOV AL, READ_MAP ; GC Read Mask Register\r
- MOV AH, CL ; Get Xpos\r
- AND AH, PLANE_BITS ; & mask out Plane #\r
- OUT_16 GC_INDEX, AX ; Select Plane to read in\r
- \r
- CLR AH ; Clear Return Value Hi byte\r
- MOV AL, ES:[DI+BX] ; Get Color of Pixel\r
- \r
- POPx DI, BP ; Restore Saved Registers\r
- RET 4 ; Exit and Clean up Stack\r
- \r
-READ_POINT ENDP\r
- \r
- \r
-;======================================================\r
-;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
-;======================================================\r
-;\r
-; Fills a rectangular block on the active display Page\r
-;\r
-; ENTRY: Xpos1 = Left X position of area to fill\r
-; Ypos1 = Top Y position of area to fill\r
-; Xpos2 = Right X position of area to fill\r
-; Ypos2 = Bottom Y position of area to fill\r
-; ColorNum = Color to fill area with\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-FB_STACK STRUC\r
- DW ?x4 ; DS, DI, SI, BP\r
- DD ? ; Caller\r
- FB_Color DB ?,? ; Fill Color\r
- FB_Ypos2 DW ? ; Y pos of Lower Right Pixel\r
- FB_Xpos2 DW ? ; X pos of Lower Right Pixel\r
- FB_Ypos1 DW ? ; Y pos of Upper Left Pixel\r
- FB_Xpos1 DW ? ; X pos of Upper Left Pixel\r
-FB_STACK ENDS\r
- \r
- PUBLIC FILL_BLOCK\r
- \r
-FILL_BLOCK PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- CLD ; Direction Flag = Forward\r
- \r
- OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select\r
- \r
- ; Validate Pixel Coordinates\r
- ; If necessary, Swap so X1 <= X2, Y1 <= Y2\r
- \r
- MOV AX, [BP].FB_Ypos1 ; AX = Y1 is Y1< Y2?\r
- MOV BX, [BP].FB_Ypos2 ; BX = Y2\r
- CMP AX, BX\r
- JLE @FB_NOSWAP1\r
- \r
- MOV [BP].FB_Ypos1, BX ; Swap Y1 and Y2 and save Y1\r
- XCHG AX, BX ; on stack for future use\r
- \r
-@FB_NOSWAP1:\r
- SUB BX, AX ; Get Y width\r
- INC BX ; Add 1 to avoid 0 value\r
- MOV [BP].FB_Ypos2, BX ; Save in Ypos2\r
- \r
- MUL SCREEN_WIDTH ; Mul Y1 by Bytes per Line\r
- ADD DI, AX ; DI = Start of Line Y1\r
- \r
- MOV AX, [BP].FB_Xpos1 ; Check X1 <= X2\r
- MOV BX, [BP].FB_Xpos2 ;\r
- CMP AX, BX\r
- JLE @FB_NOSWAP2 ; Skip Ahead if Ok\r
- \r
- MOV [BP].FB_Xpos2, AX ; Swap X1 AND X2 and save X2\r
- XCHG AX, BX ; on stack for future use\r
- \r
- ; All our Input Values are in order, Now determine\r
- ; How many full "bands" 4 pixels wide (aligned) there\r
- ; are, and if there are partial bands (<4 pixels) on\r
- ; the left and right edges.\r
- \r
-@FB_NOSWAP2:\r
- MOV DX, AX ; DX = X1 (Pixel Position)\r
- SHR DX, 2 ; DX/4 = Bytes into Line\r
- ADD DI, DX ; DI = Addr of Upper-Left Corner\r
- \r
- MOV CX, BX ; CX = X2 (Pixel Position)\r
- SHR CX, 2 ; CX/4 = Bytes into Line\r
- \r
- CMP DX, CX ; Start and end in same band?\r
- JNE @FB_NORMAL ; if not, check for l & r edges\r
- JMP @FB_ONE_BAND_ONLY ; if so, then special processing\r
- \r
-@FB_NORMAL:\r
- SUB CX, DX ; CX = # bands -1\r
- MOV SI, AX ; SI = PLANE#(X1)\r
- AND SI, PLANE_BITS ; if Left edge is aligned then\r
- JZ @FB_L_PLANE_FLUSH ; no special processing..\r
- \r
- ; Draw "Left Edge" vertical strip of 1-3 pixels...\r
- \r
- OUT_8 SC_Data, Left_Clip_Mask[SI] ; Set Left Edge Plane Mask\r
- \r
- MOV SI, DI ; SI = Copy of Start Addr (UL)\r
- \r
- MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw\r
- MOV AL, [BP].FB_Color ; Get Fill Color\r
- MOV BX, SCREEN_WIDTH ; Get Vertical increment Value\r
- \r
-@FB_LEFT_LOOP:\r
- MOV ES:[SI], AL ; Fill in Left Edge Pixels\r
- ADD SI, BX ; Point to Next Line (Below)\r
- LOOPjz DX, @FB_LEFT_CONT ; Exit loop if all Lines Drawn\r
- \r
- MOV ES:[SI], AL ; Fill in Left Edge Pixels\r
- ADD SI, BX ; Point to Next Line (Below)\r
- LOOPx DX, @FB_LEFT_LOOP ; loop until left strip is drawn\r
- \r
-@FB_LEFT_CONT:\r
- \r
- INC DI ; Point to Middle (or Right) Block\r
- DEC CX ; Reset CX instead of JMP @FB_RIGHT\r
- \r
-@FB_L_PLANE_FLUSH:\r
- INC CX ; Add in Left band to middle block\r
- \r
- ; DI = Addr of 1st middle Pixel (band) to fill\r
- ; CX = # of Bands to fill -1\r
- \r
-@FB_RIGHT:\r
- MOV SI, [BP].FB_Xpos2 ; Get Xpos2\r
- AND SI, PLANE_BITS ; Get Plane values\r
- CMP SI, 0003 ; Plane = 3?\r
- JE @FB_R_EDGE_FLUSH ; Hey, add to middle\r
- \r
- ; Draw "Right Edge" vertical strip of 1-3 pixels...\r
- \r
- OUT_8 SC_Data, Right_Clip_Mask[SI] ; Right Edge Plane Mask\r
- \r
- MOV SI, DI ; Get Addr of Left Edge\r
- ADD SI, CX ; Add Width-1 (Bands)\r
- DEC SI ; To point to top of Right Edge\r
- \r
- MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw\r
- MOV AL, [BP].FB_Color ; Get Fill Color\r
- MOV BX, SCREEN_WIDTH ; Get Vertical increment Value\r
- \r
-@FB_RIGHT_LOOP:\r
- MOV ES:[SI], AL ; Fill in Right Edge Pixels\r
- ADD SI, BX ; Point to Next Line (Below)\r
- LOOPjz DX, @FB_RIGHT_CONT ; Exit loop if all Lines Drawn\r
- \r
- MOV ES:[SI], AL ; Fill in Right Edge Pixels\r
- ADD SI, BX ; Point to Next Line (Below)\r
- LOOPx DX, @FB_RIGHT_LOOP ; loop until left strip is drawn\r
- \r
-@FB_RIGHT_CONT:\r
- \r
- DEC CX ; Minus 1 for Middle bands\r
- JZ @FB_EXIT ; Uh.. no Middle bands...\r
- \r
-@FB_R_EDGE_FLUSH:\r
- \r
- ; DI = Addr of Upper Left block to fill\r
- ; CX = # of Bands to fill in (width)\r
- \r
- OUT_8 SC_Data, ALL_PLANES ; Write to All Planes\r
- \r
- MOV DX, SCREEN_WIDTH ; DX = DI Increment\r
- SUB DX, CX ; = Screen_Width-# Planes Filled\r
- \r
- MOV BX, CX ; BX = Quick Refill for CX\r
- MOV SI, [BP].FB_Ypos2 ; SI = # of Line to Fill\r
- MOV AL, [BP].FB_Color ; Get Fill Color\r
- \r
-@FB_MIDDLE_LOOP:\r
- REP STOSB ; Fill in entire line\r
- \r
- MOV CX, BX ; Recharge CX (Line Width)\r
- ADD DI, DX ; Point to start of Next Line\r
- LOOPx SI, @FB_MIDDLE_LOOP ; Loop until all lines drawn\r
- \r
- JMP s @FB_EXIT ; Outa here\r
- \r
-@FB_ONE_BAND_ONLY:\r
- MOV SI, AX ; Get Left Clip Mask, Save X1\r
- AND SI, PLANE_BITS ; Mask out Row #\r
- MOV AL, Left_Clip_Mask[SI] ; Get Left Edge Mask\r
- MOV SI, BX ; Get Right Clip Mask, Save X2\r
- AND SI, PLANE_BITS ; Mask out Row #\r
- AND AL, Right_Clip_Mask[SI] ; Get Right Edge Mask byte\r
- \r
- OUT_8 SC_Data, AL ; Clip For Left & Right Masks\r
- \r
- MOV CX, [BP].FB_Ypos2 ; Get # of Lines to draw\r
- MOV AL, [BP].FB_Color ; Get Fill Color\r
- MOV BX, SCREEN_WIDTH ; Get Vertical increment Value\r
- \r
-@FB_ONE_LOOP:\r
- MOV ES:[DI], AL ; Fill in Pixels\r
- ADD DI, BX ; Point to Next Line (Below)\r
- LOOPjz CX, @FB_EXIT ; Exit loop if all Lines Drawn\r
- \r
- MOV ES:[DI], AL ; Fill in Pixels\r
- ADD DI, BX ; Point to Next Line (Below)\r
- LOOPx CX, @FB_ONE_LOOP ; loop until left strip is drawn\r
- \r
-@FB_EXIT:\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 10 ; Exit and Clean up Stack\r
- \r
-FILL_BLOCK ENDP\r
- \r
- \r
-;=====================================================\r
-;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
-;=====================================================\r
-;\r
-; Draws a Line on the active display page\r
-;\r
-; ENTRY: Xpos1 = X position of first point on line\r
-; Ypos1 = Y position of first point on line\r
-; Xpos2 = X position of last point on line\r
-; Ypos2 = Y position of last point on line\r
-; ColorNum = Color to draw line with\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-DL_STACK STRUC\r
- DW ?x3 ; DI, SI, BP\r
- DD ? ; Caller\r
- DL_ColorF DB ?,? ; Line Draw Color\r
- DL_Ypos2 DW ? ; Y pos of last point\r
- DL_Xpos2 DW ? ; X pos of last point\r
- DL_Ypos1 DW ? ; Y pos of first point\r
- DL_Xpos1 DW ? ; X pos of first point\r
-DL_STACK ENDS\r
- \r
- PUBLIC DRAW_LINE\r
- \r
-DRAW_LINE PROC FAR\r
- \r
- PUSHx BP, SI, DI ; Preserve Important Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- CLD ; Direction Flag = Forward\r
- \r
- OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select\r
- MOV CH, [BP].DL_ColorF ; Save Line Color in CH\r
- \r
- ; Check Line Type\r
- \r
- MOV SI, [BP].DL_Xpos1 ; AX = X1 is X1< X2?\r
- MOV DI, [BP].DL_Xpos2 ; DX = X2\r
- CMP SI, DI ; Is X1 < X2\r
- JE @DL_VLINE ; If X1=X2, Draw Vertical Line\r
- JL @DL_NOSWAP1 ; If X1 < X2, don't swap\r
- \r
- XCHG SI, DI ; X2 IS > X1, SO SWAP THEM\r
- \r
-@DL_NOSWAP1:\r
- \r
- ; SI = X1, DI = X2\r
- \r
- MOV AX, [BP].DL_Ypos1 ; AX = Y1 is Y1 <> Y2?\r
- CMP AX, [BP].DL_Ypos2 ; Y1 = Y2?\r
- JE @DL_HORZ ; If so, Draw a Horizontal Line\r
- \r
- JMP @DL_BREZHAM ; Diagonal line... go do it...\r
- \r
- ; This Code draws a Horizontal Line in Mode X where:\r
- ; SI = X1, DI = X2, and AX = Y1/Y2\r
- \r
-@DL_HORZ:\r
- \r
- MUL SCREEN_WIDTH ; Offset = Ypos * Screen_Width\r
- MOV DX, AX ; CX = Line offset into Page\r
- \r
- MOV AX, SI ; Get Left edge, Save X1\r
- AND SI, PLANE_BITS ; Mask out Row #\r
- MOV BL, Left_Clip_Mask[SI] ; Get Left Edge Mask\r
- MOV CX, DI ; Get Right edge, Save X2\r
- AND DI, PLANE_BITS ; Mask out Row #\r
- MOV BH, Right_Clip_Mask[DI] ; Get Right Edge Mask byte\r
- \r
- SHR AX, 2 ; Get X1 Byte # (=X1/4)\r
- SHR CX, 2 ; Get X2 Byte # (=X2/4)\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- ADD DI, DX ; Point to Start of Line\r
- ADD DI, AX ; Point to Pixel X1\r
- \r
- SUB CX, AX ; CX = # Of Bands (-1) to set\r
- JNZ @DL_LONGLN ; jump if longer than one segment\r
- \r
- AND BL, BH ; otherwise, merge clip masks\r
- \r
-@DL_LONGLN:\r
- \r
- OUT_8 SC_Data, BL ; Set the Left Clip Mask\r
- \r
- MOV AL, [BP].DL_ColorF ; Get Line Color\r
- MOV BL, AL ; BL = Copy of Line Color\r
- STOSB ; Set Left (1-4) Pixels\r
- \r
- JCXZ @DL_EXIT ; Done if only one Line Segment\r
- \r
- DEC CX ; CX = # of Middle Segments\r
- JZ @DL_XRSEG ; If no middle segments....\r
- \r
- ; Draw Middle Segments\r
- \r
- OUT_8 DX, ALL_PLANES ; Write to ALL Planes\r
- \r
- MOV AL, BL ; Get Color from BL\r
- REP STOSB ; Draw Middle (4 Pixel) Segments\r
- \r
-@DL_XRSEG:\r
- OUT_8 DX, BH ; Select Planes for Right Clip Mask\r
- MOV AL, BL ; Get Color Value\r
- STOSB ; Draw Right (1-4) Pixels\r
- \r
- JMP s @DL_EXIT ; We Are Done...\r
- \r
- \r
- ; This Code Draws A Vertical Line. On entry:\r
- ; CH = Line Color, SI & DI = X1\r
- \r
-@DL_VLINE:\r
- \r
- MOV AX, [BP].DL_Ypos1 ; AX = Y1\r
- MOV SI, [BP].DL_Ypos2 ; SI = Y2\r
- CMP AX, SI ; Is Y1 < Y2?\r
- JLE @DL_NOSWAP2 ; if so, Don't Swap them\r
- \r
- XCHG AX, SI ; Ok, NOW Y1 < Y2\r
- \r
-@DL_NOSWAP2:\r
- \r
- SUB SI, AX ; SI = Line Height (Y2-Y1+1)\r
- INC SI\r
- \r
- ; AX = Y1, DI = X1, Get offset into Page into AX\r
- \r
- MUL SCREEN_WIDTH ; Offset = Y1 (AX) * Screen Width\r
- MOV DX, DI ; Copy Xpos into DX\r
- SHR DI, 2 ; DI = Xpos/4\r
- ADD AX, DI ; DI = Xpos/4 + ScreenWidth * Y1\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- ADD DI, AX ; Point to Pixel X1, Y1\r
- \r
- ;Select Plane\r
- \r
- MOV CL, DL ; CL = Save X1\r
- AND CL, PLANE_BITS ; Get X1 MOD 4 (Plane #)\r
- MOV AX, MAP_MASK_PLANE1 ; Code to set Plane #1\r
- SHL AH, CL ; Change to Correct Plane #\r
- OUT_16 SC_Index, AX ; Select Plane\r
- \r
- MOV AL, CH ; Get Saved Color\r
- MOV BX, SCREEN_WIDTH ; Get Offset to Advance Line By\r
- \r
-@DL_VLoop:\r
- MOV ES:[DI], AL ; Draw Single Pixel\r
- ADD DI, BX ; Point to Next Line\r
- LOOPjz SI, @DL_EXIT ; Lines--, Exit if done\r
- \r
- MOV ES:[DI], AL ; Draw Single Pixel\r
- ADD DI, BX ; Point to Next Line\r
- LOOPx SI, @DL_VLoop ; Lines--, Loop until Done\r
- \r
-@DL_EXIT:\r
- \r
- JMP @DL_EXIT2 ; Done!\r
- \r
- ; This code Draws a diagonal line in Mode X\r
- \r
-@DL_BREZHAM:\r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- \r
- MOV AX, [BP].DL_Ypos1 ; get Y1 value\r
- MOV BX, [BP].DL_Ypos2 ; get Y2 value\r
- MOV CX, [BP].DL_Xpos1 ; Get Starting Xpos\r
- \r
- CMP BX, AX ; Y2-Y1 is?\r
- JNC @DL_DeltaYOK ; if Y2>=Y1 then goto...\r
- \r
- XCHG BX, AX ; Swap em...\r
- MOV CX, [BP].DL_Xpos2 ; Get New Starting Xpos\r
- \r
-@DL_DeltaYOK:\r
- MUL SCREEN_WIDTH ; Offset = SCREEN_WIDTH * Y1\r
- \r
- ADD DI, AX ; DI -> Start of Line Y1 on Page\r
- MOV AX, CX ; AX = Xpos (X1)\r
- SHR AX, 2 ; /4 = Byte Offset into Line\r
- ADD DI, AX ; DI = Starting pos (X1,Y1)\r
- \r
- MOV AL, 11h ; Staring Mask\r
- AND CL, PLANE_BITS ; Get Plane #\r
- SHL AL, CL ; and shift into place\r
- MOV AH, [BP].DL_ColorF ; Color in Hi Bytes\r
- \r
- PUSH AX ; Save Mask,Color...\r
- \r
- MOV AH, AL ; Plane # in AH\r
- MOV AL, MAP_MASK ; Select Plane Register\r
- OUT_16 SC_Index, AX ; Select initial plane\r
- \r
- MOV AX, [BP].DL_Xpos1 ; get X1 value\r
- MOV BX, [BP].DL_Ypos1 ; get Y1 value\r
- MOV CX, [BP].DL_Xpos2 ; get X2 value\r
- MOV DX, [BP].DL_Ypos2 ; get Y2 value\r
- \r
- MOV BP, SCREEN_WIDTH ; Use BP for Line width to\r
- ; to avoid extra memory access\r
- \r
- SUB DX, BX ; figure Delta_Y\r
- JNC @DL_DeltaYOK2 ; jump if Y2 >= Y1\r
- \r
- ADD BX, DX ; put Y2 into Y1\r
- NEG DX ; abs(Delta_Y)\r
- XCHG AX, CX ; and exchange X1 and X2\r
- \r
-@DL_DeltaYOK2:\r
- MOV BX, 08000H ; seed for fraction accumulator\r
- \r
- SUB CX, AX ; figure Delta_X\r
- JC @DL_DrawLeft ; if negative, go left\r
- \r
- JMP @DL_DrawRight ; Draw Line that slopes right\r
- \r
-@DL_DrawLeft:\r
- \r
- NEG CX ; abs(Delta_X)\r
- \r
- CMP CX, DX ; is Delta_X < Delta_Y?\r
- JB @DL_SteepLeft ; yes, so go do steep line\r
- ; (Delta_Y iterations)\r
- \r
- ; Draw a Shallow line to the left in Mode X\r
- \r
-@DL_ShallowLeft:\r
- CLR AX ; zero low word of Delta_Y * 10000h\r
- SUB AX, DX ; DX:AX <- DX * 0FFFFh\r
- SBB DX, 0 ; include carry\r
- DIV CX ; divide by Delta_X\r
- \r
- MOV SI, BX ; SI = Accumulator\r
- MOV BX, AX ; BX = Add fraction\r
- POP AX ; Get Color, Bit mask\r
- MOV DX, SC_Data ; Sequence controller data register\r
- INC CX ; Inc Delta_X so we can unroll loop\r
- \r
- ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down...\r
- \r
-@DL_SLLLoop:\r
- MOV ES:[DI], AH ; set first pixel, plane data set up\r
- LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done\r
- \r
- ADD SI, BX ; add numerator to accumulator\r
- JNC @DL_SLLL2nc ; move down on carry\r
- \r
- ADD DI, BP ; Move Down one line...\r
- \r
-@DL_SLLL2nc:\r
- DEC DI ; Left one addr\r
- ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
- CMP AL, 87h ; wrap?, if AL <88 then Carry set\r
- ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
- OUT DX, AL ; Set up New Bit Plane mask\r
- \r
- MOV ES:[DI], AH ; set pixel\r
- LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done\r
- \r
- ADD SI, BX ; add numerator to accumulator,\r
- JNC @DL_SLLL3nc ; move down on carry\r
- \r
- ADD DI, BP ; Move Down one line...\r
- \r
-@DL_SLLL3nc: ; Now move left a pixel...\r
- DEC DI ; Left one addr\r
- ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
- CMP AL, 87h ; Wrap?, if AL <88 then Carry set\r
- ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
- OUT DX, AL ; Set up New Bit Plane mask\r
- JMP s @DL_SLLLoop ; loop until done\r
- \r
-@DL_SLLExit:\r
- JMP @DL_EXIT2 ; and exit\r
- \r
- ; Draw a steep line to the left in Mode X\r
- \r
-@DL_SteepLeft:\r
- CLR AX ; zero low word of Delta_Y * 10000h\r
- XCHG DX, CX ; Delta_Y switched with Delta_X\r
- DIV CX ; divide by Delta_Y\r
- \r
- MOV SI, BX ; SI = Accumulator\r
- MOV BX, AX ; BX = Add Fraction\r
- POP AX ; Get Color, Bit mask\r
- MOV DX, SC_Data ; Sequence controller data register\r
- INC CX ; Inc Delta_Y so we can unroll loop\r
- \r
- ; Loop (x2) to Draw Pixels, Move Down, and Maybe left\r
- \r
-@DL_STLLoop:\r
- \r
- MOV ES:[DI], AH ; set first pixel\r
- LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done\r
- \r
- ADD SI, BX ; add numerator to accumulator\r
- JNC @DL_STLnc2 ; No carry, just move down!\r
- \r
- DEC DI ; Move Left one addr\r
- ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
- CMP AL, 87h ; Wrap?, if AL <88 then Carry set\r
- ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
- OUT DX, AL ; Set up New Bit Plane mask\r
- \r
-@DL_STLnc2:\r
- ADD DI, BP ; advance to next line.\r
- \r
- MOV ES:[DI], AH ; set pixel\r
- LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done\r
- \r
- ADD SI, BX ; add numerator to accumulator\r
- JNC @DL_STLnc3 ; No carry, just move down!\r
- \r
- DEC DI ; Move Left one addr\r
- ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
- CMP AL, 87h ; Wrap?, if AL <88 then Carry set\r
- ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
- OUT DX, AL ; Set up New Bit Plane mask\r
- \r
-@DL_STLnc3:\r
- ADD DI, BP ; advance to next line.\r
- JMP s @DL_STLLoop ; Loop until done\r
- \r
-@DL_STLExit:\r
- JMP @DL_EXIT2 ; and exit\r
- \r
- ; Draw a line that goes to the Right...\r
- \r
-@DL_DrawRight:\r
- CMP CX, DX ; is Delta_X < Delta_Y?\r
- JB @DL_SteepRight ; yes, so go do steep line\r
- ; (Delta_Y iterations)\r
- \r
- ; Draw a Shallow line to the Right in Mode X\r
- \r
-@DL_ShallowRight:\r
- CLR AX ; zero low word of Delta_Y * 10000h\r
- SUB AX, DX ; DX:AX <- DX * 0FFFFh\r
- SBB DX, 0 ; include carry\r
- DIV CX ; divide by Delta_X\r
- \r
- MOV SI, BX ; SI = Accumulator\r
- MOV BX, AX ; BX = Add Fraction\r
- POP AX ; Get Color, Bit mask\r
- MOV DX, SC_Data ; Sequence controller data register\r
- INC CX ; Inc Delta_X so we can unroll loop\r
- \r
- ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down...\r
- \r
-@DL_SLRLoop:\r
- MOV ES:[DI], AH ; set first pixel, mask is set up\r
- LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done..\r
- \r
- ADD SI, BX ; add numerator to accumulator\r
- JNC @DL_SLR2nc ; don't move down if carry not set\r
- \r
- ADD DI, BP ; Move Down one line...\r
- \r
-@DL_SLR2nc: ; Now move right a pixel...\r
- ROL AL, 1 ; Move Right one addr if Plane = 0\r
- CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
- ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
- OUT DX, AL ; Set up New Bit Plane mask\r
- \r
- MOV ES:[DI], AH ; set pixel\r
- LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done..\r
- \r
- ADD SI, BX ; add numerator to accumulator\r
- JNC @DL_SLR3nc ; don't move down if carry not set\r
- \r
- ADD DI, BP ; Move Down one line...\r
- \r
-@DL_SLR3nc:\r
- ROL AL, 1 ; Move Right one addr if Plane = 0\r
- CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
- ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
- OUT DX, AL ; Set up New Bit Plane mask\r
- JMP s @DL_SLRLoop ; loop till done\r
- \r
-@DL_SLRExit:\r
- JMP @DL_EXIT2 ; and exit\r
- \r
- ; Draw a Steep line to the Right in Mode X\r
- \r
-@DL_SteepRight:\r
- CLR AX ; zero low word of Delta_Y * 10000h\r
- XCHG DX, CX ; Delta_Y switched with Delta_X\r
- DIV CX ; divide by Delta_Y\r
- \r
- MOV SI, BX ; SI = Accumulator\r
- MOV BX, AX ; BX = Add Fraction\r
- POP AX ; Get Color, Bit mask\r
- MOV DX, SC_Data ; Sequence controller data register\r
- INC CX ; Inc Delta_Y so we can unroll loop\r
- \r
- ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right\r
- \r
-@STRLoop:\r
- MOV ES:[DI], AH ; set first pixel, mask is set up\r
- LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done\r
- \r
- ADD SI, BX ; add numerator to accumulator\r
- JNC @STRnc2 ; if no carry then just go down...\r
- \r
- ROL AL, 1 ; Move Right one addr if Plane = 0\r
- CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
- ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
- OUT DX, AL ; Set up New Bit Plane mask\r
- \r
-@STRnc2:\r
- ADD DI, BP ; advance to next line.\r
- \r
- MOV ES:[DI], AH ; set pixel\r
- LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done\r
- \r
- ADD SI, BX ; add numerator to accumulator\r
- JNC @STRnc3 ; if no carry then just go down...\r
- \r
- ROL AL, 1 ; Move Right one addr if Plane = 0\r
- CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
- ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
- OUT DX, AL ; Set up New Bit Plane mask\r
- \r
-@STRnc3:\r
- ADD DI, BP ; advance to next line.\r
- JMP s @STRLoop ; loop till done\r
- \r
-@DL_EXIT2:\r
- POPx DI, SI, BP ; Restore Saved Registers\r
- RET 10 ; Exit and Clean up Stack\r
- \r
-DRAW_LINE ENDP\r
- \r
- \r
- ; ===== DAC COLOR REGISTER ROUTINES =====\r
- \r
-;=================================================\r
-;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%)\r
-;=================================================\r
-;\r
-; Sets a single (RGB) Vga Palette Register\r
-;\r
-; ENTRY: Register = The DAC # to modify (0-255)\r
-; Red = The new Red Intensity (0-63)\r
-; Green = The new Green Intensity (0-63)\r
-; Blue = The new Blue Intensity (0-63)\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-SDR_STACK STRUC\r
- DW ? ; BP\r
- DD ? ; Caller\r
- SDR_Blue DB ?,? ; Blue Data Value\r
- SDR_Green DB ?,? ; Green Data Value\r
- SDR_Red DB ?,? ; Red Data Value\r
- SDR_Register DB ?,? ; Palette Register #\r
-SDR_STACK ENDS\r
- \r
- PUBLIC SET_DAC_REGISTER\r
- \r
-SET_DAC_REGISTER PROC FAR\r
- \r
- PUSH BP ; Save BP\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- ; Select which DAC Register to modify\r
- \r
- OUT_8 DAC_WRITE_ADDR, [BP].SDR_Register\r
- \r
- MOV DX, PEL_DATA_REG ; Dac Data Register\r
- OUT_8 DX, [BP].SDR_Red ; Set Red Intensity\r
- OUT_8 DX, [BP].SDR_Green ; Set Green Intensity\r
- OUT_8 DX, [BP].SDR_Blue ; Set Blue Intensity\r
- \r
- POP BP ; Restore Registers\r
- RET 8 ; Exit & Clean Up Stack\r
- \r
-SET_DAC_REGISTER ENDP\r
- \r
-;====================================================\r
-;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%)\r
-;====================================================\r
-;\r
-; Reads the RGB Values of a single Vga Palette Register\r
-;\r
-; ENTRY: Register = The DAC # to read (0-255)\r
-; Red = Offset to Red Variable in DS\r
-; Green = Offset to Green Variable in DS\r
-; Blue = Offset to Blue Variable in DS\r
-;\r
-; EXIT: The values of the integer variables Red,\r
-; Green, and Blue are set to the values\r
-; taken from the specified DAC register.\r
-;\r
- \r
-GDR_STACK STRUC\r
- DW ? ; BP\r
- DD ? ; Caller\r
- GDR_Blue DW ? ; Addr of Blue Data Value in DS\r
- GDR_Green DW ? ; Addr of Green Data Value in DS\r
- GDR_Red DW ? ; Addr of Red Data Value in DS\r
- GDR_Register DB ?,? ; Palette Register #\r
-GDR_STACK ENDS\r
- \r
- PUBLIC GET_DAC_REGISTER\r
- \r
-GET_DAC_REGISTER PROC FAR\r
- \r
- PUSH BP ; Save BP\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- ; Select which DAC Register to read in\r
- \r
- OUT_8 DAC_READ_ADDR, [BP].GDR_Register\r
- \r
- MOV DX, PEL_DATA_REG ; Dac Data Register\r
- CLR AX ; Clear AX\r
- \r
- IN AL, DX ; Read Red Value\r
- MOV BX, [BP].GDR_Red ; Get Address of Red%\r
- MOV [BX], AX ; *Red% = AX\r
- \r
- IN AL, DX ; Read Green Value\r
- MOV BX, [BP].GDR_Green ; Get Address of Green%\r
- MOV [BX], AX ; *Green% = AX\r
- \r
- IN AL, DX ; Read Blue Value\r
- MOV BX, [BP].GDR_Blue ; Get Address of Blue%\r
- MOV [BX], AX ; *Blue% = AX\r
- \r
- POP BP ; Restore Registers\r
- RET 8 ; Exit & Clean Up Stack\r
- \r
-GET_DAC_REGISTER ENDP\r
- \r
- \r
-;===========================================================\r
-;LOAD_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%, Sync%)\r
-;===========================================================\r
-;\r
-; Sets a Block of Vga Palette Registers\r
-;\r
-; ENTRY: PalData = Far Pointer to Block of palette data\r
-; StartReg = First Register # in range to set (0-255)\r
-; EndReg = Last Register # in Range to set (0-255)\r
-; Sync = Wait for Vertical Retrace Flag (Boolean)\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
-; NOTES: PalData is a linear array of 3 byte Palette values\r
-; in the order: Red (0-63), Green (0-63), Blue (0-63)\r
-;\r
- \r
-LDR_STACK STRUC\r
- DW ?x3 ; BP, DS, SI\r
- DD ? ; Caller\r
- LDR_Sync DW ? ; Vertical Sync Flag\r
- LDR_EndReg DB ?,? ; Last Register #\r
- LDR_StartReg DB ?,? ; First Register #\r
- LDR_PalData DD ? ; Far Ptr to Palette Data\r
-LDR_STACK ENDS\r
- \r
- PUBLIC LOAD_DAC_REGISTERS\r
- \r
-LOAD_DAC_REGISTERS PROC FAR\r
- \r
- PUSHx BP, DS, SI ; Save Registers\r
- mov BP, SP ; Set up Stack Frame\r
- \r
- mov AX, [BP].LDR_Sync ; Get Vertical Sync Flag\r
- or AX, AX ; is Sync Flag = 0?\r
- jz @LDR_Load ; if so, skip call\r
- \r
- call f SYNC_DISPLAY ; wait for vsync\r
- \r
- ; Determine register #'s, size to copy, etc\r
- \r
-@LDR_Load:\r
- \r
- lds SI, [BP].LDR_PalData ; DS:SI -> Palette Data\r
- mov DX, DAC_WRITE_ADDR ; DAC register # selector\r
- \r
- CLR AX, BX ; Clear for byte loads\r
- mov AL, [BP].LDR_StartReg ; Get Start Register\r
- mov BL, [BP].LDR_EndReg ; Get End Register\r
- \r
- sub BX, AX ; BX = # of DAC registers -1\r
- inc BX ; BX = # of DAC registers\r
- mov CX, BX ; CX = # of DAC registers\r
- add CX, BX ; CX = " " * 2\r
- add CX, BX ; CX = " " * 3\r
- cld ; Block OUTs forward\r
- out DX, AL ; set up correct register #\r
- \r
- ; Load a block of DAC Registers\r
- \r
- mov DX, PEL_DATA_REG ; Dac Data Register\r
- \r
- rep outsb ; block set DAC registers\r
- \r
- POPx SI, DS, BP ; Restore Registers\r
- ret 10 ; Exit & Clean Up Stack\r
- \r
-LOAD_DAC_REGISTERS ENDP\r
- \r
- \r
-;====================================================\r
-;READ_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%)\r
-;====================================================\r
-;\r
-; Reads a Block of Vga Palette Registers\r
-;\r
-; ENTRY: PalData = Far Pointer to block to store palette data\r
-; StartReg = First Register # in range to read (0-255)\r
-; EndReg = Last Register # in Range to read (0-255)\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
-; NOTES: PalData is a linear array of 3 byte Palette values\r
-; in the order: Red (0-63), Green (0-63), Blue (0-63)\r
-;\r
- \r
-RDR_STACK STRUC\r
- DW ?x3 ; BP, ES, DI\r
- DD ? ; Caller\r
- RDR_EndReg DB ?,? ; Last Register #\r
- RDR_StartReg DB ?,? ; First Register #\r
- RDR_PalData DD ? ; Far Ptr to Palette Data\r
-RDR_STACK ENDS\r
- \r
- PUBLIC READ_DAC_REGISTERS\r
- \r
-READ_DAC_REGISTERS PROC FAR\r
- \r
- PUSHx BP, ES, DI ; Save Registers\r
- mov BP, SP ; Set up Stack Frame\r
- \r
- ; Determine register #'s, size to copy, etc\r
- \r
- les DI, [BP].RDR_PalData ; ES:DI -> Palette Buffer\r
- mov DX, DAC_READ_ADDR ; DAC register # selector\r
- \r
- CLR AX, BX ; Clear for byte loads\r
- mov AL, [BP].RDR_StartReg ; Get Start Register\r
- mov BL, [BP].RDR_EndReg ; Get End Register\r
- \r
- sub BX, AX ; BX = # of DAC registers -1\r
- inc BX ; BX = # of DAC registers\r
- mov CX, BX ; CX = # of DAC registers\r
- add CX, BX ; CX = " " * 2\r
- add CX, BX ; CX = " " * 3\r
- cld ; Block INs forward\r
- \r
- ; Read a block of DAC Registers\r
- \r
- out DX, AL ; set up correct register #\r
- mov DX, PEL_DATA_REG ; Dac Data Register\r
- \r
- rep insb ; block read DAC registers\r
- \r
- POPx DI, ES, BP ; Restore Registers\r
- ret 8 ; Exit & Clean Up Stack\r
- \r
-READ_DAC_REGISTERS ENDP\r
- \r
- \r
- ; ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
- \r
-;=========================\r
-;SET_ACTIVE_PAGE (PageNo%)\r
-;=========================\r
-;\r
-; Sets the active display Page to be used for future drawing\r
-;\r
-; ENTRY: PageNo = Display Page to make active\r
-; (values: 0 to Number of Pages - 1)\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-SAP_STACK STRUC\r
- DW ? ; BP\r
- DD ? ; Caller\r
- SAP_Page DW ? ; Page # for Drawing\r
-SAP_STACK ENDS\r
- \r
- PUBLIC SET_ACTIVE_PAGE\r
- \r
-SET_ACTIVE_PAGE PROC FAR\r
- \r
- PUSH BP ; Preserve Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- MOV BX, [BP].SAP_Page ; Get Desired Page #\r
- CMP BX, LAST_PAGE ; Is Page # Valid?\r
- JAE @SAP_Exit ; IF Not, Do Nothing\r
- \r
- MOV ACTIVE_PAGE, BX ; Set Active Page #\r
- \r
- SHL BX, 1 ; Scale Page # to Word\r
- MOV AX, PAGE_ADDR[BX] ; Get offset to Page\r
- \r
- MOV CURRENT_PAGE, AX ; And set for future LES's\r
- \r
-@SAP_Exit:\r
- POP BP ; Restore Registers\r
- RET 2 ; Exit and Clean up Stack\r
- \r
-SET_ACTIVE_PAGE ENDP\r
- \r
- \r
-;================\r
-;GET_ACTIVE_PAGE%\r
-;================\r
-;\r
-; Returns the Video Page # currently used for Drawing\r
-;\r
-; ENTRY: No Parameters are passed\r
-;\r
-; EXIT: AX = Current Video Page used for Drawing\r
-;\r
- \r
- PUBLIC GET_ACTIVE_PAGE\r
- \r
-GET_ACTIVE_PAGE PROC FAR\r
- \r
- MOV AX, ACTIVE_PAGE ; Get Active Page #\r
- RET ; Exit and Clean up Stack\r
- \r
-GET_ACTIVE_PAGE ENDP\r
- \r
- \r
-;===============================\r
-;SET_DISPLAY_PAGE (DisplayPage%)\r
-;===============================\r
-;\r
-; Sets the currently visible display page.\r
-; When called this routine syncronizes the display\r
-; to the vertical blank.\r
-;\r
-; ENTRY: PageNo = Display Page to show on the screen\r
-; (values: 0 to Number of Pages - 1)\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-SDP_STACK STRUC\r
- DW ? ; BP\r
- DD ? ; Caller\r
- SDP_Page DW ? ; Page # to Display...\r
-SDP_STACK ENDS\r
- \r
- PUBLIC SET_DISPLAY_PAGE\r
- \r
-SET_DISPLAY_PAGE PROC FAR\r
- \r
- PUSH BP ; Preserve Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- MOV BX, [BP].SDP_Page ; Get Desired Page #\r
- CMP BX, LAST_PAGE ; Is Page # Valid?\r
- JAE @SDP_Exit ; IF Not, Do Nothing\r
- \r
- MOV DISPLAY_PAGE, BX ; Set Display Page #\r
- \r
- SHL BX, 1 ; Scale Page # to Word\r
- MOV CX, PAGE_ADDR[BX] ; Get offset in memory to Page\r
- ADD CX, CURRENT_MOFFSET ; Adjust for any scrolling\r
- \r
- ; Wait if we are currently in a Vertical Retrace\r
- \r
- MOV DX, INPUT_1 ; Input Status #1 Register\r
- \r
-@DP_WAIT0:\r
- IN AL, DX ; Get VGA status\r
- AND AL, VERT_RETRACE ; In Display mode yet?\r
- JNZ @DP_WAIT0 ; If Not, wait for it\r
- \r
- ; Set the Start Display Address to the new page\r
- \r
- MOV DX, CRTC_Index ; We Change the VGA Sequencer\r
- \r
- MOV AL, START_DISP_LO ; Display Start Low Register\r
- MOV AH, CL ; Low 8 Bits of Start Addr\r
- OUT DX, AX ; Set Display Addr Low\r
- \r
- MOV AL, START_DISP_HI ; Display Start High Register\r
- MOV AH, CH ; High 8 Bits of Start Addr\r
- OUT DX, AX ; Set Display Addr High\r
- \r
- ; Wait for a Vertical Retrace to smooth out things\r
- \r
- MOV DX, INPUT_1 ; Input Status #1 Register\r
- \r
-@DP_WAIT1:\r
- IN AL, DX ; Get VGA status\r
- AND AL, VERT_RETRACE ; Vertical Retrace Start?\r
- JZ @DP_WAIT1 ; If Not, wait for it\r
- \r
- ; Now Set Display Starting Address\r
- \r
- \r
-@SDP_Exit:\r
- POP BP ; Restore Registers\r
- RET 2 ; Exit and Clean up Stack\r
- \r
-SET_DISPLAY_PAGE ENDP\r
- \r
- \r
-;=================\r
-;GET_DISPLAY_PAGE%\r
-;=================\r
-;\r
-; Returns the Video Page # currently displayed\r
-;\r
-; ENTRY: No Parameters are passed\r
-;\r
-; EXIT: AX = Current Video Page being displayed\r
-;\r
- \r
- PUBLIC GET_DISPLAY_PAGE\r
- \r
-GET_DISPLAY_PAGE PROC FAR\r
- \r
- MOV AX, DISPLAY_PAGE ; Get Display Page #\r
- RET ; Exit & Clean Up Stack\r
- \r
-GET_DISPLAY_PAGE ENDP\r
- \r
- \r
-;=======================================\r
-;SET_WINDOW (DisplayPage%, Xpos%, Ypos%)\r
-;=======================================\r
-;\r
-; Since a Logical Screen can be larger than the Physical\r
-; Screen, Scrolling is possible. This routine sets the\r
-; Upper Left Corner of the Screen to the specified Pixel.\r
-; Also Sets the Display page to simplify combined page\r
-; flipping and scrolling. When called this routine\r
-; syncronizes the display to the vertical blank.\r
-;\r
-; ENTRY: DisplayPage = Display Page to show on the screen\r
-; Xpos = # of pixels to shift screen right\r
-; Ypos = # of lines to shift screen down\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-SW_STACK STRUC\r
- DW ? ; BP\r
- DD ? ; Caller\r
- SW_Ypos DW ? ; Y pos of UL Screen Corner\r
- SW_Xpos DW ? ; X pos of UL Screen Corner\r
- SW_Page DW ? ; (new) Display Page\r
-SW_STACK ENDS\r
- \r
- PUBLIC SET_WINDOW\r
- \r
-SET_WINDOW PROC FAR\r
- \r
- PUSH BP ; Preserve Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- ; Check if our Scroll Offsets are Valid\r
- \r
- MOV BX, [BP].SW_Page ; Get Desired Page #\r
- CMP BX, LAST_PAGE ; Is Page # Valid?\r
- JAE @SW_Exit ; IF Not, Do Nothing\r
- \r
- MOV AX, [BP].SW_Ypos ; Get Desired Y Offset\r
- CMP AX, MAX_YOFFSET ; Is it Within Limits?\r
- JA @SW_Exit ; if not, exit\r
- \r
- MOV CX, [BP].SW_Xpos ; Get Desired X Offset\r
- CMP CX, MAX_XOFFSET ; Is it Within Limits?\r
- JA @SW_Exit ; if not, exit\r
- \r
- ; Compute proper Display start address to use\r
- \r
- MUL SCREEN_WIDTH ; AX = YOffset * Line Width\r
- SHR CX, 2 ; CX / 4 = Bytes into Line\r
- ADD AX, CX ; AX = Offset of Upper Left Pixel\r
- \r
- MOV CURRENT_MOFFSET, AX ; Save Offset Info\r
- \r
- MOV DISPLAY_PAGE, BX ; Set Current Page #\r
- SHL BX, 1 ; Scale Page # to Word\r
- ADD AX, PAGE_ADDR[BX] ; Get offset in VGA to Page\r
- MOV BX, AX ; BX = Desired Display Start\r
- \r
- MOV DX, INPUT_1 ; Input Status #1 Register\r
- \r
- ; Wait if we are currently in a Vertical Retrace\r
- \r
-@SW_WAIT0:\r
- IN AL, DX ; Get VGA status\r
- AND AL, VERT_RETRACE ; In Display mode yet?\r
- JNZ @SW_WAIT0 ; If Not, wait for it\r
- \r
- ; Set the Start Display Address to the new window\r
- \r
- MOV DX, CRTC_Index ; We Change the VGA Sequencer\r
- MOV AL, START_DISP_LO ; Display Start Low Register\r
- MOV AH, BL ; Low 8 Bits of Start Addr\r
- OUT DX, AX ; Set Display Addr Low\r
- \r
- MOV AL, START_DISP_HI ; Display Start High Register\r
- MOV AH, BH ; High 8 Bits of Start Addr\r
- OUT DX, AX ; Set Display Addr High\r
- \r
- ; Wait for a Vertical Retrace to smooth out things\r
- \r
- MOV DX, INPUT_1 ; Input Status #1 Register\r
- \r
-@SW_WAIT1:\r
- IN AL, DX ; Get VGA status\r
- AND AL, VERT_RETRACE ; Vertical Retrace Start?\r
- JZ @SW_WAIT1 ; If Not, wait for it\r
- \r
- ; Now Set the Horizontal Pixel Pan values\r
- \r
- OUT_8 ATTRIB_Ctrl, PIXEL_PAN_REG ; Select Pixel Pan Register\r
- \r
- MOV AX, [BP].SW_Xpos ; Get Desired X Offset\r
- AND AL, 03 ; Get # of Pixels to Pan (0-3)\r
- SHL AL, 1 ; Shift for 256 Color Mode\r
- OUT DX, AL ; Fine tune the display!\r
- \r
-@SW_Exit:\r
- POP BP ; Restore Saved Registers\r
- RET 6 ; Exit and Clean up Stack\r
- \r
-SET_WINDOW ENDP\r
- \r
- \r
-;=============\r
-;GET_X_OFFSET%\r
-;=============\r
-;\r
-; Returns the X coordinate of the Pixel currently display\r
-; in the upper left corner of the display\r
-;\r
-; ENTRY: No Parameters are passed\r
-;\r
-; EXIT: AX = Current Horizontal Scroll Offset\r
-;\r
- \r
- PUBLIC GET_X_OFFSET\r
- \r
-GET_X_OFFSET PROC FAR\r
- \r
- MOV AX, CURRENT_XOFFSET ; Get current horz offset\r
- RET ; Exit & Clean Up Stack\r
- \r
-GET_X_OFFSET ENDP\r
- \r
- \r
-;=============\r
-;GET_Y_OFFSET%\r
-;=============\r
-;\r
-; Returns the Y coordinate of the Pixel currently display\r
-; in the upper left corner of the display\r
-;\r
-; ENTRY: No Parameters are passed\r
-;\r
-; EXIT: AX = Current Vertical Scroll Offset\r
-;\r
- \r
- PUBLIC GET_Y_OFFSET\r
- \r
-GET_Y_OFFSET PROC FAR\r
- \r
- MOV AX, CURRENT_YOFFSET ; Get current vertical offset\r
- RET ; Exit & Clean Up Stack\r
- \r
-GET_Y_OFFSET ENDP\r
- \r
- \r
-;============\r
-;SYNC_DISPLAY\r
-;============\r
-;\r
-; Pauses the computer until the next Vertical Retrace starts\r
-;\r
-; ENTRY: No Parameters are passed\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
- PUBLIC SYNC_DISPLAY\r
- \r
-SYNC_DISPLAY PROC FAR\r
- \r
- MOV DX, INPUT_1 ; Input Status #1 Register\r
- \r
- ; Wait for any current retrace to end\r
- \r
-@SD_WAIT0:\r
- IN AL, DX ; Get VGA status\r
- AND AL, VERT_RETRACE ; In Display mode yet?\r
- JNZ @SD_WAIT0 ; If Not, wait for it\r
- \r
- ; Wait for the start of the next vertical retrace\r
- \r
-@SD_WAIT1:\r
- IN AL, DX ; Get VGA status\r
- AND AL, VERT_RETRACE ; Vertical Retrace Start?\r
- JZ @SD_WAIT1 ; If Not, wait for it\r
- \r
- RET ; Exit & Clean Up Stack\r
- \r
-SYNC_DISPLAY ENDP\r
- \r
- \r
- ; ===== TEXT DISPLAY ROUTINES =====\r
- \r
-;==================================================\r
-;GPRINTC (CharNum%, Xpos%, Ypos%, ColorF%, ColorB%)\r
-;==================================================\r
-;\r
-; Draws an ASCII Text Character using the currently selected\r
-; 8x8 font on the active display page. It would be a simple\r
-; exercise to make this routine process variable height fonts.\r
-;\r
-; ENTRY: CharNum = ASCII character # to draw\r
-; Xpos = X position to draw Character at\r
-; Ypos = Y position of to draw Character at\r
-; ColorF = Color to draw text character in\r
-; ColorB = Color to set background to\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-GPC_STACK STRUC\r
- GPC_Width DW ? ; Screen Width-1\r
- GPC_Lines DB ?,? ; Scan lines to Decode\r
- GPC_T_SETS DW ? ; Saved Charset Segment\r
- GPC_T_SETO DW ? ; Saved Charset Offset\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- GPC_ColorB DB ?,? ; Background Color\r
- GPC_ColorF DB ?,? ; Text Color\r
- GPC_Ypos DW ? ; Y Position to Print at\r
- GPC_Xpos DW ? ; X position to Print at\r
- GPC_Char DB ?,? ; Character to Print\r
-GPC_STACK ENDS\r
- \r
- PUBLIC GPRINTC\r
- \r
-GPRINTC PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- SUB SP, 8 ; Allocate WorkSpace on Stack\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- \r
- MOV AX, SCREEN_WIDTH ; Get Logical Line Width\r
- MOV BX, AX ; BX = Screen Width\r
- DEC BX ; = Screen Width-1\r
- MOV [BP].GPC_Width, BX ; Save for later use\r
- \r
- MUL [BP].GPC_Ypos ; Start of Line = Ypos * Width\r
- ADD DI, AX ; DI -> Start of Line Ypos\r
- \r
- MOV AX, [BP].GPC_Xpos ; Get Xpos of Character\r
- MOV CX, AX ; Save Copy of Xpos\r
- SHR AX, 2 ; Bytes into Line = Xpos/4\r
- ADD DI, AX ; DI -> (Xpos, Ypos)\r
- \r
- ;Get Source ADDR of Character Bit Map & Save\r
- \r
- MOV AL, [BP].GPC_Char ; Get Character #\r
- TEST AL, 080h ; Is Hi Bit Set?\r
- JZ @GPC_LowChar ; Nope, use low char set ptr\r
- \r
- AND AL, 07Fh ; Mask Out Hi Bit\r
- MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset\r
- MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment\r
- JMP s @GPC_Set_Char ; Go Setup Character Ptr\r
- \r
-@GPC_LowChar:\r
- \r
- MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset\r
- MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment\r
- \r
-@GPC_Set_Char:\r
- MOV [BP].GPC_T_SETS, DX ; Save Segment on Stack\r
- \r
- MOV AH, 0 ; Valid #'s are 0..127\r
- SHL AX, 3 ; * 8 Bytes Per Bitmap\r
- ADD BX, AX ; BX = Offset of Selected char\r
- MOV [BP].GPC_T_SETO, BX ; Save Offset on Stack\r
- \r
- AND CX, PLANE_BITS ; Get Plane #\r
- MOV CH, ALL_PLANES ; Get Initial Plane mask\r
- SHL CH, CL ; And shift into position\r
- AND CH, ALL_PLANES ; And mask to lower nibble\r
- \r
- MOV AL, 04 ; 4-Plane # = # of initial\r
- SUB AL, CL ; shifts to align bit mask\r
- MOV CL, AL ; Shift Count for SHL\r
- \r
- ;Get segment of character map\r
- \r
- OUT_8 SC_Index, MAP_MASK ; Setup Plane selections\r
- INC DX ; DX -> SC_Data\r
- \r
- MOV AL, 08 ; 8 Lines to Process\r
- MOV [BP].GPC_Lines, AL ; Save on Stack\r
- \r
- MOV DS, [BP].GPC_T_SETS ; Point to character set\r
- \r
-@GPC_DECODE_CHAR_BYTE:\r
- \r
- MOV SI, [BP].GPC_T_SETO ; Get DS:SI = String\r
- \r
- MOV BH, [SI] ; Get Bit Map\r
- INC SI ; Point to Next Line\r
- MOV [BP].GPC_T_SETO, SI ; And save new Pointer...\r
- \r
- CLR AX ; Clear AX\r
- \r
- CLR BL ; Clear BL\r
- ROL BX, CL ; BL holds left edge bits\r
- MOV SI, BX ; Use as Table Index\r
- AND SI, CHAR_BITS ; Get Low Bits\r
- MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
- JZ @GPC_NO_LEFT1BITS ; Skip if No Pixels to set\r
- \r
- MOV AH, [BP].GPC_ColorF ; Get Foreground Color\r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
-@GPC_NO_LEFT1BITS:\r
- XOR AL, CH ; Invert mask for Background\r
- JZ @GPC_NO_LEFT0BITS ; Hey, no need for this\r
- \r
- MOV AH, [BP].GPC_ColorB ; Get background Color\r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
- ;Now Do Middle/Last Band\r
- \r
-@GPC_NO_LEFT0BITS:\r
- INC DI ; Point to next Byte\r
- ROL BX, 4 ; Shift 4 bits\r
- \r
- MOV SI, BX ; Make Lookup Pointer\r
- AND SI, CHAR_BITS ; Get Low Bits\r
- MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
- JZ @GPC_NO_MIDDLE1BITS ; Skip if no pixels to set\r
- \r
- MOV AH, [BP].GPC_ColorF ; Get Foreground Color\r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
-@GPC_NO_MIDDLE1BITS:\r
- XOR AL, ALL_PLANES ; Invert mask for Background\r
- JZ @GPC_NO_MIDDLE0BITS ; Hey, no need for this\r
- \r
- MOV AH, [BP].GPC_ColorB ; Get background Color\r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
-@GPC_NO_MIDDLE0BITS:\r
- XOR CH, ALL_PLANES ; Invert Clip Mask\r
- CMP CL, 4 ; Aligned by 4?\r
- JZ @GPC_NEXT_LINE ; If so, Exit now..\r
- \r
- INC DI ; Point to next Byte\r
- ROL BX, 4 ; Shift 4 bits\r
- \r
- MOV SI, BX ; Make Lookup Pointer\r
- AND SI, CHAR_BITS ; Get Low Bits\r
- MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
- JZ @GPC_NO_RIGHT1BITS ; Skip if No Pixels to set\r
- \r
- MOV AH, [BP].GPC_ColorF ; Get Foreground Color\r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
-@GPC_NO_RIGHT1BITS:\r
- \r
- XOR AL, CH ; Invert mask for Background\r
- JZ @GPC_NO_RIGHT0BITS ; Hey, no need for this\r
- \r
- MOV AH, [BP].GPC_ColorB ; Get background Color\r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
-@GPC_NO_RIGHT0BITS:\r
- DEC DI ; Adjust for Next Line Advance\r
- \r
-@GPC_NEXT_LINE:\r
- ADD DI, [BP].GPC_Width ; Point to Next Line\r
- XOR CH, CHAR_BITS ; Flip the Clip mask back\r
- \r
- DEC [BP].GPC_Lines ; Count Down Lines\r
- JZ @GPC_EXIT ; Ok... Done!\r
- \r
- JMP @GPC_DECODE_CHAR_BYTE ; Again! Hey!\r
- \r
-@GPC_EXIT:\r
- ADD SP, 08 ; Deallocate stack workspace\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 10 ; Exit and Clean up Stack\r
- \r
-GPRINTC ENDP\r
- \r
- \r
-;==========================================\r
-;TGPRINTC (CharNum%, Xpos%, Ypos%, ColorF%)\r
-;==========================================\r
-;\r
-; Transparently draws an ASCII Text Character using the\r
-; currently selected 8x8 font on the active display page.\r
-;\r
-; ENTRY: CharNum = ASCII character # to draw\r
-; Xpos = X position to draw Character at\r
-; Ypos = Y position of to draw Character at\r
-; ColorF = Color to draw text character in\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-TGP_STACK STRUC\r
- TGP_Width DW ? ; Screen Width-1\r
- TGP_Lines DB ?,? ; Scan lines to Decode\r
- TGP_T_SETS DW ? ; Saved Charset Segment\r
- TGP_T_SETO DW ? ; Saved Charset Offset\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- TGP_ColorF DB ?,? ; Text Color\r
- TGP_Ypos DW ? ; Y Position to Print at\r
- TGP_Xpos DW ? ; X position to Print at\r
- TGP_Char DB ?,? ; Character to Print\r
-TGP_STACK ENDS\r
- \r
- PUBLIC TGPRINTC\r
- \r
-TGPRINTC PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- SUB SP, 8 ; Allocate WorkSpace on Stack\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- \r
- MOV AX, SCREEN_WIDTH ; Get Logical Line Width\r
- MOV BX, AX ; BX = Screen Width\r
- DEC BX ; = Screen Width-1\r
- MOV [BP].TGP_Width, BX ; Save for later use\r
- \r
- MUL [BP].TGP_Ypos ; Start of Line = Ypos * Width\r
- ADD DI, AX ; DI -> Start of Line Ypos\r
- \r
- MOV AX, [BP].TGP_Xpos ; Get Xpos of Character\r
- MOV CX, AX ; Save Copy of Xpos\r
- SHR AX, 2 ; Bytes into Line = Xpos/4\r
- ADD DI, AX ; DI -> (Xpos, Ypos)\r
- \r
- ;Get Source ADDR of Character Bit Map & Save\r
- \r
- MOV AL, [BP].TGP_Char ; Get Character #\r
- TEST AL, 080h ; Is Hi Bit Set?\r
- JZ @TGP_LowChar ; Nope, use low char set ptr\r
- \r
- AND AL, 07Fh ; Mask Out Hi Bit\r
- MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset\r
- MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment\r
- JMP s @TGP_Set_Char ; Go Setup Character Ptr\r
- \r
-@TGP_LowChar:\r
- \r
- MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset\r
- MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment\r
- \r
-@TGP_Set_Char:\r
- MOV [BP].TGP_T_SETS, DX ; Save Segment on Stack\r
- \r
- MOV AH, 0 ; Valid #'s are 0..127\r
- SHL AX, 3 ; * 8 Bytes Per Bitmap\r
- ADD BX, AX ; BX = Offset of Selected char\r
- MOV [BP].TGP_T_SETO, BX ; Save Offset on Stack\r
- \r
- AND CX, PLANE_BITS ; Get Plane #\r
- MOV CH, ALL_PLANES ; Get Initial Plane mask\r
- SHL CH, CL ; And shift into position\r
- AND CH, ALL_PLANES ; And mask to lower nibble\r
- \r
- MOV AL, 04 ; 4-Plane # = # of initial\r
- SUB AL, CL ; shifts to align bit mask\r
- MOV CL, AL ; Shift Count for SHL\r
- \r
- ;Get segment of character map\r
- \r
- OUT_8 SC_Index, MAP_MASK ; Setup Plane selections\r
- INC DX ; DX -> SC_Data\r
- \r
- MOV AL, 08 ; 8 Lines to Process\r
- MOV [BP].TGP_Lines, AL ; Save on Stack\r
- \r
- MOV DS, [BP].TGP_T_SETS ; Point to character set\r
- \r
-@TGP_DECODE_CHAR_BYTE:\r
- \r
- MOV SI, [BP].TGP_T_SETO ; Get DS:SI = String\r
- \r
- MOV BH, [SI] ; Get Bit Map\r
- INC SI ; Point to Next Line\r
- MOV [BP].TGP_T_SETO, SI ; And save new Pointer...\r
- \r
- MOV AH, [BP].TGP_ColorF ; Get Foreground Color\r
- \r
- CLR BL ; Clear BL\r
- ROL BX, CL ; BL holds left edge bits\r
- MOV SI, BX ; Use as Table Index\r
- AND SI, CHAR_BITS ; Get Low Bits\r
- MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
- JZ @TGP_NO_LEFT1BITS ; Skip if No Pixels to set\r
- \r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
- ;Now Do Middle/Last Band\r
- \r
-@TGP_NO_LEFT1BITS:\r
- \r
- INC DI ; Point to next Byte\r
- ROL BX, 4 ; Shift 4 bits\r
- \r
- MOV SI, BX ; Make Lookup Pointer\r
- AND SI, CHAR_BITS ; Get Low Bits\r
- MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
- JZ @TGP_NO_MIDDLE1BITS ; Skip if no pixels to set\r
- \r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
-@TGP_NO_MIDDLE1BITS:\r
- XOR CH, ALL_PLANES ; Invert Clip Mask\r
- CMP CL, 4 ; Aligned by 4?\r
- JZ @TGP_NEXT_LINE ; If so, Exit now..\r
- \r
- INC DI ; Point to next Byte\r
- ROL BX, 4 ; Shift 4 bits\r
- \r
- MOV SI, BX ; Make Lookup Pointer\r
- AND SI, CHAR_BITS ; Get Low Bits\r
- MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
- JZ @TGP_NO_RIGHT1BITS ; Skip if No Pixels to set\r
- \r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
-@TGP_NO_RIGHT1BITS:\r
- \r
- DEC DI ; Adjust for Next Line Advance\r
- \r
-@TGP_NEXT_LINE:\r
- ADD DI, [BP].TGP_Width ; Point to Next Line\r
- XOR CH, CHAR_BITS ; Flip the Clip mask back\r
- \r
- DEC [BP].TGP_Lines ; Count Down Lines\r
- JZ @TGP_EXIT ; Ok... Done!\r
- \r
- JMP @TGP_DECODE_CHAR_BYTE ; Again! Hey!\r
- \r
-@TGP_EXIT:\r
- ADD SP, 08 ; Deallocate stack workspace\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 8 ; Exit and Clean up Stack\r
- \r
-TGPRINTC ENDP\r
- \r
- \r
-;===============================================================\r
-;PRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
-;===============================================================\r
-;\r
-; Routine to quickly Print a null terminated ASCII string on the\r
-; active display page up to a maximum length.\r
-;\r
-; ENTRY: String = Far Pointer to ASCII string to print\r
-; MaxLen = # of characters to print if no null found\r
-; Xpos = X position to draw Text at\r
-; Ypos = Y position of to draw Text at\r
-; ColorF = Color to draw text in\r
-; ColorB = Color to set background to\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-PS_STACK STRUC\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- PS_ColorB DW ? ; Background Color\r
- PS_ColorF DW ? ; Text Color\r
- PS_Ypos DW ? ; Y Position to Print at\r
- PS_Xpos DW ? ; X position to Print at\r
- PS_Len DW ? ; Maximum Length of string to print\r
- PS_Text DW ?,? ; Far Ptr to Text String\r
-PS_STACK ENDS\r
- \r
- PUBLIC PRINT_STR\r
- \r
-PRINT_STR PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
-@PS_Print_It:\r
- \r
- MOV CX, [BP].PS_Len ; Get Remaining text Length\r
- JCXZ @PS_Exit ; Exit when out of text\r
- \r
- LES DI, d [BP].PS_Text ; ES:DI -> Current Char in Text\r
- MOV AL, ES:[DI] ; AL = Text Character\r
- AND AX, 00FFh ; Clear High Word\r
- JZ @PS_Exit ; Exit if null character\r
- \r
- DEC [BP].PS_Len ; Remaining Text length--\r
- INC [BP].PS_Text ; Point to Next text char\r
- \r
- ; Set up Call to GPRINTC\r
- \r
- PUSH AX ; Set Character Parameter\r
- MOV BX, [BP].PS_Xpos ; Get Xpos\r
- PUSH BX ; Set Xpos Parameter\r
- ADD BX, 8 ; Advance 1 Char to Right\r
- MOV [BP].PS_Xpos, BX ; Save for next time through\r
- \r
- MOV BX, [BP].PS_Ypos ; Get Ypos\r
- PUSH BX ; Set Ypos Parameter\r
- \r
- MOV BX, [BP].PS_ColorF ; Get Text Color\r
- PUSH BX ; Set ColorF Parameter\r
- \r
- MOV BX, [BP].PS_ColorB ; Get Background Color\r
- PUSH BX ; Set ColorB Parameter\r
- \r
- CALL f GPRINTC ; Print Character!\r
- JMP s @PS_Print_It ; Process next character\r
- \r
-@PS_Exit:\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 14 ; Exit and Clean up Stack\r
- \r
-PRINT_STR ENDP\r
- \r
- \r
-;================================================================\r
-;TPRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
-;================================================================\r
-;\r
-; Routine to quickly transparently Print a null terminated ASCII\r
-; string on the active display page up to a maximum length.\r
-;\r
-; ENTRY: String = Far Pointer to ASCII string to print\r
-; MaxLen = # of characters to print if no null found\r
-; Xpos = X position to draw Text at\r
-; Ypos = Y position of to draw Text at\r
-; ColorF = Color to draw text in\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-TPS_STACK STRUC\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- TPS_ColorF DW ? ; Text Color\r
- TPS_Ypos DW ? ; Y Position to Print at\r
- TPS_Xpos DW ? ; X position to Print at\r
- TPS_Len DW ? ; Maximum Length of string to print\r
- TPS_Text DW ?,? ; Far Ptr to Text String\r
-TPS_STACK ENDS\r
- \r
- PUBLIC TPRINT_STR\r
- \r
-TPRINT_STR PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
-@TPS_Print_It:\r
- \r
- MOV CX, [BP].TPS_Len ; Get Remaining text Length\r
- JCXZ @TPS_Exit ; Exit when out of text\r
- \r
- LES DI, d [BP].TPS_Text ; ES:DI -> Current Char in Text\r
- MOV AL, ES:[DI] ; AL = Text Character\r
- AND AX, 00FFh ; Clear High Word\r
- JZ @TPS_Exit ; Exit if null character\r
- \r
- DEC [BP].TPS_Len ; Remaining Text length--\r
- INC [BP].TPS_Text ; Point to Next text char\r
- \r
- ; Set up Call to TGPRINTC\r
- \r
- PUSH AX ; Set Character Parameter\r
- MOV BX, [BP].TPS_Xpos ; Get Xpos\r
- PUSH BX ; Set Xpos Parameter\r
- ADD BX, 8 ; Advance 1 Char to Right\r
- MOV [BP].TPS_Xpos, BX ; Save for next time through\r
- \r
- MOV BX, [BP].TPS_Ypos ; Get Ypos\r
- PUSH BX ; Set Ypos Parameter\r
- \r
- MOV BX, [BP].TPS_ColorF ; Get Text Color\r
- PUSH BX ; Set ColorF Parameter\r
- \r
- CALL f TGPRINTC ; Print Character!\r
- JMP s @TPS_Print_It ; Process next character\r
- \r
-@TPS_Exit:\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 12 ; Exit and Clean up Stack\r
- \r
-TPRINT_STR ENDP\r
- \r
- \r
-;===========================================\r
-;SET_DISPLAY_FONT(SEG FontData, FontNumber%)\r
-;===========================================\r
-;\r
-; Allows the user to specify their own font data for\r
-; wither the lower or upper 128 characters.\r
-;\r
-; ENTRY: FontData = Far Pointer to Font Bitmaps\r
-; FontNumber = Which half of set this is\r
-; = 0, Lower 128 characters\r
-; = 1, Upper 128 characters\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-SDF_STACK STRUC\r
- DW ? ; BP\r
- DD ? ; Caller\r
- SDF_Which DW ? ; Hi Table/Low Table Flag\r
- SDF_Font DD ? ; Far Ptr to Font Table\r
-SDF_STACK ENDS\r
- \r
- PUBLIC SET_DISPLAY_FONT\r
- \r
-SET_DISPLAY_FONT PROC FAR\r
- \r
- PUSH BP ; Preserve Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- LES DI, [BP].SDF_Font ; Get Far Ptr to Font\r
- \r
- MOV SI, o CHARSET_LOW ; Assume Lower 128 chars\r
- TEST [BP].SDF_Which, 1 ; Font #1 selected?\r
- JZ @SDF_Set_Font ; If not, skip ahead\r
- \r
- MOV SI, o CHARSET_HI ; Ah, really it's 128-255\r
- \r
-@SDF_Set_Font:\r
- MOV [SI], DI ; Set Font Pointer Offset\r
- MOV [SI+2], ES ; Set Font Pointer Segment\r
- \r
- POP BP ; Restore Registers\r
- RET 6 ; We are Done.. Outa here\r
- \r
-SET_DISPLAY_FONT ENDP\r
- \r
- \r
- ; ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
- \r
-;======================================================\r
-;DRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
-;======================================================\r
-;\r
-; Draws a variable sized Graphics Bitmap such as a\r
-; picture or an Icon on the current Display Page in\r
-; Mode X. The Bitmap is stored in a linear byte array\r
-; corresponding to (0,0) (1,0), (2,0) .. (Width, Height)\r
-; This is the same linear manner as mode 13h graphics.\r
-;\r
-; ENTRY: Image = Far Pointer to Bitmap Data\r
-; Xpos = X position to Place Upper Left pixel at\r
-; Ypos = Y position to Place Upper Left pixel at\r
-; Width = Width of the Bitmap in Pixels\r
-; Height = Height of the Bitmap in Pixels\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-DB_STACK STRUC\r
- DB_LineO DW ? ; Offset to Next Line\r
- DB_PixCount DW ? ; (Minimum) # of Pixels/Line\r
- DB_Start DW ? ; Addr of Upper Left Pixel\r
- DB_PixSkew DW ? ; # of bytes to Adjust EOL\r
- DB_SkewFlag DW ? ; Extra Pix on Plane Flag\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- DB_Height DW ? ; Height of Bitmap in Pixels\r
- DB_Width DW ? ; Width of Bitmap in Pixels\r
- DB_Ypos DW ? ; Y position to Draw Bitmap at\r
- DB_Xpos DW ? ; X position to Draw Bitmap at\r
- DB_Image DD ? ; Far Pointer to Graphics Bitmap\r
-DB_STACK ENDS\r
- \r
- PUBLIC DRAW_BITMAP\r
- \r
-DRAW_BITMAP PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- SUB SP, 10 ; Allocate workspace\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- CLD ; Direction Flag = Forward\r
- \r
- MOV AX, [BP].DB_Ypos ; Get UL Corner Ypos\r
- MUL SCREEN_WIDTH ; AX = Offset to Line Ypos\r
- \r
- MOV BX, [BP].DB_Xpos ; Get UL Corner Xpos\r
- MOV CL, BL ; Save Plane # in CL\r
- SHR BX, 2 ; Xpos/4 = Offset Into Line\r
- \r
- ADD DI, AX ; ES:DI -> Start of Line\r
- ADD DI, BX ; ES:DI -> Upper Left Pixel\r
- MOV [BP].DB_Start, DI ; Save Starting Addr\r
- \r
- ; Compute line to line offset\r
- \r
- MOV BX, [BP].DB_Width ; Get Width of Image\r
- MOV DX, BX ; Save Copy in DX\r
- SHR BX, 2 ; /4 = width in bands\r
- MOV AX, SCREEN_WIDTH ; Get Screen Width\r
- SUB AX, BX ; - (Bitmap Width/4)\r
- \r
- MOV [BP].DB_LineO, AX ; Save Line Width offset\r
- MOV [BP].DB_PixCount, BX ; Minimum # pix to copy\r
- \r
- AND DX, PLANE_BITS ; Get "partial band" size (0-3)\r
- MOV [BP].DB_PixSkew, DX ; Also End of Line Skew\r
- MOV [BP].DB_SkewFlag, DX ; Save as Flag/Count\r
- \r
- AND CX, PLANE_BITS ; CL = Starting Plane #\r
- MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select\r
- SHL AH, CL ; Select correct Plane\r
- OUT_16 SC_Index, AX ; Select Plane...\r
- MOV BH, AH ; BH = Saved Plane Mask\r
- MOV BL, 4 ; BL = Planes to Copy\r
- \r
-@DB_COPY_PLANE:\r
- \r
- LDS SI, [BP].DB_Image ; DS:SI-> Source Image\r
- MOV DX, [BP].DB_Height ; # of Lines to Copy\r
- MOV DI, [BP].DB_Start ; ES:DI-> Dest pos\r
- \r
-@DB_COPY_LINE:\r
- MOV CX, [BP].DB_PixCount ; Min # to copy\r
- \r
- TEST CL, 0FCh ; 16+PixWide?\r
- JZ @DB_COPY_REMAINDER ; Nope...\r
- \r
- ; Pixel Copy loop has been unrolled to x4\r
- \r
-@DB_COPY_LOOP:\r
- MOVSB ; Copy Bitmap Pixel\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- MOVSB ; Copy Bitmap Pixel\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- MOVSB ; Copy Bitmap Pixel\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- MOVSB ; Copy Bitmap Pixel\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- \r
- SUB CL, 4 ; Pixels to Copy=-4\r
- TEST CL, 0FCh ; 4+ Pixels Left?\r
- JNZ @DB_COPY_LOOP ; if so, do another block\r
- \r
-@DB_COPY_REMAINDER:\r
- JCXZ @DB_NEXT_LINE ; Any Pixels left on line\r
- \r
-@DB_COPY2:\r
- MOVSB ; Copy Bitmap Pixel\r
- ADD SI,3 ; Skip to Next Byte in same plane\r
- LOOPx CX, @DB_COPY2 ; Pixels to Copy--, Loop until done\r
- \r
-@DB_NEXT_LINE:\r
- \r
- ; any Partial Pixels? (some planes only)\r
- \r
- OR CX, [BP].DB_SkewFlag ; Get Skew Count\r
- JZ @DB_NEXT2 ; if no partial pixels\r
- \r
- MOVSB ; Copy Bitmap Pixel\r
- DEC DI ; Back up to align\r
- DEC SI ; Back up to align\r
- \r
-@DB_NEXT2:\r
- ADD SI, [BP].DB_PixSkew ; Adjust Skew\r
- ADD DI, [BP].DB_LineO ; Set to Next Display Line\r
- LOOPx DX, @DB_COPY_LINE ; Lines to Copy--, Loop if more\r
- \r
- ; Copy Next Plane....\r
- \r
- DEC BL ; Planes to Go--\r
- JZ @DB_Exit ; Hey! We are done\r
- \r
- ROL BH, 1 ; Next Plane in line...\r
- OUT_8 SC_Data, BH ; Select Plane\r
- \r
- CMP AL, 12h ; Carry Set if AL=11h\r
- ADC [BP].DB_Start, 0 ; Screen Addr =+Carry\r
- INC w [BP].DB_Image ; Start @ Next Byte\r
- \r
- SUB [BP].DB_SkewFlag, 1 ; Reduce Planes to Skew\r
- ADC [BP].DB_SkewFlag, 0 ; Back to 0 if it was -1\r
- \r
- JMP s @DB_COPY_PLANE ; Go Copy the Next Plane\r
- \r
-@DB_Exit:\r
- ADD SP, 10 ; Deallocate workspace\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 12 ; Exit and Clean up Stack\r
- \r
-DRAW_BITMAP ENDP\r
- \r
- \r
-;=======================================================\r
-;TDRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
-;=======================================================\r
-;\r
-; Transparently Draws a variable sized Graphics Bitmap\r
-; such as a picture or an Icon on the current Display Page\r
-; in Mode X. Pixels with a value of 0 are not drawn,\r
-; leaving the previous "background" contents intact.\r
-;\r
-; The Bitmap format is the same as for the DRAW_BITMAP function.\r
-;\r
-; ENTRY: Image = Far Pointer to Bitmap Data\r
-; Xpos = X position to Place Upper Left pixel at\r
-; Ypos = Y position to Place Upper Left pixel at\r
-; Width = Width of the Bitmap in Pixels\r
-; Height = Height of the Bitmap in Pixels\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-TB_STACK STRUC\r
- TB_LineO DW ? ; Offset to Next Line\r
- TB_PixCount DW ? ; (Minimum) # of Pixels/Line\r
- TB_Start DW ? ; Addr of Upper Left Pixel\r
- TB_PixSkew DW ? ; # of bytes to Adjust EOL\r
- TB_SkewFlag DW ? ; Extra Pix on Plane Flag\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- TB_Height DW ? ; Height of Bitmap in Pixels\r
- TB_Width DW ? ; Width of Bitmap in Pixels\r
- TB_Ypos DW ? ; Y position to Draw Bitmap at\r
- TB_Xpos DW ? ; X position to Draw Bitmap at\r
- TB_Image DD ? ; Far Pointer to Graphics Bitmap\r
-TB_STACK ENDS\r
- \r
- PUBLIC TDRAW_BITMAP\r
- \r
-TDRAW_BITMAP PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- SUB SP, 10 ; Allocate workspace\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- CLD ; Direction Flag = Forward\r
- \r
- MOV AX, [BP].TB_Ypos ; Get UL Corner Ypos\r
- MUL SCREEN_WIDTH ; AX = Offset to Line Ypos\r
- \r
- MOV BX, [BP].TB_Xpos ; Get UL Corner Xpos\r
- MOV CL, BL ; Save Plane # in CL\r
- SHR BX, 2 ; Xpos/4 = Offset Into Line\r
- \r
- ADD DI, AX ; ES:DI -> Start of Line\r
- ADD DI, BX ; ES:DI -> Upper Left Pixel\r
- MOV [BP].TB_Start, DI ; Save Starting Addr\r
- \r
- ; Compute line to line offset\r
- \r
- MOV BX, [BP].TB_Width ; Get Width of Image\r
- MOV DX, BX ; Save Copy in DX\r
- SHR BX, 2 ; /4 = width in bands\r
- MOV AX, SCREEN_WIDTH ; Get Screen Width\r
- SUB AX, BX ; - (Bitmap Width/4)\r
- \r
- MOV [BP].TB_LineO, AX ; Save Line Width offset\r
- MOV [BP].TB_PixCount, BX ; Minimum # pix to copy\r
- \r
- AND DX, PLANE_BITS ; Get "partial band" size (0-3)\r
- MOV [BP].TB_PixSkew, DX ; Also End of Line Skew\r
- MOV [BP].TB_SkewFlag, DX ; Save as Flag/Count\r
- \r
- AND CX, PLANE_BITS ; CL = Starting Plane #\r
- MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select\r
- SHL AH, CL ; Select correct Plane\r
- OUT_16 SC_Index, AX ; Select Plane...\r
- MOV BH, AH ; BH = Saved Plane Mask\r
- MOV BL, 4 ; BL = Planes to Copy\r
- \r
-@TB_COPY_PLANE:\r
- \r
- LDS SI, [BP].TB_Image ; DS:SI-> Source Image\r
- MOV DX, [BP].TB_Height ; # of Lines to Copy\r
- MOV DI, [BP].TB_Start ; ES:DI-> Dest pos\r
- \r
- ; Here AH is set with the value to be considered\r
- ; "Transparent". It can be changed!\r
- \r
- MOV AH, 0 ; Value to Detect 0\r
- \r
-@TB_COPY_LINE:\r
- MOV CX, [BP].TB_PixCount ; Min # to copy\r
- \r
- TEST CL, 0FCh ; 16+PixWide?\r
- JZ @TB_COPY_REMAINDER ; Nope...\r
- \r
- ; Pixel Copy loop has been unrolled to x4\r
- \r
-@TB_COPY_LOOP:\r
- LODSB ; Get Pixel Value in AL\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- CMP AL, AH ; It is "Transparent"?\r
- JE @TB_SKIP_01 ; Skip ahead if so\r
- MOV ES:[DI], AL ; Copy Pixel to VGA screen\r
- \r
-@TB_SKIP_01:\r
- LODSB ; Get Pixel Value in AL\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- CMP AL, AH ; It is "Transparent"?\r
- JE @TB_SKIP_02 ; Skip ahead if so\r
- MOV ES:[DI+1], AL ; Copy Pixel to VGA screen\r
- \r
-@TB_SKIP_02:\r
- LODSB ; Get Pixel Value in AL\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- CMP AL, AH ; It is "Transparent"?\r
- JE @TB_SKIP_03 ; Skip ahead if so\r
- MOV ES:[DI+2], AL ; Copy Pixel to VGA screen\r
- \r
-@TB_SKIP_03:\r
- LODSB ; Get Pixel Value in AL\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- CMP AL, AH ; It is "Transparent"?\r
- JE @TB_SKIP_04 ; Skip ahead if so\r
- MOV ES:[DI+3], AL ; Copy Pixel to VGA screen\r
- \r
-@TB_SKIP_04:\r
- ADD DI, 4 ; Adjust Pixel Write Location\r
- SUB CL, 4 ; Pixels to Copy=-4\r
- TEST CL, 0FCh ; 4+ Pixels Left?\r
- JNZ @TB_COPY_LOOP ; if so, do another block\r
- \r
-@TB_COPY_REMAINDER:\r
- JCXZ @TB_NEXT_LINE ; Any Pixels left on line\r
- \r
-@TB_COPY2:\r
- LODSB ; Get Pixel Value in AL\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- CMP AL, AH ; It is "Transparent"?\r
- JE @TB_SKIP_05 ; Skip ahead if so\r
- MOV ES:[DI], AL ; Copy Pixel to VGA screen\r
- \r
-@TB_SKIP_05:\r
- INC DI ; Advance Dest Addr\r
- LOOPx CX, @TB_COPY2 ; Pixels to Copy--, Loop until done\r
- \r
-@TB_NEXT_LINE:\r
- \r
- ; any Partial Pixels? (some planes only)\r
- \r
- OR CX, [BP].TB_SkewFlag ; Get Skew Count\r
- JZ @TB_NEXT2 ; if no partial pixels\r
- \r
- LODSB ; Get Pixel Value in AL\r
- DEC SI ; Backup to Align\r
- CMP AL, AH ; It is "Transparent"?\r
- JE @TB_NEXT2 ; Skip ahead if so\r
- MOV ES:[DI], AL ; Copy Pixel to VGA screen\r
- \r
-@TB_NEXT2:\r
- ADD SI, [BP].TB_PixSkew ; Adjust Skew\r
- ADD DI, [BP].TB_LineO ; Set to Next Display Line\r
- LOOPx DX, @TB_COPY_LINE ; Lines to Copy--, Loop if More\r
- \r
- ;Copy Next Plane....\r
- \r
- DEC BL ; Planes to Go--\r
- JZ @TB_Exit ; Hey! We are done\r
- \r
- ROL BH, 1 ; Next Plane in line...\r
- OUT_8 SC_Data, BH ; Select Plane\r
- \r
- CMP AL, 12h ; Carry Set if AL=11h\r
- ADC [BP].TB_Start, 0 ; Screen Addr =+Carry\r
- INC w [BP].TB_Image ; Start @ Next Byte\r
- \r
- SUB [BP].TB_SkewFlag, 1 ; Reduce Planes to Skew\r
- ADC [BP].TB_SkewFlag, 0 ; Back to 0 if it was -1\r
- \r
- JMP @TB_COPY_PLANE ; Go Copy the next Plane\r
- \r
-@TB_Exit:\r
- ADD SP, 10 ; Deallocate workspace\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 12 ; Exit and Clean up Stack\r
- \r
-TDRAW_BITMAP ENDP\r
- \r
- \r
- ; ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
- \r
-;==================================\r
-;COPY_PAGE (SourcePage%, DestPage%)\r
-;==================================\r
-;\r
-; Duplicate on display page onto another\r
-;\r
-; ENTRY: SourcePage = Display Page # to Duplicate\r
-; DestPage = Display Page # to hold copy\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-CP_STACK STRUC\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- CP_DestP DW ? ; Page to hold copied image\r
- CP_SourceP DW ? ; Page to Make copy from\r
-CP_STACK ENDS\r
- \r
- PUBLIC COPY_PAGE\r
- \r
-COPY_PAGE PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- CLD ; Block Xfer Forwards\r
- \r
- ; Make sure Page #'s are valid\r
- \r
- MOV AX, [BP].CP_SourceP ; Get Source Page #\r
- CMP AX, LAST_PAGE ; is it > Max Page #?\r
- JAE @CP_Exit ; if so, abort\r
- \r
- MOV BX, [BP].CP_DestP ; Get Destination Page #\r
- CMP BX, LAST_PAGE ; is it > Max Page #?\r
- JAE @CP_Exit ; if so, abort\r
- \r
- CMP AX, BX ; Pages #'s the same?\r
- JE @CP_Exit ; if so, abort\r
- \r
- ; Setup DS:SI and ES:DI to Video Pages\r
- \r
- SHL BX, 1 ; Scale index to Word\r
- MOV DI, PAGE_ADDR[BX] ; Offset to Dest Page\r
- \r
- MOV BX, AX ; Index to Source page\r
- SHL BX, 1 ; Scale index to Word\r
- MOV SI, PAGE_ADDR[BX] ; Offset to Source Page\r
- \r
- MOV CX, PAGE_SIZE ; Get size of Page\r
- MOV AX, CURRENT_SEGMENT ; Get Video Mem Segment\r
- MOV ES, AX ; ES:DI -> Dest Page\r
- MOV DS, AX ; DS:SI -> Source Page\r
- \r
- ; Setup VGA registers for Mem to Mem copy\r
- \r
- OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on\r
- OUT_16 SC_Index, ALL_PLANES_ON ; Copy all Planes\r
- \r
- ; Note.. Do *NOT* use MOVSW or MOVSD - they will\r
- ; Screw with the latches which are 8 bits x 4\r
- \r
- REP MOVSB ; Copy entire Page!\r
- \r
- ; Reset VGA for normal memory access\r
- \r
- OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = off\r
- \r
-@CP_Exit:\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 4 ; Exit and Clean up Stack\r
- \r
-COPY_PAGE ENDP\r
- \r
- \r
-;==========================================================================\r
-;COPY_BITMAP (SourcePage%, X1%, Y1%, X2%, Y2%, DestPage%, DestX1%, DestY1%)\r
-;==========================================================================\r
-;\r
-; Copies a Bitmap Image from one Display Page to Another\r
-; This Routine is Limited to copying Images with the same\r
-; Plane Alignment. To Work: (X1 MOD 4) must = (DestX1 MOD 4)\r
-; Copying an Image to the Same Page is supported, but results\r
-; may be defined when the when the rectangular areas\r
-; (X1, Y1) - (X2, Y2) and (DestX1, DestY1) -\r
-; (DestX1+(X2-X1), DestY1+(Y2-Y1)) overlap...\r
-; No Paramter checking to done to insure that\r
-; X2 >= X1 and Y2 >= Y1. Be Careful...\r
-;\r
-; ENTRY: SourcePage = Display Page # with Source Image\r
-; X1 = Upper Left Xpos of Source Image\r
-; Y1 = Upper Left Ypos of Source Image\r
-; X2 = Lower Right Xpos of Source Image\r
-; Y2 = Lower Right Ypos of Source Image\r
-; DestPage = Display Page # to copy Image to\r
-; DestX1 = Xpos to Copy UL Corner of Image to\r
-; DestY1 = Ypos to Copy UL Corner of Image to\r
-;\r
-; EXIT: AX = Success Flag: 0 = Failure / -1= Success\r
-;\r
- \r
-CB_STACK STRUC\r
- CB_Height DW ? ; Height of Image in Lines\r
- CB_Width DW ? ; Width of Image in "bands"\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- CB_DestY1 DW ? ; Destination Ypos\r
- CB_DestX1 DW ? ; Destination Xpos\r
- CB_DestP DW ? ; Page to Copy Bitmap To\r
- CB_Y2 DW ? ; LR Ypos of Image\r
- CB_X2 DW ? ; LR Xpos of Image\r
- CB_Y1 DW ? ; UL Ypos of Image\r
- CB_X1 DW ? ; UL Xpos of Image\r
- CB_SourceP DW ? ; Page containing Source Bitmap\r
-CB_STACK ENDS\r
- \r
- PUBLIC COPY_BITMAP\r
- \r
-COPY_BITMAP PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- SUB SP, 4 ; Allocate WorkSpace on Stack\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- ; Prep Registers (and keep jumps short!)\r
- \r
- MOV ES, CURRENT_SEGMENT ; ES -> VGA Ram\r
- CLD ; Block Xfer Forwards\r
- \r
- ; Make sure Parameters are valid\r
- \r
- MOV BX, [BP].CB_SourceP ; Get Source Page #\r
- CMP BX, LAST_PAGE ; is it > Max Page #?\r
- JAE @CB_Abort ; if so, abort\r
- \r
- MOV CX, [BP].CB_DestP ; Get Destination Page #\r
- CMP CX, LAST_PAGE ; is it > Max Page #?\r
- JAE @CB_Abort ; if so, abort\r
- \r
- MOV AX, [BP].CB_X1 ; Get Source X1\r
- XOR AX, [BP].CB_DestX1 ; Compare Bits 0-1\r
- AND AX, PLANE_BITS ; Check Plane Bits\r
- JNZ @CB_Abort ; They should cancel out\r
- \r
- ; Setup for Copy processing\r
- \r
- OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select\r
- OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on\r
- \r
- ; Compute Info About Images, Setup ES:SI & ES:DI\r
- \r
- MOV AX, [BP].CB_Y2 ; Height of Bitmap in lines\r
- SUB AX, [BP].CB_Y1 ; is Y2 - Y1 + 1\r
- INC AX ; (add 1 since were not 0 based)\r
- MOV [BP].CB_Height, AX ; Save on Stack for later use\r
- \r
- MOV AX, [BP].CB_X2 ; Get # of "Bands" of 4 Pixels\r
- MOV DX, [BP].CB_X1 ; the Bitmap Occupies as X2-X1\r
- SHR AX, 2 ; Get X2 Band (X2 / 4)\r
- SHR DX, 2 ; Get X1 Band (X1 / 4)\r
- SUB AX, DX ; AX = # of Bands - 1\r
- INC AX ; AX = # of Bands\r
- MOV [BP].CB_Width, AX ; Save on Stack for later use\r
- \r
- SHL BX, 1 ; Scale Source Page to Word\r
- MOV SI, PAGE_ADDR[BX] ; SI = Offset of Source Page\r
- MOV AX, [BP].CB_Y1 ; Get Source Y1 Line\r
- MUL SCREEN_WIDTH ; AX = Offset to Line Y1\r
- ADD SI, AX ; SI = Offset to Line Y1\r
- MOV AX, [BP].CB_X1 ; Get Source X1\r
- SHR AX, 2 ; X1 / 4 = Byte offset\r
- ADD SI, AX ; SI = Byte Offset to (X1,Y1)\r
- \r
- MOV BX, CX ; Dest Page Index to BX\r
- SHL BX, 1 ; Scale Source Page to Word\r
- MOV DI, PAGE_ADDR[BX] ; DI = Offset of Dest Page\r
- MOV AX, [BP].CB_DestY1 ; Get Dest Y1 Line\r
- MUL SCREEN_WIDTH ; AX = Offset to Line Y1\r
- ADD DI, AX ; DI = Offset to Line Y1\r
- MOV AX, [BP].CB_DestX1 ; Get Dest X1\r
- SHR AX, 2 ; X1 / 4 = Byte offset\r
- ADD DI, AX ; DI = Byte Offset to (D-X1,D-Y1)\r
- \r
- MOV CX, [BP].CB_Width ; CX = Width of Image (Bands)\r
- DEC CX ; CX = 1?\r
- JE @CB_Only_One_Band ; 0 Means Image Width of 1 Band\r
- \r
- MOV BX, [BP].CB_X1 ; Get Source X1\r
- AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 00?)\r
- JZ @CB_Check_Right ; if so, check right alignment\r
- JNZ @CB_Left_Band ; not aligned? well..\r
- \r
-@CB_Abort:\r
- CLR AX ; Return False (Failure)\r
- JMP @CB_Exit ; and Finish Up\r
- \r
- ; Copy when Left & Right Clip Masks overlap...\r
- \r
-@CB_Only_One_Band:\r
- MOV BX, [BP].CB_X1 ; Get Left Clip Mask\r
- AND BX, PLANE_BITS ; Mask out Row #\r
- MOV AL, Left_Clip_Mask[BX] ; Get Left Edge Mask\r
- MOV BX, [BP].CB_X2 ; Get Right Clip Mask\r
- AND BX, PLANE_BITS ; Mask out Row #\r
- AND AL, Right_Clip_Mask[BX] ; Get Right Edge Mask byte\r
- \r
- OUT_8 SC_Data, AL ; Clip For Left & Right Masks\r
- \r
- MOV CX, [BP].CB_Height ; CX = # of Lines to Copy\r
- MOV DX, SCREEN_WIDTH ; DX = Width of Screen\r
- CLR BX ; BX = Offset into Image\r
- \r
-@CB_One_Loop:\r
- MOV AL, ES:[SI+BX] ; Load Latches\r
- MOV ES:[DI+BX], AL ; Unload Latches\r
- ADD BX, DX ; Advance Offset to Next Line\r
- LOOPjz CX, @CB_One_Done ; Exit Loop if Finished\r
- \r
- MOV AL, ES:[SI+BX] ; Load Latches\r
- MOV ES:[DI+BX], AL ; Unload Latches\r
- ADD BX, DX ; Advance Offset to Next Line\r
- LOOPx CX, @CB_One_Loop ; Loop until Finished\r
- \r
-@CB_One_Done:\r
- JMP @CB_Finish ; Outa Here!\r
- \r
- ; Copy Left Edge of Bitmap\r
- \r
-@CB_Left_Band:\r
- \r
- OUT_8 SC_Data, Left_Clip_Mask[BX] ; Set Left Edge Plane Mask\r
- \r
- MOV CX, [BP].CB_Height ; CX = # of Lines to Copy\r
- MOV DX, SCREEN_WIDTH ; DX = Width of Screen\r
- CLR BX ; BX = Offset into Image\r
- \r
-@CB_Left_Loop:\r
- MOV AL, ES:[SI+BX] ; Load Latches\r
- MOV ES:[DI+BX], AL ; Unload Latches\r
- ADD BX, DX ; Advance Offset to Next Line\r
- LOOPjz CX, @CB_Left_Done ; Exit Loop if Finished\r
- \r
- MOV AL, ES:[SI+BX] ; Load Latches\r
- MOV ES:[DI+BX], AL ; Unload Latches\r
- ADD BX, DX ; Advance Offset to Next Line\r
- LOOPx CX, @CB_Left_Loop ; Loop until Finished\r
- \r
-@CB_Left_Done:\r
- INC DI ; Move Dest Over 1 band\r
- INC SI ; Move Source Over 1 band\r
- DEC [BP].CB_Width ; Band Width--\r
- \r
- ; Determine if Right Edge of Bitmap needs special copy\r
- \r
-@CB_Check_Right:\r
- MOV BX, [BP].CB_X2 ; Get Source X2\r
- AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 11?)\r
- CMP BL, 03h ; Plane = 3?\r
- JE @CB_Copy_Middle ; Copy the Middle then!\r
- \r
- ; Copy Right Edge of Bitmap\r
- \r
-@CB_Right_Band:\r
- \r
- OUT_8 SC_Data, Right_Clip_Mask[BX] ; Set Right Edge Plane Mask\r
- \r
- DEC [BP].CB_Width ; Band Width--\r
- MOV CX, [BP].CB_Height ; CX = # of Lines to Copy\r
- MOV DX, SCREEN_WIDTH ; DX = Width of Screen\r
- MOV BX, [BP].CB_Width ; BX = Offset to Right Edge\r
- \r
-@CB_Right_Loop:\r
- MOV AL, ES:[SI+BX] ; Load Latches\r
- MOV ES:[DI+BX], AL ; Unload Latches\r
- ADD BX, DX ; Advance Offset to Next Line\r
- LOOPjz CX, @CB_Right_Done ; Exit Loop if Finished\r
- \r
- MOV AL, ES:[SI+BX] ; Load Latches\r
- MOV ES:[DI+BX], AL ; Unload Latches\r
- ADD BX, DX ; Advance Offset to Next Line\r
- LOOPx CX, @CB_Right_Loop ; Loop until Finished\r
- \r
-@CB_Right_Done:\r
- \r
- ; Copy the Main Block of the Bitmap\r
- \r
-@CB_Copy_Middle:\r
- \r
- MOV CX, [BP].CB_Width ; Get Width Remaining\r
- JCXZ @CB_Finish ; Exit if Done\r
- \r
- OUT_8 SC_Data, ALL_PLANES ; Copy all Planes\r
- \r
- MOV DX, SCREEN_WIDTH ; Get Width of Screen minus\r
- SUB DX, CX ; Image width (for Adjustment)\r
- MOV AX, [BP].CB_Height ; AX = # of Lines to Copy\r
- MOV BX, CX ; BX = Quick REP reload count\r
- MOV CX, ES ; Move VGA Segment\r
- MOV DS, CX ; Into DS\r
- \r
- ; Actual Copy Loop. REP MOVSB does the work\r
- \r
-@CB_Middle_Copy:\r
- MOV CX, BX ; Recharge Rep Count\r
- REP MOVSB ; Move Bands\r
- LOOPjz AX, @CB_Finish ; Exit Loop if Finished\r
- \r
- ADD SI, DX ; Adjust DS:SI to Next Line\r
- ADD DI, DX ; Adjust ES:DI to Next Line\r
- \r
- MOV CX, BX ; Recharge Rep Count\r
- REP MOVSB ; Move Bands\r
- \r
- ADD SI, DX ; Adjust DS:SI to Next Line\r
- ADD DI, DX ; Adjust ES:DI to Next Line\r
- LOOPx AX, @CB_Middle_Copy ; Copy Lines until Done\r
- \r
-@CB_Finish:\r
- OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = on\r
- \r
-@CB_Exit:\r
- ADD SP, 04 ; Deallocate stack workspace\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 16 ; Exit and Clean up Stack\r
- \r
-COPY_BITMAP ENDP\r
- \r
- END ; End of Code Segment\r
+++ /dev/null
- \r
- ' ===== SCREEN RESOLUTIONS =====\r
- \r
-CONST Mode320x200 = 0, Mode320x400 = 1\r
-CONST Mode360x200 = 2, Mode360x400 = 3\r
-CONST Mode320x240 = 4, Mode320x480 = 5\r
-CONST Mode360x240 = 6, Mode360x480 = 7\r
- \r
- ' ===== MODE X SETUP ROUTINES =====\r
- \r
-DECLARE FUNCTION SET.VGA.MODEX% ALIAS "SET_VGA_MODEX" (BYVAL ModeType%, BYVAL MaxXpos%, BYVAL MaxYpos%, BYVAL Pages%)\r
-DECLARE FUNCTION SET.MODEX% ALIAS "SET_MODEX" (BYVAL Mode%)\r
- \r
- ' ===== BASIC GRAPHICS PRIMITIVES =====\r
- \r
-DECLARE SUB CLEAR.VGA.SCREEN ALIAS "CLEAR_VGA_SCREEN" (BYVAL ColorNum%)\r
-DECLARE SUB SET.POINT ALIAS "SET_POINT" (BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorNum%)\r
-DECLARE FUNCTION READ.POINT% ALIAS "READ_POINT" (BYVAL Xpos%, BYVAL Ypos%)\r
-DECLARE SUB FILL.BLOCK ALIAS "FILL_BLOCK" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
-DECLARE SUB DRAW.LINE ALIAS "DRAW_LINE" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
- \r
- ' ===== DAC COLOR REGISTER ROUTINES =====\r
- \r
-DECLARE SUB SET.DAC.REGISTER ALIAS "SET_DAC_REGISTER" (BYVAL RegNo%, BYVAL Red%, BYVAL Green%, BYVAL Blue%)\r
-DECLARE SUB GET.DAC.REGISTER ALIAS "GET_DAC_REGISTER" (BYVAL RegNo%, Red%, Green%, Blue%)\r
-DECLARE SUB LOAD.DAC.REGISTERS ALIAS "LOAD_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%)\r
-DECLARE SUB READ.DAC.REGISTERS ALIAS "READ_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%)\r
- \r
- \r
- ' ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
- \r
-DECLARE SUB SET.ACTIVE.PAGE ALIAS "SET_ACTIVE_PAGE" (BYVAL PageNo%)\r
-DECLARE FUNCTION GET.ACTIVE.PAGE% ALIAS "GET_ACTIVE_PAGE"\r
-DECLARE SUB SET.DISPLAY.PAGE ALIAS "SET_DISPLAY_PAGE" (BYVAL PageNo%)\r
-DECLARE FUNCTION GET.DISPLAY.PAGE% ALIAS "GET_DISPLAY_PAGE"\r
-DECLARE SUB SET.WINDOW ALIAS "SET_WINDOW" (BYVAL DisplayPage%, BYVAL XOffset%, BYVAL YOffset%)\r
-DECLARE FUNCTION GET.X.OFFSET% ALIAS "GET_X_OFFSET" ()\r
-DECLARE FUNCTION GET.Y.OFFSET% ALIAS "GET_Y_OFFSET" ()\r
-DECLARE SUB SYNC.DISPLAY ALIAS "SYNC_DISPLAY"\r
- \r
- ' ===== TEXT DISPLAY ROUTINES =====\r
- \r
-DECLARE SUB GPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
-DECLARE SUB TGPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
-DECLARE SUB PRINT.STR ALIAS "PRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
-DECLARE SUB TPRINT.STR ALIAS "TPRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
-DECLARE SUB SET.DISPLAY.FONT ALIAS "SET_DISPLAY_FONT" (SEG FontData AS ANY, BYVAL FontNumber%)\r
- \r
- ' ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
- \r
-DECLARE SUB DRAW.BITMAP ALIAS "DRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
-DECLARE SUB TDRAW.BITMAP ALIAS "TDRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
- \r
- ' ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
- \r
-DECLARE SUB COPY.PAGE ALIAS "COPY_PAGE" (BYVAL SourcePage%, BYVAL DestPage%)\r
-DECLARE SUB COPY.BITMAP ALIAS "COPY_BITMAP" (BYVAL SourcePage%, BYVAL X1%, BYVAL Y1%, BYVAL X2%, BYVAL Y2%, BYVAL DestPage%, BYVAL DestX1%, BYVAL DestY1%)\r
- \r
- \r
- \r
- \r
- \r
- \r
+++ /dev/null
- \r
-#ifndef __MODEX_H\r
-#define __MODEX_H\r
- \r
- /* ===== SCREEN RESOLUTIONS ===== */\r
- \r
-#define Mode_320x200 0\r
-#define Mode_320x400 1\r
-#define Mode_360x200 2\r
-#define Mode_360x400 3\r
-#define Mode_320x240 4\r
-#define Mode_320x480 5\r
-#define Mode_360x240 6\r
-#define Mode_360x480 7\r
- \r
- /* ===== MODE X SETUP ROUTINES ===== */\r
- \r
-int far pascal set_vga_modex (int Mode, int MaxXpos, int MaxYpos, int Pages);\r
-int far pascal set_modex (int Mode);\r
- \r
- /* ===== BASIC GRAPHICS PRIMITIVES ===== */\r
- \r
-void far pascal clear_vga_screen (int Color);\r
-void far pascal set_point (int Xpos, int Ypos, int Color);\r
-int far pascal read_point (int Xpos, int Ypos);\r
-void far pascal fill_block (int Xpos1, int Ypos1, int Xpos2, int Ypos2,\r
- int Color);\r
-void far pascal draw_line (int Xpos1, int Ypos1, int Xpos2, int Ypos2,\r
- int Color);\r
- \r
- /* ===== DAC COLOR REGISTER ROUTINES ===== */\r
- \r
-void far pascal set_dac_register (int RegNo, int Red, int Green, int Blue);\r
-void far pascal get_dac_register (int RegNo, int* Red, int* Green, int* Blue);\r
-void far pascal load_dac_registers (char far *PalData, int StartReg,\r
- int EndReg, int VSync);\r
-void far pascal readd_dac_registers (char far *PalData, int StartReg,\r
- int EndReg);\r
- \r
- /* ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== */\r
- \r
-void far pascal set_active_page (int PageNo);\r
-int far pascal get_active_page (void);\r
-void far pascal set_display_page (int PageNo);\r
-int far pascal get_display_page (void);\r
-void far pascal set_window (int DisplayPage, int XOffset, int YOffset);\r
-int far pascal get_x_offset (void);\r
-int far pascal get_y_offset (void);\r
-void far pascal sync_display (void);\r
- \r
- /* ===== TEXT DISPLAY ROUTINES ===== */\r
- \r
-void far pascal gprintc (int CharNum, int Xpos, int Ypos, int ColorF,\r
- int ColorB);\r
-void far pascal tgprintc (int CharNum, int Xpos, int Ypos, int ColorF);\r
-void far pascal print_str (char far *Text, int MaxLen, int Xpos, int Ypos,\r
- int ColorF, int ColorB);\r
-void far pascal tprint_str (char far *Text, int MaxLen, int Xpos, int Ypos,\r
- int ColorF);\r
-void far pascal set_display_font (char far *FontData, int FontNumber);\r
- \r
- /* ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== */\r
- \r
-void far pascal draw_bitmap (char far *Image, int Xpos, int Ypos,\r
- int Width, int Height);\r
-void far pascal tdraw_bitmap (char far *Image, int Xpos, int Ypos,\r
- int Width, int Height);\r
- \r
- /* ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== */\r
- \r
-void far pascal copy_page (int SourcePage, int DestPage);\r
-void far pascal copy_bitmap (int SourcePage, int X1, int Y1, int X2, int Y2,\r
- int DestPage, int DestX1, int DestY1);\r
- \r
- \r
-#endif\r
+++ /dev/null
-jwASMr -0 -Zm c_utils, c_utils, c_utils, nul;
\ No newline at end of file
+++ /dev/null
-/* X-DEMO.C - a Mode "X" Demo */\r
-/* By Matt Pritchard, 14 Apr, 1993 */\r
-\r
-#include <stdlib.h>\r
-#include <stdio.h>\r
-\r
-#include "modex.h"\r
-#include "c_utils.h"\r
-\r
-#define MAX_SHAPES 32\r
-#define MAX_SPRITES 64\r
-\r
- /* routines in this file */\r
-\r
-void demo_res (int, int, int);\r
-int get_key (void);\r
-void error_out (char*);\r
-void load_shapes (void);\r
-int int_sqrt (int, int);\r
-void page_demo (void);\r
-\r
- /* Structures for Sprites */\r
-\r
-struct Shape\r
-{\r
- unsigned char Image[512];\r
- int X_Width;\r
- int Y_Width;\r
-} Img [MAX_SHAPES];\r
-\r
-struct Sprite\r
-{\r
- int X_pos;\r
- int Y_pos;\r
- int X_Dir;\r
- int Y_Dir;\r
- int Shape;\r
- int Last_X [2];\r
- int Last_Y [2];\r
-} Obj [MAX_SPRITES];\r
-\r
-\r
- /* MAIN */\r
-\r
-\r
-int main(int argc, char *argv[])\r
-{\r
-\r
- /* if (argc > 0)\r
- {\r
- while (argc > 0)\r
- {\r
- dos_print ("Unknown Argument: ");\r
- dos_print (makefp argv[argc]);\r
- argc--;\r
- }\r
- return (0);\r
-\r
- }\r
- */\r
-\r
- init_random ();\r
-\r
- load_shapes ();\r
-\r
- demo_res ( Mode_320x200, 320, 200 );\r
- demo_res ( Mode_320x400, 320, 400 );\r
-\r
- demo_res ( Mode_360x200, 360, 200 );\r
- demo_res ( Mode_360x400, 360, 400 );\r
-\r
- demo_res ( Mode_320x240, 320, 240 );\r
- demo_res ( Mode_320x480, 320, 480 );\r
-\r
- demo_res ( Mode_360x240, 360, 240 );\r
- demo_res ( Mode_360x480, 360, 480 );\r
-\r
- page_demo ();\r
-\r
- set_video_mode (3);\r
- dos_print ("This Mode X Demo is Finished");\r
- return (0);\r
-\r
-}\r
-\r
-\r
- /* Demonstrate a given resolution */\r
-\r
-\r
-void demo_res (int Screen_Mode, int X_max, int Y_max)\r
-{\r
-\r
-char *Error1 = "Failure while calling SET_MODEX";\r
-char *Error2 = "Failure during READ_PIXEL test";\r
-\r
-char *Abort_Msg = "Demo aborted by User";\r
-\r
-char *Demo_Msg = " This is a MODE X demo ";\r
-char *Scrn_Msg = "Screen Resolution is by ";\r
-char *Cont_Msg = "Press <ANY KEY> to Continue";\r
-\r
-char *Line_Msg = "LINE TEST";\r
-char *Fill_Msg = "FILL TEST";\r
-char *Pixel_Msg = "PIXEL TEST";\r
-\r
-char Text[10];\r
-\r
-int x1, y1, x2, y2 = 0;\r
-int x, y, z = 0;\r
-int X_Center, gap = 0;\r
-\r
-\r
- if (set_modex (Screen_Mode) == 0)\r
- {\r
- error_out (Error1);\r
- }\r
-\r
- X_Center = X_max / 2;\r
-\r
- x1 = 10;\r
- y1 = 10;\r
- x2 = X_max - 1;\r
- y2 = Y_max - 1;\r
-\r
- for (z = 0; z <= 3; z++)\r
- {\r
- y = 31 - z -z;\r
- draw_line (x1+z, y1+z, x2-z, y1+z, y);\r
- draw_line (x1+z, y1+z, x1+z, y2-z, y);\r
- draw_line (x1+z, y2-z, x2-z, y2-z, y);\r
- draw_line (x2-z, y1+z, x2-z, y2-z, y);\r
- }\r
-\r
- for (x = 0; x < (X_max / 10); x++)\r
- {\r
- tgprintc (48 + ((x+1) % 10), x*10+1, 1, 9 + ((x/8) % 7) );\r
- draw_line (x*10+9, 0, x*10+9, 3, c_bWHITE);\r
- }\r
-\r
- for (y = 0; y < (Y_max / 10); y++)\r
- {\r
- tgprintc (48 + ((y+1) % 10), 1, y*10+1, 9 + ((y/10) % 7) );\r
- draw_line (0, y*10+9, 3, y*10+9, c_bWHITE);\r
- }\r
-\r
- for (x = 0; x <= 63; x++)\r
- {\r
- z = 15 + (x * 3 / 4);\r
- set_dac_register (64+x, z, z, z);\r
- set_dac_register (128+x, 0, z, z);\r
-\r
- draw_line (103-x, 60, 40+x, 123, 64+x);\r
- draw_line (40, 60+x, 103, 123-x, 128+x);\r
-\r
- }\r
-\r
- tprint_str (Line_Msg, 9, 37, 130, c_BLUE);\r
-\r
- y = 60;\r
- gap = 0;\r
- for (x = 0; x <= 9; x++)\r
- {\r
- fill_block (120, y, 120+x, y+gap, 64+x);\r
- fill_block (140 - (15-x), y, 150+x, y+gap, 230+x);\r
- fill_block (170 - (15-x), y, 170, y+gap, 128+x);\r
- y = y + gap + 2;\r
- gap++;\r
- }\r
-\r
- tprint_str (Fill_Msg, 9, 110, 46, c_GREEN);\r
-\r
- for (x = 190; x <= 250; x+=2)\r
- {\r
- for (y = 60; y <= 122; y+=2)\r
- {\r
- z = (x+x+y+y) & 0xff;\r
- set_point (x, y, z);\r
- }\r
- }\r
-\r
- tprint_str (Pixel_Msg, 10, 182, 130, c_RED);\r
-\r
- for (x = 190; x <= 250; x+=2)\r
- {\r
- for (y = 60; y <= 122; y+=2)\r
- {\r
- z = (x+x+y+y) & 0xff;\r
- if (read_point(x, y) != z)\r
- {\r
- error_out (Error2);\r
- }\r
- }\r
- }\r
-\r
- print_str (Demo_Msg, 23, X_Center - 92, 20, c_bRED, c_BLUE);\r
-\r
- x = X_Center - 124;\r
- print_str (Scrn_Msg, 28, x, 30, c_bGREEN, c_BLACK);\r
-\r
- sprintf (Text, "%3d", X_max);\r
- print_str (Text, 3, x+168, 30, c_bPURPLE, c_BLACK);\r
-\r
- sprintf (Text, "%3d", Y_max);\r
- print_str (Text, 3, x + 224, 30, c_bWHITE, c_BLACK);\r
-\r
- for (x = 0; x <= 15; x++)\r
- {\r
- set_dac_register (230+x, 63-x*4, 0, 15+x*3);\r
- draw_line (30+x, Y_max-6-x, X_max-20-x, Y_max-6-x, 230+x);\r
- }\r
-\r
- tprint_str (Cont_Msg, 27, X_Center - 103, Y_max-18, c_YELLOW);\r
-\r
- if (get_key () == Ky_ESC)\r
- {\r
- error_out (Abort_Msg);\r
- }\r
-\r
- return ;\r
-\r
-}\r
-\r
-\r
- /* Wait for a Keystroke */\r
-\r
-\r
-int get_key(void)\r
-{\r
-\r
-int c = 0;\r
-\r
- while (c == 0)\r
- {\r
- c = scan_keyboard ();\r
- }\r
-\r
- return (c);\r
-\r
-}\r
-\r
-\r
- /* Error Handling Routine */\r
-\r
-\r
-void error_out (char * text)\r
-{\r
-\r
- set_video_mode (3);\r
- dos_print (text);\r
- exit (EXIT_SUCCESS);\r
-\r
-}\r
-\r
-\r
- /* Routine to generate random sprites */\r
-\r
-\r
-void load_shapes ()\r
-{\r
-\r
-unsigned char Grid[33][33];\r
-\r
-char *Error1 = "Bad Shape Selected Error";\r
-\r
-int Shape;\r
-int x, y, z;\r
-int Style, Color;\r
-int X_Width, Y_Width, Center, S_Width;\r
-int Hollow_X, Hollow_Y;\r
-\r
- for (Shape = 0; Shape < MAX_SHAPES; Shape++)\r
- {\r
- for (y = 0; y <= 32; y++)\r
- {\r
- for (x = 0; x <= 32; x++)\r
- {\r
- Grid[x][y] = c_BLACK;\r
- }\r
- }\r
-\r
- Style = random_int (6);\r
- Color = 1 + random_int (15);\r
-\r
- switch (Style)\r
-\r
- {\r
- /* SOLID BOXES */\r
-\r
- case 0:\r
-\r
- {\r
- do\r
- {\r
- X_Width = 3 + random_int(30);\r
- Y_Width = 3 + random_int(30);\r
-\r
- } while ( (X_Width * Y_Width) >= 512);\r
-\r
- for (x = 1; x <= X_Width; x++)\r
- {\r
- for (y = 1; y <= Y_Width; y++)\r
- {\r
- Grid[x][y] = Color;\r
- }\r
- }\r
-\r
- break;\r
-\r
- }\r
- /* HOLLOW BOXES */\r
-\r
- case 1:\r
-\r
- {\r
- do {\r
- X_Width = 6 + random_int(27);\r
- Y_Width = 6 + random_int(27);\r
- } while ( (X_Width * Y_Width) >= 512);\r
-\r
- for (y = 1; y <= Y_Width; y++)\r
- {\r
- for (x = 1; x <= X_Width; x++)\r
- {\r
- Grid[x][y] = Color;\r
- }\r
- }\r
-\r
- Hollow_X = 1 + random_int ((X_Width / 2) -1);\r
- Hollow_Y = 1 + random_int ((Y_Width / 2) -1);\r
-\r
- for (y = Hollow_Y+1; y <= Y_Width-Hollow_Y; y++)\r
- {\r
- for (x = Hollow_X+1; x <= X_Width-Hollow_X; x++)\r
- {\r
- Grid[x][y] = c_BLACK;\r
- }\r
- }\r
-\r
- break;\r
-\r
- }\r
-\r
- /* SOLID DIAMOND */\r
-\r
- case 2:\r
-\r
- {\r
-\r
- X_Width = 3 + 2 * random_int(10);\r
- Y_Width = X_Width;\r
- Center = X_Width / 2;\r
-\r
- for (y = 0; y <= Center; y++)\r
- {\r
- for (x = 0; x <= y; x++)\r
- {\r
- Grid [Center-x+1][y+1] = Color;\r
- Grid [Center+x+1][y+1] = Color;\r
- Grid [Center-x+1][Y_Width-y] = Color;\r
- Grid [Center+x+1][Y_Width-y] = Color;\r
- }\r
- }\r
-\r
- break;\r
-\r
- }\r
-\r
- /* HOLLOW DIAMOND */\r
-\r
- case 3:\r
-\r
- {\r
-\r
- X_Width = 3 + 2 * random_int(10);\r
- Y_Width = X_Width;\r
- Center = X_Width / 2;\r
- S_Width = random_int (Center);\r
-\r
- for (y = 0; y <= Center; y++)\r
- {\r
- for (x = 0; x <= y; x++)\r
- {\r
- if ( x+(Center-y) >= S_Width )\r
- {\r
- Grid [Center-x+1][y+1] = Color;\r
- Grid [Center+x+1][y+1] = Color;\r
- Grid [Center-x+1][Y_Width-y] = Color;\r
- Grid [Center+x+1][Y_Width-y] = Color;\r
- }\r
- }\r
- }\r
-\r
- break;\r
-\r
- }\r
-\r
- /* BALL */\r
-\r
- case 4:\r
-\r
- {\r
-\r
- X_Width = 7 + 2 * random_int (8);\r
- Y_Width = X_Width;\r
- Center = 1 + X_Width / 2;\r
-\r
- for (y = 1; y <= Y_Width; y++)\r
- {\r
- for (x = 1; x <= X_Width; x++)\r
- {\r
- z = int_sqrt(Center-x, Center-y);\r
- if (z < Center)\r
- {\r
- Grid[x][y] = 150 + Color * 2 + z * 3;\r
- }\r
- }\r
- }\r
-\r
- break;\r
- }\r
-\r
- /* HOLLOW BALLS */\r
-\r
- case 5:\r
-\r
- {\r
- X_Width = 7 + 2 * random_int (8);\r
- Y_Width = X_Width;\r
- Center = 1 + X_Width / 2;\r
- S_Width = random_int (X_Width);\r
-\r
- for (y = 1; y <= Y_Width; y++)\r
- {\r
- for (x = 1; x <= X_Width; x++)\r
- {\r
- z = int_sqrt(Center-x, Center-y);\r
- if ( (z < Center) && (z >= S_Width) )\r
- {\r
- Grid[x][y] = 150 + Color * 2 + z * 3;\r
- }\r
- }\r
- }\r
-\r
-\r
- break;\r
- }\r
-\r
- default:\r
-\r
- {\r
- error_out (Error1);\r
- break;\r
-\r
- }\r
-\r
- }\r
-\r
- z = 0;\r
- for (y = 1; y <= Y_Width; y++)\r
- {\r
- for (x = 1; x <= X_Width; x++)\r
- {\r
- Img[Shape].Image[z] = Grid[x][y];\r
- z++;\r
- }\r
- }\r
-\r
- Img[Shape].X_Width = X_Width;\r
- Img[Shape].Y_Width = Y_Width;\r
-\r
- }\r
-\r
- return;\r
-}\r
-\r
-\r
- /* Quickie Psuedo Integer Square Root Routine */\r
-\r
-\r
-int int_sqrt ( int x, int y )\r
-{\r
-\r
-int Sqr_Table[12] = {1, 4, 9, 6, 25, 36, 49, 64, 81, 100, 121, 144};\r
-\r
-int r, d;\r
-\r
- d = (x * x) + (y * y);\r
- r = 0;\r
-\r
- while ( d >= Sqr_Table[r] )\r
- {\r
- r++;\r
- }\r
-\r
- return (r);\r
-\r
-}\r
-\r
-\r
- /* The Bit Sprite Demo */\r
-\r
-\r
-void page_demo ()\r
-{\r
-\r
-char *Error1 = "Failure during SET_VGA_MODEX (0, 360, 240, 3) call";\r
-\r
-int Last_Objects[2], Visible_Objects;\r
-\r
-int Screen_X = 360;\r
-int Screen_Y = 240;\r
-\r
-int x, y, z;\r
-int c, dc;\r
-int x1, y1, x2, y2;\r
-\r
-int Sprite_X, Sprite_Y;\r
-int Current_Page;\r
-int New_X, New_Y;\r
-\r
-int View_X, View_Y, View_Max, View_Cnt, View_XD, View_YD;\r
-int Set_Color, Prev_Color, S_Dir, P_Dir;\r
-\r
-int Demo_Running = True;\r
-int redo, code;\r
-\r
- if (set_vga_modex(Mode_320x200, Screen_X, Screen_Y, 3) == 0)\r
- {\r
- error_out (Error1);\r
- }\r
-\r
- set_active_page (0);\r
- clear_vga_screen (c_BLACK);\r
-\r
- print_str ("This is a Test of the Following Functions:", 99, 10, 9, c_bWHITE, c_BLACK);\r
-\r
- draw_line (10, 18, 350, 18, c_YELLOW);\r
- print_str ("SET_ACTIVE_PAGE", 99, 10, 20, c_bBLUE, c_BLACK);\r
- print_str ("SET_DISPLAY_PAGE", 99, 10, 30, c_GREEN, c_BLACK);\r
- print_str ("SET_DAC_REGISTER", 99, 10, 40, c_RED, c_BLACK);\r
- print_str ("CLEAR_VGA_SCREEN", 99, 10, 50, c_CYAN, c_BLACK);\r
-\r
- print_str ("TDRAW_BITMAP", 99, 10, 60, c_PURPLE, c_BLACK);\r
- print_str ("COPY_PAGE", 99, 10, 70, c_GREEN, c_BLACK);\r
- print_str ("COPY_BITMAP", 99, 10, 80, c_CYAN, c_BLACK);\r
-\r
- print_str ("GPRINTC", 99, 10, 90, c_BLUE, c_BLACK);\r
- print_str ("TGPRINTC", 99, 10, 100, c_GREEN, c_BLACK);\r
- print_str ("SET_WINDOW", 99, 10, 110, c_RED, c_BLACK);\r
-\r
- print_str ("VIRTUAL SCREEN SIZES", 20, 190, 20, c_bBLUE, c_BLACK);\r
- print_str (" SMOOTH SCROLLING", 20, 190, 30, c_GREEN, c_BLACK);\r
- print_str (" SPRITE ANIMATION", 20, 190, 40, c_CYAN, c_BLACK);\r
- print_str (" PAGE FLIPPING", 20, 190, 50, c_RED, c_BLACK);\r
- print_str (" COLOR CYCLING", 20, 190, 60, c_PURPLE, c_BLACK);\r
-\r
- for (x = 0; x <=60; x++)\r
- {\r
- set_dac_register (50 + x, 3 + x, 0, 60 - x);\r
- set_dac_register (150 + x, 3 + x, 0, 60 - x);\r
- }\r
-\r
- c = 0;\r
- dc = 1;\r
- for (x = 0; x <= (Screen_X / 2); x++)\r
- {\r
- draw_line (Screen_X / 2 - 1, Screen_Y / 4, x, Screen_Y - 1, c + 50);\r
- draw_line (Screen_X / 2, Screen_Y / 4, Screen_X - x - 1, Screen_Y - 1, c + 50);\r
- c+= dc;\r
- if ((c == 0) || (c == 60) ) { dc = -dc;}\r
- }\r
-\r
- tprint_str ("Press <ANY KEY> to Continue", 99, 72, 190, c_bWHITE);\r
- tprint_str ("< > = Faster < > = Slower", 99, 72, 204, c_bGREEN);\r
- tprint_str ("< > = Fewer Shapes < > = More Shapes", 99, 32, 218, c_bCYAN);\r
-\r
- tgprintc (43, 80, 204, c_YELLOW);\r
- tgprintc (45, 200, 204, c_YELLOW);\r
-\r
- tgprintc (25, 40, 218, c_YELLOW);\r
- tgprintc (24, 200, 218, c_YELLOW);\r
-\r
- copy_page (0, 1);\r
- copy_page (0, 2);\r
-\r
- for (x = 0; x < MAX_SPRITES; x++)\r
- {\r
- do {\r
- Obj[x].X_Dir = random_int(7) - 3;\r
- Obj[x].Y_Dir = random_int(7) - 3;\r
- } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) );\r
-\r
- Obj[x].Shape = x % MAX_SHAPES;\r
-\r
- Sprite_X = Img[Obj[x].Shape].X_Width;\r
- Sprite_Y = Img[Obj[x].Shape].Y_Width;\r
-\r
- Obj[x].X_pos = 1 + random_int(Screen_X - Sprite_X - 2);\r
- Obj[x].Y_pos = 1 + random_int(Screen_Y - Sprite_Y - 2);\r
-\r
- Obj[x].Last_X[0] = Obj[x].X_pos;\r
- Obj[x].Last_X[1] = Obj[x].X_pos;\r
- Obj[x].Last_Y[0] = Obj[x].Y_pos;\r
- Obj[x].Last_Y[1] = Obj[x].Y_pos;\r
-\r
- }\r
-\r
- Current_Page = 0;\r
-\r
- View_X = 0;\r
- View_Y = 0;\r
- View_Max = 3;\r
- View_Cnt = 0;\r
- View_XD = 1;\r
- View_YD = 1;\r
-\r
- Set_Color = 3;\r
- S_Dir = 1;\r
- Prev_Color = 0;\r
- P_Dir = 1;\r
-\r
- Visible_Objects = MAX_SPRITES / 2;\r
- Last_Objects[0] = 0;\r
- Last_Objects[1] = 0;\r
-\r
- while (Demo_Running)\r
- {\r
-\r
- set_active_page (Current_Page);\r
-\r
- /* Erase Old Images */\r
-\r
- for (x = 0; x <= Last_Objects[Current_Page]; x++)\r
- {\r
- z = 2;\r
- y = Obj[x].Shape;\r
- x1 = Obj[x].Last_X[Current_Page];\r
- y1 = Obj[x].Last_Y[Current_Page];\r
- x2 = x1 + Img[y].X_Width -1;\r
- y2 = y1 + Img[y].Y_Width -1;\r
-\r
- x1 = x1 & 0xfffc;\r
- x2 = x2 | 0x0003;\r
-\r
- copy_bitmap (z, x1, y1, x2, y2, Current_Page, x1, y1);\r
- }\r
-\r
- /* Draw new images */\r
-\r
- for (x = 0; x <= Visible_Objects; x++)\r
- {\r
- Sprite_X = Img[Obj[x].Shape].X_Width;\r
- Sprite_Y = Img[Obj[x].Shape].Y_Width;\r
-\r
- /* Move Sprite */\r
-\r
- do\r
- {\r
- redo = False;\r
- New_X = Obj[x].X_pos + Obj[x].X_Dir;\r
-\r
- if (( New_X < 0 ) || (New_X + Sprite_X > Screen_X) )\r
- {\r
- Obj[x].X_Dir = -Obj[x].X_Dir;\r
- if (random_int(20) == 1)\r
- {\r
- do\r
- {\r
- Obj[x].X_Dir = random_int(7) - 3;\r
- Obj[x].Y_Dir = random_int(7) - 3;\r
- } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) );\r
- redo = True;\r
- }\r
- }\r
- } while (redo);\r
- Obj[x].X_pos = Obj[x].X_pos + Obj[x].X_Dir;\r
-\r
-\r
- do\r
- {\r
- redo = False;\r
- New_Y = Obj[x].Y_pos + Obj[x].Y_Dir;\r
-\r
- if ( (New_Y < 0) || (New_Y + Sprite_Y > Screen_Y) )\r
- {\r
- Obj[x].Y_Dir = -Obj[x].Y_Dir;\r
- if (random_int(20) == 1)\r
- {\r
- do\r
- {\r
- Obj[x].X_Dir = random_int(7) - 3;\r
- Obj[x].Y_Dir = random_int(7) - 3;\r
- } while ( (Obj[x].X_Dir == 0) && (Obj[x].Y_Dir == 0) );\r
- redo = True;\r
- }\r
- }\r
- } while (redo);\r
-\r
- Obj[x].Y_pos = Obj[x].Y_pos + Obj[x].Y_Dir;\r
-\r
- /* Draw Sprite */\r
-\r
- tdraw_bitmap ((char far*) &Img[Obj[x].Shape], Obj[x].X_pos, Obj[x].Y_pos, Sprite_X, Sprite_Y);\r
-\r
- Obj[x].Last_X[Current_Page] = Obj[x].X_pos;\r
- Obj[x].Last_Y[Current_Page] = Obj[x].Y_pos;\r
-\r
- }\r
-\r
- Last_Objects[Current_Page] = Visible_Objects;\r
-\r
-\r
- /* Pan Screen Back & Forth */\r
-\r
- View_Cnt++;\r
- if (View_Cnt >= View_Max)\r
- {\r
- View_X+= View_XD;\r
- if ( (View_X == 0) || (View_X == 39) ) {View_XD = -View_XD;}\r
- if (View_XD < 0)\r
- {\r
- View_Y+= View_YD;\r
- if ( (View_Y == 0) || (View_Y == 39) ) {View_YD = -View_YD;}\r
- }\r
-\r
- set_window (Current_Page, View_X, View_Y);\r
-\r
- View_Cnt = 0;\r
- }\r
- else\r
- {\r
- set_display_page (Current_Page);\r
- }\r
-\r
- /* Cycle Colors */\r
-\r
- set_dac_register (50 + Prev_Color, 3 + Prev_Color, 0, 60 - Prev_Color);\r
- set_dac_register (50 + Set_Color, Set_Color, 10, 63 - Set_Color);\r
-\r
- set_dac_register (150 + Prev_Color, 3 + Prev_Color, 0, 60 - Prev_Color);\r
- set_dac_register (150 + Set_Color, 63, 63, Set_Color);\r
-\r
- Set_Color+= S_Dir;\r
- if ( (Set_Color == 60) || (Set_Color == 0) ) {S_Dir = -S_Dir;}\r
-\r
- Prev_Color+= P_Dir;\r
- if ( (Prev_Color == 60) || (Prev_Color == 0) ) {P_Dir = -P_Dir;}\r
-\r
- /* Check for Keystroke */\r
-\r
- Current_Page = Current_Page ^ 0x01;\r
-\r
- code = scan_keyboard ();\r
-\r
- if (code == Ky_ESC) {Demo_Running = False;}\r
-\r
- if (code == Ky_Plus)\r
- {\r
- if (View_Max < 12) {View_Max++;}\r
- }\r
-\r
- if (code == Ky_Minus)\r
- {\r
- if (View_Max > 1) {View_Max--;}\r
- if (View_Cnt >= View_Max) {View_Cnt = 0;}\r
- }\r
-\r
- if (code == Ky_Up)\r
- {\r
- if (Visible_Objects < MAX_SPRITES-1) {Visible_Objects++;}\r
- }\r
-\r
- if (code == Ky_Down)\r
- {\r
- if (Visible_Objects > 0) {Visible_Objects--;}\r
- }\r
-\r
- }\r
-\r
-}\r
+++ /dev/null
-{ ModeX Turbo Pascal Demo Program }\r
-{ Converted to Turbo Pascal by Scott Wyatt }\r
-{ Original program written in QuickBasic by Matt Prichard }\r
-{ Released to the Public Domain }\r
-{ }\r
-{ Thanks to Matt Prichard for his *EXCELLENT* ModeX Library }\r
-{ Additional Comments by Matt Pritchard }\r
-\r
-Uses Crt;\r
-\r
-{$L modex2.obj} { This file is the external ModeX Library .OBJ }\r
-{$F+}\r
-\r
- { Mode Setting Routines }\r
-\r
-Function SET_VGA_MODEX (Mode,MaxXpos,MaxYpos,Pages : integer) : integer; external;\r
-Function SET_MODEX (Mode:integer) : Integer; external;\r
-\r
- { Graphics Primitives }\r
-\r
-Procedure CLEAR_VGA_SCREEN (Color:integer); external;\r
-Procedure SET_POINT (Xpos,Ypos,Color : integer); external;\r
-Function READ_POINT (Xpos,Ypos:integer) : integer; external;\r
-Procedure FILL_BLOCK (Xpos1,Ypos1,Xpos2,Ypos2,Color:integer); external;\r
-Procedure DRAW_LINE (Xpos1,Ypos1,Xpos2,Ypos2,Color:integer); external;\r
-\r
- { VGA DAC Routines }\r
-\r
-Procedure SET_DAC_REGISTER (RegNo,Red,Green,Blue:integer); external;\r
-Procedure GET_DAC_REGISTER (RegNo,Red,Green,Blue:integer); external;\r
-\r
- { Page and Window Control Routines }\r
-\r
-Procedure SET_ACTIVE_PAGE (PageNo:integer); external;\r
-Function GET_ACTIVE_PAGE : integer; external;\r
-Procedure SET_DISPLAY_PAGE (PageNo:integer); external;\r
-Function GET_DISPLAY_PAGE : integer; external;\r
-Procedure SET_WINDOW (DisplayPage,XOffset,YOffset : integer); external;\r
-Function GET_X_OFFSET : integer; external;\r
-Function GET_Y_OFFSET : integer; external;\r
-Procedure SYNC_DISPLAY; external;\r
-\r
- { Text Display Routines }\r
-\r
-Procedure GPRINTC (CharNum,Xpos,Ypos,ColorF,ColorB:integer); external;\r
-Procedure TGPRINTC ( CharNum,Xpos,Ypos,ColorF : integer); external;\r
-Procedure PRINT_STR (Var Text;MaxLen,Xpos,Ypos,ColorF,ColorB:integer); external;\r
-Procedure TPRINT_STR (Var Text;MaxLen,Xpos,Ypos,ColorF:integer); external;\r
-Procedure SET_DISPLAY_FONT (Var FontData;FontNumber:integer); external;\r
-\r
- { Sprite and VGA memory -> Vga memory Copy Routines }\r
-\r
-Procedure DRAW_BITMAP (Var Image;Xpos,Ypos,Width,Height:integer); external;\r
-Procedure TDRAW_BITMAP (Var Image;Xpos,Ypos,Width,Height:integer); external;\r
-Procedure COPY_PAGE (SourcePage,DestPage:integer); external;\r
-Procedure COPY_BITMAP (SourcePage,X1,Y1,X2,Y2,DestPage,DestX1,DestY1:integer); external;\r
-\r
-{$F-}\r
-\r
-\r
-TYPE Sprite = Record\r
- Xpos : INTEGER;\r
- Ypos : INTEGER;\r
- XDir : INTEGER;\r
- YDir : INTEGER;\r
- Shape : INTEGER;\r
- LastX : INTEGER;\r
- LastY : INTEGER;\r
- END;\r
-\r
-\r
-CONST MaxShapes = 32;\r
- Circle_16 : Array[1..16,1..16] of byte =\r
- (( 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0),\r
- ( 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0),\r
- ( 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0),\r
- ( 0, 0, 20, 20, 20, 20, 0, 0, 0, 0, 20, 20, 20, 20, 0, 0),\r
- ( 0, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 0),\r
- ( 0, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 0),\r
- ( 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20),\r
- ( 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20),\r
- ( 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20),\r
- ( 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20),\r
- ( 0, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 0),\r
- ( 0, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 0),\r
- ( 0, 0, 20, 20, 20, 20, 0, 0, 0, 0, 20, 20, 20, 20, 0, 0),\r
- ( 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0),\r
- ( 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0),\r
- ( 0, 0, 0, 0, 0, 0, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0));\r
- Square_16 : Array[1..16,1..16] of byte =\r
- (( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
- ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
- ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
- ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
- ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21),\r
- ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21),\r
- ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21),\r
- ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21),\r
- ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21),\r
- ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21),\r
- ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21),\r
- ( 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21),\r
- ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
- ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
- ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21),\r
- ( 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21));\r
- Diamond : Array[1..8,1..8] of byte =\r
- (( 0, 0, 0, 22, 22, 0, 0, 0),\r
- ( 0, 0, 22, 22, 22, 22, 0, 0),\r
- ( 0, 22, 22, 0, 0, 22, 22, 0),\r
- ( 22, 22, 0, 0, 0, 0, 22, 22),\r
- ( 22, 22, 0, 0, 0, 0, 22, 22),\r
- ( 0, 22, 22, 0, 0, 22, 22, 0),\r
- ( 0, 0, 22, 22, 22, 22, 0, 0),\r
- ( 0, 0, 0, 22, 22, 0, 0, 0));\r
- Rectangle : Array[1..8,1..3] of byte =\r
- (( 23, 23, 23),\r
- ( 23, 23, 23),\r
- ( 23, 23, 23),\r
- ( 23, 23, 23),\r
- ( 23, 23, 23),\r
- ( 23, 23, 23),\r
- ( 23, 23, 23),\r
- ( 23, 23, 23));\r
-\r
- { Global Variables ? }\r
-\r
-Var\r
- XCenter,X1,Y1,X2,Y2,Z,Colr,XChars,YChars,X,Y,N,Gap : Integer;\r
- s : string;\r
- s1 : Array[1..35] of Char;\r
- ch : Char;\r
- obj : Array[1..64] of Sprite;\r
- ScreenX,ScreenY : Integer;\r
- c, dc, SpriteX, SpriteY, CurrentPage, LastPage : Integer;\r
- SetColor, SDir, PrevColor, PDir : Byte;\r
- XView, YView : Integer;\r
- XView_Change, YView_Change : Integer;\r
- Right : Boolean;\r
- Number_Of_Shapes : Byte;\r
-\r
-\r
- { Error Handler - Returns to Text Mode & Displays Error }\r
-\r
-Procedure ERROR_OUT(s : string);\r
- Begin\r
- asm\r
- mov ah,0\r
- mov al,3\r
- int 10h\r
- end;\r
- WriteLn(s);\r
- Halt(0);\r
-END;\r
-\r
- { Routine to Print a PASCAL string using Print_Str }\r
-\r
-Procedure Print_Text(s : string; X,Y,BColor,FColor : integer);\r
-Var\r
- s1 : Array[1..135] of Char;\r
- i : byte;\r
-Begin\r
- For i := 1 to Length(s) DO\r
- s1[i] := s[i];\r
- Print_Str(s1,Length(s),X,Y,BColor,FColor);\r
-End;\r
-\r
- { Routine to Transparently Print a PASCAL string using TPrint_Str }\r
-\r
-Procedure TPrint_Text(s : string; X,Y,Color : integer);\r
-Var\r
- s1 : Array[1..135] of Char;\r
- i : byte;\r
-Begin\r
- For i := 1 to Length(s) DO\r
- s1[i] := s[i];\r
- TPrint_Str(s1,Length(s),X,Y,Color);\r
-End;\r
-\r
- { Routines to show test patterns for a given mode }\r
-\r
-Procedure Demo_Res(Mode, Xmax, Ymax : integer);\r
-Begin\r
-\r
- Str(mode,s);\r
- If Set_ModeX(Mode) = 0 Then\r
- Error_Out('Unable to SET_MODEX '+s);\r
- Clear_VGA_Screen(0);\r
-\r
- XCenter := Xmax div 2;\r
- X1 := 10;\r
- Y1 := 10;\r
- X2 := Xmax - 1;\r
- Y2 := Ymax - 1;\r
-\r
- FOR Z := 0 TO 3 DO\r
- Begin\r
- Colr := 31 - Z * 2;\r
- Draw_Line(X1 + Z, Y1 + Z, X2 - Z, Y1 + Z, Colr);\r
- Draw_Line(X1 + Z, Y1 + Z, X1 + Z, Y2 - Z, Colr);\r
- Draw_Line(X1 + Z, Y2 - Z, X2 - Z, Y2 - Z, Colr);\r
- Draw_Line(X2 - Z, Y1 + Z, X2 - Z, Y2 - Z, Colr);\r
- End;\r
-\r
- XChars := Xmax div 10;\r
- YChars := Ymax div 10;\r
-\r
- FOR X := 0 TO XChars - 1 DO\r
- Begin\r
- TGPRINTC(48 + ((X + 1) MOD 10), X * 10 + 1, 1, 9 + ((X div 8) MOD 7));\r
- DRAW_LINE(X * 10 + 9, 0, X * 10 + 9, 3, 15);\r
- End;\r
- FOR Y := 0 TO YChars - 1 DO\r
- Begin\r
- TGPRINTC(48 + ((Y + 1) MOD 10), 1, Y * 10 + 1, 9 + ((Y div 10) MOD 7));\r
- DRAW_LINE(0, Y * 10 + 9, 3, Y * 10 + 9, 15);\r
- End;\r
-\r
- { Test Line Drawing }\r
-\r
- FOR X := 0 TO 63 DO\r
- Begin\r
- N := 15 + ((X * 3) div 4);\r
- SET_DAC_REGISTER(64 + X, N, N, N);\r
- SET_DAC_REGISTER(128 + X, 0, N, N);\r
- DRAW_LINE(103 - X, 60, 40 + X, 123, 64 + X);\r
- DRAW_LINE(40, 60 + X, 103, 123 - X, 128 + X);\r
- End;\r
- s := 'Line Test';\r
- PRINT_Text(s,37,130,1,0);\r
-\r
- { Test Block Fills }\r
-\r
- Y := 60;\r
- Gap := 0;\r
- FOR X := 0 TO 9 DO\r
- Begin\r
- FILL_BLOCK(120, Y, 120 + X, Y + Gap, 64 + X);\r
- FILL_BLOCK(140 - (15 - X), Y, 150 + X, Y + Gap, 230 + X);\r
- FILL_BLOCK(170 - (15 - X), Y, 170, Y + Gap, 128 + X);\r
- Y := Y + Gap + 2;\r
- Gap := Gap + 1;\r
- End;\r
- s := 'Fill Test';\r
- Print_Text(s,110, 46, 2,0);\r
-\r
- { Test Pixel Write and Read }\r
-\r
- FOR X := 190 TO 250 DO\r
- FOR Y := 60 TO 122 DO\r
- SET_POINT( X, Y, X + Y + X + Y);\r
-\r
- s := 'Pixel Test';\r
- Print_Text(s,182, 130, 3,0);\r
-\r
- FOR X := 190 TO 250 DO\r
- FOR Y := 60 TO 122 DO\r
- IF READ_POINT(X, Y) <> ((X + Y + X + Y) AND 255) THEN\r
- WriteLn('READ_PIXEL Failure');\r
-\r
- { Display rest of screen }\r
-\r
- s := ' This is a MODE X demo ';\r
- Print_Text(s,XCenter - (Length(s) * 4), 20, 3, 1);\r
- s := 'Screen Resolution is by ';\r
- X := XCenter - (Length(s) * 4);\r
- Print_Text(s,X,30,4,0);\r
- Str(XMax,s);\r
- Print_Text(s, X + 8 * 21, 30, 8, 0);\r
- Str(YMax,s);\r
- Print_Text(s, X + 8 * 28, 30, 15, 0);\r
-\r
- FOR X := 0 TO 15 DO\r
- Begin\r
- SET_DAC_REGISTER( 230 + X, 63 - X * 4, 0, 15 + X * 3);\r
- DRAW_LINE(30 + X, Ymax - 6 - X, Xmax - 20 - X, Ymax - 6 - X, 230 + X);\r
- End;\r
- s := 'Press <ANY KEY> to Continue';\r
- For x := 1 to length(s) DO\r
- s1[x] := s[x];\r
- TPrint_Str(s1, length(s), XCenter - (26 * 4), Ymax - 18, 5);\r
-\r
- Ch := ReadKey;\r
- IF Ch = #27 Then\r
- Error_Out('Abort');\r
-\r
-End;\r
-\r
-\r
- { Initialize Sprites for Sprite Demo }\r
-\r
-Procedure Init_Sprites;\r
-Var i : byte;\r
-Begin\r
- For i := 1 to 64 DO\r
- Begin\r
- Obj[i].XPos := Random(300)+10;\r
- Obj[i].YPos := Random(200)+20;\r
- Obj[i].XDir := Random(10)-5;\r
- Obj[i].YDir := Random(10)-5;\r
- If (Obj[i].XDir = 0) AND (Obj[i].YDir = 0) Then\r
- Begin\r
- Obj[i].XDir := Random(5) + 1;\r
- Obj[i].YDir := Random(5) + 1;\r
- End;\r
- Obj[i].Shape := Random(4)+1;\r
- Obj[i].LastX := obj[i].XPos;\r
- Obj[i].LastY := obj[i].YPos;\r
- End;\r
-End;\r
-\r
-Procedure Set_Sprites(number : byte);\r
-Var i : Byte;\r
-Begin\r
- For i := 1 to number DO\r
- Begin\r
- obj[i].LastX := obj[i].XPos;\r
- obj[i].LastY := obj[i].YPos;\r
- obj[i].XPos := obj[i].XPos + obj[i].XDir;\r
- obj[i].YPos := obj[i].YPos + obj[i].YDir;\r
- If (obj[i].XPos > 335) OR (obj[i].XPos < 5 ) Then\r
- obj[i].XDir := -(obj[i].XDir);\r
- If (obj[i].YPos > 220) OR (obj[i].YPos < 5) Then\r
- obj[i].YDir := -(obj[i].YDir);\r
- End;\r
- For i := 1 to number DO\r
- Case obj[i].Shape of\r
- 1 : TDraw_Bitmap(Circle_16,obj[i].XPos,obj[i].YPos,16,16);\r
- 2 : TDraw_Bitmap(Square_16,obj[i].XPos,obj[i].YPos,16,16);\r
- 3 : TDraw_Bitmap(Diamond,obj[i].XPos,obj[i].YPos,8,8);\r
- 4 : TDraw_Bitmap(Rectangle,obj[i].XPos,obj[i].YPos,3,8);\r
- End;\r
-End;\r
-\r
-Procedure Remove_Sprites(p,number : byte);\r
-Var i : byte;\r
-Begin\r
- For i := 1 to number DO\r
- Copy_Bitmap(2,obj[i].LastX,obj[i].LastY,obj[i].LastX+16,obj[i].LastY+16,p,Obj[i].LastX,Obj[i].LastY);\r
-End;\r
-\r
-Procedure Page_Demo;\r
-Begin\r
- Number_Of_Shapes := 64;\r
- XView_Change := 1;\r
- YView_Change := 1;\r
- XView := 1;\r
- YView := 1;\r
- Right := TRUE;\r
- ScreenX := 360;\r
- ScreenY := 240;\r
- PrevColor := 0;\r
- SetColor := 3;\r
- SDir := 1;\r
- PDir := 1;\r
- Str(0,s);\r
-\r
- IF SET_VGA_MODEX(0, ScreenX, ScreenY, 3) = 0 THEN\r
- ERROR_OUT('Unable to SET_VGA_MODEX' + S);\r
-\r
- SET_ACTIVE_PAGE(0);\r
- CLEAR_VGA_SCREEN(0);\r
- PRINT_TEXT('This is a Test of the Following Functions:', 10, 9, 15, 0);\r
- DRAW_LINE( 10, 18, 350, 18, 4);\r
- Print_Text('SET_ACTIVE_PAGE', 10, 20, 1, 0);\r
- Print_Text('SET_DISPLAY_PAGE', 10, 30, 3,0);\r
- Print_Text('SET_DAC_REGISTER', 10, 40, 3, 0);\r
- Print_Text('CLEAR_VGA_SCREEN', 10, 50, 13, 0);\r
- Print_Text('TDRAW_BITMAP', 10, 60, 14, 0);\r
- Print_Text('COPY_PAGE', 10, 70, 3, 0);\r
- Print_Text('COPY_BITMAP', 10, 80, 13, 0);\r
- Print_Text('GPRINTC', 10, 90, 1, 0);\r
- Print_Text('TGPRINTC', 10, 100, 3, 0);\r
- Print_Text('SYNC_DISPLAY', 10, 110, 3, 0);\r
- Print_Text('SET_WINDOW', 10, 120, 14, 0);\r
- Print_Text('VIRTUAL SCREEN SIZES', 190, 20, 1, 0);\r
- Print_Text(' SMOOTH SCROLLING', 190, 30, 3, 0);\r
- Print_Text(' SPRITE ANIMATION', 190, 40, 13, 0);\r
- Print_Text(' PAGE FLIPPING', 190, 50, 3, 0);\r
- Print_Text(' COLOR CYCLING', 190, 60, 14, 0);\r
-\r
- FOR X := 0 TO 60 DO\r
- Begin\r
- SET_DAC_REGISTER( 50 + X, 3 + X, 0, 60 - X);\r
- SET_DAC_REGISTER( 150 + X, 3 + X, 0, 60 - X);\r
- End;\r
-\r
- c := 0;\r
- DC := 1;\r
- FOR X := 0 TO ScreenX div 2 DO\r
- Begin\r
- DRAW_LINE( ScreenX div 2 - 1, ScreenY div 4, X, ScreenY - 1, c + 50);\r
- DRAW_LINE( ScreenX div 2, ScreenY div 4, ScreenX - X - 1, ScreenY - 1, c + 50);\r
- c := c + DC;\r
- IF (c = 0) OR (c = 60) THEN DC := -DC;\r
- End;\r
-\r
- TPrint_Text('Press <ESC> to Continue', 82, 190, 15);\r
- TPrint_Text('<+> = Fewer Shapes <-> = More Shapes', 32, 204, 12);\r
- COPY_PAGE( 0, 1);\r
- COPY_PAGE( 0, 2);\r
-\r
- Ch := #0;\r
- CurrentPage := 1;\r
- LastPage := 0;\r
- Set_Sprites(Number_Of_Shapes);\r
- For c := 1 to 4 DO\r
- Set_Dac_Register(19+c,63-(c*10),0,0);\r
-\r
- While Ch <> #27 DO\r
- Begin\r
- Set_Active_Page(currentpage);\r
- Set_Sprites(Number_Of_Shapes);\r
- If Right Then\r
- Begin\r
- XView := XView + XView_Change;\r
- If (XView > 38) OR (XView < 2) Then\r
- Begin\r
- XView_Change := -(XView_Change);\r
- Right := FALSE;\r
- End;\r
- End\r
- Else\r
- Begin\r
- YView := YView + YView_Change;\r
- If (YView > 38) OR (YView < 2) Then\r
- Begin\r
- YView_Change := -(YView_Change);\r
- Right := TRUE;\r
- End;\r
- End;\r
-\r
- Set_Window(currentpage,XView,YView);\r
- Set_Display_Page(currentpage);\r
- Set_Dac_Register(50 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor);\r
- Set_Dac_Register(50 + SetColor, SetColor, 10, 63 - SetColor);\r
- Set_Dac_Register(150 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor);\r
- Set_Dac_Register(150 + SetColor, 63, 63, SetColor);\r
- SetColor := SetColor + SDir;\r
- IF (SetColor = 60) OR (SetColor = 0) THEN SDir := -SDir;\r
- PrevColor := PrevColor + PDir;\r
- IF (PrevColor = 60) OR (PrevColor = 0) THEN PDir := -PDir;\r
- Remove_Sprites(lastpage,Number_Of_Shapes);\r
-\r
- If Keypressed Then\r
- Begin\r
- Ch := ReadKey;\r
- Case Ch of\r
- '-' : If Number_Of_Shapes > 1 Then\r
- Begin\r
- c := Number_Of_Shapes;\r
- Copy_Bitmap(2,obj[c].XPos,obj[c].YPos,obj[c].XPos+16,obj[c].YPos+16,\r
- currentpage,obj[c].XPos,obj[c].YPos);\r
- Dec(Number_Of_Shapes);\r
- End;\r
- '+' : If Number_Of_Shapes < 64 Then Inc(Number_Of_Shapes);\r
- End;\r
- End;\r
- lastpage := (lastpage+1) MOD 2;\r
- currentpage := (currentpage+1) MOD 2;\r
- End;\r
-END;\r
-\r
- { MAIN ROUTINE - Run Through Demos and Exit }\r
-\r
-Begin\r
-\r
- Randomize;\r
- Init_Sprites;\r
-\r
- Demo_Res(0, 320, 200);\r
- Demo_Res(1, 320, 400);\r
- Demo_Res(2, 360, 200);\r
- Demo_Res(3, 360, 400);\r
- Demo_Res(4, 320, 240);\r
- Demo_Res(5, 320, 480);\r
- Demo_Res(6, 360, 240);\r
- Demo_Res(7, 360, 480);\r
- Page_Demo;\r
-\r
- asm\r
- mov ah,0\r
- mov al,3\r
- int 10h\r
- end;\r
- WriteLn('THIS MODE X DEMO IS FINISHED');\r
-\r
-END.
\ No newline at end of file
+++ /dev/null
-ECHO ... Building MODEX.QLB for QUICKBASIC 4.5\r
-LIB MODEX -+MODEX,,\r
-LIB MODEX -+UTILS,,\r
-DEL MODEX.BAK\r
-LINK /Q MODEX+UTILS, MODEX.QLB, NUL, C:\QB45\BQLB45.LIB;\1a\r
+++ /dev/null
- \r
- ' ===== SCREEN RESOLUTIONS =====\r
- \r
-CONST Mode320x200 = 0, Mode320x400 = 1\r
-CONST Mode360x200 = 2, Mode360x400 = 3\r
-CONST Mode320x240 = 4, Mode320x480 = 5\r
-CONST Mode360x240 = 6, Mode360x480 = 7\r
- \r
- ' ===== MODE X SETUP ROUTINES =====\r
- \r
-DECLARE FUNCTION SET.VGA.MODEX% ALIAS "SET_VGA_MODEX" (BYVAL ModeType%, BYVAL MaxXpos%, BYVAL MaxYpos%, BYVAL Pages%)\r
-DECLARE FUNCTION SET.MODEX% ALIAS "SET_MODEX" (BYVAL Mode%)\r
- \r
- ' ===== BASIC GRAPHICS PRIMITIVES =====\r
- \r
-DECLARE SUB CLEAR.VGA.SCREEN ALIAS "CLEAR_VGA_SCREEN" (BYVAL ColorNum%)\r
-DECLARE SUB SET.POINT ALIAS "SET_POINT" (BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorNum%)\r
-DECLARE FUNCTION READ.POINT% ALIAS "READ_POINT" (BYVAL Xpos%, BYVAL Ypos%)\r
-DECLARE SUB FILL.BLOCK ALIAS "FILL_BLOCK" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
-DECLARE SUB DRAW.LINE ALIAS "DRAW_LINE" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
- \r
- ' ===== DAC COLOR REGISTER ROUTINES =====\r
- \r
-DECLARE SUB SET.DAC.REGISTER ALIAS "SET_DAC_REGISTER" (BYVAL RegNo%, BYVAL Red%, BYVAL Green%, BYVAL Blue%)\r
-DECLARE SUB GET.DAC.REGISTER ALIAS "GET_DAC_REGISTER" (BYVAL RegNo%, Red%, Green%, Blue%)\r
-DECLARE SUB LOAD.DAC.REGISTERS ALIAS "LOAD_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%)\r
-DECLARE SUB READ.DAC.REGISTERS ALIAS "READ_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%)\r
- \r
- \r
- ' ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
- \r
-DECLARE SUB SET.ACTIVE.PAGE ALIAS "SET_ACTIVE_PAGE" (BYVAL PageNo%)\r
-DECLARE FUNCTION GET.ACTIVE.PAGE% ALIAS "GET_ACTIVE_PAGE"\r
-DECLARE SUB SET.DISPLAY.PAGE ALIAS "SET_DISPLAY_PAGE" (BYVAL PageNo%)\r
-DECLARE FUNCTION GET.DISPLAY.PAGE% ALIAS "GET_DISPLAY_PAGE"\r
-DECLARE SUB SET.WINDOW ALIAS "SET_WINDOW" (BYVAL DisplayPage%, BYVAL XOffset%, BYVAL YOffset%)\r
-DECLARE FUNCTION GET.X.OFFSET% ALIAS "GET_X_OFFSET" ()\r
-DECLARE FUNCTION GET.Y.OFFSET% ALIAS "GET_Y_OFFSET" ()\r
-DECLARE SUB SYNC.DISPLAY ALIAS "SYNC_DISPLAY"\r
- \r
- ' ===== TEXT DISPLAY ROUTINES =====\r
- \r
-DECLARE SUB GPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
-DECLARE SUB TGPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
-DECLARE SUB PRINT.STR ALIAS "PRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
-DECLARE SUB TPRINT.STR ALIAS "TPRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
-DECLARE SUB SET.DISPLAY.FONT ALIAS "SET_DISPLAY_FONT" (SEG FontData AS ANY, BYVAL FontNumber%)\r
- \r
- ' ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
- \r
-DECLARE SUB DRAW.BITMAP ALIAS "DRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
-DECLARE SUB TDRAW.BITMAP ALIAS "TDRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
- \r
- ' ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
- \r
-DECLARE SUB COPY.PAGE ALIAS "COPY_PAGE" (BYVAL SourcePage%, BYVAL DestPage%)\r
-DECLARE SUB COPY.BITMAP ALIAS "COPY_BITMAP" (BYVAL SourcePage%, BYVAL X1%, BYVAL Y1%, BYVAL X2%, BYVAL Y2%, BYVAL DestPage%, BYVAL DestX1%, BYVAL DestY1%)\r
- \r
- \r
- \r
- \r
- \r
- \r
+++ /dev/null
-'File: TEST6A.BAS\r
-'Descp.: A Mode "X" demonstration for Quickbasic 4.5\r
-'Author: Matt Pritchard\r
-'Date: 14 April, 1993\r
-'\r
-DECLARE SUB DEMO.RES (Mode%, Xmax%, Ymax%)\r
-DECLARE SUB ERROR.OUT (Message$)\r
-DECLARE FUNCTION GET.KEY% ()\r
-DECLARE SUB LOAD.SHAPES ()\r
-DECLARE SUB PAGE.DEMO ()\r
-DECLARE SUB PRINT.TEXT (Text$, Xpos%, Ypos%, ColorF%, ColorB%)\r
-DECLARE SUB TPRINT.TEXT (Text$, Xpos%, Ypos%, ColorF%)\r
-DEFINT A-Z\r
-\r
-\r
-TYPE ShapeType\r
- ImgData AS STRING * 512\r
- xWidth AS INTEGER\r
- yWidth AS INTEGER\r
-END TYPE\r
-\r
-TYPE Sprite\r
- Xpos AS INTEGER\r
- Ypos AS INTEGER\r
- XDir AS INTEGER\r
- YDir AS INTEGER\r
- Shape AS INTEGER\r
-END TYPE\r
-\r
-\r
-CONST MaxShapes = 32\r
-\r
- REM $INCLUDE: 'UTILS.BI'\r
- REM $INCLUDE: 'MODEX.BI'\r
-\r
-DIM SHARED Img(32) AS ShapeType\r
-COMMON SHARED Img() AS ShapeType\r
-\r
-\r
- CALL INIT.RANDOM\r
-\r
- CALL LOAD.SHAPES\r
-\r
- CALL DEMO.RES(Mode320x200, 320, 200)\r
- CALL DEMO.RES(Mode320x400, 320, 400)\r
-\r
- CALL DEMO.RES(Mode360x200, 360, 200)\r
- CALL DEMO.RES(Mode360x400, 360, 400)\r
-\r
- CALL DEMO.RES(Mode320x240, 320, 240)\r
- CALL DEMO.RES(Mode320x480, 320, 480)\r
-\r
- CALL DEMO.RES(Mode360x240, 360, 240)\r
- CALL DEMO.RES(Mode360x480, 360, 480)\r
-\r
- CALL PAGE.DEMO\r
-\r
- SET.VIDEO.MODE 3\r
- DOS.PRINT "THIS MODE X DEMO IS FINISHED"\r
- END\r
-\r
-SUB DEMO.RES (Mode, Xmax, Ymax)\r
-\r
- IF SET.MODEX%(Mode) = 0 THEN\r
- ERROR.OUT "Unable to SET_MODEX" + STR$(Mode)\r
- END IF\r
-\r
- XCenter = Xmax \ 2\r
- \r
- X1 = 10\r
- Y1 = 10\r
- X2 = Xmax - 1\r
- Y2 = Ymax - 1\r
-\r
- FOR Z = 0 TO 3\r
- Colr = 31 - Z * 2\r
- DRAW.LINE X1 + Z, Y1 + Z, X2 - Z, Y1 + Z, Colr\r
- DRAW.LINE X1 + Z, Y1 + Z, X1 + Z, Y2 - Z, Colr\r
- DRAW.LINE X1 + Z, Y2 - Z, X2 - Z, Y2 - Z, Colr\r
- DRAW.LINE X2 - Z, Y1 + Z, X2 - Z, Y2 - Z, Colr\r
- NEXT Z\r
-\r
- XChars = Xmax \ 10\r
- YChars = Ymax \ 10\r
-\r
- FOR X = 0 TO XChars - 1\r
- TGPRINTC 48 + ((X + 1) MOD 10), X * 10 + 1, 1, 9 + ((X \ 8) MOD 7)\r
- DRAW.LINE X * 10 + 9, 0, X * 10 + 9, 3, 15\r
- NEXT X\r
-\r
- FOR Y = 0 TO YChars - 1\r
- TGPRINTC 48 + ((Y + 1) MOD 10), 1, Y * 10 + 1, 9 + ((Y \ 10) MOD 7)\r
- DRAW.LINE 0, Y * 10 + 9, 3, Y * 10 + 9, 15\r
- NEXT Y\r
-\r
- ' Draw Lines\r
-\r
- FOR X = 0 TO 63\r
- N = 15 + X * .75\r
- SET.DAC.REGISTER 64 + X, N, N, N\r
- SET.DAC.REGISTER 128 + X, 0, N, N\r
-\r
- DRAW.LINE 103 - X, 60, 40 + X, 123, 64 + X\r
- DRAW.LINE 40, 60 + X, 103, 123 - X, 128 + X\r
-\r
- NEXT X\r
- TPRINT.TEXT "LINE TEST", 37, 130, c.BLUE\r
-\r
- Y = 60: Gap = 0\r
- FOR X = 0 TO 9\r
- FILL.BLOCK 120, Y, 120 + X, Y + Gap, 64 + X\r
- FILL.BLOCK 140 - (15 - X), Y, 150 + X, Y + Gap, 230 + X\r
- FILL.BLOCK 170 - (15 - X), Y, 170, Y + Gap, 128 + X\r
- Y = Y + Gap + 2\r
- Gap = Gap + 1\r
- NEXT X\r
- TPRINT.TEXT "FILL TEST", 110, 46, c.GREEN\r
-\r
-\r
- FOR X = 190 TO 250 STEP 2\r
- FOR Y = 60 TO 122 STEP 2\r
- SET.POINT X, Y, X + Y + X + Y\r
- NEXT Y\r
- NEXT X\r
-\r
- TPRINT.TEXT "PIXEL TEST", 182, 130, c.RED\r
-\r
- FOR X = 190 TO 250 STEP 2\r
- FOR Y = 60 TO 122 STEP 2\r
- IF READ.POINT(X, Y) <> ((X + Y + X + Y) AND 255) THEN\r
- ERROR.OUT "READ.PIXEL Failure"\r
- END IF\r
- NEXT Y\r
- NEXT X\r
-\r
-\r
-\r
- Msg$ = " This is a MODE X demo "\r
- PRINT.TEXT Msg$, XCenter - (LEN(Msg$) * 4), 20, c.bRED, c.BLUE\r
- Msg$ = "Screen Resolution is by "\r
- Xp = XCenter - (LEN(Msg$) * 4)\r
- PRINT.TEXT Msg$, Xp, 30, c.bGREEN, c.BLACK\r
-\r
- PRINT.TEXT LTRIM$(STR$(Xmax)), Xp + 8 * 21, 30, c.bPURPLE, c.BLACK\r
- PRINT.TEXT LTRIM$(STR$(Ymax)), Xp + 8 * 28, 30, c.bWHITE, c.BLACK\r
-\r
- FOR X = 0 TO 15\r
- SET.DAC.REGISTER 230 + X, 63 - X * 4, 0, 15 + X * 3\r
- DRAW.LINE 30 + X, Ymax - 6 - X, Xmax - 20 - X, Ymax - 6 - X, 230 + X\r
- NEXT X\r
- TPRINT.TEXT "Press <ANY KEY> to Continue", XCenter - (26 * 4), Ymax - 18, c.YELLOW\r
-\r
- X = GET.KEY%\r
- IF X = KyESC THEN ERROR.OUT "ABORT"\r
-\r
-END SUB\r
-\r
-SUB ERROR.OUT (Message$)\r
-\r
- SET.VIDEO.MODE 3\r
- DOS.PRINT Message$\r
- END\r
-\r
-END SUB\r
-\r
-FUNCTION GET.KEY%\r
-\r
- DO\r
- X = SCAN.KEYBOARD\r
- LOOP UNTIL X\r
-\r
- GET.KEY% = X\r
-\r
-END FUNCTION\r
-\r
-SUB LOAD.SHAPES\r
-\r
-DIM Grid(1 TO 32, 1 TO 32)\r
-\r
- FOR Shape = 0 TO MaxShapes - 1\r
-\r
- FOR Y = 1 TO 32\r
- FOR X = 1 TO 32\r
- Grid(X, Y) = 0\r
- NEXT X\r
- NEXT Y\r
-\r
- Style = RANDOM.INT(6)\r
- Colour = 1 + RANDOM.INT(15)\r
- \r
- SELECT CASE Style\r
-\r
- CASE 0: ' Solid Box\r
-\r
- DO\r
- xWidth = 3 + RANDOM.INT(30)\r
- yWidth = 3 + RANDOM.INT(30)\r
- LOOP UNTIL ((xWidth * yWidth) <= 512)\r
-\r
- FOR Y = 1 TO yWidth\r
- FOR X = 1 TO xWidth\r
- Grid(X, Y) = Colour\r
- NEXT X\r
- NEXT Y\r
-\r
- CASE 1: ' Hollow Box\r
-\r
- DO\r
- xWidth = 5 + RANDOM.INT(28)\r
- yWidth = 5 + RANDOM.INT(28)\r
- LOOP UNTIL ((xWidth * yWidth) <= 512)\r
-\r
- FOR Y = 1 TO yWidth\r
- FOR X = 1 TO xWidth\r
- Grid(X, Y) = Colour\r
- NEXT X\r
- NEXT Y\r
-\r
- HollowX = 1 + RANDOM.INT(xWidth \ 2 - 1)\r
- HollowY = 1 + RANDOM.INT(yWidth \ 2 - 1)\r
-\r
- FOR Y = HollowY + 1 TO yWidth - HollowY\r
- FOR X = HollowX + 1 TO xWidth - HollowX\r
- Grid(X, Y) = nil\r
- NEXT X\r
- NEXT Y\r
-\r
- CASE 2: ' Solid Diamond\r
-\r
- xWidth = 3 + 2 * RANDOM.INT(10)\r
- yWidth = xWidth\r
- Centre = xWidth \ 2\r
-\r
- FOR Y = 0 TO Centre\r
- FOR X = 0 TO Y\r
- Grid(Centre - X + 1, Y + 1) = Colour\r
- Grid(Centre + X + 1, Y + 1) = Colour\r
- Grid(Centre - X + 1, yWidth - Y) = Colour\r
- Grid(Centre + X + 1, yWidth - Y) = Colour\r
- NEXT X\r
- NEXT Y\r
-\r
-\r
- CASE 3: ' Hollow Diamond\r
-\r
-\r
- xWidth = 3 + 2 * RANDOM.INT(10)\r
- yWidth = xWidth\r
- Centre = xWidth \ 2\r
- sWidth = RANDOM.INT(Centre)\r
-\r
- FOR Y = 0 TO Centre\r
- FOR X = 0 TO Y\r
- IF X + (Centre - Y) >= sWidth THEN\r
- Grid(Centre - X + 1, Y + 1) = Colour\r
- Grid(Centre + X + 1, Y + 1) = Colour\r
- Grid(Centre - X + 1, yWidth - Y) = Colour\r
- Grid(Centre + X + 1, yWidth - Y) = Colour\r
- END IF\r
- NEXT X\r
- NEXT Y\r
-\r
- CASE 4: ' Ball\r
-\r
- xWidth = 7 + 2 * RANDOM.INT(8)\r
- yWidth = xWidth\r
- Centre = 1 + xWidth \ 2\r
-\r
- FOR Y = 1 TO yWidth\r
- FOR X = 1 TO xWidth\r
- D = SQR(((Centre - X) * (Centre - X)) + ((Centre - Y) * (Centre - Y)))\r
- IF D < Centre THEN Grid(X, Y) = 150 + Colour * 2 + D * 3\r
- NEXT X\r
- NEXT Y\r
-\r
- CASE 5: ' Ball\r
-\r
-\r
- xWidth = 7 + 2 * RANDOM.INT(8)\r
- yWidth = xWidth\r
- Centre = 1 + xWidth \ 2\r
- sWidth = RANDOM.INT(xWidth)\r
-\r
- FOR Y = 1 TO yWidth\r
- FOR X = 1 TO xWidth\r
- D = SQR(((Centre - X) * (Centre - X)) + ((Centre - Y) * (Centre - Y)))\r
- IF D < Centre AND D >= sWidth THEN Grid(X, Y) = 150 + Colour * 2 + D * 3\r
- NEXT X\r
- NEXT Y\r
-\r
- END SELECT\r
-\r
- Img(Shape).xWidth = xWidth\r
- Img(Shape).yWidth = yWidth\r
-\r
- A$ = STRING$(xWidth * yWidth, nil)\r
-\r
- c = 1\r
- FOR Y = 1 TO yWidth\r
- FOR X = 1 TO xWidth\r
- MID$(A$, c, 1) = CHR$(Grid(X, Y))\r
- c = c + 1\r
- NEXT X\r
- NEXT Y\r
-\r
- Img(Shape).ImgData = A$\r
- \r
-\r
- NEXT Shape\r
-\r
-END SUB\r
-\r
-SUB PAGE.DEMO\r
-\r
-CONST MaxSprites = 64\r
-\r
-DIM Obj(MaxSprites) AS Sprite\r
-DIM LastX(MaxSprites, 1), LastY(MaxSprites, 1)\r
-DIM LastObjects(1)\r
-\r
- ScreenX = 360: ScreenY = 240\r
-\r
- IF SET.VGA.MODEX%(Mode320x200, ScreenX, ScreenY, 3) = 0 THEN\r
- ERROR.OUT "Unable to SET_VGA_MODEX" + STR$(Mode)\r
- END IF\r
-\r
- SET.ACTIVE.PAGE 0\r
-\r
- CLEAR.VGA.SCREEN c.BLACK\r
- \r
- PRINT.TEXT "This is a Test of the Following Functions:", 10, 9, c.bWHITE, c.BLACK\r
-\r
- DRAW.LINE 10, 18, 350, 18, c.YELLOW\r
- PRINT.TEXT "SET_ACTIVE_PAGE", 10, 20, c.bBLUE, c.BLACK\r
- PRINT.TEXT "SET_DISPLAY_PAGE", 10, 30, c.GREEN, c.BLACK\r
- PRINT.TEXT "SET_DAC_REGISTER", 10, 40, c.RED, c.BLACK\r
- PRINT.TEXT "CLEAR_VGA_SCREEN", 10, 50, c.CYAN, c.BLACK\r
-\r
- PRINT.TEXT "TDRAW_BITMAP", 10, 60, c.PURPLE, c.BLACK\r
- PRINT.TEXT "COPY_PAGE", 10, 70, c.GREEN, c.BLACK\r
- PRINT.TEXT "COPY_BITMAP", 10, 80, c.CYAN, c.BLACK\r
-\r
- PRINT.TEXT "GPRINTC", 10, 90, c.BLUE, c.BLACK\r
- PRINT.TEXT "TGPRINTC", 10, 100, c.GREEN, c.BLACK\r
- PRINT.TEXT "SET_WINDOW", 10, 110, c.RED, c.BLACK\r
-\r
- PRINT.TEXT "VIRTUAL SCREEN SIZES", 190, 20, c.bBLUE, c.BLACK\r
- PRINT.TEXT " SMOOTH SCROLLING", 190, 30, c.GREEN, c.BLACK\r
- PRINT.TEXT " SPRITE ANIMATION", 190, 40, c.CYAN, c.BLACK\r
- PRINT.TEXT " PAGE FLIPPING", 190, 50, c.RED, c.BLACK\r
- PRINT.TEXT " COLOR CYCLING", 190, 60, c.PURPLE, c.BLACK\r
-\r
-\r
- FOR X = 0 TO 60\r
- SET.DAC.REGISTER 50 + X, 3 + X, 0, 60 - X\r
- SET.DAC.REGISTER 150 + X, 3 + X, 0, 60 - X\r
- NEXT X\r
-\r
- c = 0: DC = 1\r
- FOR X = 0 TO ScreenX \ 2\r
- DRAW.LINE ScreenX \ 2 - 1, ScreenY \ 4, X, ScreenY - 1, c + 50\r
- DRAW.LINE ScreenX \ 2, ScreenY \ 4, ScreenX - X - 1, ScreenY - 1, c + 50\r
- c = c + DC\r
- IF c = 0 OR c = 60 THEN DC = -DC\r
- NEXT X\r
- \r
- TPRINT.TEXT "Press <ANY KEY> to Continue", 72, 190, c.bWHITE\r
- TPRINT.TEXT "< > = Faster < > = Slower", 72, 204, c.bGREEN\r
- TPRINT.TEXT "< > = Fewer Shapes < > = More Shapes", 32, 218, c.bCYAN\r
-\r
- TGPRINTC 43, 80, 204, c.YELLOW\r
- TGPRINTC 45, 200, 204, c.YELLOW\r
-\r
- TGPRINTC 25, 40, 218, c.YELLOW\r
- TGPRINTC 24, 200, 218, c.YELLOW\r
-\r
- COPY.PAGE 0, 1\r
- COPY.PAGE 0, 2\r
-\r
- FOR X = 1 TO MaxSprites\r
- DO\r
- Obj(X).XDir = RANDOM.INT(7) - 3\r
- Obj(X).YDir = RANDOM.INT(7) - 3\r
- LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
-\r
- Obj(X).Shape = X MOD MaxShapes\r
-\r
- SpriteX = Img(Obj(X).Shape).xWidth\r
- SpriteY = Img(Obj(X).Shape).yWidth\r
-\r
- Obj(X).Xpos = 1 + RANDOM.INT(ScreenX - SpriteX - 2)\r
- Obj(X).Ypos = 1 + RANDOM.INT(ScreenY - SpriteY - 2)\r
-\r
- LastX(X, 0) = Obj(X).Xpos\r
- LastX(X, 1) = Obj(X).Xpos\r
- LastY(X, 0) = Obj(X).Ypos\r
- LastY(X, 1) = Obj(X).Ypos\r
- NEXT X\r
-\r
- CurrentPage = 0\r
-\r
- 'View Shift...\r
-\r
- ViewX = 0\r
- ViewY = 0\r
- ViewMax = 3\r
- ViewCnt = 0\r
- ViewXD = 1\r
- ViewYD = 1\r
-\r
- SetColor = 3: SDir = 1\r
- PrevColor = 0: PDir = 1\r
-\r
- VisObjects = MaxSprites \ 2\r
- LastObjects(0) = 0\r
- LastObjects(1) = 0\r
-\r
-DRAW.LOOP:\r
-\r
-\r
- SET.ACTIVE.PAGE CurrentPage\r
-\r
- ' Erase Old Images\r
-\r
- FOR X = 1 TO LastObjects(CurrentPage)\r
- \r
- X1 = LastX(X, CurrentPage) AND &HFFFC\r
- Y1 = LastY(X, CurrentPage)\r
- X2 = ((LastX(X, CurrentPage) + Img(Obj(X).Shape).xWidth)) OR 3\r
- Y2 = Y1 + Img(Obj(X).Shape).yWidth - 1\r
-\r
- COPY.BITMAP 2, X1, Y1, X2, Y2, CurrentPage, X1, Y1\r
- \r
- NEXT X\r
-\r
- ' Draw new images\r
-\r
- FOR X = 1 TO VisObjects\r
-\r
- SpriteX = Img(Obj(X).Shape).xWidth\r
- SpriteY = Img(Obj(X).Shape).yWidth\r
-\r
- ' Move Sprite\r
-\r
-REDOX:\r
- NewX = Obj(X).Xpos + Obj(X).XDir\r
- IF NewX < 0 OR NewX + SpriteX > ScreenX THEN\r
- Obj(X).XDir = -Obj(X).XDir\r
- IF RANDOM.INT(20) = 1 THEN\r
- DO\r
- Obj(X).XDir = RANDOM.INT(7) - 3\r
- Obj(X).YDir = RANDOM.INT(7) - 3\r
- LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
- GOTO REDOX\r
- END IF\r
- END IF\r
- Obj(X).Xpos = Obj(X).Xpos + Obj(X).XDir\r
-\r
-REDOY:\r
- NewY = Obj(X).Ypos + Obj(X).YDir\r
- IF NewY < 0 OR NewY + SpriteY > ScreenY THEN\r
- Obj(X).YDir = -Obj(X).YDir\r
- IF RANDOM.INT(20) = 1 THEN\r
- DO\r
- Obj(X).XDir = RANDOM.INT(7) - 3\r
- Obj(X).YDir = RANDOM.INT(7) - 3\r
- LOOP WHILE (Obj(X).XDir = 0 AND Obj(X).YDir = 0)\r
- GOTO REDOY\r
- END IF\r
- END IF\r
- Obj(X).Ypos = Obj(X).Ypos + Obj(X).YDir\r
-\r
- 'Draw Sprite\r
-\r
- TDRAW.BITMAP Img(Obj(X).Shape), Obj(X).Xpos, Obj(X).Ypos, SpriteX, SpriteY\r
-\r
- LastX(X, CurrentPage) = Obj(X).Xpos\r
- LastY(X, CurrentPage) = Obj(X).Ypos\r
-\r
- NEXT X\r
-\r
- LastObjects(CurrentPage) = VisObjects\r
-\r
- ' Pan Screen Back & Forth\r
-\r
- ViewCnt = ViewCnt + 1\r
- IF ViewCnt >= ViewMax THEN\r
- ViewX = ViewX + ViewXD\r
- IF ViewX = 0 OR ViewX = 39 THEN ViewXD = -ViewXD\r
- IF ViewXD < 0 THEN\r
- ViewY = ViewY + ViewYD\r
- IF ViewY = 0 OR ViewY = 39 THEN ViewYD = -ViewYD\r
- END IF\r
- \r
- SET.WINDOW CurrentPage, ViewX, ViewY\r
-\r
- ViewCnt = 0\r
- ELSE\r
- SET.DISPLAY.PAGE CurrentPage\r
- END IF\r
-\r
- ' Cycle Colors\r
-\r
- SET.DAC.REGISTER 50 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor\r
- SET.DAC.REGISTER 50 + SetColor, SetColor, 10, 63 - SetColor\r
-\r
- SET.DAC.REGISTER 150 + PrevColor, 3 + PrevColor, 0, 60 - PrevColor\r
- SET.DAC.REGISTER 150 + SetColor, 63, 63, SetColor\r
-\r
- SetColor = SetColor + SDir\r
- IF SetColor = 60 OR SetColor = 0 THEN SDir = -SDir\r
-\r
- PrevColor = PrevColor + PDir\r
- IF PrevColor = 60 OR PrevColor = 0 THEN PDir = -PDir\r
-\r
- CurrentPage = 1 - CurrentPage\r
-\r
- Code = SCAN.KEYBOARD\r
-\r
- IF Code = False THEN GOTO DRAW.LOOP\r
-\r
- IF Code = KyPlus THEN\r
- IF ViewMax < 12 THEN ViewMax = ViewMax + 1\r
- GOTO DRAW.LOOP\r
- END IF\r
-\r
- IF Code = KyMinus THEN\r
- IF ViewMax > 1 THEN ViewMax = ViewMax - 1\r
- IF ViewCnt >= ViewMax THEN ViewCnt = 0\r
- GOTO DRAW.LOOP\r
- END IF\r
-\r
- IF Code = KyUp THEN\r
- IF VisObjects < MaxSprites THEN VisObjects = VisObjects + 1\r
- GOTO DRAW.LOOP\r
- END IF\r
- \r
- IF Code = KyDown THEN\r
- IF VisObjects > 1 THEN VisObjects = VisObjects - 1\r
- GOTO DRAW.LOOP\r
- END IF\r
-\r
-\r
-END SUB\r
-\r
-SUB PRINT.TEXT (Text$, Xpos, Ypos, ColorF, ColorB)\r
-\r
- IF LEN(Text$) = 0 THEN EXIT SUB\r
- PRINT.STR VARSEG(Text$), SADD(Text$), LEN(Text$), Xpos, Ypos, ColorF, ColorB\r
-\r
-\r
-END SUB\r
-\r
-SUB TPRINT.TEXT (Text$, Xpos, Ypos, ColorF)\r
-\r
- IF LEN(Text$) = 0 THEN EXIT SUB\r
-\r
- TPRINT.STR VARSEG(Text$), SADD(Text$), LEN(Text$), Xpos, Ypos, ColorF\r
-\r
-END SUB\r
-\r
+++ /dev/null
-MASM utils, utils, utils, nul;
\ No newline at end of file
+++ /dev/null
-;=======================================================\r
-;=== UTILS.ASM - Asm Utilities for QuickBasic/BC7 ===\r
-;=======================================================\r
-\r
- PAGE 255, 132\r
-\r
- .MODEL Medium\r
- .286\r
-\r
- ; ==== MACROS ====\r
-\r
- ; macros to PUSH and POP multiple registers\r
-\r
-PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
- IFNB <R1>\r
- push R1 ; Save R1\r
- PUSHx R2, R3, R4, R5, R6, R7, R8\r
- ENDIF\r
-ENDM\r
-\r
-POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
- IFNB <R1>\r
- pop R1 ; Restore R1\r
- POPx R2, R3, R4, R5, R6, R7, R8\r
- ENDIF\r
-ENDM\r
-\r
- ; Macro to Clear a Register to 0\r
-\r
-CLR MACRO Register\r
- xor Register, Register ; Set Register = 0\r
-ENDM\r
-\r
- ; Macros to Decrement Counter & Jump on Condition\r
-\r
-LOOPx MACRO Register, Destination\r
- dec Register ; Counter--\r
- jnz Destination ; Jump if not 0\r
-ENDM\r
-\r
-LOOPjz MACRO Register, Destination\r
- dec Register ; Counter--\r
- jz Destination ; Jump if 0\r
-ENDM\r
-\r
-\r
- ; ==== General Constants ====\r
-\r
- False EQU 0\r
- True EQU -1\r
- nil EQU 0\r
-\r
- b EQU BYTE PTR\r
- w EQU WORD PTR\r
- d EQU DWORD PTR\r
- o EQU OFFSET\r
- f EQU FAR PTR\r
- s EQU SHORT\r
- ?x4 EQU <?,?,?,?>\r
- ?x3 EQU <?,?,?>\r
-\r
-\r
-IFDEF FARSTRINGS\r
-\r
- EXTRN stringaddress:far\r
- EXTRN stringlength:far\r
-\r
-ENDIF\r
-\r
-\r
- .Data\r
-\r
- EVEN\r
-\r
-RND_Seed DW 7397, 29447, 802\r
-RND_Mult DW 179, 183, 182\r
-RND_ModV DW 32771, 32779, 32783\r
-\r
-CR_LF DB 13, 10 ; the CRLF data\r
-\r
- .Code\r
-\r
-;=================\r
-;DOS_PRINT (Text$)\r
-;=================\r
-;\r
-; Prints Text Directly to DOS console w/ CR/LF\r
-;\r
-\r
- PUBLIC DOS_PRINT\r
-\r
-DP_Stack STRUC\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- DP_Text DW ? ; Address of Text$ Descriptor\r
-DP_Stack ENDS\r
-\r
-\r
-DOS_PRINT PROC FAR\r
-\r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- mov SI, [BP].DP_Text ; Get Addr of Text$ descriptor\r
-\r
-IFDEF FARSTRINGS\r
- push SI ; Push Addr of BC7 Decriptor Ptr\r
- call stringaddress ; Get Address + Len of string!!!\r
- ; DX:AX = Addr CX = Len\r
- mov DS, DX ; DS = DX = Segment of string\r
- mov DX, AX ; DX = AX = Offset of String\r
-ELSE\r
- mov CX, [SI] ; put its length into CX\r
- mov DX, [SI+02] ; now DS:DX points to the String\r
-ENDIF\r
-\r
- jcxz @No_Print ; Don't Print if empty\r
-\r
- mov BX, 1 ; 1= DOS Handle for Display\r
- mov AH, 40h ; Write Text Function\r
- int 21h ; Call DOS to do it\r
-\r
-@No_Print:\r
- mov AX, SEG DGROUP ; Restore DGroup\r
- mov DS, AX\r
-\r
- mov DX, o CR_LF ; Get Addr of CR/LF pair\r
- mov CX, 2 ; 2 Characters to Write \r
- mov BX, 1 ; 1= DOS Handle for Display\r
-\r
- mov AH, 40h ; Write Text Function\r
- int 21h ; Call DOS to do it\r
-\r
- cld ; Reset Direction Flag \r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- ret 2 ; Exit & Clean Up Stack\r
-\r
-DOS_PRINT ENDP\r
-\r
-\r
-;==================\r
-;DOS_PRINTS (Text$)\r
-;==================\r
-; \r
-; Print Text$ Directly to DOS console \r
-; without a trailing CR/LF\r
-;\r
-\r
- PUBLIC DOS_PRINTS\r
-\r
-DOS_PRINTS PROC FAR\r
-\r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- mov SI, [BP].DP_Text ; Get Addr of Text$ descriptor\r
-\r
-IFDEF FARSTRINGS\r
- push SI ; Push Addr of BC7 Decriptor Ptr\r
- call stringaddress ; Get Address + Len of string!!!\r
- ; DX:AX = Addr CX = Len\r
- mov DS, DX ; DS = DX = Segment of string\r
- mov DX, AX ; DX = AX = Offset of String\r
-ELSE\r
- mov CX, [SI] ; put its length into CX\r
- mov DX, [SI+02] ; now DS:DX points to the String\r
-ENDIF\r
-\r
- jcxz @DPS_Exit ; Don't Print if empty\r
-\r
- mov BX, 1 ; 1= DOS Handle for Display\r
- mov AH, 40h ; Write Text Function\r
- int 21h ; Call DOS to do it\r
-\r
-@DPS_Exit:\r
- cld ; Reset Direction Flag \r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- ret 2 ; Exit & Clean Up Stack\r
-\r
-DOS_PRINTS ENDP\r
-\r
-\r
-;======================\r
-;SET_VIDEO_MODE (Mode%) \r
-;======================\r
-;\r
-; Sets the Video Mode through the BIOS\r
-;\r
-\r
- PUBLIC SET_VIDEO_MODE\r
-\r
-SVM_Stack STRUC\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- SVM_Mode DB ?,? ; Desired Video Mode\r
-SVM_Stack ENDS\r
-\r
-\r
-SET_VIDEO_MODE PROC FAR\r
-\r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- CLR AH ; Function 0\r
- mov AL, [BP].SVM_Mode ; Get Mode #\r
-\r
- int 10H ; Change Video Modes\r
-\r
-@SVM_Exit:\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- ret 2 ; Exit & Clean Up Stack\r
-\r
-SET_VIDEO_MODE ENDP\r
-\r
-\r
-;==============\r
-;SCAN_KEYBOARD%\r
-;==============\r
-;\r
-; Function to scan keyboard for a pressed key\r
-;\r
-\r
- PUBLIC SCAN_KEYBOARD\r
-\r
-SCAN_KEYBOARD PROC FAR\r
-\r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
-\r
- mov AH, 01H ; Function #1\r
- int 16H ; Call Keyboard Driver\r
- jz @SK_NO_KEY ; Exit if Zero flag set\r
-\r
- mov AH, 00H ; Remove Key from Buffer\r
- int 16H ; Get Keycode in AX\r
-\r
- or AL, AL ; Low Byte Set (Ascii?)\r
- jz @SK_Exit ; if not, it's a F-Key\r
-\r
- CLR AH ; Clear ScanCode if Ascii\r
- jmp s @SK_Exit ; Return Key in AX\r
-\r
-@SK_NO_KEY:\r
- CLR AX ; Return Nil (no Keypress)\r
-\r
-@SK_Exit:\r
- cld ; Reset Direction Flag \r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- ret ; Exit & Clean Up Stack\r
-\r
-SCAN_KEYBOARD ENDP\r
-\r
-\r
-;====================\r
-;RANDOM_INT (MaxInt%)\r
-;====================\r
-;\r
-; Returns a pseudo-random number in the range of (0.. MaxInt-1)\r
-;\r
-\r
-\r
- PUBLIC RANDOM_INT\r
-\r
-RI_Stack STRUC\r
- DW ? ; BP\r
- DD ? ; Caller\r
- RI_MaxVal DW ? ; Maximum Value to Return + 1\r
-RI_Stack ENDS\r
-\r
-\r
-RANDOM_INT PROC FAR\r
-\r
- push BP ; Preserve Important Registers\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- CLR BX ; BX is the data index\r
- CLR CX ; CX is the accumulator\r
-\r
-REPT 3\r
- mov AX, RND_Seed[BX] ; load the initial seed\r
- mul RND_Mult[BX] ; multiply it\r
- div RND_ModV[BX] ; and obtain the Mod value\r
- mov RND_Seed[BX], DX ; save that for the next time\r
-\r
- add CX, DX ; add it into the accumulator\r
- inc BX\r
- inc BX ; point to the next set of values\r
-ENDM\r
-\r
- mov AX, CX ; AX = Random #\r
- CLR DX ; DX = 0\r
- div [BP].RI_MaxVal ; DX = DX:AX / MAxVal Remainder\r
-\r
- mov AX, DX\r
-\r
- pop BP ; Restore BP\r
- ret 2 ; back to BASIC with AX holding the result\r
-\r
-RANDOM_INT ENDP\r
-\r
-\r
-;===========\r
-;INIT_RANDOM\r
-;===========\r
-;\r
-; Scrambles the psuedo-random number sequence\r
-; (XOR's the seed value with the timer)\r
-;\r
-\r
- PUBLIC INIT_RANDOM\r
-\r
-INIT_RANDOM PROC FAR\r
-\r
- clr AX ; Segment = 0000\r
- mov ES, AX\r
- mov AX, ES:[046Ch] ; Get Timer Lo Word\r
-\r
- xor RND_Seed, AX ; Scramble 1st Seed\r
-\r
- ret ; Exit & Clean Up Stack\r
-\r
-INIT_RANDOM ENDP\r
-\r
-\r
-;====================\r
-;INT_SQR (X%, Round%)\r
-;====================\r
-;\r
-; Returns the Integer Square Root of (X)\r
-; Round allows the return value to be rounded to the \r
-; nearest integer value by passing 0x80. Passing 0\r
-; return the Integer Portion only. The rounding amound is\r
-; a number from 0 to 1 multiplied by 256, thus \r
-; 0.5 * 0x100 = 0x80!\r
-;\r
-\r
-ISQ_Stack STRUC\r
- DW ?,? ; BP, DI\r
- DD ? ; Caller\r
- ISQ_Round DW ? ; Amount to Round Result * 256\r
- ISQ_X DW ? ; "X"\r
-ISQ_Stack ENDS\r
-\r
- PUBLIC INT_SQR\r
-\r
-INT_SQR PROC FAR\r
-\r
- PUSHx BP, DI ; Save BP\r
- mov BP, SP ; Set up Stack Frame\r
-\r
- xor AX, AX ; {xor eax,eax}\r
- xor DX, DX ; {xor edx,edx}\r
- mov DI, [BP].ISQ_X ; {mov edi,x}\r
-\r
- mov CX, 16 ; {mov cx, 32}\r
-\r
-@ISQ_L:\r
-\r
- shl DI, 1 ; {shl edi,1}\r
- rcl DX, 1 ; {rcl edx,1}\r
- shl DI, 1 ; {shl edi,1}\r
- rcl DX, 1 ; {rcl edx,1}\r
- shl AX, 1 ; {shl eax,1}\r
- mov BX, AX ; {mov ebx,eax}\r
- shl BX, 1 ; {shl ebx,1}\r
- inc BX ; {inc ebx}\r
- cmp DX, BX ; {cmp edx,ebx}\r
- jl @ISQ_S\r
-\r
- sub DX, BX ; {sub edx,ebx}\r
- inc AX ; {inc eax}\r
-\r
-@ISQ_S: \r
- loop @ISQ_L\r
-\r
- add ax, [BP].ISQ_Round ; {add eax,$00008000} \r
- ; {*round* result in hi word: ie. +0.5}\r
- shr ax, 8 ; {shr eax,16} {to ax (result)}\r
-\r
- POPx DI, BP ; Restore Registers \r
- ret 4 ; Exit\r
-\r
-INT_SQR ENDP\r
-\r
-\r
-;============\r
-;TIMER_COUNT&\r
-;============\r
-;\r
-; Returns the current timer value as an integer/long integer\r
-;\r
-\r
-\r
- PUBLIC TIMER_COUNT\r
-\r
-TIMER_COUNT PROC FAR\r
-\r
- clr AX ; Segment = 0000\r
- mov ES, AX ; use ES to get at data\r
- mov AX, ES:[046Ch] ; Get Timer Lo Word\r
- mov DX, ES:[046Eh] ; Get Timer Hi Word\r
- ret ; Exit & Return value in DX:AX\r
-\r
-TIMER_COUNT ENDP\r
-\r
-\r
- END\r
+++ /dev/null
-\r
- ' Misc Constants\r
-\r
-CONST True = -1, False = 0, nil = 0\r
-\r
- ' Keyboard Codes: Extended\r
-\r
-CONST KyF1 = &H3B00, KyF2 = &H3C00, KyF3 = &H3D00, KyF4 = &H3E00, KyF5 = &H3F00\r
-CONST KyF6 = &H4000, KyF7 = &H4100, KyF8 = &H4200, KyF9 = &H4300, KyF10 = &H4400\r
-\r
-CONST KyUp = &H4800, KyLeft = &H4B00, KyRight = &H4D00, KyDown = &H5000\r
-CONST KySLeft = &HCB00, KySRight = &HCD00, KySUp = &HC800, KySDown = &HD000\r
-\r
-CONST KyHome = &H4700, KyPgUp = &H4900, KyEnd = &H4F00, KyPgDn = &H5100\r
-CONST KySHome = &HC700, KySPgUp = &HC900, KySEnd = &HCF00, KySPgDn = &HD100\r
-\r
-CONST KyIns = &H5200, KyDel = &H5300, KyRvsTab = &H8F00\r
-CONST KySIns = &HC200, KySDel = &HC300\r
-\r
-CONST KyAltA = &H1E00, KyAltB = &H3000, KyAltC = &H2E00, KyAltD = &H2000\r
-CONST KyAltE = &H1200, KyAltF = &H2100, KyAltG = &H2200, KyAltH = &H2300\r
-CONST KyAltI = &H1700, KyAltJ = &H2400, KyAltK = &H2500, KyAltL = &H2600\r
-CONST KyAltM = &H3200, KyAltN = &H3100, KyAltO = &H1800, KyAltP = &H1900\r
-CONST KyAltQ = &H1000, KyAltR = &H1300, KyAltS = &H1F00, KyAltT = &H1400\r
-CONST KyAltU = &H1600, KyAltV = &H2F00, KyAltW = &H1100, KyAltX = &H2D00\r
-CONST KyAltY = &H1500, KyAltZ = &H2C00\r
-\r
- ' Keyboard Codes: Ascii\r
-\r
-CONST KyBS = 8, KyTab = 9, KyCR = 13, KyESC = &H1B, KyClr = &H7F\r
-CONST KyPlus = 45, KyMinus = 43\r
-\r
- ' Color Constants\r
-\r
-CONST c.BLACK = 0, c.BLUE = 1, c.GREEN = 2, c.CYAN = 3\r
-CONST c.RED = 4, c.PURPLE = 5, c.BROWN = 6, c.WHITE = 7\r
-CONST c.GREY = 8, c.bBLUE = 9, c.bGREEN = 10, c.bCYAN = 11\r
-CONST c.bRED = 12, c.bPURPLE = 13, c.YELLOW = 14, c.bWHITE = 15\r
-CONST c.BRIGHT = 8\r
-\r
- ' From UTILS.ASM\r
-\r
-DECLARE SUB DOS.PRINT ALIAS "DOS_PRINT" (Text$)\r
-DECLARE SUB DOS.PRINTS ALIAS "DOS_PRINTS" (Text$)\r
-DECLARE SUB SET.VIDEO.MODE ALIAS "SET_VIDEO_MODE" (BYVAL Mode%)\r
-DECLARE FUNCTION SCAN.KEYBOARD% ALIAS "SCAN_KEYBOARD"\r
-DECLARE FUNCTION RANDOM.INT ALIAS "RANDOM_INT" (BYVAL MaxInt%)\r
-DECLARE SUB INIT.RANDOM ALIAS "INIT_RANDOM"\r
-DECLARE FUNCTION TIMER.COUNT& ALIAS "TIMER_COUNT"\r
-DECLARE FUNCTION INT.SQR ALIAS "INT_SQR" (BYVAL X%, BYVAL Round%)\r
-\r
+++ /dev/null
-\r
-CSEDIT - A Simple Font Editor by Matt Pritchard\r
- \r
- \r
-CSEDIT is distributed with MODEXnnn.ZIP, the general purpose MODE X\r
-Library for VGA Graphics.\r
- \r
-WHAT YOU NEED TO RUN CSEDIT:\r
- \r
- * A Vga Monitor\r
- * A Microsoft Compatible Mouse\r
- \r
- A Mouse is most definitely required, as the keyboard is used for\r
- nothing except entering file names.\r
- \r
-FILES NEEDED IN THE CURRENT DIRECTORY:\r
- \r
- CSEDIT.EXE - The Font Editor Program\r
- CHARSETS.CS - The Font Editor's Internal Fonts\r
- PALETTE.CS - The Font Editor's Palette\r
- MOUSEIMG.CS - The Font Editor's Mouse Pointer\r
- \r
-SAMPLE FONT FILE THAT SHOULD BE INCLUDED:\r
- \r
- SYSTEM.FNT - The Font used by CSEDIT.EXE\r
- INVERSE.FNT - An Inverted version of SYSTEM.FNT\r
- SPACEAGE.FNT - A Futuristic, Tech style font\r
- ROM_8X8.FNT - The Lower 128 characters from the VGA BIOS Rom\r
- \r
-WHAT IT EDITS:\r
- \r
- 8 by 8 character fonts, 128 characters at a time. 2 fonts at a time.\r
- \r
-HOW IT WORKS/FEATURES:\r
- \r
- CSEDIT allows the user to edit 2 different font groups at a time,\r
- which may be loaded and saved separately.\r
- \r
- A enlarged character grid allows the user to edit individual pixels\r
- on a selected character.\r
- \r
- The Following operations can be performed on a single character or\r
- simultaneously on a selected block of characters.\r
- \r
- * Shift the selected character(s) in any direction\r
- with or without clipping at the edges.\r
- * Vertically Flip the selected character(s)\r
- * Horizontally Flip the selected character(s)\r
- * Rotate the selected character(s) 90 Degrees Clockwise\r
- * Rotate the selected character(s) 90 Degrees Counterclockwise\r
- * Clear the selected character(s)\r
- * Invert the selected character(s)\r
- * XOR the selected character(s) with other character(s)\r
- * AND the selected character(s) with other character(s)\r
- * OR the selected character(s) with other character(s)\r
- * Copy the selected character(s) to another position or font.\r
- \r
- An UNDO feature allows the reversal of the most recent operation.\r
- \r
-DESCRIPTION OF OBJECTS/FEATURES FROM THE TOP DOWN:\r
- \r
- Character Grid: (RED) Box in Upper Left corner of screen. This is\r
- where you edit an individual character. The Left Button sets the\r
- pixel the mouse pointer is on, while the Right Button clears that\r
- pixel.\r
- \r
- Scroll Buttons: The Four Scroll Buttons are labeled with directional\r
- arrows, and arranged in a diamond pattern. Left Clicking on a\r
- directional button will scroll the currently selected character\r
- in that direction, with the pixels on the edge rolling off and\r
- appearing on the other size. Right Clicking will prevent the\r
- pixels from rolling to the other side.\r
- \r
- Vertical Flip Button:\r
- Horizontal Flip Button: Clicking these buttons will flip the pattern\r
- of the currently selected character(s) around the indicated axis.\r
- i.e. the top row will be swapped with the bottom row, etc. or the\r
- left row column will be swapped with right column, etc.\r
- depending upon which button you push.\r
- \r
- Invert Button: Clicking this button causes all pixels in the selected\r
- character(s) to flip flop between on and off.\r
- \r
- Clear Button: Clicking this button erases the selected characters\r
- \r
- Rotate Buttons: Clicking these buttons will rotate the pattern in the\r
- selected character(s) 90 degrees in the indicated direction.\r
- \r
- XOR Button: Clicking this button will let you XOR the currently\r
- selected character(s) with other character(s) in either font.\r
- The Button will turn RED, indicating that it is waiting for\r
- you to click on the desired character (or upper left corner\r
- of the desired block of characters) in either the Red or Green\r
- Character Set Displays. Clicking anywhere else will abort this\r
- process without doing anything. If you click on (any of) the\r
- selected character(s) the operation is aborted. If a block is\r
- selected and the character you click on is in a position where\r
- it can't represent the upper left corner of a block of the same\r
- size, then the operation is not performed.\r
- \r
- AND Button & OR Button: These buttons work just like the XOR Button\r
- except that the Binary operation performed is either an AND or OR\r
- depending upon which button you have selected.\r
- \r
- COPY Button: This button lets you copy a character or selected block\r
- of characters to another area in the current font or the other\r
- font. After clicking, the button turns RED and works much like\r
- the XOR Button. Clicking on a valid position in either font\r
- window will copy the selected character(s) to that location.\r
- \r
- MODE Button: Clicking this button toggles the editor between BLOCK\r
- mode and CHARACTER mode. The current mode is displayed on a plate\r
- at the top of the screen, just to the right of the enlarged\r
- character grid. In character mode the plate will read "CHAR" and\r
- the currently selected character is displayed just to the right\r
- of the plate. In Block mode the plate will read "BLOCK" and the\r
- enlarged character grid is disabled.\r
- \r
- UNDO Button: Clicking this Button will UNDO or reverse the effects of\r
- the most recent operation.\r
- \r
- QUIT Button: Clicking this button will return you to DOS. Any loaded\r
- fonts are not saved, and no confirmation is given.\r
- \r
- \r
- GREEN FONT AREA: This area displays one of the current fonts which\r
- can be edited. The characters are display in order from #0 to #127\r
- from the upper left, going right, then down. The Font Box is 32\r
- characters wide and 4 characters Tall. When the editor is in\r
- character mode, just point at and Left Click on the character you\r
- wish to edit and a Cyan box will appear around that character.\r
-\r
- * If you Right Click on a character, the last current character,\r
- which will still appear in the enlarged character grid, will be\r
- copied onto the character you pointed at, replacing it. This is\r
- a shortcut for copying characters: You can hold the right button\r
- down an fill in a large area with a single character pattern.\r
- When the editor is in Block Mode, you select an area by clicking\r
- on any corner of the desired block. Then drag the mouse to the\r
- opposite corner while holding down the left button. A Cyan Box\r
- will stretch to surround the selected block of characters.\r
- \r
- GREEN FONT FILE NAME BOX: This Text Box is used to enter the name\r
- of a font file to load or the name to save the current Green font\r
- as. Just click on the Box, and it will change color and a\r
- flashing cursor will appear. Now you type in a filename or edit\r
- the existing filename. Press <RETURN> or click outside the text\r
- box to end editing.\r
- \r
- GREEN FONT LOAD BUTTON: Clicking this button will load the font file\r
- that is named in the Green File name box. If no name is given or\r
- no such file exists, then nothing will be loaded.\r
- \r
- GREEN FONT SAVE BUTTON: Clicking this button will save the current\r
- font in the Green Font Area under the name given in the File Name\r
- Box. If a Valid name is not provided, nothing will be saved.\r
- \r
- RED FONT AREA: This is just the same as the GREEN FONT AREA; providing\r
- you with the ability to copy and edit between multiple fonts.\r
- \r
- RED FONT FILE NAME BOX: This works just like the GREEN FONT FILE\r
- NAME BOX.\r
- \r
- RED FONT LOAD BUTTON: This works just like the GREEN FONT LOAD BUTTON.\r
- \r
- RED FONT SAVE BUTTON: This works just like the GREEN FONT SAVE BUTTON.\r
- \r
- Message Bar: At the very bottom of the screen, this Bar will display\r
- information and messages for various functions.\r
- \r
- \r
-FONT FILE FORMAT:\r
- \r
- BINARY Image, in order of character. The format is identical to that\r
- used by the VGA ROM. The Files will be exactly 1024 (128 * 8) bytes\r
- long.\r
- \r
- CHARACTER: 8 Bytes\r
- \r
- FONT: Array (0 to 127) of CHARACTER\r
- \r
- \r
-COMMENTS, QUESTIONS, BUG REPORTS, etc:\r
- \r
- Send the to the Author: Matt Pritchard\r
- \r
- Through the 80xxx Fidonet Echo or\r
- \r
- Matt Pritchard\r
- P.O. Box 140264\r
- Irving, TX 75014\r
- \r
-CREDITS:\r
- \r
- This Font Editor was written in QuickBASIC 4.5\r
- \r
+++ /dev/null
-The following is a FAQ (Frequently Asked Question) summary of \r
-information and assembly routines for Mode "X" Graphics.\r
-\r
-An overview of Mode "X" for the VGA Adaptor:\r
-\r
-1) Mode "X" is a 256 color graphics mode that is available on *ANY* VGA\r
-card with the minimum of 256K video RAM. It is capable of providing\r
-higher resoultions than the only "Official" 256 color mode, mode 13h.\r
-(In quickbasic that is mode 13)\r
-\r
-2) Mode "X" comes in 8 different flavors: 320 or 360 pixels\r
-horizontally, and 200, 240, 400, and 480 pixels vertically.\r
-\r
-3) Since mode X is not supported by the VGA BIOS, there is no built in\r
-support for it. A program must provide its own routines for *ALL*\r
-operations in Mode "X", including setting up the video mode.\r
-\r
-4) Unlike Mode 13h, which has one display page, Mode "X" allows from 1\r
-to 4 video pages, depending upon the resoultion selected. The reason\r
-that Mode 13h has but one page is that it activates a VGA hardware\r
-feature known as CHAIN4, which prevents access to all but 64K of VGA's\r
-video RAM. CHAIN4 is what provides mode 13h's linear addres space.\r
-\r
-5) Unlike Mode 13h, where each 256 color (1-byte) pixel has a unique\r
-address in the E000: segement, in Mode X there are Four (4) Pixels\r
-at each address in E000: segment. The VGA's control registers allow you\r
-to control which of the 4 pixels is currently available at an address.\r
-\r
-6) It is possible to use the VGA's control registers to operate on 2 or\r
-more of the Pixels at the same address at the same time. The CPU can\r
-write one color value, and set up to 4 pixels with that value at the\r
-same time.\r
-\r
-7) Video RAM that is not being used for the current screen display can\r
-be used to store images and patterns. These images and patterns can be\r
-copied to other parts of the Video RAM 4 bytes (32 bits) at a time,\r
-which is much faster than the 8 bits (1 byte) at time that is possible\r
-over the ISA BUS. (16 Bit BUS operations can produce erroneous results)\r
-\r
-If anything is unclear, inadequate, or you just plain want to know more \r
-or have other specific questions, please send me a message.\r
-\r
-\r
--Matt Pritchard\r
+++ /dev/null
-;========================================================\r
-; MODEX.ASM - A Complete Mode X Library\r
-;\r
-; Version 1.04 Release, 3 May 1993, By Matt Pritchard\r
-; With considerable input from Michael Abrash\r
-;\r
-; The following information is donated to the public domain in\r
-; the hopes that save other programmers much frustration.\r
-;\r
-; If you do use this code in a product, it would be nice if\r
-; you include a line like "Mode X routines by Matt Pritchard"\r
-; in the credits.\r
-;\r
-; =========================================================\r
-;\r
-; All of this code is designed to be assembled with MASM 5.10a\r
-; but TASM 3.0 could be used as well.\r
-;\r
-; The routines contained are designed for use in a MEDIUM model\r
-; program. All Routines are FAR, and is assumed that a DGROUP\r
-; data segment exists and that DS will point to it on entry.\r
-;\r
-; For all routines, the AX, BX, CX, DX, ES and FLAGS registers\r
-; will not be preserved, while the DS, BP, SI and DI registers\r
-; will be preserved.\r
-;\r
-; Unless specifically noted, All Parameters are assumed to be\r
-; "PASSED BY VALUE". That is, the actual value is placed on\r
-; the stack. When a reference is passed it is assumed to be\r
-; a near pointer to a variable in the DGROUP segment.\r
-;\r
-; Routines that return a single 16-Bit integer value will\r
-; return that value in the AX register.\r
-;\r
-; This code will *NOT* run on an 8086/8088 because 80286+\r
-; specific instructions are used. If you have an 8088/86\r
-; and VGA, you can buy an 80386-40 motherboard for about\r
-; $160 and move into the 90's.\r
-;\r
-; This code is reasonably optimized: Most drawing loops have\r
-; been unrolled once and memory references are minimized by\r
-; keeping stuff in registers when possible.\r
-;\r
-; Error Trapping varies by Routine. No Clipping is performed\r
-; so the caller should verify that all coordinates are valid.\r
-;\r
-; Several Macros are used to simplify common 2 or 3 instruction\r
-; sequences. Several Single letter Text Constants also\r
-; simplify common assembler expressions like "WORD PTR".\r
-;\r
-; ------------------ Mode X Variations ------------------\r
-;\r
-; Mode # Screen Size Max Pages Aspect Ratio (X:Y)\r
-;\r
-; 0 320 x 200 4 Pages 1.2:1\r
-; 1 320 x 400 2 Pages 2.4:1\r
-; 2 360 x 200 3 Pages 1.35:1\r
-; 3 360 x 400 1 Page 2.7:1\r
-; 4 320 x 240 3 Pages 1:1\r
-; 5 320 x 480 1 Page 2:1\r
-; 6 360 x 240 3 Pages 1.125:1\r
-; 7 360 x 480 1 Page 2.25:1\r
-;\r
-; -------------------- The Legal Stuff ------------------\r
-;\r
-; No warranty, either written or implied, is made as to\r
-; the accuracy and usability of this code product. Use\r
-; at your own risk. Batteries not included. Pepperoni\r
-; and extra cheese available for an additional charge.\r
-;\r
-; ----------------------- The Author --------------------\r
-;\r
-; Matt Pritchard is a paid programmer who'd rather be\r
-; writing games. He can be reached at: P.O. Box 140264,\r
-; Irving, TX 75014 USA. Michael Abrash is a living\r
-; god, who now works for Bill Gates (Microsoft).\r
-;\r
-; -------------------- Revision History -----------------\r
-; 4-12-93: v1.02 - SET_POINT & READ_POINT now saves DI\r
-; SET_MODEX now saves SI\r
-; 5-3-93: v1.04 - added LOAD_DAC_REGISTERS and\r
-; READ_DAC_REGISTERS. Expanded CLR Macro\r
-; to handle multiple registers\r
-;\r
- \r
- PAGE 255, 132\r
- \r
- .MODEL Medium\r
- .286\r
- \r
- ; ===== MACROS =====\r
- \r
- ; Macro to OUT a 16 bit value to an I/O port\r
- \r
-OUT_16 MACRO Register, Value\r
- IFDIFI <Register>, <DX> ; If DX not setup\r
- MOV DX, Register ; then Select Register\r
- ENDIF\r
- IFDIFI <Value>, <AX> ; If AX not setup\r
- MOV AX, Value ; then Get Data Value\r
- ENDIF\r
- OUT DX, AX ; Set I/O Register(s)\r
-ENDM\r
- \r
- ; Macro to OUT a 8 bit value to an I/O Port\r
- \r
-OUT_8 MACRO Register, Value\r
- IFDIFI <Register>, <DX> ; If DX not setup\r
- MOV DX, Register ; then Select Register\r
- ENDIF\r
- IFDIFI <Value>, <AL> ; If AL not Setup\r
- MOV AL, Value ; then Get Data Value\r
- ENDIF\r
- OUT DX, AL ; Set I/O Register\r
-ENDM\r
- \r
- ; macros to PUSH and POP multiple registers\r
- \r
-PUSHx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
- IFNB <R1>\r
- PUSH R1 ; Save R1\r
- PUSHx R2, R3, R4, R5, R6, R7, R8\r
- ENDIF\r
-ENDM\r
- \r
-POPx MACRO R1, R2, R3, R4, R5, R6, R7, R8\r
- IFNB <R1>\r
- POP R1 ; Restore R1\r
- POPx R2, R3, R4, R5, R6, R7, R8\r
- ENDIF\r
-ENDM\r
- \r
- ; Macro to Clear Registers to 0\r
- \r
-CLR MACRO Register, R2, R3, R4, R5, R6\r
- IFNB <Register>\r
- XOR Register, Register ; Set Register = 0\r
- CLR R2, R3, R4, R5, R6\r
- ENDIF\r
-ENDM\r
- \r
- ; Macros to Decrement Counter & Jump on Condition\r
- \r
-LOOPx MACRO Register, Destination\r
- DEC Register ; Counter--\r
- JNZ Destination ; Jump if not 0\r
-ENDM\r
- \r
-LOOPjz MACRO Register, Destination\r
- DEC Register ; Counter--\r
- JZ Destination ; Jump if 0\r
-ENDM\r
- \r
- \r
- ; ===== General Constants =====\r
- \r
- False EQU 0\r
- True EQU -1\r
- nil EQU 0\r
- \r
- b EQU BYTE PTR\r
- w EQU WORD PTR\r
- d EQU DWORD PTR\r
- o EQU OFFSET\r
- f EQU FAR PTR\r
- s EQU SHORT\r
- ?x4 EQU <?,?,?,?>\r
- ?x3 EQU <?,?,?>\r
- \r
- ; ===== VGA Register Values =====\r
- \r
- VGA_Segment EQU 0A000h ; Vga Memory Segment\r
- \r
- ATTRIB_Ctrl EQU 03C0h ; VGA Attribute Controller\r
- GC_Index EQU 03CEh ; VGA Graphics Controller\r
- SC_Index EQU 03C4h ; VGA Sequencer Controller\r
- SC_Data EQU 03C5h ; VGA Sequencer Data Port\r
- CRTC_Index EQU 03D4h ; VGA CRT Controller\r
- CRTC_Data EQU 03D5h ; VGA CRT Controller Data\r
- MISC_OUTPUT EQU 03C2h ; VGA Misc Register\r
- INPUT_1 EQU 03DAh ; Input Status #1 Register\r
- \r
- DAC_WRITE_ADDR EQU 03C8h ; VGA DAC Write Addr Register\r
- DAC_READ_ADDR EQU 03C7h ; VGA DAC Read Addr Register\r
- PEL_DATA_REG EQU 03C9h ; VGA DAC/PEL data Register R/W\r
- \r
- PIXEL_PAN_REG EQU 033h ; Attrib Index: Pixel Pan Reg\r
- MAP_MASK EQU 002h ; Sequ Index: Write Map Mask reg\r
- READ_MAP EQU 004h ; GC Index: Read Map Register\r
- START_DISP_HI EQU 00Ch ; CRTC Index: Display Start Hi\r
- START_DISP_LO EQU 00Dh ; CRTC Index: Display Start Lo\r
- \r
- MAP_MASK_PLANE1 EQU 00102h ; Map Register + Plane 1\r
- MAP_MASK_PLANE2 EQU 01102h ; Map Register + Plane 1\r
- ALL_PLANES_ON EQU 00F02h ; Map Register + All Bit Planes\r
- \r
- CHAIN4_OFF EQU 00604h ; Chain 4 mode Off\r
- ASYNC_RESET EQU 00100h ; (A)synchronous Reset\r
- SEQU_RESTART EQU 00300h ; Sequencer Restart\r
- \r
- LATCHES_ON EQU 00008h ; Bit Mask + Data from Latches\r
- LATCHES_OFF EQU 0FF08h ; Bit Mask + Data from CPU\r
- \r
- VERT_RETRACE EQU 08h ; INPUT_1: Vertical Retrace Bit\r
- PLANE_BITS EQU 03h ; Bits 0-1 of Xpos = Plane #\r
- ALL_PLANES EQU 0Fh ; All Bit Planes Selected\r
- CHAR_BITS EQU 0Fh ; Bits 0-3 of Character Data\r
- \r
- GET_CHAR_PTR EQU 01130h ; VGA BIOS Func: Get Char Set\r
- ROM_8x8_Lo EQU 03h ; ROM 8x8 Char Set Lo Pointer\r
- ROM_8x8_Hi EQU 04h ; ROM 8x8 Char Set Hi Pointer\r
- \r
- ; Constants Specific for these routines\r
- \r
- NUM_MODES EQU 8 ; # of Mode X Variations\r
- \r
- ; Specific Mode Data Table format...\r
- \r
-Mode_Data_Table STRUC\r
- M_MiscR DB ? ; Value of MISC_OUTPUT register\r
- M_Pages DB ? ; Maximum Possible # of pages\r
- M_XSize DW ? ; X Size Displayed on screen\r
- M_YSize DW ? ; Y Size Displayed on screen\r
- M_XMax DW ? ; Maximum Possible X Size\r
- M_YMax DW ? ; Maximum Possible Y Size\r
- M_CRTC DW ? ; Table of CRTC register values\r
-Mode_Data_Table ENDS\r
- \r
- ; ===== DGROUP STORAGE NEEDED (42 BYTES) =====\r
- \r
- .DATA?\r
- \r
-SCREEN_WIDTH DW 0 ; Width of a line in Bytes\r
-SCREEN_HEIGHT DW 0 ; Vertical Height in Pixels\r
- \r
-LAST_PAGE DW 0 ; # of Display Pages\r
-PAGE_ADDR DW 4 DUP (0) ; Offsets to start of each page\r
- \r
-PAGE_SIZE DW 0 ; Size of Page in Addr Bytes\r
- \r
-DISPLAY_PAGE DW 0 ; Page # currently displayed\r
-ACTIVE_PAGE DW 0 ; Page # currently active\r
- \r
-CURRENT_PAGE DW 0 ; Offset of current Page\r
-CURRENT_SEGMENT DW 0 ; Segment of VGA memory\r
- \r
-CURRENT_XOFFSET DW 0 ; Current Display X Offset\r
-CURRENT_YOFFSET DW 0 ; Current Display Y Offset\r
- \r
-CURRENT_MOFFSET DW 0 ; Current Start Offset\r
- \r
-MAX_XOFFSET DW 0 ; Current Display X Offset\r
-MAX_YOFFSET DW 0 ; Current Display Y Offset\r
- \r
-CHARSET_LOW DW 0, 0 ; Far Ptr to Char Set: 0-127\r
-CHARSET_HI DW 0, 0 ; Far Ptr to Char Set: 128-255\r
- \r
- .CODE\r
- \r
- ; ===== DATA TABLES =====\r
- \r
- ; Data Tables, Put in Code Segment for Easy Access\r
- ; (Like when all the other Segment Registers are in\r
- ; use!!) and reduced DGROUP requirements...\r
- \r
- ; Bit Mask Tables for Left/Right/Character Masks\r
- \r
-Left_Clip_Mask DB 0FH, 0EH, 0CH, 08H\r
- \r
-Right_Clip_Mask DB 01H, 03H, 07H, 0FH\r
- \r
- ; Bit Patterns for converting character fonts\r
- \r
-Char_Plane_Data DB 00H,08H,04H,0CH,02H,0AH,06H,0EH\r
- DB 01H,09H,05H,0DH,03H,0BH,07H,0FH\r
- \r
- ; CRTC Register Values for Various Configurations\r
- \r
-MODE_Single_Line: ; CRTC Setup Data for 400/480 Line modes\r
- DW 04009H ; Cell Height (1 Scan Line)\r
- DW 00014H ; Dword Mode off\r
- DW 0E317H ; turn on Byte Mode\r
- DW nil ; End of CRTC Data for 400/480 Line Mode\r
- \r
-MODE_Double_Line: ; CRTC Setup Data for 200/240 Line modes\r
- DW 04109H ; Cell Height (2 Scan Lines)\r
- DW 00014H ; Dword Mode off\r
- DW 0E317H ; turn on Byte Mode\r
- DW nil ; End of CRTC Data for 200/240 Line Mode\r
- \r
-MODE_320_Wide: ; CRTC Setup Data for 320 Horz Pixels\r
- DW 05F00H ; Horz total\r
- DW 04F01H ; Horz Displayed\r
- DW 05002H ; Start Horz Blanking\r
- DW 08203H ; End Horz Blanking\r
- DW 05404H ; Start H Sync\r
- DW 08005H ; End H Sync\r
- DW nil ; End of CRTC Data for 320 Horz pixels\r
- \r
-MODE_360_Wide: ; CRTC Setup Data for 360 Horz Pixels\r
- DW 06B00H ; Horz total\r
- DW 05901H ; Horz Displayed\r
- DW 05A02H ; Start Horz Blanking\r
- DW 08E03H ; End Horz Blanking\r
- DW 05E04H ; Start H Sync\r
- DW 08A05H ; End H Sync\r
- DW nil ; End of CRTC Data for 360 Horz pixels\r
- \r
-MODE_200_Tall:\r
-MODE_400_Tall: ; CRTC Setup Data for 200/400 Line modes\r
- DW 0BF06H ; Vertical Total\r
- DW 01F07H ; Overflow\r
- DW 09C10H ; V Sync Start\r
- DW 08E11H ; V Sync End/Prot Cr0 Cr7\r
- DW 08F12H ; Vertical Displayed\r
- DW 09615H ; V Blank Start\r
- DW 0B916H ; V Blank End\r
- DW nil ; End of CRTC Data for 200/400 Lines\r
- \r
-MODE_240_Tall:\r
-MODE_480_Tall: ; CRTC Setup Data for 240/480 Line modes\r
- DW 00D06H ; Vertical Total\r
- DW 03E07H ; Overflow\r
- DW 0EA10H ; V Sync Start\r
- DW 08C11H ; V Sync End/Prot Cr0 Cr7\r
- DW 0DF12H ; Vertical Displayed\r
- DW 0E715H ; V Blank Start\r
- DW 00616H ; V Blank End\r
- DW nil ; End of CRTC Data for 240/480 Lines\r
- \r
- ; Table of Display Mode Tables\r
- \r
-MODE_TABLE:\r
- DW o MODE_320x200, o MODE_320x400\r
- DW o MODE_360x200, o MODE_360x400\r
- DW o MODE_320x240, o MODE_320x480\r
- DW o MODE_360x240, o MODE_360x480\r
- \r
- ; Table of Display Mode Components\r
- \r
-MODE_320x200: ; Data for 320 by 200 Pixels\r
- \r
- DB 063h ; 400 scan Lines & 25 Mhz Clock\r
- DB 4 ; Maximum of 4 Pages\r
- DW 320, 200 ; Displayed Pixels (X,Y)\r
- DW 1302, 816 ; Max Possible X and Y Sizes\r
- \r
- DW o MODE_320_Wide, o MODE_200_Tall\r
- DW o MODE_Double_Line, nil\r
- \r
-MODE_320x400: ; Data for 320 by 400 Pixels\r
- \r
- DB 063h ; 400 scan Lines & 25 Mhz Clock\r
- DB 2 ; Maximum of 2 Pages\r
- DW 320, 400 ; Displayed Pixels X,Y\r
- DW 648, 816 ; Max Possible X and Y Sizes\r
- \r
- DW o MODE_320_Wide, o MODE_400_Tall\r
- DW o MODE_Single_Line, nil\r
- \r
-MODE_360x240: ; Data for 360 by 240 Pixels\r
- \r
- DB 0E7h ; 480 scan Lines & 28 Mhz Clock\r
- DB 3 ; Maximum of 3 Pages\r
- DW 360, 240 ; Displayed Pixels X,Y\r
- DW 1092, 728 ; Max Possible X and Y Sizes\r
- \r
- DW o MODE_360_Wide, o MODE_240_Tall\r
- DW o MODE_Double_Line , nil\r
- \r
-MODE_360x480: ; Data for 360 by 480 Pixels\r
- \r
- DB 0E7h ; 480 scan Lines & 28 Mhz Clock\r
- DB 1 ; Only 1 Page Possible\r
- DW 360, 480 ; Displayed Pixels X,Y\r
- DW 544, 728 ; Max Possible X and Y Sizes\r
- \r
- DW o MODE_360_Wide, o MODE_480_Tall\r
- DW o MODE_Single_Line , nil\r
- \r
-MODE_320x240: ; Data for 320 by 240 Pixels\r
- \r
- DB 0E3h ; 480 scan Lines & 25 Mhz Clock\r
- DB 3 ; Maximum of 3 Pages\r
- DW 320, 240 ; Displayed Pixels X,Y\r
- DW 1088, 818 ; Max Possible X and Y Sizes\r
- \r
- DW o MODE_320_Wide, o MODE_240_Tall\r
- DW o MODE_Double_Line, nil\r
- \r
-MODE_320x480: ; Data for 320 by 480 Pixels\r
- \r
- DB 0E3h ; 480 scan Lines & 25 Mhz Clock\r
- DB 1 ; Only 1 Page Possible\r
- DW 320, 480 ; Displayed Pixels X,Y\r
- DW 540, 818 ; Max Possible X and Y Sizes\r
- \r
- DW o MODE_320_WIDE, o MODE_480_Tall\r
- DW o MODE_Single_Line, nil\r
- \r
-MODE_360x200: ; Data for 360 by 200 Pixels\r
- \r
- DB 067h ; 400 scan Lines & 28 Mhz Clock\r
- DB 3 ; Maximum of 3 Pages\r
- DW 360, 200 ; Displayed Pixels (X,Y)\r
- DW 1302, 728 ; Max Possible X and Y Sizes\r
- \r
- DW o MODE_360_Wide, MODE_200_Tall\r
- DW o MODE_Double_Line, nil\r
- \r
-MODE_360x400: ; Data for 360 by 400 Pixels\r
- \r
- DB 067h ; 400 scan Lines & 28 Mhz Clock\r
- DB 1 ; Maximum of 1 Pages\r
- DW 360, 400 ; Displayed Pixels X,Y\r
- DW 648, 816 ; Max Possible X and Y Sizes\r
- \r
- DW o MODE_360_Wide, MODE_400_Tall\r
- DW o MODE_Single_Line, nil\r
- \r
- \r
- ; ===== MODE X SETUP ROUTINES =====\r
- \r
-;======================================================\r
-;SET_VGA_MODEX% (ModeType%, MaxXPos%, MaxYpos%, Pages%)\r
-;======================================================\r
-;\r
-; Sets Up the specified version of Mode X. Allows for\r
-; the setup of multiple video pages, and a virtual\r
-; screen which can be larger than the displayed screen\r
-; (which can then be scrolled a pixel at a time)\r
-;\r
-; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
-;\r
-; 0 = 320 x 200, 4 Pages max, 1.2:1 Aspect Ratio\r
-; 1 = 320 x 400, 2 Pages max, 2.4:1 Aspect Ratio\r
-; 2 = 360 x 200, 3 Pages max, 1.35:1 Aspect Ratio\r
-; 3 = 360 x 400, 1 Page max, 2.7:1 Aspect Ratio\r
-; 4 = 320 x 240, 3 Pages max, 1:1 Aspect Ratio\r
-; 5 = 320 x 480, 1 Page max, 2:1 Aspect Ratio\r
-; 6 = 360 x 240, 3 Pages max, 1.125:1 Aspect Ratio\r
-; 7 = 360 x 480, 1 Page max, 2.25:1 Aspect Ratio\r
-;\r
-; MaxXpos = The Desired Virtual Screen Width\r
-; MaxYpos = The Desired Virtual Screen Height\r
-; Pages = The Desired # of Video Pages\r
-;\r
-; EXIT: AX = Success Flag: 0 = Failure / -1= Success\r
-;\r
- \r
-SVM_STACK STRUC\r
- SVM_Table DW ? ; Offset of Mode Info Table\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- SVM_Pages DW ? ; # of Screen Pages desired\r
- SVM_Ysize DW ? ; Vertical Screen Size Desired\r
- SVM_Xsize DW ? ; Horizontal Screen Size Desired\r
- SVM_Mode DW ? ; Display Resolution Desired\r
-SVM_STACK ENDS\r
- \r
- PUBLIC SET_VGA_MODEX\r
- \r
-SET_VGA_MODEX PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- SUB SP, 2 ; Allocate workspace\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- ; Check Legality of Mode Request....\r
- \r
- MOV BX, [BP].SVM_Mode ; Get Requested Mode #\r
- CMP BX, NUM_MODES ; Is it 0..7?\r
- JAE @SVM_BadModeSetup ; If Not, Error out\r
- \r
- SHL BX, 1 ; Scale BX\r
- MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info\r
- MOV [BP].SVM_Table, SI ; Save ptr for later use\r
- \r
- ; Check # of Requested Display Pages\r
- \r
- MOV CX, [BP].SVM_Pages ; Get # of Requested Pages\r
- CLR CH ; Set Hi Word = 0!\r
- CMP CL, CS:[SI].M_Pages ; Check # Pages for mode\r
- JA @SVM_BadModeSetup ; Report Error if too Many Pages\r
- JCXZ @SVM_BadModeSetup ; Report Error if 0 Pages\r
- \r
- ; Check Validity of X Size\r
- \r
- AND [BP].SVM_XSize, 0FFF8h ; X size Mod 8 Must = 0\r
- \r
- MOV AX, [BP].SVM_XSize ; Get Logical Screen Width\r
- CMP AX, CS:[SI].M_XSize ; Check against Displayed X\r
- JB @SVM_BadModeSetup ; Report Error if too small\r
- CMP AX, CS:[SI].M_XMax ; Check against Max X\r
- JA @SVM_BadModeSetup ; Report Error if too big\r
- \r
- ; Check Validity of Y Size\r
- \r
- MOV BX, [BP].SVM_YSize ; Get Logical Screen Height\r
- CMP BX, CS:[SI].M_YSize ; Check against Displayed Y\r
- JB @SVM_BadModeSetup ; Report Error if too small\r
- CMP BX, CS:[SI].M_YMax ; Check against Max Y\r
- JA @SVM_BadModeSetup ; Report Error if too big\r
- \r
- ; Enough memory to Fit it all?\r
- \r
- SHR AX, 2 ; # of Bytes:Line = XSize/4\r
- MUL CX ; AX = Bytes/Line * Pages\r
- MUL BX ; DX:AX = Total VGA mem needed\r
- JNO @SVM_Continue ; Exit if Total Size > 256K\r
- \r
- DEC DX ; Was it Exactly 256K???\r
- OR DX, AX ; (DX = 1, AX = 0000)\r
- JZ @SVM_Continue ; if so, it's valid...\r
- \r
-@SVM_BadModeSetup:\r
- \r
- CLR AX ; Return Value = False\r
- JMP @SVM_Exit ; Normal Exit\r
- \r
-@SVM_Continue:\r
- \r
- MOV AX, 13H ; Start with Mode 13H\r
- INT 10H ; Let BIOS Set Mode\r
- \r
- OUT_16 SC_INDEX, CHAIN4_OFF ; Disable Chain 4 Mode\r
- OUT_16 SC_INDEX, ASYNC_RESET ; (A)synchronous Reset\r
- OUT_8 MISC_OUTPUT, CS:[SI].M_MiscR ; Set New Timing/Size\r
- OUT_16 SC_INDEX, SEQU_RESTART ; Restart Sequencer ...\r
- \r
- OUT_8 CRTC_INDEX, 11H ; Select Vert Retrace End Register\r
- INC DX ; Point to Data\r
- IN AL, DX ; Get Value, Bit 7 = Protect\r
- AND AL, 7FH ; Mask out Write Protect\r
- OUT DX, AL ; And send it back\r
- \r
- MOV DX, CRTC_INDEX ; Vga Crtc Registers\r
- ADD SI, M_CRTC ; SI -> CRTC Parameter Data\r
- \r
- ; Load Tables of CRTC Parameters from List of Tables\r
- \r
-@SVM_Setup_Table:\r
- \r
- MOV DI, CS:[SI] ; Get Pointer to CRTC Data Tbl\r
- ADD SI, 2 ; Point to next Ptr Entry\r
- OR DI, DI ; A nil Ptr means that we have\r
- JZ @SVM_Set_Data ; finished CRTC programming\r
- \r
-@SVM_Setup_CRTC:\r
- MOV AX, CS:[DI] ; Get CRTC Data from Table\r
- ADD DI, 2 ; Advance Pointer\r
- OR AX, AX ; At End of Data Table?\r
- JZ @SVM_Setup_Table ; If so, Exit & get next Table\r
- \r
- OUT DX, AX ; Reprogram VGA CRTC reg\r
- JMP s @SVM_Setup_CRTC ; Process Next Table Entry\r
- \r
- ; Initialize Page & Scroll info, DI = 0\r
- \r
-@SVM_Set_Data:\r
- MOV DISPLAY_PAGE, DI ; Display Page = 0\r
- MOV ACTIVE_PAGE, DI ; Active Page = 0\r
- MOV CURRENT_PAGE, DI ; Current Page (Offset) = 0\r
- MOV CURRENT_XOFFSET, DI ; Horz Scroll Index = 0\r
- MOV CURRENT_YOFFSET, DI ; Vert Scroll Index = 0\r
- MOV CURRENT_MOFFSET, DI ; Memory Scroll Index = 0\r
- \r
- MOV AX, VGA_SEGMENT ; Segment for VGA memory\r
- MOV CURRENT_SEGMENT, AX ; Save for Future LES's\r
- \r
- ; Set Logical Screen Width, X Scroll and Our Data\r
- \r
- MOV SI, [BP].SVM_Table ; Get Saved Ptr to Mode Info\r
- MOV AX, [BP].SVM_Xsize ; Get Display Width\r
- \r
- MOV CX, AX ; CX = Logical Width\r
- SUB CX, CS:[SI].M_XSize ; CX = Max X Scroll Value\r
- MOV MAX_XOFFSET, CX ; Set Maximum X Scroll\r
- \r
- SHR AX, 2 ; Bytes = Pixels / 4\r
- MOV SCREEN_WIDTH, AX ; Save Width in Pixels\r
- \r
- SHR AX, 1 ; Offset Value = Bytes / 2\r
- MOV AH, 13h ; CRTC Offset Register Index\r
- XCHG AL, AH ; Switch format for OUT\r
- OUT DX, AX ; Set VGA CRTC Offset Reg\r
- \r
- ; Setup Data table, Y Scroll, Misc for Other Routines\r
- \r
- MOV AX, [BP].SVM_Ysize ; Get Logical Screen Height\r
- \r
- MOV CX, AX ; CX = Logical Height\r
- SUB BX, CS:[SI].M_YSize ; CX = Max Y Scroll Value\r
- MOV MAX_YOFFSET, CX ; Set Maximum Y Scroll\r
- \r
- MOV SCREEN_HEIGHT, AX ; Save Height in Pixels\r
- MUL SCREEN_WIDTH ; AX = Page Size in Bytes,\r
- MOV PAGE_SIZE, AX ; Save Page Size\r
- \r
- MOV CX, [BP].SVM_Pages ; Get # of Pages\r
- MOV LAST_PAGE, CX ; Save # of Pages\r
- \r
- CLR BX ; Page # = 0\r
- MOV DX, BX ; Page 0 Offset = 0\r
- \r
-@SVM_Set_Pages:\r
- \r
- MOV PAGE_ADDR[BX], DX ; Set Page #(BX) Offset\r
- ADD BX, 2 ; Page#++\r
- ADD DX, AX ; Compute Addr of Next Page\r
- LOOPx CX, @SVM_Set_Pages ; Loop until all Pages Set\r
- \r
- ; Clear VGA Memory\r
- \r
- OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes\r
- LES DI, d CURRENT_PAGE ; -> Start of VGA memory\r
- \r
- CLR AX ; AX = 0\r
- CLD ; Block Xfer Forwards\r
- MOV CX, 8000H ; 32K * 4 * 2 = 256K\r
- REP STOSW ; Clear dat memory!\r
- \r
- ; Setup Font Pointers\r
- \r
- MOV BH, ROM_8x8_Lo ; Ask for 8x8 Font, 0-127\r
- MOV AX, GET_CHAR_PTR ; Service to Get Pointer\r
- INT 10h ; Call VGA BIOS\r
- \r
- MOV CHARSET_LOW, BP ; Save Char Set Offset\r
- MOV CHARSET_LOW+2, ES ; Save Char Set Segment\r
- \r
- MOV BH, ROM_8x8_Hi ; Ask for 8x8 Font, 128-255\r
- MOV AX, GET_CHAR_PTR ; Service to Get Pointer\r
- INT 10h ; Call VGA BIOS\r
- \r
- MOV CHARSET_HI, BP ; Save Char Set Offset\r
- MOV CHARSET_HI+2, ES ; Save Char Set Segment\r
- \r
- MOV AX, True ; Return Success Code\r
- \r
-@SVM_EXIT:\r
- ADD SP, 2 ; Deallocate workspace\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 8 ; Exit & Clean Up Stack\r
- \r
-SET_VGA_MODEX ENDP\r
- \r
- \r
-;==================\r
-;SET_MODEX% (Mode%)\r
-;==================\r
-;\r
-; Quickie Mode Set - Sets Up Mode X to Default Configuration\r
-;\r
-; ENTRY: ModeType = Desired Screen Resolution (0-7)\r
-; (See SET_VGA_MODEX for list)\r
-;\r
-; EXIT: AX = Success Flag: 0 = Failure / -1= Success\r
-;\r
- \r
-SM_STACK STRUC\r
- DW ?,? ; BP, SI\r
- DD ? ; Caller\r
- SM_Mode DW ? ; Desired Screen Resolution\r
-SM_STACK ENDS\r
- \r
- PUBLIC SET_MODEX\r
- \r
-SET_MODEX PROC FAR\r
- \r
- PUSHx BP, SI ; Preserve Important registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- CLR AX ; Assume Failure\r
- MOV BX, [BP].SM_Mode ; Get Desired Mode #\r
- CMP BX, NUM_MODES ; Is it a Valid Mode #?\r
- JAE @SMX_Exit ; If Not, don't Bother\r
- \r
- PUSH BX ; Push Mode Parameter\r
- \r
- SHL BX, 1 ; Scale BX to word Index\r
- MOV SI, w MODE_TABLE[BX] ; CS:SI -> Mode Info\r
- \r
- PUSH CS:[SI].M_XSize ; Push Default X Size\r
- PUSH CS:[SI].M_Ysize ; Push Default Y size\r
- MOV AL, CS:[SI].M_Pages ; Get Default # of Pages\r
- CLR AH ; Hi Byte = 0\r
- PUSH AX ; Push # Pages\r
- \r
- CALL f SET_VGA_MODEX ; Set up Mode X!\r
- \r
-@SMX_Exit:\r
- POPx SI, BP ; Restore Registers\r
- RET 2 ; Exit & Clean Up Stack\r
- \r
-SET_MODEX ENDP\r
- \r
- \r
- ; ===== BASIC GRAPHICS PRIMITIVES =====\r
- \r
-;============================\r
-;CLEAR_VGA_SCREEN (ColorNum%)\r
-;============================\r
-;\r
-; Clears the active display page\r
-;\r
-; ENTRY: ColorNum = Color Value to fill the page with\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-CVS_STACK STRUC\r
- DW ?,? ; DI, BP\r
- DD ? ; Caller\r
- CVS_COLOR DB ?,? ; Color to Set Screen to\r
-CVS_STACK ENDS\r
- \r
- PUBLIC CLEAR_VGA_SCREEN\r
- \r
-CLEAR_VGA_SCREEN PROC FAR\r
- \r
- PUSHx BP, DI ; Preserve Important Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- OUT_16 SC_INDEX, ALL_PLANES_ON ; Select All Planes\r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- \r
- MOV AL, [BP].CVS_COLOR ; Get Color\r
- MOV AH, AL ; Copy for Word Write\r
- CLD ; Block fill Forwards\r
- \r
- MOV CX, PAGE_SIZE ; Get Size of Page\r
- SHR CX, 1 ; Divide by 2 for Words\r
- REP STOSW ; Block Fill VGA memory\r
- \r
- POPx DI, BP ; Restore Saved Registers\r
- RET 2 ; Exit & Clean Up Stack\r
- \r
-CLEAR_VGA_SCREEN ENDP\r
- \r
- \r
-;===================================\r
-;SET_POINT (Xpos%, Ypos%, ColorNum%)\r
-;===================================\r
-;\r
-; Plots a single Pixel on the active display page\r
-;\r
-; ENTRY: Xpos = X position to plot pixel at\r
-; Ypos = Y position to plot pixel at\r
-; ColorNum = Color to plot pixel with\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-SP_STACK STRUC\r
- DW ?,? ; BP, DI\r
- DD ? ; Caller\r
- SETP_Color DB ?,? ; Color of Point to Plot\r
- SETP_Ypos DW ? ; Y pos of Point to Plot\r
- SETP_Xpos DW ? ; X pos of Point to Plot\r
-SP_STACK ENDS\r
- \r
- PUBLIC SET_POINT\r
- \r
-SET_POINT PROC FAR\r
- \r
- PUSHx BP, DI ; Preserve Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- \r
- MOV AX, [BP].SETP_Ypos ; Get Line # of Pixel\r
- MUL SCREEN_WIDTH ; Get Offset to Start of Line\r
- \r
- MOV BX, [BP].SETP_Xpos ; Get Xpos\r
- MOV CX, BX ; Copy to extract Plane # from\r
- SHR BX, 2 ; X offset (Bytes) = Xpos/4\r
- ADD BX, AX ; Offset = Width*Ypos + Xpos/4\r
- \r
- MOV AX, MAP_MASK_PLANE1 ; Map Mask & Plane Select Register\r
- AND CL, PLANE_BITS ; Get Plane Bits\r
- SHL AH, CL ; Get Plane Select Value\r
- OUT_16 SC_Index, AX ; Select Plane\r
- \r
- MOV AL,[BP].SETP_Color ; Get Pixel Color\r
- MOV ES:[DI+BX], AL ; Draw Pixel\r
- \r
- POPx DI, BP ; Restore Saved Registers\r
- RET 6 ; Exit and Clean up Stack\r
- \r
-SET_POINT ENDP\r
- \r
- \r
-;==========================\r
-;READ_POINT% (Xpos%, Ypos%)\r
-;==========================\r
-;\r
-; Read the color of a pixel from the Active Display Page\r
-;\r
-; ENTRY: Xpos = X position of pixel to read\r
-; Ypos = Y position of pixel to read\r
-;\r
-; EXIT: AX = Color of Pixel at (Xpos, Ypos)\r
-;\r
- \r
-RP_STACK STRUC\r
- DW ?,? ; BP, DI\r
- DD ? ; Caller\r
- RP_Ypos DW ? ; Y pos of Point to Read\r
- RP_Xpos DW ? ; X pos of Point to Read\r
-RP_STACK ENDS\r
- \r
- PUBLIC READ_POINT\r
- \r
-READ_POINT PROC FAR\r
- \r
- PUSHx BP, DI ; Preserve Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- \r
- MOV AX, [BP].RP_Ypos ; Get Line # of Pixel\r
- MUL SCREEN_WIDTH ; Get Offset to Start of Line\r
- \r
- MOV BX, [BP].RP_Xpos ; Get Xpos\r
- MOV CX, BX\r
- SHR BX, 2 ; X offset (Bytes) = Xpos/4\r
- ADD BX, AX ; Offset = Width*Ypos + Xpos/4\r
- \r
- MOV AL, READ_MAP ; GC Read Mask Register\r
- MOV AH, CL ; Get Xpos\r
- AND AH, PLANE_BITS ; & mask out Plane #\r
- OUT_16 GC_INDEX, AX ; Select Plane to read in\r
- \r
- CLR AH ; Clear Return Value Hi byte\r
- MOV AL, ES:[DI+BX] ; Get Color of Pixel\r
- \r
- POPx DI, BP ; Restore Saved Registers\r
- RET 4 ; Exit and Clean up Stack\r
- \r
-READ_POINT ENDP\r
- \r
- \r
-;======================================================\r
-;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
-;======================================================\r
-;\r
-; Fills a rectangular block on the active display Page\r
-;\r
-; ENTRY: Xpos1 = Left X position of area to fill\r
-; Ypos1 = Top Y position of area to fill\r
-; Xpos2 = Right X position of area to fill\r
-; Ypos2 = Bottom Y position of area to fill\r
-; ColorNum = Color to fill area with\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-FB_STACK STRUC\r
- DW ?x4 ; DS, DI, SI, BP\r
- DD ? ; Caller\r
- FB_Color DB ?,? ; Fill Color\r
- FB_Ypos2 DW ? ; Y pos of Lower Right Pixel\r
- FB_Xpos2 DW ? ; X pos of Lower Right Pixel\r
- FB_Ypos1 DW ? ; Y pos of Upper Left Pixel\r
- FB_Xpos1 DW ? ; X pos of Upper Left Pixel\r
-FB_STACK ENDS\r
- \r
- PUBLIC FILL_BLOCK\r
- \r
-FILL_BLOCK PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- CLD ; Direction Flag = Forward\r
- \r
- OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select\r
- \r
- ; Validate Pixel Coordinates\r
- ; If necessary, Swap so X1 <= X2, Y1 <= Y2\r
- \r
- MOV AX, [BP].FB_Ypos1 ; AX = Y1 is Y1< Y2?\r
- MOV BX, [BP].FB_Ypos2 ; BX = Y2\r
- CMP AX, BX\r
- JLE @FB_NOSWAP1\r
- \r
- MOV [BP].FB_Ypos1, BX ; Swap Y1 and Y2 and save Y1\r
- XCHG AX, BX ; on stack for future use\r
- \r
-@FB_NOSWAP1:\r
- SUB BX, AX ; Get Y width\r
- INC BX ; Add 1 to avoid 0 value\r
- MOV [BP].FB_Ypos2, BX ; Save in Ypos2\r
- \r
- MUL SCREEN_WIDTH ; Mul Y1 by Bytes per Line\r
- ADD DI, AX ; DI = Start of Line Y1\r
- \r
- MOV AX, [BP].FB_Xpos1 ; Check X1 <= X2\r
- MOV BX, [BP].FB_Xpos2 ;\r
- CMP AX, BX\r
- JLE @FB_NOSWAP2 ; Skip Ahead if Ok\r
- \r
- MOV [BP].FB_Xpos2, AX ; Swap X1 AND X2 and save X2\r
- XCHG AX, BX ; on stack for future use\r
- \r
- ; All our Input Values are in order, Now determine\r
- ; How many full "bands" 4 pixels wide (aligned) there\r
- ; are, and if there are partial bands (<4 pixels) on\r
- ; the left and right edges.\r
- \r
-@FB_NOSWAP2:\r
- MOV DX, AX ; DX = X1 (Pixel Position)\r
- SHR DX, 2 ; DX/4 = Bytes into Line\r
- ADD DI, DX ; DI = Addr of Upper-Left Corner\r
- \r
- MOV CX, BX ; CX = X2 (Pixel Position)\r
- SHR CX, 2 ; CX/4 = Bytes into Line\r
- \r
- CMP DX, CX ; Start and end in same band?\r
- JNE @FB_NORMAL ; if not, check for l & r edges\r
- JMP @FB_ONE_BAND_ONLY ; if so, then special processing\r
- \r
-@FB_NORMAL:\r
- SUB CX, DX ; CX = # bands -1\r
- MOV SI, AX ; SI = PLANE#(X1)\r
- AND SI, PLANE_BITS ; if Left edge is aligned then\r
- JZ @FB_L_PLANE_FLUSH ; no special processing..\r
- \r
- ; Draw "Left Edge" vertical strip of 1-3 pixels...\r
- \r
- OUT_8 SC_Data, Left_Clip_Mask[SI] ; Set Left Edge Plane Mask\r
- \r
- MOV SI, DI ; SI = Copy of Start Addr (UL)\r
- \r
- MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw\r
- MOV AL, [BP].FB_Color ; Get Fill Color\r
- MOV BX, SCREEN_WIDTH ; Get Vertical increment Value\r
- \r
-@FB_LEFT_LOOP:\r
- MOV ES:[SI], AL ; Fill in Left Edge Pixels\r
- ADD SI, BX ; Point to Next Line (Below)\r
- LOOPjz DX, @FB_LEFT_CONT ; Exit loop if all Lines Drawn\r
- \r
- MOV ES:[SI], AL ; Fill in Left Edge Pixels\r
- ADD SI, BX ; Point to Next Line (Below)\r
- LOOPx DX, @FB_LEFT_LOOP ; loop until left strip is drawn\r
- \r
-@FB_LEFT_CONT:\r
- \r
- INC DI ; Point to Middle (or Right) Block\r
- DEC CX ; Reset CX instead of JMP @FB_RIGHT\r
- \r
-@FB_L_PLANE_FLUSH:\r
- INC CX ; Add in Left band to middle block\r
- \r
- ; DI = Addr of 1st middle Pixel (band) to fill\r
- ; CX = # of Bands to fill -1\r
- \r
-@FB_RIGHT:\r
- MOV SI, [BP].FB_Xpos2 ; Get Xpos2\r
- AND SI, PLANE_BITS ; Get Plane values\r
- CMP SI, 0003 ; Plane = 3?\r
- JE @FB_R_EDGE_FLUSH ; Hey, add to middle\r
- \r
- ; Draw "Right Edge" vertical strip of 1-3 pixels...\r
- \r
- OUT_8 SC_Data, Right_Clip_Mask[SI] ; Right Edge Plane Mask\r
- \r
- MOV SI, DI ; Get Addr of Left Edge\r
- ADD SI, CX ; Add Width-1 (Bands)\r
- DEC SI ; To point to top of Right Edge\r
- \r
- MOV DX, [BP].FB_Ypos2 ; Get # of Lines to draw\r
- MOV AL, [BP].FB_Color ; Get Fill Color\r
- MOV BX, SCREEN_WIDTH ; Get Vertical increment Value\r
- \r
-@FB_RIGHT_LOOP:\r
- MOV ES:[SI], AL ; Fill in Right Edge Pixels\r
- ADD SI, BX ; Point to Next Line (Below)\r
- LOOPjz DX, @FB_RIGHT_CONT ; Exit loop if all Lines Drawn\r
- \r
- MOV ES:[SI], AL ; Fill in Right Edge Pixels\r
- ADD SI, BX ; Point to Next Line (Below)\r
- LOOPx DX, @FB_RIGHT_LOOP ; loop until left strip is drawn\r
- \r
-@FB_RIGHT_CONT:\r
- \r
- DEC CX ; Minus 1 for Middle bands\r
- JZ @FB_EXIT ; Uh.. no Middle bands...\r
- \r
-@FB_R_EDGE_FLUSH:\r
- \r
- ; DI = Addr of Upper Left block to fill\r
- ; CX = # of Bands to fill in (width)\r
- \r
- OUT_8 SC_Data, ALL_PLANES ; Write to All Planes\r
- \r
- MOV DX, SCREEN_WIDTH ; DX = DI Increment\r
- SUB DX, CX ; = Screen_Width-# Planes Filled\r
- \r
- MOV BX, CX ; BX = Quick Refill for CX\r
- MOV SI, [BP].FB_Ypos2 ; SI = # of Line to Fill\r
- MOV AL, [BP].FB_Color ; Get Fill Color\r
- \r
-@FB_MIDDLE_LOOP:\r
- REP STOSB ; Fill in entire line\r
- \r
- MOV CX, BX ; Recharge CX (Line Width)\r
- ADD DI, DX ; Point to start of Next Line\r
- LOOPx SI, @FB_MIDDLE_LOOP ; Loop until all lines drawn\r
- \r
- JMP s @FB_EXIT ; Outa here\r
- \r
-@FB_ONE_BAND_ONLY:\r
- MOV SI, AX ; Get Left Clip Mask, Save X1\r
- AND SI, PLANE_BITS ; Mask out Row #\r
- MOV AL, Left_Clip_Mask[SI] ; Get Left Edge Mask\r
- MOV SI, BX ; Get Right Clip Mask, Save X2\r
- AND SI, PLANE_BITS ; Mask out Row #\r
- AND AL, Right_Clip_Mask[SI] ; Get Right Edge Mask byte\r
- \r
- OUT_8 SC_Data, AL ; Clip For Left & Right Masks\r
- \r
- MOV CX, [BP].FB_Ypos2 ; Get # of Lines to draw\r
- MOV AL, [BP].FB_Color ; Get Fill Color\r
- MOV BX, SCREEN_WIDTH ; Get Vertical increment Value\r
- \r
-@FB_ONE_LOOP:\r
- MOV ES:[DI], AL ; Fill in Pixels\r
- ADD DI, BX ; Point to Next Line (Below)\r
- LOOPjz CX, @FB_EXIT ; Exit loop if all Lines Drawn\r
- \r
- MOV ES:[DI], AL ; Fill in Pixels\r
- ADD DI, BX ; Point to Next Line (Below)\r
- LOOPx CX, @FB_ONE_LOOP ; loop until left strip is drawn\r
- \r
-@FB_EXIT:\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 10 ; Exit and Clean up Stack\r
- \r
-FILL_BLOCK ENDP\r
- \r
- \r
-;=====================================================\r
-;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%)\r
-;=====================================================\r
-;\r
-; Draws a Line on the active display page\r
-;\r
-; ENTRY: Xpos1 = X position of first point on line\r
-; Ypos1 = Y position of first point on line\r
-; Xpos2 = X position of last point on line\r
-; Ypos2 = Y position of last point on line\r
-; ColorNum = Color to draw line with\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-DL_STACK STRUC\r
- DW ?x3 ; DI, SI, BP\r
- DD ? ; Caller\r
- DL_ColorF DB ?,? ; Line Draw Color\r
- DL_Ypos2 DW ? ; Y pos of last point\r
- DL_Xpos2 DW ? ; X pos of last point\r
- DL_Ypos1 DW ? ; Y pos of first point\r
- DL_Xpos1 DW ? ; X pos of first point\r
-DL_STACK ENDS\r
- \r
- PUBLIC DRAW_LINE\r
- \r
-DRAW_LINE PROC FAR\r
- \r
- PUSHx BP, SI, DI ; Preserve Important Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- CLD ; Direction Flag = Forward\r
- \r
- OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select\r
- MOV CH, [BP].DL_ColorF ; Save Line Color in CH\r
- \r
- ; Check Line Type\r
- \r
- MOV SI, [BP].DL_Xpos1 ; AX = X1 is X1< X2?\r
- MOV DI, [BP].DL_Xpos2 ; DX = X2\r
- CMP SI, DI ; Is X1 < X2\r
- JE @DL_VLINE ; If X1=X2, Draw Vertical Line\r
- JL @DL_NOSWAP1 ; If X1 < X2, don't swap\r
- \r
- XCHG SI, DI ; X2 IS > X1, SO SWAP THEM\r
- \r
-@DL_NOSWAP1:\r
- \r
- ; SI = X1, DI = X2\r
- \r
- MOV AX, [BP].DL_Ypos1 ; AX = Y1 is Y1 <> Y2?\r
- CMP AX, [BP].DL_Ypos2 ; Y1 = Y2?\r
- JE @DL_HORZ ; If so, Draw a Horizontal Line\r
- \r
- JMP @DL_BREZHAM ; Diagonal line... go do it...\r
- \r
- ; This Code draws a Horizontal Line in Mode X where:\r
- ; SI = X1, DI = X2, and AX = Y1/Y2\r
- \r
-@DL_HORZ:\r
- \r
- MUL SCREEN_WIDTH ; Offset = Ypos * Screen_Width\r
- MOV DX, AX ; CX = Line offset into Page\r
- \r
- MOV AX, SI ; Get Left edge, Save X1\r
- AND SI, PLANE_BITS ; Mask out Row #\r
- MOV BL, Left_Clip_Mask[SI] ; Get Left Edge Mask\r
- MOV CX, DI ; Get Right edge, Save X2\r
- AND DI, PLANE_BITS ; Mask out Row #\r
- MOV BH, Right_Clip_Mask[DI] ; Get Right Edge Mask byte\r
- \r
- SHR AX, 2 ; Get X1 Byte # (=X1/4)\r
- SHR CX, 2 ; Get X2 Byte # (=X2/4)\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- ADD DI, DX ; Point to Start of Line\r
- ADD DI, AX ; Point to Pixel X1\r
- \r
- SUB CX, AX ; CX = # Of Bands (-1) to set\r
- JNZ @DL_LONGLN ; jump if longer than one segment\r
- \r
- AND BL, BH ; otherwise, merge clip masks\r
- \r
-@DL_LONGLN:\r
- \r
- OUT_8 SC_Data, BL ; Set the Left Clip Mask\r
- \r
- MOV AL, [BP].DL_ColorF ; Get Line Color\r
- MOV BL, AL ; BL = Copy of Line Color\r
- STOSB ; Set Left (1-4) Pixels\r
- \r
- JCXZ @DL_EXIT ; Done if only one Line Segment\r
- \r
- DEC CX ; CX = # of Middle Segments\r
- JZ @DL_XRSEG ; If no middle segments....\r
- \r
- ; Draw Middle Segments\r
- \r
- OUT_8 DX, ALL_PLANES ; Write to ALL Planes\r
- \r
- MOV AL, BL ; Get Color from BL\r
- REP STOSB ; Draw Middle (4 Pixel) Segments\r
- \r
-@DL_XRSEG:\r
- OUT_8 DX, BH ; Select Planes for Right Clip Mask\r
- MOV AL, BL ; Get Color Value\r
- STOSB ; Draw Right (1-4) Pixels\r
- \r
- JMP s @DL_EXIT ; We Are Done...\r
- \r
- \r
- ; This Code Draws A Vertical Line. On entry:\r
- ; CH = Line Color, SI & DI = X1\r
- \r
-@DL_VLINE:\r
- \r
- MOV AX, [BP].DL_Ypos1 ; AX = Y1\r
- MOV SI, [BP].DL_Ypos2 ; SI = Y2\r
- CMP AX, SI ; Is Y1 < Y2?\r
- JLE @DL_NOSWAP2 ; if so, Don't Swap them\r
- \r
- XCHG AX, SI ; Ok, NOW Y1 < Y2\r
- \r
-@DL_NOSWAP2:\r
- \r
- SUB SI, AX ; SI = Line Height (Y2-Y1+1)\r
- INC SI\r
- \r
- ; AX = Y1, DI = X1, Get offset into Page into AX\r
- \r
- MUL SCREEN_WIDTH ; Offset = Y1 (AX) * Screen Width\r
- MOV DX, DI ; Copy Xpos into DX\r
- SHR DI, 2 ; DI = Xpos/4\r
- ADD AX, DI ; DI = Xpos/4 + ScreenWidth * Y1\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- ADD DI, AX ; Point to Pixel X1, Y1\r
- \r
- ;Select Plane\r
- \r
- MOV CL, DL ; CL = Save X1\r
- AND CL, PLANE_BITS ; Get X1 MOD 4 (Plane #)\r
- MOV AX, MAP_MASK_PLANE1 ; Code to set Plane #1\r
- SHL AH, CL ; Change to Correct Plane #\r
- OUT_16 SC_Index, AX ; Select Plane\r
- \r
- MOV AL, CH ; Get Saved Color\r
- MOV BX, SCREEN_WIDTH ; Get Offset to Advance Line By\r
- \r
-@DL_VLoop:\r
- MOV ES:[DI], AL ; Draw Single Pixel\r
- ADD DI, BX ; Point to Next Line\r
- LOOPjz SI, @DL_EXIT ; Lines--, Exit if done\r
- \r
- MOV ES:[DI], AL ; Draw Single Pixel\r
- ADD DI, BX ; Point to Next Line\r
- LOOPx SI, @DL_VLoop ; Lines--, Loop until Done\r
- \r
-@DL_EXIT:\r
- \r
- JMP @DL_EXIT2 ; Done!\r
- \r
- ; This code Draws a diagonal line in Mode X\r
- \r
-@DL_BREZHAM:\r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- \r
- MOV AX, [BP].DL_Ypos1 ; get Y1 value\r
- MOV BX, [BP].DL_Ypos2 ; get Y2 value\r
- MOV CX, [BP].DL_Xpos1 ; Get Starting Xpos\r
- \r
- CMP BX, AX ; Y2-Y1 is?\r
- JNC @DL_DeltaYOK ; if Y2>=Y1 then goto...\r
- \r
- XCHG BX, AX ; Swap em...\r
- MOV CX, [BP].DL_Xpos2 ; Get New Starting Xpos\r
- \r
-@DL_DeltaYOK:\r
- MUL SCREEN_WIDTH ; Offset = SCREEN_WIDTH * Y1\r
- \r
- ADD DI, AX ; DI -> Start of Line Y1 on Page\r
- MOV AX, CX ; AX = Xpos (X1)\r
- SHR AX, 2 ; /4 = Byte Offset into Line\r
- ADD DI, AX ; DI = Starting pos (X1,Y1)\r
- \r
- MOV AL, 11h ; Staring Mask\r
- AND CL, PLANE_BITS ; Get Plane #\r
- SHL AL, CL ; and shift into place\r
- MOV AH, [BP].DL_ColorF ; Color in Hi Bytes\r
- \r
- PUSH AX ; Save Mask,Color...\r
- \r
- MOV AH, AL ; Plane # in AH\r
- MOV AL, MAP_MASK ; Select Plane Register\r
- OUT_16 SC_Index, AX ; Select initial plane\r
- \r
- MOV AX, [BP].DL_Xpos1 ; get X1 value\r
- MOV BX, [BP].DL_Ypos1 ; get Y1 value\r
- MOV CX, [BP].DL_Xpos2 ; get X2 value\r
- MOV DX, [BP].DL_Ypos2 ; get Y2 value\r
- \r
- MOV BP, SCREEN_WIDTH ; Use BP for Line width to\r
- ; to avoid extra memory access\r
- \r
- SUB DX, BX ; figure Delta_Y\r
- JNC @DL_DeltaYOK2 ; jump if Y2 >= Y1\r
- \r
- ADD BX, DX ; put Y2 into Y1\r
- NEG DX ; abs(Delta_Y)\r
- XCHG AX, CX ; and exchange X1 and X2\r
- \r
-@DL_DeltaYOK2:\r
- MOV BX, 08000H ; seed for fraction accumulator\r
- \r
- SUB CX, AX ; figure Delta_X\r
- JC @DL_DrawLeft ; if negative, go left\r
- \r
- JMP @DL_DrawRight ; Draw Line that slopes right\r
- \r
-@DL_DrawLeft:\r
- \r
- NEG CX ; abs(Delta_X)\r
- \r
- CMP CX, DX ; is Delta_X < Delta_Y?\r
- JB @DL_SteepLeft ; yes, so go do steep line\r
- ; (Delta_Y iterations)\r
- \r
- ; Draw a Shallow line to the left in Mode X\r
- \r
-@DL_ShallowLeft:\r
- CLR AX ; zero low word of Delta_Y * 10000h\r
- SUB AX, DX ; DX:AX <- DX * 0FFFFh\r
- SBB DX, 0 ; include carry\r
- DIV CX ; divide by Delta_X\r
- \r
- MOV SI, BX ; SI = Accumulator\r
- MOV BX, AX ; BX = Add fraction\r
- POP AX ; Get Color, Bit mask\r
- MOV DX, SC_Data ; Sequence controller data register\r
- INC CX ; Inc Delta_X so we can unroll loop\r
- \r
- ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down...\r
- \r
-@DL_SLLLoop:\r
- MOV ES:[DI], AH ; set first pixel, plane data set up\r
- LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done\r
- \r
- ADD SI, BX ; add numerator to accumulator\r
- JNC @DL_SLLL2nc ; move down on carry\r
- \r
- ADD DI, BP ; Move Down one line...\r
- \r
-@DL_SLLL2nc:\r
- DEC DI ; Left one addr\r
- ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
- CMP AL, 87h ; wrap?, if AL <88 then Carry set\r
- ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
- OUT DX, AL ; Set up New Bit Plane mask\r
- \r
- MOV ES:[DI], AH ; set pixel\r
- LOOPjz CX, @DL_SLLExit ; Delta_X--, Exit if done\r
- \r
- ADD SI, BX ; add numerator to accumulator,\r
- JNC @DL_SLLL3nc ; move down on carry\r
- \r
- ADD DI, BP ; Move Down one line...\r
- \r
-@DL_SLLL3nc: ; Now move left a pixel...\r
- DEC DI ; Left one addr\r
- ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
- CMP AL, 87h ; Wrap?, if AL <88 then Carry set\r
- ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
- OUT DX, AL ; Set up New Bit Plane mask\r
- JMP s @DL_SLLLoop ; loop until done\r
- \r
-@DL_SLLExit:\r
- JMP @DL_EXIT2 ; and exit\r
- \r
- ; Draw a steep line to the left in Mode X\r
- \r
-@DL_SteepLeft:\r
- CLR AX ; zero low word of Delta_Y * 10000h\r
- XCHG DX, CX ; Delta_Y switched with Delta_X\r
- DIV CX ; divide by Delta_Y\r
- \r
- MOV SI, BX ; SI = Accumulator\r
- MOV BX, AX ; BX = Add Fraction\r
- POP AX ; Get Color, Bit mask\r
- MOV DX, SC_Data ; Sequence controller data register\r
- INC CX ; Inc Delta_Y so we can unroll loop\r
- \r
- ; Loop (x2) to Draw Pixels, Move Down, and Maybe left\r
- \r
-@DL_STLLoop:\r
- \r
- MOV ES:[DI], AH ; set first pixel\r
- LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done\r
- \r
- ADD SI, BX ; add numerator to accumulator\r
- JNC @DL_STLnc2 ; No carry, just move down!\r
- \r
- DEC DI ; Move Left one addr\r
- ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
- CMP AL, 87h ; Wrap?, if AL <88 then Carry set\r
- ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
- OUT DX, AL ; Set up New Bit Plane mask\r
- \r
-@DL_STLnc2:\r
- ADD DI, BP ; advance to next line.\r
- \r
- MOV ES:[DI], AH ; set pixel\r
- LOOPjz CX, @DL_STLExit ; Delta_Y--, Exit if done\r
- \r
- ADD SI, BX ; add numerator to accumulator\r
- JNC @DL_STLnc3 ; No carry, just move down!\r
- \r
- DEC DI ; Move Left one addr\r
- ROR AL, 1 ; Move Left one plane, back on 0 1 2\r
- CMP AL, 87h ; Wrap?, if AL <88 then Carry set\r
- ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
- OUT DX, AL ; Set up New Bit Plane mask\r
- \r
-@DL_STLnc3:\r
- ADD DI, BP ; advance to next line.\r
- JMP s @DL_STLLoop ; Loop until done\r
- \r
-@DL_STLExit:\r
- JMP @DL_EXIT2 ; and exit\r
- \r
- ; Draw a line that goes to the Right...\r
- \r
-@DL_DrawRight:\r
- CMP CX, DX ; is Delta_X < Delta_Y?\r
- JB @DL_SteepRight ; yes, so go do steep line\r
- ; (Delta_Y iterations)\r
- \r
- ; Draw a Shallow line to the Right in Mode X\r
- \r
-@DL_ShallowRight:\r
- CLR AX ; zero low word of Delta_Y * 10000h\r
- SUB AX, DX ; DX:AX <- DX * 0FFFFh\r
- SBB DX, 0 ; include carry\r
- DIV CX ; divide by Delta_X\r
- \r
- MOV SI, BX ; SI = Accumulator\r
- MOV BX, AX ; BX = Add Fraction\r
- POP AX ; Get Color, Bit mask\r
- MOV DX, SC_Data ; Sequence controller data register\r
- INC CX ; Inc Delta_X so we can unroll loop\r
- \r
- ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down...\r
- \r
-@DL_SLRLoop:\r
- MOV ES:[DI], AH ; set first pixel, mask is set up\r
- LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done..\r
- \r
- ADD SI, BX ; add numerator to accumulator\r
- JNC @DL_SLR2nc ; don't move down if carry not set\r
- \r
- ADD DI, BP ; Move Down one line...\r
- \r
-@DL_SLR2nc: ; Now move right a pixel...\r
- ROL AL, 1 ; Move Right one addr if Plane = 0\r
- CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
- ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
- OUT DX, AL ; Set up New Bit Plane mask\r
- \r
- MOV ES:[DI], AH ; set pixel\r
- LOOPjz CX, @DL_SLRExit ; Delta_X--, Exit if done..\r
- \r
- ADD SI, BX ; add numerator to accumulator\r
- JNC @DL_SLR3nc ; don't move down if carry not set\r
- \r
- ADD DI, BP ; Move Down one line...\r
- \r
-@DL_SLR3nc:\r
- ROL AL, 1 ; Move Right one addr if Plane = 0\r
- CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
- ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
- OUT DX, AL ; Set up New Bit Plane mask\r
- JMP s @DL_SLRLoop ; loop till done\r
- \r
-@DL_SLRExit:\r
- JMP @DL_EXIT2 ; and exit\r
- \r
- ; Draw a Steep line to the Right in Mode X\r
- \r
-@DL_SteepRight:\r
- CLR AX ; zero low word of Delta_Y * 10000h\r
- XCHG DX, CX ; Delta_Y switched with Delta_X\r
- DIV CX ; divide by Delta_Y\r
- \r
- MOV SI, BX ; SI = Accumulator\r
- MOV BX, AX ; BX = Add Fraction\r
- POP AX ; Get Color, Bit mask\r
- MOV DX, SC_Data ; Sequence controller data register\r
- INC CX ; Inc Delta_Y so we can unroll loop\r
- \r
- ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right\r
- \r
-@STRLoop:\r
- MOV ES:[DI], AH ; set first pixel, mask is set up\r
- LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done\r
- \r
- ADD SI, BX ; add numerator to accumulator\r
- JNC @STRnc2 ; if no carry then just go down...\r
- \r
- ROL AL, 1 ; Move Right one addr if Plane = 0\r
- CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
- ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
- OUT DX, AL ; Set up New Bit Plane mask\r
- \r
-@STRnc2:\r
- ADD DI, BP ; advance to next line.\r
- \r
- MOV ES:[DI], AH ; set pixel\r
- LOOPjz CX, @DL_EXIT2 ; Delta_Y--, Exit if Done\r
- \r
- ADD SI, BX ; add numerator to accumulator\r
- JNC @STRnc3 ; if no carry then just go down...\r
- \r
- ROL AL, 1 ; Move Right one addr if Plane = 0\r
- CMP AL, 12h ; Wrap? if AL >12 then Carry not set\r
- ADC DI, 0 ; Adjust Address: DI = DI + Carry\r
- OUT DX, AL ; Set up New Bit Plane mask\r
- \r
-@STRnc3:\r
- ADD DI, BP ; advance to next line.\r
- JMP s @STRLoop ; loop till done\r
- \r
-@DL_EXIT2:\r
- POPx DI, SI, BP ; Restore Saved Registers\r
- RET 10 ; Exit and Clean up Stack\r
- \r
-DRAW_LINE ENDP\r
- \r
- \r
- ; ===== DAC COLOR REGISTER ROUTINES =====\r
- \r
-;=================================================\r
-;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%)\r
-;=================================================\r
-;\r
-; Sets a single (RGB) Vga Palette Register\r
-;\r
-; ENTRY: Register = The DAC # to modify (0-255)\r
-; Red = The new Red Intensity (0-63)\r
-; Green = The new Green Intensity (0-63)\r
-; Blue = The new Blue Intensity (0-63)\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-SDR_STACK STRUC\r
- DW ? ; BP\r
- DD ? ; Caller\r
- SDR_Blue DB ?,? ; Blue Data Value\r
- SDR_Green DB ?,? ; Green Data Value\r
- SDR_Red DB ?,? ; Red Data Value\r
- SDR_Register DB ?,? ; Palette Register #\r
-SDR_STACK ENDS\r
- \r
- PUBLIC SET_DAC_REGISTER\r
- \r
-SET_DAC_REGISTER PROC FAR\r
- \r
- PUSH BP ; Save BP\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- ; Select which DAC Register to modify\r
- \r
- OUT_8 DAC_WRITE_ADDR, [BP].SDR_Register\r
- \r
- MOV DX, PEL_DATA_REG ; Dac Data Register\r
- OUT_8 DX, [BP].SDR_Red ; Set Red Intensity\r
- OUT_8 DX, [BP].SDR_Green ; Set Green Intensity\r
- OUT_8 DX, [BP].SDR_Blue ; Set Blue Intensity\r
- \r
- POP BP ; Restore Registers\r
- RET 8 ; Exit & Clean Up Stack\r
- \r
-SET_DAC_REGISTER ENDP\r
- \r
-;====================================================\r
-;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%)\r
-;====================================================\r
-;\r
-; Reads the RGB Values of a single Vga Palette Register\r
-;\r
-; ENTRY: Register = The DAC # to read (0-255)\r
-; Red = Offset to Red Variable in DS\r
-; Green = Offset to Green Variable in DS\r
-; Blue = Offset to Blue Variable in DS\r
-;\r
-; EXIT: The values of the integer variables Red,\r
-; Green, and Blue are set to the values\r
-; taken from the specified DAC register.\r
-;\r
- \r
-GDR_STACK STRUC\r
- DW ? ; BP\r
- DD ? ; Caller\r
- GDR_Blue DW ? ; Addr of Blue Data Value in DS\r
- GDR_Green DW ? ; Addr of Green Data Value in DS\r
- GDR_Red DW ? ; Addr of Red Data Value in DS\r
- GDR_Register DB ?,? ; Palette Register #\r
-GDR_STACK ENDS\r
- \r
- PUBLIC GET_DAC_REGISTER\r
- \r
-GET_DAC_REGISTER PROC FAR\r
- \r
- PUSH BP ; Save BP\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- ; Select which DAC Register to read in\r
- \r
- OUT_8 DAC_READ_ADDR, [BP].GDR_Register\r
- \r
- MOV DX, PEL_DATA_REG ; Dac Data Register\r
- CLR AX ; Clear AX\r
- \r
- IN AL, DX ; Read Red Value\r
- MOV BX, [BP].GDR_Red ; Get Address of Red%\r
- MOV [BX], AX ; *Red% = AX\r
- \r
- IN AL, DX ; Read Green Value\r
- MOV BX, [BP].GDR_Green ; Get Address of Green%\r
- MOV [BX], AX ; *Green% = AX\r
- \r
- IN AL, DX ; Read Blue Value\r
- MOV BX, [BP].GDR_Blue ; Get Address of Blue%\r
- MOV [BX], AX ; *Blue% = AX\r
- \r
- POP BP ; Restore Registers\r
- RET 8 ; Exit & Clean Up Stack\r
- \r
-GET_DAC_REGISTER ENDP\r
- \r
- \r
-;===========================================================\r
-;LOAD_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%, Sync%)\r
-;===========================================================\r
-;\r
-; Sets a Block of Vga Palette Registers\r
-;\r
-; ENTRY: PalData = Far Pointer to Block of palette data\r
-; StartReg = First Register # in range to set (0-255)\r
-; EndReg = Last Register # in Range to set (0-255)\r
-; Sync = Wait for Vertical Retrace Flag (Boolean)\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
-; NOTES: PalData is a linear array of 3 byte Palette values\r
-; in the order: Red (0-63), Green (0-63), Blue (0-63)\r
-;\r
- \r
-LDR_STACK STRUC\r
- DW ?x3 ; BP, DS, SI\r
- DD ? ; Caller\r
- LDR_Sync DW ? ; Vertical Sync Flag\r
- LDR_EndReg DB ?,? ; Last Register #\r
- LDR_StartReg DB ?,? ; First Register #\r
- LDR_PalData DD ? ; Far Ptr to Palette Data\r
-LDR_STACK ENDS\r
- \r
- PUBLIC LOAD_DAC_REGISTERS\r
- \r
-LOAD_DAC_REGISTERS PROC FAR\r
- \r
- PUSHx BP, DS, SI ; Save Registers\r
- mov BP, SP ; Set up Stack Frame\r
- \r
- mov AX, [BP].LDR_Sync ; Get Vertical Sync Flag\r
- or AX, AX ; is Sync Flag = 0?\r
- jz @LDR_Load ; if so, skip call\r
- \r
- call f SYNC_DISPLAY ; wait for vsync\r
- \r
- ; Determine register #'s, size to copy, etc\r
- \r
-@LDR_Load:\r
- \r
- lds SI, [BP].LDR_PalData ; DS:SI -> Palette Data\r
- mov DX, DAC_WRITE_ADDR ; DAC register # selector\r
- \r
- CLR AX, BX ; Clear for byte loads\r
- mov AL, [BP].LDR_StartReg ; Get Start Register\r
- mov BL, [BP].LDR_EndReg ; Get End Register\r
- \r
- sub BX, AX ; BX = # of DAC registers -1\r
- inc BX ; BX = # of DAC registers\r
- mov CX, BX ; CX = # of DAC registers\r
- add CX, BX ; CX = " " * 2\r
- add CX, BX ; CX = " " * 3\r
- cld ; Block OUTs forward\r
- out DX, AL ; set up correct register #\r
- \r
- ; Load a block of DAC Registers\r
- \r
- mov DX, PEL_DATA_REG ; Dac Data Register\r
- \r
- rep outsb ; block set DAC registers\r
- \r
- POPx SI, DS, BP ; Restore Registers\r
- ret 10 ; Exit & Clean Up Stack\r
- \r
-LOAD_DAC_REGISTERS ENDP\r
- \r
- \r
-;====================================================\r
-;READ_DAC_REGISTERS (SEG PalData, StartReg%, EndReg%)\r
-;====================================================\r
-;\r
-; Reads a Block of Vga Palette Registers\r
-;\r
-; ENTRY: PalData = Far Pointer to block to store palette data\r
-; StartReg = First Register # in range to read (0-255)\r
-; EndReg = Last Register # in Range to read (0-255)\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
-; NOTES: PalData is a linear array of 3 byte Palette values\r
-; in the order: Red (0-63), Green (0-63), Blue (0-63)\r
-;\r
- \r
-RDR_STACK STRUC\r
- DW ?x3 ; BP, ES, DI\r
- DD ? ; Caller\r
- RDR_EndReg DB ?,? ; Last Register #\r
- RDR_StartReg DB ?,? ; First Register #\r
- RDR_PalData DD ? ; Far Ptr to Palette Data\r
-RDR_STACK ENDS\r
- \r
- PUBLIC READ_DAC_REGISTERS\r
- \r
-READ_DAC_REGISTERS PROC FAR\r
- \r
- PUSHx BP, ES, DI ; Save Registers\r
- mov BP, SP ; Set up Stack Frame\r
- \r
- ; Determine register #'s, size to copy, etc\r
- \r
- les DI, [BP].RDR_PalData ; ES:DI -> Palette Buffer\r
- mov DX, DAC_READ_ADDR ; DAC register # selector\r
- \r
- CLR AX, BX ; Clear for byte loads\r
- mov AL, [BP].RDR_StartReg ; Get Start Register\r
- mov BL, [BP].RDR_EndReg ; Get End Register\r
- \r
- sub BX, AX ; BX = # of DAC registers -1\r
- inc BX ; BX = # of DAC registers\r
- mov CX, BX ; CX = # of DAC registers\r
- add CX, BX ; CX = " " * 2\r
- add CX, BX ; CX = " " * 3\r
- cld ; Block INs forward\r
- \r
- ; Read a block of DAC Registers\r
- \r
- out DX, AL ; set up correct register #\r
- mov DX, PEL_DATA_REG ; Dac Data Register\r
- \r
- rep insb ; block read DAC registers\r
- \r
- POPx DI, ES, BP ; Restore Registers\r
- ret 8 ; Exit & Clean Up Stack\r
- \r
-READ_DAC_REGISTERS ENDP\r
- \r
- \r
- ; ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
- \r
-;=========================\r
-;SET_ACTIVE_PAGE (PageNo%)\r
-;=========================\r
-;\r
-; Sets the active display Page to be used for future drawing\r
-;\r
-; ENTRY: PageNo = Display Page to make active\r
-; (values: 0 to Number of Pages - 1)\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-SAP_STACK STRUC\r
- DW ? ; BP\r
- DD ? ; Caller\r
- SAP_Page DW ? ; Page # for Drawing\r
-SAP_STACK ENDS\r
- \r
- PUBLIC SET_ACTIVE_PAGE\r
- \r
-SET_ACTIVE_PAGE PROC FAR\r
- \r
- PUSH BP ; Preserve Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- MOV BX, [BP].SAP_Page ; Get Desired Page #\r
- CMP BX, LAST_PAGE ; Is Page # Valid?\r
- JAE @SAP_Exit ; IF Not, Do Nothing\r
- \r
- MOV ACTIVE_PAGE, BX ; Set Active Page #\r
- \r
- SHL BX, 1 ; Scale Page # to Word\r
- MOV AX, PAGE_ADDR[BX] ; Get offset to Page\r
- \r
- MOV CURRENT_PAGE, AX ; And set for future LES's\r
- \r
-@SAP_Exit:\r
- POP BP ; Restore Registers\r
- RET 2 ; Exit and Clean up Stack\r
- \r
-SET_ACTIVE_PAGE ENDP\r
- \r
- \r
-;================\r
-;GET_ACTIVE_PAGE%\r
-;================\r
-;\r
-; Returns the Video Page # currently used for Drawing\r
-;\r
-; ENTRY: No Parameters are passed\r
-;\r
-; EXIT: AX = Current Video Page used for Drawing\r
-;\r
- \r
- PUBLIC GET_ACTIVE_PAGE\r
- \r
-GET_ACTIVE_PAGE PROC FAR\r
- \r
- MOV AX, ACTIVE_PAGE ; Get Active Page #\r
- RET ; Exit and Clean up Stack\r
- \r
-GET_ACTIVE_PAGE ENDP\r
- \r
- \r
-;===============================\r
-;SET_DISPLAY_PAGE (DisplayPage%)\r
-;===============================\r
-;\r
-; Sets the currently visible display page.\r
-; When called this routine syncronizes the display\r
-; to the vertical blank.\r
-;\r
-; ENTRY: PageNo = Display Page to show on the screen\r
-; (values: 0 to Number of Pages - 1)\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-SDP_STACK STRUC\r
- DW ? ; BP\r
- DD ? ; Caller\r
- SDP_Page DW ? ; Page # to Display...\r
-SDP_STACK ENDS\r
- \r
- PUBLIC SET_DISPLAY_PAGE\r
- \r
-SET_DISPLAY_PAGE PROC FAR\r
- \r
- PUSH BP ; Preserve Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- MOV BX, [BP].SDP_Page ; Get Desired Page #\r
- CMP BX, LAST_PAGE ; Is Page # Valid?\r
- JAE @SDP_Exit ; IF Not, Do Nothing\r
- \r
- MOV DISPLAY_PAGE, BX ; Set Display Page #\r
- \r
- SHL BX, 1 ; Scale Page # to Word\r
- MOV CX, PAGE_ADDR[BX] ; Get offset in memory to Page\r
- ADD CX, CURRENT_MOFFSET ; Adjust for any scrolling\r
- \r
- ; Wait if we are currently in a Vertical Retrace\r
- \r
- MOV DX, INPUT_1 ; Input Status #1 Register\r
- \r
-@DP_WAIT0:\r
- IN AL, DX ; Get VGA status\r
- AND AL, VERT_RETRACE ; In Display mode yet?\r
- JNZ @DP_WAIT0 ; If Not, wait for it\r
- \r
- ; Set the Start Display Address to the new page\r
- \r
- MOV DX, CRTC_Index ; We Change the VGA Sequencer\r
- \r
- MOV AL, START_DISP_LO ; Display Start Low Register\r
- MOV AH, CL ; Low 8 Bits of Start Addr\r
- OUT DX, AX ; Set Display Addr Low\r
- \r
- MOV AL, START_DISP_HI ; Display Start High Register\r
- MOV AH, CH ; High 8 Bits of Start Addr\r
- OUT DX, AX ; Set Display Addr High\r
- \r
- ; Wait for a Vertical Retrace to smooth out things\r
- \r
- MOV DX, INPUT_1 ; Input Status #1 Register\r
- \r
-@DP_WAIT1:\r
- IN AL, DX ; Get VGA status\r
- AND AL, VERT_RETRACE ; Vertical Retrace Start?\r
- JZ @DP_WAIT1 ; If Not, wait for it\r
- \r
- ; Now Set Display Starting Address\r
- \r
- \r
-@SDP_Exit:\r
- POP BP ; Restore Registers\r
- RET 2 ; Exit and Clean up Stack\r
- \r
-SET_DISPLAY_PAGE ENDP\r
- \r
- \r
-;=================\r
-;GET_DISPLAY_PAGE%\r
-;=================\r
-;\r
-; Returns the Video Page # currently displayed\r
-;\r
-; ENTRY: No Parameters are passed\r
-;\r
-; EXIT: AX = Current Video Page being displayed\r
-;\r
- \r
- PUBLIC GET_DISPLAY_PAGE\r
- \r
-GET_DISPLAY_PAGE PROC FAR\r
- \r
- MOV AX, DISPLAY_PAGE ; Get Display Page #\r
- RET ; Exit & Clean Up Stack\r
- \r
-GET_DISPLAY_PAGE ENDP\r
- \r
- \r
-;=======================================\r
-;SET_WINDOW (DisplayPage%, Xpos%, Ypos%)\r
-;=======================================\r
-;\r
-; Since a Logical Screen can be larger than the Physical\r
-; Screen, Scrolling is possible. This routine sets the\r
-; Upper Left Corner of the Screen to the specified Pixel.\r
-; Also Sets the Display page to simplify combined page\r
-; flipping and scrolling. When called this routine\r
-; syncronizes the display to the vertical blank.\r
-;\r
-; ENTRY: DisplayPage = Display Page to show on the screen\r
-; Xpos = # of pixels to shift screen right\r
-; Ypos = # of lines to shift screen down\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-SW_STACK STRUC\r
- DW ? ; BP\r
- DD ? ; Caller\r
- SW_Ypos DW ? ; Y pos of UL Screen Corner\r
- SW_Xpos DW ? ; X pos of UL Screen Corner\r
- SW_Page DW ? ; (new) Display Page\r
-SW_STACK ENDS\r
- \r
- PUBLIC SET_WINDOW\r
- \r
-SET_WINDOW PROC FAR\r
- \r
- PUSH BP ; Preserve Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- ; Check if our Scroll Offsets are Valid\r
- \r
- MOV BX, [BP].SW_Page ; Get Desired Page #\r
- CMP BX, LAST_PAGE ; Is Page # Valid?\r
- JAE @SW_Exit ; IF Not, Do Nothing\r
- \r
- MOV AX, [BP].SW_Ypos ; Get Desired Y Offset\r
- CMP AX, MAX_YOFFSET ; Is it Within Limits?\r
- JA @SW_Exit ; if not, exit\r
- \r
- MOV CX, [BP].SW_Xpos ; Get Desired X Offset\r
- CMP CX, MAX_XOFFSET ; Is it Within Limits?\r
- JA @SW_Exit ; if not, exit\r
- \r
- ; Compute proper Display start address to use\r
- \r
- MUL SCREEN_WIDTH ; AX = YOffset * Line Width\r
- SHR CX, 2 ; CX / 4 = Bytes into Line\r
- ADD AX, CX ; AX = Offset of Upper Left Pixel\r
- \r
- MOV CURRENT_MOFFSET, AX ; Save Offset Info\r
- \r
- MOV DISPLAY_PAGE, BX ; Set Current Page #\r
- SHL BX, 1 ; Scale Page # to Word\r
- ADD AX, PAGE_ADDR[BX] ; Get offset in VGA to Page\r
- MOV BX, AX ; BX = Desired Display Start\r
- \r
- MOV DX, INPUT_1 ; Input Status #1 Register\r
- \r
- ; Wait if we are currently in a Vertical Retrace\r
- \r
-@SW_WAIT0:\r
- IN AL, DX ; Get VGA status\r
- AND AL, VERT_RETRACE ; In Display mode yet?\r
- JNZ @SW_WAIT0 ; If Not, wait for it\r
- \r
- ; Set the Start Display Address to the new window\r
- \r
- MOV DX, CRTC_Index ; We Change the VGA Sequencer\r
- MOV AL, START_DISP_LO ; Display Start Low Register\r
- MOV AH, BL ; Low 8 Bits of Start Addr\r
- OUT DX, AX ; Set Display Addr Low\r
- \r
- MOV AL, START_DISP_HI ; Display Start High Register\r
- MOV AH, BH ; High 8 Bits of Start Addr\r
- OUT DX, AX ; Set Display Addr High\r
- \r
- ; Wait for a Vertical Retrace to smooth out things\r
- \r
- MOV DX, INPUT_1 ; Input Status #1 Register\r
- \r
-@SW_WAIT1:\r
- IN AL, DX ; Get VGA status\r
- AND AL, VERT_RETRACE ; Vertical Retrace Start?\r
- JZ @SW_WAIT1 ; If Not, wait for it\r
- \r
- ; Now Set the Horizontal Pixel Pan values\r
- \r
- OUT_8 ATTRIB_Ctrl, PIXEL_PAN_REG ; Select Pixel Pan Register\r
- \r
- MOV AX, [BP].SW_Xpos ; Get Desired X Offset\r
- AND AL, 03 ; Get # of Pixels to Pan (0-3)\r
- SHL AL, 1 ; Shift for 256 Color Mode\r
- OUT DX, AL ; Fine tune the display!\r
- \r
-@SW_Exit:\r
- POP BP ; Restore Saved Registers\r
- RET 6 ; Exit and Clean up Stack\r
- \r
-SET_WINDOW ENDP\r
- \r
- \r
-;=============\r
-;GET_X_OFFSET%\r
-;=============\r
-;\r
-; Returns the X coordinate of the Pixel currently display\r
-; in the upper left corner of the display\r
-;\r
-; ENTRY: No Parameters are passed\r
-;\r
-; EXIT: AX = Current Horizontal Scroll Offset\r
-;\r
- \r
- PUBLIC GET_X_OFFSET\r
- \r
-GET_X_OFFSET PROC FAR\r
- \r
- MOV AX, CURRENT_XOFFSET ; Get current horz offset\r
- RET ; Exit & Clean Up Stack\r
- \r
-GET_X_OFFSET ENDP\r
- \r
- \r
-;=============\r
-;GET_Y_OFFSET%\r
-;=============\r
-;\r
-; Returns the Y coordinate of the Pixel currently display\r
-; in the upper left corner of the display\r
-;\r
-; ENTRY: No Parameters are passed\r
-;\r
-; EXIT: AX = Current Vertical Scroll Offset\r
-;\r
- \r
- PUBLIC GET_Y_OFFSET\r
- \r
-GET_Y_OFFSET PROC FAR\r
- \r
- MOV AX, CURRENT_YOFFSET ; Get current vertical offset\r
- RET ; Exit & Clean Up Stack\r
- \r
-GET_Y_OFFSET ENDP\r
- \r
- \r
-;============\r
-;SYNC_DISPLAY\r
-;============\r
-;\r
-; Pauses the computer until the next Vertical Retrace starts\r
-;\r
-; ENTRY: No Parameters are passed\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
- PUBLIC SYNC_DISPLAY\r
- \r
-SYNC_DISPLAY PROC FAR\r
- \r
- MOV DX, INPUT_1 ; Input Status #1 Register\r
- \r
- ; Wait for any current retrace to end\r
- \r
-@SD_WAIT0:\r
- IN AL, DX ; Get VGA status\r
- AND AL, VERT_RETRACE ; In Display mode yet?\r
- JNZ @SD_WAIT0 ; If Not, wait for it\r
- \r
- ; Wait for the start of the next vertical retrace\r
- \r
-@SD_WAIT1:\r
- IN AL, DX ; Get VGA status\r
- AND AL, VERT_RETRACE ; Vertical Retrace Start?\r
- JZ @SD_WAIT1 ; If Not, wait for it\r
- \r
- RET ; Exit & Clean Up Stack\r
- \r
-SYNC_DISPLAY ENDP\r
- \r
- \r
- ; ===== TEXT DISPLAY ROUTINES =====\r
- \r
-;==================================================\r
-;GPRINTC (CharNum%, Xpos%, Ypos%, ColorF%, ColorB%)\r
-;==================================================\r
-;\r
-; Draws an ASCII Text Character using the currently selected\r
-; 8x8 font on the active display page. It would be a simple\r
-; exercise to make this routine process variable height fonts.\r
-;\r
-; ENTRY: CharNum = ASCII character # to draw\r
-; Xpos = X position to draw Character at\r
-; Ypos = Y position of to draw Character at\r
-; ColorF = Color to draw text character in\r
-; ColorB = Color to set background to\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-GPC_STACK STRUC\r
- GPC_Width DW ? ; Screen Width-1\r
- GPC_Lines DB ?,? ; Scan lines to Decode\r
- GPC_T_SETS DW ? ; Saved Charset Segment\r
- GPC_T_SETO DW ? ; Saved Charset Offset\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- GPC_ColorB DB ?,? ; Background Color\r
- GPC_ColorF DB ?,? ; Text Color\r
- GPC_Ypos DW ? ; Y Position to Print at\r
- GPC_Xpos DW ? ; X position to Print at\r
- GPC_Char DB ?,? ; Character to Print\r
-GPC_STACK ENDS\r
- \r
- PUBLIC GPRINTC\r
- \r
-GPRINTC PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- SUB SP, 8 ; Allocate WorkSpace on Stack\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- \r
- MOV AX, SCREEN_WIDTH ; Get Logical Line Width\r
- MOV BX, AX ; BX = Screen Width\r
- DEC BX ; = Screen Width-1\r
- MOV [BP].GPC_Width, BX ; Save for later use\r
- \r
- MUL [BP].GPC_Ypos ; Start of Line = Ypos * Width\r
- ADD DI, AX ; DI -> Start of Line Ypos\r
- \r
- MOV AX, [BP].GPC_Xpos ; Get Xpos of Character\r
- MOV CX, AX ; Save Copy of Xpos\r
- SHR AX, 2 ; Bytes into Line = Xpos/4\r
- ADD DI, AX ; DI -> (Xpos, Ypos)\r
- \r
- ;Get Source ADDR of Character Bit Map & Save\r
- \r
- MOV AL, [BP].GPC_Char ; Get Character #\r
- TEST AL, 080h ; Is Hi Bit Set?\r
- JZ @GPC_LowChar ; Nope, use low char set ptr\r
- \r
- AND AL, 07Fh ; Mask Out Hi Bit\r
- MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset\r
- MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment\r
- JMP s @GPC_Set_Char ; Go Setup Character Ptr\r
- \r
-@GPC_LowChar:\r
- \r
- MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset\r
- MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment\r
- \r
-@GPC_Set_Char:\r
- MOV [BP].GPC_T_SETS, DX ; Save Segment on Stack\r
- \r
- MOV AH, 0 ; Valid #'s are 0..127\r
- SHL AX, 3 ; * 8 Bytes Per Bitmap\r
- ADD BX, AX ; BX = Offset of Selected char\r
- MOV [BP].GPC_T_SETO, BX ; Save Offset on Stack\r
- \r
- AND CX, PLANE_BITS ; Get Plane #\r
- MOV CH, ALL_PLANES ; Get Initial Plane mask\r
- SHL CH, CL ; And shift into position\r
- AND CH, ALL_PLANES ; And mask to lower nibble\r
- \r
- MOV AL, 04 ; 4-Plane # = # of initial\r
- SUB AL, CL ; shifts to align bit mask\r
- MOV CL, AL ; Shift Count for SHL\r
- \r
- ;Get segment of character map\r
- \r
- OUT_8 SC_Index, MAP_MASK ; Setup Plane selections\r
- INC DX ; DX -> SC_Data\r
- \r
- MOV AL, 08 ; 8 Lines to Process\r
- MOV [BP].GPC_Lines, AL ; Save on Stack\r
- \r
- MOV DS, [BP].GPC_T_SETS ; Point to character set\r
- \r
-@GPC_DECODE_CHAR_BYTE:\r
- \r
- MOV SI, [BP].GPC_T_SETO ; Get DS:SI = String\r
- \r
- MOV BH, [SI] ; Get Bit Map\r
- INC SI ; Point to Next Line\r
- MOV [BP].GPC_T_SETO, SI ; And save new Pointer...\r
- \r
- CLR AX ; Clear AX\r
- \r
- CLR BL ; Clear BL\r
- ROL BX, CL ; BL holds left edge bits\r
- MOV SI, BX ; Use as Table Index\r
- AND SI, CHAR_BITS ; Get Low Bits\r
- MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
- JZ @GPC_NO_LEFT1BITS ; Skip if No Pixels to set\r
- \r
- MOV AH, [BP].GPC_ColorF ; Get Foreground Color\r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
-@GPC_NO_LEFT1BITS:\r
- XOR AL, CH ; Invert mask for Background\r
- JZ @GPC_NO_LEFT0BITS ; Hey, no need for this\r
- \r
- MOV AH, [BP].GPC_ColorB ; Get background Color\r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
- ;Now Do Middle/Last Band\r
- \r
-@GPC_NO_LEFT0BITS:\r
- INC DI ; Point to next Byte\r
- ROL BX, 4 ; Shift 4 bits\r
- \r
- MOV SI, BX ; Make Lookup Pointer\r
- AND SI, CHAR_BITS ; Get Low Bits\r
- MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
- JZ @GPC_NO_MIDDLE1BITS ; Skip if no pixels to set\r
- \r
- MOV AH, [BP].GPC_ColorF ; Get Foreground Color\r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
-@GPC_NO_MIDDLE1BITS:\r
- XOR AL, ALL_PLANES ; Invert mask for Background\r
- JZ @GPC_NO_MIDDLE0BITS ; Hey, no need for this\r
- \r
- MOV AH, [BP].GPC_ColorB ; Get background Color\r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
-@GPC_NO_MIDDLE0BITS:\r
- XOR CH, ALL_PLANES ; Invert Clip Mask\r
- CMP CL, 4 ; Aligned by 4?\r
- JZ @GPC_NEXT_LINE ; If so, Exit now..\r
- \r
- INC DI ; Point to next Byte\r
- ROL BX, 4 ; Shift 4 bits\r
- \r
- MOV SI, BX ; Make Lookup Pointer\r
- AND SI, CHAR_BITS ; Get Low Bits\r
- MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
- JZ @GPC_NO_RIGHT1BITS ; Skip if No Pixels to set\r
- \r
- MOV AH, [BP].GPC_ColorF ; Get Foreground Color\r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
-@GPC_NO_RIGHT1BITS:\r
- \r
- XOR AL, CH ; Invert mask for Background\r
- JZ @GPC_NO_RIGHT0BITS ; Hey, no need for this\r
- \r
- MOV AH, [BP].GPC_ColorB ; Get background Color\r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
-@GPC_NO_RIGHT0BITS:\r
- DEC DI ; Adjust for Next Line Advance\r
- \r
-@GPC_NEXT_LINE:\r
- ADD DI, [BP].GPC_Width ; Point to Next Line\r
- XOR CH, CHAR_BITS ; Flip the Clip mask back\r
- \r
- DEC [BP].GPC_Lines ; Count Down Lines\r
- JZ @GPC_EXIT ; Ok... Done!\r
- \r
- JMP @GPC_DECODE_CHAR_BYTE ; Again! Hey!\r
- \r
-@GPC_EXIT:\r
- ADD SP, 08 ; Deallocate stack workspace\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 10 ; Exit and Clean up Stack\r
- \r
-GPRINTC ENDP\r
- \r
- \r
-;==========================================\r
-;TGPRINTC (CharNum%, Xpos%, Ypos%, ColorF%)\r
-;==========================================\r
-;\r
-; Transparently draws an ASCII Text Character using the\r
-; currently selected 8x8 font on the active display page.\r
-;\r
-; ENTRY: CharNum = ASCII character # to draw\r
-; Xpos = X position to draw Character at\r
-; Ypos = Y position of to draw Character at\r
-; ColorF = Color to draw text character in\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-TGP_STACK STRUC\r
- TGP_Width DW ? ; Screen Width-1\r
- TGP_Lines DB ?,? ; Scan lines to Decode\r
- TGP_T_SETS DW ? ; Saved Charset Segment\r
- TGP_T_SETO DW ? ; Saved Charset Offset\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- TGP_ColorF DB ?,? ; Text Color\r
- TGP_Ypos DW ? ; Y Position to Print at\r
- TGP_Xpos DW ? ; X position to Print at\r
- TGP_Char DB ?,? ; Character to Print\r
-TGP_STACK ENDS\r
- \r
- PUBLIC TGPRINTC\r
- \r
-TGPRINTC PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- SUB SP, 8 ; Allocate WorkSpace on Stack\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- \r
- MOV AX, SCREEN_WIDTH ; Get Logical Line Width\r
- MOV BX, AX ; BX = Screen Width\r
- DEC BX ; = Screen Width-1\r
- MOV [BP].TGP_Width, BX ; Save for later use\r
- \r
- MUL [BP].TGP_Ypos ; Start of Line = Ypos * Width\r
- ADD DI, AX ; DI -> Start of Line Ypos\r
- \r
- MOV AX, [BP].TGP_Xpos ; Get Xpos of Character\r
- MOV CX, AX ; Save Copy of Xpos\r
- SHR AX, 2 ; Bytes into Line = Xpos/4\r
- ADD DI, AX ; DI -> (Xpos, Ypos)\r
- \r
- ;Get Source ADDR of Character Bit Map & Save\r
- \r
- MOV AL, [BP].TGP_Char ; Get Character #\r
- TEST AL, 080h ; Is Hi Bit Set?\r
- JZ @TGP_LowChar ; Nope, use low char set ptr\r
- \r
- AND AL, 07Fh ; Mask Out Hi Bit\r
- MOV BX, CHARSET_HI ; BX = Char Set Ptr:Offset\r
- MOV DX, CHARSET_HI+2 ; DX = Char Set Ptr:Segment\r
- JMP s @TGP_Set_Char ; Go Setup Character Ptr\r
- \r
-@TGP_LowChar:\r
- \r
- MOV BX, CHARSET_LOW ; BX = Char Set Ptr:Offset\r
- MOV DX, CHARSET_LOW+2 ; DX = Char Set Ptr:Segment\r
- \r
-@TGP_Set_Char:\r
- MOV [BP].TGP_T_SETS, DX ; Save Segment on Stack\r
- \r
- MOV AH, 0 ; Valid #'s are 0..127\r
- SHL AX, 3 ; * 8 Bytes Per Bitmap\r
- ADD BX, AX ; BX = Offset of Selected char\r
- MOV [BP].TGP_T_SETO, BX ; Save Offset on Stack\r
- \r
- AND CX, PLANE_BITS ; Get Plane #\r
- MOV CH, ALL_PLANES ; Get Initial Plane mask\r
- SHL CH, CL ; And shift into position\r
- AND CH, ALL_PLANES ; And mask to lower nibble\r
- \r
- MOV AL, 04 ; 4-Plane # = # of initial\r
- SUB AL, CL ; shifts to align bit mask\r
- MOV CL, AL ; Shift Count for SHL\r
- \r
- ;Get segment of character map\r
- \r
- OUT_8 SC_Index, MAP_MASK ; Setup Plane selections\r
- INC DX ; DX -> SC_Data\r
- \r
- MOV AL, 08 ; 8 Lines to Process\r
- MOV [BP].TGP_Lines, AL ; Save on Stack\r
- \r
- MOV DS, [BP].TGP_T_SETS ; Point to character set\r
- \r
-@TGP_DECODE_CHAR_BYTE:\r
- \r
- MOV SI, [BP].TGP_T_SETO ; Get DS:SI = String\r
- \r
- MOV BH, [SI] ; Get Bit Map\r
- INC SI ; Point to Next Line\r
- MOV [BP].TGP_T_SETO, SI ; And save new Pointer...\r
- \r
- MOV AH, [BP].TGP_ColorF ; Get Foreground Color\r
- \r
- CLR BL ; Clear BL\r
- ROL BX, CL ; BL holds left edge bits\r
- MOV SI, BX ; Use as Table Index\r
- AND SI, CHAR_BITS ; Get Low Bits\r
- MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
- JZ @TGP_NO_LEFT1BITS ; Skip if No Pixels to set\r
- \r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
- ;Now Do Middle/Last Band\r
- \r
-@TGP_NO_LEFT1BITS:\r
- \r
- INC DI ; Point to next Byte\r
- ROL BX, 4 ; Shift 4 bits\r
- \r
- MOV SI, BX ; Make Lookup Pointer\r
- AND SI, CHAR_BITS ; Get Low Bits\r
- MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
- JZ @TGP_NO_MIDDLE1BITS ; Skip if no pixels to set\r
- \r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
-@TGP_NO_MIDDLE1BITS:\r
- XOR CH, ALL_PLANES ; Invert Clip Mask\r
- CMP CL, 4 ; Aligned by 4?\r
- JZ @TGP_NEXT_LINE ; If so, Exit now..\r
- \r
- INC DI ; Point to next Byte\r
- ROL BX, 4 ; Shift 4 bits\r
- \r
- MOV SI, BX ; Make Lookup Pointer\r
- AND SI, CHAR_BITS ; Get Low Bits\r
- MOV AL, Char_Plane_Data[SI] ; Get Mask in AL\r
- JZ @TGP_NO_RIGHT1BITS ; Skip if No Pixels to set\r
- \r
- OUT DX, AL ; Set up Screen Mask\r
- MOV ES:[DI], AH ; Write Foreground color\r
- \r
-@TGP_NO_RIGHT1BITS:\r
- \r
- DEC DI ; Adjust for Next Line Advance\r
- \r
-@TGP_NEXT_LINE:\r
- ADD DI, [BP].TGP_Width ; Point to Next Line\r
- XOR CH, CHAR_BITS ; Flip the Clip mask back\r
- \r
- DEC [BP].TGP_Lines ; Count Down Lines\r
- JZ @TGP_EXIT ; Ok... Done!\r
- \r
- JMP @TGP_DECODE_CHAR_BYTE ; Again! Hey!\r
- \r
-@TGP_EXIT:\r
- ADD SP, 08 ; Deallocate stack workspace\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 8 ; Exit and Clean up Stack\r
- \r
-TGPRINTC ENDP\r
- \r
- \r
-;===============================================================\r
-;PRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
-;===============================================================\r
-;\r
-; Routine to quickly Print a null terminated ASCII string on the\r
-; active display page up to a maximum length.\r
-;\r
-; ENTRY: String = Far Pointer to ASCII string to print\r
-; MaxLen = # of characters to print if no null found\r
-; Xpos = X position to draw Text at\r
-; Ypos = Y position of to draw Text at\r
-; ColorF = Color to draw text in\r
-; ColorB = Color to set background to\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-PS_STACK STRUC\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- PS_ColorB DW ? ; Background Color\r
- PS_ColorF DW ? ; Text Color\r
- PS_Ypos DW ? ; Y Position to Print at\r
- PS_Xpos DW ? ; X position to Print at\r
- PS_Len DW ? ; Maximum Length of string to print\r
- PS_Text DW ?,? ; Far Ptr to Text String\r
-PS_STACK ENDS\r
- \r
- PUBLIC PRINT_STR\r
- \r
-PRINT_STR PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
-@PS_Print_It:\r
- \r
- MOV CX, [BP].PS_Len ; Get Remaining text Length\r
- JCXZ @PS_Exit ; Exit when out of text\r
- \r
- LES DI, d [BP].PS_Text ; ES:DI -> Current Char in Text\r
- MOV AL, ES:[DI] ; AL = Text Character\r
- AND AX, 00FFh ; Clear High Word\r
- JZ @PS_Exit ; Exit if null character\r
- \r
- DEC [BP].PS_Len ; Remaining Text length--\r
- INC [BP].PS_Text ; Point to Next text char\r
- \r
- ; Set up Call to GPRINTC\r
- \r
- PUSH AX ; Set Character Parameter\r
- MOV BX, [BP].PS_Xpos ; Get Xpos\r
- PUSH BX ; Set Xpos Parameter\r
- ADD BX, 8 ; Advance 1 Char to Right\r
- MOV [BP].PS_Xpos, BX ; Save for next time through\r
- \r
- MOV BX, [BP].PS_Ypos ; Get Ypos\r
- PUSH BX ; Set Ypos Parameter\r
- \r
- MOV BX, [BP].PS_ColorF ; Get Text Color\r
- PUSH BX ; Set ColorF Parameter\r
- \r
- MOV BX, [BP].PS_ColorB ; Get Background Color\r
- PUSH BX ; Set ColorB Parameter\r
- \r
- CALL f GPRINTC ; Print Character!\r
- JMP s @PS_Print_It ; Process next character\r
- \r
-@PS_Exit:\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 14 ; Exit and Clean up Stack\r
- \r
-PRINT_STR ENDP\r
- \r
- \r
-;================================================================\r
-;TPRINT_STR (SEG String, MaxLen%, Xpos%, Ypos%, ColorF%, ColorB%)\r
-;================================================================\r
-;\r
-; Routine to quickly transparently Print a null terminated ASCII\r
-; string on the active display page up to a maximum length.\r
-;\r
-; ENTRY: String = Far Pointer to ASCII string to print\r
-; MaxLen = # of characters to print if no null found\r
-; Xpos = X position to draw Text at\r
-; Ypos = Y position of to draw Text at\r
-; ColorF = Color to draw text in\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-TPS_STACK STRUC\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- TPS_ColorF DW ? ; Text Color\r
- TPS_Ypos DW ? ; Y Position to Print at\r
- TPS_Xpos DW ? ; X position to Print at\r
- TPS_Len DW ? ; Maximum Length of string to print\r
- TPS_Text DW ?,? ; Far Ptr to Text String\r
-TPS_STACK ENDS\r
- \r
- PUBLIC TPRINT_STR\r
- \r
-TPRINT_STR PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
-@TPS_Print_It:\r
- \r
- MOV CX, [BP].TPS_Len ; Get Remaining text Length\r
- JCXZ @TPS_Exit ; Exit when out of text\r
- \r
- LES DI, d [BP].TPS_Text ; ES:DI -> Current Char in Text\r
- MOV AL, ES:[DI] ; AL = Text Character\r
- AND AX, 00FFh ; Clear High Word\r
- JZ @TPS_Exit ; Exit if null character\r
- \r
- DEC [BP].TPS_Len ; Remaining Text length--\r
- INC [BP].TPS_Text ; Point to Next text char\r
- \r
- ; Set up Call to TGPRINTC\r
- \r
- PUSH AX ; Set Character Parameter\r
- MOV BX, [BP].TPS_Xpos ; Get Xpos\r
- PUSH BX ; Set Xpos Parameter\r
- ADD BX, 8 ; Advance 1 Char to Right\r
- MOV [BP].TPS_Xpos, BX ; Save for next time through\r
- \r
- MOV BX, [BP].TPS_Ypos ; Get Ypos\r
- PUSH BX ; Set Ypos Parameter\r
- \r
- MOV BX, [BP].TPS_ColorF ; Get Text Color\r
- PUSH BX ; Set ColorF Parameter\r
- \r
- CALL f TGPRINTC ; Print Character!\r
- JMP s @TPS_Print_It ; Process next character\r
- \r
-@TPS_Exit:\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 12 ; Exit and Clean up Stack\r
- \r
-TPRINT_STR ENDP\r
- \r
- \r
-;===========================================\r
-;SET_DISPLAY_FONT(SEG FontData, FontNumber%)\r
-;===========================================\r
-;\r
-; Allows the user to specify their own font data for\r
-; wither the lower or upper 128 characters.\r
-;\r
-; ENTRY: FontData = Far Pointer to Font Bitmaps\r
-; FontNumber = Which half of set this is\r
-; = 0, Lower 128 characters\r
-; = 1, Upper 128 characters\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-SDF_STACK STRUC\r
- DW ? ; BP\r
- DD ? ; Caller\r
- SDF_Which DW ? ; Hi Table/Low Table Flag\r
- SDF_Font DD ? ; Far Ptr to Font Table\r
-SDF_STACK ENDS\r
- \r
- PUBLIC SET_DISPLAY_FONT\r
- \r
-SET_DISPLAY_FONT PROC FAR\r
- \r
- PUSH BP ; Preserve Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- LES DI, [BP].SDF_Font ; Get Far Ptr to Font\r
- \r
- MOV SI, o CHARSET_LOW ; Assume Lower 128 chars\r
- TEST [BP].SDF_Which, 1 ; Font #1 selected?\r
- JZ @SDF_Set_Font ; If not, skip ahead\r
- \r
- MOV SI, o CHARSET_HI ; Ah, really it's 128-255\r
- \r
-@SDF_Set_Font:\r
- MOV [SI], DI ; Set Font Pointer Offset\r
- MOV [SI+2], ES ; Set Font Pointer Segment\r
- \r
- POP BP ; Restore Registers\r
- RET 6 ; We are Done.. Outa here\r
- \r
-SET_DISPLAY_FONT ENDP\r
- \r
- \r
- ; ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
- \r
-;======================================================\r
-;DRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
-;======================================================\r
-;\r
-; Draws a variable sized Graphics Bitmap such as a\r
-; picture or an Icon on the current Display Page in\r
-; Mode X. The Bitmap is stored in a linear byte array\r
-; corresponding to (0,0) (1,0), (2,0) .. (Width, Height)\r
-; This is the same linear manner as mode 13h graphics.\r
-;\r
-; ENTRY: Image = Far Pointer to Bitmap Data\r
-; Xpos = X position to Place Upper Left pixel at\r
-; Ypos = Y position to Place Upper Left pixel at\r
-; Width = Width of the Bitmap in Pixels\r
-; Height = Height of the Bitmap in Pixels\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-DB_STACK STRUC\r
- DB_LineO DW ? ; Offset to Next Line\r
- DB_PixCount DW ? ; (Minimum) # of Pixels/Line\r
- DB_Start DW ? ; Addr of Upper Left Pixel\r
- DB_PixSkew DW ? ; # of bytes to Adjust EOL\r
- DB_SkewFlag DW ? ; Extra Pix on Plane Flag\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- DB_Height DW ? ; Height of Bitmap in Pixels\r
- DB_Width DW ? ; Width of Bitmap in Pixels\r
- DB_Ypos DW ? ; Y position to Draw Bitmap at\r
- DB_Xpos DW ? ; X position to Draw Bitmap at\r
- DB_Image DD ? ; Far Pointer to Graphics Bitmap\r
-DB_STACK ENDS\r
- \r
- PUBLIC DRAW_BITMAP\r
- \r
-DRAW_BITMAP PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- SUB SP, 10 ; Allocate workspace\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- CLD ; Direction Flag = Forward\r
- \r
- MOV AX, [BP].DB_Ypos ; Get UL Corner Ypos\r
- MUL SCREEN_WIDTH ; AX = Offset to Line Ypos\r
- \r
- MOV BX, [BP].DB_Xpos ; Get UL Corner Xpos\r
- MOV CL, BL ; Save Plane # in CL\r
- SHR BX, 2 ; Xpos/4 = Offset Into Line\r
- \r
- ADD DI, AX ; ES:DI -> Start of Line\r
- ADD DI, BX ; ES:DI -> Upper Left Pixel\r
- MOV [BP].DB_Start, DI ; Save Starting Addr\r
- \r
- ; Compute line to line offset\r
- \r
- MOV BX, [BP].DB_Width ; Get Width of Image\r
- MOV DX, BX ; Save Copy in DX\r
- SHR BX, 2 ; /4 = width in bands\r
- MOV AX, SCREEN_WIDTH ; Get Screen Width\r
- SUB AX, BX ; - (Bitmap Width/4)\r
- \r
- MOV [BP].DB_LineO, AX ; Save Line Width offset\r
- MOV [BP].DB_PixCount, BX ; Minimum # pix to copy\r
- \r
- AND DX, PLANE_BITS ; Get "partial band" size (0-3)\r
- MOV [BP].DB_PixSkew, DX ; Also End of Line Skew\r
- MOV [BP].DB_SkewFlag, DX ; Save as Flag/Count\r
- \r
- AND CX, PLANE_BITS ; CL = Starting Plane #\r
- MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select\r
- SHL AH, CL ; Select correct Plane\r
- OUT_16 SC_Index, AX ; Select Plane...\r
- MOV BH, AH ; BH = Saved Plane Mask\r
- MOV BL, 4 ; BL = Planes to Copy\r
- \r
-@DB_COPY_PLANE:\r
- \r
- LDS SI, [BP].DB_Image ; DS:SI-> Source Image\r
- MOV DX, [BP].DB_Height ; # of Lines to Copy\r
- MOV DI, [BP].DB_Start ; ES:DI-> Dest pos\r
- \r
-@DB_COPY_LINE:\r
- MOV CX, [BP].DB_PixCount ; Min # to copy\r
- \r
- TEST CL, 0FCh ; 16+PixWide?\r
- JZ @DB_COPY_REMAINDER ; Nope...\r
- \r
- ; Pixel Copy loop has been unrolled to x4\r
- \r
-@DB_COPY_LOOP:\r
- MOVSB ; Copy Bitmap Pixel\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- MOVSB ; Copy Bitmap Pixel\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- MOVSB ; Copy Bitmap Pixel\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- MOVSB ; Copy Bitmap Pixel\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- \r
- SUB CL, 4 ; Pixels to Copy=-4\r
- TEST CL, 0FCh ; 4+ Pixels Left?\r
- JNZ @DB_COPY_LOOP ; if so, do another block\r
- \r
-@DB_COPY_REMAINDER:\r
- JCXZ @DB_NEXT_LINE ; Any Pixels left on line\r
- \r
-@DB_COPY2:\r
- MOVSB ; Copy Bitmap Pixel\r
- ADD SI,3 ; Skip to Next Byte in same plane\r
- LOOPx CX, @DB_COPY2 ; Pixels to Copy--, Loop until done\r
- \r
-@DB_NEXT_LINE:\r
- \r
- ; any Partial Pixels? (some planes only)\r
- \r
- OR CX, [BP].DB_SkewFlag ; Get Skew Count\r
- JZ @DB_NEXT2 ; if no partial pixels\r
- \r
- MOVSB ; Copy Bitmap Pixel\r
- DEC DI ; Back up to align\r
- DEC SI ; Back up to align\r
- \r
-@DB_NEXT2:\r
- ADD SI, [BP].DB_PixSkew ; Adjust Skew\r
- ADD DI, [BP].DB_LineO ; Set to Next Display Line\r
- LOOPx DX, @DB_COPY_LINE ; Lines to Copy--, Loop if more\r
- \r
- ; Copy Next Plane....\r
- \r
- DEC BL ; Planes to Go--\r
- JZ @DB_Exit ; Hey! We are done\r
- \r
- ROL BH, 1 ; Next Plane in line...\r
- OUT_8 SC_Data, BH ; Select Plane\r
- \r
- CMP AL, 12h ; Carry Set if AL=11h\r
- ADC [BP].DB_Start, 0 ; Screen Addr =+Carry\r
- INC w [BP].DB_Image ; Start @ Next Byte\r
- \r
- SUB [BP].DB_SkewFlag, 1 ; Reduce Planes to Skew\r
- ADC [BP].DB_SkewFlag, 0 ; Back to 0 if it was -1\r
- \r
- JMP s @DB_COPY_PLANE ; Go Copy the Next Plane\r
- \r
-@DB_Exit:\r
- ADD SP, 10 ; Deallocate workspace\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 12 ; Exit and Clean up Stack\r
- \r
-DRAW_BITMAP ENDP\r
- \r
- \r
-;=======================================================\r
-;TDRAW_BITMAP (SEG Image, Xpos%, Ypos%, Width%, Height%)\r
-;=======================================================\r
-;\r
-; Transparently Draws a variable sized Graphics Bitmap\r
-; such as a picture or an Icon on the current Display Page\r
-; in Mode X. Pixels with a value of 0 are not drawn,\r
-; leaving the previous "background" contents intact.\r
-;\r
-; The Bitmap format is the same as for the DRAW_BITMAP function.\r
-;\r
-; ENTRY: Image = Far Pointer to Bitmap Data\r
-; Xpos = X position to Place Upper Left pixel at\r
-; Ypos = Y position to Place Upper Left pixel at\r
-; Width = Width of the Bitmap in Pixels\r
-; Height = Height of the Bitmap in Pixels\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-TB_STACK STRUC\r
- TB_LineO DW ? ; Offset to Next Line\r
- TB_PixCount DW ? ; (Minimum) # of Pixels/Line\r
- TB_Start DW ? ; Addr of Upper Left Pixel\r
- TB_PixSkew DW ? ; # of bytes to Adjust EOL\r
- TB_SkewFlag DW ? ; Extra Pix on Plane Flag\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- TB_Height DW ? ; Height of Bitmap in Pixels\r
- TB_Width DW ? ; Width of Bitmap in Pixels\r
- TB_Ypos DW ? ; Y position to Draw Bitmap at\r
- TB_Xpos DW ? ; X position to Draw Bitmap at\r
- TB_Image DD ? ; Far Pointer to Graphics Bitmap\r
-TB_STACK ENDS\r
- \r
- PUBLIC TDRAW_BITMAP\r
- \r
-TDRAW_BITMAP PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- SUB SP, 10 ; Allocate workspace\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- LES DI, d CURRENT_PAGE ; Point to Active VGA Page\r
- CLD ; Direction Flag = Forward\r
- \r
- MOV AX, [BP].TB_Ypos ; Get UL Corner Ypos\r
- MUL SCREEN_WIDTH ; AX = Offset to Line Ypos\r
- \r
- MOV BX, [BP].TB_Xpos ; Get UL Corner Xpos\r
- MOV CL, BL ; Save Plane # in CL\r
- SHR BX, 2 ; Xpos/4 = Offset Into Line\r
- \r
- ADD DI, AX ; ES:DI -> Start of Line\r
- ADD DI, BX ; ES:DI -> Upper Left Pixel\r
- MOV [BP].TB_Start, DI ; Save Starting Addr\r
- \r
- ; Compute line to line offset\r
- \r
- MOV BX, [BP].TB_Width ; Get Width of Image\r
- MOV DX, BX ; Save Copy in DX\r
- SHR BX, 2 ; /4 = width in bands\r
- MOV AX, SCREEN_WIDTH ; Get Screen Width\r
- SUB AX, BX ; - (Bitmap Width/4)\r
- \r
- MOV [BP].TB_LineO, AX ; Save Line Width offset\r
- MOV [BP].TB_PixCount, BX ; Minimum # pix to copy\r
- \r
- AND DX, PLANE_BITS ; Get "partial band" size (0-3)\r
- MOV [BP].TB_PixSkew, DX ; Also End of Line Skew\r
- MOV [BP].TB_SkewFlag, DX ; Save as Flag/Count\r
- \r
- AND CX, PLANE_BITS ; CL = Starting Plane #\r
- MOV AX, MAP_MASK_PLANE2 ; Plane Mask & Plane Select\r
- SHL AH, CL ; Select correct Plane\r
- OUT_16 SC_Index, AX ; Select Plane...\r
- MOV BH, AH ; BH = Saved Plane Mask\r
- MOV BL, 4 ; BL = Planes to Copy\r
- \r
-@TB_COPY_PLANE:\r
- \r
- LDS SI, [BP].TB_Image ; DS:SI-> Source Image\r
- MOV DX, [BP].TB_Height ; # of Lines to Copy\r
- MOV DI, [BP].TB_Start ; ES:DI-> Dest pos\r
- \r
- ; Here AH is set with the value to be considered\r
- ; "Transparent". It can be changed!\r
- \r
- MOV AH, 0 ; Value to Detect 0\r
- \r
-@TB_COPY_LINE:\r
- MOV CX, [BP].TB_PixCount ; Min # to copy\r
- \r
- TEST CL, 0FCh ; 16+PixWide?\r
- JZ @TB_COPY_REMAINDER ; Nope...\r
- \r
- ; Pixel Copy loop has been unrolled to x4\r
- \r
-@TB_COPY_LOOP:\r
- LODSB ; Get Pixel Value in AL\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- CMP AL, AH ; It is "Transparent"?\r
- JE @TB_SKIP_01 ; Skip ahead if so\r
- MOV ES:[DI], AL ; Copy Pixel to VGA screen\r
- \r
-@TB_SKIP_01:\r
- LODSB ; Get Pixel Value in AL\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- CMP AL, AH ; It is "Transparent"?\r
- JE @TB_SKIP_02 ; Skip ahead if so\r
- MOV ES:[DI+1], AL ; Copy Pixel to VGA screen\r
- \r
-@TB_SKIP_02:\r
- LODSB ; Get Pixel Value in AL\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- CMP AL, AH ; It is "Transparent"?\r
- JE @TB_SKIP_03 ; Skip ahead if so\r
- MOV ES:[DI+2], AL ; Copy Pixel to VGA screen\r
- \r
-@TB_SKIP_03:\r
- LODSB ; Get Pixel Value in AL\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- CMP AL, AH ; It is "Transparent"?\r
- JE @TB_SKIP_04 ; Skip ahead if so\r
- MOV ES:[DI+3], AL ; Copy Pixel to VGA screen\r
- \r
-@TB_SKIP_04:\r
- ADD DI, 4 ; Adjust Pixel Write Location\r
- SUB CL, 4 ; Pixels to Copy=-4\r
- TEST CL, 0FCh ; 4+ Pixels Left?\r
- JNZ @TB_COPY_LOOP ; if so, do another block\r
- \r
-@TB_COPY_REMAINDER:\r
- JCXZ @TB_NEXT_LINE ; Any Pixels left on line\r
- \r
-@TB_COPY2:\r
- LODSB ; Get Pixel Value in AL\r
- ADD SI, 3 ; Skip to Next Byte in same plane\r
- CMP AL, AH ; It is "Transparent"?\r
- JE @TB_SKIP_05 ; Skip ahead if so\r
- MOV ES:[DI], AL ; Copy Pixel to VGA screen\r
- \r
-@TB_SKIP_05:\r
- INC DI ; Advance Dest Addr\r
- LOOPx CX, @TB_COPY2 ; Pixels to Copy--, Loop until done\r
- \r
-@TB_NEXT_LINE:\r
- \r
- ; any Partial Pixels? (some planes only)\r
- \r
- OR CX, [BP].TB_SkewFlag ; Get Skew Count\r
- JZ @TB_NEXT2 ; if no partial pixels\r
- \r
- LODSB ; Get Pixel Value in AL\r
- DEC SI ; Backup to Align\r
- CMP AL, AH ; It is "Transparent"?\r
- JE @TB_NEXT2 ; Skip ahead if so\r
- MOV ES:[DI], AL ; Copy Pixel to VGA screen\r
- \r
-@TB_NEXT2:\r
- ADD SI, [BP].TB_PixSkew ; Adjust Skew\r
- ADD DI, [BP].TB_LineO ; Set to Next Display Line\r
- LOOPx DX, @TB_COPY_LINE ; Lines to Copy--, Loop if More\r
- \r
- ;Copy Next Plane....\r
- \r
- DEC BL ; Planes to Go--\r
- JZ @TB_Exit ; Hey! We are done\r
- \r
- ROL BH, 1 ; Next Plane in line...\r
- OUT_8 SC_Data, BH ; Select Plane\r
- \r
- CMP AL, 12h ; Carry Set if AL=11h\r
- ADC [BP].TB_Start, 0 ; Screen Addr =+Carry\r
- INC w [BP].TB_Image ; Start @ Next Byte\r
- \r
- SUB [BP].TB_SkewFlag, 1 ; Reduce Planes to Skew\r
- ADC [BP].TB_SkewFlag, 0 ; Back to 0 if it was -1\r
- \r
- JMP @TB_COPY_PLANE ; Go Copy the next Plane\r
- \r
-@TB_Exit:\r
- ADD SP, 10 ; Deallocate workspace\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 12 ; Exit and Clean up Stack\r
- \r
-TDRAW_BITMAP ENDP\r
- \r
- \r
- ; ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
- \r
-;==================================\r
-;COPY_PAGE (SourcePage%, DestPage%)\r
-;==================================\r
-;\r
-; Duplicate on display page onto another\r
-;\r
-; ENTRY: SourcePage = Display Page # to Duplicate\r
-; DestPage = Display Page # to hold copy\r
-;\r
-; EXIT: No meaningful values returned\r
-;\r
- \r
-CP_STACK STRUC\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- CP_DestP DW ? ; Page to hold copied image\r
- CP_SourceP DW ? ; Page to Make copy from\r
-CP_STACK ENDS\r
- \r
- PUBLIC COPY_PAGE\r
- \r
-COPY_PAGE PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- MOV BP, SP ; Set up Stack Frame\r
- CLD ; Block Xfer Forwards\r
- \r
- ; Make sure Page #'s are valid\r
- \r
- MOV AX, [BP].CP_SourceP ; Get Source Page #\r
- CMP AX, LAST_PAGE ; is it > Max Page #?\r
- JAE @CP_Exit ; if so, abort\r
- \r
- MOV BX, [BP].CP_DestP ; Get Destination Page #\r
- CMP BX, LAST_PAGE ; is it > Max Page #?\r
- JAE @CP_Exit ; if so, abort\r
- \r
- CMP AX, BX ; Pages #'s the same?\r
- JE @CP_Exit ; if so, abort\r
- \r
- ; Setup DS:SI and ES:DI to Video Pages\r
- \r
- SHL BX, 1 ; Scale index to Word\r
- MOV DI, PAGE_ADDR[BX] ; Offset to Dest Page\r
- \r
- MOV BX, AX ; Index to Source page\r
- SHL BX, 1 ; Scale index to Word\r
- MOV SI, PAGE_ADDR[BX] ; Offset to Source Page\r
- \r
- MOV CX, PAGE_SIZE ; Get size of Page\r
- MOV AX, CURRENT_SEGMENT ; Get Video Mem Segment\r
- MOV ES, AX ; ES:DI -> Dest Page\r
- MOV DS, AX ; DS:SI -> Source Page\r
- \r
- ; Setup VGA registers for Mem to Mem copy\r
- \r
- OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on\r
- OUT_16 SC_Index, ALL_PLANES_ON ; Copy all Planes\r
- \r
- ; Note.. Do *NOT* use MOVSW or MOVSD - they will\r
- ; Screw with the latches which are 8 bits x 4\r
- \r
- REP MOVSB ; Copy entire Page!\r
- \r
- ; Reset VGA for normal memory access\r
- \r
- OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = off\r
- \r
-@CP_Exit:\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 4 ; Exit and Clean up Stack\r
- \r
-COPY_PAGE ENDP\r
- \r
- \r
-;==========================================================================\r
-;COPY_BITMAP (SourcePage%, X1%, Y1%, X2%, Y2%, DestPage%, DestX1%, DestY1%)\r
-;==========================================================================\r
-;\r
-; Copies a Bitmap Image from one Display Page to Another\r
-; This Routine is Limited to copying Images with the same\r
-; Plane Alignment. To Work: (X1 MOD 4) must = (DestX1 MOD 4)\r
-; Copying an Image to the Same Page is supported, but results\r
-; may be defined when the when the rectangular areas\r
-; (X1, Y1) - (X2, Y2) and (DestX1, DestY1) -\r
-; (DestX1+(X2-X1), DestY1+(Y2-Y1)) overlap...\r
-; No Paramter checking to done to insure that\r
-; X2 >= X1 and Y2 >= Y1. Be Careful...\r
-;\r
-; ENTRY: SourcePage = Display Page # with Source Image\r
-; X1 = Upper Left Xpos of Source Image\r
-; Y1 = Upper Left Ypos of Source Image\r
-; X2 = Lower Right Xpos of Source Image\r
-; Y2 = Lower Right Ypos of Source Image\r
-; DestPage = Display Page # to copy Image to\r
-; DestX1 = Xpos to Copy UL Corner of Image to\r
-; DestY1 = Ypos to Copy UL Corner of Image to\r
-;\r
-; EXIT: AX = Success Flag: 0 = Failure / -1= Success\r
-;\r
- \r
-CB_STACK STRUC\r
- CB_Height DW ? ; Height of Image in Lines\r
- CB_Width DW ? ; Width of Image in "bands"\r
- DW ?x4 ; DI, SI, DS, BP\r
- DD ? ; Caller\r
- CB_DestY1 DW ? ; Destination Ypos\r
- CB_DestX1 DW ? ; Destination Xpos\r
- CB_DestP DW ? ; Page to Copy Bitmap To\r
- CB_Y2 DW ? ; LR Ypos of Image\r
- CB_X2 DW ? ; LR Xpos of Image\r
- CB_Y1 DW ? ; UL Ypos of Image\r
- CB_X1 DW ? ; UL Xpos of Image\r
- CB_SourceP DW ? ; Page containing Source Bitmap\r
-CB_STACK ENDS\r
- \r
- PUBLIC COPY_BITMAP\r
- \r
-COPY_BITMAP PROC FAR\r
- \r
- PUSHx BP, DS, SI, DI ; Preserve Important Registers\r
- SUB SP, 4 ; Allocate WorkSpace on Stack\r
- MOV BP, SP ; Set up Stack Frame\r
- \r
- ; Prep Registers (and keep jumps short!)\r
- \r
- MOV ES, CURRENT_SEGMENT ; ES -> VGA Ram\r
- CLD ; Block Xfer Forwards\r
- \r
- ; Make sure Parameters are valid\r
- \r
- MOV BX, [BP].CB_SourceP ; Get Source Page #\r
- CMP BX, LAST_PAGE ; is it > Max Page #?\r
- JAE @CB_Abort ; if so, abort\r
- \r
- MOV CX, [BP].CB_DestP ; Get Destination Page #\r
- CMP CX, LAST_PAGE ; is it > Max Page #?\r
- JAE @CB_Abort ; if so, abort\r
- \r
- MOV AX, [BP].CB_X1 ; Get Source X1\r
- XOR AX, [BP].CB_DestX1 ; Compare Bits 0-1\r
- AND AX, PLANE_BITS ; Check Plane Bits\r
- JNZ @CB_Abort ; They should cancel out\r
- \r
- ; Setup for Copy processing\r
- \r
- OUT_8 SC_INDEX, MAP_MASK ; Set up for Plane Select\r
- OUT_16 GC_Index, LATCHES_ON ; Data from Latches = on\r
- \r
- ; Compute Info About Images, Setup ES:SI & ES:DI\r
- \r
- MOV AX, [BP].CB_Y2 ; Height of Bitmap in lines\r
- SUB AX, [BP].CB_Y1 ; is Y2 - Y1 + 1\r
- INC AX ; (add 1 since were not 0 based)\r
- MOV [BP].CB_Height, AX ; Save on Stack for later use\r
- \r
- MOV AX, [BP].CB_X2 ; Get # of "Bands" of 4 Pixels\r
- MOV DX, [BP].CB_X1 ; the Bitmap Occupies as X2-X1\r
- SHR AX, 2 ; Get X2 Band (X2 / 4)\r
- SHR DX, 2 ; Get X1 Band (X1 / 4)\r
- SUB AX, DX ; AX = # of Bands - 1\r
- INC AX ; AX = # of Bands\r
- MOV [BP].CB_Width, AX ; Save on Stack for later use\r
- \r
- SHL BX, 1 ; Scale Source Page to Word\r
- MOV SI, PAGE_ADDR[BX] ; SI = Offset of Source Page\r
- MOV AX, [BP].CB_Y1 ; Get Source Y1 Line\r
- MUL SCREEN_WIDTH ; AX = Offset to Line Y1\r
- ADD SI, AX ; SI = Offset to Line Y1\r
- MOV AX, [BP].CB_X1 ; Get Source X1\r
- SHR AX, 2 ; X1 / 4 = Byte offset\r
- ADD SI, AX ; SI = Byte Offset to (X1,Y1)\r
- \r
- MOV BX, CX ; Dest Page Index to BX\r
- SHL BX, 1 ; Scale Source Page to Word\r
- MOV DI, PAGE_ADDR[BX] ; DI = Offset of Dest Page\r
- MOV AX, [BP].CB_DestY1 ; Get Dest Y1 Line\r
- MUL SCREEN_WIDTH ; AX = Offset to Line Y1\r
- ADD DI, AX ; DI = Offset to Line Y1\r
- MOV AX, [BP].CB_DestX1 ; Get Dest X1\r
- SHR AX, 2 ; X1 / 4 = Byte offset\r
- ADD DI, AX ; DI = Byte Offset to (D-X1,D-Y1)\r
- \r
- MOV CX, [BP].CB_Width ; CX = Width of Image (Bands)\r
- DEC CX ; CX = 1?\r
- JE @CB_Only_One_Band ; 0 Means Image Width of 1 Band\r
- \r
- MOV BX, [BP].CB_X1 ; Get Source X1\r
- AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 00?)\r
- JZ @CB_Check_Right ; if so, check right alignment\r
- JNZ @CB_Left_Band ; not aligned? well..\r
- \r
-@CB_Abort:\r
- CLR AX ; Return False (Failure)\r
- JMP @CB_Exit ; and Finish Up\r
- \r
- ; Copy when Left & Right Clip Masks overlap...\r
- \r
-@CB_Only_One_Band:\r
- MOV BX, [BP].CB_X1 ; Get Left Clip Mask\r
- AND BX, PLANE_BITS ; Mask out Row #\r
- MOV AL, Left_Clip_Mask[BX] ; Get Left Edge Mask\r
- MOV BX, [BP].CB_X2 ; Get Right Clip Mask\r
- AND BX, PLANE_BITS ; Mask out Row #\r
- AND AL, Right_Clip_Mask[BX] ; Get Right Edge Mask byte\r
- \r
- OUT_8 SC_Data, AL ; Clip For Left & Right Masks\r
- \r
- MOV CX, [BP].CB_Height ; CX = # of Lines to Copy\r
- MOV DX, SCREEN_WIDTH ; DX = Width of Screen\r
- CLR BX ; BX = Offset into Image\r
- \r
-@CB_One_Loop:\r
- MOV AL, ES:[SI+BX] ; Load Latches\r
- MOV ES:[DI+BX], AL ; Unload Latches\r
- ADD BX, DX ; Advance Offset to Next Line\r
- LOOPjz CX, @CB_One_Done ; Exit Loop if Finished\r
- \r
- MOV AL, ES:[SI+BX] ; Load Latches\r
- MOV ES:[DI+BX], AL ; Unload Latches\r
- ADD BX, DX ; Advance Offset to Next Line\r
- LOOPx CX, @CB_One_Loop ; Loop until Finished\r
- \r
-@CB_One_Done:\r
- JMP @CB_Finish ; Outa Here!\r
- \r
- ; Copy Left Edge of Bitmap\r
- \r
-@CB_Left_Band:\r
- \r
- OUT_8 SC_Data, Left_Clip_Mask[BX] ; Set Left Edge Plane Mask\r
- \r
- MOV CX, [BP].CB_Height ; CX = # of Lines to Copy\r
- MOV DX, SCREEN_WIDTH ; DX = Width of Screen\r
- CLR BX ; BX = Offset into Image\r
- \r
-@CB_Left_Loop:\r
- MOV AL, ES:[SI+BX] ; Load Latches\r
- MOV ES:[DI+BX], AL ; Unload Latches\r
- ADD BX, DX ; Advance Offset to Next Line\r
- LOOPjz CX, @CB_Left_Done ; Exit Loop if Finished\r
- \r
- MOV AL, ES:[SI+BX] ; Load Latches\r
- MOV ES:[DI+BX], AL ; Unload Latches\r
- ADD BX, DX ; Advance Offset to Next Line\r
- LOOPx CX, @CB_Left_Loop ; Loop until Finished\r
- \r
-@CB_Left_Done:\r
- INC DI ; Move Dest Over 1 band\r
- INC SI ; Move Source Over 1 band\r
- DEC [BP].CB_Width ; Band Width--\r
- \r
- ; Determine if Right Edge of Bitmap needs special copy\r
- \r
-@CB_Check_Right:\r
- MOV BX, [BP].CB_X2 ; Get Source X2\r
- AND BX, PLANE_BITS ; Aligned? (bits 0-1 = 11?)\r
- CMP BL, 03h ; Plane = 3?\r
- JE @CB_Copy_Middle ; Copy the Middle then!\r
- \r
- ; Copy Right Edge of Bitmap\r
- \r
-@CB_Right_Band:\r
- \r
- OUT_8 SC_Data, Right_Clip_Mask[BX] ; Set Right Edge Plane Mask\r
- \r
- DEC [BP].CB_Width ; Band Width--\r
- MOV CX, [BP].CB_Height ; CX = # of Lines to Copy\r
- MOV DX, SCREEN_WIDTH ; DX = Width of Screen\r
- MOV BX, [BP].CB_Width ; BX = Offset to Right Edge\r
- \r
-@CB_Right_Loop:\r
- MOV AL, ES:[SI+BX] ; Load Latches\r
- MOV ES:[DI+BX], AL ; Unload Latches\r
- ADD BX, DX ; Advance Offset to Next Line\r
- LOOPjz CX, @CB_Right_Done ; Exit Loop if Finished\r
- \r
- MOV AL, ES:[SI+BX] ; Load Latches\r
- MOV ES:[DI+BX], AL ; Unload Latches\r
- ADD BX, DX ; Advance Offset to Next Line\r
- LOOPx CX, @CB_Right_Loop ; Loop until Finished\r
- \r
-@CB_Right_Done:\r
- \r
- ; Copy the Main Block of the Bitmap\r
- \r
-@CB_Copy_Middle:\r
- \r
- MOV CX, [BP].CB_Width ; Get Width Remaining\r
- JCXZ @CB_Finish ; Exit if Done\r
- \r
- OUT_8 SC_Data, ALL_PLANES ; Copy all Planes\r
- \r
- MOV DX, SCREEN_WIDTH ; Get Width of Screen minus\r
- SUB DX, CX ; Image width (for Adjustment)\r
- MOV AX, [BP].CB_Height ; AX = # of Lines to Copy\r
- MOV BX, CX ; BX = Quick REP reload count\r
- MOV CX, ES ; Move VGA Segment\r
- MOV DS, CX ; Into DS\r
- \r
- ; Actual Copy Loop. REP MOVSB does the work\r
- \r
-@CB_Middle_Copy:\r
- MOV CX, BX ; Recharge Rep Count\r
- REP MOVSB ; Move Bands\r
- LOOPjz AX, @CB_Finish ; Exit Loop if Finished\r
- \r
- ADD SI, DX ; Adjust DS:SI to Next Line\r
- ADD DI, DX ; Adjust ES:DI to Next Line\r
- \r
- MOV CX, BX ; Recharge Rep Count\r
- REP MOVSB ; Move Bands\r
- \r
- ADD SI, DX ; Adjust DS:SI to Next Line\r
- ADD DI, DX ; Adjust ES:DI to Next Line\r
- LOOPx AX, @CB_Middle_Copy ; Copy Lines until Done\r
- \r
-@CB_Finish:\r
- OUT_16 GC_Index, LATCHES_OFF ; Data from Latches = on\r
- \r
-@CB_Exit:\r
- ADD SP, 04 ; Deallocate stack workspace\r
- POPx DI, SI, DS, BP ; Restore Saved Registers\r
- RET 16 ; Exit and Clean up Stack\r
- \r
-COPY_BITMAP ENDP\r
- \r
- END ; End of Code Segment\r
+++ /dev/null
- \r
- ' ===== SCREEN RESOLUTIONS =====\r
- \r
-CONST Mode320x200 = 0, Mode320x400 = 1\r
-CONST Mode360x200 = 2, Mode360x400 = 3\r
-CONST Mode320x240 = 4, Mode320x480 = 5\r
-CONST Mode360x240 = 6, Mode360x480 = 7\r
- \r
- ' ===== MODE X SETUP ROUTINES =====\r
- \r
-DECLARE FUNCTION SET.VGA.MODEX% ALIAS "SET_VGA_MODEX" (BYVAL ModeType%, BYVAL MaxXpos%, BYVAL MaxYpos%, BYVAL Pages%)\r
-DECLARE FUNCTION SET.MODEX% ALIAS "SET_MODEX" (BYVAL Mode%)\r
- \r
- ' ===== BASIC GRAPHICS PRIMITIVES =====\r
- \r
-DECLARE SUB CLEAR.VGA.SCREEN ALIAS "CLEAR_VGA_SCREEN" (BYVAL ColorNum%)\r
-DECLARE SUB SET.POINT ALIAS "SET_POINT" (BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorNum%)\r
-DECLARE FUNCTION READ.POINT% ALIAS "READ_POINT" (BYVAL Xpos%, BYVAL Ypos%)\r
-DECLARE SUB FILL.BLOCK ALIAS "FILL_BLOCK" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
-DECLARE SUB DRAW.LINE ALIAS "DRAW_LINE" (BYVAL Xpos1%, BYVAL Ypos1%, BYVAL Xpos2%, BYVAL Ypos2%, BYVAL ColorNum%)\r
- \r
- ' ===== DAC COLOR REGISTER ROUTINES =====\r
- \r
-DECLARE SUB SET.DAC.REGISTER ALIAS "SET_DAC_REGISTER" (BYVAL RegNo%, BYVAL Red%, BYVAL Green%, BYVAL Blue%)\r
-DECLARE SUB GET.DAC.REGISTER ALIAS "GET_DAC_REGISTER" (BYVAL RegNo%, Red%, Green%, Blue%)\r
-DECLARE SUB LOAD.DAC.REGISTERS ALIAS "LOAD_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%, BYVAL VSync%)\r
-DECLARE SUB READ.DAC.REGISTERS ALIAS "READ_DAC_REGISTERS" (SEG PalData AS ANY, BYVAL StartReg%, BYVAL EndReg%)\r
- \r
- \r
- ' ===== PAGE FLIPPING AND SCROLLING ROUTINES =====\r
- \r
-DECLARE SUB SET.ACTIVE.PAGE ALIAS "SET_ACTIVE_PAGE" (BYVAL PageNo%)\r
-DECLARE FUNCTION GET.ACTIVE.PAGE% ALIAS "GET_ACTIVE_PAGE"\r
-DECLARE SUB SET.DISPLAY.PAGE ALIAS "SET_DISPLAY_PAGE" (BYVAL PageNo%)\r
-DECLARE FUNCTION GET.DISPLAY.PAGE% ALIAS "GET_DISPLAY_PAGE"\r
-DECLARE SUB SET.WINDOW ALIAS "SET_WINDOW" (BYVAL DisplayPage%, BYVAL XOffset%, BYVAL YOffset%)\r
-DECLARE FUNCTION GET.X.OFFSET% ALIAS "GET_X_OFFSET" ()\r
-DECLARE FUNCTION GET.Y.OFFSET% ALIAS "GET_Y_OFFSET" ()\r
-DECLARE SUB SYNC.DISPLAY ALIAS "SYNC_DISPLAY"\r
- \r
- ' ===== TEXT DISPLAY ROUTINES =====\r
- \r
-DECLARE SUB GPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
-DECLARE SUB TGPRINTC (BYVAL CharacterNum%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
-DECLARE SUB PRINT.STR ALIAS "PRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%, BYVAL ColorB%)\r
-DECLARE SUB TPRINT.STR ALIAS "TPRINT_STR" (BYVAL StrSeg%, BYVAL StrOfs%, BYVAL MaxLen%, BYVAL Xpos%, BYVAL Ypos%, BYVAL ColorF%)\r
-DECLARE SUB SET.DISPLAY.FONT ALIAS "SET_DISPLAY_FONT" (SEG FontData AS ANY, BYVAL FontNumber%)\r
- \r
- ' ===== BITMAP (SPRITE) DISPLAY ROUTINES =====\r
- \r
-DECLARE SUB DRAW.BITMAP ALIAS "DRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
-DECLARE SUB TDRAW.BITMAP ALIAS "TDRAW_BITMAP" (SEG Image AS ANY, BYVAL Xpos%, BYVAL Ypos%, BYVAL xWidth%, BYVAL Height%)\r
- \r
- ' ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES =====\r
- \r
-DECLARE SUB COPY.PAGE ALIAS "COPY_PAGE" (BYVAL SourcePage%, BYVAL DestPage%)\r
-DECLARE SUB COPY.BITMAP ALIAS "COPY_BITMAP" (BYVAL SourcePage%, BYVAL X1%, BYVAL Y1%, BYVAL X2%, BYVAL Y2%, BYVAL DestPage%, BYVAL DestX1%, BYVAL DestY1%)\r
- \r
- \r
- \r
- \r
- \r
- \r
+++ /dev/null
- \r
-#ifndef __MODEX_H\r
-#define __MODEX_H\r
- \r
- /* ===== SCREEN RESOLUTIONS ===== */\r
- \r
-#define Mode_320x200 0\r
-#define Mode_320x400 1\r
-#define Mode_360x200 2\r
-#define Mode_360x400 3\r
-#define Mode_320x240 4\r
-#define Mode_320x480 5\r
-#define Mode_360x240 6\r
-#define Mode_360x480 7\r
- \r
- /* ===== MODE X SETUP ROUTINES ===== */\r
- \r
-int far pascal set_vga_modex (int Mode, int MaxXpos, int MaxYpos, int Pages);\r
-int far pascal set_modex (int Mode);\r
- \r
- /* ===== BASIC GRAPHICS PRIMITIVES ===== */\r
- \r
-void far pascal clear_vga_screen (int Color);\r
-void far pascal set_point (int Xpos, int Ypos, int Color);\r
-int far pascal read_point (int Xpos, int Ypos);\r
-void far pascal fill_block (int Xpos1, int Ypos1, int Xpos2, int Ypos2,\r
- int Color);\r
-void far pascal draw_line (int Xpos1, int Ypos1, int Xpos2, int Ypos2,\r
- int Color);\r
- \r
- /* ===== DAC COLOR REGISTER ROUTINES ===== */\r
- \r
-void far pascal set_dac_register (int RegNo, int Red, int Green, int Blue);\r
-void far pascal get_dac_register (int RegNo, int* Red, int* Green, int* Blue);\r
-void far pascal load_dac_registers (char far *PalData, int StartReg,\r
- int EndReg, int VSync);\r
-void far pascal readd_dac_registers (char far *PalData, int StartReg,\r
- int EndReg);\r
- \r
- /* ===== PAGE FLIPPING AND SCROLLING ROUTINES ===== */\r
- \r
-void far pascal set_active_page (int PageNo);\r
-int far pascal get_active_page (void);\r
-void far pascal set_display_page (int PageNo);\r
-int far pascal get_display_page (void);\r
-void far pascal set_window (int DisplayPage, int XOffset, int YOffset);\r
-int far pascal get_x_offset (void);\r
-int far pascal get_y_offset (void);\r
-void far pascal sync_display (void);\r
- \r
- /* ===== TEXT DISPLAY ROUTINES ===== */\r
- \r
-void far pascal gprintc (int CharNum, int Xpos, int Ypos, int ColorF,\r
- int ColorB);\r
-void far pascal tgprintc (int CharNum, int Xpos, int Ypos, int ColorF);\r
-void far pascal print_str (char far *Text, int MaxLen, int Xpos, int Ypos,\r
- int ColorF, int ColorB);\r
-void far pascal tprint_str (char far *Text, int MaxLen, int Xpos, int Ypos,\r
- int ColorF);\r
-void far pascal set_display_font (char far *FontData, int FontNumber);\r
- \r
- /* ===== BITMAP (SPRITE) DISPLAY ROUTINES ===== */\r
- \r
-void far pascal draw_bitmap (char far *Image, int Xpos, int Ypos,\r
- int Width, int Height);\r
-void far pascal tdraw_bitmap (char far *Image, int Xpos, int Ypos,\r
- int Width, int Height);\r
- \r
- /* ==== VIDEO MEMORY to VIDEO MEMORY COPY ROUTINES ===== */\r
- \r
-void far pascal copy_page (int SourcePage, int DestPage);\r
-void far pascal copy_bitmap (int SourcePage, int X1, int Y1, int X2, int Y2,\r
- int DestPage, int DestX1, int DestY1);\r
- \r
- \r
-#endif\r
+++ /dev/null
-\r
-PACKING LIST FOR MODEX104\r
-\r
-DIRECTORY: \ - The Mode X Library versoon 1.04 \r
-\r
-ASM BAT 26 05-14-93 6:00p - Batch File to Assemble MODEX.ASM\r
-MODE-X TXT 2135 05-14-93 6:00p - File Describing MODE X Routines\r
-MODEX ASM 117039 05-14-93 6:00p - Assembly source to Mode X Library\r
-MODEX BI 3238 05-14-93 6:00p - Include File for BASIC/PDS\r
-MODEX H 2943 05-14-93 6:00p - Include File for C/C++\r
-MODEX OBJ 5208 05-14-93 6:00p - The Mode X Library\r
-README DOC 3259 05-14-93 6:00p - Information on this Product\r
-PACKING LST 4767 05-14-93 6:00p - This File\r
-\r
-DIRECTORY: \DEMOS - Mode X Demos\r
-\r
-CHARDEMO EXE 13066 05-14-93 6:00p - Demo of Multiple Fonts & Color Cycling\r
-TEST6 EXE 19990 05-14-93 6:00p - Main Mode X Demo\r
-ROM_8X8 FNT 1024 05-14-93 6:00p - Font for CHARDEMO.EXE\r
-SPACEAGE FNT 1024 05-14-93 6:00p - Font for CHARDEMO.EXE\r
-SYSTEM FNT 1024 05-14-93 6:00p - Font for CHARDEMO.EXE\r
-\r
-DIRECTORY: \DEMOS\BASIC7 - Demo Sources for Microsoft BASIC 7.1 (PDS)\r
-\r
-MAKE-LIB BAT 166 05-14-93 6:00p - Batch File to make MODEX.LIB/.QLB\r
-MODEX BI 3238 05-14-93 6:00p - Include File for MODE X Library\r
-MODEX LIB 7189 05-14-93 6:00p - Mode X & Utility Libraries for QBX\r
-MODEX OBJ 5208 05-14-93 6:00p - Mode X Library - Object File\r
-MODEX QLB 11141 05-14-93 6:00p - Mode X & Utility Quick Library\r
-TEST6 BAS 12733 05-14-93 6:00p - Main Demo Source Code (TEST6.EXE)\r
-UASM-BC7 BAT 43 05-14-93 6:00p - Batch file to Make UTILS.OBJ for QBX\r
-UTILS ASM 8506 05-14-93 6:00p - Basic Utilities - Assembler source\r
-UTILS BI 2028 05-14-93 6:00p - Basic Utilities - Basic Includes\r
-UTILS OBJ 681 05-14-93 6:00p - Basic Utilities - Object File\r
-CHARDEMO BAS 3431 05-14-93 6:00p - Source to CHARDEMO.EXE\r
-\r
-DIRECTORY: \DEMOS\C - Demo Sources for Borland C/C++\r
-\r
-C_UTILS ASM 8782 05-14-93 6:00p - C Utilities - Assembler source\r
-C_UTILS H 2623 05-14-93 6:00p - C Utilities - C Includes\r
-C_UTILS OBJ 648 05-14-93 6:00p - C Utilities - Object File\r
-MODEX H 2943 05-14-93 6:00p - Mode X Library C Incldues\r
-MODEX OBJ 5208 05-14-93 6:00p - Mode X Library\r
-UTLS-ASM BAT 36 05-14-93 6:00p - Batch File to Make C_UTILS.OBJ\r
-X-DEMO C 15085 05-14-93 6:00p - Source to Main Demo (TEST6) in C\r
-X-DEMO EXE 41090 05-14-93 6:00p - C Version of Main Demo\r
-X-DEMO PRJ 5188 05-14-93 6:00p - Borland C Project file\r
-\r
-DIRECTORY: \DEMOS\PASCAL - Demo Sources for Turbo Pascal\r
-\r
-TEST5 PAS 15873 05-14-93 6:00p - Source for a TP Version of TEST6.EXE\r
-\r
-DIRECTORY: \DEMOS\QB45 - Demo Sources for Microsoft QuickBASIC 4.5\r
-\r
-MAKE-LIB BAT 164 05-14-93 6:00p - Batch File to make MODEX.LIB/.QLB\r
-MODEX BI 3238 05-14-93 6:00p - Include File for MODE X Library\r
-MODEX LIB 7189 05-14-93 6:00p - Mode X & Utility Libraries for QB45\r
-MODEX OBJ 5208 05-14-93 6:00p - Mode X Library - Object File\r
-MODEX QLB 9739 05-14-93 6:00p - Mode X & Utility Quick Library/QB45\r
-TEST6A BAS 12743 05-14-93 6:00p - Main Demo Source Code (TEST6.EXE)\r
-TEST6A EXE 40544 05-14-93 6:00p - QB45 Version of Main Demo\r
-UASM-QB4 BAT 30 05-14-93 6:00p - Batch file to Make UTILS.OBJ for QB45\r
-UTILS ASM 8506 05-14-93 6:00p - Basic Utilities - Assembler source\r
-UTILS BI 2028 05-14-93 6:00p - Basic Utilities - Basic Includes\r
-UTILS OBJ 628 05-14-93 6:00p - Basic Utilities - Object File\r
-\r
-DIRECTORY: \FONTEDIT - Font Editor\r
-\r
-CSEDIT EXE 39242 05-14-93 6:00p - Font Editor Program\r
-CSEDIT DOC 8629 05-14-93 6:00p - Font Editor Documentation\r
-CHARSETS CS 2144 05-14-93 6:00p - Internal Fonts for Editor\r
-MOUSEIMG CS 128 05-14-93 6:00p - Mouse Pointers for Editor\r
-PALETTE CS 768 05-14-93 6:00p - Palette for Editor\r
-INVERSE FNT 1024 05-14-93 6:00p - Sample Font\r
-ROM_8X8 FNT 1024 05-14-93 6:00p - Sample Font\r
-SPACEAGE FNT 1024 05-14-93 6:00p - Sample Font\r
-SYSTEM FNT 1024 05-14-93 6:00p - Sample Font\r
-\r
-DIRECTORY: \PALEDIT - Palette Editor\r
-\r
-PALEDIT EXE 31954 05-14-93 6:00p - Palette Editor Program\r
-PALEDIT DOC 6688 05-14-93 6:00p - Palette Editor Documentation\r
-CHARSETS CS 2144 05-14-93 6:00p - Internal Fonts for Editor\r
-MOUSEIMG CS 128 05-14-93 6:00p - Mouse Pointers for Editor\r
-GAMECOLR PAL 768 05-14-93 6:00p - Sample Palette\r
-PRIME PAL 768 05-14-93 6:00p - Sample Palette\r
-RGB PAL 768 05-14-93 6:00p - Sample Palette\r
+++ /dev/null
- \r
-PALEDIT - A Simple VGA 256 Color Palette Editor\r
- \r
- \r
-PALEDIT is distributed with MODEXnnn.ZIP, the general purpose MODE X\r
-Library for VGA Graphics.\r
- \r
-WHAT YOU NEED TO RUN PALEDIT:\r
- \r
- * A Vga Monitor\r
- * A Microsoft Compatible Mouse\r
- \r
- A Mouse is most definitely required, as the keyboard is used for\r
- nothing except entering file names.\r
- \r
-FILES NEEDED IN THE CURRENT DIRECTORY:\r
- \r
- PALEDIT.EXE - The Palette Editor Program\r
- CHARSETS.CS - The Palette Editor's Internal Fonts\r
- MOUSEIMG.CS - The Palette Editor's Mouse Pointer\r
- \r
-SAMPLE PALETTE FILE THAT SHOULD BE INCLUDED:\r
- \r
- RGB.PAL - A Simple Palette with Reds, Greens, and Blues\r
- PRIME.PAL - A Simple Palette\r
- GAMECOLR.PAL - A Bright Palette from a Game of mine.\r
- \r
-WHAT IT EDITS:\r
- \r
- The VGA DAC Registers, all 256 of them.\r
- \r
-HOW IT WORKS/FEATURES:\r
- \r
- PALEDIT allows the user to see the entire VGA Palette of 256 colors\r
- and select and modify the RED, GREEN, and BLUE values of any individual\r
- color (DAC) register. The entire group of 256 colors can be saved to\r
- a disk file for later retrieval.\r
- \r
- Individual "SLIDERS" show the current RED, GREEN, and BLUE color\r
- components of the current color and allow them to be changed.\r
- \r
- The Following operations can be performed.\r
- \r
- * Raise, Lower, and set the RED, GREEN, or BLUE components.\r
- * Copy the current RGB values to another Color (DAC) Register\r
- * Brighten the selected color\r
- * Darken and selected color\r
- * Reset the selected color to its original state\r
- * Blend an entire range of colors, creating a smooth\r
- Transition from one color to another\r
- * Optionally Lock out the first 16 colors to prevent\r
- Accidental Modification\r
- \r
-DESCRIPTION OF OBJECTS/FEATURES FROM THE TOP DOWN:\r
- \r
- COLOR SLIDERS: In the upper left of the screen there are\r
- Three Rectangular Boxes: One for each primary color:\r
- RED, GREEN, and BLUE. Each Box has an arrow at each\r
- end, and a scale bar in the middle, connecting the two\r
- arrows. The scale bar is much like a thermometer,\r
- indicating how much of that color is in the selected\r
- color. To the right of each Box, the name of the color\r
- is indicated, along with the content color in the form\r
- of a number from 0 to 63; where 0 means none of that\r
- color goes into making the selected color, and 63 means\r
- that the selected color is saturated with that color.\r
- \r
- Clicking the mouse on the slider's left arrow box will\r
- decrease the amount of that primary color in the selected\r
- color. Holding the mouse button down will reduce the\r
- color value all the way to 0.\r
- \r
- Clicking the mouse on the slider's right arrow box will\r
- increase the amount of that primary color in the selected\r
- color. Holding the mouse button down will increase the\r
- color value all the way to 63.\r
- \r
- Clicking the mouse on the scale bar will set the amount\r
- of that primary color to the value the represents that\r
- position on the slider.\r
- \r
- LOCK Button: Clicking the button toggles the lockout of the\r
- first 16 colors. When they are locked out, they can not\r
- be modified, and when selected the word "LOCKED" will\r
- appear below the color # on the Color Information Display.\r
- \r
- LOAD Button: Clicking this button will load the Palette file\r
- that is named in the Palette File name box. If no name is\r
- given or no such file exists, then nothing will be loaded.\r
- \r
- SAVE Button: Clicking this button will save the current Palette\r
- in a file using the name given in the Palette File Name Box.\r
- If a Valid name is not provided, nothing will be saved.\r
- \r
- QUIT Button: Clicking this button will return you to DOS.\r
- Nothing is saved, and no confirmation is given.\r
- \r
- \r
- Color Information Display: This Box is on the left side of the\r
- Screen, below the Color Sliders. It shows the number of the\r
- currently selected color (from 0 to 255) and indicates if\r
- that color is locked. To the right of this box is a big\r
- square showing the current color.\r
- \r
- LIGHTER Button: Clicking this button will make the selected\r
- color brighter.\r
- \r
- DARKER Button: Clicking this button will make the selected\r
- color darker.\r
- \r
- RESET Button: Clicking this button will restore the selected\r
- color to the value it had when it was first selected.\r
- \r
- BLEND Button: Clicking this button will let you Blend a range\r
- of colors together. One end of the range of colors is the\r
- currently selected color. After Clicking the BLEND button.\r
- You must click on the color at the other end of the range\r
- in the Palette Display Box. All of the colors in between\r
- those two colors will be changed to represent a gradual\r
- transition from the color at one end to the color at the\r
- other end.\r
- \r
- PALETTE FILE NAME BOX: This Text Box is used to enter the name\r
- of a Palette file to load or the name to save the current\r
- Palette as. Just click on the Box, and it will change color\r
- and a flashing cursor will appear. Now you type in a filename\r
- or edit the existing filename. Press <RETURN> or click\r
- outside the text box to end editing.\r
- \r
- PALETTE DISPLAY BOX: This Box shows all 256 colors in an array\r
- of 32 by 8 color blocks. The Currently Selected Color will\r
- have a Box around it. Clicking on a color with the Left\r
- Mouse button will make that color the new currently selected\r
- color. Clicking on a color with the Right Mouse Button will\r
- copy the color value from the old selected color to it, before\r
- it is made the new selected color.\r
- \r
- Message Bar: At the very bottom of the screen, this Bar will display\r
- information and messages for various functions.\r
- \r
-PALETTE FILE FORMAT:\r
- \r
- BINARY image, in order of VGA DAC (Color) Number. 3 Bytes Per\r
- Color, 256 Colors. 768 Bytes total. The Files will be exactly\r
- 768 bytes in size.\r
- \r
- COLOR:\r
- RED: 1 BYTE\r
- GREEN: 1 BYTE\r
- BLUE: 1 BYTE\r
- \r
- PALETTE: Array (0 to 255) of COLOR\r
- \r
-COMMENTS, QUESTIONS, BUG REPORTS, etc:\r
- \r
- Send the to the Author: Matt Pritchard\r
- \r
- Through the 80xxx Fidonet Echo or\r
- \r
- Matt Pritchard\r
- P.O. Box 140264\r
- Irving, TX 75014\r
- \r
-CREDITS:\r
- \r
- This Palette Editor was written in QuickBASIC 4.5\r
+++ /dev/null
-\r
-=========================================================================\r
- þ þ þþþþþ þþþþ þþþþþ þ þ þ þþþþþ þ þ \r
- þþ þþ þ þ þ þ þ þ þ þþ þ þ þ þ\r
- þ þ þ þ þ þ þ þþþþ þ þ þ þ þ þþþþþ\r
- þ þ þ þ þ þ þ þ þ þ þ þ þ\r
- þ þ þþþþþ þþþþ þþþþþ þ þ þþþþþ þþ þþþþþ þ\r
-=========================================================================\r
- MODE X 1.04\r
-=========================================================================\r
- Library & Editors by Matt Pritchard: Release 1.04 on 14 Mar 93\r
-=========================================================================\r
-\r
-MODEX104 is a library of high performance assembler routines for setting,\r
-accessing, and manipulating the Undocumented 256 Color Modes available in\r
-all VGA adaptors.\r
-\r
-MODEX104 includes the following elements:\r
-\r
- MODE X Library - A library of MODE X routines written in assembly.\r
-\r
- FONT EDITOR - An editor for creating and modifying fonts for use by\r
- The MODE X Library.\r
-\r
- PALETTE EDITOR - An editor for creating and modifying palettes for\r
- use in VGA 256 Color modes.\r
-\r
- MODE X Demos - Programs that show off the various features of the\r
- MODE X Library\r
-\r
- MODE X Demo Source - The Full source code for the MODE X Demos for \r
- the following Languages: Microsoft QuickBASIC 4.5,\r
- Microsoft BASIC 7.1 PDS, Borland C/C++ 3.1,\r
- and Borland Turbo Pascal.\r
-\r
-THE LEGAL STUFF:\r
-\r
- The Mode X Library has been placed into the Public Domain by the\r
- Author (Matt Pritchard). The Font Editor and Palette Editor are also\r
- placed into the Public Domain by the Author (Matt Pritchard). The\r
- Source Code to the above editors is not in the Public Domain.\r
-\r
- The Mode X Demos and the Mode X Demo Sources have been placed into the\r
- Public domain by the Author (Matt Pritchard).\r
-\r
- The Mode X Library may be used freely in any non commerical product.\r
- It would be nice if the author was credited for the contribution, \r
- but it is not necessary. No $$$ involved.\r
- \r
- The Mode X Library may be used freely in a commercial product, *IF*\r
- the author (Matt Pritchard) is credited for the contribution. That's\r
- it. No $$$ involved.\r
-\r
- The Mode X Library should not be re-sold or modified and re-sold.\r
- No fee in excess of $5 should be charged for duplication of this\r
- Library.\r
-\r
-CONTRIBUTORS: The following people have contributed to this effort.\r
-\r
- Michael Abrash - He told us all how to do it in the first place.\r
- Scott Wyatt - He ported the Main Demo code to Turbo Pascal.\r
-\r
-THE AUTHOR:\r
-\r
- The author of MODEX104 is Matt Pritchard.\r
- All Questions and correspondance can be directed to:\r
-\r
- "Matt Pritchard" on Fido Net ECHO Conference: 80xxx\r
-\r
- or mailed to: Matt Pritchard\r
- P.O. Box 140264\r
- Irving, TX 75014-0264\r
-\r
- Questions, Inquiries, Comments, Donations, etc are quite welcome.\r
-\r
-\r
wpp /d1 /0 /ml dos_gfx\r
-wlink debug c option cvp file 'dos_gfx','lib\x\mxvs.obj' library 'lib\x\modex.lib' name dos_gfx
+wlink debug c option cvp file 'dos_gfx' library 'lib\x\modex.lib' name dos_gfx\r
copy /y dos_gfx.exe c:\z\bakapi.exe\r