--- /dev/null
+/* VERY QUICK AND ULTRA-DIRTY DEMO USING XLIB */\r
+\r
+/* Simple Demo of MODE X Split screen and panning */\r
+/* Compile using Turbo C and Tasm */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <conio.h>\r
+#include <ctype.h>\r
+#include <alloc.h>\r
+#include <dos.h>\r
+#include "Xlib_all.h"\r
+\r
+#define MAX_OBJECTS 10\r
+\r
+static char *texttest[6] =\r
+ {"This is a demonstration of the fonts ",\r
+ "available in XLIB. Notice fixed and ",\r
+ "variabe spaced fonts are supported but",\r
+ "are limited to a maximum of 8 pixels in",\r
+ "width. Height of the characters is ",\r
+ "ofcourse unlimited..."};\r
+\r
+typedef struct {\r
+ int X,Y,Width,Height,XDir,YDir,XOtherPage,YOtherPage;\r
+ char far * Image;\r
+ char far * bg;\r
+ char far * bgOtherPage;\r
+} AnimatedObject;\r
+\r
+AnimatedObject objects[MAX_OBJECTS];\r
+int object_count=0;\r
+\r
+static char bm[] = {4,12,\r
+ /* plane 0 */\r
+ 2,2,2,2,2,1,1,1,2,1,1,1,2,3,3,1,\r
+ 2,0,0,3,2,0,0,3,2,0,0,3,2,0,0,3,\r
+ 2,3,3,1,2,1,1,1,2,1,1,1,2,2,2,2,\r
+ /* plane 1 */\r
+ 2,2,2,2,1,1,1,1,1,1,1,1,1,3,3,1,\r
+ 1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,\r
+ 1,3,3,1,1,1,1,1,1,1,1,1,2,2,2,2,\r
+ /* plane 2 */\r
+ 2,2,2,2,1,1,1,1,1,1,1,1,1,3,3,1,\r
+ 1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,\r
+ 1,3,3,1,1,1,1,1,1,1,1,1,2,2,2,2,\r
+ /* plane 3 */\r
+ 2,2,2,2,1,1,1,2,1,1,1,2,1,3,3,2,\r
+ 3,0,0,2,3,0,0,2,3,0,0,2,3,0,0,2,\r
+ 1,3,3,2,1,1,1,2,1,1,1,2,2,2,2,2};\r
+\r
+static char bm2[] = {4,12,\r
+ /* plane 0 */\r
+ 2,2,2,2,2,4,4,4,2,4,4,4,2,2,2,4,\r
+ 2,0,0,2,2,0,0,2,2,0,0,2,2,0,0,2,\r
+ 2,2,2,4,2,4,4,4,2,4,4,4,2,2,2,2,\r
+ /* plane 1 */\r
+ 2,2,2,2,4,4,4,4,4,4,4,4,4,2,2,4,\r
+ 4,0,0,4,4,0,0,4,4,0,0,4,4,0,0,4,\r
+ 4,2,2,4,4,4,4,4,4,4,4,4,2,2,2,2,\r
+ /* plane 2 */\r
+ 2,2,2,2,4,4,4,4,4,4,4,4,4,2,2,4,\r
+ 4,0,0,4,4,0,0,4,4,0,0,4,4,0,0,4,\r
+ 4,2,2,4,4,4,4,4,4,4,4,4,2,2,2,2,\r
+ /* plane 2 */\r
+ 2,2,2,2,4,4,4,2,4,4,4,2,4,2,2,2,\r
+ 2,0,0,2,2,0,0,2,2,0,0,2,2,0,0,2,\r
+ 4,2,2,2,4,4,4,2,4,4,4,2,2,2,2,2};\r
+\r
+int textwindow_x=0,textwindow_y=0;\r
+char far * pal,far * pal2;\r
+char palscrolldir=1;\r
+char far * userfnt1;\r
+\r
+\r
+\r
+void drawtext(int height){\r
+ int i;\r
+ for (i=0;i<6;i++)\r
+ x_printf(textwindow_x+5,50+i*(height+2),VisiblePageOffs,9,texttest[i]);\r
+}\r
+\r
+/* initialize a new object */\r
+void init_object(int x,int y,int width, int height, int xdir, int ydir,\r
+ char far * image){\r
+ int i;\r
+ objects[object_count].X = objects[object_count].XOtherPage = x;\r
+ objects[object_count].Y = objects[object_count].YOtherPage = y;\r
+ objects[object_count].Width = width;\r
+ objects[object_count].Height = height;\r
+ objects[object_count].XDir = xdir;\r
+ objects[object_count].YDir = ydir;\r
+ objects[object_count].Image = image;\r
+ objects[object_count].bg = (char far *) farmalloc(4*width*height+20);\r
+ objects[object_count].bgOtherPage = (char far *) farmalloc(4*width*height+20);\r
+ x_get_pbm(x,y,(unsigned)width,height,VisiblePageOffs,\r
+ objects[object_count].bg);\r
+ x_get_pbm(x,y,(unsigned)width,height,HiddenPageOffs,\r
+ objects[object_count].bgOtherPage);\r
+ object_count++;\r
+}\r
+\r
+/* Move the specified object, bouncing at the edges of the screen and\r
+ remembering where the object was before the move for erasing next time */\r
+void MoveObject(AnimatedObject * ObjectToMove) {\r
+ int X, Y;\r
+ char far *cptr;\r
+ X = ObjectToMove->X + ObjectToMove->XDir;\r
+ Y = ObjectToMove->Y + ObjectToMove->YDir;\r
+ if ((X < 0) || (X > (ScrnLogicalPixelWidth-((ObjectToMove->Width)<<2)))) {\r
+ ObjectToMove->XDir = -ObjectToMove->XDir;\r
+ X = ObjectToMove->X + ObjectToMove->XDir;\r
+ }\r
+ if ((Y < 0) || (Y > (ScrnLogicalHeight-ObjectToMove->Height))) {\r
+ ObjectToMove->YDir = -ObjectToMove->YDir;\r
+ Y = ObjectToMove->Y + ObjectToMove->YDir;\r
+ }\r
+ /* Remember previous location for erasing purposes */\r
+ ObjectToMove->XOtherPage = ObjectToMove->X;\r
+ ObjectToMove->YOtherPage = ObjectToMove->Y;\r
+ ObjectToMove->X = X; /* set new location */\r
+ ObjectToMove->Y = Y;\r
+ cptr = ObjectToMove->bg;\r
+ ObjectToMove->bg = ObjectToMove->bgOtherPage;\r
+ ObjectToMove->bgOtherPage = cptr;\r
+}\r
+\r
+void animate(void){\r
+ int i;\r
+ for(i=object_count-1;i>=0;i--){\r
+ x_put_pbm(objects[i].XOtherPage,objects[i].YOtherPage,\r
+ HiddenPageOffs,objects[i].bgOtherPage);\r
+ }\r
+ for(i=0;i<object_count;i++){\r
+ MoveObject(&objects[i]);\r
+\r
+ x_get_pbm(objects[i].X,objects[i].Y,\r
+ (unsigned)objects[i].Width,objects[i].Height,HiddenPageOffs,\r
+ objects[i].bg);\r
+ x_put_masked_pbm(objects[i].X,objects[i].Y,HiddenPageOffs,\r
+ objects[i].Image);\r
+ }\r
+}\r
+\r
+void clear_objects(void){\r
+ int i;\r
+ for(i=object_count-1;i>=0;i--){\r
+ x_put_pbm(objects[i].XOtherPage,objects[i].YOtherPage,\r
+ HiddenPageOffs,objects[i].bgOtherPage);\r
+ }\r
+}\r
+\r
+\r
+void textwindow(int Margin){\r
+ int x0=0+Margin;\r
+ int y0=0+Margin;\r
+ int x1=ScrnPhysicalPixelWidth-Margin;\r
+ int y1=ScrnPhysicalHeight-Margin;\r
+ x_rect_fill(x0, y0, x1,y1,VisiblePageOffs,1);\r
+ x_line(x0,y0,x1,y0,2,VisiblePageOffs);\r
+ x_line(x0,y1,x1,y1,2,VisiblePageOffs);\r
+ x_line(x0,y0,x0,y1,2,VisiblePageOffs);\r
+ x_line(x1,y0,x1,y1,2,VisiblePageOffs);\r
+ x_line(x0+2,y0+2,x1-2,y0+2,2,VisiblePageOffs);\r
+ x_line(x0+2,y1-2,x1-2,y1-2,2,VisiblePageOffs);\r
+ x_line(x0+2,y0+2,x0+2,y1-2,2,VisiblePageOffs);\r
+ x_line(x1-2,y0+2,x1-2,y1-2,2,VisiblePageOffs);\r
+ textwindow_x=x0;\r
+ textwindow_y=y0;\r
+\r
+}\r
+\r
+\r
+void wait_for_keypress(void){\r
+ x_show_mouse();\r
+ while(kbhit()) getch();\r
+ palscrolldir^=1;\r
+\r
+ do {\r
+ x_rot_pal_struc(pal,palscrolldir);\r
+ MouseFrozen=1;\r
+ x_put_pal_struc(pal);\r
+ x_update_mouse();\r
+ } while (!kbhit() && !(MouseButtonStatus==LEFT_PRESSED));\r
+ while(MouseButtonStatus==LEFT_PRESSED);\r
+ while(kbhit()) getch();\r
+\r
+}\r
+\r
+\r
+void exitfunc(void){\r
+ x_mouse_remove();\r
+ x_remove_vsync_handler();\r
+ x_text_mode();\r
+ printf("Thanks to everyone who assisted in the development of XLIB.\n");\r
+ printf("\nSpecial thanks to Matthew Mackenzie for contributing \n");\r
+ printf("lots of code, documentation and ideas.\n\n");\r
+ printf("If you make any money using this code and you're the generous\n");\r
+ printf("type please send us some, or at least a copy of your program!\n");\r
+}\r
+\r
+int terminate(void){\r
+ exit(0);\r
+}\r
+\r
+void intro_1(void){\r
+ x_set_rgb(1,40,40,40); /* BG Gray */\r
+ x_set_rgb(2,63,63,0); /* Bright Yellow */\r
+ x_set_rgb(3,63,0,0); /* Bright Red */\r
+ x_set_rgb(4,0,63,0); /* Bright Green */\r
+ x_set_rgb(5,0,0,63); /* Bright Blue */\r
+ x_set_rgb(6,0,0,28); /* Dark Blue */\r
+ x_set_rgb(7,0,28,0); /* Dark Green */\r
+ x_set_rgb(8,28,0,0); /* Dark red */\r
+ x_set_rgb(9,0,0,38); /* Med Blue */\r
+\r
+ textwindow(20);\r
+ x_set_font(1);\r
+ x_printf(textwindow_x+54,textwindow_y+4,VisiblePageOffs,6," XLIB Version 6.0");\r
+ x_printf(textwindow_x+53,textwindow_y+3,VisiblePageOffs,2," XLIB Version 6.0");\r
+ x_set_font(0);\r
+ x_printf(textwindow_x+24,textwindow_y+18,VisiblePageOffs,6," Not the Unix version");\r
+ x_printf(textwindow_x+23,textwindow_y+17,VisiblePageOffs,2," Not the Unix version");\r
+\r
+ x_printf(textwindow_x+24,168,VisiblePageOffs,6," Press any key to continue");\r
+ x_printf(textwindow_x+23,167,VisiblePageOffs,2," Press any key to continue");\r
+}\r
+\r
+void subsequent_page(void){\r
+ x_hide_mouse();\r
+ textwindow(20);\r
+ x_set_font(1);\r
+ x_printf(textwindow_x+54,textwindow_y+4,VisiblePageOffs,6," XLIB Version 6.0");\r
+ x_printf(textwindow_x+53,textwindow_y+3,VisiblePageOffs,2," XLIB Version 6.0");\r
+ x_set_font(0);\r
+ x_printf(textwindow_x+24,168,VisiblePageOffs,6," Press any key to continue");\r
+ x_printf(textwindow_x+23,167,VisiblePageOffs,2," Press any key to continue");\r
+}\r
+\r
+void load_user_fonts(void){\r
+ FILE *f;\r
+ f=fopen("var6x8.fnt","rb");\r
+ /* read char by char as fread wont read to far pointers in small model */\r
+ { int i; char c;\r
+ for (i=0;i<256*8+4;i++){\r
+ fread(&c,1,1,f);\r
+ *(userfnt1+i)=c;\r
+ }\r
+ }\r
+\r
+ fclose(f);\r
+\r
+ x_register_userfont(userfnt1);\r
+\r
+}\r
+\r
+\r
+\r
+void main(){\r
+ int i, j, xinc, yinc, Margin;\r
+ char ch;\r
+ WORD curr_x=0, curr_y=0;\r
+\r
+ pal = (char far *) farmalloc(256*3);\r
+ pal2 = (char far *) farmalloc(256*3);\r
+ userfnt1 = (char far *) farmalloc(256*16+4);\r
+\r
+\r
+ /* INITIALIZE XLIB */\r
+\r
+ /* we set up Mode X 360x200x256 with a logical width of ~ 500 */\r
+ /* pixels; we actually get 496 due to the fact that the width */\r
+ /* must be divisible by 8 */\r
+\r
+ x_text_mode(); /* make sure VGA is in color mode, if possible */\r
+ x_set_mode(X_MODE_360x200,500); /* actually is set to 496 */\r
+ x_install_vsync_handler(2);\r
+ x_set_splitscreen(ScrnPhysicalHeight-60); /* split screen 60 pixels high */\r
+ x_set_doublebuffer(220);\r
+ x_text_init();\r
+ x_hide_splitscreen();\r
+ x_mouse_init();\r
+ MouseColor=2;\r
+ atexit(exitfunc);\r
+\r
+ /* DRAW BACKGROUND LINES */\r
+\r
+ for(j=0;j<ScrnPhysicalHeight;j++){\r
+ x_line(0,j,ScrnLogicalPixelWidth,j,16+(j%239),VisiblePageOffs);\r
+ }\r
+\r
+ ctrlbrk(terminate);\r
+ x_get_pal_struc(pal, 240,16);\r
+ load_user_fonts();\r
+\r
+ intro_1();\r
+ x_set_font(2);\r
+ x_hide_mouse();\r
+ x_printf(textwindow_x+5,50 ,VisiblePageOffs,9, " Hi, folks. This is yet another FREEWARE Mode X");\r
+ x_printf(textwindow_x+5,50+8 ,VisiblePageOffs,9, " graphics library. It is by no means complete,");\r
+ x_printf(textwindow_x+5,50+16,VisiblePageOffs,9, " but I believe it contains a rich enough set of");\r
+ x_printf(textwindow_x+5,50+24,VisiblePageOffs,9, " functions to achieve its design goal - to be");\r
+ x_printf(textwindow_x+5,50+32,VisiblePageOffs,9, " a game development oriented library for");\r
+ x_printf(textwindow_x+5,50+40,VisiblePageOffs,9, " Borland TC/BC/BC++ and TASM programmers.");\r
+\r
+ x_printf(textwindow_x+5,50+48,VisiblePageOffs,9, " This library comes with TASM and C sources.");\r
+ x_printf(textwindow_x+5,50+56,VisiblePageOffs,9, " It was inspired by the DDJ Graphics column and");\r
+ x_printf(textwindow_x+5,50+64,VisiblePageOffs,9, " many INTERNET and USENET authors who, unlike the");\r
+ x_printf(textwindow_x+5,50+72,VisiblePageOffs,9, " majority of programmers (you know who you are!),");\r
+ x_printf(textwindow_x+5,50+80,VisiblePageOffs,9, " willingly share their code and ideas with others.");\r
+\r
+ x_printf(textwindow_x+5,50+88,VisiblePageOffs,9, " I can't afford, nor do I want, to copyright");\r
+ x_printf(textwindow_x+5,50+96,VisiblePageOffs,9, " this code - but if you use it, some credit would ");\r
+ x_printf(textwindow_x+5,50+104,VisiblePageOffs,9," be appreciated. ");\r
+\r
+ wait_for_keypress();\r
+\r
+ subsequent_page();\r
+ x_set_font(0);\r
+ x_printf(textwindow_x+24,textwindow_y+18,VisiblePageOffs,6,"Supported 256 colour resolutions.");\r
+ x_printf(textwindow_x+23,textwindow_y+17,VisiblePageOffs,3,"Supported 256 colour resolutions.");\r
+ x_set_font(2);\r
+ x_printf(textwindow_x+5,50 ,VisiblePageOffs,9, " 320x200 Standard for games ~ 4 pages");\r
+ x_printf(textwindow_x+5,50+8 ,VisiblePageOffs,9, " 320x240 DDJ Mode X square pixels ~ 3.5 pages");\r
+ x_printf(textwindow_x+5,50+16,VisiblePageOffs,9, " 360x200 My favourite for games ~ 3 pages ");\r
+ x_printf(textwindow_x+5,50+24,VisiblePageOffs,9, " 360x240 ~ 2.8 pages");\r
+ x_printf(textwindow_x+5,50+32,VisiblePageOffs,9, " 320x400 ~ 2 pages ");\r
+ x_printf(textwindow_x+5,50+40,VisiblePageOffs,9, " 320x480 All subsequent modes support");\r
+ x_printf(textwindow_x+5,50+48,VisiblePageOffs,9, " 360x400 less than two pages.");\r
+ x_printf(textwindow_x+5,50+56,VisiblePageOffs,9, " 360x480");\r
+ x_printf(textwindow_x+5,50+64,VisiblePageOffs,9, " 376x282,360x360,376x308,376x564,256x200,256x240");\r
+ x_printf(textwindow_x+5,50+72,VisiblePageOffs,9, " Phew! and they'll run on all VGA cards and ");\r
+ x_printf(textwindow_x+5,50+80,VisiblePageOffs,9, " monitors (some of the weird ones are best suited");\r
+ x_printf(textwindow_x+5,50+88,VisiblePageOffs,9, " to monitors with both vert & horiz adjustments)");\r
+ x_printf(textwindow_x+5,50+98,VisiblePageOffs,2, " ");\r
+ x_printf(textwindow_x+5,50+106,VisiblePageOffs,2," Overkill? Maybe!! ");\r
+\r
+\r
+ wait_for_keypress();\r
+\r
+ subsequent_page();\r
+ x_printf(textwindow_x+24,textwindow_y+18,VisiblePageOffs,6," Text display functions.");\r
+ x_printf(textwindow_x+23,textwindow_y+17,VisiblePageOffs,3," Text display functions.");\r
+ x_set_font(2);\r
+ x_printf(textwindow_x+5,50 ,VisiblePageOffs,9, " Several text printing functions are provided.");\r
+ x_printf(textwindow_x+5,50+8 ,VisiblePageOffs,9, " They support the VGA ROM 8x14 and 8x8 fonts as");\r
+ x_printf(textwindow_x+5,50+16,VisiblePageOffs,9, " well as user-defined fonts (like this 6x8 font).");\r
+ x_printf(textwindow_x+5,50+24,VisiblePageOffs,9, " Furthermore, a function similar to printf is");\r
+ x_printf(textwindow_x+5,50+32,VisiblePageOffs,9, " included which provides formatted text output.");\r
+ x_printf(textwindow_x+5,50+40,VisiblePageOffs,9, " User defined fonts may be proportionally spaced");\r
+ x_printf(textwindow_x+5,50+58,VisiblePageOffs,9, " but have a maximum width of 8 pixels.");\r
+\r
+\r
+ wait_for_keypress();\r
+\r
+ subsequent_page();\r
+ x_printf(textwindow_x+24,textwindow_y+18,VisiblePageOffs,6," Advanced screen functions.");\r
+ x_printf(textwindow_x+23,textwindow_y+17,VisiblePageOffs,3," Advanced screen functions.");\r
+ x_set_font(2);\r
+ x_printf(textwindow_x+5,50 ,VisiblePageOffs,9, " The library supports virtual screens larger");\r
+ x_printf(textwindow_x+5,50+8 ,VisiblePageOffs,9, " than the physical screen, panning of such");\r
+ x_printf(textwindow_x+5,50+16,VisiblePageOffs,9, " screens, and a split screen option.");\r
+ x_printf(textwindow_x+5,50+24,VisiblePageOffs,9, " These functions can be used together or");\r
+ x_printf(textwindow_x+5,50+32,VisiblePageOffs,9, " in isolation, and in the lower resolutions");\r
+ x_printf(textwindow_x+5,50+40,VisiblePageOffs,9, " double buffering can also be accomplished.");\r
+\r
+ x_rect_fill(0, 0, ScrnPhysicalPixelWidth,60,SplitScrnOffs,5);\r
+ x_line(0,0,ScrnPhysicalPixelWidth,0,2,SplitScrnOffs);\r
+ x_set_font(1);\r
+ x_printf(10,10,SplitScrnOffs,2, " This is a split screen, tops for scores.");\r
+ x_set_font(0);\r
+ for (i=ScrnPhysicalHeight;i>ScrnPhysicalHeight-60;i--){\r
+ x_adjust_splitscreen(i);\r
+ }\r
+ x_printf(10,25,SplitScrnOffs,2, " Even better for scrolling games etc.");\r
+\r
+ x_cp_vid_rect(0,0,ScrnLogicalPixelWidth,ScrnLogicalHeight,0,0,\r
+ VisiblePageOffs,HiddenPageOffs,\r
+ ScrnLogicalPixelWidth,ScrnLogicalPixelWidth);\r
+\r
+\r
+ x_show_mouse();\r
+ wait_for_keypress();\r
+\r
+ curr_x=curr_y=0;\r
+\r
+\r
+ init_object(60,90,4, 12, -1, 1, MK_FP(FP_SEG(bm2),FP_OFF(bm2)));\r
+ init_object(30,30,4, 12, 1, 1, MK_FP(FP_SEG(bm),FP_OFF(bm)));\r
+ init_object(80,120,4, 12, 2, 1, MK_FP(FP_SEG(bm),FP_OFF(bm)));\r
+ init_object(300,200,4, 12, 1, -2, MK_FP(FP_SEG(bm),FP_OFF(bm)));\r
+ init_object(360,30,4, 12, -1, -1, MK_FP(FP_SEG(bm),FP_OFF(bm)));\r
+ init_object(360,10,4, 12, -2, 2, MK_FP(FP_SEG(bm),FP_OFF(bm)));\r
+\r
+ x_hide_mouse();\r
+\r
+ while (!kbhit()&& !(MouseButtonStatus==LEFT_PRESSED)){\r
+ animate();\r
+ if (objects[0].X>=curr_x+ScrnPhysicalPixelWidth-32 &&\r
+ curr_x < MaxScrollX) curr_x++;\r
+ else if (objects[0].X < curr_x+16 && curr_x > 0) curr_x--;\r
+ if (objects[0].Y>=curr_y+ScrnPhysicalHeight-92 &&\r
+ curr_y < MaxScrollY) curr_y++;\r
+ else if (objects[0].Y < curr_y+16 && curr_y > 0) curr_y--;\r
+ x_page_flip(curr_x,curr_y);\r
+ while(StartAddressFlag);\r
+ }\r
+ while(MouseButtonStatus==LEFT_PRESSED);\r
+ while(kbhit()) getch();\r
+\r
+ clear_objects();\r
+ x_page_flip(curr_x,curr_y);\r
+ while(StartAddressFlag);\r
+\r
+\r
+ x_set_start_addr(0,0);\r
+\r
+\r
+ for (j=0;j<4;j++){\r
+ x_hide_splitscreen();\r
+ delay(100);\r
+ x_show_splitscreen();\r
+ delay(100);\r
+ }\r
+\r
+\r
+ for (i=ScrnPhysicalHeight-60;i<=ScrnPhysicalHeight;i++){\r
+ x_adjust_splitscreen(i);\r
+ }\r
+\r
+ x_hide_mouse();\r
+ subsequent_page();\r
+ x_printf(textwindow_x+24,textwindow_y+18,VisiblePageOffs,6," Palette functions.");\r
+ x_printf(textwindow_x+23,textwindow_y+17,VisiblePageOffs,3," Palette functions.");\r
+ x_set_font(2);\r
+ x_printf(textwindow_x+5,50 ,VisiblePageOffs,9, " A number of palette manipulation functions");\r
+ x_printf(textwindow_x+5,50+8 ,VisiblePageOffs,9, " are provided. You have already seen some of");\r
+ x_printf(textwindow_x+5,50+16,VisiblePageOffs,9, " them in action. Another common operation is");\r
+ x_printf(textwindow_x+5,50+24,VisiblePageOffs,9, " palette fading. ");\r
+\r
+ i=0;\r
+ ch=255;\r
+ while (x_cpcontrast_pal_struc(pal, pal2,ch-=2)){\r
+ x_put_pal_struc(pal2);\r
+ x_rot_pal_struc(pal,palscrolldir);\r
+ i++;\r
+ };\r
+ for (j=0;j<i;j++){\r
+ x_cpcontrast_pal_struc(pal, pal2,ch+=2);\r
+ x_put_pal_struc(pal2);\r
+ x_rot_pal_struc(pal,palscrolldir);\r
+ };\r
+ wait_for_keypress();\r
+\r
+ subsequent_page();\r
+ x_printf(textwindow_x+24,textwindow_y+18,VisiblePageOffs,6," NEW Version 3.0 Functions!");\r
+ x_printf(textwindow_x+23,textwindow_y+17,VisiblePageOffs,3," NEW Version 3.0 Functions!");\r
+ x_set_font(2);\r
+ x_printf(textwindow_x+5,50 ,VisiblePageOffs,9, " NEW functions not demonstrated here include:");\r
+ x_printf(textwindow_x+5,50+10,VisiblePageOffs,9, " - RLE data compression");\r
+ x_printf(textwindow_x+5,50+20,VisiblePageOffs,9, " - FAST compiled masked bitmaps");\r
+ x_printf(textwindow_x+5,50+30,VisiblePageOffs,9, " - Hardware detection");\r
+\r
+ x_show_mouse();\r
+ wait_for_keypress();\r
+\r
+ x_hide_mouse();\r
+ for (i = 0; i < 150; i++) {\r
+ x_circle(0, 0, i, 181 - i, VisiblePageOffs);\r
+ x_circle(360 - i, 0, i, i + 30, VisiblePageOffs);\r
+ x_circle(0, 200 - i, i, i + 30, VisiblePageOffs);\r
+ x_circle(360 - i, 200 - i, i, 181 - i, VisiblePageOffs);\r
+ }\r
+ for (i = 0; i < 100; i++)\r
+ x_filled_circle(80 + i, i, 201 - (i << 1), 30+i, VisiblePageOffs);\r
+ x_show_mouse();\r
+ wait_for_keypress();\r
+\r
+ subsequent_page();\r
+ x_printf(textwindow_x+24,textwindow_y+18,VisiblePageOffs,6," NEW Version 4.0 Functions!");\r
+ x_printf(textwindow_x+23,textwindow_y+17,VisiblePageOffs,3," NEW Version 4.0 Functions!");\r
+ x_set_font(2);\r
+ x_printf(textwindow_x+5,50 ,VisiblePageOffs,9, " NEW functions not demonstrated here include:");\r
+ x_printf(textwindow_x+5,50+10,VisiblePageOffs,9, " - FAST VRAM-based masked bitmaps, including");\r
+ x_printf(textwindow_x+5,50+18,VisiblePageOffs,9, " support for clipping regions");\r
+ x_printf(textwindow_x+5,50+28,VisiblePageOffs,9, " - Faster, smaller compiled bitmaps");\r
+ x_printf(textwindow_x+5,50+38,VisiblePageOffs,9, " - Improved planar bitmap performance and");\r
+ x_printf(textwindow_x+5,50+46,VisiblePageOffs,9, " additional support for clipping");\r
+ x_printf(textwindow_x+5,50+56,VisiblePageOffs,9, " - mouse module");\r
+ x_printf(textwindow_x+5,50+66,VisiblePageOffs,9, " - Detection of math co-processor and mouse");\r
+ x_printf(textwindow_x+5,50+76,VisiblePageOffs,9, " - Bezier curve module");\r
+ x_printf(textwindow_x+5,50+86,VisiblePageOffs,9, " - Four new resolutions, including one with");\r
+ x_printf(textwindow_x+5,50+94,VisiblePageOffs,9, " square pixels (376x282)");\r
+ x_printf(textwindow_x+5,50+104,VisiblePageOffs,9, " - More bug fixes");\r
+\r
+ wait_for_keypress();\r
+\r
+ subsequent_page();\r
+ x_printf(textwindow_x+24,textwindow_y+18,VisiblePageOffs,6," NEW Version 5.0 Functions!");\r
+ x_printf(textwindow_x+23,textwindow_y+17,VisiblePageOffs,3," NEW Version 5.0 Functions!");\r
+ x_set_font(2);\r
+ x_printf(textwindow_x+5,50 ,VisiblePageOffs,9, " - *FAST* filled and clipped triangles ideal for");\r
+ x_printf(textwindow_x+5,50+10,VisiblePageOffs,9, " 3D work. Thanks to S. Dollins for the code.");\r
+ x_printf(textwindow_x+5,50+20,VisiblePageOffs,9, " - Filled and clipped polygons, C++ Compatible");\r
+ x_printf(textwindow_x+5,50+30,VisiblePageOffs,9, " - header files, and of course bug fixes!");\r
+\r
+ x_show_mouse();\r
+ wait_for_keypress();\r
+\r
+ subsequent_page();\r
+ x_printf(textwindow_x+24,textwindow_y+18,VisiblePageOffs,6," NEW Version 6.0 Functions!");\r
+ x_printf(textwindow_x+23,textwindow_y+17,VisiblePageOffs,3," NEW Version 6.0 Functions!");\r
+ x_set_font(2);\r
+ x_printf(textwindow_x+5,50 ,VisiblePageOffs,9, " - Fast flood filling functions ");\r
+ x_printf(textwindow_x+5,50+10,VisiblePageOffs,9, " - New pbm flipping put functions.");\r
+ x_printf(textwindow_x+5,50+20,VisiblePageOffs,9, " - Timer synchronized vertical retrace");\r
+ x_printf(textwindow_x+5,50+30,VisiblePageOffs,9, " - Tripple buffering extensions");\r
+ x_printf(textwindow_x+5,50+40,VisiblePageOffs,9, " Checkout demo 9 and 10 for previews");\r
+ \r
+\r
+\r
+ x_show_mouse();\r
+ wait_for_keypress();\r
+\r
+\r
+ randomize();\r
+ x_hide_mouse();\r
+ while(kbhit()) getch();\r
+ palscrolldir^=1;\r
+ do {\r
+ int x0,x1,x2,y0,y1,y2,i;\r
+ i=random(256);\r
+ x0=random(ScrnLogicalPixelWidth);\r
+ x1=random(ScrnLogicalPixelWidth);\r
+ x2=random(ScrnLogicalPixelWidth);\r
+ y0=random(ScrnPhysicalHeight);\r
+ y1=random(ScrnPhysicalHeight);\r
+ y2=random(ScrnPhysicalHeight);\r
+ x_triangle(x0,y0,x1,y1,x2,y2,i,VisiblePageOffs);\r
+ } while (!kbhit() && !(MouseButtonStatus==LEFT_PRESSED));\r
+ while(MouseButtonStatus==LEFT_PRESSED);\r
+ while(kbhit()) getch();\r
+ x_show_mouse();\r
+\r
+ subsequent_page();\r
+ x_printf(textwindow_x+24,textwindow_y+18,VisiblePageOffs,6," PLEASE...");\r
+ x_printf(textwindow_x+23,textwindow_y+17,VisiblePageOffs,3," PLEASE...");\r
+ x_set_font(2);\r
+ x_printf(textwindow_x+5,50 ,VisiblePageOffs,9, " Please mention my name in programs that use XLIB");\r
+ x_printf(textwindow_x+5,50+8 ,VisiblePageOffs,9, " just to make me feel it was worth the effort.");\r
+ x_printf(textwindow_x+5,50+16,VisiblePageOffs,9, " If you have any bug to report please feel free to");\r
+ x_printf(textwindow_x+5,50+24,VisiblePageOffs,9, " mail me a message. Any hints, suggestions and");\r
+ x_printf(textwindow_x+5,50+32,VisiblePageOffs,9, " contributions are welcome and encouraged.");\r
+ x_printf(textwindow_x+5,50+52,VisiblePageOffs,9, " I have contributed this code to the public domain.");\r
+ x_printf(textwindow_x+5,50+60,VisiblePageOffs,9, " Please respect my wishes and leave it there.");\r
+\r
+ x_printf(textwindow_x+5,50+80,VisiblePageOffs,9, " Finally, I hope you all find this stuff useful,");\r
+ x_printf(textwindow_x+5,50+96,VisiblePageOffs,9, " Themie Gouthas - EGG@DSTOS3.DSTO.GOV.AU");\r
+\r
+ wait_for_keypress();\r
+\r
+ x_hide_mouse();\r
+\r
+ x_shift_rect (27, 27, 360-27, 177, 27, 23, VisiblePageOffs);\r
+ x_rect_fill(25, 173, 335, 176, VisiblePageOffs, 1);\r
+ for (i = 0; i < 50; i++) {\r
+ x_shift_rect (27, 26, 360-27, 177 - (i * 3), 27, 23, VisiblePageOffs);\r
+ }\r
+}\r
+\r
+\r
--- /dev/null
+/*************************************************************************\r
+\r
+DEMO 2\r
+\r
+Demonstrates the speed difference between compiled bitmap, conventional\r
+masked planar bitmap, and video bitmap blits.\r
+\r
+**************************************************************************/\r
+\r
+\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <conio.h>\r
+#include <ctype.h>\r
+#include <alloc.h>\r
+#include <dos.h>\r
+#include "xlib.h"\r
+#include "xcbitmap.h"\r
+#include "xpbitmap.h"\r
+#include "xvbitmap.h"\r
+#include "xbmtools.h"\r
+#include "xtext.h"\r
+#include "xrect.h"\r
+#include "xrect.h"\r
+\r
+/* Macro to make pointer parameters model independent */\r
+#define FARPTR(x) (MK_FP(FP_SEG(x),FP_OFF(x)))\r
+\r
+char turtle[] = {\r
+ 20,30,\r
+/* | . | . | . | . */\r
+ 8,14, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 8, 2,14, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 8, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 8, 0, 2,14, 0, 0,14,14,14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 8, 0, 2, 5, 0, 4, 4, 4, 4,14,14, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 8, 0, 2, 2, 4, 4, 0, 4, 4, 0, 4,14, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 2, 4, 4, 4, 0, 4, 4, 0, 4, 4,14, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 2, 4, 4, 4, 0, 0, 0, 0, 4, 4,14, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 4, 0, 4, 4, 4, 0, 0, 0, 4, 0, 0, 2, 2, 0, 0, 0,\r
+ 0, 0, 0, 4, 0, 4, 4, 4, 0, 4, 4, 4, 0,14, 0, 0, 2, 2, 0, 0,\r
+ 0, 0, 0, 4, 4, 0, 0, 0, 4, 4, 0, 4, 0, 4, 2, 2, 2, 2, 0, 0,\r
+ 0, 0, 0, 4, 4, 4, 0, 4, 4, 0, 4, 4, 0, 4,14, 2, 2, 2, 0, 0,\r
+ 0, 0, 0, 4, 4, 4, 0, 0, 0, 4, 4, 0, 4, 0, 0, 2, 2, 0, 0, 0,\r
+ 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4,14, 2, 0, 0, 0, 0,\r
+ 0, 0, 2, 2, 0, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0,\r
+ 2, 2, 2, 2, 4, 0, 0, 4, 4, 0, 4, 4, 0, 4,14, 0, 0, 0, 0, 0,\r
+ 0, 2, 2, 0, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 2, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 4, 4, 0, 4, 4, 4, 0, 4, 4, 2,14, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 0, 4, 0, 2, 2,14,14, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 4, 4, 2, 2, 2, 2, 2,14, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 5,14, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 2, 0, 0, 2, 2, 2, 0, 2,14,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2,14,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+ };\r
+\r
+\r
+char far *pbm, far *vbm;\r
+char far *newfnt;\r
+\r
+char far *\r
+AllocatedSprite(int width, int height, int logical_width, char far * bitmap)\r
+{\r
+ char far * result;\r
+ int size;\r
+\r
+ pbm = farmalloc(width * height + 2);\r
+ x_bm_to_pbm(bitmap,pbm);\r
+\r
+ result = farmalloc((width * height * 7) / 2 + 25);\r
+ if (result == 0)\r
+ return(0);\r
+ size = x_compile_bitmap(logical_width, bitmap, result);\r
+\r
+ return farrealloc(result, size);\r
+}\r
+\r
+\r
+\r
+void load_user_fonts(){\r
+ FILE *f;\r
+ int i; char c;\r
+// f=fopen("c:\\font.fnt","rb");\r
+ f=fopen("smalbold.fnt","rb");\r
+ newfnt = farmalloc(256*16+4);\r
+ for (i=0;i<256*16+4;i++){\r
+ fread(&c,1,1,f);\r
+ *(newfnt+i)=c;\r
+ }\r
+ fclose(f);\r
+ x_text_init();\r
+ x_register_userfont(newfnt);\r
+ x_set_font(2);\r
+}\r
+\r
+void\r
+main()\r
+{\r
+ int i,j,k;\r
+\r
+ double ratio,ratio2;\r
+ struct time pbm_t0,pbm_t1,cbm_t0,cbm_t1,vbm_t0,vbm_t1;\r
+ long vbm_ticks,pbm_ticks,cbm_ticks;\r
+ char far * TurtleSprite;\r
+\r
+ x_set_mode(X_MODE_320x240,360);\r
+\r
+ TurtleSprite = AllocatedSprite(20, 30, 90,FARPTR(turtle));\r
+\r
+ vbm = x_make_vbm(MK_FP(_DS,turtle),&NonVisual_Offs);\r
+ if (!vbm) {\r
+ sound(1000);\r
+ delay(100);\r
+ nosound();\r
+ }\r
+\r
+ load_user_fonts();\r
+ x_bgprintf(0,0,0,14,0,\r
+ "This is a demo to show the speed difference between");\r
+ x_bgprintf(0,8,0,14,0,\r
+ "compiled, planar and video bitmaps. The bitmap:");\r
+\r
+ x_put_cbitmap(140, 18, 0, TurtleSprite);\r
+\r
+ x_bgprintf(0,48,0,14,0,\r
+ "This demo uses the NON CLIPPED, MASKED versions of");\r
+ x_bgprintf(0,56,0,14,0,\r
+ " 'PBM' and VBM' put functions");\r
+ x_bgprintf(0,78,0,14,0,\r
+ "Press a key to start with PLANAR BITMAP demo");\r
+\r
+ getch();\r
+ x_rect_fill(0,0,ScrnPhysicalPixelWidth,ScrnPhysicalHeight,0,0);\r
+\r
+\r
+ gettime(&pbm_t0);\r
+ for (k=0;k<3;k++)\r
+ for (j=0;j<(ScrnPhysicalHeight/30);j++)\r
+ for (i=0;i<(ScrnPhysicalPixelWidth/20);i++)\r
+ x_put_masked_pbm(i*20, j*30, 0, pbm);\r
+ gettime(&pbm_t1);\r
+ pbm_ticks = (((long)pbm_t1.ti_hund\r
+ +((long)pbm_t1.ti_sec*100)\r
+ +((long)pbm_t1.ti_min*6000)) -\r
+ (((long)pbm_t0.ti_hund\r
+ +((long)pbm_t0.ti_sec*100)\r
+ +((long)pbm_t0.ti_min*6000))));\r
+\r
+\r
+ x_bgprintf(0,0,0,14,0,\r
+ "Press a key to start with the VIDEO BITMAP demo");\r
+\r
+ getch();\r
+ x_rect_fill(0,0,ScrnPhysicalPixelWidth,ScrnPhysicalHeight,0,0);\r
+\r
+\r
+ gettime(&vbm_t0);\r
+ for (k=0;k<3;k++)\r
+ for (j=0;j<(ScrnPhysicalHeight/30);j++)\r
+ for (i=0;i<(ScrnPhysicalPixelWidth/20);i++)\r
+ x_put_masked_vbm(i*20, j*30, 0, vbm);\r
+ gettime(&vbm_t1);\r
+ vbm_ticks = (((long)vbm_t1.ti_hund\r
+ +((long)vbm_t1.ti_sec*100)\r
+ +((long)vbm_t1.ti_min*6000)) -\r
+ (((long)vbm_t0.ti_hund\r
+ +((long)vbm_t0.ti_sec*100)\r
+ +((long)vbm_t0.ti_min*6000))));\r
+\r
+\r
+\r
+\r
+ x_bgprintf(0,0,0,14,0,\r
+ "Now Press a key to start with COMPILED BITMAP demo");\r
+\r
+ getch();\r
+ x_rect_fill(0,0,ScrnPhysicalPixelWidth,ScrnPhysicalHeight,0,0);\r
+\r
+ gettime(&cbm_t0);\r
+ for (k=0;k<3;k++)\r
+ for (j=0;j<(ScrnPhysicalHeight/30);j++)\r
+ for (i=0;i<(ScrnPhysicalPixelWidth/20);i++)\r
+ x_put_cbitmap(i*20, j*30, 0, TurtleSprite);\r
+ gettime(&cbm_t1);\r
+ cbm_ticks = (((long)cbm_t1.ti_hund\r
+ +((long)cbm_t1.ti_sec*100)\r
+ +((long)cbm_t1.ti_min*6000)) -\r
+ (((long)cbm_t0.ti_hund\r
+ +((long)cbm_t0.ti_sec*100)\r
+ +((long)cbm_t0.ti_min*6000))));\r
+ if (cbm_ticks==0){\r
+ cbm_ticks=1;\r
+ pbm_ticks+=1;\r
+ vbm_ticks+=1;\r
+ }\r
+ ratio = pbm_ticks*(double)1.0/cbm_ticks;\r
+ ratio2 = vbm_ticks*(double)1.0/cbm_ticks;\r
+\r
+ x_set_font(1);\r
+ x_bgprintf(0,ScrnPhysicalHeight-30,0,14,0,\r
+ "s/100 PBM=%ld VBM=%ld CBM=%ld - %4.1lf:%4.1lf:1",\r
+ pbm_ticks,vbm_ticks,cbm_ticks,ratio,ratio2);\r
+ x_set_font(2);\r
+ x_bgprintf(0,ScrnPhysicalHeight-16,0,14,0,\r
+ "Timing is rough but still, quite impressive ! ");\r
+ x_bgprintf(0,ScrnPhysicalHeight-8,0,14,0,\r
+ "Clipping slows things down considerably. ");\r
+\r
+\r
+ getch();\r
+ x_text_mode();\r
+}\r
+\r
--- /dev/null
+#include <stdio.h>\r
+#include "xlib.h"\r
+#include "xdetect.h"\r
+int processor;\r
+void main(void){\r
+ printf("Hardware detection demo...\n\n");\r
+ printf("Graphics Card : ");\r
+ switch (x_graphics_card()){\r
+ case NoGraphics: printf("None\n"); break;\r
+ case MDA: printf("MDA\n"); break;\r
+ case CGA: printf("CGA\n"); break;\r
+ case EGAMono: printf("EGA Mono\n"); break;\r
+ case EGAColor: printf("EGA Color\n"); break;\r
+ case VGAMono: printf("VGA Mono\n");\r
+ case VGAColor: printf("VGA Color\n"); break;\r
+ case MCGAMono: printf("MCGA mono\n"); break;\r
+ case MCGAColor: printf("MCGA Color\n"); break;\r
+ };\r
+ printf("Processor : ");\r
+ switch (processor=x_processor()){\r
+ case I8086: printf("8088 or 8086\n"); break;\r
+ case I80186: printf("80186\n"); break;\r
+ case I80286: printf("80286\n"); break;\r
+ case I80386SX: printf("80386-SX\n"); break;\r
+ case I80386DX: printf("80386-DX\n"); break;\r
+ };\r
+\r
+ if (processor==I80486){\r
+ if (x_coprocessor()) printf("80486-DX or 80486-SX+FPU\n");\r
+ else printf("80486-SX\n");\r
+ } else {\r
+ printf("Math Co-Processor: ");\r
+ switch (x_coprocessor()){\r
+ case 0: printf("8088 Assumed\n"); break;\r
+ case 1: switch (processor=x_processor()){\r
+ case I8086: printf("80287 Assumed\n"); break;\r
+ case I80186: printf("80187 Assumed\n"); break;\r
+ case I80286: printf("0287 Assumed\n"); break;\r
+ case I80386SX:\r
+ case I80386DX: printf("80387 Assumed\n"); break;\r
+ };\r
+ };\r
+ };\r
+ printf("Mouse Driver : ");\r
+ switch (x_mousedriver()){\r
+ case 0: printf("not installed\n"); break;\r
+ case 1: {\r
+ printf("installed (Mouse Driver vers %d.%d)\n",\r
+ (MouseVersion>>8),(MouseVersion&0xff));\r
+ printf(" ");\r
+ switch (MouseType) {\r
+ case BUS_MOUSE: printf("Bus Mouse on IRQ");break;\r
+ case SERIAL_MOUSE: printf("Serial Mouse on IRQ ");break;\r
+ case INPORT_MOUSE: printf("Inport Mouse on IRQ ");break;\r
+ case PS2_MOUSE: printf("PS/2 Mouse on IRQ ");break;\r
+ case HP_MOUSE: printf("HP Mouse on IRQ ");break;\r
+ default : printf("Unknown Mouse on IRQ ");break;\r
+ }\r
+ printf("%d with %d buttons.",MouseIRQ, MouseButtonCount);\r
+ }\r
+ }\r
+ }
\ No newline at end of file
--- /dev/null
+/*************************************************************************\r
+\r
+DEMO 4\r
+\r
+Demonstrates RLE encoding to file QUICK and DIRTY\r
+**************************************************************************/\r
+\r
+\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <conio.h>\r
+#include <ctype.h>\r
+#include <alloc.h>\r
+#include <dos.h>\r
+#include "xlib.h"\r
+#include "xvbitmap.h"\r
+#include "xbmtools.h"\r
+#include "xtext.h"\r
+#include "xrect.h"\r
+#include "xrletool.h"\r
+#include "xfileio.h"\r
+/* Macro to make pointer parameters model independent */\r
+#define FARPTR(x) (MK_FP(FP_SEG(x),FP_OFF(x)))\r
+\r
+char turtle[] = {\r
+ 20,30,\r
+/* | . | . | . | . */\r
+ 8,14, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 8, 2,14, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 8, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 8, 0, 2,14, 0, 0,14,14,14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 8, 0, 2, 5, 0, 4, 4, 4, 4,14,14, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 8, 0, 2, 2, 4, 4, 0, 4, 4, 0, 4,14, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 2, 4, 4, 4, 0, 4, 4, 0, 4, 4,14, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 2, 4, 4, 4, 0, 0, 0, 0, 4, 4,14, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 4, 0, 4, 4, 4, 0, 0, 0, 4, 0, 0, 2, 2, 0, 0, 0,\r
+ 0, 0, 0, 4, 0, 4, 4, 4, 0, 4, 4, 4, 0,14, 0, 0, 2, 2, 0, 0,\r
+ 0, 0, 0, 4, 4, 0, 0, 0, 4, 4, 0, 4, 0, 4, 2, 2, 2, 2, 0, 0,\r
+ 0, 0, 0, 4, 4, 4, 0, 4, 4, 0, 4, 4, 0, 4,14, 2, 2, 2, 0, 0,\r
+ 0, 0, 0, 4, 4, 4, 0, 0, 0, 4, 4, 0, 4, 0, 0, 2, 2, 0, 0, 0,\r
+ 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4,14, 2, 0, 0, 0, 0,\r
+ 0, 0, 2, 2, 0, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0,\r
+ 2, 2, 2, 2, 4, 0, 0, 4, 4, 0, 4, 4, 0, 4,14, 0, 0, 0, 0, 0,\r
+ 0, 2, 2, 0, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 2, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 4, 4, 0, 4, 4, 4, 0, 4, 4, 2,14, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 0, 4, 0, 2, 2,14,14, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 4, 4, 2, 2, 2, 2, 2,14, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 5,14, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 2, 0, 0, 2, 2, 2, 0, 2,14,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2,14,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+ };\r
+\r
+\r
+char far *pbm;\r
+char far *newfnt;\r
+int far *buffsize;\r
+\r
+void error(char * string){\r
+ x_text_mode();\r
+ printf("%s\n",string);\r
+ exit(0);\r
+}\r
+\r
+void load_user_fonts(){\r
+ FILE *f;\r
+ int i; char c;\r
+ f=fopen("var6x8.fnt","rb");\r
+ newfnt = farmalloc(256*16+4);\r
+ for (i=0;i<256*16+4;i++){\r
+ fread(&c,1,1,f);\r
+ *(newfnt+i)=c;\r
+ }\r
+ fclose(f);\r
+ x_text_init();\r
+ x_register_userfont(newfnt);\r
+ x_set_font(2);\r
+}\r
+\r
+void main(){\r
+ int i,j,handle,size,comp_size;\r
+ char far * tempbuff,far * diskbuff;\r
+\r
+ pbm = farmalloc(20 * 30 + 2);\r
+ x_bm_to_pbm( MK_FP(FP_SEG(turtle),FP_OFF(turtle)), pbm);\r
+\r
+ x_set_mode(X_MODE_360x240,360);\r
+ load_user_fonts();\r
+\r
+ x_bgprintf(0,0,0,14,0,\r
+ "This is a demo of RLE compression of 360x240 video screen to ");\r
+ x_bgprintf(0,8,0,14,0,\r
+ "disk. Uncompressed, this screen requires a file of size ");\r
+ x_bgprintf(0,16,0,14,0,"86400 (360x240) bytes.");\r
+ x_bgprintf(0,48,0,14,0,\r
+ "Press a key to draw the image and save it to screen:");\r
+\r
+ getch();\r
+ x_rect_fill(0,0,ScrnPhysicalPixelWidth,ScrnPhysicalHeight,0,0);\r
+\r
+ for (j=0;j<(ScrnPhysicalHeight/30);j++)\r
+ for (i=0;i<(ScrnPhysicalPixelWidth/20);i++)\r
+ x_put_masked_pbm(i*20, j*30, 0, pbm);\r
+\r
+ x_set_start_addr(0,240);\r
+\r
+ x_bgprintf(0,0,240*90,14,0,\r
+ "Now compressing and writing to file 'screen.dat'.");\r
+ x_bgprintf(0,8,240*90,14,0,"Please wait... ");\r
+\r
+\r
+ if((handle=f_open("screen.dat",F_WRONLY))==FILE_ERR)\r
+ error("Unable to open 'screen.dat' for writing.");\r
+ size=0;\r
+ tempbuff=farmalloc(90*240);\r
+ diskbuff=farmalloc(90*240);\r
+ buffsize=(int far *)farmalloc(2);\r
+\r
+ for (i=0;i<4;i++){\r
+ x_select_default_plane(i);\r
+ if (!(j=x_buff_RLEncode(MK_FP(0xA000,0),tempbuff,90*240)))\r
+ error("Error buff compressing");\r
+ *buffsize=j;\r
+ f_writefar(handle,(char far *)buffsize,2);\r
+ f_writefar(handle,tempbuff,j);\r
+ size+=j;\r
+ }\r
+ comp_size=size;\r
+ f_close(handle);\r
+\r
+ if((handle=f_open("screen.raw",F_WRONLY))==FILE_ERR)\r
+ error("Unable to open 'screen.dat' for writing.");\r
+ for (i=0;i<4;i++){\r
+ x_select_default_plane(i);\r
+ f_writefar(handle,MK_FP(0xA000,0),90*240);\r
+ }\r
+ f_close(handle);\r
+\r
+ x_bgprintf(0,8,240*90,14,0,"Done. Press a key to restore.");\r
+ getch();\r
+\r
+ x_rect_fill(0,0,ScrnPhysicalPixelWidth,ScrnPhysicalHeight,0,0);\r
+ x_set_start_addr(0,0);\r
+\r
+ if((handle=f_open("screen.dat",F_RDONLY))==FILE_ERR)\r
+ error("Unable to open 'screen.dat' for reading.");\r
+\r
+ size=0;\r
+ for (i=0;i<4;i++){\r
+ x_select_default_plane(i);\r
+ f_readfar(handle,(char far *)buffsize,2);\r
+ f_readfar(handle,diskbuff,*buffsize);\r
+ j=x_buff_RLDecode(diskbuff,MK_FP(0xA000,0));\r
+ size+=j;\r
+ }\r
+ f_close(handle);\r
+\r
+ getch();\r
+ x_text_mode();\r
+ printf("screen size = 86400 compressed = %u",comp_size);\r
+}\r
+\r
+\1a
\ No newline at end of file
--- /dev/null
+/*************************************************************************\r
+\r
+DEMO 5\r
+\r
+Demonstrates Planar Bitmap Clipping Functions\r
+\r
+Themie Gouthas\r
+**************************************************************************/\r
+\r
+\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <conio.h>\r
+#include <ctype.h>\r
+#include <alloc.h>\r
+#include <dos.h>\r
+#include "xlib.h"\r
+#include "xpbitmap.h"\r
+#include "xpbmclip.h"\r
+#include "xrect.h"\r
+#include "xbmtools.h"\r
+#include "xline.h"\r
+#include "xtext.h"\r
+/* Macro to make pointer parameters model independent */\r
+#define FARPTR(x) (MK_FP(FP_SEG(x),FP_OFF(x)))\r
+\r
+int i,j;\r
+\r
+char turtle[] = {\r
+ 20,30,\r
+/* | . | . | . | . */\r
+ 8,14, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 8, 2,14, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 8, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 8, 0, 2,14, 0, 0,14,14,14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 8, 0, 2, 5, 0, 4, 4, 4, 4,14,14, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 8, 0, 2, 2, 4, 4, 0, 4, 4, 0, 4,14, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 2, 4, 4, 4, 0, 4, 4, 0, 4, 4,14, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 2, 4, 4, 4, 0, 0, 0, 0, 4, 4,14, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 4, 0, 4, 4, 4, 0, 0, 0, 4, 0, 0, 2, 2, 0, 0, 0,\r
+ 0, 0, 0, 4, 0, 4, 4, 4, 0, 4, 4, 4, 0,14, 0, 0, 2, 2, 0, 0,\r
+ 0, 0, 0, 4, 4, 0, 0, 0, 4, 4, 0, 4, 0, 4, 2, 2, 2, 2, 0, 0,\r
+ 0, 0, 0, 4, 4, 4, 0, 4, 4, 0, 4, 4, 0, 4,14, 2, 2, 2, 0, 0,\r
+ 0, 0, 0, 4, 4, 4, 0, 0, 0, 4, 4, 0, 4, 0, 0, 2, 2, 0, 0, 0,\r
+ 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4,14, 2, 0, 0, 0, 0,\r
+ 0, 0, 2, 2, 0, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0,\r
+ 2, 2, 2, 2, 4, 0, 0, 4, 4, 0, 4, 4, 0, 4,14, 0, 0, 0, 0, 0,\r
+ 0, 2, 2, 0, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 2, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 4, 4, 0, 4, 4, 4, 0, 4, 4, 2,14, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 0, 4, 0, 2, 2,14,14, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 4, 4, 2, 2, 2, 2, 2,14, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 5,14, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 2, 0, 0, 2, 2, 2, 0, 2,14,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2,14,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+ };\r
+\r
+\r
+char far *vbm;\r
+\r
+void error(char * string){\r
+ x_text_mode();\r
+ printf("%s\n",string);\r
+ exit(0);\r
+}\r
+\r
+typedef struct {\r
+ unsigned int size; /* valid only for the first header */\r
+ unsigned char ImageWidth;\r
+ unsigned char ImageHeight;\r
+ unsigned int ImagePtr;\r
+ unsigned int MaskPtr;\r
+} alignment_header;\r
+\r
+\r
+void main(){\r
+ int i,j,k,handle,size,comp_size;\r
+ char far *bm;\r
+\r
+ alignment_header far * tempbuff;\r
+ x_set_mode(X_MODE_360x240,360);\r
+ ;NonVisual_Offs=16384;\r
+\r
+ x_text_init();\r
+ x_set_font(FONT_8x15);\r
+ x_bgprintf(0,0,0,14,0," This is a demo of PBM clipping.");\r
+ getch();\r
+\r
+ bm=farmalloc(20*30+2);\r
+ x_bm_to_pbm(MK_FP(_DS,turtle),bm);\r
+\r
+ x_set_cliprect(4,5,50,150);\r
+\r
+ x_line(0,TopClip-1,320,TopClip-1,23,0);\r
+ x_line(0,BottomClip+1,320,BottomClip+1,23,0);\r
+ x_line((LeftClip<<2)-1,0,(LeftClip<<2)-1,200,23,0);\r
+ x_line((RightClip<<2)+4,0,(RightClip<<2)+4,200,23,0);\r
+\r
+ for (k=0;k<8;k++){\r
+ for (j=1;j<ScrnPhysicalHeight;j+=30)\r
+ for (i=0;i<ScrnPhysicalPixelWidth-20;i+=20)\r
+ x_put_pbm(i+k+1,j,0,bm);\r
+ }\r
+\r
+ x_line(0,TopClip-1,320,TopClip-1,23,0);\r
+ x_line(0,BottomClip+1,320,BottomClip+1,23,0);\r
+ x_line((LeftClip<<2)-1,0,(LeftClip<<2)-1,200,23,0);\r
+ x_line((RightClip<<2)+4,0,(RightClip<<2)+4,200,23,0);\r
+\r
+ x_rect_fill((LeftClip<<2),TopClip,(RightClip<<2)+3,BottomClip,0,0);\r
+\r
+ x_bgprintf(0,BottomClip+4,0,14,0," Now the clipping...");\r
+ getch();\r
+\r
+ for (k=0;k<8;k++){\r
+ for (j=1;j<ScrnPhysicalHeight;j+=30)\r
+ for (i=0;i<ScrnPhysicalPixelWidth-20;i+=20)\r
+ x_put_pbm_clipxy(i+k+1,j,0,bm);\r
+ }\r
+ for (k=0;k<8;k++){\r
+ for (j=1;j<ScrnPhysicalHeight;j+=30)\r
+ for (i=0;i<ScrnPhysicalPixelWidth-20;i+=20)\r
+ x_put_pbm_clipxy(i+7+1,j+k,0,bm);\r
+ }\r
+ for (k=7;k>=0;k--){\r
+ for (j=1;j<ScrnPhysicalHeight;j+=30)\r
+ for (i=0;i<ScrnPhysicalPixelWidth-20;i+=20)\r
+ x_put_pbm_clipxy(i+k+1,j+7,0,bm);\r
+ }\r
+ for (k=7;k>=0;k--){\r
+ for (j=1;j<ScrnPhysicalHeight;j+=30)\r
+ for (i=0;i<ScrnPhysicalPixelWidth-20;i+=20)\r
+ x_put_pbm_clipxy(i+1,j+k,0,bm);\r
+ }\r
+\r
+ getch();\r
+ x_text_mode();\r
+ printf("%d %d %d %d\n",LeftClip,TopClip,RightClip,BottomClip);\r
+\r
+}\r
+\r
--- /dev/null
+#include <conio.h>\r
+\r
+#include "xlib.h"\r
+#include "xcircle.h"\r
+\r
+void main(void)\r
+{\r
+ int i;\r
+\r
+ x_set_mode(1, 320);\r
+ for (i = 0; i < 120; i++) {\r
+ x_circle(0, 0, i, 121 - i, 0);\r
+ x_circle(319 - i, 0, i, i - 20, 0);\r
+ x_circle(0, 239 - i, i, i - 20, 0);\r
+ x_circle(319 - i, 239 - i, i, 121 - i, 0);\r
+ x_filled_circle(40 + i, i, 241 - (i << 1), i+1, 0);\r
+ }\r
+ getch();\r
+\r
+ x_text_mode();\r
+}\r
+\1a
\ No newline at end of file
--- /dev/null
+/* Program to demonstrate Bezier curves */\r
+\r
+#include <conio.h>\r
+\r
+#include "xlib.h"\r
+#include "xbezier.h"\r
+#include "xpal.h"\r
+\r
+void main(void)\r
+{\r
+ int i, r, g, b;\r
+\r
+ x_set_mode(X_MODE_360x480, 360);\r
+\r
+ for (b = 0; b < 6; b++)\r
+ for (g = 0; g < 6; g++)\r
+ for (r = 0; r < 6; r++)\r
+ x_set_rgb(b + 6 * g + 36 * r,\r
+ 12 * b + 3, 12 * g + 3, 12 * r + 3);\r
+ for (i = 216; i < 256; i++)\r
+ x_set_rgb(i, i - 193, i - 193, 279 - i);\r
+\r
+ for (i = 0; i <= 1080; i++) {\r
+ x_bezier(i, 240, 90, i, 270, 479-i, 359 - i, 240,\r
+ 6, i ,0);\r
+ }\r
+ for (i = 720; i >= 0; i--) {\r
+ x_bezier(360 - i, i/3, 360 - i, i, i, i, i, i/3,\r
+ 4, i ,0);\r
+ x_bezier(360 - i, 479-i/3, 360 - i, 479-i, i, 479-i, i, 479-i/3,\r
+ 4, i ,0);\r
+ }\r
+\r
+ getch();\r
+\r
+ x_text_mode();\r
+}\r
+\r
--- /dev/null
+/*************************************************************************\r
+\r
+DEMO 2\r
+\r
+Demonstrates the speed difference between compiled bitmap, conventional\r
+masked planar bitmap, and video bitmap blits.\r
+\r
+**************************************************************************/\r
+\r
+\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <conio.h>\r
+#include <ctype.h>\r
+#include <alloc.h>\r
+#include <dos.h>\r
+#include <dir.h>\r
+#include <string.h>\r
+\r
+#include "xlib.h"\r
+#include "xtext.h"\r
+#include "xrect.h"\r
+\r
+/* Macro to make pointer parameters model independent */\r
+#define FARPTR(x) (MK_FP(FP_SEG(x),FP_OFF(x)))\r
+\r
+char *swidth[10]={"0","1","2","3","4","5","6","7","8","9"};\r
+char far *fonts[20];\r
+char names[20][20];\r
+int i,fcount=0;\r
+ char c;\r
+\r
+typedef struct {\r
+ int dummy;\r
+ char height;\r
+ char width;\r
+} header;\r
+\r
+void load_user_fonts(){\r
+ FILE *f;\r
+ long len;\r
+ struct ffblk ffblock;\r
+\r
+ if(findfirst("*.fnt",&ffblock,0)!=0){\r
+ printf("No Fonts found in current directory!\n");\r
+ exit(0);\r
+ };\r
+ do {\r
+ printf("Loading font \"%s\"...\n",ffblock.ff_name);\r
+ strncpy(names[fcount],ffblock.ff_name,14);\r
+\r
+ f=fopen(ffblock.ff_name,"rb");\r
+\r
+ fseek(f,0,SEEK_END);\r
+ len=ftell(f);\r
+ fseek(f,0,SEEK_SET);\r
+\r
+ fonts[fcount] = farmalloc(len);\r
+ if (!fonts[fcount]){\r
+ printf("Out of memory");\r
+ if (fcount!=0){\r
+ printf("- No more fonts can be loaded\n");\r
+ fclose(f);\r
+ goto NoMoreFonts;\r
+ } else printf("\n");\r
+\r
+ exit(0);\r
+ };\r
+\r
+ for (i=0;i<len;i++){\r
+ fread(&c,1,1,f);\r
+ *(fonts[fcount]+i)=c;\r
+ }\r
+\r
+ fclose(f);\r
+ fcount++;\r
+\r
+ } while (!findnext(&ffblock));\r
+\r
+NoMoreFonts:\r
+ printf("\n Press 'v' to view, any other key to quit\n");\r
+ c=getch();\r
+ if (c!='V' && c!='v'){\r
+ x_text_mode();\r
+ exit(0);\r
+ }\r
+\r
+ x_text_init();\r
+ x_set_mode(X_MODE_320x240,0);\r
+ x_register_userfont(fonts[0]);\r
+ x_set_font(2);\r
+}\r
+\r
+ //......................................//\r
+char *text[30] = {"EXTRACT: Stephen King's \"SALEM'S LOT\" ",\r
+ "",\r
+ "The memory rose up in almost total ",\r
+ "sensory reference, and for the moment ",\r
+ "of its totality he was paralyzed. He ",\r
+ "could even smell the plaster and the ",\r
+ "wild odour of nesting animals. It ",\r
+ "seemed to him that the plain varnished",\r
+ "door of Matt Burke's guest room stood ",\r
+ "between him and all the secrets of ",\r
+ "Hell. Then he twisted the knob and ",\r
+ "pushed the door handle inwards... ",\r
+ "",\r
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ ",\r
+ "abcdefghijklmnopqrstuvwxyz 0123456789 ",\r
+ "~!@#$%^&*()_+|`-=\\{}[]:\";'<>?,./ ",\r
+ NULL};\r
+\r
+\r
+\r
+\r
+\r
+void main(){\r
+ int textline;\r
+ int strindex;\r
+ int height;\r
+ load_user_fonts();\r
+\r
+\r
+\r
+ for (i=0;i<fcount;i++){\r
+ x_set_font(FONT_8x8);\r
+ x_rect_fill(0, 0, 319, 239, 0, 0);\r
+ x_line(0,9,319,9,14,0);\r
+ x_line(0,ScrnPhysicalHeight-10,319,ScrnPhysicalHeight-10,14,0);\r
+\r
+ x_bgprintf(0,0,0,14,0,"Font \"%s\" H=%d,W=%s",names[i],\r
+ (int)*(fonts[i]+2),\r
+ (*(fonts[i]+3)==0)?"Variable":swidth[*(fonts[i]+3)]);\r
+ x_bgprintf(0,ScrnPhysicalHeight-8,0,14,0,\r
+ "Press a key for next font...");\r
+\r
+ x_register_userfont(fonts[i]);\r
+ x_set_font(FONT_USER);\r
+\r
+ height=(int)*(fonts[i]+2)+1;\r
+ textline=12;\r
+ strindex=0;\r
+ while(text[strindex]){\r
+ x_printf(0,textline,0,14,text[strindex++]);\r
+ textline+=height;\r
+ }\r
+\r
+ getch();\r
+ }\r
+\r
+ x_text_mode();\r
+}\r
+\r
--- /dev/null
+IFDEF s\r
+ DISPLAY "XLIB04 Small Model"\r
+ .model small\r
+ELSE\r
+ IFDEF c\r
+ DISPLAY "XLIB04 Compact Model"\r
+ .model compact\r
+ ELSE\r
+ IFDEF l\r
+ DISPLAY "XLIB04 Large Model"\r
+ .model large\r
+ ELSE\r
+ DISPLAY "WARNING: Model was not defined at the command line."\r
+ DISPLAY " Using default small model ie /ds "\r
+ DISPLAY " Include in TASM commandline either /ds, /dc or /dl"\r
+ .model small\r
+ ENDIF\r
+ ENDIF\r
+ENDIF\r
+\r
+\1a
\ No newline at end of file
--- /dev/null
+This is XLIB the mode X graphics library. There is no organization to the\r
+files in this archive; that is left up to each users preferences.\r
+\r
+Famous last words ;-)\r
+\r
+"This is the last version I intend to release, unless of course someone has\r
+something really nifty they'd like to contribute."\r
+\r
+MOUSE TIP:\r
+\r
+Theres a slight design flaw in the mouse driver and lots of people have had\r
+problems with mouse droppings in the lower RH corner of the screen. This \r
+happens under some circulstances because the code does not clip the saved\r
+background as is done for the cursor graphic itself so bits of the mouse \r
+graphic stored in the video ram just below the visual page get picked up into \r
+the background.\r
+\r
+To bypass this problem is simple when you know how. If you are having this \r
+problem insert NonVisual_Offs+=ScrnLogicalByteWidth*14 just before the call\r
+to x_init_mouse.\r
+\r
+Sorry about not fixing the problem more elegantly, but I didn't want to \r
+do any major work on the mouse driver.\r
+\r
+Themie\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
--- /dev/null
+Xlib version 2 modifications\r
+\r
+Files modified:\r
+ XLIB.INC\r
+ XMAIN.ASM\r
+ DEMO.C\r
+\r
+\r
+26-09-92 - PRIMARILY JUST ADDED SUPPORT FOR PEL PANNING\r
+\r
+ Pel panning code added to allow for panning to any pixel\r
+ coordinates.\r
+ Functions affected:\r
+ x_set_splitscreen\r
+ Split screen pel panning suppression code added.\r
+ Functionally unchanged.\r
+ x_set_start_addr,x_page_flip\r
+ Pel panning code added. The x parameter now expects\r
+ a pixel coordinate where previously a byte coordinate\r
+ was expected.\r
+\r
+ Original files modified\r
+ -----------------------\r
+ XLIB.INC\r
+ XMAIN.ASM\r
+ DEMO.C\r
+ Aknowledgements\r
+ ---------------\r
+ Thanks to Robert Schmidt for contributed PEL panning sample\r
+ code and everyone else who responded to my rec.games.programmer\r
+ post.\r
+\r
+Xlib version 3 modifications\r
+\r
+10-10-92 - BUG ERADICATION AND ADDITION OF NEW MODULES AND MINOR CODE\r
+ EXTENSIONS\r
+\r
+ MaxScrollX and MaxScrollY were not always set correctly, now\r
+ that's fixed (I Think)\r
+ Added variable "SplitScrnVisibleHeight" needed for above fix.\r
+ Some miscellaneous code changes\r
+ Included XCBITMAP module generously donated by Matthew MacKenzie\r
+ Added support for the LARGE memory model\r
+ Added a make file to simplify compilation\r
+ Library modules now compiled into .LIB files\r
+ Added a documentation file\r
+ Added XBMTOOLS module containing bitmap type conversion\r
+ Added XDETECT module containing hardware detection functions\r
+ Added C header files for all modules\r
+ ADDED XFILEIO module\r
+ ADDED XRLETOOL module\r
+\r
+ Original files modified\r
+ -----------------------\r
+ XLIB.INC\r
+ XMAIN.ASM\r
+ DEMO.C\r
+ XTEXT.INC\r
+ XTEXT.ASM\r
+\r
+ Aknowledgements\r
+ ---------------\r
+ Special thanks to Matthew Mackenzie for an excellent module\r
+ and Darren Lyon for putting together a C header file for XLIB.\r
+ Again thanks also to everyone else who supported this software.\r
+\r
+Xlib version 4 modifications\r
+\r
+\r
+30-10-92 EXTENSIONS TO XLIB 3 AND BUG FIXES\r
+\r
+ Files Modified\r
+ --------------\r
+ Assume all have been modified\r
+\r
+ Modifications/Additions\r
+ ------------------------\r
+ **** Fixed ATI VGA incompatibility problem **** 4\r
+ **** Fixed Large Model problems ***************\r
+ Manual : The ref. manual has been split ito two files for\r
+ those editors that cannot cope with file > 64k\r
+ XDETECT: added numeric co-pro detection\r
+ added mouse driver detection\r
+ XMAIN : added new resolution tweaks\r
+ added clipping rectangle setting proc and vars\r
+ further bug fixes (I can't remember exactly what)\r
+ XCBITMAP:Improved performance of compilation and compiled bitmaps\r
+ and added a function to calculate mem required for\r
+ a bitmap compilation\r
+ XPBITMAP:Improved performance of planar bitmaps\r
+ XRECT :Added "x_shift_rect" function\r
+ XPBMTOOL:Added several utility macros\r
+\r
+ New Modules\r
+ -----------\r
+ XPBMCLIP:Implements clipping versions of functions in XPBITMAP\r
+ XVBITMAP:Video based masked bitmap functions. Contains standard\r
+ and clipping versions of all functions.\r
+ XMAKEVBM:Support module for XVBITMAP\r
+ XMOUSE :Basic mouse support module\r
+ XBEZIER :Fast Bezier curves (For scalable fonts etc..)\r
+\r
+\r
+Xlib version 4b modifications\r
+\r
+10-12-92 BUG FIX RELEASE\r
+\r
+ Files Modified\r
+ --------------\r
+\r
+ XMAIN.*\r
+ XPBMCLIP.*\r
+ XVBMCLIP.*\r
+ XCLIPPBM.*\r
+\r
+ Modifications/Additions\r
+ ------------------------\r
+ Some minor fixes and modifications in xmain.asm\r
+ fixed the split screen starting scan line problem\r
+\r
+ This fix is a cludge - Sam Thompson has suggested a more\r
+ elegant fix but I just dont have much time these days\r
+\r
+ changed mode setting code to allow 320x200 mode to have same\r
+ aspect ratio as mode 13h\r
+\r
+ The clipped functions were modified to return 1 if the image being\r
+ clipped was completely off the logical screen.\r
+ Minor clipping bugs which gave inconsistent results when clipping\r
+ to the left and right screen borders were fixed in the XPBMCLIP &\r
+ VBMCLIP modules.\r
+ A bug in demo 2 which caused crashing on 486 machines was also\r
+ fixed. (The speed of the 486 resulted in 0 time delay which inturn\r
+ caused a division by zero error)\r
+\r
+28-12-92 Modified PEL panning code to be smoother on snail paced PC's\r
+ Added quick & dirty planar bitmap compiler\r
+\r
+\r
+15-2-93 Converted text module to allow variable width user fonts\r
+\r
+ Added a function x_get_char_width in module xtext\r
+ Added fonts var6x8.fnt varswisl.fnt varswisb.fnt\r
+ Clened up virt screen start address setting code in xmain.asm\r
+\r
+ Added demo 8 to preview user defined fonts\r
+\r
+ Added x_wait_vsync in module xmain\r
+\r
+ Fixed a bug with mode sets on some VGA bios'es that dont\r
+ preserve CX on an int 10h\r
+\r
+18-8-93 XLIB05 Final Release\r
+ -----------------------------------------------\r
+\r
+ GENERAL:\r
+ Added C++ compatability in header files\r
+ Added new fonts \r
+ XDETECT: now can differentiate between 386sx 386dx and 486\r
+ (486sx can be verified by absence of FPU)\r
+ XMOUSE:\r
+ Fixed x_mouse_position bug and general xmouse improvements\r
+ Added x_mouse_window function\r
+ XFILEIO:\r
+ Modified f_read and f_write functions xfileio module\r
+ f_read - now reads into near buffer reguardless of model\r
+ f_readfar " " " far " " " "\r
+ f_write " writes " near " " " "\r
+ f_writefar " " " far " " " "\r
+ Added f_tell function to get file position. I beleive I\r
+ improved the error handling a little but I cant remember\r
+ for sure.\r
+ XMAIN:\r
+ Added 2 new resolutions 256x200 & 256x240.\r
+ I dont know why you'd want them but theyre there if you do.\r
+ These came from Draeden of VLA (Did you write them Ben ?)\r
+ I think they may have originally been posted on R.G.P ???\r
+ XRECT:\r
+ Added x_rect_fill_clipped & x_rect_pattern_clipped, probably\r
+ useless but what the heck!\r
+ XPOLYGON:\r
+ New function x_triangle - a fast clipped and filled trinagle\r
+ function ideal for 3D work.\r
+ x_polygon - a clipped and filled polygon function (convex\r
+ polygons only). This one's not the fastest - it splits\r
+ polygons into component triangles and uses the above\r
+ triangle routine to draw them, but still it should\r
+ perform fast enough for most 3D applications.\r
+ MISCELLANEOUS:\r
+ xdiscuss.zip: Included Robert Schmidt's excellent mode X article\r
+ for those interested in the hows and why's of Mode X progamming\r
+ xlibtl02.zip: Some bitmap conversion code and a TSR bitmap\r
+ capture program.\r
+\r
+\r
+ Aknowledgements\r
+ ---------------\r
+ Gerald Dalley - For getting me off my butt and doing\r
+ this release.\r
+\r
+ Steve Dollins - Never returned my mail asking for\r
+ permission to use his code so I\r
+ assumed it'd be OK ;)\r
+\r
+ Christian Harms - For suggesting xdetect improvements and\r
+ promising to make XLIB for T.P. freeware\r
+ when its complete. good on ya mate!\r
+\r
+ Jason Truong - For spotting the bug in xmouse and\r
+ general suggestions for improvements\r
+\r
+ Chris Kirby - For suggestion to make .h files C++\r
+ compliant\r
+\r
+ Robert Scmidt - For his mode X article.\r
+\r
+ jeremi@ee.ualberta.ca - Thanks for the xtext suggestions\r
+ (name unknown) even if they didnt make this release\r
+\r
+ And others whom I may have forgotten.\r
+\r
+ Also Greetings to my internet pals,\r
+ Mat Mackenzie, Jari Karjala, Draeden, Victor Putz,\r
+ Josh Jensen, Chicken and the rest of you dudes...\r
+ Thanks for helping my productivity live up to\r
+ "Public Servant" standards ;-))\r
+\r
+5-10-93\r
+ -----------------------------------------------\r
+ XCBITM32:\r
+ 32 bit compiled bitmaps, originally developed by Matthew\r
+ Mackenzie for our game. NOTE: The compiler is written in C -\r
+ conversion to assembler is left as an excersise for the user :-)\r
+ \r
+ XMOUSE: Finished x_mouse_window this time. I had overlooked\r
+ its semi-completed x_mouse_window function in the last release.\r
+\r
+ XPBITMAP:\r
+ Added x_flip_pbm and x_flip_masked_pbm\r
+ Identical to x_put_pbm and x_put_masked_pbm but have an\r
+ extra parameter which indicates whether the bitmap is flipped\r
+ from left to right as drawn or not - Ideal for saving bitmap\r
+ memory.\r
+\r
+ XFILL:\r
+ Added a new module containing 2 flood fill variants. Both return\r
+ the number of pixels filled.\r
+\r
+ XVSYNC:\r
+ New module to synchronise timer 0 to the vertical retrace. This\r
+ allows for smoother animation due to the elimination of\r
+ unnecessary vsync waiting.\r
+\r
+ XMAIN:\r
+ Modifications to allow standard vsync polling or optional\r
+ timer0/vsync synchronization and new support for tripple\r
+ buffering for super-smooth animation. This stuff's way cool!\r
+\r
+ BUGS:\r
+ fixed the odd bug here and there - nothing too serious.\r
+\r
+\r
+ Aknowledgements:\r
+\r
+ Tiaan A Geldenhuys - for pointing out that I forgot to finish\r
+ some code in xmouse.asm, for the new cursor shape and stuff.\r
+\r
+ Thanks to Tore Jahn Bastiansen (toreba@ifi.uio.no) for the\r
+ tripple buffering extensions to XMAIN and the excellent\r
+ Timer vsync sunchronization which is the highlight of this\r
+ release. This module is a "MUST HAVE" if youre going to do\r
+ any animation.\r
+\r
+ Also thanks to any others, whom I may have lost track of,\r
+ for bug fixes'n stuff.\r
+\r
+ Apologies to the person who sent me the pbm flipping code.\r
--- /dev/null
+\r
+;-----------------------------------------------------------------------\r
+; MODULE XBEZIER\r
+;\r
+;\r
+; Compile with TASM.\r
+; C near-callable.\r
+;\r
+; This module was written by Matthew MacKenzie\r
+; matm@eng.umd.edu\r
+;-----------------------------------------------------------------------\r
+include xlib.inc\r
+include xbezier.inc\r
+\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; _x_bezier\r
+;\r
+; Plot a Bezier curve, which is described by a box of two endpoints\r
+; and two control points:\r
+; C1--------C2\r
+; / \\r
+; / \\r
+; E1..............E2\r
+;\r
+; All coordinates must be in the range -1024 to 3071.\r
+; No clipping is performed.\r
+;\r
+; C near-callable as:\r
+; x_bezier (int E1x, int E1y, int C1x, int C1y, int C2x, int C2y,\r
+; int E2x, int E2y, int levels, char color,\r
+; unsigned int PageOffset);\r
+;\r
+; All four main registers are totaled.\r
+; This function may use as many as 162 bytes of stack space.\r
+\r
+; Bezier curves need 32-bit precision, so we'll define macros and\r
+; constants for operations on 32-bit virtual registers V0, V1, and V2.\r
+; V0 is made up of DI and AX, V1 of SI and BX, and V2 of CX and DX.\r
+\r
+LowWord equ 0\r
+HighWord equ 2\r
+\r
+; to load data --\r
+\r
+LoadV0 macro loc, field\r
+ mov ax, word ptr [bp + loc + field + LowWord]\r
+ mov di, word ptr [bp + loc + field + HighWord]\r
+ endm\r
+\r
+LoadV1 macro loc, field\r
+ mov bx, word ptr [bp + loc + field + LowWord]\r
+ mov si, word ptr [bp + loc + field + HighWord]\r
+ endm\r
+\r
+LoadV2 macro loc, field\r
+ mov dx, word ptr [bp + loc + field + LowWord]\r
+ mov cx, word ptr [bp + loc + field + HighWord]\r
+ endm\r
+\r
+; to store data --\r
+\r
+StoreV0 macro loc, field\r
+ mov word ptr [bp + loc + field + LowWord], ax\r
+ mov word ptr [bp + loc + field + HighWord], di\r
+ endm\r
+\r
+StoreV1 macro loc, field\r
+ mov word ptr [bp + loc + field + LowWord], bx\r
+ mov word ptr [bp + loc + field + HighWord], si\r
+ endm\r
+\r
+\r
+; to take the average of two registers (result is in first register) --\r
+\r
+AverageV0nV1 macro\r
+ add ax, bx\r
+ adc di, si\r
+ shr di, 1\r
+ rcr ax, 1\r
+ endm\r
+\r
+AverageV0nV2 macro\r
+ add ax, dx\r
+ adc di, cx\r
+ shr di, 1\r
+ rcr ax, 1\r
+ endm\r
+\r
+AverageV1nV2 macro\r
+ add bx, dx\r
+ adc si, cx\r
+ shr si, 1\r
+ rcr bx, 1\r
+ endm\r
+\r
+\r
+; to take the average of a register and data --\r
+\r
+AverageV1nData macro loc, field\r
+ add bx, word ptr [bp + loc + field + LowWord]\r
+ adc si, word ptr [bp + loc + field + HighWord]\r
+ shr si, 1\r
+ rcr bx, 1\r
+ endm\r
+\r
+AverageV2nData macro loc, field\r
+ add dx, word ptr [bp + loc + field + LowWord]\r
+ adc cx, word ptr [bp + loc + field + HighWord]\r
+ shr cx, 1\r
+ rcr dx, 1\r
+ endm\r
+\r
+\r
+; to turn a 32-bit fixed point data into a regular integer --\r
+\r
+Extract macro reg, source, field\r
+ mov reg, word ptr [bp + source + field + HighWord]\r
+ shr reg, 3\r
+ adc reg, 0 ; round\r
+ endm\r
+\r
+\r
+; to turn an integer argument into a 32-bit fixed point number\r
+; and store it as local data --\r
+\r
+Convert macro source, dest, field\r
+ mov ax, source\r
+ add ax, 1024\r
+ shl ax, 3\r
+ push ax\r
+ push 0\r
+ endm\r
+\r
+\r
+; useful numbers for dealing with Bezier boxes (sets of four points) --\r
+\r
+XCoord equ 4\r
+YCoord equ 0\r
+\r
+; stack offsets for splitting boxes\r
+E1Src equ 48\r
+C1Src equ 40\r
+C2Src equ 32\r
+E2Src equ 24\r
+\r
+E1Dest equ 48\r
+P1Dest equ 40\r
+P4Dest equ 32\r
+P6Dest equ 24\r
+P5Dest equ 16\r
+P2Dest equ 8\r
+E2Dest equ 0\r
+\r
+; stack offsets for drawing boxes\r
+E1Draw equ 24\r
+C1Draw equ 16\r
+C2Draw equ 8\r
+E2Draw equ 0\r
+\r
+ .data\r
+\r
+ align 2\r
+\r
+; depth of recursion at which to plot\r
+WhenToDraw label byte\r
+ db 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4\r
+ db 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5\r
+\r
+\r
+; since we'll be moving bp and sp in our recursion,\r
+; we need to put local storage in the data segment\r
+level dw (?)\r
+gencount dw (?)\r
+AdjustedOffs dw (?)\r
+p1xt dw (?)\r
+p1yt dw (?)\r
+p2xt dw (?)\r
+p2yt dw (?)\r
+p4xt dw (?)\r
+p4yt dw (?)\r
+p5xt dw (?)\r
+p5yt dw (?)\r
+c1xt dw (?)\r
+c1yt dw (?)\r
+c2xt dw (?)\r
+c2yt dw (?)\r
+xdiff dw (?)\r
+ydiff dw (?)\r
+moveline dw (?)\r
+stepper dw (?)\r
+bptemp dw (?)\r
+\r
+; by the same token we need a copy of this argument\r
+Colort dw (?)\r
+\r
+\r
+ColumnMasks label byte\r
+ db 011h, 022h, 044h, 088h\r
+\r
+ .code\r
+\r
+ align 2\r
+_x_bezier proc\r
+ARG E1x, E1y, C1x, C1y, C2x, C2y, E2x, E2y, Levels, Color, PageOffs:word\r
+\r
+ push bp\r
+ mov bp, sp ; caller's stack frame\r
+ push si\r
+ push di\r
+ push es\r
+\r
+ ; set local variables\r
+ mov ax, -1024 ; 1024 rows\r
+ imul [_ScrnLogicalByteWidth]\r
+ add ax, PageOffs\r
+ sub ax, 256 ; 1024 columns\r
+ mov AdjustedOffs, ax ; subtract 1024 rows and 1024 columns\r
+\r
+; copy color into data segment so we can change bp & sp\r
+ mov ax, Color\r
+ mov Colort, ax\r
+\r
+ mov cx, Levels\r
+ dec cx ; gencount (number of boxes we will actually plot) =\r
+ mov ax,1 ; 2^(Levels - 1)\r
+ shl ax,cl\r
+ dec ax\r
+ mov gencount, ax\r
+\r
+ mov [level], 0 ; variable to tell us where we are in the stack\r
+ mov bptemp, bp ; when the dust settles at the end\r
+\r
+; translate coordinates for adjusted offset, convert 'em to fixed-point\r
+; with 13 bits for the integer part and 19 for the fractional part,\r
+; and push them onto the stack in the right order to for a Bezier box\r
+\r
+ Convert E2x\r
+ Convert E2y\r
+\r
+ Convert C2x\r
+ Convert C2y\r
+\r
+ Convert C1x\r
+ Convert C1y\r
+\r
+ Convert E1x\r
+ Convert E1y\r
+\r
+ mov bp, sp ; we are using them as basically one pointer\r
+\r
+ mov ax, 0a000h ; point extra segment to VGA memory\r
+ mov es, ax\r
+\r
+ mov dx, SC_INDEX\r
+ mov al, MAP_MASK\r
+ out dx, al\r
+\r
+MainLoop:\r
+ mov si, gencount\r
+ mov ax, 0\r
+ mov al, WhenToDraw[si]\r
+ cmp ax, level ; are we at a terminal curve?\r
+ jne Recurse\r
+ jmp PlotCurve\r
+\r
+Recurse:\r
+; not at a terminal -- so expand this curve into two more and recurse\r
+\r
+; start with:\r
+; C1___C2\r
+; | |\r
+; E1...E2\r
+;\r
+; stack looks like: E1 C1 C2 E2\r
+\r
+; expand like this:\r
+; C1.....P3.....C2\r
+; . . . .\r
+; . _P4_P6__P5_ .\r
+; P1- .. .. P2\r
+; | .. .. |\r
+; |.. ..|\r
+; E1............E2\r
+;\r
+; stack looks like: E1 P1 P4 P6 P5 P2 E2\r
+; Since P6 is part of both new boxes, we use it twice.\r
+\r
+ sub sp, 24\r
+ sub bp, 24\r
+\r
+; new points for X --\r
+ LoadV0 E1Src, XCoord\r
+ LoadV1 E2Src, XCoord\r
+ StoreV1 E2Dest, XCoord\r
+ LoadV2 C1Src, XCoord\r
+ AverageV0nV2\r
+ StoreV0 P1Dest, XCoord\r
+ AverageV1nData C2Src, XCoord\r
+ StoreV1 P2Dest, XCoord\r
+ AverageV2nData C2Src, XCoord\r
+ AverageV0nV2\r
+ StoreV0 P4Dest, XCoord\r
+ AverageV1nV2\r
+ StoreV1 P5Dest, XCoord\r
+ AverageV0nV1\r
+ StoreV0 P6Dest, XCoord\r
+\r
+; same thing for Y --\r
+ LoadV0 E1Src, YCoord\r
+ LoadV1 E2Src, YCoord\r
+ StoreV1 E2Dest, YCoord\r
+ LoadV2 C1Src, YCoord\r
+ AverageV0nV2\r
+ StoreV0 P1Dest, YCoord\r
+ AverageV1nData C2Src, YCoord\r
+ StoreV1 P2Dest, YCoord\r
+ AverageV2nData C2Src, YCoord\r
+ AverageV0nV2\r
+ StoreV0 P4Dest, YCoord\r
+ AverageV1nV2\r
+ StoreV1 P5Dest, YCoord\r
+ AverageV0nV1\r
+ StoreV0 P6Dest, YCoord\r
+\r
+ inc level ; one level further into stack\r
+ jmp MainLoop\r
+\r
+PlotCurve:\r
+; pull 16-bit coordinates back out of 32-bit fixed-point coordinates;\r
+; integer part is highest 13 bits\r
+\r
+ Extract cx, C1Draw, XCoord\r
+ Extract di, E1Draw, XCoord\r
+ mov c1xt, cx\r
+ add cx, di\r
+ shr cx, 1\r
+ mov p1xt, cx\r
+\r
+ Extract ax, C1Draw, YCoord\r
+ Extract si, E1Draw, YCoord\r
+ mov c1yt, ax\r
+ add ax, si\r
+ shr ax, 1\r
+ mov p1yt, ax\r
+ call ShortLine ; line from P1 to E1\r
+\r
+ Extract cx, E2Draw, XCoord\r
+ Extract di, C2Draw, XCoord\r
+ mov c2xt, di\r
+ add di, cx\r
+ shr di, 1\r
+ mov p2xt, di\r
+\r
+ Extract ax, E2Draw, YCoord\r
+ Extract si, C2Draw, YCoord\r
+ mov c2yt, si\r
+ add si, ax\r
+ shr si, 1\r
+ mov p2yt, si\r
+ call ShortLine ; line from E2 to P2\r
+\r
+; P3 is not in any line we draw, so we'll use it now to find both P5\r
+; for the line after this on, and P4 for this line, then discard it --\r
+ mov bx, c1xt\r
+ add bx, c2xt\r
+ shr bx, 1\r
+ mov dx, c1yt\r
+ add dx, c2yt\r
+ shr dx, 1\r
+\r
+; find P5 x and save for later lines\r
+ mov cx, p2xt\r
+ add cx, bx\r
+ shr cx, 1\r
+ mov p5xt, cx\r
+; find P4 x for this line\r
+ mov cx, p1xt\r
+ add cx, bx\r
+ shr cx, 1\r
+ mov p4xt, cx\r
+ mov di, p1xt\r
+\r
+; find P5 y and save for later lines\r
+ mov ax, p2yt\r
+ add ax, dx\r
+ shr ax, 1\r
+ mov p5yt, ax\r
+; find P4 y for this line\r
+ mov ax, p1yt\r
+ add ax, dx\r
+ shr ax, 1\r
+ mov p4yt, ax\r
+ mov si, p1yt\r
+ call ShortLine ; line from P4 to P1 -- finally!\r
+\r
+; we've already done all the work for these last two --\r
+ mov cx, p2xt\r
+ mov di, p5xt\r
+ mov ax, p2yt\r
+ mov si, p5yt\r
+ call ShortLine ; line from P2 to P5\r
+\r
+ mov cx, p5xt\r
+ mov di, p4xt\r
+ mov ax, p5yt\r
+ mov si, p4yt\r
+ call ShortLine ; line from P5 to P4\r
+\r
+; we've drawn our five lines; this bezier box\r
+; can be dropped off the stack\r
+ add bp, 24\r
+ add sp, 24\r
+\r
+ dec gencount\r
+ mov cx, gencount\r
+ cmp cx, -1\r
+\r
+ je WrapUp ; if we've generated all the terminal nodes we\r
+ ; are supposed to, we pack our bags and go.\r
+ dec level\r
+ jmp MainLoop\r
+\r
+WrapUp:\r
+; plot the final point, which is simply the original E1\r
+\r
+ mov bp, bptemp ; back where we started\r
+ mov ax, E1y\r
+ add ax, 1024\r
+ mul [_ScrnLogicalByteWidth]\r
+ mov di, E1x\r
+ add di, 1024\r
+ mov si, di\r
+ shr di, 2\r
+ add di, ax\r
+ add di, AdjustedOffs\r
+ and si, 3\r
+ mov al, ColumnMasks[si]\r
+ mov ah, byte ptr Color\r
+ mov dx, SC_INDEX + 1\r
+ out dx, al\r
+ mov es:[di], ah\r
+\r
+ pop es\r
+ pop di\r
+ pop si\r
+ mov sp, bp\r
+ pop bp\r
+ ret ; git\r
+\r
+; ShortLine subfunction --\r
+;\r
+; This is designed for short line segments. For longer lines,\r
+; especially horizontal ones, the x_line routine in the XLINE module\r
+; would be faster. But calling that from here it would be a lot of\r
+; extra complication. This is part of the x_bezier routine because\r
+; it has no particular outside use, and we can call it much faster\r
+; through registers than through the stack.\r
+;\r
+; Since our line segments overlap, the second endpoint is not drawn.\r
+; These routines are all out of order for the sake of conditional jumps.\r
+\r
+LRHorz:\r
+ dec di\r
+LRHorzLoop:\r
+ rol al, 1\r
+ adc bx, 0\r
+ out dx, al\r
+ mov es:[bx], ah\r
+ sub di, 1\r
+ jg LRHorzLoop\r
+ retn\r
+\r
+; You are in a maze of little subroutines, all alike...\r
+\r
+\r
+LR45Deg:\r
+ dec si\r
+LR45DegLoop:\r
+ add bx, cx\r
+ rol al, 1\r
+ adc bx, 0\r
+ out dx, al\r
+ mov es:[bx], ah\r
+ sub si, 1\r
+ jg LR45DegLoop\r
+ retn\r
+\r
+\r
+LRXMajor:\r
+ mov cx, di\r
+ dec cx\r
+ shr di, 1\r
+LRXMajorLoop:\r
+ sub di, si\r
+ jge LRXMajorIterate\r
+ add di, xdiff\r
+ add bx, moveline\r
+LRXMajorIterate:\r
+ rol al, 1\r
+ adc bx, 0\r
+ out dx, al\r
+ mov es:[bx], ah\r
+ sub cx, 1\r
+ jg LRXMajorLoop\r
+ retn\r
+\r
+\r
+LeftToRight:\r
+ mov xdiff, di ; store distance across line\r
+\r
+ mov cx, [_ScrnLogicalByteWidth]\r
+ cmp si, 0 ; check if height is positive, negative, or zero\r
+ je LRHorz\r
+ jg LRTopToBottom\r
+ neg si\r
+ neg cx\r
+LRTopToBottom:\r
+ mov ydiff, si\r
+ mov moveline, cx\r
+ cmp di, si\r
+ jg LRXMajor\r
+ je LR45Deg\r
+\r
+\r
+LRYMajor:\r
+ mov cx, si\r
+ dec cx\r
+ shr si, 1\r
+LRYMajorLoop:\r
+ add bx, moveline\r
+ sub si, di\r
+ jge LRYMajorIterate\r
+ add si, ydiff\r
+ rol al, 1\r
+ adc bx, 0\r
+LRYMajorIterate:\r
+ out dx, al\r
+ mov es:[bx], ah\r
+ sub cx, 1\r
+ jg LRYMajorLoop\r
+ retn\r
+\r
+\r
+; This is the actual starting point.\r
+; On entry, registers look like this:\r
+; X1: cx\r
+; Y1: ax\r
+; X2: di\r
+; Y2: si\r
+ShortLine:\r
+ sub si, ax ; height goes out in si\r
+ sub di, cx ; width goes out in di\r
+\r
+ mul [_ScrnLogicalByteWidth]\r
+ mov dx, cx\r
+ shr dx, 2\r
+ add ax, dx\r
+ add ax, AdjustedOffs\r
+ mov bx, ax ; starting byte of X1, Y1 goes out in bx\r
+ and cx, 3\r
+ mov ax, 011h\r
+ shl al, cl ; column mask goes out in al\r
+ mov dx, SC_INDEX + 1\r
+ mov ah, byte ptr Colort; color goes out in ah\r
+ out dx, al\r
+ mov es:[bx], ah ; plot first point\r
+\r
+ cmp di, 0\r
+\r
+ jg LeftToRight\r
+ je VerticalLine\r
+\r
+\r
+RightToLeft:\r
+ neg di ; much more useful this way\r
+ mov xdiff, di\r
+\r
+ mov cx, [_ScrnLogicalByteWidth]\r
+ cmp si, 0 ; check if height is positive, negative, or zero\r
+ je RLHorz\r
+ jg RLTopToBottom\r
+ neg si\r
+ neg cx\r
+RLTopToBottom:\r
+ mov ydiff, si\r
+ mov moveline, cx\r
+ cmp di, si\r
+ jg RLXMajor\r
+ je RL45Deg\r
+\r
+\r
+RLYMajor:\r
+ mov cx, si\r
+ dec cx\r
+ shr si, 1\r
+RLYMajorLoop:\r
+ add bx, moveline\r
+ sub si, di\r
+ jge RLYMajorIterate\r
+ add si, ydiff\r
+ ror al, 1\r
+ sbb bx, 0\r
+RLYMajorIterate:\r
+ out dx, al\r
+ mov es:[bx], ah\r
+ sub cx, 1\r
+ jg RLYMajorLoop\r
+ retn\r
+\r
+\r
+VerticalLine:\r
+ mov cx, [_ScrnLogicalByteWidth]\r
+ cmp si, 0 ; check if height is positive\r
+ jg VTopToBottom\r
+ neg si\r
+ neg cx\r
+VTopToBottom:\r
+ dec si\r
+VLoop:\r
+ add bx, cx\r
+ mov es:[bx], ah\r
+ sub si, 1\r
+ jg VLoop\r
+ retn\r
+\r
+\r
+RLHorz:\r
+ dec di\r
+RLHorzLoop:\r
+ ror al, 1\r
+ sbb bx, 0\r
+ out dx, al\r
+ mov es:[bx], ah\r
+ sub di, 1\r
+ jg RLHorzLoop\r
+ retn\r
+\r
+\r
+RL45Deg:\r
+ dec si\r
+RL45DegLoop:\r
+ add bx, cx\r
+ ror al, 1\r
+ sbb bx, 0\r
+ out dx, al\r
+ mov es:[bx], ah\r
+ sub si, 1\r
+ jg RL45DegLoop\r
+ retn\r
+\r
+\r
+RLXMajor:\r
+ mov cx, di\r
+ dec cx\r
+ shr di, 1\r
+RLXMajorLoop:\r
+ sub di, si\r
+ jge RLXMajorIterate\r
+ add di, xdiff\r
+ add bx, moveline\r
+RLXMajorIterate:\r
+ ror al, 1\r
+ sbb bx, 0\r
+ out dx, al\r
+ mov es:[bx], ah\r
+ sub cx,1\r
+ jg RLXMajorLoop\r
+ retn\r
+\r
+\r
+_x_bezier endp\r
+\r
+ end\r
+\r
--- /dev/null
+/*********************************************************************\\r
+| XBEZIER header file\r
+|\r
+|\r
+| This module was written by Matthew MacKenzie\r
+| matm@eng.umd.edu\r
+\*********************************************************************/\r
+\r
+#ifndef _XBEZIER_H_\r
+#define _XBEZIER_H_\r
+#ifdef __cplusplus\r
+\r
+extern "C" {\r
+#endif\r
+\r
+void x_bezier (int E1x, int E1y, int C1x, int C1y, int C2x, int C2y,\r
+ int E2x, int E2y, int levels, char color,\r
+ unsigned PageOffset);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+; XBEZIER include file\r
+;\r
+;\r
+; This module was written by Matthew MacKenzie\r
+; matm@eng.umd.edu\r
+;-----------------------------------------------------------------------\r
+\r
+global _x_bezier : proc\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XBMTOOLS\r
+;\r
+; Bitmap conversion / manipulation tools\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+COMMENT $\r
+\r
+ This module implements a set of functions to manipulate both planar\r
+ bitmaps and linear bitmaps (as used by x_compile_bitmap):\r
+\r
+ PLANAR BITMAPS\r
+\r
+ Planar bitmaps as used by these functions have the following structure:\r
+\r
+ BYTE 0 The bitmap width in bytes (4 pixel groups) range 1..255\r
+ BYTE 1 The bitmap height in rows range 1..255\r
+ BYTE 2..n1 The plane 0 pixels width*height bytes\r
+ BYTE n1..n2 The plane 1 pixels width*height bytes\r
+ BYTE n2..n3 The plane 2 pixels width*height bytes\r
+ BYTE n3..n4 The plane 3 pixels width*height bytes\r
+\r
+ LINEAR BITMAPS\r
+\r
+ Linear bitmaps have the following structure:\r
+\r
+ BYTE 0 The bitmap width in pixels range 1..255\r
+ BYTE 1 The bitmap height in rows range 1..255\r
+ BYTE 2..n The width*height bytes of the bitmap\r
+\r
+\r
+\r
+$\r
+\r
+LOCALS\r
+.286\r
+\r
+include model.inc\r
+include xbmtools.inc\r
+\r
+ .code\r
+\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; x_pbm_to_bm\r
+;\r
+; This function converts a bitmap in the planar format to the linear format\r
+; as used by x_compile_bitmap.\r
+;\r
+; WARNING: the source and destination bitmaps must be pre - allocated\r
+;\r
+; NOTE: This function can only convert planar bitmaps that are suitable.\r
+; If the source planar bitmap's width (per plane) is >= 256/4\r
+; it cannot be converted. In this situation an error code\r
+; BM_WIDTH_ERROR. On successful conversion 0 is returned.\r
+;\r
+; C callable as:\r
+; int x_pbm_to_bm(char far * source_pbm, char far * dest_bm);\r
+;\r
+; Written By Themie Gouthas\r
+\r
+proc _x_pbm_to_bm\r
+ARG src_pbm:dword,dest_bm:dword\r
+ push bp ; Preserve caller's stack frame\r
+ mov bp,sp\r
+ push ds\r
+ push di\r
+ push si\r
+\r
+ les di,[dest_bm] ; es:di -> destination bitmap\r
+ lds si,[src_pbm] ; ds:si -> source planar bitmap\r
+ lodsb ; load AL with source pbm pixel width per plane\r
+ mov bl,al ; save in CL\r
+ xor ah,ah ; convert to word\r
+ shl ax,2 ; mult by 4 giving source image width\r
+ cmp ax,255 ; if the result > 255 then we have exceeded\r
+ ja @@WidthError ; the max width of linear bm.\r
+\r
+ stosb ; write do dest_bm\r
+\r
+ lodsb ; tranfer source pbm height in pixels to\r
+ stosb ; dest_bm\r
+\r
+ xor ah,ah ; convert to word\r
+ mul bl ; AX = AX * BL ie. total no. pixels per plane\r
+ mov dx,di ; save DI, the pointer to the destination bm\r
+ mov bl,3 ; set plane loop counter (BL)\r
+\r
+@@PlaneLoop:\r
+ mov cx,ax ; set CX to total number of pixels per plane\r
+\r
+@@PixelLoop:\r
+ movsb ; transfer pixel\r
+ add di,3 ; increment destination to compensate for plane\r
+ loop @@PixelLoop\r
+\r
+ inc dx ; increment original di for next pixel plane\r
+ mov di,dx ; and restore di from incremented original\r
+ dec bl ; decrement plane counter\r
+ jns @@PlaneLoop ; loop if more planes left\r
+ xor ax,ax\r
+ jmp short @@Done\r
+@@WidthError:\r
+ mov ax,1\r
+\r
+@@Done:\r
+ pop si\r
+ pop di\r
+ pop ds\r
+ pop bp ;restore caller's stack frame\r
+ ret\r
+_x_pbm_to_bm endp\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; x_bm_to_pbm\r
+;\r
+; This function converts a bitmap in the linear format as used by\r
+; x_compile_bitmap to the planar formap.\r
+;\r
+; WARNING: the source and destination bitmaps must be pre - allocated\r
+;\r
+; NOTE: This function can only convert linear bitmaps that are suitable.\r
+; If the source linear bitmap's width is not a multiple of 4\r
+; it cannot be converted. In this situation an error code\r
+; BM_WIDTH_ERROR. On successful conversion 0 is returned.\r
+;\r
+;\r
+; C callable as:\r
+; int x_bm_to_pbm(char far * source_pbm, char far * dest_bm);\r
+;\r
+; Written By Themie Gouthas\r
+\r
+proc _x_bm_to_pbm\r
+ARG src_bm:dword,dest_pbm:dword\r
+ push bp ; Preserve caller's stack frame\r
+ mov bp,sp\r
+ push ds\r
+ push di\r
+ push si\r
+\r
+ les di,[dest_pbm] ; es:di -> destination planar bitmap\r
+ lds si,[src_bm] ; ds:si -> source bitmap\r
+ lodsb ; load AX with source bitmap width\r
+ test al,03h ; Check that width is a multiple of 4\r
+ jnz @@WidthIncompatible\r
+ shr al,2 ; divide by 4 giving width of plane\r
+ stosb ; store destination planar bitmap width\r
+ mov bl,al ; and copy to bl\r
+ lodsb\r
+ stosb ; Transfer source bitmap height to dest pbm\r
+ xor ah,ah ; Conver height to word\r
+ mul bl ; calculate the total no. of pixels / plane\r
+ mov dx,si ; save source offset\r
+ mov bl,3\r
+\r
+@@PlaneLoop:\r
+ mov cx,ax ; set CX to total number of pixels per plane\r
+\r
+@@PixelLoop:\r
+ movsb ; transfer pixel\r
+ add si,3 ; increment src offset to compensate for plane\r
+ loop @@PixelLoop\r
+\r
+ inc dx ; increment original si for next pixel plane\r
+ mov si,dx ; and restore si from incremented original\r
+ dec bl ; decrement plane counter\r
+ jns @@PlaneLoop ; loop if more planes left\r
+ xor ax,ax\r
+ jmp short @@Done\r
+@@WidthIncompatible:\r
+ mov ax,1\r
+\r
+@@Done:\r
+ pop si\r
+ pop di\r
+ pop ds\r
+ pop bp ;restore caller's stack frame\r
+ ret\r
+_x_bm_to_pbm endp\r
+\r
+\r
+ end\r
+\r
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XPOINT - header file\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; Macros written by Mathew Mackenzie\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;-----------------------------------------------------------------------*/\r
+\r
+#ifndef _XBMTOOLS_H_\r
+#define _XBMTOOLS_H_\r
+\r
+#define BM_WIDTH_ERROR 1\r
+\r
+#define LBMHeight(lbitmap) lbitmap[1]\r
+#define LBMWidth(lbitmap) lbitmap[0]\r
+#define PBMHeight(pbitmap) pbitmap[1]\r
+#define PBMWidth(pbitmap) (pbitmap[0]<<2)\r
+#define PBMByteWidth(pbitmap) pbitmap[0]\r
+\r
+#define LBMPutPix(x,y,lbitmap,color) \\r
+ lbitmap[2 + (x) + (y) * LBMWidth(lbitmap)] = color\r
+\r
+#define LBMGetPix(x,y,lbitmap) \\r
+ (lbitmap[2 + (x) + (y) * LBMWidth(lbitmap)])\r
+\r
+\r
+\r
+/* FUNCTIONS =========================================================== */\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+ int x_pbm_to_bm( /* Convert from planar bitmap to linear */\r
+ char far * source_pbm,\r
+ char far * dest_bm);\r
+\r
+ int x_bm_to_pbm( /* Convert from linear bitmap to planar */\r
+ char far * source_pbm,\r
+ char far * dest_bm);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XBMTOOLS - Include file\r
+;\r
+; XBMTOOLS.ASM export functions\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+ global _x_pbm_to_bm :proc\r
+ global _x_bm_to_pbm :proc\r
+\1a
\ No newline at end of file
--- /dev/null
+#include "xbmtools.h"\r
+\r
+/* these are here instead of the header file because they're not part\r
+ of the library interface */\r
+\r
+// rol al\r
+#define ROL_AL 0xc0d0\r
+// mov [si + disp8], imm8\r
+#define SHORT_STORE_8 0x44c6\r
+// mov [si + disp16], imm8\r
+#define STORE_8 0x84c6\r
+// mov [si + disp8], imm16\r
+#define SHORT_STORE_16 0x44c7\r
+// mov [si + disp16], imm16\r
+#define STORE_16 0x84c7\r
+// adc si, imm8\r
+#define ADC_SI_IMMED 0xd683\r
+// out dx, al\r
+#define OUT_AL 0xee\r
+// ret\r
+#define RETURN 0xcb\r
+// 32-bit prefix\r
+#define DWORD_PREFIX 0x66\r
+\r
+#define Emitb(x) *(output + output_used) = (x); output_used++\r
+\r
+#define Emitw(x) *(output + output_used) = (x) & 255; \\r
+ *(output + output_used + 1) = (x) >> 8; \\r
+ output_used += 2\r
+\r
+\r
+int x_compile_bitmap_32 (int logical_screen_width, char far * bitmap,\r
+ char far * output)\r
+{\r
+ int pix0, pix1, pix2, pix3, numpix, pos;\r
+ int column = 0, set_column = 0;\r
+ int scanx = 0, scany = 0;\r
+ int output_used = 0;\r
+\r
+ int height = LBMHeight(bitmap);\r
+ int width = LBMWidth(bitmap);\r
+ int margin = width - 1;\r
+ int margin2 = margin - 4;\r
+ int margin4 = margin - 12;\r
+\r
+ while (column < 4) {\r
+ numpix = 1;\r
+ pix0 = LBMGetPix(scanx, scany, bitmap);\r
+ if (pix0 != 0) {\r
+ if (set_column != column) {\r
+ do {\r
+ Emitw (ROL_AL);\r
+ Emitw (ADC_SI_IMMED);\r
+ Emitb (0);\r
+ set_column++;\r
+ } while (set_column != column);\r
+ Emitb (OUT_AL);\r
+ }\r
+ if (scanx <= margin2) {\r
+ pix1 = LBMGetPix(scanx + 4, scany, bitmap);\r
+ if ((pix1 != 0)\r
+ &&(scanx <= margin4)) {\r
+ numpix = 2;\r
+ pix2 = LBMGetPix(scanx + 8, scany, bitmap);\r
+ pix3 = LBMGetPix(scanx + 12, scany, bitmap);\r
+ if ((pix2 != 0) && (pix3 != 0)) {\r
+ numpix = 4;\r
+ Emitb (DWORD_PREFIX);\r
+ }\r
+ }\r
+ }\r
+ pos = (scany * logical_screen_width) + (scanx >> 2) - 128;\r
+ if ((pos >= -128) && (pos <= 127)) {\r
+ if (numpix == 1) {\r
+ Emitw (SHORT_STORE_8);\r
+ Emitb (pos);\r
+ Emitb (pix0);\r
+ } else {\r
+ Emitw (SHORT_STORE_16);\r
+ Emitb (pos);\r
+ Emitb (pix0);\r
+ Emitb (pix1);\r
+ if (numpix == 4) {\r
+ Emitb (pix2);\r
+ Emitb (pix3);\r
+ }\r
+ }\r
+ } else {\r
+ if (numpix == 1) {\r
+ Emitw (STORE_8);\r
+ Emitw (pos);\r
+ Emitb (pix0);\r
+ } else {\r
+ Emitw (STORE_16);\r
+ Emitw (pos);\r
+ Emitb (pix0);\r
+ Emitb (pix1);\r
+ if (numpix == 4) {\r
+ Emitb (pix2);\r
+ Emitb (pix3);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ scanx += (numpix << 2);\r
+ if (scanx > margin) {\r
+ scanx = column;\r
+ scany++;\r
+ if (scany == height) {\r
+ scany = 0;\r
+ column++;\r
+ }\r
+ }\r
+ }\r
+ Emitb(RETURN);\r
+ return(output_used);\r
+}\r
+\r
+\r
+int x_sizeof_cbitmap_32 (int logical_screen_width, char far * bitmap)\r
+{\r
+ int pix0, pix1, pix2, pix3, numpix, pos;\r
+ int column = 0, set_column = 0;\r
+ int scanx = 0, scany = 0;\r
+ int output_used = 1;\r
+\r
+ int height = LBMHeight(bitmap);\r
+ int width = LBMWidth(bitmap);\r
+ int margin = width - 1;\r
+ int margin2 = margin - 4;\r
+ int margin4 = margin - 12;\r
+\r
+ while (column < 4) {\r
+ numpix = 1;\r
+ pix0 = LBMGetPix(scanx, scany, bitmap);\r
+ if (pix0 != 0) {\r
+ if (set_column != column) {\r
+ do {\r
+ output_used += 5;\r
+ set_column++;\r
+ } while (set_column != column);\r
+ output_used++;\r
+ }\r
+ if (scanx <= margin2) {\r
+ pix1 = LBMGetPix(scanx + 4, scany, bitmap);\r
+ if ((pix1 != 0)\r
+ &&(scanx <= margin4)) {\r
+ numpix = 2;\r
+ pix2 = LBMGetPix(scanx + 8, scany, bitmap);\r
+ pix3 = LBMGetPix(scanx + 12, scany, bitmap);\r
+ if ((pix2 != 0) && (pix3 != 0)) {\r
+ numpix = 4;\r
+ output_used++;\r
+ }\r
+ }\r
+ }\r
+ pos = (scany * logical_screen_width) + (scanx >> 2) - 128;\r
+ if ((pos >= -128) && (pos <= 127)) {\r
+ if (numpix == 1) {\r
+ output_used += 4;\r
+ } else {\r
+ output_used += 5;\r
+ if (numpix == 4)\r
+ output_used += 2;\r
+ }\r
+ } else {\r
+ if (numpix == 1) {\r
+ output_used += 5;\r
+ } else {\r
+ output_used += 6;\r
+ if (numpix == 4)\r
+ output_used += 2;\r
+ }\r
+ }\r
+ }\r
+ scanx += (numpix << 2);\r
+ if (scanx > margin) {\r
+ scanx = column;\r
+ scany++;\r
+ if (scany == height) {\r
+ scany = 0;\r
+ column++;\r
+ }\r
+ }\r
+ }\r
+ return(output_used);\r
+}\r
+\r
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XCBITM32 - header file\r
+;\r
+; This module was written by Matthew MacKenzie\r
+; matm@eng.umd.edu\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+;----------------------------------------------------------------------*/\r
+/* Notice that there is no function in this module to plot a\r
+ compiled bitmap. Use x_put_cbitmap in module XCBITMAP. */\r
+\r
+/* This module is only for 386+ class computers. */\r
+\r
+#ifndef _XCBITM32_H_\r
+#define _XCBITM32_H_\r
+\r
+extern int x_compile_bitmap_32 ( /* Compile a linear bitmap to generate */\r
+ WORD logical_screen_width, /* machine code to plot it at any */\r
+ char far * bitmap, /* required screen coordinates FAST. */\r
+ char far * output);\r
+\r
+extern int x_sizeof_cbitmap_32 ( /* Find the size of the code which a */\r
+ WORD logical_screen_width, /* bitmap would result in, if it */\r
+ char far * bitmap); /* were compiled (used for allocation). */\r
+\r
+#endif\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XCBITMAP\r
+; This module was written by Matthew MacKenzie\r
+; matm@eng.umd.edu\r
+;\r
+; Compiled bitmap functions all MODE X 256 Color resolutions\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+; ****** Aeronautical Research Laboratory ****************\r
+; ****** Defence Science and Technology Organisation ****************\r
+; ****** Australia ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+include xlib.inc\r
+include xcbitmap.inc\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; _x_compile_bitmap\r
+;\r
+; Compile a linear bitmap to generate machine code to plot it\r
+; at any required screen coordinates FAST. Faster than blits\r
+; using planar bitmaps as in module XPBIITMAP\r
+;\r
+; C near-callable as:\r
+; int x_compile_bitmap (WORD logical_screen_width,\r
+; char far * bitmap, char far * output);\r
+;\r
+; The logical width is in bytes rather than pixels.\r
+;\r
+; All four main registers are totaled.\r
+;\r
+; The source linear bitmaps have the following structure:\r
+;\r
+; BYTE 0 The bitmap width in pixels range 1..255\r
+; BYTE 1 The bitmap height in rows range 1..255\r
+; BYTE 2..n The width*height bytes of the bitmap in\r
+; cloumn row order\r
+;\r
+; The returned value is the size of the compiled bitmap, in bytes.\r
+\r
+\r
+; accessory macros to save typing (what else?)\r
+Emitb macro arg\r
+ mov byte ptr es:[di],&arg&\r
+ inc di\r
+ endm\r
+\r
+Emitw macro arg\r
+ mov word ptr es:[di],&arg&\r
+ add di,2\r
+ endm\r
+\r
+; opcodes emitted by _x_compile_sprite\r
+ROL_AL equ 0c0d0h ; rol al\r
+SHORT_STORE_8 equ 044c6h ; mov [si]+disp8, imm8\r
+STORE_8 equ 084c6h ; mov [si]+disp16, imm8\r
+SHORT_STORE_16 equ 044c7h ; mov [si]+disp8, imm16\r
+STORE_16 equ 084c7h ; mov [si]+disp16, imm16\r
+ADC_SI_IMMED equ 0d683h ; adc si,imm8\r
+OUT_AL equ 0eeh ; out dx,al\r
+RETURN equ 0cbh ; ret\r
+\r
+\r
+.data\r
+\r
+align 2\r
+ColumnMask db 011h,022h,044h,088h\r
+\r
+\r
+.code\r
+\r
+ align 2\r
+_x_compile_bitmap proc\r
+ARG logical_width:word,bitmap:dword,output:dword\r
+LOCAL bwidth,scanx,scany,outputx,outputy,column,set_column,input_size:word=LocalStk\r
+ push bp\r
+ mov bp, sp ; caller's stack frame\r
+ sub sp,LocalStk ; local space\r
+ push si\r
+ push di\r
+ push ds\r
+\r
+ mov word ptr [scanx],0\r
+ mov word ptr [scany],0\r
+ mov word ptr [outputx],0\r
+ mov word ptr [outputy],0\r
+ mov word ptr [column],0\r
+ mov word ptr [set_column],0\r
+\r
+ lds si,[bitmap] ; 32-bit pointer to source bitmap\r
+\r
+ les di,[output] ; 32-bit pointer to destination stream\r
+\r
+ lodsb ; load width byte\r
+ xor ah, ah ; convert to word\r
+ mov [bwidth], ax ; save for future reference\r
+ mov bl, al ; copy width byte to bl\r
+ lodsb ; load height byte -- already a word since ah=0\r
+ mul bl ; mult height word by width byte\r
+ mov [input_size], ax; to get pixel total \r
+\r
+@@MainLoop:\r
+ mov bx, [scanx] ; position in original bitmap\r
+ add bx, [scany]\r
+\r
+ mov al, [si+bx] ; get pixel\r
+ or al, al ; skip empty pixels\r
+ jnz @@NoAdvance\r
+ jmp @@Advance\r
+@@NoAdvance:\r
+\r
+ mov dx, [set_column]\r
+ cmp dx, [column]\r
+ je @@SameColumn\r
+@@ColumnLoop:\r
+ Emitw ROL_AL ; emit code to move to new column\r
+ Emitw ADC_SI_IMMED\r
+ Emitb 0\r
+\r
+ inc dx\r
+ cmp dx, [column]\r
+ jl @@ColumnLoop\r
+\r
+ Emitb OUT_AL ; emit code to set VGA mask for new column\r
+ mov [set_column], dx\r
+@@SameColumn:\r
+ mov dx, [outputy] ; calculate output position\r
+ add dx, [outputx]\r
+ sub dx, 128\r
+\r
+ add word ptr [scanx], 4\r
+ mov cx, [scanx] ; within four pixels of right edge?\r
+ cmp cx, [bwidth]\r
+ jge @@OnePixel\r
+\r
+ inc word ptr [outputx]\r
+ mov ah, [si+bx+4] ; get second pixel\r
+ or ah, ah\r
+ jnz @@TwoPixels\r
+@@OnePixel:\r
+ cmp dx, 127 ; can we use shorter form?\r
+ jg @@OnePixLarge\r
+ cmp dx, -128\r
+ jl @@OnePixLarge\r
+ Emitw SHORT_STORE_8\r
+ Emitb dl ; 8-bit position in output\r
+ jmp @@EmitOnePixel\r
+@@OnePixLarge:\r
+ Emitw STORE_8\r
+ Emitw dx ; position in output\r
+@@EmitOnePixel:\r
+ Emitb al\r
+ jmp short @@Advance\r
+@@TwoPixels:\r
+ cmp dx, 127\r
+ jg @@TwoPixLarge\r
+ cmp dx, -128\r
+ jl @@TwoPixLarge\r
+ Emitw SHORT_STORE_16\r
+ Emitb dl ; 8-bit position in output\r
+ jmp @@EmitTwoPixels\r
+@@TwoPixLarge:\r
+ Emitw STORE_16\r
+ Emitw dx ; position in output\r
+@@EmitTwoPixels:\r
+ Emitw ax\r
+\r
+@@Advance:\r
+ inc word ptr [outputx]\r
+ mov ax, [scanx]\r
+ add ax, 4\r
+ cmp ax, [bwidth]\r
+ jl @@AdvanceDone\r
+ mov dx, [outputy]\r
+ add dx, [logical_width]\r
+ mov cx, [scany]\r
+ add cx, [bwidth]\r
+ cmp cx, [input_size]\r
+ jl @@NoNewColumn\r
+ inc word ptr [column]\r
+ mov cx, [column]\r
+ cmp cx, 4\r
+ je @@Exit ; Column 4: there is no column 4.\r
+ xor cx, cx ; scany and outputy are 0 again for\r
+ mov dx, cx ; the new column\r
+@@NoNewColumn:\r
+ mov [outputy], dx\r
+ mov [scany], cx\r
+ mov word ptr [outputx], 0\r
+ mov ax,[column]\r
+@@AdvanceDone:\r
+ mov [scanx], ax\r
+ jmp @@MainLoop\r
+\r
+@@Exit:\r
+ Emitb RETURN\r
+ mov ax,di\r
+ sub ax,word ptr [output] ; size of generated code\r
+\r
+ pop ds\r
+ pop di\r
+ pop si\r
+ mov sp, bp\r
+ pop bp\r
+\r
+ ret\r
+_x_compile_bitmap endp\r
+\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; _x_sizeof_cbitmap\r
+;\r
+; This function follows the same algorithm as the one above,\r
+; but does not generate a new object. Its sole purpose is to\r
+; determine how much space the compiled bitmap will require.\r
+;\r
+; C near-callable as:\r
+; int x_sizeof_cbitmap (WORD logical_screen_width,\r
+; char far * bitmap);\r
+;\r
+; The logical width is in bytes rather than pixels.\r
+;\r
+; All four main registers are totaled.\r
+;\r
+; The source linear bitmaps have the following structure:\r
+;\r
+; BYTE 0 The bitmap width in pixels range 1..255\r
+; BYTE 1 The bitmap height in rows range 1..255\r
+; BYTE 2..n The width*height bytes of the bitmap in\r
+; cloumn row order\r
+;\r
+; The returned value is the size of the compiled bitmap, in bytes.\r
+\r
+\r
+ align 2\r
+_x_sizeof_cbitmap proc\r
+ARG logical_width:word,bitmap:dword\r
+LOCAL bwidth,scanx,scany,outputx,outputy,column,set_column,input_size:word=LocalStk\r
+ push bp\r
+ mov bp, sp ; caller's stack frame\r
+ sub sp,LocalStk ; local space\r
+ push si\r
+ push di\r
+ push ds\r
+\r
+ mov word ptr [scanx], 0\r
+ mov word ptr [scany], 0\r
+ mov word ptr [outputx], 0\r
+ mov word ptr [outputy], 0\r
+ mov word ptr [column], 0\r
+ mov word ptr [set_column], 0\r
+\r
+ lds si,[bitmap] ; 32-bit pointer to source bitmap\r
+\r
+ mov di, 1 ; initial size is just the size of the far RET\r
+\r
+ lodsb ; load width byte\r
+ xor ah, ah ; convert to word\r
+ mov [bwidth], ax ; save for future reference\r
+ mov bl, al ; copy width byte to bl\r
+ lodsb ; load height byte -- already a word since ah=0\r
+ mul bl ; mult height word by width byte\r
+ mov [input_size], ax; to get pixel total\r
+\r
+@@MainLoop:\r
+ mov bx, [scanx] ; position in original bitmap\r
+ add bx, [scany]\r
+\r
+ mov al, [si+bx] ; get pixel\r
+ or al, al ; skip empty pixels\r
+ jnz @@NoAdvance\r
+ jmp @@Advance\r
+@@NoAdvance:\r
+\r
+ mov dx, [set_column]\r
+ cmp dx, [column]\r
+ je @@SameColumn\r
+@@ColumnLoop:\r
+ add di, 5 ; size of code to move to new column\r
+ inc dx\r
+ cmp dx,[column]\r
+ jl @@ColumnLoop\r
+\r
+ inc di ; size of code to set VGA mask\r
+ mov [set_column], dx\r
+@@SameColumn:\r
+ mov dx, [outputy] ; calculate output position\r
+ add dx, [outputx]\r
+ sub dx, 128\r
+\r
+ add word ptr [scanx], 4\r
+ mov cx, [scanx] ; within four pixels of right edge?\r
+ cmp cx, [bwidth]\r
+ jge @@OnePixel\r
+\r
+ inc word ptr [outputx]\r
+ mov ah,[si+bx+4] ; get second pixel\r
+ or ah, ah\r
+ jnz @@TwoPixels\r
+@@OnePixel:\r
+ cmp dx, 127 ; can we use shorter form?\r
+ jg @@OnePixLarge\r
+ cmp dx, -128\r
+ jl @@OnePixLarge\r
+ add di, 4 ; size of 8-bit position in output plus one pixel\r
+ jmp @@EmitOnePixel\r
+@@OnePixLarge:\r
+ add di, 5 ; size of position in output plus one pixels\r
+@@EmitOnePixel:\r
+ jmp short @@Advance\r
+@@TwoPixels:\r
+ cmp dx, 127\r
+ jg @@TwoPixLarge\r
+ cmp dx, -128\r
+ jl @@TwoPixLarge\r
+ add di, 5 ; size of 8-bit position in output plus two pixels\r
+ jmp @@EmitTwoPixels\r
+@@TwoPixLarge:\r
+ add di, 6 ; size of 16-bit position in output plus two pixels\r
+@@EmitTwoPixels:\r
+\r
+@@Advance:\r
+ inc word ptr [outputx]\r
+ mov ax, [scanx]\r
+ add ax,4\r
+ cmp ax, [bwidth]\r
+ jl @@AdvanceDone\r
+ mov dx, [outputy]\r
+ add dx, [logical_width]\r
+ mov cx, [scany]\r
+ add cx, [bwidth]\r
+ cmp cx, [input_size]\r
+ jl @@NoNewColumn\r
+ inc word ptr [column]\r
+ mov cx, [column]\r
+ cmp cx, 4\r
+ je @@Exit ; Column 4: there is no column 4.\r
+ xor cx,cx ; scany and outputy are 0 again for\r
+ mov dx,cx ; the new column\r
+@@NoNewColumn:\r
+ mov [outputy], dx\r
+ mov [scany], cx\r
+ mov word ptr [outputx], 0\r
+ mov ax,[column]\r
+@@AdvanceDone:\r
+ mov [scanx], ax\r
+ jmp @@MainLoop\r
+\r
+@@Exit:\r
+ mov ax, di ; size of generated code\r
+\r
+ pop ds\r
+ pop di\r
+ pop si\r
+ mov sp,bp\r
+ pop bp\r
+\r
+ ret\r
+_x_sizeof_cbitmap endp\r
+\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; _x_put_cbitmap\r
+;\r
+; Displays a compiled bitmap generated by x_compile_bitmap at given\r
+; coordinates, on a given screen page.\r
+;\r
+; C near-callable as:\r
+; void x_put_cbitmap (int XPos, int YPos,\r
+; unsigned int PageOffset, char far * Sprite);\r
+; ax, bx, cx, and dx are squashed like insignificant insects.\r
+\r
+ align 2\r
+_x_put_cbitmap proc\r
+ARG XPos:word,YPos:word,PageOffset:word,Sprite:dword\r
+\r
+ push bp\r
+ mov bp, sp\r
+ push si\r
+ push ds\r
+\r
+ mov ax, [_ScrnLogicalByteWidth] ; global Xlib variable\r
+ mul word ptr [YPos] ; height in bytes\r
+ mov si, [XPos]\r
+ mov bx, si\r
+ sar si, 2 ; width in bytes\r
+ add si, ax\r
+ add si, [PageOffset]; (YPos * screen width) +\r
+ add si, 128 ; (Xpos / 4) + page base + 128 ==> starting pos\r
+\r
+ and bx, 3\r
+ mov ah, ColumnMask[bx]\r
+\r
+ mov dx, SC_INDEX\r
+ mov al, MAP_MASK\r
+ out dx, ax\r
+ inc dx ; ready to send out other masks as bytes\r
+ mov al, ah\r
+\r
+ mov bx, SCREEN_SEG\r
+ mov ds, bx ; We do this so the compiled shape won't need\r
+ ; segment overrides.\r
+\r
+ call dword ptr [Sprite] ; the business end of the routine\r
+\r
+ pop ds\r
+ pop si\r
+ pop bp\r
+\r
+ ret\r
+_x_put_cbitmap endp\r
+\r
+end\r
+\r
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XCBITMAP - header file\r
+;\r
+; This module was written by Matthew MacKenzie\r
+; matm@eng.umd.edu\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+;----------------------------------------------------------------------*/\r
+\r
+#ifndef _XCBITMAP_H_\r
+#define _XCBITMAP_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+\r
+\r
+ int x_compile_bitmap ( /* Compile a linear bitmap to generate */\r
+ WORD logical_screen_width, /* machine code to plot it at any */\r
+ char far * bitmap, /* required screen coordinates FAST. */\r
+ char far * output);\r
+\r
+ int x_sizeof_cbitmap ( /* Find the size of the code which a */\r
+ WORD logical_screen_width, /* bitmap would result in, if it */\r
+ char far * bitmap); /* were compiled (used for allocation). */\r
+\r
+ void x_put_cbitmap ( /* Displays a compiled bitmap generated */\r
+ WORD XPos, /* by x_compile_bitmap. */\r
+ WORD YPos,\r
+ WORD PageOffset,\r
+ char far * CompiledBitmap);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+#endif\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XCBITMAP - Include file\r
+; This module was written by Matthew MacKenzie\r
+; matm@eng.umd.edu\r
+;\r
+; XCBITMAP.ASM export functions\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+global _x_compile_bitmap : proc\r
+global _x_sizeof_cbitmap : proc\r
+global _x_put_cbitmap : proc\r
+\r
+\1a
\ No newline at end of file
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; MODULE XCIRCLE\r
+;\r
+; This module was written by Matthew MacKenzie\r
+; matm@eng.umd.edu\r
+;\r
+; Circles, full and empty.\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+include xlib.inc\r
+include xcircle.inc\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; _x_circle\r
+;\r
+; Draw a circle.\r
+;\r
+; C near-callable as:\r
+; int x_circle (WORD Left, WORD Top, WORD Diameter,\r
+; WORD Color, WORD ScreenOffs);\r
+;\r
+; No clipping is performed.\r
+;\r
+; ax, bx, cx, and dx bite the dust, as Homer would say.\r
+\r
+; we plot into eight arcs at once:\r
+; 4 0\r
+; 6 \|/ 2\r
+; --*--\r
+; 7 /|\ 3\r
+; 5 1\r
+;\r
+; 0, 1, 4, and 5 are considered x-major; the rest, y-major.\r
+;\r
+; The x-major plots grow out from the top and bottom of the circle,\r
+; while the y-major plots start at the left and right edges.\r
+\r
+ .data\r
+\r
+ align 2\r
+\r
+ColumnMask db 011h,022h,044h,088h\r
+\r
+ .code\r
+\r
+ public _x_circle\r
+ align 2\r
+_x_circle proc\r
+ARG Left:word, Top:word, Diameter:word, Color:word, ScreenOffs:word\r
+LOCAL offset0,offset1,offset2,offset3,offset4,offset5,offset6,offset7,mask0n1,mask2n3,mask4n5,mask6n7,shrunk_radius,diameter_even,error:word=LocalStk\r
+; Tasm 1.0 does not allow the \ line continuation\r
+;LOCAL offset0:word, offset1:word, offset2:word, offset3:word, \\r
+; offset4:word, offset5:word, offset6:word, offset7:word, \\r
+; mask0n1:word, mask2n3:word, mask4n5:word, mask6n7:word, \\r
+; shrunk_radius:word, diameter_even:word, error:word=LocalStk\r
+\r
+ push bp\r
+ mov bp, sp\r
+ sub sp, LocalStk\r
+ push si\r
+ push di\r
+ push ds\r
+\r
+; find starting locations of plots 2, 3, 6, and 7\r
+ mov di, _ScrnLogicalByteWidth\r
+ xor dx, dx\r
+\r
+ mov ax, Diameter ; find vertical midpoint\r
+ dec ax\r
+ shr ax, 1\r
+ adc dx, 0 ; remember if it's rounded\r
+ mov shrunk_radius, ax ; radius, rounded down for adding\r
+ mov diameter_even, dx ; (diameter - 1) & 1, effectively\r
+ add ax, Top\r
+ mul di ; vertical midpoint in bytes\r
+ add ax, ScreenOffs\r
+\r
+ mov bx, Left\r
+ mov cx, bx ; save for later\r
+ mov si, bx\r
+ shr si, 2\r
+ add si, ax\r
+ mov offset6, si\r
+ and bx, 3 ; column of left side\r
+ mov bl, ColumnMask[bx]\r
+ mov mask6n7, bx\r
+\r
+ add cx, Diameter\r
+ dec cx\r
+ mov bx, cx\r
+ shr cx, 2\r
+ add cx, ax\r
+ mov offset2, cx\r
+ and bx, 3 ; column of right side\r
+ mov bl, ColumnMask[bx]\r
+ mov mask2n3, bx\r
+\r
+ cmp diameter_even, 1\r
+ jne @@MiddlePlotsOverlap\r
+ add si, di\r
+ add cx, di\r
+@@MiddlePlotsOverlap:\r
+ mov offset7, si\r
+ mov offset3, cx\r
+\r
+; starting locations of 0, 1, 4, and 5\r
+ mov bx, Left\r
+ add bx, shrunk_radius ; find horizontal midpoint\r
+\r
+ mov ax, Top ; top in bytes\r
+ mul di\r
+ add ax, ScreenOffs\r
+ mov si, ax\r
+\r
+ mov ax, Diameter ; bottom in bytes\r
+ dec ax\r
+ mul di\r
+ add ax, si\r
+\r
+ mov di, bx ; horizontal midpoint in bytes\r
+ shr di, 2\r
+ add si, di ; top midpoint in bytes\r
+ mov offset4, si\r
+ add di, ax ; bottom midpoint in bytes\r
+ mov offset5, di\r
+ and bx, 3 ; column of horizontal midpoint\r
+ mov bl, ColumnMask[bx]\r
+ mov mask4n5, bx\r
+\r
+ cmp diameter_even, 1\r
+ jne @@TopAndBottomPlotsOverlap\r
+ rol bl, 1\r
+ jnc @@TopAndBottomPlotsOverlap\r
+ inc si\r
+ inc di\r
+@@TopAndBottomPlotsOverlap:\r
+ mov offset0, si\r
+ mov offset1, di\r
+ mov mask0n1, bx\r
+\r
+; we've got our eight plots in their starting positions, so\r
+; it's time to sort out the registers\r
+ mov bx, _ScrnLogicalByteWidth\r
+\r
+ mov dx, SCREEN_SEG\r
+ mov ds, dx\r
+\r
+ mov dx, SC_INDEX ; set VGA to accept column masks\r
+ mov al, MAP_MASK\r
+ out dx, al\r
+ inc dx ; gun the engine...\r
+\r
+ mov si, Diameter ; initial y is radius -- 2 #s per pixel\r
+ inc si\r
+\r
+ mov cx, si\r
+ neg cx\r
+ add cx, 2\r
+ mov error, cx ; error = -y + one pixel since we're a step ahead\r
+\r
+ xor cx, cx ; initial x = 0\r
+ mov ah, byte ptr Color\r
+ jmp @@CircleCalc ; let's actually put something on the screen!\r
+\r
+; move the x-major plots horizontally and the y-major plots vertically\r
+@@NoAdvance:\r
+ mov al, byte ptr mask0n1\r
+ out dx, al\r
+ mov di, offset0 ; plot 0\r
+ mov [di], ah\r
+ rol al, 1 ; advance 0 right\r
+ mov byte ptr mask0n1, al\r
+ adc di, 0\r
+ mov offset0, di\r
+ mov di, offset1\r
+ mov [di], ah ; plot 1\r
+ ror al, 1 ; what was that bit again?\r
+ adc di, 0 ; advance 1 right\r
+ mov offset1, di\r
+\r
+ mov al, byte ptr mask2n3\r
+ out dx, al\r
+ mov di, offset2\r
+ mov [di], ah ; plot 2\r
+ sub di, bx ; advance 2 up\r
+ mov offset2, di\r
+ mov di, offset3\r
+ mov [di], ah ; plot 3\r
+ add di, bx ; advance 3 down\r
+ mov offset3, di\r
+\r
+ mov al, byte ptr mask4n5\r
+ out dx, al\r
+ mov di, offset4\r
+ mov [di], ah\r
+ ror al, 1\r
+ mov byte ptr mask4n5, al\r
+ sbb di, 0\r
+ mov offset4, di\r
+ mov di, offset5\r
+ mov [di], ah\r
+ rol al, 1\r
+ sbb di, 0\r
+ mov offset5, di\r
+\r
+ mov al, byte ptr mask6n7\r
+ out dx, al\r
+ mov di, offset6\r
+ mov [di], ah\r
+ sub di, bx\r
+ mov offset6, di\r
+ mov di, offset7\r
+ mov [di], ah\r
+ add di, bx\r
+ mov offset7, di\r
+\r
+ jmp @@CircleCalc\r
+\r
+; move all plots diagonally\r
+@@Advance:\r
+ mov al, byte ptr mask0n1\r
+ out dx, al\r
+ mov di, offset0\r
+ mov [di], ah ; plot 0\r
+ rol al, 1 ; advance 0 right and down\r
+ mov byte ptr mask0n1, al\r
+ adc di, bx\r
+ mov offset0, di\r
+ mov di, offset1\r
+ mov [di], ah ; plot 1\r
+ ror al, 1 ; what was that bit again?\r
+ adc di, 0 ; advance 1 right and up\r
+ sub di, bx\r
+ mov offset1, di\r
+\r
+ mov al, byte ptr mask2n3\r
+ out dx, al\r
+ mov di, offset2\r
+ mov [di], ah ; plot 2\r
+ ror al, 1 ; advance 2 up and left\r
+ mov byte ptr mask2n3, al\r
+ sbb di, bx\r
+ mov offset2, di\r
+ mov di, offset3\r
+ mov [di], ah ; plot 3\r
+ rol al, 1\r
+ sbb di, 0 ; advance 3 down and left\r
+ add di, bx\r
+ mov offset3, di\r
+\r
+ mov al, byte ptr mask4n5\r
+ out dx, al\r
+ mov di, offset4\r
+ mov [di], ah\r
+ ror al, 1\r
+ mov byte ptr mask4n5, al\r
+ sbb di, 0\r
+ add di, bx\r
+ mov offset4, di\r
+ mov di, offset5\r
+ mov [di], ah\r
+ rol al, 1\r
+ sbb di, bx\r
+ mov offset5, di\r
+\r
+ mov al, byte ptr mask6n7\r
+ out dx, al\r
+ mov di, offset6\r
+ mov [di], ah\r
+ rol al, 1\r
+ mov byte ptr mask6n7, al\r
+ adc di, 0\r
+ sub di, bx\r
+ mov offset6, di\r
+ mov di, offset7\r
+ mov [di], ah\r
+ ror al, 1\r
+ adc di, bx\r
+ mov offset7, di\r
+\r
+; do you realize the entire function has been set up for this little jot?\r
+; keep in mind that radii values are 2 per pixel\r
+@@CircleCalc:\r
+ add cx, 2 ; x += 1\r
+ mov di, error\r
+ add di, cx ; error += (2 * x) + 1\r
+ inc di\r
+ jl @@CircleNoError\r
+ cmp cx, si ; x > y?\r
+ ja @@FleeFlyFlowFum\r
+ sub si, 2 ; y -= 1\r
+ sub di, si ; error -= (2 * y)\r
+ mov error, di\r
+ jmp @@Advance\r
+@@CircleNoError:\r
+ mov error, di\r
+ jmp @@NoAdvance\r
+\r
+@@FleeFlyFlowFum:\r
+ pop ds\r
+ pop di\r
+ pop si\r
+ mov sp,bp\r
+ pop bp\r
+\r
+ ret\r
+\r
+_x_circle endp\r
+\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; _x_filled_circle\r
+;\r
+; Draw a disc.\r
+;\r
+; C near-callable as:\r
+; int x_filled_circle (WORD Left, WORD Top, WORD Diameter,\r
+; WORD Color, WORD ScreenOffs);\r
+;\r
+; No clipping is performed.\r
+;\r
+; ax, bx, cx, dx, and es bite the dust, as Homer would say.\r
+; DF is set to 0 (strings go forward).\r
+\r
+ .data\r
+\r
+ align 2\r
+\r
+; the only entries of these tables which are used are positions\r
+; 1, 2, 4, and 8\r
+LeftMaskTable db 0, 0ffh, 0eeh, 0, 0cch, 0, 0, 0, 088h\r
+RightMaskTable db 0, 011h, 033h, 0, 077h, 0, 0, 0, 0ffh\r
+\r
+ .code\r
+\r
+ public _x_filled_circle\r
+ align 2\r
+_x_filled_circle proc\r
+ARG Left:word, Top:word, Diameter:word, Color:word, ScreenOffs:word\r
+; Tasm 1.0 does not allow the \ line continuation\r
+;LOCAL offset0:word, offset1:word, offset2:word, offset3:word, \\r
+; offset4:word, offset5:word, offset6:word, offset7:word, \\r
+; mask0n1:word, mask2n3:word, mask4n5:word, mask6n7:word, \\r
+; shrunk_radius:word, diameter_even:word, error:word, \\r
+; jump_vector:word=LocalStk\r
+LOCAL offset0,offset1,offset2,offset3,offset4,offset5,offset6,offset7,mask0n1,mask2n3,mask4n5,mask6n7,shrunk_radius,diameter_even,error,jump_vector:word=LocalStk\r
+\r
+ push bp\r
+ mov bp, sp\r
+ sub sp, LocalStk\r
+ push si\r
+ push di\r
+\r
+ cld ; strings march forward\r
+\r
+; this first part is identical to the other function --\r
+; the only differences, in fact, are in the drawing and moving around\r
+\r
+; find starting locations of plots 2, 3, 6, and 7\r
+ mov di, _ScrnLogicalByteWidth\r
+ xor dx, dx\r
+\r
+ mov ax, Diameter ; find vertical midpoint\r
+ dec ax\r
+ shr ax, 1\r
+ adc dx, 0 ; remember if it's rounded\r
+ mov shrunk_radius, ax ; radius, rounded down for adding\r
+ mov diameter_even, dx ; (diameter - 1) & 1, effectively\r
+ add ax, Top\r
+ mul di ; vertical midpoint in bytes\r
+ add ax, ScreenOffs\r
+\r
+ mov bx, Left\r
+ mov cx, bx ; save for later\r
+ mov si, bx\r
+ shr si, 2\r
+ add si, ax\r
+ mov offset6, si\r
+ and bx, 3 ; column of left side\r
+ mov bl, ColumnMask[bx]\r
+ mov mask6n7, bx\r
+\r
+ add cx, Diameter\r
+ dec cx\r
+ mov bx, cx\r
+ shr cx, 2\r
+ add cx, ax\r
+ mov offset2, cx\r
+ and bx, 3 ; column of right side\r
+ mov bl, ColumnMask[bx]\r
+ mov mask2n3, bx\r
+\r
+ cmp diameter_even, 1\r
+ jne @@MiddlePlotsOverlap\r
+ add si, di\r
+ add cx, di\r
+@@MiddlePlotsOverlap:\r
+ mov offset7, si\r
+ mov offset3, cx\r
+\r
+; starting locations of 0, 1, 4, and 5\r
+ mov bx, Left\r
+ add bx, shrunk_radius ; find horizontal midpoint\r
+\r
+ mov ax, Top ; top in bytes\r
+ mul di\r
+ add ax, ScreenOffs\r
+ mov si, ax\r
+\r
+ mov ax, Diameter ; bottom in bytes\r
+ dec ax\r
+ mul di\r
+ add ax, si\r
+\r
+ mov di, bx ; horizontal midpoint in bytes\r
+ shr di, 2\r
+ add si, di ; top midpoint in bytes\r
+ mov offset4, si\r
+ add di, ax ; bottom midpoint in bytes\r
+ mov offset5, di\r
+ and bx, 3 ; column of horizontal midpoint\r
+ mov bl, ColumnMask[bx]\r
+ mov mask4n5, bx\r
+\r
+ cmp diameter_even, 1\r
+ jne @@TopAndBottomPlotsOverlap\r
+ rol bl, 1\r
+ jnc @@TopAndBottomPlotsOverlap\r
+ inc si\r
+ inc di\r
+@@TopAndBottomPlotsOverlap:\r
+ mov offset0, si\r
+ mov offset1, di\r
+ mov mask0n1, bx\r
+\r
+; we've got our eight plots in their starting positions, so\r
+; it's time to sort out the registers\r
+ mov bx, _ScrnLogicalByteWidth\r
+\r
+ mov dx, SCREEN_SEG\r
+ mov es, dx\r
+\r
+ mov dx, SC_INDEX ; set VGA to accept column masks\r
+ mov al, MAP_MASK\r
+ out dx, al\r
+ inc dx ; gun the engine...\r
+\r
+ mov si, Diameter ; initial y is radius -- 2 #s per pixel\r
+ inc si\r
+\r
+ mov cx, si\r
+ neg cx\r
+ add cx, 2\r
+ mov error, cx ; error = -y + one pixel since we're a step ahead\r
+\r
+ xor cx, cx ; initial x = 0\r
+ mov ah, byte ptr Color\r
+ jmp @@FilledCircleCalc ; let's actually put something on the screen!\r
+\r
+\r
+; plotting is completely different from in the other function (naturally)\r
+@@PlotLines:\r
+ push cx ; we'll need cx for string stores\r
+\r
+; draw x-major horz. lines, from plot 4 to plot 0 and from plot 5 to plot 1\r
+ mov di, mask0n1\r
+ and di, 0000fh ; we only want the lower nybble for the mask table\r
+ mov al, RightMaskTable[di]\r
+ mov di, offset0 ; left and right offsets the same?\r
+ cmp di, offset4\r
+ jne @@PlotXMajorNontrivial ; try and say this one 10 times fast!\r
+ mov di, mask4n5\r
+ and di, 0000fh\r
+ and al, LeftMaskTable[di] ; intersection of left & right masks\r
+ out dx, al ; set mask\r
+ mov di, offset4\r
+ mov es:[di], ah\r
+ mov di, offset5\r
+ mov es:[di], ah\r
+ jmp @@PlotYMajor\r
+@@PlotXMajorNontrivial:\r
+ out dx, al ; draw right edge\r
+ mov es:[di], ah\r
+ mov di, offset1\r
+ mov es:[di], ah\r
+\r
+ mov di, mask4n5 ; draw left edge\r
+ and di, 0000fh\r
+ mov al, LeftMaskTable[di]\r
+ out dx, al\r
+ mov di, offset4\r
+ mov es:[di], ah\r
+ mov di, offset5\r
+ mov es:[di], ah\r
+\r
+ mov al, 0ffh ; set mask for middle chunks\r
+ out dx, al\r
+ mov al, ah ; ready to store two pixels at a time\r
+ inc di ; move string start past left edge\r
+ mov cx, offset1 ; store line from plot 5 to plot 1, exclusive\r
+ sub cx, di ; width of section in bytes\r
+ push cx\r
+ shr cx, 1 ; draw midsection eight pixels at a time\r
+ rep stosw\r
+ adc cx, 0 ; draw last four pixels, if such there are\r
+ rep stosb\r
+\r
+ mov di, offset4 ; draw line from plot 4 to plot 0\r
+ inc di ; move past left edge\r
+ pop cx\r
+ shr cx, 1\r
+ rep stosw\r
+ adc cx, 0\r
+ rep stosb\r
+\r
+@@PlotYMajor:\r
+; draw y-major horz. lines, from plot 6 to plot 2 and from plot 7 to plot 3\r
+ mov di, mask2n3\r
+ and di, 0000fh ; we only want the lower nybble for the mask table\r
+ mov al, RightMaskTable[di]\r
+ mov di, offset2 ; left and right offsets the same?\r
+ cmp di, offset6\r
+ jne @@PlotYMajorNontrivial ; try and say this one 10 times fast!\r
+ mov di, mask6n7\r
+ and di, 0000fh\r
+ and al, LeftMaskTable[di] ; intersection of left & right masks\r
+ out dx, al ; set mask\r
+ mov di, offset6\r
+ mov es:[di], ah\r
+ mov di, offset7\r
+ mov es:[di], ah\r
+ jmp @@ClimaxOfPlot\r
+@@PlotYMajorNontrivial:\r
+ out dx, al ; draw right edge\r
+ mov es:[di], ah\r
+ mov di, offset3\r
+ mov es:[di], ah\r
+\r
+ mov di, mask6n7 ; draw left edge\r
+ and di, 0000fh\r
+ mov al, LeftMaskTable[di]\r
+ out dx, al\r
+ mov di, offset6\r
+ mov es:[di], ah\r
+ mov di, offset7\r
+ mov es:[di], ah\r
+\r
+ mov al, 0ffh ; set mask for middle chunks\r
+ out dx, al\r
+ mov al, ah ; ready to store two pixels at a time\r
+\r
+ inc di ; move string start past left edge\r
+ mov cx, offset3 ; draw line from plot 7 to plot 3, exclusive\r
+ sub cx, di ; width of section in bytes\r
+ push cx\r
+ shr cx, 1 ; store midsection\r
+ rep stosw\r
+ adc cx, 0\r
+ rep stosb\r
+\r
+ mov di, offset6 ; draw line from plot 6 to plot 2\r
+ inc di ; move past left edge\r
+ pop cx\r
+ shr cx, 1\r
+ rep stosw\r
+ adc cx, 0\r
+ rep stosb\r
+\r
+@@ClimaxOfPlot:\r
+ pop cx\r
+ jmp [jump_vector] ; either @@Advance or @@NoAdvance\r
+\r
+\r
+; unlike their counterparts in the other function, these do not draw --\r
+; they only move the eight pointers\r
+\r
+; move the x-major plots horizontally and the y-major plots vertically\r
+@@NoAdvance:\r
+ mov al, byte ptr mask0n1 ; advance left x-major plots\r
+ mov di, offset0\r
+ rol al, 1 ; advance 0 right\r
+ mov byte ptr mask0n1, al\r
+ adc di, 0\r
+ mov offset0, di\r
+ mov di, offset1\r
+ ror al, 1 ; what was that bit again?\r
+ adc di, 0 ; advance 1 right\r
+ mov offset1, di\r
+\r
+ mov al, byte ptr mask4n5 ; advance left x-major plots\r
+ mov di, offset4\r
+ ror al, 1\r
+ mov byte ptr mask4n5, al\r
+ sbb di, 0\r
+ mov offset4, di\r
+ mov di, offset5\r
+ rol al, 1\r
+ sbb di, 0\r
+ mov offset5, di\r
+\r
+ mov al, byte ptr mask2n3\r
+ mov di, offset2\r
+ sub di, bx ; advance 2 up\r
+ mov offset2, di\r
+ mov di, offset3\r
+ add di, bx ; advance 3 down\r
+ mov offset3, di\r
+\r
+ mov al, byte ptr mask6n7\r
+ mov di, offset6\r
+ sub di, bx\r
+ mov offset6, di\r
+ mov di, offset7\r
+ add di, bx\r
+ mov offset7, di\r
+\r
+ jmp @@FilledCircleCalc\r
+\r
+; move all plots diagonally\r
+@@Advance:\r
+ mov al, byte ptr mask0n1\r
+ mov di, offset0\r
+ rol al, 1 ; advance 0 right and down\r
+ mov byte ptr mask0n1, al\r
+ adc di, bx\r
+ mov offset0, di\r
+ mov di, offset1\r
+ ror al, 1 ; what was that bit again?\r
+ adc di, 0 ; advance 1 right and up\r
+ sub di, bx\r
+ mov offset1, di\r
+\r
+ mov al, byte ptr mask2n3\r
+ mov di, offset2\r
+ ror al, 1 ; advance 2 up and left\r
+ mov byte ptr mask2n3, al\r
+ sbb di, bx\r
+ mov offset2, di\r
+ mov di, offset3\r
+ rol al, 1\r
+ sbb di, 0 ; advance 3 down and left\r
+ add di, bx\r
+ mov offset3, di\r
+\r
+ mov al, byte ptr mask4n5\r
+ mov di, offset4\r
+ ror al, 1\r
+ mov byte ptr mask4n5, al\r
+ sbb di, 0\r
+ add di, bx\r
+ mov offset4, di\r
+ mov di, offset5\r
+ rol al, 1\r
+ sbb di, bx\r
+ mov offset5, di\r
+\r
+ mov al, byte ptr mask6n7\r
+ mov di, offset6\r
+ rol al, 1\r
+ mov byte ptr mask6n7, al\r
+ adc di, 0\r
+ sub di, bx\r
+ mov offset6, di\r
+ mov di, offset7\r
+ ror al, 1\r
+ adc di, bx\r
+ mov offset7, di\r
+\r
+; do you realize the entire function has been set up around this little jot?\r
+; keep in mind that radii values are 2 per pixel\r
+@@FilledCircleCalc:\r
+ add cx, 2 ; x += 1\r
+ mov di, error\r
+ add di, cx ; error += (2 * x) + 1\r
+ inc di\r
+ jl @@FilledCircleNoError\r
+ cmp cx, si ; x > y?\r
+ ja @@FleeFlyFlowFum\r
+ sub si, 2 ; y -= 1\r
+ sub di, si ; error -= (2 * y)\r
+ mov error, di\r
+ mov jump_vector, offset @@Advance\r
+ jmp @@PlotLines\r
+@@FilledCircleNoError:\r
+ mov error, di\r
+ mov jump_vector, offset @@NoAdvance\r
+ jmp @@PlotLines\r
+\r
+@@FleeFlyFlowFum:\r
+ pop di\r
+ pop si\r
+ mov sp,bp\r
+ pop bp\r
+\r
+ ret\r
+\r
+_x_filled_circle endp\r
+\r
+ end\r
+\r
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XCIRCLE - header file\r
+;\r
+; This module was written by Matthew MacKenzie\r
+; matm@eng.umd.edu\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+;----------------------------------------------------------------------*/\r
+\r
+#ifndef _XCIRCLE_H_\r
+#define _XCIRCLE_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+\r
+ void x_circle (WORD Left, WORD Top, WORD Diameter,\r
+ WORD Color, WORD ScreenOffs);\r
+\r
+ void x_filled_circle (WORD Left, WORD Top, WORD Diameter,\r
+ WORD Color, WORD ScreenOffs);\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+#endif\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XCIRCLE - Include file\r
+;\r
+; This module was written by Matthew MacKenzie\r
+; matm@eng.umd.edu\r
+;\r
+; XCIRCLE.ASM export functions\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+ global _x_circle : proc\r
+ global _x_filled_circle : proc\r
+\r
+\1a
\ No newline at end of file
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XCLIPPBM\r
+;\r
+; This module was written by Matthew MacKenzie\r
+; matm@eng.umd.edu\r
+;\r
+; Clipped transfer of planar bitmaps from system memory to video memory.\r
+;\r
+; Compile with TASM.\r
+; C near-callable.\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+include xlib.inc\r
+include xclippbm.inc\r
+\r
+\r
+ .data\r
+\r
+ align 2\r
+\r
+; global clipping variables\r
+_TopBound dw (?)\r
+_BottomBound dw (?)\r
+_LeftBound dw (?)\r
+_RightBound dw (?)\r
+\r
+; VGA plane masks\r
+ColumnMask db 011h,022h,044h,088h\r
+\r
+; bit delay timers\r
+LeftDelay db 0, 1, 2, 4\r
+RightDelay db 0, 4, 2, 1\r
+\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; _x_clip_pbm\r
+;\r
+; C near-callable as:\r
+;\r
+; void x_clip_pbm (int X, int Y, int ScreenOffs, char far * Bitmap);\r
+;\r
+; Bitmap is a planar bitmap, in the regular Xlib format.\r
+;\r
+; ax, bx, cx, and dx go south.\r
+\r
+ .code\r
+\r
+ public _x_clip_pbm\r
+ align 2\r
+_x_clip_pbm proc\r
+ARG X:word, Y:word, ScreenOffs:word, Bitmap:dword\r
+LOCAL left_counter, right_counter,column,clipped_height,clipped_width,screen_pos,bitmap_pos,bitmap_size,VGA_mask,width_copy,height_temp,screen_width:word=LocalStk\r
+; Tasm 1.0 does not allow the \ line continuation\r
+;LOCAL left_counter:word, right_counter:word, \\r
+; column:word, clipped_height:word, clipped_width:word, \\r
+; screen_pos:word, bitmap_pos:word, bitmap_size:word, \\r
+; VGA_mask:word, width_copy, height_temp:word, \\r
+; screen_width:word=LocalStk\r
+\r
+ push bp\r
+ mov bp, sp\r
+ sub sp, LocalStk\r
+ push si\r
+ push di\r
+ push ds\r
+\r
+; sociopathic cases: are the clipping bounds out of order?\r
+ mov ax, _TopBound\r
+ cmp ax, _BottomBound\r
+ jg @@GetOut\r
+ mov ax, _LeftBound\r
+ cmp ax, _RightBound\r
+ jle @@ReasonableAndProper\r
+@@GetOut: ; return a 1 -- no image drawn\r
+ pop ds\r
+ pop di\r
+ pop si\r
+ mov ax, 1\r
+ mov sp, bp\r
+ pop bp\r
+ ret\r
+\r
+@@ReasonableAndProper:\r
+\r
+; we need to use both the tables in ds and the height and width of the bitmap\r
+ les si, Bitmap\r
+\r
+; vertical position\r
+ xor cx, cx\r
+ mov cl, byte ptr es:[si + 1] ; height of bitmap\r
+ xor ax, ax\r
+ mov al, byte ptr es:[si] ; width of bitmap\r
+ mul cx\r
+ mov bitmap_size, ax\r
+ mov ax, Y\r
+ cmp ax, _BottomBound ; top edge below clipping box?\r
+ jg @@GetOut\r
+\r
+ mov bx, cx\r
+ add bx, ax\r
+ dec bx ; bottom edge = Y + height - 1\r
+ cmp bx, _TopBound\r
+ jl @@GetOut\r
+ sub bx, _BottomBound ; bottom margin = bottom edge - BottomBound\r
+ jle @@NoBottomBound\r
+ sub cx, bx ; clip bottom margin from height\r
+@@NoBottomBound:\r
+ mov bx, _TopBound\r
+ sub bx, ax ; top margin = TopBound - Y\r
+ jle @@NoTopBound\r
+ add ax, bx ; top edge = Y + top margin\r
+ sub cx, bx ; clip top margin from height\r
+ jmp @@KeepMargin\r
+@@NoTopBound:\r
+ xor bx, bx\r
+@@KeepMargin:\r
+ mov clipped_height, cx\r
+\r
+ mul _ScrnLogicalByteWidth\r
+ mov di, ax\r
+ add di, ScreenOffs ; row of upper-left corner of blit\r
+\r
+ mov cl, byte ptr es:[si] ; width of bitmap (ch is still 0 from height)\r
+ mov ax, cx\r
+ mul bx\r
+ add si, ax\r
+ add si, 2 ; starting position in bitmap\r
+\r
+; horizontal position\r
+ mov width_copy, cx\r
+ mov dx, X\r
+ cmp dx, _RightBound\r
+ jg @@GetOut\r
+ mov dx, 0 ; unclipped value for right delay\r
+\r
+ mov ax, cx\r
+ shl ax, 2 ; width in pixels\r
+ add ax, X\r
+ dec ax ; right edge = X + width in pixels - 1\r
+ cmp ax, _LeftBound\r
+ jl @@GetOut\r
+ sub ax, _RightBound ; right margin = right edge - RightBound\r
+ jle @@NoRightBound\r
+ mov bx, ax\r
+ and bx, 3\r
+ mov dl, RightDelay[bx]\r
+ shr ax, 2\r
+ sub cx, ax ; subtract clipped bytes from width\r
+@@NoRightBound:\r
+ mov right_counter, dx\r
+ mov dx, 0 ; unclipped value for left delay\r
+ mov ax, _LeftBound\r
+ sub ax, X ; left margin = LeftBound - X\r
+ jle @@NoLeftBound\r
+ mov bx, ax\r
+ and bx, 3\r
+ mov dl, LeftDelay[bx]\r
+ add ax, 3\r
+ shr ax, 2 ; left margin/4, rounded up\r
+ sub cx, ax ; subtract clipped bytes from width\r
+ add si, ax ; move starting position in bitmap past margin\r
+ add di, ax ; move starting position on screen past margin\r
+@@NoLeftBound:\r
+ mov left_counter, dx\r
+ mov clipped_width, cx\r
+\r
+ mov ax, X ; add x coordinate to screen position\r
+ mov bx, ax\r
+ sar ax, 2\r
+ add di, ax\r
+\r
+ mov dx, SC_INDEX\r
+ mov al, MAP_MASK\r
+ out dx, al\r
+ inc dx\r
+\r
+ and bx, 3 ; initial mask\r
+ xor ax, ax\r
+ mov al, ColumnMask[bx]\r
+ mov VGA_mask, ax\r
+ out dx, al ; initial mask\r
+\r
+ mov column, 4\r
+ mov bitmap_pos, si\r
+ mov screen_pos, di\r
+ mov ax, _ScrnLogicalByteWidth\r
+ mov screen_width, ax ; since we move ds\r
+\r
+; we've used all our tables, so we can change ds to point to the bitmap,\r
+; and es to point to the screen\r
+ mov ds, word ptr [Bitmap + 2]\r
+ mov ax, SCREEN_SEG\r
+ mov es, ax\r
+\r
+ cld ; strings go forward\r
+ mov bx, width_copy\r
+ sub bx, clipped_width ; bytes to advance one line in bitmap\r
+\r
+; let's actually draw something for a change\r
+@@WritePlane:\r
+ mov ax, clipped_height\r
+ mov height_temp, ax\r
+ mov dx, screen_width\r
+ sub dx, clipped_width ; bytes to advance one line across screen\r
+\r
+@@WriteLine:\r
+ mov cx, clipped_width\r
+ shr cx, 1\r
+ rep movsw ; in they went, two by two...\r
+ adc cx, 0\r
+ rep movsb ; catch stray last byte, if it's there\r
+ add si, bx ; advance one bitmap line\r
+ add di, dx ; advance one screen line\r
+\r
+ dec height_temp\r
+ jnz @@WriteLine\r
+\r
+ dec column\r
+ jz @@OuttaHere ; only four columns per customer, please\r
+ mov dx, SC_INDEX + 1\r
+ rol byte ptr VGA_mask, 1\r
+ adc screen_pos, 0 ; add to location if we've wrapped to plane 0\r
+ mov al, byte ptr VGA_mask\r
+ out dx, al ; set VGA for next column\r
+\r
+ shr right_counter, 1\r
+ jnc @@NoRightCounter\r
+ dec clipped_width ; cut off right edge for later planes\r
+ inc bx\r
+@@NoRightCounter:\r
+ shr left_counter, 1\r
+ jnc @@NoLeftCounter\r
+ inc clipped_width ; add to left edge for later planes\r
+ dec bx\r
+ dec bitmap_pos\r
+ dec screen_pos\r
+@@NoLeftCounter:\r
+ mov si, bitmap_pos\r
+ add si, bitmap_size\r
+ mov bitmap_pos, si\r
+ mov di, screen_pos\r
+ jmp @@WritePlane\r
+\r
+@@OuttaHere: ; return a 0 -- something was inside the boundary\r
+ pop ds\r
+ pop di\r
+ pop si\r
+ mov ax, 0\r
+ mov sp, bp\r
+ pop bp\r
+ ret\r
+_x_clip_pbm endp\r
+\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; _x_clip_masked_pbm\r
+;\r
+; C near-callable as:\r
+;\r
+; void x_clip_masked_pbm (int X, int Y, int ScreenOffs, char far * Bitmap);\r
+;\r
+; Bitmap is a planar bitmap, in the regular Xlib format.\r
+; The width of the bitmap cannot be greater than 90 bytes, however.\r
+; Ain't that just criminal?\r
+;\r
+; ax, bx, cx, and dx go south.\r
+\r
+\r
+; one branch per pixel is more than enough -- we'll unroll the line-writing\r
+; loop all the way to try to get a little speed (at the expense, as usual,\r
+; of a chunk of memory)\r
+\r
+MaskedPoint macro offset\r
+ mov al, [si + offset]\r
+ or al, al\r
+ jz $+6\r
+ mov es:[di + offset], al\r
+ endm\r
+\r
+MaskedPointSize equ 11\r
+\r
+ public _x_clip_masked_pbm\r
+ align 2\r
+_x_clip_masked_pbm proc\r
+ARG X:word, Y:word, ScreenOffs:word, Bitmap:dword\r
+; Tasm 1.0 does not allow the \ line continuation\r
+LOCAL left_counter,right_counter,column:word,clipped_height,screen_pos,bitmap_pos,bitmap_size,VGA_mask,width_copy,height_temp,screen_width:word=LocalStk\r
+;LOCAL left_counter:word, right_counter:word, \\r
+; column:word, clipped_height:word, \\r
+; screen_pos:word, bitmap_pos:word, bitmap_size:word, \\r
+; VGA_mask:word, width_copy, height_temp:word, \\r
+; screen_width:word=LocalStk\r
+ push bp\r
+ mov bp, sp\r
+ sub sp, LocalStk\r
+ push si\r
+ push di\r
+ push ds\r
+\r
+; sociopathic cases: are the clipping bounds out of order?\r
+ mov ax, _TopBound\r
+ cmp ax, _BottomBound\r
+ jg @@GetOut\r
+ mov ax, _LeftBound\r
+ cmp ax, _RightBound\r
+ jle @@ReasonableAndProper\r
+@@GetOut: ; return a 1 -- no image drawn\r
+ pop ds\r
+ pop di\r
+ pop si\r
+ mov ax, 1\r
+ mov sp, bp\r
+ pop bp\r
+ ret\r
+\r
+@@ReasonableAndProper:\r
+\r
+; we need to use both the tables in ds and the height and width of the bitmap\r
+ les si, Bitmap\r
+\r
+; vertical position\r
+ xor cx, cx\r
+ mov cl, byte ptr es:[si + 1] ; height of bitmap\r
+ xor ax, ax\r
+ mov al, byte ptr es:[si] ; width of bitmap\r
+ mul cx\r
+ mov bitmap_size, ax\r
+ mov ax, Y\r
+ cmp ax, _BottomBound ; top edge below clipping box?\r
+ jg @@GetOut\r
+\r
+ mov bx, cx\r
+ add bx, ax\r
+ dec bx ; bottom edge = Y + height - 1\r
+ cmp bx, _TopBound\r
+ jl @@GetOut\r
+ sub bx, _BottomBound ; bottom margin = bottom edge - BottomBound\r
+ jle @@NoBottomBound\r
+ sub cx, bx ; clip bottom margin from height\r
+@@NoBottomBound:\r
+ mov bx, _TopBound\r
+ sub bx, ax ; top margin = TopBound - Y\r
+ jle @@NoTopBound\r
+ add ax, bx ; top edge = Y + top margin\r
+ sub cx, bx ; clip top margin from height\r
+ jmp @@KeepMargin\r
+@@NoTopBound:\r
+ xor bx, bx\r
+@@KeepMargin:\r
+ mov clipped_height, cx\r
+\r
+ mul _ScrnLogicalByteWidth\r
+ mov di, ax\r
+ add di, ScreenOffs ; row of upper-left corner of blit\r
+\r
+ mov cl, byte ptr es:[si] ; width of bitmap (ch is still 0 from height)\r
+ mov ax, cx\r
+ mul bx\r
+ add si, ax\r
+ add si, 2 ; starting position in bitmap\r
+\r
+; horizontal position\r
+ mov width_copy, cx\r
+ mov dx, X\r
+ cmp dx, _RightBound\r
+ jg @@GetOut\r
+ mov dx, 0 ; unclipped value for right delay\r
+\r
+ mov ax, cx\r
+ shl ax, 2 ; width in pixels\r
+ add ax, X\r
+ dec ax ; right edge = X + width in pixels - 1\r
+ cmp ax, _LeftBound\r
+ jl @@GetOut\r
+ sub ax, _RightBound ; right margin = right edge - RightBound\r
+ jle @@NoRightBound\r
+ mov bx, ax\r
+ and bx, 3\r
+ mov dl, RightDelay[bx]\r
+ shr ax, 2\r
+ sub cx, ax ; subtract clipped bytes from width\r
+@@NoRightBound:\r
+ mov right_counter, dx\r
+ mov dx, 0 ; unclipped value for left delay\r
+ mov ax, _LeftBound\r
+ sub ax, X ; left margin = LeftBound - X\r
+ jle @@NoLeftBound\r
+ mov bx, ax\r
+ and bx, 3\r
+ mov dl, LeftDelay[bx]\r
+ add ax, 3\r
+ shr ax, 2 ; left margin/4, rounded up\r
+ sub cx, ax ; subtract clipped bytes from width\r
+ add si, ax ; move starting position in bitmap past margin\r
+ add di, ax ; move starting position on screen past margin\r
+@@NoLeftBound:\r
+ mov left_counter, dx\r
+ mov ax, cx\r
+ imul ax, (-1 * MaskedPointSize)\r
+ add ax, offset @@LineDone + 2\r
+ mov cx, ax ; jump offset for plotting\r
+\r
+ mov ax, X ; add x coordinate to screen position\r
+ mov bx, ax\r
+ shr ax, 2\r
+ add di, ax\r
+\r
+ mov dx, SC_INDEX\r
+ mov al, MAP_MASK\r
+ out dx, al\r
+ inc dx\r
+\r
+ and bx, 3 ; initial mask\r
+ xor ax, ax\r
+ mov al, ColumnMask[bx]\r
+ mov VGA_mask, ax\r
+ out dx, al\r
+\r
+ mov column, 4\r
+ mov bitmap_pos, si\r
+ mov screen_pos, di\r
+ mov ax, _ScrnLogicalByteWidth\r
+ mov screen_width, ax ; since we move ds\r
+\r
+; we've used all our tables, so we can change ds to point to the bitmap,\r
+; and es to point to the screen\r
+ mov ds, word ptr [Bitmap + 2]\r
+ mov ax, SCREEN_SEG\r
+ mov es, ax\r
+\r
+ mov bx, width_copy\r
+\r
+; let's actually draw something for a change\r
+ mov ax, clipped_height\r
+ mov height_temp, ax\r
+ mov dx, screen_width\r
+ jmp cx\r
+\r
+; 90 bottles of beer on the wall...\r
+ PointLoop = 89\r
+ rept 89\r
+ MaskedPoint PointLoop\r
+ PointLoop = PointLoop - 1\r
+ endm\r
+; one bottle of beer...\r
+\r
+; final point needs a different branch offset, so we don't use MaskedPoint\r
+ mov al, [si]\r
+ or al, al\r
+ jz @@LineDone\r
+ mov es:[di], al\r
+\r
+@@LineDone:\r
+ add si, bx ; advance one bitmap line\r
+ add di, dx ; advance one screen line\r
+ dec height_temp\r
+ jz @@PlaneDone\r
+ jmp cx\r
+\r
+@@PlaneDone:\r
+ dec column\r
+ jz @@OuttaHere ; only four columns per customer, please\r
+ mov dx, SC_INDEX + 1\r
+ rol byte ptr VGA_mask, 1\r
+ adc screen_pos, 0 ; move to new column if we've wrapped to plane 0\r
+ mov al, byte ptr VGA_mask\r
+ out dx, al ; set VGA for next column\r
+\r
+ shr right_counter, 1\r
+ jnc @@NoRightCounter\r
+ add cx, MaskedPointSize ; cut off right edge for later planes\r
+@@NoRightCounter:\r
+ shr left_counter, 1\r
+ jnc @@NoLeftCounter\r
+ sub cx, MaskedPointSize ; add to left edge for later planes\r
+ dec bitmap_pos\r
+ dec screen_pos\r
+@@NoLeftCounter:\r
+ mov si, bitmap_pos\r
+ add si, bitmap_size\r
+ mov bitmap_pos, si\r
+ mov di, screen_pos\r
+\r
+ mov ax, clipped_height\r
+ mov height_temp, ax\r
+ mov dx, screen_width\r
+ jmp cx\r
+\r
+@@OuttaHere: ; return a 0 -- something was inside the boundary\r
+ pop ds\r
+ pop di\r
+ pop si\r
+ mov ax, 0\r
+ mov sp, bp\r
+ pop bp\r
+ ret\r
+_x_clip_masked_pbm endp\r
+\r
+ end\r
+\r
--- /dev/null
+/*-----------------------------------------------------------------------\r
+; MODULE XCLIPPBM\r
+;\r
+; This module was written by Matthew MacKenzie\r
+; matm@eng.umd.edu\r
+;\r
+; Clipped transfer of planar bitmaps from system memory to video memory.\r
+;\r
+; Compile with TASM.\r
+; C near-callable.\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;----------------------------------------------------------------------*/\r
+\r
+#ifndef _XCLIPPBM_H_\r
+#define _XCLIPPBM_H_\r
+\r
+/* unlike most global variables in Xlib, these are meant to be written to;\r
+ in fact they start off uninitialized -- all values are in pixels */\r
+extern int TopBound;\r
+extern int BottomBound;\r
+extern int LeftBound;\r
+extern int RightBound;\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+\r
+/* for both functions, a return value of 1 indicates that the entire\r
+bitmap was outside the bounding box, while a value of 0 means that\r
+something may have ended up on the screen */\r
+\r
+/* copies a planar bitmap from SRAM to VRAM, with clipping */\r
+\r
+ int x_clip_pbm (int X, int Y, int ScreenOffs, char far * Bitmap);\r
+\r
+/* copies a planar bitmap from SRAM to VRAM, with clipping -- 0 bytes\r
+ in the bitmap are not copied */\r
+\r
+ int x_clip_masked_pbm (int X, int Y, int ScreenOffs, char far * Bitmap);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+#endif\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XPBITMAP - Include file\r
+;\r
+; This module was written by Matthew MacKenzie\r
+; matm@eng.umd.edu\r
+;\r
+; XPBITMAP.ASM export functions\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+ global _x_clip_masked_pbm :proc\r
+ global _x_clip_pbm :proc\r
+\r
+ global _LeftBound :word\r
+ global _RightBound :word\r
+ global _TopBound :word\r
+ global _BottomBound :word\r
+\r
+\1a
\ No newline at end of file
--- /dev/null
+;-----------------------------------------------------------------------\r
+; module XCOMPPBM\r
+;\r
+; This module contains only the compiler and sizeof routines --\r
+; use the plotter from XCBITMAP.\r
+;\r
+;-----------------------------------------------------------------------\r
+\r
+include xlib.inc\r
+include xcomppbm.inc\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; _x_compile_pbm\r
+;\r
+; I only changed five instructions, instead of rewriting this\r
+; for PBMs. So it is amazingly inefficient. But, what the hell,\r
+; It's only a game :).\r
+;\r
+\r
+; accessory macros to save typing (what else?)\r
+Emitb macro arg\r
+ mov byte ptr es:[di],&arg&\r
+ inc di\r
+ endm\r
+\r
+Emitw macro arg\r
+ mov word ptr es:[di],&arg&\r
+ add di,2\r
+ endm\r
+\r
+; opcodes emitted by _x_compile_pbm\r
+ROL_AL equ 0c0d0h ; rol al\r
+SHORT_STORE_8 equ 044c6h ; mov [si]+disp8, imm8\r
+STORE_8 equ 084c6h ; mov [si]+disp16, imm8\r
+SHORT_STORE_16 equ 044c7h ; mov [si]+disp8, imm16\r
+STORE_16 equ 084c7h ; mov [si]+disp16, imm16\r
+ADC_SI_IMMED equ 0d683h ; adc si,imm8\r
+OUT_AL equ 0eeh ; out dx,al\r
+RETURN equ 0cbh ; ret\r
+\r
+\r
+.data\r
+\r
+align 2\r
+ColumnMask db 011h,022h,044h,088h\r
+\r
+\r
+.code\r
+\r
+ align 2\r
+_x_compile_pbm proc\r
+ARG logical_width:word,bitmap:dword,output:dword\r
+LOCAL bwidth,scanx,scany,outputx,outputy,column,set_column,input_size:word=LocalStk\r
+ push bp\r
+ mov bp, sp ; caller's stack frame\r
+ sub sp,LocalStk ; local space\r
+ push si\r
+ push di\r
+ push ds\r
+\r
+ mov word ptr [scanx],0\r
+ mov word ptr [scany],0\r
+ mov word ptr [outputx],0\r
+ mov word ptr [outputy],0\r
+ mov word ptr [column],0\r
+ mov word ptr [set_column],0\r
+\r
+ lds si,[bitmap] ; 32-bit pointer to source bitmap\r
+\r
+ les di,[output] ; 32-bit pointer to destination stream\r
+\r
+ lodsb ; load width byte\r
+ xor ah, ah ; convert to word\r
+ mov [bwidth], ax ; save for future reference\r
+ mov bl, al ; copy width byte to bl\r
+ lodsb ; load height byte -- already a word since ah=0\r
+ mul bl ; mult height word by width byte\r
+ mov [input_size], ax; to get pixel total\r
+\r
+@@MainLoop:\r
+ mov bx, [scanx] ; position in original bitmap\r
+ add bx, [scany]\r
+\r
+ mov al, [si+bx] ; get pixel\r
+ or al, al ; skip empty pixels\r
+ jnz @@NoAdvance\r
+ jmp @@Advance\r
+@@NoAdvance:\r
+\r
+ mov dx, [set_column]\r
+ cmp dx, [column]\r
+ je @@SameColumn\r
+@@ColumnLoop:\r
+ Emitw ROL_AL ; emit code to move to new column\r
+ Emitw ADC_SI_IMMED\r
+ Emitb 0\r
+\r
+ inc dx\r
+ cmp dx, [column]\r
+ jl @@ColumnLoop\r
+\r
+ Emitb OUT_AL ; emit code to set VGA mask for new column\r
+ mov [set_column], dx\r
+@@SameColumn:\r
+ mov dx, [outputy] ; calculate output position\r
+ add dx, [outputx]\r
+ sub dx, 128\r
+\r
+ inc word ptr [scanx]\r
+ mov cx, [scanx] ; within four pixels of right edge?\r
+ cmp cx, [bwidth]\r
+ jge @@OnePixel\r
+\r
+ inc word ptr [outputx]\r
+ mov ah, [si+bx+1] ; get second pixel\r
+ or ah, ah\r
+ jnz @@TwoPixels\r
+@@OnePixel:\r
+ cmp dx, 127 ; can we use shorter form?\r
+ jg @@OnePixLarge\r
+ cmp dx, -128\r
+ jl @@OnePixLarge\r
+ Emitw SHORT_STORE_8\r
+ Emitb dl ; 8-bit position in output\r
+ jmp @@EmitOnePixel\r
+@@OnePixLarge:\r
+ Emitw STORE_8\r
+ Emitw dx ; position in output\r
+@@EmitOnePixel:\r
+ Emitb al\r
+ jmp short @@Advance\r
+@@TwoPixels:\r
+ cmp dx, 127\r
+ jg @@TwoPixLarge\r
+ cmp dx, -128\r
+ jl @@TwoPixLarge\r
+ Emitw SHORT_STORE_16\r
+ Emitb dl ; 8-bit position in output\r
+ jmp @@EmitTwoPixels\r
+@@TwoPixLarge:\r
+ Emitw STORE_16\r
+ Emitw dx ; position in output\r
+@@EmitTwoPixels:\r
+ Emitw ax\r
+\r
+@@Advance:\r
+ inc word ptr [outputx]\r
+ mov ax, [scanx]\r
+ inc ax\r
+ cmp ax, [bwidth]\r
+ jl @@AdvanceDone\r
+ mov dx, [outputy]\r
+ add dx, [logical_width]\r
+ mov cx, [scany]\r
+ add cx, [bwidth]\r
+ cmp cx, [input_size]\r
+ jl @@NoNewColumn\r
+ inc word ptr [column]\r
+ mov cx, [column]\r
+ cmp cx, 4\r
+ je @@Exit ; Column 4: there is no column 4.\r
+ xor cx, cx ; scany and outputy are 0 again for\r
+ mov dx, cx ; the new column\r
+ add si, [input_size]\r
+@@NoNewColumn:\r
+ mov [outputy], dx\r
+ mov [scany], cx\r
+ xor ax, ax\r
+ mov word ptr [outputx], 0\r
+@@AdvanceDone:\r
+ mov [scanx], ax\r
+ jmp @@MainLoop\r
+\r
+@@Exit:\r
+ Emitb RETURN\r
+ mov ax,di\r
+ sub ax,word ptr [output] ; size of generated code\r
+\r
+ pop ds\r
+ pop di\r
+ pop si\r
+ mov sp, bp\r
+ pop bp\r
+\r
+ ret\r
+_x_compile_pbm endp\r
+\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; _x_sizeof_cpbm\r
+;\r
+\r
+\r
+ align 2\r
+_x_sizeof_cpbm proc\r
+ARG logical_width:word,bitmap:dword\r
+LOCAL bwidth,scanx,scany,outputx,outputy,column,set_column,input_size:word=LocalStk\r
+ push bp\r
+ mov bp, sp ; caller's stack frame\r
+ sub sp,LocalStk ; local space\r
+ push si\r
+ push di\r
+ push ds\r
+\r
+ mov word ptr [scanx], 0\r
+ mov word ptr [scany], 0\r
+ mov word ptr [outputx], 0\r
+ mov word ptr [outputy], 0\r
+ mov word ptr [column], 0\r
+ mov word ptr [set_column], 0\r
+\r
+ lds si,[bitmap] ; 32-bit pointer to source bitmap\r
+\r
+ mov di, 1 ; initial size is just the size of the far RET\r
+\r
+ lodsb ; load width byte\r
+ xor ah, ah ; convert to word\r
+ mov [bwidth], ax ; save for future reference\r
+ mov bl, al ; copy width byte to bl\r
+ lodsb ; load height byte -- already a word since ah=0\r
+ mul bl ; mult height word by width byte\r
+ mov [input_size], ax; to get pixel total\r
+\r
+@@MainLoop:\r
+ mov bx, [scanx] ; position in original bitmap\r
+ add bx, [scany]\r
+\r
+ mov al, [si+bx] ; get pixel\r
+ or al, al ; skip empty pixels\r
+ jnz @@NoAdvance\r
+ jmp @@Advance\r
+@@NoAdvance:\r
+\r
+ mov dx, [set_column]\r
+ cmp dx, [column]\r
+ je @@SameColumn\r
+@@ColumnLoop:\r
+ add di, 5 ; size of code to move to new column\r
+ inc dx\r
+ cmp dx,[column]\r
+ jl @@ColumnLoop\r
+\r
+ inc di ; size of code to set VGA mask\r
+ mov [set_column], dx\r
+@@SameColumn:\r
+ mov dx, [outputy] ; calculate output position\r
+ add dx, [outputx]\r
+ sub dx, 128\r
+\r
+ inc word ptr [scanx]\r
+ mov cx, [scanx] ; within four pixels of right edge?\r
+ cmp cx, [bwidth]\r
+ jge @@OnePixel\r
+\r
+ inc word ptr [outputx]\r
+ mov ah,[si+bx+1] ; get second pixel\r
+ or ah, ah\r
+ jnz @@TwoPixels\r
+@@OnePixel:\r
+ cmp dx, 127 ; can we use shorter form?\r
+ jg @@OnePixLarge\r
+ cmp dx, -128\r
+ jl @@OnePixLarge\r
+ add di, 4 ; size of 8-bit position in output plus one pixel\r
+ jmp @@EmitOnePixel\r
+@@OnePixLarge:\r
+ add di, 5 ; size of position in output plus one pixels\r
+@@EmitOnePixel:\r
+ jmp short @@Advance\r
+@@TwoPixels:\r
+ cmp dx, 127\r
+ jg @@TwoPixLarge\r
+ cmp dx, -128\r
+ jl @@TwoPixLarge\r
+ add di, 5 ; size of 8-bit position in output plus two pixels\r
+ jmp @@EmitTwoPixels\r
+@@TwoPixLarge:\r
+ add di, 6 ; size of 16-bit position in output plus two pixels\r
+@@EmitTwoPixels:\r
+\r
+@@Advance:\r
+ inc word ptr [outputx]\r
+ mov ax, [scanx]\r
+ inc ax\r
+ cmp ax, [bwidth]\r
+ jl @@AdvanceDone\r
+ mov dx, [outputy]\r
+ add dx, [logical_width]\r
+ mov cx, [scany]\r
+ add cx, [bwidth]\r
+ cmp cx, [input_size]\r
+ jl @@NoNewColumn\r
+ inc word ptr [column]\r
+ mov cx, [column]\r
+ cmp cx, 4\r
+ je @@Exit ; Column 4: there is no column 4.\r
+ xor cx,cx ; scany and outputy are 0 again for\r
+ mov dx,cx ; the new column\r
+ add si, [input_size]\r
+@@NoNewColumn:\r
+ mov [outputy], dx\r
+ mov [scany], cx\r
+ xor ax, ax\r
+ mov word ptr [outputx], ax\r
+@@AdvanceDone:\r
+ mov [scanx], ax\r
+ jmp @@MainLoop\r
+\r
+@@Exit:\r
+ mov ax, di ; size of generated code\r
+\r
+ pop ds\r
+ pop di\r
+ pop si\r
+ mov sp,bp\r
+ pop bp\r
+\r
+ ret\r
+_x_sizeof_cpbm endp\r
+\r
+end\r
+\r
--- /dev/null
+#ifndef _XCOMPPBM_H_\r
+#define _XCOMPPBM_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+\r
+ int x_compile_pbm ( /* Compile a planar bitmap to generate */\r
+ WORD logical_screen_width, /* machine code to plot it at any */\r
+ char far * bitmap, /* required screen coordinates FAST. */\r
+ char far * output);\r
+\r
+ int x_sizeof_cpbm ( /* Find the size of the code which a */\r
+ WORD logical_screen_width, /* pbm would result in, if it */\r
+ char far * bitmap); /* were compiled (used for allocation). */\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
--- /dev/null
+global _x_compile_pbm : proc\r
+global _x_sizeof_cpbm : proc\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XDETECT\r
+;\r
+; Hardware detection module\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+LOCALS\r
+.286\r
+\r
+include model.inc\r
+include xdetect.inc\r
+\r
+ .data\r
+\r
+_MouseButtonCount dw 0\r
+_MouseVersion dw 0\r
+_MouseType db 0\r
+_MouseIRQ db 0\r
+\r
+ .code\r
+\r
+\r
+i86 equ 0\r
+i186 equ 1\r
+i286 equ 2\r
+i386sx equ 3\r
+i386dx equ 4\r
+i486 equ 5\r
+\r
+\r
+NONE equ 0\r
+MDA equ 1\r
+CGA equ 2\r
+EGAMono equ 3\r
+EGAColor equ 4\r
+VGAMono equ 5\r
+VGAColor equ 6\r
+MCGAMono equ 7\r
+MCGAColor equ 8\r
+\r
+PS2_CARDS db 0,1,2,2,4,3,2,5,6,2,8,7,8\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; PC Graphics detection routine. Returns graphics card type\r
+;\r
+; C callable as:\r
+; unsigned int x_graphics_card();\r
+;\r
+;\r
+\r
+proc _x_graphics_card\r
+ push bp ; Preserve caller's stack frame\r
+ mov bp,sp\r
+ mov ax,1A00h ; Try calling VGA Identity Adapter function\r
+ int 10h\r
+ cmp al,1Ah ; Do we have PS/2 video bios ?\r
+ jne @@not_PS2 ; No!\r
+\r
+ cmp bl,0Ch ; bl > 0Ch => CGA hardware\r
+ jg @@is_CGA ; Jump if we have CGA\r
+ xor bh,bh\r
+ xor ah,ah\r
+ mov al,cs:PS2_CARDS[bx] ; Load ax from PS/2 hardware table\r
+ jmp short @@done ; return ax\r
+@@is_CGA:\r
+ mov ax,CGA ; Have detected CGA, return id\r
+ jmp short @@done\r
+@@not_PS2: ; OK We don't have PS/2 Video bios\r
+ mov ah,12h ; Set alternate function service\r
+ mov bx,10h ; Set to return EGA information\r
+ int 10h ; call video service\r
+ cmp bx,10h ; Is EGA there ?\r
+ je @@simple_adapter ; Nop!\r
+ mov ah,12h ; Since we have EGA bios, get details\r
+ mov bl,10h\r
+ int 10h\r
+ or bh,bh ; Do we have colour EGA ?\r
+ jz @@ega_color ; Yes\r
+ mov ax,EGAMono ; Otherwise we have Mono EGA\r
+ jmp short @@done\r
+@@ega_color:\r
+ mov ax,EGAColor ; Have detected EGA Color, return id\r
+ jmp short @@done\r
+@@simple_adapter:\r
+ int 11h ; Lets try equipment determination service\r
+ and al,30h\r
+ shr al,4\r
+ xor ah,ah\r
+ or al,al ; Do we have any graphics card at all ?\r
+ jz @@done ; No ? This is a stupid machine!\r
+ cmp al,3 ; Do We have a Mono adapter\r
+ jne @@is_CGA ; No\r
+ mov ax,MDA ; Have detected MDA, return id\r
+@@done:\r
+ pop bp ;restore caller's stack frame\r
+ ret\r
+_x_graphics_card endp\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; PC Processor detection routine\r
+;\r
+; C callable as:\r
+; unsigned int x_processor();\r
+;\r
+;\r
+proc _x_processor\r
+ push bp\r
+ mov bp,sp\r
+ pushf ; Save flags\r
+ xor ax,ax ; Clear AX\r
+ push ax ; Push it on the stack\r
+ popf ; Zero the flags\r
+ pushf ; Try to zero bits 12-15\r
+ pop ax ; Recover flags\r
+ and ax,0F000h ; If bits 12-15 are 1 => i86 or i286\r
+ cmp ax,0F000h\r
+ jne @@1\r
+\r
+ push cx ; save CX\r
+ mov ax,0FFFFh ; Set all AX bits\r
+ mov cl,33 ; Will shift once on 80186\r
+ shl ax,cl ; or 33 x on 8086\r
+ pop cx\r
+ mov ax,i186\r
+ jnz @@done\r
+ mov ax,i86 ; 0 => 8086/8088\r
+ jmp short @@done\r
+\r
+@@1:\r
+ mov ax,07000h ; Try to set bits 12-14\r
+ push ax\r
+ popf\r
+ pushf\r
+ pop ax\r
+ and ax,07000h ; If bits 12-14 are 0 => i286\r
+ mov ax,i286\r
+ jz @@done\r
+\r
+ ;; 386/486 resolution code taken from WHATCPU.ASM by\r
+ ;; Dave M. Walker\r
+\r
+\r
+ P386\r
+ mov eax,cr0\r
+ mov ebx,eax ;Original CR0 into EBX\r
+ or al,10h ;Set bit\r
+ mov cr0,eax ;Store it\r
+ mov eax,cr0 ;Read it back\r
+ mov cr0,ebx ;Restore CR0\r
+ test al,10h ;Did it set?\r
+ mov ax,i386sx\r
+ jz @@done ;Jump if 386SX\r
+\r
+ ;*** Test AC bit in EFLAGS (386DX won't change)\r
+ mov ecx,esp ;Original ESP in ECX\r
+ pushfd ;Original EFLAGS in EBX\r
+ pop ebx\r
+ and esp,not 3 ;Align stack to prevent 486\r
+ ; fault when AC is flipped\r
+ mov eax,ebx ;EFLAGS => EAX\r
+ xor eax,40000h ;Flip AC flag\r
+ push eax ;Store it\r
+ popfd\r
+ pushfd ;Read it back\r
+ pop eax\r
+ push ebx ;Restore EFLAGS\r
+ popfd\r
+ mov esp,ecx ;Restore ESP\r
+ cmp eax,ebx ;Compare old/new AC bits\r
+ mov ax,i386dx\r
+ je @@done\r
+is_486: ;Until the Pentium appears...\r
+ mov ax,i486\r
+@@done:\r
+ popf\r
+ .286\r
+ pop bp\r
+ ret\r
+_x_processor endp\r
+\r
+.8086\r
+;-----------------------------------------------------------------------\r
+; PC Numeric coprocessor detection routine\r
+;\r
+; C callable as:\r
+; unsigned int x_coprocessor();\r
+;\r
+; Based on an article in PC Tech Journal, Aug 87 by Ted Forgeron\r
+;\r
+; Returns 1 if coprocessor found, zero otherwise\r
+\r
+_x_coprocessor proc\r
+ARG control:word=StkSize\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,StkSize\r
+\r
+ fninit ; try to initialize the copro.\r
+ mov [control],0 ; clear control word variable\r
+ fnstcw control ; put control word in memory\r
+ mov ax,[control] ;\r
+ cmp ah,03h ; do we have a coprocessor ?\r
+ je @@HaveCopro ; jump if yes!\r
+ xor ax,ax ; return 0 since nothing found\r
+ jmp short @@done\r
+@@HaveCopro:\r
+ mov ax,1\r
+@@done:\r
+ mov sp,bp\r
+ pop bp\r
+ ret\r
+_x_coprocessor endp\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; PC Mouse Driver detection routine\r
+;\r
+; C callable as:\r
+; unsigned int x_mousedriver();\r
+;\r
+;\r
+; Returns 1 if mouse driver found, zero otherwise\r
+_x_mousedriver proc\r
+ push bp\r
+ mov bp,sp\r
+ mov ax,3533h ; Get int 33 interrupt vector\r
+ int 21h ; Call dos\r
+ xor cx,cx ; Clear "found" flag\r
+ mov ax,es ; Is the vector null (ES==0 && BX==0) ?\r
+ or bx,ax\r
+ jz @@NoMouseDriver ; Yes! No mouse driver installed - Jump\r
+\r
+ ; Just make absolutely sure the vector points to the mouse\r
+ ; driver (just in case)\r
+\r
+ xor ax,ax ; FUNC 0: Mouse Initialization\r
+ int 33h\r
+ or ax,ax ; Do we have an installed mouse driver ?\r
+ jz @@NoMouseDriver; No ?\r
+ mov [_MouseButtonCount],bx\r
+\r
+ mov ax,24h\r
+ int 33h\r
+ mov [_MouseVersion],bx\r
+ mov [_MouseType],ch\r
+ mov [_MouseIRQ],cl\r
+\r
+ mov cx,1 ; Yes! set flag\r
+\r
+@@NoMouseDriver:\r
+ mov ax,cx ; Return "found" flag\r
+ pop bp\r
+ ret\r
+_x_mousedriver endp\r
+\r
+\r
+end
\ No newline at end of file
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XDETECT - header file\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;-----------------------------------------------------------------------*/\r
+\r
+#ifndef _XDETECT_H_\r
+#define _XDETECT_H_\r
+\r
+#define I8086 0\r
+#define I80186 1\r
+#define I80286 2\r
+#define I80386SX 3\r
+#define I80386DX 4\r
+#define I80486 5\r
+\r
+#define NoGraphics 0\r
+#define MDA 1\r
+#define CGA 2\r
+#define EGAMono 3\r
+#define EGAColor 4\r
+#define VGAMono 5\r
+#define VGAColor 6\r
+#define MCGAMono 7\r
+#define MCGAColor 8\r
+\r
+#define BUS_MOUSE 1\r
+#define SERIAL_MOUSE 2\r
+#define INPORT_MOUSE 3\r
+#define PS2_MOUSE 4\r
+#define HP_MOUSE 5\r
+\r
+/* VARIABLES =========================================================== */\r
+\r
+extern WORD MouseButtonCount; /* number of mouse buttons */\r
+extern WORD MouseVersion; /* mouse driver version */\r
+extern WORD MouseType; /* mouse type */\r
+extern WORD MouseIRQ; /* mouse IRQ number */\r
+\r
+/* FUNCTIONS =========================================================== */\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+ int x_graphics_card(void); /* Detect installed Graphics card type */\r
+ int x_processor(void); /* Detect processor type */\r
+ int x_coprocessor(void); /* Detect math co-processor type */\r
+ int x_mousedriver(void); /* Detect math co-processor type */\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XDETECT - Include file\r
+;\r
+; XDETECT.ASM export functions\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+ global _MouseButtonCount :word\r
+ global _MouseVersion :word\r
+ global _MouseType :byte\r
+ global _MouseIRQ :byte\r
+\r
+\r
+ global _x_graphics_card :proc\r
+ global _x_processor :proc\r
+ global _x_coprocessor :proc\r
+ global _x_mousedriver :proc\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XFILEIO\r
+;\r
+; Sequential binary file I/O functions\r
+;\r
+; Some functions based on a r.g.p post by Joshua Jensen\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+COMMENT $\r
+\r
+\r
+$\r
+\r
+LOCALS\r
+.286\r
+\r
+include model.inc\r
+include xfileio.inc\r
+ .data\r
+\r
+ _file_err dw (?) ; error value\r
+\r
+ .code\r
+\r
+PUSH_DS macro\r
+ IFNDEF s\r
+ push ds\r
+ ENDIF\r
+ endm\r
+\r
+POP_DS macro\r
+ IFNDEF s\r
+ pop ds\r
+ ENDIF\r
+ endm\r
+\r
+LDS_M macro arg1,arg2\r
+ IFNDEF s\r
+ lds &arg1&,&arg2&\r
+ ELSE\r
+ mov &arg1&,word ptr &arg2&\r
+ ENDIF\r
+ endm\r
+\r
+\r
+\r
+;****************************************************************\r
+;\r
+; name: f_open\r
+;\r
+; C Prototype:\r
+;\r
+; extern int f_open(char * filename, char access)\r
+;\r
+; Opens a file according to the access char:\r
+;\r
+; 0 = read only - If doesnt exist return error\r
+; 1 = write only - If doesnt exist create it otherwise clear it\r
+; 2 = read/write - If doesnt exist create it\r
+;\r
+; Returns the file handle on success, -1 on failure\r
+;\r
+;\r
+proc _f_open\r
+IFNDEF s\r
+ ARG filename:dword,access:byte\r
+ELSE\r
+ ARG filename:word,access:byte\r
+ENDIF\r
+ push bp ; Preserve caller's stack frame\r
+ mov bp,sp\r
+ PUSH_DS\r
+ LDS_M dx,[filename] ; point DS:DX to file name string\r
+ mov [_file_err],0\r
+ cmp [access],1\r
+ je @@creat\r
+\r
+ mov ah,3dh ; select "open file" DOS service\r
+ mov al,[access] ; select access type code\r
+ int 21h ; call DOS service\r
+ jnb @@Done ; If carry flag set we have failed\r
+\r
+\r
+ cmp [access],2\r
+ jne @@error\r
+@@creat:\r
+ mov ah,3ch ; select "creat file" DOS service\r
+ mov cx,0\r
+ int 21h ; call DOS service\r
+ jnb @@Done ; If carry flag set we have failed\r
+@@error:\r
+ mov [_file_err],ax\r
+ mov ax,-1 ; indicate failure\r
+@@Done: ; otherwise return file handle\r
+ POP_DS\r
+ pop bp ;restore caller's stack frame\r
+ ret\r
+_f_open endp\r
+\r
+\r
+;****************************************************************\r
+;\r
+; name: f_close\r
+;\r
+; C Prototype:\r
+;\r
+; extern int f_close(int handle)\r
+;\r
+; Closes the file associated with the specified handle\r
+;\r
+; Returns 0 on success, -1 on failure\r
+;\r
+proc _f_close\r
+ARG handle:word\r
+ push bp ; Preserve caller's stack frame\r
+ mov bp,sp\r
+\r
+ mov [_file_err],0 ; Clear error\r
+ mov ah,3eh ; select "close file handle" DOS service\r
+ mov bx,[handle] ; select handle of file to close\r
+ int 21h ; call DOS service\r
+ jnb @@Fix ; failed if carry flag set\r
+ mov [_file_err],ax;\r
+ mov ax,-1 ; return error\r
+ jmp short @@Done\r
+@@Fix: ; otherwise\r
+ xor ax,ax ; return 0\r
+@@Done:\r
+ pop bp ;restore caller's stack frame\r
+ ret\r
+_f_close endp\r
+\r
+\r
+;****************************************************************\r
+;\r
+; name: f_read\r
+;\r
+; C Prototype:\r
+;\r
+; extern int f_read(int handle, char *buffer, int count)\r
+;\r
+; Reads a block of count bytes from the file specified by the handle\r
+; into the buffer\r
+;\r
+; Returns count on success, failure is detectable via _file_err\r
+;\r
+proc _f_read\r
+IFNDEF s\r
+ ARG handle:word,buffer:dword,count:word\r
+ELSE\r
+ ARG handle:word,buffer:word,count:word\r
+ENDIF\r
+ push bp ; Preserve caller's stack frame\r
+ mov bp,sp\r
+ PUSH_DS\r
+\r
+ mov [_file_err],0 ; Clear error\r
+ mov ah,3fh ; select "read from file or device" DOS service\r
+ mov bx,[handle] ; select handle of file to close\r
+ mov cx,[count]\r
+ LDS_M dx,[buffer]\r
+ int 21h ; call DOS service\r
+ jnb @@Done ; failed if carry flag set\r
+ mov [_file_err],ax\r
+ xor ax,ax ; return error\r
+ jmp short @@Done\r
+@@Done:\r
+ POP_DS\r
+ pop bp ;restore caller's stack frame\r
+ ret\r
+_f_read endp\r
+\r
+;****************************************************************\r
+;\r
+; name: f_write\r
+;\r
+; C Prototype:\r
+;\r
+; extern int f_write(int handle, char *buffer, int count)\r
+;\r
+; Writes a block of count bytes to the file specified by the handle\r
+; from the buffer\r
+;\r
+; Returns count on success, error is indicated by _file_err iff count = 0\r
+;\r
+proc _f_write\r
+IFNDEF s\r
+ ARG handle:word,buffer:dword,count:word\r
+ELSE\r
+ ARG handle:word,buffer:word,count:word\r
+ENDIF\r
+ push bp ; Preserve caller's stack frame\r
+ mov bp,sp\r
+ PUSH_DS\r
+\r
+ mov [_file_err],0 ; Clear error\r
+ mov ah,40h ; select "write to file or device" DOS service\r
+ mov bx,[handle] ; select handle of file to write\r
+ mov cx,[count]\r
+ LDS_M dx,[buffer]\r
+ int 21h ; call DOS service\r
+ jnb @@Done ; has the function failed ?\r
+ mov [_file_err],ax\r
+ xor ax,ax ; yes, return error\r
+ jmp short @@Done\r
+@@Done: ; otherwise return bytes written\r
+ POP_DS\r
+ pop bp ; restore caller's stack frame\r
+ ret\r
+_f_write endp\r
+\r
+;****************************************************************\r
+;\r
+; name: f_readfar\r
+;\r
+; C Prototype:\r
+;\r
+; extern int f_readfar(int handle, char far * buffer, int count)\r
+;\r
+; Reads a block of count bytes from the file specified by the handle\r
+; into the buffer\r
+;\r
+; Returns count on success, failure is detectable via _file_err\r
+;\r
+proc _f_readfar\r
+ARG handle:word,buffer:dword,count:word\r
+ push bp ; Preserve caller's stack frame\r
+ mov bp,sp\r
+ push ds\r
+\r
+ mov [_file_err],0 ; Clear error\r
+ mov ah,3fh ; select "read from file or device" DOS service\r
+ mov bx,[handle] ; select handle of file to close\r
+ mov cx,[count]\r
+ lds dx,[buffer]\r
+ int 21h ; call DOS service\r
+ jnb @@Done ; failed if carry flag set\r
+ mov [_file_err],ax\r
+ xor ax,ax ; return error\r
+ jmp short @@Done\r
+@@Done:\r
+ pop ds\r
+ pop bp ;restore caller's stack frame\r
+ ret\r
+_f_readfar endp\r
+\r
+;****************************************************************\r
+;\r
+; name: f_writefar\r
+;\r
+; C Prototype:\r
+;\r
+; extern int f_writefar(int handle, char far * buffer, int count)\r
+;\r
+; Writes a block of count bytes to the file specified by the handle\r
+; from the buffer\r
+;\r
+; Returns count on success, error is indicated by _file_err iff count = 0\r
+;\r
+proc _f_writefar\r
+ARG handle:word,buffer:dword,count:word\r
+ push bp ; Preserve caller's stack frame\r
+ mov bp,sp\r
+ push ds\r
+\r
+ mov [_file_err],0 ; Clear error\r
+ mov ah,40h ; select "write to file or device" DOS service\r
+ mov bx,[handle] ; select handle of file to write\r
+ mov cx,[count]\r
+ lds dx,[buffer]\r
+ int 21h ; call DOS service\r
+ jnb @@Done ; has the function failed ?\r
+ mov [_file_err],ax\r
+ xor ax,ax ; yes, return error\r
+ jmp short @@Done\r
+@@Done: ; otherwise return bytes written\r
+ pop ds\r
+ pop bp ; restore caller's stack frame\r
+ ret\r
+_f_writefar endp\r
+\r
+\r
+\r
+;****************************************************************\r
+;\r
+; name: f_seek\r
+;\r
+; C Prototype:\r
+;\r
+; extern long int f_seek(int handle, long int position, char method_code)\r
+;\r
+; Moves the file pointer according to the position and method code\r
+;\r
+; Returns file pointer position on success, -1 on failure\r
+;\r
+proc _f_seek\r
+ARG handle:word,position:dword,method_code:byte\r
+ push bp ; Preserve caller's stack frame\r
+ mov bp,sp\r
+\r
+ mov [_file_err],0 ; Clear error\r
+ mov ah,42h ; select "move file pointer" DOS service\r
+ mov bx,[handle] ; select handle of file to close\r
+ mov al,[method_code]\r
+ mov cx,word ptr [position+2]\r
+ mov dx,word ptr [position]\r
+ int 21h ; call DOS service\r
+ jnb @@Done ; has the function failed ?\r
+ mov [_file_err],ax\r
+ mov ax,-1 ; yes, return error\r
+ mov dx,-1 ;\r
+ jmp short @@Done\r
+@@Done: ; otherwise return bytes written\r
+ pop bp ; restore caller's stack frame\r
+ ret\r
+_f_seek endp\r
+\r
+;****************************************************************\r
+;\r
+; name: f_tell\r
+;\r
+; C Prototype:\r
+;\r
+; extern long int f_tell(int handle)\r
+;\r
+; Returns file pointer position on success, -1 on failure\r
+;\r
+proc _f_tell\r
+ARG handle:word,position:dword,method_code:byte\r
+ push bp ; Preserve caller's stack frame\r
+ mov bp,sp\r
+\r
+ mov [_file_err],0 ; Clear error\r
+ mov ah,42h ; select "move file pointer" DOS service\r
+ mov bx,[handle] ; select handle of file to close\r
+ xor dx,dx\r
+ mov cx,dx\r
+ int 21h\r
+ jnb @@Done\r
+ mov [_file_err],ax\r
+ mov ax,-1 ; yes, return error\r
+ mov dx,-1 ;\r
+ jmp short @@Done\r
+@@Done: ; otherwise return bytes written\r
+ pop bp ; restore caller's stack frame\r
+ ret\r
+_f_tell endp\r
+\r
+\r
+;****************************************************************\r
+;\r
+; name: f_filelength\r
+;\r
+; C Prototype:\r
+;\r
+; extern long int f_filelength(int handle)\r
+;\r
+; Returns the length of the file associated with the specified handle\r
+;\r
+; Returns file length on success, -1 on failure\r
+;\r
+proc _f_filelength\r
+ARG handle:word\r
+LOCAL low:word,high:word=LocalStk\r
+ push bp ; Preserve caller's stack frame\r
+ mov bp,sp\r
+ sub sp,LocalStk\r
+\r
+ mov [_file_err],0 ; Clear error\r
+\r
+ ; Get ptr's current location in file and save it\r
+\r
+ mov ah,42h ; select "move file pointer" DOS service\r
+ mov al,1 ; select "from current location" method\r
+ mov bx,[handle] ; select handle of file to close\r
+ xor cx,cx\r
+ xor dx,dx\r
+ int 21h\r
+ jb @@Error\r
+ mov [low],ax\r
+ mov [high],dx\r
+\r
+ ; Get ptr's value at end of file\r
+\r
+ mov ah,42h ; select "move file pointer" DOS service\r
+ mov al,2 ; select "from end of file" method\r
+ mov bx,[handle] ; select handle of file to close\r
+ xor cx,cx\r
+ xor dx,dx\r
+ int 21h\r
+ jb @@Error\r
+\r
+ ; Save the results while returning pointer to its previous location\r
+\r
+ push ax\r
+ push dx\r
+\r
+ mov ah,42h ; select "move file pointer" DOS service\r
+ mov al,0 ; select "from start of file" method\r
+ mov bx,[handle] ; select handle of file to close\r
+ mov cx,[high]\r
+ mov dx,[low]\r
+ int 21h\r
+\r
+ ; restore resultant length\r
+\r
+ pop dx\r
+ pop ax\r
+\r
+ jnb @@Done ; Was the operation a success ?\r
+@@Error:\r
+ mov [_file_err],ax\r
+ mov ax,-1 ; no, return error\r
+ mov dx,-1 ;\r
+@@Done: ; otherwise return bytes written\r
+ mov sp,bp\r
+ pop bp ; restore caller's stack frame\r
+ ret\r
+_f_filelength endp\r
+\r
+\r
+ end\r
+\r
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XFILEIO - header file\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;-----------------------------------------------------------------------*/\r
+\r
+#ifndef _XFILEIO_H_\r
+#define _XFILEIO_H_\r
+\r
+#define F_RDONLY 0\r
+#define F_WRONLY 1\r
+#define F_RDWR 2\r
+\r
+#define SEEK_START 0\r
+#define SEEK_CURR 1\r
+#define SEEK_END 2\r
+\r
+#define FILE_ERR -1\r
+\r
+#define FIO_INVALID_METHOD 1\r
+#define FIO_FILE_NOT_FOUND 2\r
+#define FIO_PATH_NOT_FOUND 3\r
+#define FIO_HANDLE_UNAVAIL 4\r
+#define FIO_ACCESS_DENIED 5\r
+#define FIO_INVALID_HANDLE 6\r
+\r
+extern int file_err;\r
+\r
+/* FUNCTIONS =========================================================== */\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+\r
+ int f_open( /* Open a file returning its handle */\r
+ char * filename,\r
+ char access);\r
+\r
+ int f_close( /* Close a file */\r
+ int handle);\r
+\r
+ int f_read( /* Read a block of data from a file */\r
+ int handle,\r
+ char * buffer,\r
+ int count);\r
+\r
+ int f_write( /* Write a block of data to a file */\r
+ int handle,\r
+ char * buffer,\r
+ int count);\r
+\r
+ int f_readfar( /* Read a block of data from a file */\r
+ int handle,\r
+ char far * buffer,\r
+ int count);\r
+\r
+ int f_writefar( /* Write a block of data to a file */\r
+ int handle,\r
+ char far * buffer,\r
+ int count);\r
+\r
+ long int f_seek( /* Position the file pointer */\r
+ int handle,\r
+ long int position,\r
+ char method_code);\r
+\r
+ long int f_tell( /* return position the file pointer */\r
+ int handle);\r
+\r
+ long int f_filelength( /* Return the length of the file */\r
+ int handle);\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XFILEIO - Include file\r
+;\r
+; XFILEIO.ASM export functions\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+ global _f_open :proc\r
+ global _f_close :proc\r
+ global _f_read :proc\r
+ global _f_write :proc\r
+ global _f_readfar :proc\r
+ global _f_writefar :proc\r
+ global _f_seek :proc\r
+ global _f_tell :proc\r
+ global _f_filelength :proc\r
+\r
+ global _file_err :word
\ No newline at end of file
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XFILL\r
+;\r
+; Point functions all MODE X 256 Color resolutions\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+COMMENT $\r
+\r
+ This code is my interpretation of a simple "C" flood filling algorithm\r
+ titled:\r
+\r
+ * A Seed Fill Algorithm\r
+ * by Paul Heckbert\r
+ * from "Graphics Gems", Academic Press, 1990\r
+\r
+ The original C source is readily available at numerous internet archive\r
+ sites.\r
+\r
+ Its been modified and optimized for tweaked 13h modes (Mode X derrivatives).\r
+ The most fundamental change is that it fills a column at a time rather\r
+ than a row at a time to minimize the number of plane setting "out"s.\r
+ And of course the border fill variant was a logical and useful further\r
+ modification.\r
+\r
+ Both functions return the number of pixels filled..\r
+\r
+ WARNING: These fill functions make heavy use of the stack and no stack\r
+ checking is performed, so caution is advised.\r
+\r
+$\r
+\r
+\r
+include xlib.inc\r
+include xfill.inc\r
+\r
+ .code\r
+\r
+_x_flood_fill proc\r
+ ARG X:word,Y:word,PgOfs:word,Color:word\r
+ LOCAL len:word,y1:word,y2:word,deltax:word,floodval:word,\\r
+ stackptr:word,FillCount:word=STK\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,STK\r
+ mov [FillCount],0\r
+ push di si\r
+ mov si,[Y]\r
+ mov ax,[_ScrnLogicalByteWidth]\r
+ mul si ;offset of pixel's scan line in page\r
+ mov di,[X]\r
+ mov bx,di\r
+ shr di,2 ;X/4 = offset of pixel in scan line\r
+ add di,ax ;offset of pixel in page\r
+ add di,[PgOfs] ;offset of pixel in display memory\r
+ mov ax,SCREEN_SEG\r
+ mov es,ax ;point ES:DI to the pixel's address\r
+\r
+ ;---- Select read plane ------\r
+\r
+ mov ah,bl\r
+ and ah,011b ;AH = pixel's plane\r
+ mov al,READ_MAP ;AL = index in GC of the Read Map reg\r
+ mov dx,GC_INDEX ;set the Read Map to read the pixel's\r
+ out dx,ax ; plane\r
+\r
+ mov al,es:[di] ;read the pixel's color\r
+ cmp al,byte ptr Color ;Is dest pixel the same color as the flood?\r
+ je @@Done2 ; if it is abort.\r
+\r
+ mov cx,_LeftClip ; Is the dest. pixel out of the clipping window?\r
+ sal cx,2 ; if not abort.\r
+ cmp bx,cx\r
+ jl @@Done2\r
+\r
+ mov cx,_RightClip\r
+ sal cx,2\r
+ cmp bx,cx\r
+ jg @@Done2\r
+\r
+ mov floodval,ax ; store the color to flood\r
+\r
+ ;-- Push fill segment ---\r
+\r
+ push bx ; X\r
+ push si ; Y\r
+ push si ; Y\r
+ mov cx,1 ; deltaX (either 1 or -1 indicating direction)\r
+ push cx\r
+ mov stackptr,1\r
+\r
+ mov deltax,-1 ; Initialize first column scan\r
+ mov y1,si ; then bypass some of the preliminary crap in\r
+ mov y2,si ; the main fill loop\r
+ jmp short @@entry\r
+\r
+@@Done2:mov ax,[FillCount]\r
+ pop si di\r
+ mov sp,bp\r
+ pop bp\r
+ ret\r
+\r
+@@NextScanCol:\r
+ dec stackptr\r
+ js @@Done2\r
+\r
+@@WhileLoop:\r
+ pop cx ; get fill segment from stack\r
+ mov deltax,cx ; ie deltaX, Y1, Y2, X\r
+ pop ax\r
+ mov y2,ax\r
+ pop si\r
+ mov y1,si\r
+ pop bx\r
+\r
+ sub ax,si ; Acculmulate number of filled pixels\r
+ jns @@PositiveY\r
+ neg ax\r
+@@PositiveY:\r
+ add FillCount,ax\r
+\r
+\r
+ add bx,cx ; move to new column according to deltaX\r
+\r
+ mov ax,bx ; Make sure the column is within the clipping\r
+ sar ax,2 ; rectangle\r
+ cmp ax,_LeftClip\r
+ jl @@NextScanCol\r
+\r
+ cmp ax,_RightClip\r
+ jg @@NextScanCol\r
+\r
+\r
+ ;---- Select read plane ------\r
+\r
+ mov ah,bl\r
+ and ah,011b ;AH = pixel's plane\r
+ mov al,READ_MAP ;AL = index in GC of the Read Map reg\r
+ mov dx,GC_INDEX ;set the Read Map to read the pixel's\r
+ out dx,ax ; plane\r
+\r
+@@entry:\r
+\r
+ ;---- Select write plane ------\r
+\r
+ mov cl,bl\r
+ and cl,011b ;CL = pixel's plane\r
+ mov ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg\r
+ shl ah,cl ;set only the bit for the pixel's\r
+ ; plane to 1\r
+ mov dx,SC_INDEX ;set the Map Mask to enable only the\r
+ out dx,ax ; pixel's plane\r
+\r
+ mov ax,_ScrnLogicalByteWidth ; store logical width in CX\r
+ mov cx,ax ; get offset of scan row\r
+ mul si ; set ES:DI ->\r
+ mov di,bx ; address of pixel at x,y1\r
+ shr di,2\r
+ add di,ax\r
+ add di,PgOfs ;ES:DI->first pixel of column segment to fill\r
+ mov dx,di ; save y1 offset for after upward fill\r
+\r
+ mov al,byte ptr Color\r
+ mov ah,byte ptr floodval\r
+\r
+@@FillColUpward:\r
+ cmp si,_TopClip ; Dont fill beyond clip boundaries\r
+ jl @@UpwardFillDone\r
+\r
+ cmp es:[di],ah ; if flood pixel color then replace\r
+ jne @@UpwardFillDone ; with new color otherwise column is done\r
+\r
+ mov es:[di],al\r
+ sub di,cx\r
+ dec si\r
+ jmp short @@FillColUpward\r
+\r
+@@UpwardFillDone:\r
+ cmp si,y1\r
+ jge @@Skip\r
+\r
+ inc si\r
+ mov len,si\r
+\r
+ cmp si,y1\r
+ jge @@AtColumnTop\r
+\r
+ push bx ; queue an upward leak check\r
+ push si\r
+ mov ax,y1\r
+ dec ax\r
+ push ax\r
+ mov ax,deltax\r
+ neg ax\r
+ push ax\r
+ inc stackptr\r
+\r
+@@AtColumnTop:\r
+ mov si,y1\r
+ mov di,dx\r
+ add di,cx\r
+ inc si\r
+\r
+\r
+@@ColumnLoop:\r
+ mov ah,byte ptr floodval\r
+ mov al,byte ptr Color\r
+\r
+@@DownwardFill:\r
+ cmp si,_BottomClip\r
+ jg @@DownwardFillDone\r
+ cmp es:[di],ah\r
+ jne @@DownwardFillDone\r
+ mov es:[di],al\r
+ add di,cx\r
+ inc si\r
+ jmp short @@DownwardFill\r
+\r
+@@DownwardFillDone:\r
+\r
+ push bx ; queue an upward leak check\r
+ mov ax,len\r
+ push ax\r
+ mov ax,si\r
+ dec ax\r
+ push ax\r
+ mov ax,deltax\r
+ push ax\r
+ inc stackptr\r
+\r
+ mov ax,y2\r
+ inc ax\r
+ cmp si,ax\r
+ jle @@Skip\r
+\r
+ push bx ; queue a downward leak check\r
+ push ax\r
+ mov ax,si\r
+ dec ax\r
+ push ax\r
+ mov ax,deltax\r
+ neg ax\r
+ push ax\r
+ inc stackptr\r
+\r
+@@Skip:\r
+ mov ah,byte ptr floodval\r
+ mov dx,y2\r
+\r
+@@Backtrack:\r
+ add di,cx\r
+ inc si\r
+ cmp si,dx\r
+ jg @@BacktrackDone\r
+\r
+ cmp byte ptr es:[di],ah\r
+ jne @@Backtrack\r
+\r
+@@BacktrackDone:\r
+ mov len,si\r
+ cmp si,dx\r
+ jle @@ColumnLoop\r
+\r
+ dec stackptr\r
+ js @@Done\r
+ jmp @@WhileLoop\r
+@@Done:\r
+ mov ax,[FillCount]\r
+ pop si di\r
+ mov sp,bp\r
+ pop bp\r
+ ret\r
+_x_flood_fill endp\r
+\r
+\r
+_x_boundary_fill proc\r
+ ARG X:word,Y:word,PgOfs:word,BoundaryColor:word,Color:word\r
+ LOCAL len:word,y1:word,y2:word,deltax:word,y1_offs:word,\\r
+ stackptr:word,FillCount:word=STK\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,STK\r
+ mov [FillCount],0\r
+ push di si\r
+ mov si,[Y]\r
+ mov ax,[_ScrnLogicalByteWidth]\r
+ mul si ;offset of pixel's scan line in page\r
+ mov di,[X]\r
+ mov bx,di\r
+ shr di,2 ;X/4 = offset of pixel in scan line\r
+ add di,ax ;offset of pixel in page\r
+ add di,[PgOfs] ;offset of pixel in display memory\r
+ mov ax,SCREEN_SEG\r
+ mov es,ax ;point ES:DI to the pixel's address\r
+\r
+ ;---- Select read plane ------\r
+\r
+ mov ah,bl\r
+ and ah,011b ;AH = pixel's plane\r
+ mov al,READ_MAP ;AL = index in GC of the Read Map reg\r
+ mov dx,GC_INDEX ;set the Read Map to read the pixel's\r
+ out dx,ax ; plane\r
+\r
+ mov al,es:[di] ;read the pixel's color\r
+ cmp al,byte ptr Color ;Is dest pixel the same color as the flood?\r
+ je @@Done2\r
+\r
+ cmp al,byte ptr BoundaryColor ;Is dest pixel the same color\r
+ je @@Done2 ; as the boundary color?\r
+\r
+\r
+ mov cx,_LeftClip ; Is the dest. pixel out of the clipping window?\r
+ sal cx,2\r
+ cmp bx,cx\r
+ jl @@Done2\r
+\r
+ mov cx,_RightClip\r
+ sal cx,2\r
+ cmp bx,cx\r
+ jg @@Done2\r
+\r
+ push bx ; X\r
+ push si ; Y\r
+ push si ; Y\r
+ mov cx,1 ; DX\r
+ push cx\r
+ mov stackptr,1\r
+ mov al,byte ptr BoundaryColor\r
+ mov byte ptr [Color+1],al\r
+\r
+ mov deltax,-1\r
+ mov y1,si\r
+ mov y2,si\r
+ jmp short @@entry\r
+\r
+@@Done2:mov ax,[FillCount]\r
+ pop si di\r
+ mov sp,bp\r
+ pop bp\r
+ ret\r
+\r
+@@NextScanCol:\r
+ dec stackptr\r
+ js @@Done2\r
+\r
+@@WhileLoop:\r
+ pop cx\r
+ mov deltax,cx\r
+ pop ax\r
+ mov y2,ax\r
+ pop si\r
+ mov y1,si\r
+ pop bx\r
+ add bx,cx ; bx = X\r
+\r
+ sub ax,si ; Acculmulate number of filled pixels\r
+ jns @@PositiveY\r
+ neg ax\r
+@@PositiveY:\r
+ add FillCount,ax\r
+\r
+\r
+\r
+ mov ax,bx ; Make sure the column is within the clipping\r
+ sar ax,2 ; rectangle\r
+ cmp ax,_LeftClip\r
+ jl @@NextScanCol\r
+ cmp ax,_RightClip\r
+ jg @@NextScanCol\r
+\r
+\r
+ ;---- Select read plane ------\r
+\r
+ mov ah,bl\r
+ and ah,011b ;AH = pixel's plane\r
+ mov al,READ_MAP ;AL = index in GC of the Read Map reg\r
+ mov dx,GC_INDEX ;set the Read Map to read the pixel's\r
+ out dx,ax ; plane\r
+\r
+@@entry:\r
+\r
+ ;---- Select write plane ------\r
+\r
+ mov cl,bl\r
+ and cl,011b ;CL = pixel's plane\r
+ mov ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg\r
+ shl ah,cl ;set only the bit for the pixel's\r
+ ; plane to 1\r
+ mov dx,SC_INDEX ;set the Map Mask to enable only the\r
+ out dx,ax ; pixel's plane\r
+\r
+ mov ax,_ScrnLogicalByteWidth ; store logical width in CX\r
+ mov cx,ax ; get offset of scan row\r
+ mul si ; set ES:DI ->\r
+ mov di,bx ; address of pixel at x,y1\r
+ shr di,2\r
+ add di,ax\r
+ add di,PgOfs\r
+ mov y1_offs,di ; save y1 offset for after upward fill\r
+\r
+ mov ax,Color ; al = Color ah = BoundaryColor\r
+\r
+@@FillColUpward:\r
+ cmp si,_TopClip ; Dont fill beyond clip boundaries\r
+ jl @@UpwardFillDone\r
+\r
+ mov dl,es:[di]\r
+ cmp dl,ah\r
+ je @@UpwardFillDone\r
+\r
+ cmp dl,al\r
+ je @@UpwardFillDone\r
+\r
+ mov es:[di],al\r
+ sub di,cx\r
+ dec si\r
+ jmp short @@FillColUpward\r
+\r
+@@UpwardFillDone:\r
+ cmp si,y1\r
+ jge @@Skip\r
+\r
+ inc si\r
+ mov len,si\r
+\r
+ cmp si,y1\r
+ jge @@AtColumnTop\r
+\r
+ push bx ; queue an upward leak check\r
+ push si\r
+ mov ax,y1\r
+ dec ax\r
+ push ax\r
+ mov ax,deltax\r
+ neg ax\r
+ push ax\r
+ inc stackptr\r
+\r
+@@AtColumnTop:\r
+ mov si,y1\r
+ mov di,y1_offs\r
+ add di,cx\r
+ inc si\r
+\r
+\r
+@@ColumnLoop:\r
+ mov ax,Color ; al = Color ah = BoundaryColor\r
+\r
+@@DownwardFill:\r
+ cmp si,_BottomClip\r
+ jg @@DownwardFillDone\r
+\r
+ cmp es:[di],ah\r
+ je @@DownwardFillDone\r
+\r
+ cmp es:[di],al\r
+ je @@DownwardFillDone\r
+\r
+ mov es:[di],al\r
+ add di,cx\r
+ inc si\r
+ jmp short @@DownwardFill\r
+\r
+@@DownwardFillDone:\r
+\r
+ push bx ; queue an upward leak check\r
+ mov ax,len\r
+ push ax\r
+ mov ax,si\r
+ dec ax\r
+ push ax\r
+ mov ax,deltax\r
+ push ax\r
+ inc stackptr\r
+\r
+ mov ax,y2\r
+ inc ax\r
+ cmp si,ax\r
+ jle @@Skip\r
+\r
+ push bx ; queue a downward leak check\r
+ push ax\r
+ mov ax,si\r
+ dec ax\r
+ push ax\r
+ mov ax,deltax\r
+ neg ax\r
+ push ax\r
+ inc stackptr\r
+\r
+@@Skip:\r
+ mov ax,Color ; al = Color ah = BoundaryColor\r
+\r
+@@Backtrack:\r
+ add di,cx\r
+ inc si\r
+ cmp si,y2\r
+ jg @@BacktrackDone\r
+\r
+ mov dl,byte ptr es:[di]\r
+ cmp dl,al\r
+ je @@Backtrack\r
+\r
+ cmp dl,ah\r
+ je @@Backtrack\r
+\r
+@@BacktrackDone:\r
+ mov len,si\r
+ cmp si,y2\r
+ jle @@ColumnLoop\r
+\r
+ dec stackptr\r
+ js @@Done\r
+ jmp @@WhileLoop\r
+@@Done:\r
+ mov ax,[FillCount]\r
+ pop si di\r
+ mov sp,bp\r
+ pop bp\r
+ ret\r
+_x_boundary_fill endp\r
+\r
+end\r
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XFILL - header file\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;----------------------------------------------------------------------*/\r
+\r
+#ifndef _XFILL_H_\r
+#define _XFILL_H_\r
+\r
+\r
+/* FUNCTIONS =========================================================== */\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+int x_flood_fill(int x,\r
+ int y,\r
+ unsigned ofs,\r
+ int color\r
+ );\r
+\r
+int x_boundary_fill(int x,\r
+ int y,\r
+ unsigned ofs,\r
+ int boundary,\r
+ int color\r
+ );\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+global _x_flood_fill:proc\r
+global _x_boundary_fill:proc
\ No newline at end of file
--- /dev/null
+/*----------------------------------------------------------------------\r
+;\r
+; XLIB - header file\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; Header file contributed by Darren Lyon (darren@nicky.DIALix.oz.au)\r
+;\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;----------------------------------------------------------------------*/\r
+\r
+#ifndef _XLIB_H_\r
+#define _XLIB_H_\r
+\r
+#define BYTE unsigned char\r
+#define WORD unsigned int\r
+\r
+\r
+#define X_MODE_320x200 0\r
+#define X_MODE_320x240 1\r
+#define X_MODE_360x200 2\r
+#define X_MODE_360x240 3\r
+#define X_MODE_376x282 4\r
+#define X_MODE_320x400 5\r
+#define X_MODE_320x480 6\r
+#define X_MODE_360x400 7\r
+#define X_MODE_360x480 8\r
+#define X_MODE_360x360 9\r
+#define X_MODE_376x308 10\r
+#define X_MODE_376x564 11\r
+#define X_MODE_256x400 12\r
+#define X_MODE_256x480 13\r
+\r
+\r
+#define BACKWARD 0\r
+#define FORWARD 1\r
+\r
+#define X_MODE_INVALID -1\r
+#define ERROR 1\r
+#define OK 0\r
+\r
+/* FUNCTIONS =========================================================== */\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+ WORD x_set_mode(\r
+ WORD mode, /* Initialize x mode */\r
+ WORD WidthInPixels);\r
+\r
+ void x_select_default_plane( /*Enables Read/Write access to a */\r
+ BYTE plane); /* a specified plane */\r
+\r
+ void x_set_splitscreen( /* set the split screen start */\r
+ WORD line); /*scan line (initialize) */\r
+\r
+ void x_set_start_addr(\r
+ WORD X, /* Set the screen start */\r
+ WORD Y); /* address in video ram */\r
+\r
+ void x_hide_splitscreen(void); /* Disable the split screen (Split */\r
+ /* Screen RAM remains reserved) */\r
+\r
+ void x_show_splitscreen(void); /* Enable the split screen (given it */\r
+ /* was previously "hidden") */\r
+\r
+\r
+ void x_adjust_splitscreen( /* Adjust the start scan line of the */\r
+ WORD line); /* split screen */\r
+\r
+\r
+ WORD x_set_doublebuffer( /* Enable double buffering with a */\r
+ WORD PageHeight); /* specified page height */\r
+\r
+ WORD x_set_tripplebuffer( /* Enable tripple buffering with a */\r
+ WORD PageHeight); /* specified page height */\r
+\r
+\r
+ void x_page_flip( /* Swap visible page (only when double */\r
+ WORD X, /* buffering is active) & sets virt start*/\r
+ WORD Y);\r
+\r
+ void x_set_cliprect( /* Define the clipping rectangle */\r
+ WORD left, /* NOTE: left and right are in bytes */\r
+ WORD top,\r
+ WORD righ,\r
+ WORD bottom);\r
+\r
+ void x_text_mode(void); /* return to text mode */\r
+ void x_wait_vsync(void); /* wait for vsync */\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+/* VARIABLES =========================================================== */\r
+\r
+extern BYTE InGraphics; /* non zero if in X graphics mode */\r
+extern WORD CurrXMode; /* contains current X graphics mode id */\r
+extern WORD ScrnPhysicalByteWidth; /* Physical screen width in bytes */\r
+extern WORD ScrnPhysicalPixelWidth; /* Physical screen width in pixels */\r
+extern WORD ScrnPhysicalHeight; /* Physical screen height in pixels */\r
+extern WORD ErrorValue; /* Error return value */\r
+extern WORD SplitScrnOffs; /* Offset in VRAM of split screen */\r
+extern WORD SplitScrnScanLine; /* Scan line split screen starts at */\r
+ /* initially. Resizing the split scrn */\r
+ /* using the other functions does not */\r
+ /* change this value */\r
+extern WORD SplitScrnVisibleHeight; /* Height of the visible portion of the*/\r
+ /* split screen. */\r
+extern WORD Page0_Offs; /* Offset in VRAM of main virt. screen */\r
+extern WORD Page1_Offs; /* Offset in VRAM of 2nd virt. screen */\r
+extern WORD Page2_Offs; /* Offset in VRAM of 3rd virt. screen */\r
+extern WORD ScrnLogicalByteWidth; /* Virtual screen width in bytes */\r
+extern WORD ScrnLogicalPixelWidth; /* Virtual screen width in pixels */\r
+extern WORD ScrnLogicalHeight; /* Virtual screen height in pixels */\r
+extern WORD MaxScrollX; /* Max X position of physical screen */\r
+ /* within virtual screen */\r
+extern WORD MaxScrollY; /* Max Y position of physical screen */\r
+ /* within virtual screen */\r
+extern WORD DoubleBufferActive; /* Indicates whether double buffering */\r
+ /* is active */\r
+extern WORD TrippleBufferActive; /* Indicates whether tripple */\r
+ /* buffering is active */\r
+extern WORD VisiblePageIdx; /* Index number of visible page 0 or 1 */\r
+extern WORD HiddenPageOffs; /* Offset of Hidden Pg | only valid */\r
+extern WORD VisiblePageOffs; /* Offset of Visible Pg| for D.B. mode */\r
+extern WORD WaitingPageOffs; /* Offset of Waiting Pg| for T.B. mode */\r
+extern WORD NonVisual_Offs; /* Offset of first non-visible VRAM */\r
+\r
+extern WORD StartAddressFlag;\r
+\r
+extern WORD TopClip; /* Clipping rectangle */\r
+extern WORD BottomClip;\r
+extern WORD LeftClip;\r
+extern WORD RightClip;\r
+\r
+extern WORD PhysicalStartPixelX; /* Coordinates of physical (visible) */\r
+extern WORD PhysicalStartByteX; /* screen relative to the virtual */\r
+extern WORD PhysicalStartY; /* screen's U.L. corner */\r
+\r
+extern char* VsyncPaletteBuffer;\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XLIB - Include file\r
+;\r
+; Global equates and variables\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; MODIFICATIONS:\r
+; 26-9-92 : Pel panning code added\r
+; 23-10-92: Added clip rectangle code\r
+;-----------------------------------------------------------------------\r
+\r
+;\r
+\r
+LOCALS\r
+.286\r
+\r
+; First lets find out what memory model to use\r
+\r
+include model.inc\r
+\r
+\r
+AC_INDEX equ 03c0h ;Attribute controller index register\r
+MISC_OUTPUT equ 03c2h ;Miscellaneous Output register\r
+SC_INDEX equ 03c4h ;Sequence Controller Index\r
+GC_INDEX equ 03ceh ; Graphics controller Index\r
+CRTC_INDEX equ 03d4h ;CRT Controller Index\r
+DAC_READ_INDEX equ 03c7h ;\r
+DAC_WRITE_INDEX equ 03c8h ;\r
+DAC_DATA equ 03c9h ;\r
+INPUT_STATUS_0 equ 03dah ;Input status 0 register\r
+\r
+\r
+SCREEN_SEG equ 0a000h ;segment of display memory in mode X\r
+\r
+MAP_MASK equ 02h ;index in SC of Map Mask register\r
+READ_MAP equ 04h ;index in GC of the Read Map register\r
+BIT_MASK equ 08h ;index in GC of Bit Mask register\r
+\r
+OVERFLOW equ 07h ; CRTC overflow register index\r
+MAX_SCAN_LINE equ 09h ; CRTC maximum scan line register index\r
+ADDR_HIGH equ 0ch ;Index of Start Address High reg in CRTC\r
+ADDR_LOW equ 0dh ; Low\r
+CRTC_OFFSET equ 13h ; CRTC offset register index\r
+UNDERLINE equ 14h ; CRTC underline location register index\r
+MODE_CONTROL equ 17h ; CRTC mode control register index\r
+LINE_COMPARE equ 18h ; CRTC line compare reg. index (bits 0-7 of\r
+ ; split screen scan line\r
+\r
+AC_MODE_CONTROL equ 10h ; Index of Mode COntrol register in AC\r
+PEL_PANNING equ 13h ; Pel panning register index in AC\r
+\r
+PATTERN_BUFFER equ 0fffch ;offset in screen memory of pattern buffer\r
+\r
+TRUE equ 1\r
+FALSE equ 0\r
+\r
+\r
+OK equ 0\r
+ERROR equ 1\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; Macro to wait for the vertical retrace leading edge\r
+\r
+WaitVsyncStart macro\r
+ LOCAL WaitNotVsync,WaitVsync\r
+ mov dx,INPUT_STATUS_0\r
+WaitNotVsync:\r
+ in al,dx\r
+ test al,08h\r
+ jnz WaitNotVsync\r
+WaitVsync:\r
+ in al,dx\r
+ test al,08h\r
+ jz WaitVsync\r
+ endm\r
+\r
+;-----------------------------------------------------------------------\r
+; Macro to wait for the vertical retrace trailing edge\r
+\r
+WaitVsyncEnd macro\r
+ LOCAL WaitNotVsync,WaitVsync\r
+ mov dx,INPUT_STATUS_0\r
+WaitVsync2:\r
+ in al,dx\r
+ test al,08h\r
+ jz WaitVsync2\r
+WaitNotVsync2:\r
+ in al,dx\r
+ test al,08h\r
+ jnz WaitNotVsync2\r
+ endm\r
+\r
+;--- Word out macro ------------------------------------------\r
+\r
+ WORDOUT macro\r
+ IFDEF nw\r
+ out dx,al\r
+ inc dx\r
+ xchg al,ah\r
+ out dx,al\r
+ xchg al,ah\r
+ dec dx\r
+ ELSE\r
+ out dx,al\r
+ ENDIF\r
+ endm\r
+\r
+;------------------------------------------------------------------------\r
+; Global variables - XMAIN exports\r
+;\r
+ global _InGraphics :byte\r
+ global _CurrXMode :word\r
+ global _ScrnPhysicalByteWidth :word\r
+ global _ScrnPhysicalPixelWidth :word\r
+ global _ScrnPhysicalHeight :word\r
+ global _ErrorValue :byte\r
+\r
+ global _SplitScrnOffs :word\r
+ global _SplitScrnScanLine :word\r
+ global _SplitScrnVisibleHeight :word\r
+ global _Page0_Offs :word\r
+ global _Page1_Offs :word\r
+ global _Page2_Offs :word\r
+ global _ScrnLogicalByteWidth :word\r
+ global _ScrnLogicalPixelWidth :word\r
+ global _ScrnLogicalHeight :word\r
+\r
+ global _MaxScrollX :word\r
+ global _MaxScrollY :word\r
+ global _DoubleBufferActive :word\r
+ global _TrippleBufferActive :word\r
+ global _VisiblePageIdx :word\r
+ global _VisiblePageOffs :word\r
+ global _HiddenPageOffs :word\r
+ global _WaitingPageOffs :word\r
+ global _NonVisual_Offs :word\r
+ global _TopClip :word\r
+ global _BottomClip :word\r
+ global _LeftClip :word\r
+ global _RightClip :word\r
+\r
+ global _PhysicalStartByteX :word\r
+ global _PhysicalStartPixelX :word\r
+ global _PhysicalStartY :word\r
+\r
+ global _VsyncHandlerActive :word\r
+ global _MouseRefreshFlag :word\r
+ global _MouseVsyncHandler :dword\r
+ global _StartAddressFlag :word\r
+ global _WaitingStartLow :word\r
+ global _WaitingStartHigh :word\r
+ global _WaitingPelPan :word\r
+ global _VsyncPaletteStart :word\r
+ global _VsyncPaletteCount :word\r
+ global _VsyncPaletteBuffer :byte\r
+\r
+\r
--- /dev/null
+PART 1 of 2\r
+-----------------------------------------------------------------------------\r
+\r
+ ********* XLIB - Mode X graphics library ****************\r
+ ********* ****************\r
+ ********* Written By Themie Gouthas ****************\r
+ ********* ****************\r
+ ********* egg@dstos3.dsto.gov.au ****************\r
+ ********* teg@bart.dsto.gov.au ****************\r
+\r
+ Some of the code in this library has been contributed by :\r
+\r
+ Matthew MacKenzie - matm@eng.umd.edu\r
+\r
+ and others. See individual modules.\r
+\r
+ I informally reserve all rights to the code in XLIB\r
+ Rights to contributed code is also assumed to be reserved by\r
+ the original authors.\r
+-----------------------------------------------------------------------------\r
+\r
+DISCLAIMER\r
+\r
+ This library is distributed AS IS. The author/s specifically disclaim\r
+ any responsibility for any loss of profit or any incidental, consequen-\r
+ tial or other damages.\r
+\r
+---------------------------------------------------------------------------\r
+INTRODUCTION\r
+---------------------------------------------------------------------------\r
+\r
+XLIB is a "user supported freeware" graphics library specifically designed\r
+with game programming in mind.\r
+\r
+It has been placed in the public domain for the benefit of all, and\r
+represents *MANY* hours of work so it is requested that all users comply\r
+with the the wishes of the author/s as specified in the individual modules\r
+and:\r
+a) To leave the code in the public domain\r
+b) Not distribute any modified or incomplete versions of this library\r
+\r
+New contribution and comments are welcome and hopefully there will be\r
+more releases as the code evolves.\r
+\r
+Finally, do not trust this excuse for a manual if in doubt, as this code has\r
+undergone several revisions. The place to get the answers is in the code\r
+itself.\r
+\r
+REQUIREMENTS\r
+\r
+Minimum requirements\r
+ 286 processor,\r
+ Turbo C 2.0 or higher, or BORLANDC\r
+ MAKE 2.0 or higher\r
+ TLIB 2.0 or higher\r
+ Turbo Assembler 1.01 or higher\r
+\r
+\r
+GENERAL FEATURES\r
+\r
+ Support for a number of 256 colour tweaked graphics mode resolutions\r
+ 320x200 320x240 360x200 360x240 376x282 320x400 320x480 360x400 360x480\r
+ 360x360 376x308 376x564\r
+\r
+ Please note that some of the new resolutions best suit monitors with\r
+ adjustable vertical height.\r
+\r
+ Virtual screens larger than the physical screen (memory\r
+ permitting) that can be panned at pixel resolution in all directions\r
+\r
+ A split screen capability for status displays etc.\r
+\r
+ Text functions supporting 8x8 and 8x14 ROM fonts and user defined fonts\r
+\r
+ Support for page flipping\r
+\r
+ Graphics primitives such as line and rectangle drawing functions and\r
+ of course bit block manipulation functions\r
+\r
+MODULES COMPRISING XLIB\r
+ XMAIN - Main module containig mode setting code and basic functions\r
+ XPOINT - Pixel functions\r
+ XRECT - Filled Rectangle and VRAM to VRAM block move functions\r
+ XPAL - Palette functions\r
+ XLINE - Line Functions\r
+ XTEXT - Text and Font Functions\r
+ XPRINTF - Printf style string output\r
+ XPBITMAP - Planar Bitmap functions\r
+ XCBITMAP - Compiled Bitmap functions\r
+ XVBITMAP - Video Bitmap functions\r
+ XPBMCLIP - Clipped Planar Bitmap functions\r
+ XMAKEVBM - Support module for video bitmaps\r
+ XBMTOOLS - Bitmap format conversion tools\r
+ XDETECT - Hardware detection module\r
+ XFILEIO - File I/O functions\r
+ XRLETOOL - RLE encoding/decoding functions\r
+ XMOUSE - Mouse functions\r
+ XBEZIER - Bezier curve drawing\r
+\r
+-------------------------------------------------------------------------\r
+BUILDING THE LIBRARIES\r
+-------------------------------------------------------------------------\r
+\r
+Building the library had been made simple through the use of make.\r
+\r
+To build and examples for one of the two models:\r
+\r
+a) edit the makefile for the apropriate model (see note in the makefile)\r
+b) edit the makefile for the apropriate compiler (again see note in the\r
+ makefile)\r
+c) type "make" at the dos prompt.\r
+\r
+It should be as simple as that. If problems are encountered then check\r
+to see if tasm, make, tlib, link and bcc (or tcc) are withinin your path.\r
+If not either change your path or specify the full path for these programs\r
+in the makefile. It is preferrable to have your path set correctly.\r
+\r
+Individual Compilation\r
+----------------------\r
+\r
+each ASM module can be compiled with the following commandline:\r
+\r
+tasm /ml /d<model> <asm module name>\r
+\r
+where <model> is s c or l. Where s = small model, c = compact model and\r
+l = large model.\r
+\r
+The resulting libraries are:\r
+\r
+ xlib<version>s.lib - small model library\r
+ xlib<version>c.lib - large model library\r
+ xlib<version>l.lib - large model library\r
+\r
+To link the library with your programs just include the apropriate .lib\r
+file in your project file or on the BCC or TCC command line.\r
+\r
+Using the library with your programs\r
+------------------------------------\r
+\r
+Using the XLIB library in your programs is simple. Knowing the particular\r
+modules you require, just include the associated header files in your program\r
+and link your program modules with the library. If you don't want to wory\r
+about selecting the apropriate header file then just include "XLIB_ALL.H"\r
+which automatically includes all XLIB header files in your program.\r
+\r
+For example compilations see the supplied makefile.\r
+\r
+--------------------------------------------------------------------------\r
+GLOBAL DEFINES (xlib.inc)\r
+--------------------------------------------------------------------------\r
+\r
+Types\r
+\r
+ BYTE unsigned char\r
+ WORD unsigned int\r
+\r
+Available X mode resolutions\r
+\r
+ X_MODE_320x200 0\r
+ X_MODE_320x240 1\r
+ X_MODE_360x200 2\r
+ X_MODE_360x240 3\r
+ X_MODE_360x282 4\r
+ X_MODE_320x400 5\r
+ X_MODE_320x480 6\r
+ X_MODE_360x400 7\r
+ X_MODE_360x480 8\r
+ X_MODE_360x360 9\r
+ X_MODE_376x308 10\r
+ X_MODE_376x564 11\r
+\r
+Palette rotation direction directiion\r
+\r
+ BACKWARD 0\r
+ FORWARD 1\r
+\r
+\r
+ X_MODE_INVALID -1\r
+ ERROR 1\r
+ OK 0\r
+\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XMAIN\r
+--------------------------------------------------------------------------\r
+\r
+The Xmain module is the base module of the XLIB library. It contains the\r
+essential functions that initialize and customize the graphic environment.\r
+\r
+\r
+ASM SOURCES\r
+\r
+ xmain.asm xmain.inc xlib.inc model.inc\r
+\r
+C HEADER FILE\r
+\r
+ xlib.h\r
+\r
+EXPORTED VARIABLES\r
+\r
+ NOTE: All variables are read only unless otherwise specified. If you modify\r
+ them manually, the results may be unpredictable.\r
+\r
+ InGraphics - BYTE - Flag indicating that the xlib graphics system is\r
+ active. Set by function "x_set_mode".\r
+\r
+ CurrXMode - WORD - If the xlib graphics system is active, contains the id\r
+ of the x mode. Set by function "x_set_mode".\r
+ See also defines (ie X_MODE_320x200 ... )\r
+\r
+ ScrnPhysicalByteWidth - WORD - Physical screen width in bytes. Set by\r
+ function "x_set_mode"\r
+\r
+ ScrnPhysicalPixelWidth - WORD - Physical screen width in pixels. Set by\r
+ function "x_set_mode"\r
+\r
+ ScrnPhysicalHeight - WORD - Physical screen height in pixels. Set by\r
+ function "x_set_mode".\r
+\r
+ ErrorValue - WORD - Contains error value. General use variable to\r
+ communicate the error status from several functions. The value\r
+ in this variable usually is only valid for the the last\r
+ function called that sets it.\r
+\r
+ SplitScrnOffs - WORD - Offset in video ram of split screen. Set by\r
+ function "x_set_splitscrn". The value is only valid if a split\r
+ screen is active. See also global variable "SplitScrnActive".\r
+\r
+ SplitScrnScanLine - WORD - Screen Scan Line the Split Screen starts at\r
+ initially when set by function "x_set_splitscrn". The value is only\r
+ valid if a split screen is active. See also global variable\r
+ "SplitScrnActive".This variable is not updated by "x_hide_splitscrn",\r
+ "x_adjust_splitscrn".\r
+\r
+ SplitScrnVisibleHeight - WORD - The number of rows of the initial split\r
+ screen which are currently displayed. Modified by "x_hide_splitscrn",\r
+ "x_adjust_splitscrn" and "x_show_splitscrn".\r
+\r
+ Page0_Offs - WORD - Offset in video ram of main virtual screen. Initially\r
+ set by function "x_set_mode" but is updated by functions\r
+ "x_set_splitscrn" and "x_set_doublebuffer".\r
+\r
+ Page1_Offs - WORD - Offset in video ram of second virtual screen. Set by\r
+ and only is valid after a call to "x_set_doublebuffer".\r
+\r
+ ScrnLogicalByteWidth - WORD - Virtual screen width in bytes. Set by\r
+ function "x_set_mode".\r
+\r
+ ScrnLogicalPixelWidth - WORD - Virtual screen width in pixels. Set\r
+ by function "x_set_mode".\r
+\r
+ ScrnLogicalHeight - WORD - Virtual screen height in pixels. Set\r
+ initially by function "x_set_mode" but is updated by functions\r
+ "x_set_splitscrn" and "x_set_doublebuffer".\r
+\r
+ MaxScrollX - WORD - Max X pixel position of physical screen within\r
+ virtual screen. Set by function "x_set_mode".\r
+\r
+ MaxScrollY - WORD - Max Y position of physical screen within virtual\r
+ screen. Set initially by function "x_set_mode" but is updated by\r
+ functions "x_set_splitscrn" and "x_set_doublebuffer".\r
+\r
+ DoubleBufferActive - WORD - Indicates whether double-buffering is on. Set\r
+ by function "x_set_doublebuffer".\r
+\r
+ VisiblePageIdx - WORD - Index number of current visible page. Initially\r
+ set by function "x_set_doublebuffer" but is updated by "x_page_flip".\r
+ This variable is only used while double buffering is on.\r
+\r
+ HiddenPageOffs - WORD - Offset of hidden page. Initially set by function\r
+ "x_set_doublebuffer" but is updated by "x_page_flip". This variable\r
+ is only used while double buffering is on.\r
+\r
+ VisiblePageOffs - WORD - Offset of visible page. Initially set by function\r
+ "x_set_doublebuffer" but is updated by "x_page_flip". This variable\r
+ is only used while double buffering is on.\r
+\r
+ NonVisual_Offs - WORD - Offset of first byte of non-visual ram, the ram\r
+ that is available for bitmap storage etc. Set initially by function\r
+ "x_set_mode" but is updated by functions "x_set_splitscrn" and\r
+ "x_set_doublebuffer".\r
+\r
+ TopClip, BottomClip, LeftClip RightClip - WORD - Define the clipping\r
+ rectangle for Linear and Video clipped bitmap put functions. Set\r
+ either manually or by "x_set_cliprect". Note X coordinates are in\r
+ bytes as all clip functions clip to byte boundaries.\r
+\r
+ PhysicalStartPixelX - WORD - X pixel Offset of physical (visible) screen\r
+ relative to the upper left hand corner (0,0) of the virtual screen.\r
+\r
+ PhysicalStartByteX - WORD - X byte Offset of physical (visible) screen\r
+ relative to the upper left hand corner (0,0) of the virtual screen.\r
+\r
+ PhysicalStartY - WORD - Y pixel Offset of physical (visible) screen\r
+ relative to the upper left hand corner (0,0) of the virtual screen.\r
+\r
+EXPORTED FUNCTIONS\r
+\r
+ x_set_mode\r
+ ----------\r
+ C Prototype: extern WORD x_set_mode(WORD mode,WORD WidthInPixels);\r
+\r
+ mode - The required mode as defined by the "Available X Mode\r
+ resolutions" set of defines in the xlib.h header file.\r
+ WidthInPixels - The required virtual screen width.\r
+ Returns - The actual width in pixels of the allocated virtual\r
+ screen\r
+\r
+ This function initialises the graphics system, setting the apropriate\r
+ screen resolution and allocating a virtual screen. The virtual screen\r
+ allocated may not necessarily be of the same size as specified in the\r
+ "WidthInPixels" parameter as it is rounded down to the nearest\r
+ multiple of 4.\r
+\r
+ The function returns the actual width of the allocated virtual screen\r
+ in pixels if a valid mode was selected otherwise returns\r
+ X_MODE_INVALID.\r
+\r
+ Saves virtual screen pixel width in "ScrnLogicalPixelWidth".\r
+ Saves virtual screen byte width in "ScrnLogicalByteWidth".\r
+ Physical screen dimensions are set in "ScrnPhysicalPixelWidth".\r
+ "ScrnPhysicalByteWidth" and "ScrnPhysicalHeight". Other global\r
+ variables set are "CurrXMode","MaxScrollX", "MaxScrollY",\r
+ "InGraphics". The variable "SplitScrnScanline" is also initialized\r
+ to zero.\r
+\r
+ See also:\r
+ Available X Mode resolutions\r
+ What is Mode X\r
+\r
+ x_select_default_plane\r
+ ----------------------\r
+\r
+ C Prototype: void x_select_default_plane(BYTE plane);\r
+\r
+ Enables default Read/Write access to a specified plane\r
+\r
+\r
+ x_set_splitscreen\r
+ -----------------\r
+\r
+ C Prototype: extern void x_set_splitscreen(WORD line);\r
+\r
+ line - The starting scan line of the required split screen.\r
+\r
+ This function activates Mode X split screen and sets starting scan\r
+ line. The split screen resides on the bottom half of the screen and has\r
+ a starting address of A000:0000 in video RAM.\r
+\r
+ It also Updates Page0_Offs to reflect the existence of the split screen\r
+ region ie "MainScrnOffset" is set to the offset of the first pixel\r
+ beyond the split screen region. Other variable set are "Page1_Offs" which\r
+ is set to the same value as "Page0_Offs" (see graphics call sequence\r
+ below), "ScrnLogicalHeight","ScrnPhysicalHeight", "SplitScrnScanLine" and\r
+ "MaxScrollY".\r
+\r
+ This function cannot be called after double buffering has been activated,\r
+ it will return an error. To configure your graphics environment the\r
+ sequence of graphics calls is as follows although either or both steps b\r
+ and c may be omitted:\r
+ a) x_set_mode\r
+ b) x_set_splitscreen\r
+ c) x_set_doublebuffer\r
+ Thus when you call this function successfully, double buffering is not\r
+ active so "Page1_Offs" is set to the same address as "Page0_Offs".\r
+\r
+ WARNING: If you use one of the high resolution modes (376x564 as an\r
+ extreme example) you may not have enough video ram for split screen\r
+ and double buffering options since VGA video RAM is restricted to\r
+ 64K.\r
+\r
+ See Also:\r
+ What is a Split Screen ?\r
+ What is double buffering ?\r
+\r
+ x_set_doublebuffer\r
+ ------------------\r
+\r
+ C Prototype: extern WORD x_set_doublebuffer(WORD PageHeight);\r
+\r
+ PageHeight - The height of the two double buffering virtual screens.\r
+ Returns - The closest possible height to the specified.\r
+\r
+ This function sets up two double buffering virtual pages. 'ErrorValue"\r
+ is set according to the success or failure of this command.\r
+\r
+ Other variables set are:\r
+\r
+ _Page1_Offs Offset of second virtual page\r
+ _NonVisual_Offs Offset of first non visible video ram byte\r
+ _DoubleBufferActive Flag\r
+ _PageAddrTable Table of Double buffering pages start offsets\r
+ _ScrnLogicalHeight Logical height of the double buffering pages\r
+ _MaxScrollY Max vertical start address of physical screen\r
+ within the virtual screen\r
+\r
+ WARNING: If you use one of the high resolution modes (376x564 as an\r
+ extreme example) you may not have enough video ram for split screen\r
+ and double buffering options since VGA video RAM is restricted to\r
+ 64K.\r
+\r
+ See Also:\r
+ What is double buffering ?\r
+\r
+ x_hide_splitscreen\r
+ ------------------\r
+\r
+ C Prototype: extern void x_hide_splitscreen(void);\r
+\r
+\r
+ This function hides an existing split screen by setting its starting\r
+ scan line to the last physical screen scan line.\r
+ "ScreenPhysicalHeight" is adjusted but the "SplitScreenScanLine" is not\r
+ altered as it is required for restoring the split screen at a later stage.\r
+\r
+ WARNING: Only to be used if SplitScrnLine has been previously called\r
+ Disabled for mode 5-11 (320x400-376x564). The memory for\r
+ the initial split screen is reserved and the size limitations\r
+ of these modes means any change in the split screen scan line\r
+ will encroach on the split screen ram\r
+ Update: Now disabled for these modes\r
+\r
+ See Also:\r
+\r
+ What is a split screen ?\r
+\r
+ x_show_splitscreen\r
+ ------------------\r
+\r
+ C Prototype: extern void x_show_splitscreen(void);\r
+\r
+ Restores split screen start scan line to the initial split screen\r
+ starting scan line as set by "SplitScrnScanLine".\r
+ "ScreenPhysicalHeight" is adjusted.\r
+\r
+ WARNING: Only to be used if SplitScrnLine has been previously called\r
+ Disabled for mode 4-10 (320x400-376x564). The memory for\r
+ the initial split screen is reserved and the size limitations\r
+ of these modes means any change in the split screen scan line\r
+ will encroach on the split screen ram\r
+\r
+\r
+ x_adjust_splitscreen\r
+ --------------------\r
+\r
+ C Prototype: extern void x_adjust_splitscreen(WORD line);\r
+\r
+ line - The scan line at which the split screen is to start.\r
+\r
+ Sets the split screen start scan line to a new scan line. Valid scan lines\r
+ are between the initial split screen starting scan line and the last\r
+ physical screen scan line. "ScreenPhysicalHeight" is also adjusted.\r
+\r
+ WARNING: Only to be used if SplitScrnLine has been previously called\r
+ Disabled for mode 4-10 (320x400-376x564). The memory for\r
+ the initial split screen is reserved and the size limitations\r
+ of these modes means any change in the split screen scan line\r
+ will encroach on the split screen ram\r
+\r
+ x_set_start_addr\r
+ ----------------\r
+\r
+ C Prototype: extern void x_set_start_addr(WORD X,WORD Y);\r
+\r
+ X,Y - coordinates of top left corner of physical screen within current\r
+ virtual screen.\r
+\r
+ Set Mode X non split screen physical start address within current virtual\r
+ page.\r
+\r
+ X must not exceed (Logical screen width - Physical screen width)\r
+ ie "MaxScrollX" and Y must not exceed (Logical screen height -\r
+ Physical screen height) ie "MaxScrollY"\r
+\r
+ x_page_flip\r
+ -----------\r
+\r
+ C Prototype: extern void x_page_flip(WORD X,WORD Y);\r
+\r
+ X,Y - coordinates of top left corner of physical screen within the\r
+ the hidden virtual screen if double buffering is active, or\r
+ the current virtual screen otherwise.\r
+\r
+ Sets the physical screen start address within currently hidden virtual\r
+ page and then flips pages. If double buffering is not active then this\r
+ function is functionally equivalent to "x_set_start_addr".\r
+\r
+ X must not exceed (Logical screen width - Physical screen width)\r
+ ie "MaxScrollX" and Y must not exceed (Logical screen height -\r
+ Physical screen height) ie "MaxScrollY"\r
+\r
+ x_text_mode\r
+ -----------\r
+\r
+ C Prototype: extern void x_text_mode(void);\r
+\r
+ Disables graphics mode.\r
+\r
+ x_set_cliprect\r
+ --------------\r
+\r
+ C Prototype: extern void x_set_cliprect(WORD left,WORD top,WORD right,\r
+ WORD bottom);\r
+\r
+ Defines the clipping rectangle for clipping versions of planar and video\r
+ bitmap puts.\r
+\r
+ NOTE: Compiled bitmaps cannot be clipped.\r
+\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XPOINT\r
+--------------------------------------------------------------------------\r
+\r
+ Point functions all MODE X 256 Color resolutions\r
+\r
+ ASM SOURCES\r
+\r
+ xpoint.asm xpoint.inc xlib.inc model.inc\r
+\r
+ C HEADER FILE\r
+\r
+ xpoint.h\r
+\r
+ EXPORTED FUNCTIONS\r
+\r
+ x_put_pix\r
+ ---------\r
+\r
+ C Prototype: extern void x_put_pix(WORD X,WORD Y,WORD PageOffset,\r
+ WORD Color);\r
+\r
+ Draw a point of specified colour at coordinates X,Y\r
+ within the virtual page starting at offset PageOffset.\r
+\r
+ x_get_pix\r
+ ---------\r
+\r
+ C Prototype: extern WORD x_get_pix(WORD X, WORD Y, WORD PageBase);\r
+\r
+ Read a point of at coordinates X,Y within the virtual page starting\r
+ at offset PageOffset.\r
+\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XRECT\r
+--------------------------------------------------------------------------\r
+\r
+ Screen rectangle display and manipulation functions\r
+\r
+ ASM SOURCES\r
+\r
+ xrect.asm xrect.inc xlib.inc model.inc\r
+\r
+ C HEADER FILE\r
+\r
+ xrect.h\r
+\r
+\r
+ EXPORTED FUNCTIONS\r
+\r
+ x_rect_pattern\r
+ --------------\r
+\r
+ C Prototype: extern void x_rect_pattern(WORD StartX, WORD StartY,\r
+ WORD EndX, WORD EndY,\r
+ WORD PageBase,BYTE far *Pattern);\r
+\r
+ StartX,StartY - Coordinates of upper left hand corner of rectangle\r
+ EndX,EndY - Coordinates of lower right hand corner of rectangle\r
+ PageBase - Offset of virtual screen\r
+ *Pattern - Pointer to the user defined pattern (16 bytes)\r
+\r
+\r
+ Mode X rectangle 4x4 pattern fill routine.\r
+\r
+ Upper left corner of pattern is always aligned to a multiple-of-4\r
+ row and column. Works on all VGAs. Uses approach of copying the\r
+ pattern to off-screen display memory, then loading the latches with\r
+ the pattern for each scan line and filling each scan line four\r
+ pixels at a time. Fills up to but not including the column at EndX\r
+ and the row at EndY. No clipping is performed.\r
+\r
+ Based on code originally published in DDJ Mag by M. Abrash\r
+\r
+ Warning the VGA memory locations PATTERN_BUFFER (A000:FFFc) to\r
+ A000:FFFF are reserved for the pattern buffer\r
+\r
+\r
+ See Also:\r
+ Doctor Dobbs Journal references.\r
+\r
+\r
+ x_rect_pattern_clipped\r
+ ----------------------\r
+\r
+ As above but clipped.\r
+\r
+ x_rect_fill\r
+ -----------\r
+\r
+ C Prototype: extern void x_rect_fill(WORD StartX,WORD StartY,\r
+ WORD EndX,WORD EndY,\r
+ WORD PageBase,WORD color);\r
+\r
+ StartX,StartY - Coordinates of upper left hand corner of rectangle\r
+ EndX,EndY - Coordinates of lower right hand corner of rectangle\r
+ PageBase - Offset of virtual screen\r
+ Color -color to use for fill\r
+\r
+ Mode X rectangle solid color fill routine.\r
+ Based on code originally published in DDJ Mag by M. Abrash\r
+\r
+ See Also:\r
+ Doctor Dobbs Journal references.\r
+\r
+ x_rect_fill_clipped\r
+ -------------------\r
+\r
+ as above but clipped.\r
+\r
+\r
+ x_cp_vid_rect\r
+ -------------\r
+\r
+ C Prototype: extern void x_cp_vid_rect(WORD SourceStartX,WORD SourceStartY,\r
+ WORD SourceEndX,WORD SourceEndY,\r
+ WORD DestStartX,WORD DestStartY,\r
+ WORD SourcePageBase,WORD DestPageBase,\r
+ WORD SourceBitmapWidth,WORD DestBitmapWidth);\r
+\r
+ StartX,StartY- Coordinates of upper left hand corner of source rectangle\r
+ EndX,EndY - Coordinates of lower right hand corner of source rectangle\r
+ DestStartX,DestStartY - Coordinates of rectangle destination\r
+ SourcePageBase - source rectangle page offset\r
+ DestPageBase - destination rectangles page offset\r
+ SourceBitmapWidth - width of bitmap within the source virtual screen\r
+ containing the source rectangle\r
+ DestBitmapWidth - width of bitmap within the dest. virtual screen\r
+ containing the destination rectangle\r
+\r
+ Mode X display memory to display memory copy\r
+ routine. Left edge of source rectangle modulo 4 must equal left edge\r
+ of destination rectangle modulo 4. Works on all VGAs. Uses approach\r
+ of reading 4 pixels at a time from the source into the latches, then\r
+ writing the latches to the destination. Copies up to but not\r
+ including the column at SrcEndX and the row at SrcEndY. No\r
+ clipping is performed. Results are not guaranteed if the source and\r
+ destination overlap.\r
+\r
+\r
+ Based on code originally published in DDJ Mag by M. Abrash\r
+\r
+ See Also:\r
+ Doctor Dobbs Journal references.\r
+\r
+ x_shift_rect\r
+ ------------\r
+\r
+ C Prototype:\r
+ extern void x_shift_rect (WORD SrcLeft, WORD SrcTop,\r
+ WORD SrcRight, WORD SrcBottom,\r
+ WORD DestLeft, WORD DestTop, WORD ScreenOffs);\r
+\r
+ SrcLeft, SrcTop - Coordinates of upper left hand corner of rectangle\r
+ SrcRight, SrcBottom - Coordinates of lower right hand corner of rectangle\r
+ DestLeft, DestTop - Coordinates of upper left corner of destination\r
+ ScreenOffs - Offset of virtual screen\r
+\r
+ This function copies a rectangle of VRAM onto another area of VRAM,\r
+ even if the destination overlaps with the source. It is designed\r
+ for scrolling text up and down, and for moving large areas of screens\r
+ around in tiling systems. It rounds all horizontal coordinates to\r
+ the nearest byte (4-column chunk) for the sake of speed. This means\r
+ that it can NOT perform smooth horizontal scrolling. For that,\r
+ either scroll the whole screen (minus the split screen), or copy\r
+ smaller areas through system memory using the functions in the\r
+ XPBITMAP module.\r
+\r
+ SrcRight is rounded up, and the left edges are rounded down, to\r
+ ensure that the pixels pointed to by the arguments are inside the\r
+ the rectangle. That is, SrcRight is treated as (SrcRight+3) >> 2,\r
+ and SrcLeft as SrcLeft >> 2.\r
+\r
+ The width of the rectangle in bytes (width in pixels / 4)\r
+ cannot exceed 255.\r
+\r
+---------------------------------------------------------------------------\r
+MODULE XPAL\r
+---------------------------------------------------------------------------\r
+\r
+ Palette functions for VGA 256 color modes.\r
+\r
+ All the functions in this module operate on two variations of the\r
+ pallete buffer, the raw and annotated buffers.\r
+\r
+ All those functions ending in "raw" operate on the following palette\r
+ structure:\r
+\r
+ BYTE:r0,g0,b0,r1,g1,b1,...rn,gn,bn\r
+\r
+ No reference to the starting colour index or number of colours stored\r
+ is contained in the structure.\r
+\r
+ All those functions ending in "struc" operate on the following palette\r
+ structure:\r
+\r
+ BYTE:c,BYTE:n,BYTE:r0,g0,b0,r1,g1,b1,...rn,gn,bn\r
+\r
+ where c is the starting colour and n is the number of colours stored\r
+\r
+\r
+ WARNING: There is no validity checking in these functions. The onus is\r
+ on the user to supply valid parameters to the functions.\r
+\r
+\r
+ ASM SOURCES\r
+\r
+ xpal.asm xpal.inc xlib.inc model.inc\r
+\r
+ C HEADER FILE:\r
+\r
+ xpal.h\r
+\r
+ EXPORTED FUNCTIONS\r
+\r
+ x_get_pal_raw\r
+ -------------\r
+\r
+ C Prototype: extern void x_get_pal_raw(BYTE far * pal,WORD num_colrs,\r
+ WORD start_index);\r
+\r
+ Read DAC palette into raw buffer with interrupts disabled\r
+ ie BYTE r1,g1,b1,r1,g2,b2...rn,gn,bn\r
+\r
+ WARNING: Memory for the palette buffers must all be pre-allocated.\r
+\r
+ x_get_pal_struc\r
+ ---------------\r
+\r
+ C Prototype: extern void x_get_pal_struc(BYTE far * pal,WORD num_colrs,\r
+ WORD start_index);\r
+\r
+ Read DAC palette into annotated type buffer with interrupts disabled\r
+ ie BYTE colours to skip, BYTE colours to set, r1,g1,b1,r1,g2,b2...rn,gn,bn\r
+\r
+ WARNING: memory for the palette buffers must all be pre-allocated\r
+\r
+ x_put_pal_raw\r
+ -------------\r
+\r
+ C Prototype: extern void x_put_pal_raw(BYTE far * pal,WORD num_colrs,\r
+ WORD start_index);\r
+\r
+ Write DAC palette from raw buffer with interrupts disabled\r
+ ie BYTE r1,g1,b1,r1,g2,b2...rn,gn,bn\r
+\r
+ x_put_pal_struc\r
+ --------------\r
+\r
+ C Prototype: extern void x_put_pal_struc(BYTE far * pal);\r
+\r
+ Write DAC palette from annotated type buffer with interrupts disabled\r
+ ie BYTE colours to skip, BYTE colours to set, r1,g1,b1,r1,g2,b2...rn,gn,bn\r
+\r
+ x_set_rgb\r
+ ---------\r
+\r
+ C Prototype: extern x_set_rgb(BYTE color,BYTE red_c,BYTE green_c,\r
+ BYTE blue_c);\r
+\r
+ Set the RGB components of a vga color\r
+\r
+ x_rot_pal_struc\r
+ ---------------\r
+\r
+ C Prototype: extern void x_rot_pal_struc(BYTE far * pal,WORD direction);\r
+\r
+ Rotate annotated palette buffer entries. Direction 0 = backward,\r
+ 1 = forward.\r
+\r
+ x_rot_pal_raw\r
+ -------------\r
+\r
+ C Prototype: extern x_rot_pal_raw(BYTE far * pal,WORD direction,\r
+ WORD num_colrs);\r
+\r
+ Rotate a raw palette buffer. Direction 0 = backward,\r
+ 1 = forward.\r
+\r
+ x_put_contrast_pal_struc\r
+ ------------------------\r
+\r
+ C Prototype: extern void x_put_contrast_pal_struc(BYTE far * pal,\r
+ BYTE intensity);\r
+\r
+ Write DAC palette from annotated type buffer with specified intensity\r
+ adjustment (ie palette entries are decremented where possible by\r
+ "intensity" units).\r
+\r
+ Designed for fading in or out a palette without using an intermediate\r
+ working palette buffer ! (Slow but memory efficient ... OK for small\r
+ pal strucs}\r
+\r
+\r
+ x_transpose_pal_struc\r
+ ---------------------\r
+\r
+ C Prototype: extern void x_transpose_pal_struc(BYTE far * pal,\r
+ WORD StartColor);\r
+\r
+ Write DAC palette from annotated type buffer with interrupts disabled\r
+ starting at a new palette index.\r
+\r
+\r
+ x_cpcontrast_pal_struc\r
+ ----------------------\r
+\r
+ C Prototype: extern WORD x_cpcontrast_pal_struc(BYTE far *src_pal,\r
+ BYTE far *dest_pal,BYTE Intensity);\r
+\r
+ Copy one annotated palette buffer to another making the intensity\r
+ adjustment. Used in fading in and out fast and smoothly.\r
+\r
+---------------------------------------------------------------------------\r
+MODULE XLINE\r
+---------------------------------------------------------------------------\r
+\r
+ Line Drawing functions.\r
+\r
+ ASM SOURCES\r
+\r
+ xline.asm xline.inc xlib.inc model.inc\r
+\r
+ C HEADER FILE\r
+\r
+ xline.h\r
+\r
+ EXPORTED FUNCTIONS\r
+\r
+ x_line\r
+ ------\r
+\r
+ C Prototype: extern void x_line(WORD x0,WORD y0,WORD x1,WORD y1,\r
+ WORD color,WORD PageBase);\r
+\r
+ Draw a line with the specified end points in the page starting at\r
+ offset "PageBase".\r
+\r
+ No Clipping is performed.\r
+\r
+---------------------------------------------------------------------------\r
+MODULE XTEXT\r
+---------------------------------------------------------------------------\r
+\r
+ ASM SOURCES\r
+\r
+ xtext.asm xtext.inc xlib.inc model.inc\r
+\r
+ C HEADER FILE\r
+\r
+ xtext.h\r
+\r
+ MACROS\r
+\r
+ FONT_8x8 0\r
+ FONT_8x15 1\r
+ FONT_USER 2\r
+\r
+ EXPORTED VARIABLES\r
+\r
+ NOTE: All variables are read only. I you modify them the results may\r
+ be unpredictable.\r
+\r
+ CharHeight - BYTE - Height of current inbuilt character set\r
+\r
+ CharWidth - BYTE - Width of current inbuilt character set\r
+\r
+ FirstChar - BYTE - First character of current inbuilt character set\r
+\r
+ UserCharHeight - BYTE - Height of current user character set\r
+\r
+ UserCharWidth - BYTE - Width of current user character set\r
+\r
+ UserFirstCh - BYTE - First character of current user character set\r
+\r
+\r
+ EXPORTED FUNCTIONS\r
+\r
+ x_text_init\r
+ -----------\r
+\r
+ C Prototype: extern WORD x_text_init(void);\r
+\r
+ Initializes the Mode X text driver and sets the default font (VGA ROM 8x8)\r
+\r
+ x_set_font\r
+ ----------\r
+\r
+ C Prototype: extern void x_set_font(WORD FontId);\r
+\r
+ Select the working font where 0 = VGA ROM 8x8, 1 = VGA ROM 8x14\r
+ 2 = User defined bitmapped font.\r
+\r
+ WARNING: A user font must be registered before setting FontID 2\r
+\r
+ See Also:\r
+\r
+ Defines for this module\r
+\r
+ x_register_userfont\r
+ -------------------\r
+\r
+ C Prototype: extern void x_register_userfont(char far *UserFontPtr);\r
+\r
+\r
+ Register a user font for later selection. Only one user font can be\r
+ registered at any given time. Registering a user font deregisters the\r
+ previous user font. User fonts may be at most 8 pixels wide.\r
+\r
+ USER FONT STRUCTURE\r
+\r
+ Word: ascii code of first char in font\r
+ Byte: Height of chars in font\r
+ Byte: Width of chars in font\r
+ n*h*Byte: the font data where n = number of chars and h = height\r
+ of chars\r
+\r
+ WARNING: The onus is on the program to ensure that all characters\r
+ drawn whilst this font is active, are within the range of\r
+ characters defined.\r
+\r
+ x_put_char\r
+ ----------\r
+\r
+ C Prototype: extern void x_put_char(char ch,WORD X,WORD Y,WORD PgOffs,\r
+ WORD Color);\r
+\r
+ Draw a text character at the specified location with the specified\r
+ color.\r
+\r
+ ch - char to draw\r
+ x,y - screen coords at which to draw ch\r
+ ScrnOffs - Starting offset of page on whih to draw\r
+ Color - Color of the text\r
+\r
+ WARNING: InitTextDriver must be called before using this function\r
+\r
+\r
+ **** NOTE ****\r
+\r
+ The file "xprintf.c" implements a printf style formatted output function\r
+\r
+ x_printf\r
+ --------\r
+\r
+ C Prototype: void x_printf(int x,int y,unsigned ScrnOffs,int color,\r
+ char *ln,...);\r
+\r
+ x,y - screen coords at which to draw ch\r
+ ScrnOffs - Starting offset of page on whih to draw\r
+ Color - Color of the text\r
+\r
+ Parameters beyond Color conform to the standard printf parameters.\r
+\r
+ x_bgprintf\r
+ ----------\r
+\r
+ C Prototype: void x_bgprintf(int x,int y,unsigned ScrnOffs,int fgcolor,\r
+ int bgcolor, char *ln,...);\r
+\r
+ x,y - screen coords at which to draw ch\r
+ ScrnOffs - Starting offset of page on whih to draw\r
+ fgcolor - Color of the text foreground\r
+ bgcolor - Color of the text background\r
+\r
+ Parameters beyond bgolor conform to the standard printf parameters.\r
+\r
+\r
+ x_get_char_width\r
+ ----------------\r
+\r
+ C Prototype: unsigned int x_get_char_width(char ch)\r
+\r
+ ch - character to get width of\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XPBITMAP\r
+--------------------------------------------------------------------------\r
+\r
+ This module implements a set of functions to operate on planar bitmaps.\r
+ Planar bitmaps as used by these functions have the following structure:\r
+\r
+ BYTE 0 The bitmap width in bytes (4 pixel groups) range 1..255\r
+ BYTE 1 The bitmap height in rows range 1..255\r
+ BYTE 2..n1 The plane 0 pixels width*height bytes\r
+ BYTE n1..n2 The plane 1 pixels width*height bytes\r
+ BYTE n2..n3 The plane 2 pixels width*height bytes\r
+ BYTE n3..n4 The plane 3 pixels width*height bytes\r
+\r
+ These functions provide the fastest possible bitmap blts from system ram to\r
+ to video and further, the single bitmap is applicable to all pixel\r
+ allignments. The masked functions do not need separate masks since all non\r
+ zero pixels are considered to be masking pixels, hence if a pixel is 0 the\r
+ corresponding screen destination pixel is left unchanged.\r
+\r
+\r
+ ASM SOURCES\r
+\r
+ xpbitmap.asm xpbitmap.inc xlib.inc model.inc\r
+\r
+ C HEADER FILE\r
+\r
+ xpbitmap.h\r
+\r
+ EXPORT FUNCTIONS\r
+\r
+ x_put_masked_pbm\r
+ ----------------\r
+\r
+ C Prototype: extern void x_put_masked_pbm(WORD X,WORD Y,WORD ScrnOffs,\r
+ BYTE far * Bitmap);\r
+\r
+ Mask write a planar bitmap from system ram to video ram. All zero source\r
+ bitmap bytes indicate destination byte to be left unchanged.\r
+\r
+ Source Bitmap structure:\r
+\r
+ Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,\r
+ Bitmap data (plane 2)..,Bitmap data (plane 3)..\r
+\r
+ NOTE: width is in bytes ie lots of 4 pixels\r
+\r
+ LIMITATIONS: No clipping is supported\r
+ Only supports bitmaps with widths which are a multiple of\r
+ 4 pixels\r
+\r
+ See Also: XBMTOOLS module for linear <-> planar bitmap conversion\r
+ functions.\r
+\r
+ x_put_pbm\r
+ ---------\r
+\r
+ C Prototype: extern void x_put_pbm(WORD X, WORD Y, WORD ScrnOffs,\r
+ BYTE far * Bitmap);\r
+\r
+ Write a planar bitmap from system ram to video ram.\r
+\r
+ Source Bitmap structure:\r
+\r
+ Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,\r
+ Bitmap data (plane 2)..,Bitmap data (plane 3)..\r
+\r
+ NOTE: width is in bytes ie lots of 4 pixels\r
+\r
+ LIMITATIONS: No clipping is supported\r
+ Only supports bitmaps with widths which are a multiple of\r
+ 4 pixels\r
+\r
+\r
+ See Also: XBMTOOLS module for linear <-> planar bitmap conversion\r
+ functions.\r
+\r
+ x_get_pbm\r
+ ---------\r
+\r
+ C Prototype: extern void x_get_pbm(WORD X, WORD Y,BYTE Bw,BYTE Bh,\r
+ WORD ScrnOffs, BYTE far * Bitmap);\r
+\r
+ Read a planar bitmap to system ram from video ram.\r
+\r
+ Source Bitmap structure:\r
+\r
+ Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,\r
+ Bitmap data (plane 2)..,Bitmap data (plane 3)..\r
+\r
+ NOTE: width is in bytes ie lots of 4 pixels\r
+\r
+ LIMITATIONS: No clipping is supported\r
+ Only supports bitmaps with widths which are a multiple of\r
+ 4 pixels\r
+\r
+\r
+ See Also: XBMTOOLS module for linear <-> planar bitmap conversion\r
+ functions.\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XPBMCLIP\r
+--------------------------------------------------------------------------\r
+\r
+ This module implements a similar set of functions to operate on planar\r
+ bitmaps as "XPBITMAP" but incorporates clipping to a user defined\r
+ clipping rectangle (which is set by "x_set_cliprect" in module xmain).\r
+\r
+ The planar bitmap format is identical to the above module\r
+\r
+ There are three variations of the functions in XPBITMAP in this module\r
+ identified by the three function name extensions: _clipx, _clipy _clipxy.\r
+ Because speed is critical in games programming you do not want to be\r
+ checking for clipping if not necessary thus for sprites that move only\r
+ horizontally you would use the _clipx version of the put function,\r
+ for sprites that move vertically you would use the _clipy version and for\r
+ sprites that move both directions you would use the clipxy version.\r
+ Keep in mind also that the clipping components of these functions assume\r
+ that the clipping rectangle is equal to or larger than the size of the\r
+ bitmap ie. if a bitmap is top clipped, it is assumed that the bitmap's\r
+ bottom is not also clipped. Similarly with horizontal clipping.\r
+\r
+ Note: performance in decreasing order is as follows.\r
+ _clipy,_clipx,_clipxy with masked puts being slower than unmasked\r
+ puts\r
+\r
+ Horizontal clipping is performed to byte boundaries (4 pixels) rather than\r
+ pixels. This allows for the fastest implementation of the functions. It is\r
+ not such a handicap because for one, your screen width a multiple of 4\r
+ pixels wide and for most purposes it is the screen edges that form the\r
+ clipping rectangle.\r
+\r
+ Following is an example of setting a clipping rectangle to the logical\r
+ screen edges:\r
+\r
+ x_set_cliprect(0,0,ScrnLogicalByteWidth,ScrnLogicalHeight)\r
+\r
+ NOTE: the functions now return a value;\r
+ 1 if clipped image is fully clipped (ie no portion of it\r
+ appears on the screen) otherwise it returns 0\r
+\r
+\r
+ ASM SOURCES\r
+\r
+ xpbmclip.asm xpbmclip.inc xlib.inc model.inc\r
+\r
+ C HEADER FILE\r
+\r
+ xpbmclip.h\r
+\r
+ EXPORT FUNCTIONS\r
+\r
+ x_put_pbm_clipx\r
+ ---------------\r
+ x_put_pbm_clipy\r
+ ---------------\r
+ x_put_pbm_clipxy\r
+ ----------------\r
+ x_put_masked_pbm_clipx\r
+ ----------------------\r
+ x_put_masked_pbm_clipy\r
+ ----------------------\r
+ x_put_masked_pbm_clipxy\r
+ -----------------------\r
+\r
+ For a detailed description of parameters etc. see equivalent functions\r
+ in module "XPBITMAP".\r
+\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XCBITMAP\r
+--------------------------------------------------------------------------\r
+\r
+ XCBITMAP:\r
+ The Care and Feeding of Compiled Masked Blits\r
+ by Matthew MacKenzie\r
+\r
+The XCBITMAP module of the Xlib library is made up of the files\r
+XCBITMAP.ASM, XCBITMAP.INC, and XCBITMAP.H.\r
+\r
+The XCBITMAP module is small, containing only three procedures:\r
+ o x_compile_bitmap compiles your bitmap into native code which writes\r
+ to the VGA screen in an X mode.\r
+ o x_put_cbitmap converts X and Y coordinates into a location on the\r
+ screen, sets up the necessary VGA registers, and executes the compiled\r
+ bitmap as a subroutine.\r
+ o x_sizeof_cbitmap takes a planar bitmap and returns an integer equal to\r
+ the size of the compiled bitmap which the planar bitmap would produce.\r
+ It is essentially a lobotomized version of x_compile_bitmap, with all\r
+ the code generation replaced with a size counter.\r
+\r
+ x_compile_bitmap scans through a source bitmap and generates 8086\r
+instructions to plot every nonzero pixel. It is designed to be used\r
+before the action begins rather than on-the-fly. The compiled bitmap\r
+contains no branches, and no reference to the zero (transparent) pixels.\r
+Where two pixels are exactly four columns apart they are plotted with a\r
+single 16-bit store, and the VGA MAP_MASK register will be set at most\r
+four times. As a result your bitmap may run several times faster than a\r
+traditional memory-to-VGA masked blit routine.\r
+ There is no way to perform clipping on these bitmaps, or to plot a\r
+pixel of color zero.\r
+ x_compile_bitmap works with bitmaps in the standard Xlib planar bitmap\r
+format. On a time scale of 60 frames per second, it is actually relatively\r
+slow. Since a compiled bitmap is relocatable you may just want to have it\r
+saved to disk, and not include the source bitmap in your program at all.\r
+ The source bitmap format is an array of bytes, a little like this:\r
+\r
+char eye[] ={4, 7, /* four byte columns across, seven rows tall */\r
+ 0, 0, 0, 0, 9, 1, 1, 1, 9, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 9, 9, 1, 1, 1, 4, 4, 9, 9, 0, 0, 0, 0, 0,\r
+ 0, 9, 9, 1, 2, 0, 0, 4, 4, 1, 9, 9, 0, 0, 0, 0,\r
+ 9, 9, 9, 1, 0, 0, 0, 0, 1, 1, 9, 9, 9, 0, 0, 0,\r
+ 0, 9, 9, 1, 2, 0, 0, 2, 1, 1, 9, 9, 0, 0, 0, 0,\r
+ 0, 0, 9, 9, 1, 1, 1, 1, 1, 9, 9, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 9, 1, 1, 1, 9, 0, 0, 0, 0, 0, 0, 0};\r
+\r
+ This is actually a linear bitmap, which is the wrong format for\r
+compilation, but is easier on human eyes. Use the module XBMTOOLS to\r
+convert linear bitmaps into planar bitmaps, and vice-versa.\r
+ To compile this image for a mode 360 pixels (90 byte columns) across:\r
+\r
+char planar_eye[4*7 + 2];\r
+char far * EyeSize;\r
+\r
+(void) x_bm_to_pbm((char far *) eye, (char far *) planar_eye);\r
+EyeSize = x_sizeof_cbitmap((far char *) planar_eye);\r
+CompiledEye = farmalloc(EyeSize);\r
+(void) x_compile_bitmap(90, (far char *) planar_eye, CompiledEye);\r
+\r
+ Notice that both buffers must exist beforehand. Since x_compile_bitmap\r
+returns the size of the compiled code, in bytes, you can reallocate the\r
+bitmap immediately to the right size if using x_sizeof_xbitmap seems\r
+inconvenient (reallocation may even be faster, though using the function is\r
+cleaner). The pointers are 32-bit because compiled bitmaps take so much\r
+space: they are at one end of the speed-versus-memory spectrum. A good\r
+rule of thumb is to allocate (3.5 x buffer-height x buffer-width) + 25\r
+bytes (rounding up ;-), then pare your bitmap down when you find out how\r
+much space you've actually used.\r
+ Since the compiled bitmap has to fit within one segment of memory, it\r
+cannot contain more than about 19,000 pixels. This will not be a\r
+limitation for most sane programmers. If you are not a sane programmer try\r
+splitting your huge, unwieldy image up into smaller parts -- you can use\r
+the same gigantic bitmap if you divide it into horizontal slices for\r
+compilation. For that matter, dividing the source up that way will let\r
+you use a source bitmap large than 64K, which is an even sicker idea...\r
+ Back to business. A bitmap is compiled for only one width of screen.\r
+If you are using a logical screen larger than your physical screen, call\r
+the bitmap compiler with the logical width -- the important thing is the\r
+number of bytes per line. Notice that you do not have to be in a graphics\r
+mode to use this routine. This allows you to develop and compile bitmaps\r
+separately, with whatever utility programs you might cook up.\r
+\r
+ The final function is x_put_cbitmap. To plot our eye at (99,4), on\r
+the page which starts at location 0:\r
+x_put_cbitmap(99, 4, 0, CompiledEye);\r
+ This function depends on the global variable ScrnLogicalByteWidth from\r
+the module XMAIN, which should be the same number as the column parameter\r
+you used to compile your bitmap.\r
+ The XCBITMAP module supports memory-to-VGA blits only. Xlib also\r
+includes non-masking routines which can quickly save and restore the\r
+background screen behind your bitmap, using fast string operations.\r
+\r
+ This module is part of the Xlib package, and is in the public domain.\r
+If you write something which uses it, though, please send me a copy as a\r
+courtesy -- if for no other reason so I can tilt my chair back and reflect\r
+that it may have been worth the trouble after all.\r
+\r
+The included program DEMO2.C demonstrates the performance difference\r
+between planar bitmap masked blits and compiled bitmap blits.\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XCOMPPBM\r
+--------------------------------------------------------------------------\r
+\r
+Identical to XCBITMAP except that the source bitmaps are the PBM form\r
+rather than LBM.\r
+\r
+FUNCTIONS\r
+\r
+x_compile_pbm\r
+-------------\r
+x_sizeof_cpbm\r
+-------------\r
+\r
+See XCBITMAP module\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XVBITMAP\r
+--------------------------------------------------------------------------\r
+\r
+The XVBITMAP module implements yet another type of bitmap to complement\r
+planar and compiled bitmaps, VRAM based bitmaps. If a 4 cylinder car is\r
+analagous to planar bitmaps, that is thrifty on memory consumption but low\r
+performance and and a V8 is analagous to Compiled bitmaps, memory guzzlers\r
+that really fly, then VRAM based bitmaps are the 6 cylinder modest performers\r
+with acceptable memory consumption.\r
+\r
+To summarise their selling points, VBM's are moderately fast with fair memory\r
+consumption, and unlike compiled bitmaps, can be clipped. The disadvantages\r
+are that they are limited by the amount of free video ram and have a complex\r
+structure.\r
+\r
+The VRAM bitmap format is rather complex consisting of components stored in\r
+video ram and components in system ram working together. This complexity\r
+necessitates the existence of a creation function "x_make_vbm" which takes\r
+an input linear bitmap and generates the equivalent VBM (VRAM Bit Map).\r
+\r
+VBM structure:\r
+\r
+ WORD 0 Size Total size of this VBM structure in bytes\r
+ WORD 1 ImageWidth Width in bytes of the image (for all alignments)\r
+ WORD 2 ImageHeight Height in scan lines of the image\r
+\r
+ WORD 3 Alignment 0 ImagePtr Offset in VidRAM of this aligned image\r
+ +--WORD 4 MaskPtr Offset (within this structure's DS) of\r
+ | . alignment masks\r
+ | .\r
+ | .\r
+ | WORD 9 Alignment 3 ImagePtr Offset in VidRAM of this aligned image\r
+ +|--WORD 10 MaskPtr Offset (within this structure's DS) of\r
+ || alignment masks\r
+ ||\r
+ |+->BYTE 21 (WORD 11) -------+-- Image masks for alignment 0\r
+ | . |\r
+ | . |\r
+ | BYTE 21 + ImageWidth*ImageHeight -----+\r
+ |\r
+ | .\r
+ | . (similaly for alignments 1 - 2 )\r
+ | .\r
+ |\r
+ +-->BYTE 21 + 3*ImageWidth*ImageHeight + 1-+-- Image masks for alignment 3\r
+ . |\r
+ . |\r
+ BYTE 21 + 4*(ImageWidth*ImageHeight) --+\r
+\r
+ .\r
+ .\r
+ << Similarly for alignments 2 and 3 >>\r
+ .\r
+ .\r
+ BYTE 21 + 4*(ImageWidth*ImageHeight)\r
+ -------------\r
+\r
+ (And dont forget the corresponding data in video ram)\r
+\r
+You can see for yourself the complexity of this bitmap format. The image\r
+is stored in video ram in its 4 different alignments with pointers to these\r
+alignments in the VBM. Similarly there are 4 alignments of the corresponding\r
+masks within the VBM itself (towards the end). The mask bytes contain the\r
+plane settings for the corresponding video bytes so that one memory move can\r
+move up to 4 pixels at a time (depending on the mask settings) using the\r
+VGA's latches, theoretically giving you a 4x speed improvement over\r
+conventional blits like the ones implemented in "XPBITMAP". In actual fact\r
+its anywhere between 2 and 3 due to incurred overheads.\r
+\r
+These bitmaps are more difficult to store in files than PBM'S and CBM's but\r
+still posible with a bit of work, so do not dismiss these as too difficult\r
+to use. Consider all the bitmap formats carefully before deciding on which\r
+to use. There may even be situations that a careful application of all three\r
+types would be most effective ie. compiled bitmaps for Background tiles and\r
+the main game character (which never need clipping), VRAM based bitmaps for\r
+the most frequently occuring (oponent, alien etc) characters which get\r
+clipped as they come into and leave your current location and planar bitmaps\r
+for smaller or less frequently encountered characters.\r
+\r
+ASM SOURCES\r
+\r
+ xvbitmap.asm xvbitmap.inc xlib.inc model.inc\r
+ xmakevbm.c - Additional C module implementing creation function\r
+\r
+ C HEADER FILE\r
+\r
+ xvbitmap.h\r
+\r
+ EXPORTED FUNCTIONS\r
+\r
+ x_make_vbm\r
+ ----------\r
+\r
+ C Prototype: extern char far * x_make_vbm(char far *lbm, WORD *VramStart);\r
+\r
+ Create the VBM from the given linear bitmap and place the image alignments\r
+ in video ram starting at the offset in the variable pointed to by\r
+ "VramStart". "VramStart" is then updated to point to the next free VRAM byte\r
+ (just after the last byte of the image alignments). Usually you will point\r
+ "VramStart" to "NonVisual_Offs".\r
+\r
+ lbm Pointer to the input linear bitmap\r
+ VramStart Pointer to variable containing Offset of first free VRAM byte\r
+\r
+ x_put_masked_vbm\r
+ ----------------\r
+\r
+ C Prototype: extern int x_put_masked_vbm(int X, int Y, WORD ScrnOffs,\r
+ BYTE far * VBitmap);\r
+\r
+ Draw a VRAM based bitmap at (X,Y) relative to the screen with starting\r
+ offset "ScrnOffs".\r
+\r
+ Returns 1 if clipped image is fully clipped (ie no portion of it\r
+ appears on the screen) otherwise it returns 0\r
+\r
+ x_put_masked_vbm_clipx\r
+ ----------------------\r
+ x_put_masked_vbm_clipy\r
+ ----------------------\r
+ x_put_masked_vbm_clipxy\r
+ -----------------------\r
+\r
+ Clipping versions of "x_put_masked_vbm".\r
+\r
+ See XPBMCLIP for more details on the type of clipping used as it is\r
+ identical to XVBITMAP.\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XMOUSE\r
+--------------------------------------------------------------------------\r
+The XMOUSE module implements very basic mouse handling functions. The way\r
+in which it operates is by installing an event handler function during\r
+initialization which subsequently intercepts and processes mouse events and\r
+automatically updates status variables such as mouse position and button\r
+pressed status. It does not support the full functionality of:\r
+\r
+ SPLIT SCREENS\r
+ SCROLLED WINDOWS\r
+ VIRTUAL WINDOWS\r
+\r
+This was done to primarily prevent unecessary impedences to performance,\r
+since the mouse handler function has the potential to degrade performance.\r
+It also saves me alot of coding which I was too lazy to do.\r
+\r
+Programs communicate with the mouse driver as with other devices, through\r
+an interrupt vector namely 33h. On generating an interrupt, the mouse driver\r
+expects a function number in AX and possibly other parameters in other\r
+registers and returns information via the registers. A brief description\r
+of the mouse functions follows:\r
+\r
+ --------------------------------------\r
+\r
+ MS Mouse Driver Functions\r
+\r
+ Mouse Initialization 0\r
+ Show Cursor 1\r
+ Hide Cursor 2\r
+ Get Mouse Position & Button Status 3\r
+ Set Mouse Cursor Position 4\r
+ Get Button Press Information 5\r
+ Get Button Release Information 6\r
+ Set Min/Max Horizontal Position 7\r
+ Set Min/Max Vertical Position 8\r
+ Define Graphics Cursor Block 9\r
+ Define Text Cursor 10\r
+ Read Mouse Motion Counters 11\r
+ Define Event Handler 12\r
+ Light Pen Emulation Mode ON 13\r
+ Light Pen Emulation Mode OFF 14\r
+ Set Mouse Mickey/Pixel Ratio 15\r
+ Conditional Hide Cursor 16\r
+ Set Double-Speed Threshold 19\r
+ --------------------------------------\r
+\r
+In practice only afew of these functions are used and even fewer when the\r
+mouse status is monitored by an event handler function such as is used in\r
+this module.\r
+\r
+The most important thing to note when using the mouse module is that the\r
+mouse event handler must be removed before exiting the program. It is a good\r
+idea to have an exit function (see the C "atexit" function) and include the\r
+line "x_mouse_remove();" along with any other pre-exit cleanup code.\r
+\r
+\r
+ ASM SOURCES\r
+\r
+ xmouse.asm xlib.inc model.inc\r
+\r
+ C HEADER FILE\r
+\r
+ xmouse.h\r
+\r
+ EXPORTED VARIABLES\r
+\r
+ MouseInstalled - WORD - Indicates whether mouse handler installed\r
+ MouseHidden - WORD - Indicates whether mouse cursor is hidden\r
+ MouseButtonStatus - WORD - Holds the mouse button status\r
+ MouseX - WORD - Current X position of mouse cursor\r
+ MouseY - WORD - Current Y position of mouse cursor\r
+ MouseFrozen - WORD - Disallows position updates if TRUE\r
+ MouseColor - BYTE - The mouse cursors colour\r
+\r
+ EXPORTED FUNCTIONS\r
+\r
+ x_mouse_init\r
+ ------------\r
+\r
+ C Prototype: int x_mouse_init()\r
+\r
+ Initialize the mouse driver functions and install the mouse event handler\r
+ function. This is the first function you must call before using any of the\r
+ mouse functions. This mouse code uses the fastest possible techniques to\r
+ save and restore mouse backgrounds and to draw the mouse cursor.\r
+\r
+ WARNING: This function uses and updates "NonVisual_Offset" to allocate\r
+ video ram for the saved mouse background.\r
+\r
+ LIMITATIONS: No clipping is supported horizontally for the mouse cursor\r
+ No validity checking is performed for NonVisual_Offs\r
+\r
+ **WARNING** You must Hide or at least Freeze the mouse cursor while drawing\r
+ using any of the other XLIB modules since the mouse handler may\r
+ modify vga register settings at any time. VGA register settings\r
+ are not preserved which will result in unpredictable drawing\r
+ behavior. If you know the drawing will occur away from the\r
+ mouse cursor set MouseFrozen to TRUE (1), do your drawing\r
+ then set it to FALSE (0). Alternatively call "x_hide_mouse",\r
+ perform your drawing and then call "x_show_mouse". Another\r
+ alternative is to disable interrupts while drawing but usually\r
+ drawing takes up alot of time and having interrupts disabled\r
+ for too long is not a good idea.\r
+\r
+ x_define_mouse_cursor\r
+ ---------------------\r
+\r
+ C Prototype:\r
+ void x_define_mouse_cursor(char far *MouseDef, unsigned char MouseColor)\r
+\r
+ MouseDef - a pointer to 14 characters containing a bitmask for all the\r
+ cursor's rows.\r
+ MouseColor - The colour to use when drawing the mouse cursor.\r
+\r
+ Define a mouse cursor shape for use in subsequent cursor redraws. XMouse\r
+ has a hardwired mouse cursor size of 8 pixels across by 14 pixels down.\r
+\r
+ WARNING: This function assumes MouseDef points to 14 bytes.\r
+\r
+ Note: Bit order is in reverse. ie bit 7 represents pixel 0 ..\r
+ bit 0 represents pixel 7 in each "MouseDef" byte.\r
+\r
+ x_show_mouse\r
+ ------------\r
+\r
+ C Prototype: void x_show_mouse()\r
+\r
+ Makes the cursor visible if it was previously hidden.\r
+ See Also: "x_hide_mouse".\r
+\r
+ x_hide_mouse\r
+ ------------\r
+\r
+ C Prototype: void x_hide_mouse()\r
+\r
+ Makes the cursor hidden if it was previously visible.\r
+ See Also: "x_show_mouse".\r
+\r
+ x_mouse_remove\r
+ --------------\r
+\r
+ C Prototype: void x_mouse_remove()\r
+\r
+ Stop mouse event handling and remove the mouse handler.\r
+\r
+ NOTE: This function MUST be called before quitting the program if\r
+ a mouse handler has been installed\r
+\r
+ x_position_mouse\r
+ ----------------\r
+\r
+ C Prototype void x_position_mouse(int x, int y)\r
+\r
+ Positions the mouse cursor at the specified location\r
+\r
+ x_mouse_window\r
+ ------------\r
+\r
+ C Prototype: void x_mouse_window(int x0, int y0, int x1, int y1)\r
+\r
+ Defines a mouse window.\r
+\r
+ x_update_mouse\r
+ --------------\r
+\r
+ C Prototype: void x_update_mouse()\r
+\r
+ Forces the mouse position to be updated and cursor to be redrawn.\r
+ Note: this function is useful when you have set "MouseFrozen" to true.\r
+ Allows the cursor position to be updated manually rather than\r
+ automatically by the installed handler.\r
+\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XBMTOOLS\r
+--------------------------------------------------------------------------\r
+\r
+ This module implements a set of functions to convert between planar\r
+ bitmaps and linear bitmaps.\r
+\r
+ PLANAR BITMAPS\r
+\r
+ Planar bitmaps as used by these functions have the following structure:\r
+\r
+ BYTE 0 The bitmap width in bytes (4 pixel groups) range 1..255\r
+ BYTE 1 The bitmap height in rows range 1..255\r
+ BYTE 2..n1 The plane 0 pixels width*height bytes\r
+ BYTE n1..n2 The plane 1 pixels width*height bytes\r
+ BYTE n2..n3 The plane 2 pixels width*height bytes\r
+ BYTE n3..n4 The plane 3 pixels width*height bytes\r
+\r
+ as used by x_put_pbm, x_get_pbm, x_put_masked_pbm.\r
+\r
+ LINEAR BITMAPS\r
+\r
+ Linear bitmaps have the following structure:\r
+\r
+ BYTE 0 The bitmap width in pixels range 1..255\r
+ BYTE 1 The bitmap height in rows range 1..255\r
+ BYTE 2..n The width*height bytes of the bitmap\r
+\r
+ ASM SOURCES\r
+\r
+ xbmtools.asm xpbmtools.inc model.inc\r
+\r
+ C HEADER FILE\r
+\r
+ xbmtools.h\r
+\r
+ MACROS\r
+\r
+ BM_WIDTH_ERROR\r
+\r
+ LBMHeight(lbitmap) - Height of linear bitmap "lbitmap"\r
+ LBMWidth(lbitmap) - Width of linear bitmap "lbitmap"\r
+ PBMHeight(pbitmap) - Height of planar bitmap "pbitmap"\r
+ PBMWidth(pbitmap) - Width of planar bitmap "pbitmap"\r
+\r
+ LBMPutPix(x,y,lbitmap,color) - set pixel (x,y) colour in linear bitmap\r
+ LBMGetPix(x,y,lbitmap) - colour of pixel (x,y) in linear bitmap\r
+\r
+ EXPORT FUNCTIONS\r
+\r
+ x_pbm_to_bm\r
+ ------------\r
+ C Prototype: extern int x_pbm_to_bm(char far * source_pbm,\r
+ char far * dest_bm);\r
+\r
+ This function converts a bitmap in the planar format to the linear format\r
+ as used by x_compile_bitmap.\r
+\r
+ WARNING: the source and destination bitmaps must be pre - allocated\r
+\r
+ NOTE: This function can only convert planar bitmaps that are suitable.\r
+ If the source planar bitmap's width (per plane) is >= 256/4\r
+ it cannot be converted. In this situation an error code\r
+ BM_WIDTH_ERROR. On successful conversion 0 is returned.\r
+\r
+ x_bm_to_pbm\r
+ ------------\r
+ C Prototype: extern int x_bm_to_pbm(char far * source_pbm,\r
+ char far * dest_bm);\r
+\r
+ This function converts a bitmap in the linear format as used by\r
+ x_compile_bitmap to the planar formap.\r
+\r
+ WARNING: the source and destination bitmaps must be pre - allocated\r
+\r
+ NOTE: This function can only convert linear bitmaps that are suitable.\r
+ If the source linear bitmap's width is not a multiple of 4\r
+ it cannot be converted. In this situation an error code\r
+ BM_WIDTH_ERROR. On successful conversion 0 is returned.\r
+\r
--- /dev/null
+PART 2 of 2\r
+-----------------------------------------------------------------------------\r
+\r
+ ********* XLIB - Mode X graphics library ****************\r
+ ********* ****************\r
+ ********* Written By Themie Gouthas ****************\r
+ ********* ****************\r
+ ********* egg@dstos3.dsto.gov.au ****************\r
+ ********* teg@bart.dsto.gov.au ****************\r
+\r
+ Some of the code in this library has been contributed by :\r
+\r
+ Matthew MacKenzie - matm@eng.umd.edu\r
+\r
+ and others. See individual modules.\r
+\r
+ I informally reserve all rights to the code in XLIB\r
+ Rights to contributed code is also assumed to be reserved by\r
+ the original authors.\r
+-----------------------------------------------------------------------------\r
+MODULE XCLIPPBM note: VERY SIMILAR to XPBMCLIP\r
+This module implements blits of clipped planar bitmaps. Blits are\r
+clipped to pixels, both horizontally. This makes the unmasked blit\r
+function here slightly slower than the equivalent functions in the\r
+XPBMCLIP module.\r
+--------------------------------------------------------------------------\r
+ XCLIPPBM:\r
+ Blits and Pieces\r
+ by Matthew MacKenzie\r
+\r
+The XCLIPPBM module contains clipping versions of two of the three routines\r
+in the XPBITMAP module:\r
+ o x_clip_pbm transfers a planar bitmap to the screen, clipping off any\r
+ part outside a bounding box.\r
+ o x_clip_masked_pbm does the same thing, but transfers only nonzero\r
+ pixels.\r
+\r
+ The planar bitmap format is described elsewhere. Here we will look at\r
+the clipping itself, since it is the only distinguishing feature of this\r
+module.\r
+ The bounding box is made up of four integers, TopBound, BottomBound,\r
+LeftBound, and RightBound. Unlike most global variables in Xlib, these are\r
+meant to be written to. In fact, they start out uninitialized. Be sure to\r
+set them before you try plotting any clipped bitmaps.\r
+ Note that these are not the same variables which are used in the other\r
+clipping modules in Xlib. This is because the two systems are incompatible:\r
+the other modules clip horizontally to columns while this one clips to\r
+pixels. As you might have guessed, those functions and these were developed\r
+in different hemispheres of the planet...\r
+ If it's any consolation, this does give you two independent\r
+bounding boxes to futz with, should the mood visit you.\r
+ Bitmaps cannot go outside the perimeter of the bounding box, but they\r
+can overlap it. If TopBound equals BottomBound, for example, a horizontal\r
+slice of a bitmap may still be plotted. It is safe to turn the box "inside\r
+out" to make sure nothing will be plotted -- this is the first thing each\r
+routine checks for.\r
+ To plot a bitmap, minus its zero pixels, minus anything outside the\r
+bounding box:\r
+\r
+x_clip_masked_pbm (int X, int Y, int ScreenOffs, char far * Bitmap);\r
+\r
+ The arguments are in the same order as those for x_put_masked_pbm in\r
+the module XPBITMAP. The bounding box is relative to the given\r
+ScreenOffs(et). This lets you perform page flipping without worrying about\r
+what screen you are clipping to -- it's always the current screen. The\r
+bitmap itself, of course, is not affected; clipping is performed on-the-\r
+fly. Both functions return an integer which indicates whether any part\r
+of the bitmap was inside the bounding box. If the entire bitmap was\r
+outside, a 1 is returned; otherwise, a 0.\r
+ The third function in XPBITMAP, for which this module has no\r
+equivalent, copies from video RAM to system RAM. The absence of such a\r
+routine may seem at first like a disadvantage -- but this, like so many\r
+things in this life, is an illusion. You can use the unclipped routine,\r
+and clip the bitmap when you want to plot it back onto the screen.\r
+\r
+ ASM SOURCES\r
+\r
+ xclippbm.asm xclippbm.inc xlib.inc model.inc\r
+\r
+ C HEADER FILE\r
+\r
+ xclippbm.h\r
+\r
+ EXPORTED VARIABLES\r
+\r
+ TopBound - int\r
+ BottomBound - int\r
+ LeftBound - int\r
+ RightBound - int\r
+\r
+ EXPORTED FUNCTIONS\r
+\r
+ x_clip_pbm\r
+ ----------\r
+ C Prototype: extern int x_clip_pbm (int X, int Y, int ScreenOffs, char\r
+ far * Bitmap);\r
+\r
+ Copies a planar bitmap from SRAM to VRAM, with clipping. If the entire\r
+ bitmap turns out to be outside the bounding box, this function returns\r
+ a 1; otherwise it returns a 0.\r
+\r
+ x_clip_masked_pbm\r
+ -----------------\r
+ C Prototype: extern int x_clip_masked_pbm (int X, int Y,\r
+ int ScreenOffs, char far * Bitmap);\r
+\r
+ Copies a planar bitmap from SRAM to VRAM, with clipping -- 0 bytes\r
+ in the bitmap are not copied. If the entire bitmap turns out to be\r
+ outside the bounding box, this function returns a 1; otherwise,\r
+ it returns a 0.\r
+\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XMOUSE\r
+--------------------------------------------------------------------------\r
+The XMOUSE module implements very basic mouse handling functions. The way\r
+in which it operates is by installing an event handler function during\r
+initialization which subsequently intercepts and processes mouse events and\r
+automatically updates status variables such as mouse position and button\r
+pressed status. It does not support the full functionality of:\r
+\r
+ SPLIT SCREENS\r
+ SCROLLED WINDOWS\r
+ VIRTUAL WINDOWS\r
+\r
+This was done to primarily prevent unecessary impedences to performance,\r
+since the mouse handler function has the potential to degrade performance.\r
+It also saves me alot of coding which I was too lazy to do.\r
+\r
+Programs communicate with the mouse driver as with other devices, through\r
+an interrupt vector namely 33h. On generating an interrupt, the mouse driver\r
+expects a function number in AX and possibly other parameters in other\r
+registers and returns information via the registers. A brief description\r
+of the mouse functions follows:\r
+\r
+ --------------------------------------\r
+\r
+ MS Mouse Driver Functions\r
+\r
+ Mouse Initialization 0\r
+ Show Cursor 1\r
+ Hide Cursor 2\r
+ Get Mouse Position & Button Status 3\r
+ Set Mouse Cursor Position 4\r
+ Get Button Press Information 5\r
+ Get Button Release Information 6\r
+ Set Min/Max Horizontal Position 7\r
+ Set Min/Max Vertical Position 8\r
+ Define Graphics Cursor Block 9\r
+ Define Text Cursor 10\r
+ Read Mouse Motion Counters 11\r
+ Define Event Handler 12\r
+ Light Pen Emulation Mode ON 13\r
+ Light Pen Emulation Mode OFF 14\r
+ Set Mouse Mickey/Pixel Ratio 15\r
+ Conditional Hide Cursor 16\r
+ Set Double-Speed Threshold 19\r
+ --------------------------------------\r
+\r
+In practice only afew of these functions are used and even fewer when the\r
+mouse status is monitored by an event handler function such as is used in\r
+this module.\r
+\r
+The most important thing to note when using the mouse module is that the\r
+mouse event handler must be removed before exiting the program. It is a good\r
+idea to have an exit function (see the C "atexit" function) and include the\r
+line "x_mouse_remove();" along with any other pre-exit cleanup code.\r
+\r
+See also: XDETECT for mouse detection.\r
+\r
+ ASM SOURCES\r
+\r
+ xmouse.asm xlib.inc model.inc\r
+\r
+ C HEADER FILE\r
+\r
+ xmouse.h\r
+\r
+ EXPORTED VARIABLES\r
+\r
+ MouseInstalled - WORD - Indicates whether mouse handler installed\r
+ MouseHidden - WORD - Indicates whether mouse cursor is hidden\r
+ MouseButtonStatus - WORD - Holds the mouse button status\r
+ MouseX - WORD - Current X position of mouse cursor\r
+ MouseY - WORD - Current Y position of mouse cursor\r
+ MouseFrozen - WORD - Disallows position updates if TRUE\r
+ MouseColor - BYTE - The mouse cursors colour\r
+\r
+ EXPORTED FUNCTIONS\r
+\r
+ x_mouse_init\r
+ ------------\r
+\r
+ C Prototype: int x_mouse_init()\r
+\r
+ Initialize the mouse driver functions and install the mouse event handler\r
+ function. This is the first function you must call before using any of the\r
+ mouse functions. This mouse code uses the fastest possible techniques to\r
+ save and restore mouse backgrounds and to draw the mouse cursor.\r
+\r
+ WARNING: This function uses and updates "NonVisual_Offset" to allocate\r
+ video ram for the saved mouse background.\r
+\r
+ LIMITATIONS: No clipping is supported horizontally for the mouse cursor\r
+ No validity checking is performed for NonVisual_Offs\r
+\r
+ **WARNING** You must Hide or at least Freeze the mouse cursor while drawing\r
+ using any of the other XLIB modules since the mouse handler may\r
+ modify vga register settings at any time. VGA register settings\r
+ are not preserved which will result in unpredictable drawing\r
+ behavior. If you know the drawing will occur away from the\r
+ mouse cursor set MouseFrozen to TRUE (1), do your drawing\r
+ then set it to FALSE (0). Alternatively call "x_hide_mouse",\r
+ perform your drawing and then call "x_show_mouse". Another\r
+ alternative is to disable interrupts while drawing but usually\r
+ drawing takes up alot of time and having interrupts disabled\r
+ for too long is not a good idea.\r
+\r
+ x_define_mouse_cursor\r
+ ---------------------\r
+\r
+ C Prototype:\r
+ void x_define_mouse_cursor(char far *MouseDef, unsigned char MouseColor)\r
+\r
+ MouseDef - a pointer to 14 characters containing a bitmask for all the\r
+ cursor's rows.\r
+ MouseColor - The colour to use when drawing the mouse cursor.\r
+\r
+ Define a mouse cursor shape for use in subsequent cursor redraws. XMouse\r
+ has a hardwired mouse cursor size of 8 pixels across by 14 pixels down.\r
+\r
+ WARNING: This function assumes MouseDef points to 14 bytes.\r
+\r
+ Note: Bit order is in reverse. ie bit 7 represents pixel 0 ..\r
+ bit 0 represents pixel 7 in each "MouseDef" byte.\r
+\r
+ x_show_mouse\r
+ ------------\r
+\r
+ C Prototype: void x_show_mouse()\r
+\r
+ Makes the cursor visible if it was previously hidden.\r
+ See Also: "x_hide_mouse".\r
+\r
+ x_hide_mouse\r
+ ------------\r
+\r
+ C Prototype: void x_hide_mouse()\r
+\r
+ Makes the cursor hidden if it was previously visible.\r
+ See Also: "x_show_mouse".\r
+\r
+ x_remove_mouse\r
+ --------------\r
+\r
+ C Prototype: void x_remove_mouse()\r
+\r
+ Stop mouse event handling and remove the mouse handler.\r
+\r
+ NOTE: This function MUST be called before quitting the program if\r
+ a mouse handler has been installed\r
+\r
+ x_position_mouse\r
+ ----------------\r
+\r
+ C Prototype void x_position_mouse(int x, int y)\r
+\r
+ Positions the mouse cursor at the specified location\r
+\r
+ x_update_mouse\r
+ --------------\r
+\r
+ C Prototype: void x_update_mouse()\r
+\r
+ Forces the mouse position to be updated and cursor to be redrawn.\r
+ Note: this function is useful when you have set "MouseFrozen" to true.\r
+ Allows the cursor position to be updated manually rather than\r
+ automatically by the installed handler.\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XCIRCLE\r
+--------------------------------------------------------------------------\r
+ XCIRCLE:\r
+ Wheel Have to See About That\r
+ by Matthew MacKenzie\r
+\r
+The XCIRCLE module contains two functions, neither of which should be\r
+a big mystery:\r
+ o x_circle, oddly enough, draws a circle.\r
+ o x_filled_circle does too, only the circle is filled (in some\r
+ libraries this is called a disc).\r
+\r
+ The word `circle' here refers to a round thing which is as many\r
+pixels tall as across. It only looks like a circle in 320x240 mode --\r
+the original mode X -- and in 376x282 mode.\r
+ In both functions, the circle is specified by the coordinates of the\r
+upper-left-hand corner of the smallest box which holds it, and the\r
+diameter. Some circle functions have you specify a center point;\r
+this system is kind of odd because a circle with an even diameter does\r
+not have a particular pixel for a center. Every circle, on the other\r
+hand, has a box with an upper-left corner.\r
+ No bounds are checked. A diameter of zero will draw nothing, and\r
+a negative diameter will blow your VGA board into hundreds of thousands\r
+of tiny little smoldering fragments. Neither function supports clipping.\r
+ The calculation of the circle is based on an algorithm described\r
+by Michael P. Lindner in a letter to the editor on page 8 of Dr. Dobb's\r
+Journal #169 (October 1990). The algorithm has been rearranged to\r
+allow drawing and moving the plots in the eight octants to be performed\r
+in one step, so that each pixel does not have to be loaded into the CPU\r
+twice. x_filled_circle does not take advantage of this optimization\r
+because it handles different parts of each plot at different times.\r
+\r
+ ASM SOURCES\r
+\r
+ xcircle.asm xcircle.inc xlib.inc model.inc\r
+\r
+ C HEADER FILE\r
+\r
+ xcircle.h\r
+\r
+ EXPORTED FUNCTIONS\r
+\r
+ x_circle\r
+ --------\r
+ C Prototype: extern void x_circle (WORD Left, WORD Top, WORD Diameter,\r
+ WORD Color, WORD ScreenOffs);\r
+\r
+ Draws a circle with the given upper-left-hand corner and diameter,\r
+ which are given in pixels.\r
+\r
+\r
+ x_filled_circle\r
+ ---------------\r
+ C Prototype: extern void x_filled_circle (WORD Left, WORD Top,\r
+ WORD Diameter, WORD Color, WORD ScreenOffs);\r
+\r
+ Draws a filled circle with the given upper-left-hand corner and\r
+ diameter.\r
+\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XDETECT\r
+--------------------------------------------------------------------------\r
+\r
+ This module implements a set of functions to detect the PC's hardware\r
+ configuration.\r
+\r
+ ASM SOURCES\r
+\r
+ xdetect.asm xdetect.inc model.inc\r
+\r
+ C HEADER FILE\r
+\r
+ xdetect.h\r
+\r
+ EXPORTED MACROS\r
+\r
+ I8086 0\r
+ I80186 1\r
+ I80286 2\r
+ I80386 3\r
+\r
+ NoGraphics 0\r
+ MDA 1\r
+ CGA 2\r
+ EGAMono 3\r
+ EGAColor 4\r
+ VGAMono 5\r
+ VGAColor 6\r
+ MCGAMono 7\r
+ MCGAColor 8\r
+\r
+ BUS_MOUSE 1\r
+ SERIAL_MOUSE 2\r
+ INPORT_MOUSE 3\r
+ PS2_MOUSE 4\r
+ HP_MOUSE 5\r
+\r
+\r
+ EXPORT VARIABLES\r
+\r
+ MouseButtonCount - WORD - The number of buttons on the detected mouse\r
+ MouseVersion - WORD - Mouse driver version (High byte = Major version\r
+ Low byte = minor version)\r
+ MouseType - BYTE - The mouse type\r
+ MouseIRQ - BYTE - The IRQ number used by the mouse driver\r
+\r
+ EXPORT FUNCTIONS\r
+\r
+\r
+ x_graphics_card\r
+ ---------------\r
+ C Prototype: extern int x_graphics_card();\r
+\r
+ This function returns the type of graphics card installed. See defines\r
+ above.\r
+\r
+ x_processor\r
+ -----------\r
+ C Prototype: extern int x_processor();\r
+\r
+ This function returns the type of processor installed. A 486 registers\r
+ as a 386. See defines above.\r
+\r
+ x_coprocessor\r
+ -------------\r
+ C Prototype: extern int x_coprocessor();\r
+\r
+ This function returns 1 of a numeric co-processor is present, 0 if not.\r
+ The type is not detected but it's mnot really necessary as the processor\r
+ type usually determines the numeric coprocessor type\r
+\r
+ x_mousedriver\r
+ -------------\r
+ C Prototype: extern int x_mousedriver();\r
+\r
+ This function returns 1 of a mouse driver is installed, 0 otherwise.\r
+ If a mouse driver is detected the mouse related variable (above) are\r
+ set accordingly.\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XFILEIO\r
+--------------------------------------------------------------------------\r
+\r
+ Handle based file I/O functions.\r
+\r
+ See any good DOS programming reference for more information on int 21h\r
+ DOS services.\r
+\r
+ ASM SOURCES\r
+\r
+ xfileio.asm xfileio.inc model.inc\r
+\r
+ C HEADER FILE\r
+\r
+ xfileio.h\r
+\r
+ EXPORTED MACROS\r
+\r
+ file access modes\r
+\r
+ F_RDONLY\r
+ F_WRONLY\r
+ F_RDWR\r
+\r
+ seek codes\r
+\r
+ SEEK_START\r
+ SEEK_CURR\r
+ SEEK_END\r
+\r
+ file error value\r
+\r
+ FILE_ERR\r
+\r
+ EXPORT FUNCTIONS\r
+\r
+ f_open\r
+ ------\r
+ C Prototype: extern int f_open(char * filename, char access);\r
+\r
+ Opens a file according to the access char:\r
+\r
+ F_RDONLY = read only - If doesnt exist return error\r
+ F_WRONLY = write only - If doesnt exist create it otherwise clear it\r
+ F_RDWR = read/write - If doesnt exist create it\r
+\r
+ Returns the file handle on success, FILE_ERR on failure\r
+\r
+\r
+ f_close\r
+ -------\r
+\r
+ C Prototype: extern int f_close(int handle);\r
+\r
+ Closes the file associated with the specified handle\r
+\r
+ Returns 0 on success, FILE_ERR on failure\r
+\r
+\r
+ f_read\r
+ ------\r
+\r
+ C Prototype:\r
+\r
+ extern int f_read(int handle,char near * buffer, int count);\r
+\r
+ Reads a block of count bytes from the file specified by the handle\r
+ into the near buffer\r
+\r
+ Returns count on success, FILE_ERR on failure\r
+\r
+ f_readfar\r
+ ---------\r
+\r
+ C Prototype:\r
+\r
+ extern int f_readfar(int handle,char far * buffer, int count);\r
+\r
+ Reads a block of count bytes from the file specified by the handle\r
+ into the far buffer\r
+\r
+ Returns count on success, FILE_ERR on failure\r
+\r
+\r
+ f_write\r
+ -------\r
+\r
+ C Prototype: extern int f_write(int handle, char near * buffer, int count);\r
+\r
+ Writes a block of count bytes to the file specified by the handle\r
+ from the near buffer\r
+\r
+ Returns count on success, FILE_ERR on failure\r
+\r
+ f_writefar\r
+ ----------\r
+\r
+ C Prototype: extern int f_write(int handle, char far * buffer, int count);\r
+\r
+ Writes a block of count bytes to the file specified by the handle\r
+ from the far buffer\r
+\r
+ Returns count on success, FILE_ERR on failure\r
+\r
+\r
+ f_seek\r
+ ------\r
+\r
+ C Prototype: extern long int f_seek(int handle, long int position,\r
+ char method_code)\r
+\r
+ Moves the file pointer according to the position and method code\r
+\r
+ Returns file pointer position on success, FILE_ERR on failure\r
+\r
+\r
+ f_filelength\r
+ ------------\r
+\r
+ C Prototype:\r
+\r
+ extern long int f_filelength(int handle)\r
+\r
+ Returns the length of the file associated with the specified handle\r
+\r
+ Returns file length on success, FILE_ERR on failure\r
+\r
+\r
+ f_tell\r
+ ------\r
+\r
+ C Prototype:\r
+\r
+ extern long int f_tell(int handle)\r
+\r
+\r
+ Returns file pointer position on success, FILE_ERR on failure\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XRLETOOL\r
+--------------------------------------------------------------------------\r
+\r
+This module implements a number of functions comprising an RLE encoding\r
+decoding system.\r
+\r
+RLE stands for RUN LENGTH ENCODING. It is a quick simple data compression\r
+scheme which is commonly used for image data compression or compression\r
+of any data. Although not the most efficient system, it is fast, which is\r
+why it is used in image storage systems like PCX. This implementation is\r
+more efficient than the one used in PCX files because it uses 1 bit to\r
+identify a Run Length byte as opposed to two in PCX files, but more on this\r
+later.\r
+\r
+This set of functions can be used to implement your own compressed image\r
+file format or for example compress game mapse for various levels etc.\r
+The uses are limited by your imagination.\r
+\r
+I opted for trading off PCX RLE compatibility for the improved compression\r
+efficiency.\r
+\r
+Here is how the data is un-compressed to give an idea of its structure.\r
+\r
+\r
+STEP 1 read a byte from the RLE compressed source buffer.\r
+\r
+STEP 2 if has its high bit is set then the lower 7 bits represent the number\r
+ of times the next byte is to be repeated in the destination buffer.\r
+ if the count (lower 7 bits) is zero then\r
+ we have finished decoding goto STEP 5\r
+ else goto STEP 4\r
+\r
+STEP 3 Read a data from the source buffer and copy it directly to the\r
+ destination buffer.\r
+ goto STEP 1\r
+\r
+STEP 4 Read a data byte from the source buffer and copy it to the destination\r
+ buffer the number of times specified by step 2.\r
+ goto STEP 1\r
+\r
+STEP 5 Stop, decoding done.\r
+\r
+If the byte does not have the high bit set then the byte itself is transfered\r
+ to the destination buffer.\r
+\r
+Data bytes that have the high bit already set and are unique in the input\r
+ stream are represented as a Run Length of 1 (ie 81 which includes high bit)\r
+ followed by the data byte.\r
+\r
+If your original uncompressed data contains few consecutive bytes and most\r
+have high bit set (ie have values > 127) then your so called\r
+compressed data would require up to 2x the space of the uncompressed data,\r
+so be aware that the compression ratio is extremely variable depending on the\r
+type of data being compressed.\r
+\r
+Apologies for this poor attempt at a description, but you can look up\r
+RLE in any good text. Alternatively, any text that describes the PCX file\r
+structure in any depth should have a section on RLE compression.\r
+\r
+\r
+\r
+ ASM SOURCES\r
+\r
+ xrletool.asm xrletool.inc model.inc\r
+\r
+ C HEADER FILE\r
+\r
+ xrletool.h\r
+\r
+ EXPORTED MACROS\r
+\r
+\r
+ EXPORT FUNCTIONS\r
+\r
+ x_buff_RLDecode\r
+ ---------------\r
+\r
+ Expands an RLE compresses source buffer to a destination buffer.\r
+ returns the size of the resultant uncompressed data.\r
+\r
+ C PROTOTYPE:\r
+\r
+ extern unsigned int x_buff_RLDecode(char far * source_buff,\r
+ char far * dest_buff);\r
+\r
+ source_buff - The buffer to compress\r
+ dest_buff - The destination buffer\r
+\r
+ WARNING: buffers must be pre allocated.\r
+\r
+\r
+ x_buff_RLEncode\r
+ ---------------\r
+\r
+ RLE Compresses a source buffer to a destination buffer and returns\r
+ the size of the resultant compressed data.\r
+\r
+ C PROTOTYPE:\r
+\r
+ extern unsigned int x_buff_RLEncode(char far * source_buff,\r
+ char far * dest_buff,unsigned int count);\r
+\r
+ source_buff - The buffer to compress\r
+ dest_buff - The destination buffer\r
+ count - The size of the source data in bytes\r
+\r
+ WARNING: buffers must be pre allocated.\r
+\r
+ x_buff_RLE_size\r
+ ---------------\r
+\r
+ Returns the size the input data would compress to.\r
+\r
+ C PROTOTYPE:\r
+\r
+ extern unsigned int x_buff_RLE_size(char far * source_buff,\r
+ unsigned int count);\r
+\r
+ source_buff - The uncompressed data buffer\r
+ count - The size of the source data in bytes\r
+\r
+\r
+ x_file_RLEncode\r
+ ---------------\r
+\r
+ RLE Compresses a source buffer to an output file returning\r
+ the size of the resultant compressed data or 0 if it fails.\r
+\r
+ C PROTOTYPE:\r
+\r
+ extern unsigned int x_file_RLEncode(int handle,\r
+ char far * source_buff,unsigned int count);\r
+\r
+ source_buff - The buffer to compress\r
+ handle - The file handler\r
+ count - The size of the source data in bytes\r
+\r
+ x_file_RLDecode\r
+ ---------------\r
+\r
+ Expands an RLE compresses file to a destination RAM buffer.\r
+ returns the size of the resultant uncompressed data.\r
+\r
+ C PROTOTYPE:\r
+\r
+ extern unsigned int x_buff_RLDecode(int handle,\r
+ char far * dest_buff);\r
+\r
+ handle - Input file handle\r
+ dest_buff - The destination buffer\r
+\r
+\r
+\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XPOLYGON\r
+--------------------------------------------------------------------------\r
+\r
+ This module implements eneral filled convex polygon and triangle\r
+ functions\r
+\r
+ C HEADER FILE\r
+\r
+ xpolygon.h\r
+\r
+ TYPE DEFS\r
+\r
+ typedef struct {\r
+ int X;\r
+ int Y;\r
+ } far VERTEX;\r
+\r
+\r
+\r
+ EXPORT FUNCTIONS\r
+\r
+\r
+ x_triangle\r
+ ------------\r
+ C Prototype:\r
+\r
+ void x_triangle(int x0, int y0, int x1, int y1, int x2, int y2,\r
+ WORD color, WORD PageBase);\r
+\r
+ This function draws a filled triangle which is clipped to the current\r
+ clipping window defined by TopClip,BottomClip,LeftClip,RightClip.\r
+ Remember: the X clipping variable are in BYTES not PIXELS so you\r
+ can only clip to 4 pixel byte boundaries.\r
+\r
+\r
+ x_polygon\r
+ ---------\r
+\r
+ C Prototype:\r
+\r
+ void x_polygon(VERTEX *vertices, int num_vertices,\r
+ WORD color, WORD PageBase);\r
+\r
+ This function is similar to the triangle function but draws\r
+ convex polygons. The vertices are supplied in the form of a FAR\r
+ pointer.\r
+\r
+ NOTE: a convex polygon is one such that if you draw a line from\r
+ any two vertices, every point on that line will be within the\r
+ polygon.\r
+\r
+ This function works by splitting up a polygon into its component\r
+ triangles and calling the triangle routine above to draw each one.\r
+ Performance is respectable but a custom polygon routine might be\r
+ faster.\r
+\r
+\r
+--------------------------------------------------------------------------\r
+MODULE XFILL\r
+--------------------------------------------------------------------------\r
+\r
+ This module implements a couple of general purpose flood fill functions\r
+ functions\r
+\r
+ C HEADER FILE\r
+\r
+ xfill.h\r
+\r
+\r
+ EXPORT FUNCTIONS\r
+\r
+\r
+ x_flood_fill\r
+ ------------\r
+ C Prototype:\r
+\r
+ int x_flood_fill(int x, int y, unsigned ofs, int color);\r
+\r
+ This function performs the familiar flood filling used by many\r
+ paint programs and of course the Borland BGI's flood fill function.\r
+ The pixel at x,y and all adjacent pixels of the same color are filled\r
+ to the new color. Filling stops when there are no more adjacent pixels\r
+ of the original pixel's color. The function returns the number of\r
+ pixels that have been filled.\r
+\r
+ x_boundary_fill\r
+ ------------\r
+ C Prototype:\r
+\r
+\r
+ int x_boundary_fill(int x,int y,unsigned ofs,int boundary,int color);\r
+\r
+ This function is a variant of the flood fill described above. This\r
+ function, unlike the above function, can fill across color boundaries.\r
+ Filling stops when the area being filled is fully enclosed by pixels\r
+ of the color "boundary". Again, this function returns the number of\r
+ pixels filled.\r
+\r
+-------------------------------------------------------------------------------\r
+MODULE VSYNC\r
+-------------------------------------------------------------------------------\r
+\r
+ VSYNC\r
+\r
+ Simulated Vertical Retrace Interrupt Module\r
+\r
+ by Tore Jahn Bastiansen <toreba@ifi.uio.no>\r
+\r
+ Inspired by REND386 v3.01 by Dave Stampe and Bernie Roehl\r
+\r
+The xvsync module uses timer 0 to simulate a vertical retrace interrupt.\r
+It's designed to significantly reduce the idle waiting time in Xlib.\r
+Why simulate the VRT interrupt ? Simply because a true VRT interrupt is\r
+not implemented on many VGA cards. Using a VRT interrupt as opposed to\r
+polling, can result in huge performance improvements for your code and\r
+help make animation much smoother than it would be using polling.\r
+\r
+Normally xlib waits for vsync when x_page_flip, x_set_start_address or\r
+x_put_pal_??? is called. This waiting period could be better utilized to do\r
+housekeeping calculations or whatever. The x_put_pal_??? functions also\r
+doesn't work very smoothly in conjunction with other functions that wait for\r
+the vertical retrace since each function introduces its own VRT delay.\r
+\r
+When using the vsync handler, the VRT delay is reduced to the absolute\r
+minumum which can result in a huge performance boost for your programs.\r
+\r
+When using double buffering, you may still have to wait before drawing,\r
+but you could do as much other work as possible, like this:\r
+\r
+ x_page_flip(...)\r
+ ...\r
+ <animate the palette>\r
+ <do some collision detection and 3D calculations>\r
+ <read the joystick>\r
+ ...\r
+ x_wait_start_address(); (Not needed with triple buffering)\r
+ ...\r
+ <draw next frame>\r
+ ...\r
+\r
+ASM SOURCES\r
+\r
+ xvsync.asm xmain.asm xvsync.inc xmain.inc\r
+\r
+C HEADER FILE\r
+\r
+ xvsync.h\r
+\r
+EXPORTED VARIABLES\r
+\r
+VsyncPeriod - WORD -time in 1.193 us between two vsyncs\r
+\r
+TicksPerSecond - WORD - number of vsyncs per second\r
+\r
+VsyncTimerInt - long - number of vsyncs since x_install_vsync_handler was\r
+ called. Nice for game timing.\r
+\r
+EXPORTED FUNCTIONS\r
+\r
+x_install_vsync_handler\r
+-----------------------\r
+\r
+C Prototype: void x_install_vsync_handler(int VrtsToSkip);\r
+\r
+This function installs the vsync handler using timer 0. It's called\r
+about 100 microseconds before every vertical retrace.\r
+\r
+The VrtsToSkip value (>=1) defines the delay in VRT's between consecutive\r
+physical screen start address changes, thus allowing you to limit the\r
+maximum frame rate for page flips in animation systems. The frame rate\r
+is calculated as Vertical refresh rate / VrtsToSkip, eg for\r
+320x240 mode which refreshes at 60Hz a VrtsToSkip value of 3 will result\r
+in a maximum page flipping rate of 20Hz (frames per second)\r
+\r
+WARNING: Be sure to remove it before exiting.\r
+ When used with a debugger, the system clock may speed up.\r
+\r
+x_remove_vsync_handler\r
+----------------------\r
+\r
+C Prototype: void x_remove_vsync_handler\r
+\r
+This routine _MUST_ be called before exiting (or aborting) the program,\r
+or your system will crash.\r
+\r
+x_set_user_vsync_handler\r
+------------------------\r
+\r
+C Prototype: void x_set_user_vsync_handler(void far (*f)());\r
+\r
+Installs a user routine to be called once each vertical retrace. The user\r
+handler have its own stack of 256 bytes , so be careful with the stack\r
+checking option in BC.\r
+WARNING: This installs an interrupt driven handler, beware of the following:\r
+ Only 8086 registers are preserved. If you're using 386 code, save\r
+ all the 386 regs.\r
+ Don't do any drawing.\r
+ Don't call any DOS functions.\r
+\r
+So why use it?\r
+Well, you can update global variables if you're careful. And it's nice for\r
+palette animation. You can even do fades while loading from disk. You\r
+should use this instead of installing your own int08h routine and chain\r
+to the original.\r
+\r
+x_wait_start_addr\r
+-----------------\r
+\r
+C Prototype: void x_wait_start_addr(void)\r
+\r
+You must call this function before drawing after a call to x_set_start_addr\r
+or x_page_flip when you are using the vsync handler and not using\r
+triple buffering.\r
+\r
+MODULE XMAIN additions\r
+\r
+EXPORTED VARIABLES\r
+\r
+Page2_Offs - WORD - Offset in video ram of third virtual screen. Set by\r
+ x_triple_buffer.\r
+\r
+WaitingPageOffs - WORD - Offset of page waiting to be invisible. Initially\r
+ set by x_set_triple_buffer but is updated by x_page_flip. This\r
+ variable is only used while triple buffering is on.\r
+\r
+VsyncHandlerActive - WORD - Indicates whether the vsync handler is installed.\r
+\r
+TripleBufferActive - WORD - Indicates whether triple-buffering is on.\r
+ Set by x_triple_buffer.\r
+\r
+StartAddressFlag - WORD - This flag is set if there is a new start\r
+ address waiting to be set by the vsync handler.\r
+\r
+WaitingStartLow - WORD - Needed by vsync handler. Keep off.\r
+WaitingStartHigh - WORD - Needed by vsync handler. Keep off.\r
+WaitingPelPan - WORD - Needed by vsync handler. Keep off.\r
+\r
+VsyncPaletteStart - WORD - Start index of video DAC register to be\r
+ updated next vsync. Set by palette functions.\r
+\r
+VsyncPaletteCount - WORD - Number of palette entries to be outed next\r
+ vsync. Set by palette functions.\r
+\r
+VsyncPaletteBuffer - BYTE[768] - Buffer containing values for the next\r
+ update of the DAC.\r
+\r
+EXPORTED FUNCTIONS\r
+\r
+x_triple_buffer\r
+----------------\r
+\r
+C Prototype: void x_triple_buffer(WORD PageHeight);\r
+\r
+This function behaves like x_double_buffer, but when used with\r
+x_install_vsync_handler you can draw immediately after a page flip.\r
+When x_page_flip is called, VisiblePageOffs is set to the page that\r
+will be display next vsync. Until then, WaitingPageOffs will be displayed.\r
+You can draw to HiddenPageOffs .\r
+\r
+\r
+\r
+\r
+--------------------------------------------------------------------\r
+REFERENCE SECTION\r
+--------------------------------------------------------------------\r
+\r
+\r
+REFERENCES\r
+----------\r
+\r
+In my opinion Doctor Dobbs Journal is the best reference text for\r
+VGA Mode X graphics:\r
+\r
+Issue 178 Jul 1991 : First reference to Mode X\r
+Article Abstract : VGA's undocumented Mode X supports page flipping,\r
+ makes off screen memory available, has square pixels,\r
+ and increases performance by as muck as 4 times.\r
+\r
+Issue 179 Aug 1991 : Continuation\r
+Article Abstract : Michael discusses latches and VGA's undoccumented\r
+ Mode X.\r
+\r
+Issue 181 Sep 1991 : Continuation\r
+Article Abstract : Michael puts the moves on animation using VGA's 256\r
+ colors.\r
+\r
+Issue 184 Oct 1991 : First of a continuing series covering 3-D animation\r
+ using VGA's Mode X. This series is still ongoing\r
+ (October 1992)\r
+Article Abstract : Michael moves into 3-D animation, starting with basic\r
+ polygon fills and page flips.\r
+\r
+\r
+WHAT IS MODE X ?\r
+----------------\r
+\r
+Mode X is a derrivative of the VGA's standard mode 13h (320x200 256 color).\r
+It is a (family) of undocumented video modes that are created by tweaking\r
+the VGA's registers. The beauty of mode X is that it offers several\r
+benefits to the programmer:\r
+ - Multiple graphice pages where mode 13h doesn't allowing for page flipping\r
+ (also known as double buffering) and storage of images and data in\r
+ offscreen video memory\r
+ - A planar video ram organization which although more difficult to program,\r
+ allows the VGA's plane-oriented hardware to be used to process pixels in\r
+ parallel, improving performance by up to 4 times over mode 13h\r
+\r
+ See issue 178-179 of D.D.J. for a full description of VGA's Mode X.\r
+\r
+WHAT IS A SPLIT SCREEN ?\r
+------------------------\r
+\r
+A split screen is a neat hardware feature offered by the EGA and VGA video\r
+cards. A split screen is a mode of graphics operationin which the Hardware\r
+splits the visual graphics screen horizontally and treats both halves as\r
+individual screens each starting at different locations in video RAM.\r
+\r
+The bottom half (which is usually referred to as the split screen) always\r
+starts at address A000:0000 but the top half's starting address is user\r
+definable.\r
+\r
+The most common application of split screens in games is the status display\r
+in scrolling games. Split screens make this sort of game simpler to program\r
+because when the top half window is scrolled the programmer does not have to\r
+worry about redrawing the bottom half.\r
+\r
+WHAT IS DOUBLE BUFFERING ?\r
+--------------------------\r
+\r
+Double buffering (also known as page flipping) is the technique most often\r
+used to do animation. it requires hardware that is capable of displaying\r
+multiple graphics pages (or at least 2). Animation is achieved by drawing\r
+an image in the non visible screen and then displaying the non visible\r
+screen. Once the page has been flipped the process starts again. The next\r
+frame of the animation is drawn on the non visible screen, the page is\r
+flipped again etc.\r
+\r
+\r
+WHAT IS TRIPPLE BUFFERING ?\r
+--------------------------\r
+\r
+Triple buffering is similar to double buffering in many ways, but it\r
+relies on 3 pages being defined for animation. The main selling point\r
+of triple buffering is that it eliminates the need to wait for the\r
+vertical retrace to flip pages before drawing on the new page thus\r
+alowing the programmer to start building the next animation frame\r
+immediately after completing the current one. Heres how it works:\r
+\r
+With double buffering, once you complete drawing the hidden page and\r
+youre ready to flip pages, you have to wait for the VGA hardware to\r
+actually flip the page (during the vertical retrace) before you start\r
+drawing the next page otherwise you will be drawing on the visible page.\r
+\r
+With triple buffering you cycle between three pages, thus the page you\r
+draw on is guaranteed not to be visible. I know this is a poor\r
+description but it really is quite simple\r
+\r
+Triple buffering can acheive the fastest possible animation under the\r
+right conditions but the draw back is that more video RAM is required. If\r
+you wish to store bitmaps in video ram such as background tiles, double\r
+buffering would be the better alternative.\r
+\r
+\r
+WHAT IS MODE X ?\r
+----------------\r
+\r
+Mode X is a derrivative of the VGA's standard mode 13h (320x200 256 color).\r
+It is a (family) of undocumented video modes that are created by tweaking\r
+the VGA's registers. The beauty of mode X is that it offers several\r
+benefits to the programmer:\r
+ - Multiple graphice pages where mode 13h doesn't allowing for page flipping\r
+ (also known as double buffering) and storage of images and data in\r
+ offscreen video memory\r
+ - A planar video ram organization which although more difficult to program,\r
+ allows the VGA's plane-oriented hardware to be used to process pixels in\r
+ parallel, improving performance by up to 4 times over mode 13h\r
+\r
+ Again see D.D.J. for an in depth discussion of animation using Mode X.\r
+\r
+ -----------------------------------------------------------------------\r
+\r
+\r
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XLIB_ALL - header file\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;----------------------------------------------------------------------*/\r
+\r
+#include "XLIB.H"\r
+#include "XPOINT.H"\r
+#include "XRECT.H"\r
+#include "XLINE.H"\r
+#include "XPAL.H"\r
+#include "XTEXT.H"\r
+#include "XPBITMAP.H"\r
+#include "XCBITMAP.H"\r
+#include "XDETECT.H"\r
+#include "XBMTOOLS.H"\r
+#include "XFILEIO.H"\r
+#include "XRLETOOL.H"\r
+#include "XBEZIER.H"\r
+#include "XVBITMAP.H"\r
+#include "XMOUSE.H"\r
+#include "XPBMCLIP.H"\r
+#include "XCIRCLE.H"\r
+#include "XCLIPPBM.H"\r
+#include "XPOLYGON.H"\r
+#include "XVSYNC.H"\r
+#include "XFILL.H"\r
+#include "XCBITM32.H"\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XLINE\r
+;\r
+; Line drawing functions.\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+include xlib.inc\r
+include xline.inc\r
+\r
+ .code\r
+\r
+\r
+ModeXAddr macro\r
+ mov cl,bl\r
+ push dx\r
+ mov dx,[_ScrnLogicalByteWidth]\r
+ mul dx\r
+ pop dx\r
+ shr bx,2\r
+ add bx,ax\r
+ add bx,[PgOffs]\r
+ and cl,3\r
+ endm\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; _x_line\r
+;\r
+; Line drawing function for all MODE X 256 Color resolutions\r
+; Based on code from "PC and PS/2 Video Systems" by Richard Wilton.\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+\r
+_x_line proc\r
+ARG x1:word,y1:word,x2:word,y2:word,Color:word,PgOffs:word\r
+LOCAL vertincr:word,incr1:word,incr2:word,routine:word=LocalStk\r
+ push bp ; Set up stack frame\r
+ mov bp,sp\r
+ sub sp,LocalStk\r
+ push si\r
+ push di\r
+\r
+ mov ax,0a000h\r
+ mov es,ax\r
+\r
+ mov dx,SC_INDEX ; setup for plane mask access\r
+\r
+; check for vertical line\r
+\r
+ mov si,[_ScrnLogicalByteWidth]\r
+ mov cx,[x2]\r
+ sub cx,[x1]\r
+ jz VertLine\r
+\r
+; force x1 < x2\r
+\r
+ jns L01\r
+\r
+ neg cx\r
+\r
+ mov bx,[x2]\r
+ xchg bx,[x1]\r
+ mov [x2],bx\r
+\r
+ mov bx,[y2]\r
+ xchg bx,[y1]\r
+ mov [y2],bx\r
+\r
+; calc dy = abs(y2 - y1)\r
+\r
+L01:\r
+ mov bx,[y2]\r
+ sub bx,[y1]\r
+ jnz short skip\r
+ jmp HorizLine\r
+skip: jns L03\r
+\r
+ neg bx\r
+ neg si\r
+\r
+; select appropriate routine for slope of line\r
+\r
+L03:\r
+ mov [vertincr],si\r
+ mov [routine],offset LoSlopeLine\r
+ cmp bx,cx\r
+ jle L04\r
+ mov [routine],offset HiSlopeLine\r
+ xchg bx,cx\r
+\r
+; calc initial decision variable and increments\r
+\r
+L04:\r
+ shl bx,1\r
+ mov [incr1],bx\r
+ sub bx,cx\r
+ mov si,bx\r
+ sub bx,cx\r
+ mov [incr2],bx\r
+\r
+; calc first pixel address\r
+\r
+ push cx\r
+ mov ax,[y1]\r
+ mov bx,[x1]\r
+ ModeXAddr\r
+ mov di,bx\r
+ mov al,1\r
+ shl al,cl\r
+ mov ah,al ; duplicate nybble\r
+ shl al,4\r
+ add ah,al\r
+ mov bl,ah\r
+ pop cx\r
+ inc cx\r
+ jmp [routine]\r
+\r
+; routine for verticle lines\r
+\r
+VertLine:\r
+ mov ax,[y1]\r
+ mov bx,[y2]\r
+ mov cx,bx\r
+ sub cx,ax\r
+ jge L31\r
+ neg cx\r
+ mov ax,bx\r
+\r
+L31:\r
+ inc cx\r
+ mov bx,[x1]\r
+ push cx\r
+ ModeXAddr\r
+\r
+ mov ah,1\r
+ shl ah,cl\r
+ mov al,MAP_MASK\r
+ out dx,ax\r
+ pop cx\r
+ mov ax, word ptr [Color]\r
+\r
+; draw the line\r
+\r
+L32:\r
+ mov es:[bx],al\r
+ add bx,si\r
+ loop L32\r
+ jmp Lexit\r
+\r
+; routine for horizontal line\r
+\r
+HorizLine:\r
+ push ds\r
+\r
+ mov ax,[y1]\r
+ mov bx,[x1]\r
+ ModeXAddr\r
+\r
+ mov di,bx ; set dl = first byte mask\r
+ mov dl,00fh\r
+ shl dl,cl\r
+\r
+ mov cx,[x2] ; set dh = last byte mask\r
+ and cl,3\r
+ mov dh,00eh\r
+ shl dh,cl\r
+ not dh\r
+\r
+; determine byte offset of first and last pixel in line\r
+\r
+ mov ax,[x2]\r
+ mov bx,[x1]\r
+\r
+ shr ax,2 ; set ax = last byte column\r
+ shr bx,2 ; set bx = first byte column\r
+ mov cx,ax ; cx = ax - bx\r
+ sub cx,bx\r
+\r
+ mov ax,dx ; mov end byte masks to ax\r
+ mov dx,SC_INDEX ; setup dx for VGA outs\r
+ mov bx, [Color]\r
+\r
+; set pixels in leftmost byte of line\r
+\r
+ or cx,cx ; is start and end pt in same byte\r
+ jnz L42 ; no !\r
+ and ah,al ; combine start and end masks\r
+ jmp short L44\r
+\r
+L42: push ax\r
+ mov ah,al\r
+ mov al,MAP_MASK\r
+ out dx,ax\r
+ mov al,bl\r
+ stosb\r
+ dec cx\r
+\r
+; draw remainder of the line\r
+\r
+L43:\r
+ mov ah,0Fh\r
+ mov al,MAP_MASK\r
+ out dx,ax\r
+ mov al,bl\r
+ rep stosb\r
+ pop ax\r
+\r
+; set pixels in rightmost byte of line\r
+\r
+L44:\r
+ mov al,MAP_MASK\r
+ out dx, ax\r
+ mov byte ptr es:[di],bl\r
+ pop ds\r
+ jmp short Lexit\r
+\r
+\r
+; routine for dy >= dx (slope <= 1)\r
+\r
+LoSlopeLine:\r
+ mov al,MAP_MASK\r
+ mov bh,byte ptr [Color]\r
+L10:\r
+ mov ah,bl\r
+\r
+L11:\r
+ or ah,bl\r
+ rol bl,1\r
+ jc L14\r
+\r
+; bit mask not shifted out\r
+\r
+ or si,si\r
+ jns L12\r
+ add si,[incr1]\r
+ loop L11\r
+\r
+ out dx,ax\r
+ mov es:[di],bh\r
+ jmp short Lexit\r
+\r
+L12:\r
+ add si,[incr2]\r
+ out dx,ax\r
+ mov es:[di],bh\r
+ add di,[vertincr]\r
+ loop L10\r
+ jmp short Lexit\r
+\r
+; bit mask shifted out\r
+\r
+L14: out dx,ax\r
+ mov es:[di],bh\r
+ inc di\r
+ or si,si\r
+ jns L15\r
+ add si,[incr1]\r
+ loop L10\r
+ jmp short Lexit\r
+\r
+L15:\r
+ add si,[incr2]\r
+ add di,[vertincr]\r
+ loop L10\r
+ jmp short Lexit\r
+\r
+; routine for dy > dx (slope > 1)\r
+\r
+HiSlopeLine:\r
+ mov bx,[vertincr]\r
+ mov al,MAP_MASK\r
+L21: out dx,ax\r
+ push ax\r
+ mov ax,[Color]\r
+ mov es:[di],al\r
+ pop ax\r
+ add di,bx\r
+\r
+L22:\r
+ or si,si\r
+ jns L23\r
+\r
+ add si,[incr1]\r
+ loop L21\r
+ jmp short Lexit\r
+\r
+L23:\r
+ add si,[incr2]\r
+ rol ah,1\r
+ adc di,0\r
+lx21: loop L21\r
+\r
+; return to caller\r
+\r
+Lexit:\r
+ pop di\r
+ pop si\r
+ mov sp,bp\r
+ pop bp\r
+ ret\r
+\r
+_x_line endp\r
+\r
+end\r
+\1a
\ No newline at end of file
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XLINE - header file\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;----------------------------------------------------------------------*/\r
+\r
+#ifndef _XLINE_H_\r
+#define _XLINE_H_\r
+\r
+\r
+/* FUNCTIONS =========================================================== */\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+extern void x_line( /* Draw a line, what else */\r
+ WORD x0,\r
+ WORD y0,\r
+ WORD x1,\r
+ WORD y1,\r
+ WORD color,\r
+ WORD PageBase);\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XLINE - Include file\r
+;\r
+; XLINE.ASM export functions\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+ global _x_line :proc\r
+\1a
\ No newline at end of file
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XMAIN\r
+;\r
+; Initialization, panning and split screen functions for all MODE X 256\r
+; Color resolutions\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; MODIFICATIONS:\r
+; 26-9-92: Pel panning code added\r
+; Dates forgotten: Numerous ;^)\r
+; 05-10-93: Timer synchronized vsync handling extensions\r
+; and tripple buffering - Tore Jahn Bastiansen\r
+; (toreba@ifi.uio.no) for the\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+include xlib.inc\r
+include xmain.inc\r
+\r
+\r
+ .data\r
+\r
+\r
+; Mode X CRTC register tweaks for various resolutions\r
+\r
+\r
+LABEL X256Y200 word\r
+ db 0e3h ; dot clock\r
+ db 8 ; Number of CRTC Registers to update\r
+ dw 05f00h ; horz total\r
+ dw 03f01h ; horz displayed\r
+ dw 04202h ; start horz blanking\r
+ dw 09f03h ; end horz blanking\r
+ dw 04c04h ; start h sync\r
+ dw 00005h ; end h sync\r
+ dw 00014h ; turn off dword mode\r
+ dw 0e317h ; turn on byte mode\r
+ dw 256\r
+ dw 200\r
+\r
+\r
+LABEL X256Y240 word\r
+ db 0e3h ; dot clock\r
+ db 16 ; Number of CRTC Registers to update\r
+ dw 05f00h ; horz total\r
+ dw 03f01h ; horz displayed\r
+ dw 04202h ; start horz blanking\r
+ dw 09f03h ; end horz blanking\r
+ dw 04c04h ; start h sync\r
+ dw 00005h ; end h sync\r
+ dw 00d06h ; vertical total\r
+ dw 03e07h ; overflow (bit 8 of vertical counts)\r
+ dw 04109h ; cell height (2 to double-scan)\r
+ dw 0ea10h ; v sync start\r
+ dw 0ac11h ; v sync end and protect cr0-cr7\r
+ dw 0df12h ; vertical displayed\r
+ dw 00014h ; turn off dword mode\r
+ dw 0e715h ; v blank start\r
+ dw 00616h ; v blank end\r
+ dw 0e317h ; turn on byte mode\r
+ dw 256\r
+ dw 240\r
+\r
+\r
+X320Y200 label word\r
+ db 00 ; 0e3h ; dot clock\r
+ db 02 ; Number of CRTC Registers to update\r
+ dw 00014h ; turn off dword mode\r
+ dw 0e317h ; turn on byte mode\r
+ dw 320 ; width\r
+ dw 200 ; height\r
+\r
+X320Y240 label word\r
+ db 0e3h ; dot clock\r
+ db 10 ; Number of CRTC Registers to update\r
+ dw 00d06h ; vertical total\r
+ dw 03e07h ; overflow (bit 8 of vertical counts)\r
+ dw 04109h ; cell height (2 to double-scan)\r
+ dw 0ea10h ; v sync start\r
+ dw 0ac11h ; v sync end and protect cr0-cr7\r
+ dw 0df12h ; vertical displayed\r
+ dw 00014h ; turn off dword mode\r
+ dw 0e715h ; v blank start\r
+ dw 00616h ; v blank end\r
+ dw 0e317h ; turn on byte mode\r
+ dw 320 ; width\r
+ dw 240 ; height\r
+\r
+X360Y200 label word\r
+ db 0e7h ; dot clock\r
+ db 08 ; Number of CRTC Registers to update\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 00014h ; turn off dword mode\r
+ dw 0e317h ; turn on byte mode\r
+ dw 360 ; width\r
+ dw 200 ; height\r
+\r
+X360Y240 label word\r
+ db 0e7h ; dot clock\r
+ db 17 ; Number of CRTC Registers to update\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 00d06h ; vertical total\r
+ dw 03e07h ; overflow (bit 8 of vertical counts)\r
+ dw 04109h ; cell height (2 to double-scan)\r
+ dw 0ea10h ; v sync start\r
+ dw 0ac11h ; v sync end and protect cr0-cr7\r
+ dw 0df12h ; vertical displayed\r
+ dw 02d13h ; offset;\r
+ dw 00014h ; turn off dword mode\r
+ dw 0e715h ; v blank start\r
+ dw 00616h ; v blank end\r
+ dw 0e317h ; turn on byte mode\r
+ dw 360\r
+ dw 240\r
+\r
+X376Y282 label word\r
+ db 0e7h\r
+ db 18\r
+ dw 06e00h ; horz total\r
+ dw 05d01h ; horz displayed\r
+ dw 05e02h ; start horz blanking\r
+ dw 09103h ; end horz blanking\r
+ dw 06204h ; start h sync\r
+ dw 08f05h ; end h sync\r
+ dw 06206h ; vertical total\r
+ dw 0f007h ; overflow\r
+ dw 06109h ; cell height\r
+ dw 0310fh ;\r
+ dw 03710h ; v sync start\r
+ dw 08911h ; v sync end and protect cr0-cr7\r
+ dw 03312h ; vertical displayed\r
+ dw 02f13h ; offset\r
+ dw 00014h ; turn off dword mode\r
+ dw 03c15h ; v blank start\r
+ dw 05c16h ; v blank end\r
+ dw 0e317h ; turn on byte mode\r
+ dw 376\r
+ dw 282\r
+\r
+LABEL X256Y400 word\r
+ db 0e3h ; dot clock\r
+ db 8 ; Number of CRTC Registers to update\r
+ dw 05f00h ; horz total\r
+ dw 03f01h ; horz displayed\r
+ dw 04202h ; start horz blanking\r
+ dw 09f03h ; end horz blanking\r
+ dw 04c04h ; start h sync\r
+ dw 00005h ; end h sync\r
+ dw 04009h ; cell height\r
+ dw 00014h ; turn off dword mode\r
+ dw 0e317h ; turn on byte mode\r
+ dw 256\r
+ dw 400\r
+\r
+\r
+LABEL X256Y480 word\r
+ db 0e3h ; dot clock\r
+ db 16 ; Number of CRTC Registers to update\r
+ dw 05f00h ; horz total\r
+ dw 03f01h ; horz displayed\r
+ dw 04202h ; start horz blanking\r
+ dw 09f03h ; end horz blanking\r
+ dw 04c04h ; start h sync\r
+ dw 00005h ; end h sync\r
+ dw 00d06h ; vertical total\r
+ dw 03e07h ; overflow (bit 8 of vertical counts)\r
+ dw 04009h ; cell height (2 to double-scan)\r
+ dw 0ea10h ; v sync start\r
+ dw 0ac11h ; v sync end and protect cr0-cr7\r
+ dw 0df12h ; vertical displayed\r
+ dw 00014h ; turn off dword mode\r
+ dw 0e715h ; v blank start\r
+ dw 00616h ; v blank end\r
+ dw 0e317h ; turn on byte mode\r
+ dw 256\r
+ dw 480\r
+\r
+\r
+\r
+X320Y400 label word\r
+ db 0e3h ; dot clock\r
+ db 03 ; Number of CRTC Registers to update\r
+ dw 04009h ; cell height\r
+ dw 00014h ; turn off dword mode\r
+ dw 0e317h ; turn on byte mode\r
+ dw 320 ; width\r
+ dw 400 ; height\r
+\r
+X320Y480 label word\r
+ db 0e3h ; dotclock\r
+ db 10 ; Number of CRTC Registers to update\r
+ dw 00d06h ; vertical total\r
+ dw 03e07h ; overflow (bit 8 of vertical counts)\r
+ dw 04009h ; cell height (2 to double-scan)\r
+ dw 0ea10h ; v sync start\r
+ dw 0ac11h ; v sync end and protect cr0-cr7\r
+ dw 0df12h ; vertical displayed\r
+ dw 00014h ; turn off dword mode\r
+ dw 0e715h ; v blank start\r
+ dw 00616h ; v blank end\r
+ dw 0e317h ; turn on byte mode\r
+ dw 320 ; width\r
+ dw 480 ; height\r
+\r
+X360Y400 label word\r
+ db 0e7h ; dot clock\r
+ db 09 ; Number of CRTC Registers to update\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 04009h ; cell height\r
+ dw 00014h ; turn off dword mode\r
+ dw 0e317h ; turn on byte mode\r
+ dw 360 ; width\r
+ dw 400 ; height\r
+\r
+\r
+\r
+X360Y480 label word\r
+ db 0e7h\r
+ db 17\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 00d06h ; vertical total\r
+ dw 03e07h ; overflow\r
+ dw 04009h ; cell height\r
+ dw 0ea10h ; v sync start\r
+ dw 0ac11h ; v sync end and protect cr0-cr7\r
+ dw 0df12h ; vertical displayed\r
+ dw 02d13h ; offset\r
+ dw 00014h ; turn off dword mode\r
+ dw 0e715h ; v blank start\r
+ dw 00616h ; v blank end\r
+ dw 0e317h ; turn on byte mode\r
+ dw 360\r
+ dw 480\r
+\r
+X360Y360 label word\r
+ db 0e7h\r
+ db 15\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 04009h ; cell height\r
+ dw 08810h ; v sync start\r
+ dw 08511h ; v sync end and protect cr0-cr7\r
+ dw 06712h ; vertical displayed\r
+ dw 02d13h ; offset\r
+ dw 00014h ; turn off dword mode\r
+ dw 06d15h ; v blank start\r
+ dw 0ba16h ; v blank end\r
+ dw 0e317h ; turn on byte mode\r
+ dw 360\r
+ dw 360\r
+\r
+\r
+X376Y308 label word\r
+ db 0e7h\r
+ db 18\r
+ dw 06e00h ; horz total\r
+ dw 05d01h ; horz displayed\r
+ dw 05e02h ; start horz blanking\r
+ dw 09103h ; end horz blanking\r
+ dw 06204h ; start h sync\r
+ dw 08f05h ; end h sync\r
+ dw 06206h ; vertical total\r
+ dw 00f07h ; overflow\r
+ dw 04009h ;\r
+ dw 0310fh ;\r
+ dw 03710h ; v sync start\r
+ dw 08911h ; v sync end and protect cr0-cr7\r
+ dw 03312h ; vertical displayed\r
+ dw 02f13h ; offset\r
+ dw 00014h ; turn off dword mode\r
+ dw 03c15h ; v blank start\r
+ dw 05c16h ; v blank end\r
+ dw 0e317h ; turn on byte mode\r
+ dw 376\r
+ dw 308\r
+\r
+X376Y564 label word\r
+ db 0e7h\r
+ db 18\r
+ dw 06e00h ; horz total\r
+ dw 05d01h ; horz displayed\r
+ dw 05e02h ; start horz blanking\r
+ dw 09103h ; end horz blanking\r
+ dw 06204h ; start h sync\r
+ dw 08f05h ; end h sync\r
+ dw 06206h ; vertical total\r
+ dw 0f007h ; overflow\r
+ dw 06009h ;\r
+ dw 0310fh ;\r
+ dw 03710h ; v sync start\r
+ dw 08911h ; v sync end and protect cr0-cr7\r
+ dw 03312h ; vertical displayed\r
+ dw 02f13h ; offset\r
+ dw 00014h ; turn off dword mode\r
+ dw 03c15h ; v blank start\r
+ dw 05c16h ; v blank end\r
+ dw 0e317h ; turn on byte mode\r
+ dw 376\r
+ dw 564\r
+\r
+LAST_X_MODE equ 13\r
+ModeTable label word ; Mode X tweak table\r
+ dw offset X320Y200\r
+ dw offset X320Y240\r
+ dw offset X360Y200\r
+ dw offset X360Y240\r
+ dw offset X376Y282\r
+ dw offset X320Y400\r
+ dw offset X320Y480\r
+ dw offset X360Y400\r
+ dw offset X360Y480\r
+ dw offset X360Y360\r
+ dw offset X376Y308\r
+ dw offset X376Y564\r
+ dw offset X256Y200\r
+ dw offset X256Y240\r
+\r
+\r
+PARAMS label byte\r
+\r
+ _CurrXMode dw 0 ; Current graphics mode index\r
+ _InGraphics db 0 ; Flag indicating graphics activity\r
+ _ScrnPhysicalByteWidth dw 0 ; Physical width in bytes of screen\r
+ _ScrnPhysicalPixelWidth dw 0 ; Physical width in pixels of screen\r
+ _ScrnPhysicalHeight dw 0 ; Physical Height of screen\r
+ _ErrorValue db 0 ; Set after function calls\r
+\r
+\r
+ _SplitScrnActive db 0 ; Flag indicating Split scrn activity\r
+ _DoubleBufferActive dw 0 ; Flag indicating double buffering\r
+ _TrippleBufferActive dw 0 ; Flag indicating tripple buffering\r
+\r
+ _SplitScrnScanLine dw 0 ; Split Screen's starting scan line\r
+ _SplitScrnVisibleHeight dw 0 ; Split Screen's height on screen\r
+\r
+ _SplitScrnOffs dw 0 ; Offset in video ram of Split Screen\r
+ ; always = 0\r
+ _Page0_Offs dw 0 ; Ofset in video ram of Main virtual\r
+ ; screen ( = 0 if no split screen\r
+ ; otherwise = offset of first byte\r
+ ; after split screen\r
+ _Page1_Offs dw 0 ; Ofset in video ram of Second virtual\r
+ ; screen ( = 0 if no split screen\r
+ ; otherwise = offset of first byte\r
+ ; after split screen\r
+ ; = Page0_Offs if Doubble buffering\r
+ ; not enabled\r
+ _Page2_Offs dw 0\r
+\r
+ _NonVisual_Offs dw 0 ; Ofset in video ram of first byte\r
+ ; of non visible ram\r
+ _ScrnLogicalByteWidth dw 0 ; Logical width in bytes of screen\r
+ _ScrnLogicalPixelWidth dw 0 ; Logical width in pixels of screen\r
+ _ScrnLogicalHeight dw 0 ; Logical Height of screen\r
+\r
+ _MaxScrollX dw 0 ; Max X start position of Physical\r
+ ; screen within virtual screen (in\r
+ ; bytes)\r
+ _MaxScrollY dw 0 ; Max Y start position of Physical\r
+ ; screen within virtual screen\r
+\r
+ _VisiblePageIdx dw 0 ; Index of currently visible D.B.\r
+ ; page\r
+\r
+ PageAddrTable label word\r
+ _VisiblePageOffs dw 0 ; Table containing starting offsets\r
+ _HiddenPageOffs dw 0 ; of the double buffer pages\r
+ _WaitingPageOffs dw 0\r
+\r
+ _TopClip dw 0 ; Clipping Rectangle\r
+ _BottomClip dw 0 ;\r
+ _LeftClip dw 0 ; Left/Right coordinates in bytes\r
+ _RightClip dw 0 ;\r
+ _PhysicalStartByteX dw 0 ; X byte coord of physical screen\r
+ ; relative to virtual virtual screen\r
+ _PhysicalStartPixelX dw 0 ; X pixel coord of physical screen\r
+ ; relative to virtual screen\r
+ _PhysicalStartY dw 0 ; Y pixel coord of physical screen\r
+ ; relative to virtual screen\r
+\r
+; NEW\r
+ _VsyncHandlerActive dw 0\r
+ _MouseRefreshFlag dw 0\r
+ _MouseVsyncHandler dd 0\r
+ _StartAddressFlag dw 0\r
+ _WaitingStartLow dw 0\r
+ _WaitingStartHigh dw 0\r
+ _WaitingPelPan dw 0\r
+ _VsyncPaletteStart dw 0\r
+ _VsyncPaletteCount dw 0\r
+ _VsyncPaletteBuffer label byte\r
+ db 768 dup(?)\r
+\r
+\r
+PARAMS_END label byte\r
+\r
+PARAM_COUNT equ ($-PARAMS)\r
+\r
+\r
+; Index/data pairs for CRT Controller registers that differ between\r
+; mode 13h and mode X.\r
+\r
+ ;Pelpan values for 0,1,2,3 pixel panning to the left, respectively\r
+ PelPanMask db 000h,002h,004h,006h\r
+\r
+DoubleScanFlag db ? ; Flag to indicate double scanned mode\r
+\r
+ .code\r
+\r
+;-------------------------------------------------------------------------\r
+; Local Logical Screen Width setting function\r
+; cx = Requitrd Logical Width\r
+;\r
+; WARNING: no registers are preserved\r
+\r
+SetLogicalScrWidth proc\r
+ mov dx,CRTC_INDEX\r
+ mov al,CRTC_OFFSET\r
+ out dx,al\r
+ inc dx\r
+\r
+ mov ax,cx\r
+ cmp ax,[_ScrnPhysicalPixelWidth]; Is logical width >= physical width\r
+ jge @@ValidLogicalWidth ; yes - continue\r
+ mov ax,bx ; no - set logical width = physical\r
+\r
+@@ValidLogicalWidth:\r
+ shr ax,3\r
+ out dx,al\r
+\r
+ ; The EXACT logical pixel width may not have been possible since\r
+ ; it should be divisible by 8. Round down to the closest possible\r
+ ; width and update the status variables\r
+\r
+ shl ax,1\r
+ mov bx,ax\r
+ mov [_ScrnLogicalByteWidth],ax ; Store the byte width of virtual\r
+ mov [_RightClip],ax ; Set default Right clip column\r
+ ; screen\r
+ sub ax,[_ScrnPhysicalByteWidth] ; Calculate and store Max X position\r
+ shl ax,2 ; of physical screen in virtual\r
+ mov [_MaxScrollX],ax ; screen in pixels\r
+ mov ax,bx ; set ax to byte width of virt scrn\r
+ shl ax,2 ; convert to pixels\r
+ mov [_ScrnLogicalPixelWidth],ax ; store virt scrn pixel width\r
+ mov cx,ax ; save ax (return value)\r
+\r
+ ; calculate no. non split screen rows in video ram\r
+\r
+ mov ax,0ffffh ; cx = Maximum video ram offset\r
+ sub dx,dx ; DX:AX is divide operand, set DX = 0\r
+ div bx ; divide ax by ScrnLogicalByteWidth\r
+ mov [_ScrnLogicalHeight],ax ; Save Screen Logical Height\r
+ mov [_BottomClip],ax ; Set default bottom clip row\r
+ sub ax,[_ScrnPhysicalHeight] ; Update the maximum Y position of\r
+ mov [_MaxScrollY],ax ; Physical screen in logical screen\r
+ mov ax,cx ; restore ax (return value)\r
+\r
+ ; calculate initial NonVisual\r
+ mov ax,[_ScrnLogicalByteWidth]\r
+ mul [_ScrnPhysicalHeight]\r
+ mov [_NonVisual_Offs],ax\r
+\r
+@@Done: ret\r
+SetLogicalScrWidth endp\r
+\r
+clear_vram proc\r
+ push di\r
+ mov dx,SC_INDEX\r
+ mov ax,0f02h\r
+ out dx,ax ; enable writes to all four planes\r
+ mov ax,SCREEN_SEG ; now clear all display memory, 8 pixels\r
+ mov es,ax ; at a time\r
+ sub di,di ; point ES:DI to display memory\r
+\r
+ WaitVsyncEnd\r
+\r
+ sub ax,ax ; clear to zero-value pixels\r
+ mov cx,0FFFFh ; # of words in display memory\r
+ rep stosw ; clear all of display memory\r
+ pop di\r
+ ret\r
+clear_vram endp\r
+\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; Mode X graphics mode set with a virtual screen\r
+; logical screen width.\r
+; C near-callable as:\r
+;\r
+; int x_set_mode(unsigned int mode,unsigned int WidthInPixels);\r
+;\r
+; returns the actual width of the allocated virtual screen in pixels\r
+; if a valid mode was selected otherwise returns -1\r
+;\r
+; Saves virtual screen pixel width in _ScrnLogicalPixelWidth.\r
+; Saves virtual screen byte width in _ScrnLogicalByteWidth.\r
+; Physical screen dimensions are set in _ScrnPhysicalPixelWidth,\r
+; _ScrnPhysicalByteWidth and _ScrnPhysicalHeight\r
+;\r
+;\r
+; Modes: 0 = 320 x 200 (256 color) NOTE: Some of these modes require\r
+; 1 = 320 x 240 (256 color) vertical size adjustment.\r
+; 2 = 360 x 200 (256 color)\r
+; 3 = 360 x 240 (256 color)\r
+; 4 = 320 x 400 (256 color)\r
+; 5 = 320 x 480 (256 color)\r
+; 6 = 360 x 200 (256 color)\r
+; 7 = 360 x 480 (256 color)\r
+; 8 = 360 x 360 (256 color)\r
+; 9 = 376 x 308 (256 color)\r
+; 10 = 376 x 564 (256 color)\r
+;\r
+; Written by Themie Gouthas,\r
+; parts adapted from M. Abrash code.\r
+;------------------------------------------------------------------------\r
+_x_set_mode proc\r
+ ARG mode:word,logicalscrwidth:word\r
+ push bp ;preserve caller's stack frame\r
+ mov bp,sp\r
+\r
+ push si ;preserve C register vars\r
+ push di ; (don't count on BIOS preserving anything)\r
+\r
+ cld\r
+ mov ax,ds\r
+ mov es,ax\r
+ mov di,offset PARAMS\r
+ xor ax,ax\r
+ mov cx,PARAM_COUNT\r
+ rep stosb\r
+\r
+ mov cx,[mode]\r
+ cmp cx,LAST_X_MODE ; have we selected a valid mode\r
+ jle @@ValidMode ; Yes !\r
+\r
+ mov [_InGraphics],FALSE ; No return -1\r
+ mov ax,-1\r
+ pop di\r
+ pop si\r
+ pop bp\r
+ ret\r
+\r
+@@ValidMode:\r
+\r
+ mov [_CurrXMode],cx\r
+ mov [_InGraphics],TRUE\r
+\r
+ xor al,al\r
+ cmp cx,3\r
+ jg @@SetDoubleScanFlag\r
+ mov al,TRUE\r
+@@SetDoubleScanFlag:\r
+ mov [DoubleScanFlag],al\r
+ push cx ; some bios's dont preserve cx\r
+\r
+ call clear_vram\r
+\r
+ mov ax,13h ; let the BIOS set standard 256-color\r
+ int 10h ; mode (320x200 linear)\r
+\r
+\r
+ pop cx\r
+\r
+ mov dx,SC_INDEX\r
+ mov ax,0604h\r
+ out dx,ax ; disable chain4 mode\r
+ mov ax,0100h\r
+ out dx,ax ; synchronous reset while setting Misc\r
+ ; Output for safety, even though clock\r
+ ; unchanged\r
+\r
+ mov bx,offset ModeTable\r
+ shl cx,1\r
+ add bx,cx\r
+ mov si, word ptr [bx]\r
+ lodsb\r
+\r
+ or al,al\r
+ jz @@DontSetDot\r
+ mov dx,MISC_OUTPUT\r
+ out dx,al ; select the dot clock and Horiz\r
+ ; scanning rate\r
+@@DontSetDot:\r
+ mov dx,SC_INDEX\r
+ mov ax,0300h\r
+ out dx,ax ; undo reset (restart sequencer)\r
+\r
+\r
+ mov dx,CRTC_INDEX ; reprogram the CRT Controller\r
+ mov al,11h ; VSync End reg contains register write\r
+ out dx,al ; protect bit\r
+ inc dx ; CRT Controller Data register\r
+ in al,dx ; get current VSync End register setting\r
+ and al,07fh ; remove write protect on various\r
+ out dx,al ; CRTC registers\r
+ dec dx ; CRT Controller Index\r
+ cld\r
+ xor cx,cx\r
+ lodsb\r
+ mov cl,al\r
+\r
+@@SetCRTParmsLoop:\r
+ lodsw ; get the next CRT Index/Data pair\r
+ out dx,ax ; set the next CRT Index/Data pair\r
+ loop @@SetCRTParmsLoop\r
+\r
+ mov dx,SC_INDEX\r
+ mov ax,0f02h\r
+ out dx,ax ; enable writes to all four planes\r
+ mov ax,SCREEN_SEG ; now clear all display memory, 8 pixels\r
+ mov es,ax ; at a time\r
+ sub di,di ; point ES:DI to display memory\r
+ sub ax,ax ; clear to zero-value pixels\r
+ mov cx,8000h ; # of words in display memory\r
+ rep stosw ; clear all of display memory\r
+\r
+ ; Set pysical screen dimensions\r
+\r
+ lodsw ; Load scrn pixel width\r
+ mov [_ScrnPhysicalPixelWidth],ax ; from tweak table and store\r
+ mov [_SplitScrnScanLine],ax ; No splitscrn ==\r
+ ; splitscrn=PhysicalscrnHeight\r
+ mov bx,ax ; Copy width for later use\r
+ shr ax,2 ; Convert to byte width\r
+ mov [_ScrnPhysicalByteWidth],ax ; Store for later use\r
+ lodsw ; Load Screen Phys. Height\r
+ mov [_ScrnPhysicalHeight],ax ; Store for later use\r
+\r
+\r
+ ; Mode X is set, now set the required logical page width.\r
+\r
+ mov cx,[logicalscrwidth]\r
+\r
+ call SetLogicalScrWidth\r
+\r
+ pop di ;restore C register vars\r
+ pop si\r
+ pop bp ;restore caller's stack frame\r
+ ret\r
+_x_set_mode endp\r
+\r
+;----------------------------------------------------------------------\r
+; Mode X (256 color mode) set default access video plane\r
+;\r
+; C near-callable as:\r
+; void x_select_default_plane(unsigned char plane);\r
+;\r
+; Enables Read/Write access to a plane using general memory access\r
+; methods\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_select_default_plane proc\r
+ARG Plane:byte\r
+ push bp\r
+ mov bp,sp ; set up stack frame\r
+ mov cl,byte ptr [Plane]\r
+\r
+ ; SELECT WRITE PLANE\r
+ and cl,011b ;CL = plane\r
+ mov ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg\r
+ shl ah,cl ;set only the bit for the required\r
+ ; plane to 1\r
+ mov dx,SC_INDEX ;set the Map Mask to enable only the\r
+ out dx,ax ; pixel's plane\r
+\r
+ ; SELECT READ PLANE\r
+ mov ah,cl ;AH = plane\r
+ mov al,READ_MAP ;AL = index in GC of the Read Map reg\r
+ mov dx,GC_INDEX ;set the Read Map to read the pixel's\r
+ out dx,ax ; plane\r
+\r
+ pop bp\r
+ ret\r
+_x_select_default_plane endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; Mode X (256 color mode) Set Mode X split screen starting row\r
+; The split screen resides on the bottom half of the screen and has a\r
+; starting address of A000:0000\r
+;\r
+; C near-callable as:\r
+; void x_set_splitscreen(unsigned int line);\r
+;\r
+; Updates _Page0_Offs to reflect the existence of the split screen region\r
+; ie _MainScrnOffset is set to the offset of the first pixel beyond the split\r
+; screen region\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+\r
+_x_set_splitscreen proc\r
+ ARG Line:word\r
+ push bp\r
+ mov bp,sp ; set up stack frame\r
+ push si\r
+\r
+ xor si,si ; si=0 -> x virtual page start coord\r
+\r
+ cmp [_DoubleBufferActive],0\r
+ jne @@error\r
+\r
+ cmp [_SplitScrnActive],0\r
+ je @@NotPreviouslyCalled\r
+\r
+@@error:\r
+ mov [_ErrorValue],ERROR\r
+ pop si\r
+ pop bp ; Return if previously called\r
+ ret\r
+\r
+@@NotPreviouslyCalled:\r
+\r
+ ; Turn on split screen pal pen suppression, so the split screen\r
+ ; wo'nt be subject to pel panning as is the non split screen portion.\r
+\r
+ mov dx,INPUT_STATUS_0\r
+ in al,dx ; Reset the AC Index/Data toggle to\r
+ ; index state\r
+ mov al,AC_MODE_CONTROL+20h ; Bit 5 set to prevent screen blanking\r
+ mov dx,AC_INDEX ; Point AC to Index/Data register\r
+ out dx,al\r
+ inc dx ; Point to AC Data reg (for reads only)\r
+ in al,dx ; Get the current AC Mode Control reg\r
+ or al,20h ; Enable split scrn Pel panning suppress.\r
+ dec dx ; Point to AC Index/Data reg (for writes only)\r
+ out dx,al ; Write the new AC Mode Control setting\r
+ ; with split screen pel panning\r
+ ; suppression turned on\r
+\r
+ mov [_PhysicalStartByteX],ax ; Set the Phisical screen start\r
+ mov [_PhysicalStartPixelX],ax ; offset within virtual screen\r
+ mov [_PhysicalStartY],ax\r
+ mov [_SplitScrnActive],TRUE\r
+ mov ax,[Line]\r
+ jns @@NotNeg ; Check that Split Scrn start scan line is +ve\r
+\r
+ mov ax,0 ; Since -ve set to 0\r
+\r
+@@NotNeg:\r
+ mov [_SplitScrnScanLine],ax ; save the scanline\r
+\r
+\r
+\r
+ or [DoubleScanFlag],0\r
+ jz @@NotDoubleScanned\r
+ shl ax,1\r
+ dec ax\r
+@@NotDoubleScanned:\r
+ ;mov cl,[DoubleScanFlag]\r
+ ;shl ax,cl ; Mode X 200 and 240 line modes are actually\r
+ ; 400 and 480 lines that are double scanned\r
+ ; so for start scanline multiply required ModeX\r
+ ; scan line by 2 if its a double scanned mode\r
+\r
+\r
+ mov bx,ax ; save the scanline\r
+\r
+\r
+ WaitVsyncStart ; wait for vertical retrace\r
+\r
+ cli ; Dont allow register setting to be interrupted\r
+ mov dx,CRTC_INDEX\r
+ mov ah,bl\r
+ mov al,LINE_COMPARE\r
+ out dx,ax ; Bits 7-0 of the split screen scan line\r
+\r
+ mov ah,bh\r
+ and ah,1\r
+ shl ah,4\r
+ mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split\r
+ out dx,al ; screen scan line,\r
+ inc dx ; So using readability of VGA registers\r
+ in al,dx ; Read the OVERFLOW register, and set the\r
+ and al, not 10h ; bit corresponding to Bit 8 (above)\r
+ or al,ah\r
+ out dx,al\r
+\r
+ dec dx\r
+ mov ah,bh\r
+ and ah,2\r
+ ror ah,3\r
+ mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register =\r
+ out dx,al ; Bit 9 of split screen scan line\r
+ inc dx ; As we did before, update the apropriate\r
+ in al,dx ; bit without disturbing the rest\r
+ and al, not 40h\r
+ or al,ah\r
+ out dx,al\r
+ sti ; Registers are set, so interrupts are safe\r
+\r
+ mov ax,[_ScrnPhysicalHeight] ; Determine where the first byte\r
+ sub ax,[_SplitScrnScanLine] ; of the non split screen video ram\r
+ mov [_SplitScrnVisibleHeight],ax ; starts and store it for reference\r
+\r
+ mov bx,[_ScrnLogicalByteWidth]\r
+ mul bx\r
+ mov [_Page0_Offs],ax\r
+ mov [_Page1_Offs],ax\r
+ mov [_Page2_Offs],ax\r
+\r
+ ; calculate no. non split screen rows in video ram\r
+ mov cx,0ffffh ; cx = Maximum video ram offset\r
+ sub cx,ax ; cx = cx - _Page0_Offs\r
+ xchg cx,ax ; swap cx and ax\r
+ sub dx,dx ; DX:AX is divide operand, set DX = 0\r
+ div bx ; divide ax (prev cx) by\r
+ ; ScrnLogicalByteWidth\r
+\r
+ mov [_ScrnLogicalHeight],ax ; Save Screen Logical Height\r
+ cmp ax,[_BottomClip]\r
+ jle @@BottomClipOK ; Adjust Clip Rectangle if necessary\r
+ mov [_BottomClip],ax\r
+@@BottomClipOK:\r
+ sub ax,[_SplitScrnScanLine] ; Update the maximum Y position of\r
+ mov [_MaxScrollY],ax ; Physical screen in logical screen\r
+\r
+ xchg cx,ax ; restore original ax (MainScrnOfs)\r
+ mov bh,al ; Set the visible screen start address\r
+ mov ch,ah ; to the top left corner of the virtual\r
+ jmp StartAddrEntry ; screen\r
+_x_set_splitscreen endp\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; Mode X (256 color mode) Page flip primer\r
+; No clipping is performed.\r
+; C near-callable as:\r
+;\r
+; void x_page_flip(unsigned int x, unsigned int y);\r
+;\r
+; Swaps visible and hidden page offsets and then executes the SetStartAddr\r
+; to achieve a page flip.\r
+;\r
+; SEE x_set_start_addr below\r
+;\r
+; Written by Themie Gouthas\r
+;------------------------------------------------------------------------\r
+\r
+_x_page_flip proc\r
+ ARG x:word,y:word\r
+ push bp ;preserve caller's stack frame\r
+ mov bp,sp ;point to local stack frame\r
+ push si\r
+\r
+ mov si,[x]\r
+ mov ax,[_ScrnLogicalByteWidth] ; Calculate Offset increment\r
+ mov cx,[y]\r
+ mul cx ; for Y\r
+ cmp [_DoubleBufferActive],TRUE ; Do we have double buffering ?\r
+ je @@DoubleBuffer\r
+ cmp [_TrippleBufferActive],TRUE\r
+ jne PageFlipEntry1\r
+\r
+; TrippleBuffer\r
+ mov bx,[_HiddenPageOffs]\r
+ xchg bx,[_VisiblePageOffs]\r
+ xchg bx,[_WaitingPageOffs]\r
+ mov [_HiddenPageOffs],bx\r
+ mov bx,[_VisiblePageIdx]\r
+ inc bx\r
+ cmp bx,3\r
+ jne @@IdxOk\r
+ xor bx,bx\r
+@@IdxOk:\r
+ mov [_VisiblePageIdx],bx\r
+ jmp short PageFlipEntry2\r
+@@DoubleBuffer:\r
+ mov bx,[_HiddenPageOffs]\r
+ xchg bx,[_VisiblePageOffs] ; Swap the Page Offsete\r
+ xchg [_HiddenPageOffs],bx\r
+ xor [_VisiblePageIdx],01h ; Set the Visible page index\r
+ jmp short PageFlipEntry2\r
+_x_page_flip endp\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; Mode X (256 color mode) Set Mode X non split screen start address\r
+; of logical screen.\r
+; C near-callable as:\r
+;\r
+; void x_set_start_addr(unsigned int x, unsigned int y);\r
+;\r
+; Params: StartOffset is offset of first byte of logical screen ram\r
+; (Useful if you want to double buffer by splitting your non\r
+; split screen video ram into 2 pages)\r
+; X,Y coordinates of the top left hand corner of the physical screen\r
+; within the logical screen\r
+; X must not exceed (Logical screen width - Physical screen width)\r
+; Y must not exceed (Logical screen height - Physical screen height)\r
+;\r
+;\r
+; Written by Themie Gouthas,\r
+; Parts addapted from M. Abrash code published in DDJ Mag.\r
+;------------------------------------------------------------------------\r
+_x_set_start_addr proc\r
+ ARG x:word,y:word\r
+ push bp\r
+ mov bp,sp\r
+ push si\r
+\r
+ mov si,[x]\r
+ mov ax,[_ScrnLogicalByteWidth] ; Calculate Offset increment\r
+ mov cx,[y] ; for Y\r
+ mul cx\r
+ cmp [_DoubleBufferActive],TRUE ; Do we have double buffering ?\r
+ je @@PageResolution\r
+ cmp [_TrippleBufferActive],TRUE\r
+ je @@PageResolution\r
+PageFlipEntry1:\r
+ add ax,[_Page0_Offs] ; no - add page 0 offset\r
+ jmp short @@AddColumn\r
+\r
+PageFlipEntry2:\r
+\r
+ mov [_PhysicalStartPixelX],si\r
+ mov [_PhysicalStartY],cx\r
+\r
+@@PageResolution:\r
+ add ax,[_VisiblePageOffs] ; Add visible page offset\r
+\r
+@@AddColumn:\r
+ mov cx,si\r
+ shr cx,2\r
+ mov [_PhysicalStartByteX],cx\r
+ add ax,cx ; add the column offset for X\r
+ mov bh,al ; setup CRTC start addr regs and\r
+ ; values in word registers for\r
+ mov ch,ah ; fast word outs\r
+\r
+StartAddrEntry:\r
+ mov bl,ADDR_LOW\r
+ mov cl,ADDR_HIGH\r
+ and si,0003h ; select pel pan register value for the\r
+ mov ah,PelPanMask[si] ; required x coordinate\r
+ mov al,PEL_PANNING+20h\r
+ mov si,ax\r
+\r
+ cmp [_VsyncHandlerActive],TRUE\r
+ jne @@NoVsyncHandler\r
+; NEW STUFF\r
+@@WaitLast:\r
+ cmp [_StartAddressFlag],0\r
+ jne @@WaitLast\r
+ cli\r
+ mov [_WaitingStartLow],bx\r
+ mov [_WaitingStartHigh],cx\r
+ mov [_WaitingPelPan],si\r
+ mov [_StartAddressFlag],1\r
+ sti\r
+ jmp short @@Return\r
+\r
+@@NoVsyncHandler:\r
+ mov dx,INPUT_STATUS_0 ;Wait for trailing edge of Vsync pulse\r
+@@WaitDE:\r
+ in al,dx\r
+ test al,01h\r
+ jnz @@WaitDE ;display enable is active low (0 = active)\r
+\r
+ mov dx,CRTC_INDEX\r
+ mov ax,bx\r
+ cli\r
+ out dx,ax ;start address low\r
+ mov ax,cx\r
+ out dx,ax ;start address high\r
+ sti\r
+\r
+; Now wait for vertical sync, so the other page will be invisible when\r
+; we start drawing to it.\r
+ mov dx,INPUT_STATUS_0 ;Wait for trailing edge of Vsync pulse\r
+@@WaitVS:\r
+ in al,dx\r
+ test al,08h\r
+ jz @@WaitVS ;display enable is active low (0 = active)\r
+\r
+\r
+ mov dx,AC_INDEX\r
+ mov ax,si ; Point the attribute controller to pel pan\r
+ cli\r
+ out dx,al ; reg. Bit 5 also set to prevent blanking\r
+ mov al,ah\r
+ out dx,al ; load new Pel Pan setting.\r
+ sti\r
+\r
+@@Return:\r
+ mov [_ErrorValue],OK\r
+ pop si\r
+ pop bp\r
+ ret\r
+_x_set_start_addr endp\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; Mode X (256 color mode) Mode X split screen hide\r
+; C near-callable as:\r
+;\r
+; void x_hide_splitscreen()\r
+;\r
+; Hides an existing split screen by setting its starting scan line to\r
+; the last physical screen scan line\r
+;\r
+; WARNING: Only to be used if SplitScrnLine has been previously called\r
+; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for\r
+; the initial split screen is reserved and the size limitations\r
+; of these modes means any change in the split screen scan line\r
+; will encroach on the split screen ram\r
+;\r
+; Written by Themie Gouthas\r
+;------------------------------------------------------------------------\r
+\r
+_x_hide_splitscreen proc\r
+ push bp\r
+ mov bp,sp\r
+\r
+ cmp [_SplitScrnActive],TRUE\r
+ je @@SplitScreenEnabled\r
+\r
+@@error:\r
+ mov [_ErrorValue],ERROR\r
+ pop bp\r
+ ret\r
+\r
+@@SplitScreenEnabled:\r
+ cmp [_CurrXMode],4 ; Do nothing for Modes > 2\r
+ jg @@error\r
+ mov bx,[_ScrnPhysicalHeight]\r
+\r
+ mov ax,[_ScrnLogicalHeight]\r
+ sub ax,bx\r
+ mov [_MaxScrollY],ax\r
+ xor ax,ax\r
+ mov [_SplitScrnVisibleHeight],ax\r
+\r
+ or [DoubleScanFlag],0\r
+ jz @@NotDoubleScanned\r
+ shl bx,1\r
+ dec bx\r
+@@NotDoubleScanned:\r
+ ;mov cl,[DoubleScanFlag] ; Compensate for double scanned modes\r
+ ;shl bx,cl\r
+\r
+ WaitVsyncStart ; wait for vertical retrace\r
+\r
+ cli ; Dont allow register setting to be interrupted\r
+ mov dx,CRTC_INDEX\r
+ mov ah,bl\r
+ mov al,LINE_COMPARE\r
+ out dx,ax ; Bits 7-0 of the split screen scan line\r
+\r
+ mov ah,bh\r
+ and ah,1\r
+ shl ah,4\r
+ mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split\r
+ out dx,al ; screen scan line,\r
+ inc dx ; So using readability of VGA registers\r
+ in al,dx ; Read the OVERFLOW register, and set the\r
+ and al, not 10h ; bit corresponding to Bit 8 (above)\r
+ or al,ah\r
+ out dx,al\r
+\r
+ dec dx\r
+ mov ah,bh\r
+ and ah,2\r
+ ror ah,3\r
+ mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register =\r
+ out dx,al ; Bit 9 of split screen scan line\r
+ inc dx ; As we did before, update the apropriate\r
+ in al,dx ; bit without disturbing the rest\r
+ and al, not 40h\r
+ or al,ah\r
+ out dx,al\r
+ sti ; Registers are set, so interrupts are safe\r
+\r
+@@done:\r
+\r
+ mov [_ErrorValue],OK\r
+ pop bp\r
+ ret\r
+_x_hide_splitscreen endp\r
+\r
+;-----------------------------------------------------------------------\r
+; Mode X (256 color mode) Mode X split screen show\r
+; C near-callable as:\r
+;\r
+; void x_show_splitscreen()\r
+;\r
+; Restores split screen start scan line to the initial split screen\r
+; starting scan line as set by SplitScrnLine.\r
+;\r
+; WARNING: Only to be used if SplitScrnLine has been previously called\r
+; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for\r
+; the initial split screen is reserved and the size limitations\r
+; of these modes means any change in the split screen scan line\r
+; will encroach on the split screen ram\r
+; Update: Now disabled for these modes\r
+;\r
+; Written by Themie Gouthas\r
+;------------------------------------------------------------------------\r
+\r
+\r
+_x_show_splitscreen proc\r
+ push bp\r
+ mov bp,sp\r
+\r
+ cmp [_SplitScrnActive],TRUE\r
+ je @@SplitScreenEnabled\r
+\r
+@@error:\r
+ mov [_ErrorValue],ERROR\r
+ pop bp\r
+ ret\r
+\r
+@@SplitScreenEnabled:\r
+ cmp [_CurrXMode],4 ; Do nothing for Modes > 2\r
+ jg @@error\r
+\r
+ mov bx,[_SplitScrnScanLine]\r
+ mov ax,[_ScrnLogicalHeight] ; Update Max Scroll Y\r
+ sub ax,bx\r
+ mov [_MaxScrollY],ax\r
+\r
+ mov ax,[_ScrnPhysicalHeight]\r
+ sub ax,bx\r
+ mov [_SplitScrnVisibleHeight],ax\r
+\r
+ or [DoubleScanFlag],0\r
+ jz @@NotDoubleScanned\r
+ shl bx,1\r
+ dec bx\r
+@@NotDoubleScanned:\r
+ ;mov cl,[DoubleScanFlag] ; Compensate for double scanned modes\r
+ ;shl bx,cl\r
+ WaitVsyncStart ; wait for vertical retrace\r
+\r
+ cli ; Dont allow register setting to be interrupted\r
+ mov dx,CRTC_INDEX\r
+ mov ah,bl\r
+ mov al,LINE_COMPARE\r
+ out dx,ax ; Bits 7-0 of the split screen scan line\r
+\r
+ mov ah,bh\r
+ and ah,1\r
+ shl ah,4\r
+ mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split\r
+ out dx,al ; screen scan line,\r
+ inc dx ; So using readability of VGA registers\r
+ in al,dx ; Read the OVERFLOW register, and set the\r
+ and al, not 10h ; bit corresponding to Bit 8 (above)\r
+ or al,ah\r
+ out dx,al\r
+\r
+ dec dx\r
+ mov ah,bh\r
+ and ah,2\r
+ ror ah,3\r
+ mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register =\r
+ out dx,al ; Bit 9 of split screen scan line\r
+ inc dx ; As we did before, update the apropriate\r
+ in al,dx ; bit without disturbing the rest\r
+ and al, not 40h\r
+ or al,ah\r
+ out dx,al\r
+ sti ; Registers are set, so interrupts are safe\r
+\r
+@@Done:\r
+ mov [_ErrorValue],0\r
+ pop bp\r
+ ret\r
+_x_show_splitscreen endp\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; Mode X (256 color mode) Modify Mode X split screen starting scan line\r
+; C near-callable as:\r
+;\r
+; void x_adjust_splitscreen(unsigned int ScanLine)\r
+;\r
+; Sets the split screen start scan line to a new scan line. Valid scan lines\r
+; are between the initial split screen starting scan line and the last\r
+; physical screen scan line.\r
+;\r
+; WARNING: Only to be used if SplitScrnLine has been previously called\r
+; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for\r
+; the initial split screen is reserved and the size limitations\r
+; of these modes means any change in the split screen scan line\r
+; will encroach on the split screen ram\r
+; Update: Now disabled for these modes\r
+;\r
+;\r
+; Written by Themie Gouthas\r
+;------------------------------------------------------------------------\r
+\r
+\r
+_x_adjust_splitscreen proc\r
+ ARG ScanLine\r
+ push bp\r
+ mov bp,sp\r
+\r
+ cmp [_SplitScrnActive],TRUE\r
+ je @@SplitScreenEnabled\r
+\r
+@@error:\r
+ mov [_ErrorValue],ERROR\r
+ pop bp\r
+ ret\r
+\r
+@@SplitScreenEnabled:\r
+ cmp [_CurrXMode],4 ; Do nothing for Modes > 2\r
+ jg @@error\r
+ mov bx,[ScanLine] ; Is the required starting scan line\r
+ cmp bx,[_SplitScrnScanLine] ; valid ?\r
+ js @@Done ; No - Then do nothing\r
+\r
+@@ValidScanLine:\r
+\r
+ mov ax,[_ScrnLogicalHeight] ; Update Max Scroll Y\r
+ sub ax,bx\r
+ mov [_MaxScrollY],ax\r
+\r
+ mov ax,[_ScrnPhysicalHeight]\r
+ sub ax,bx\r
+ mov [_SplitScrnVisibleHeight],ax\r
+\r
+ or [DoubleScanFlag],0\r
+ jz @@NotDoubleScanned\r
+ shl bx,1\r
+ dec bx\r
+@@NotDoubleScanned:\r
+ ;mov cl,[DoubleScanFlag] ; Compensate for double scanned modes\r
+ ;shl bx,cl\r
+\r
+ WaitVsyncStart ; wait for vertical retrace\r
+\r
+ cli ; Dont allow register setting to be interrupted\r
+\r
+ mov dx,CRTC_INDEX\r
+ mov ah,bl\r
+ mov al,LINE_COMPARE\r
+ out dx,ax ; Bits 7-0 of the split screen scan line\r
+\r
+ mov ah,bh\r
+ and ah,1\r
+ shl ah,4\r
+ mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split\r
+ out dx,al ; screen scan line,\r
+ inc dx ; So using readability of VGA registers\r
+ in al,dx ; Read the OVERFLOW register, and set the\r
+ and al, not 10h ; bit corresponding to Bit 8 (above)\r
+ or al,ah\r
+ out dx,al\r
+\r
+ dec dx\r
+ mov ah,bh\r
+ and ah,2\r
+ ror ah,3\r
+ mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register =\r
+ out dx,al ; Bit 9 of split screen scan line\r
+ inc dx ; As we did before, update the apropriate\r
+ in al,dx ; bit without disturbing the rest\r
+ and al, not 40h\r
+ or al,ah\r
+ out dx,al\r
+ sti ; Registers are set, so interrupts are safe\r
+@@Done:\r
+ mov [_ErrorValue],OK\r
+ pop bp\r
+ ret\r
+_x_adjust_splitscreen endp\r
+\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; Mode X (256 color mode) Enable DoubleBuffering on non split screen area\r
+; C near-callable as:\r
+;\r
+; int x_set_doublebuffer(unsigned int PageHeight);\r
+;\r
+; Params: PageHeight is the height of the virtual screen to double buffer\r
+; Returns the closest possible height to the specified.\r
+;\r
+; Sets up two double buffering virtual pages\r
+; GLOBAL variables set:\r
+;\r
+; _Page1_Offs Offset of second virtual page\r
+; _NonVisual_Offs Offset of first non visible video ram byte\r
+; _DoubleBufferActive Flag\r
+; _PageAddrTable Table of Double buffering pages start offsets\r
+; _ScrnLogicalHeight Logical height of the double buffering pages\r
+;\r
+;\r
+; Written by Themie Gouthas\r
+;------------------------------------------------------------------------\r
+\r
+\r
+_x_set_doublebuffer proc\r
+ ARG PageHeight:word\r
+ push bp\r
+ mov bp,sp\r
+\r
+ cmp [_DoubleBufferActive],0\r
+ je @@OkToContinue\r
+@error:\r
+ mov [_ErrorValue],ERROR\r
+ pop bp\r
+ ret\r
+\r
+@@OkToContinue:\r
+ mov [_VisiblePageIdx],0 ; Set visible Page to 0\r
+ mov ax,[_ScrnLogicalHeight] ; Set Maximum D.B. Page height to\r
+ shr ax,1 ; _ScrnLogicalHeight / 2\r
+\r
+ mov bx,[PageHeight] ; Is the require D.B. Page Height\r
+ cmp ax,bx ; > the Maximum D.B. Page Height ?\r
+\r
+ js @@InvalidHeight ; no - jump\r
+ mov ax,bx ; yes - Set the D.B. Page height to\r
+ ; to the maximum allowed.\r
+\r
+@@InvalidHeight:\r
+ mov [_ScrnLogicalHeight],ax ; Update logical screen height to\r
+ ; reflect the height of a D.B. page\r
+ cmp ax,[_BottomClip]\r
+ jle @@BottomClipOK ; Adjust Clip Rectangle if necessary\r
+ mov [_BottomClip],ax\r
+@@BottomClipOK:\r
+ push ax\r
+ mul [_ScrnLogicalByteWidth] ; Calculate the offset of the second\r
+ mov cx,ax ; D.B. Page in video ram\r
+ mov bx,[_Page0_Offs]\r
+ mov [_VisiblePageOffs],bx\r
+\r
+ add ax,bx\r
+ mov [_Page1_Offs],ax ; Save it\r
+ mov [_HiddenPageOffs],ax\r
+\r
+ add ax,cx ; Calculate the offset of first byte\r
+ mov [_NonVisual_Offs],ax ; beyond the D.B. pages and save it\r
+ mov [_DoubleBufferActive],TRUE ; Set flag indicating D.B'ing mode on\r
+\r
+ pop ax\r
+ sub ax,[_ScrnPhysicalHeight]\r
+ add ax,[_SplitScrnVisibleHeight]\r
+ mov [_MaxScrollY],ax\r
+\r
+ mov ax,dx ; return the D.B. pages' height\r
+ mov [_ErrorValue],OK\r
+ pop bp\r
+ ret\r
+_x_set_doublebuffer endp\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; Mode X (256 color mode) Enable TrippleBuffering on non split screen area\r
+; C near-callable as:\r
+;\r
+; int x_set_tripplebuffer(unsigned int PageHeight);\r
+;\r
+; Params: PageHeight is the height of the virtual screen to tripple buffer\r
+; Returns the closest possible height to the specified.\r
+;\r
+; Sets up two tripple buffering virtual pages\r
+; GLOBAL variables set:\r
+;\r
+; _Page1_Offs Offset of second virtual page\r
+; _Page2_Offs Offset of third virtual page\r
+; _NonVisual_Offs Offset of first non visible video ram byte\r
+; _DoubleBufferActive Flag\r
+; _PageAddrTable Table of Double buffering pages start offsets\r
+; _ScrnLogicalHeight Logical height of the double buffering pages\r
+;\r
+;\r
+; Almost written by Tore Bastiansen (cut & paste from _x_set_doublebuffer)\r
+;------------------------------------------------------------------------\r
+\r
+_x_set_tripplebuffer proc\r
+ ARG PageHeight:word\r
+ push bp\r
+ mov bp,sp\r
+\r
+ cmp [_DoubleBufferActive],0\r
+ jne @@Error\r
+ cmp [_TrippleBufferActive],0\r
+ je @@OkToContinue\r
+@@Error:\r
+ mov [_ErrorValue],ERROR\r
+ pop bp\r
+ ret\r
+\r
+@@OkToContinue:\r
+ mov [_VisiblePageIdx],0 ; Set visible Page to 0\r
+ mov ax,[_ScrnLogicalHeight] ; Set Maximum T.B. Page height to\r
+ mov bx,3\r
+ xor dx,dx\r
+ idiv bx ; _ScrnLogicalHeight / 3\r
+\r
+ mov bx,[PageHeight] ; Is the require T.B. Page Height\r
+ cmp ax,bx ; > the Maximum T.B. Page Height ?\r
+\r
+ js @@InvalidHeight ; no - jump\r
+ mov ax,bx ; yes - Set the T.B. Page height to\r
+ ; to the maximum allowed.\r
+\r
+@@InvalidHeight:\r
+ mov [_ScrnLogicalHeight],ax ; Update logical screen height to\r
+ ; reflect the height of a T.B. page\r
+ cmp ax,[_BottomClip]\r
+ jle @@BottomClipOK ; Adjust Clip Rectangle if necessary\r
+ mov [_BottomClip],ax\r
+@@BottomClipOK:\r
+ push ax\r
+ mul [_ScrnLogicalByteWidth] ; Calculate the offset of the second\r
+ mov cx,ax ; D.B. Page in video ram\r
+ mov bx,[_Page0_Offs]\r
+ mov [_VisiblePageOffs],bx\r
+\r
+ add ax,bx\r
+ mov [_Page1_Offs],ax ; Save it\r
+ mov [_HiddenPageOffs],ax\r
+\r
+ add ax,cx\r
+ mov [_Page2_Offs],ax ; Save the other it ?\r
+ mov [_WaitingPageOffs],ax\r
+\r
+ add ax,cx ; Calculate the offset of first byte\r
+ mov [_NonVisual_Offs],ax ; beyond the D.B. pages and save it\r
+ mov [_TrippleBufferActive],TRUE ; Set flag indicating T.B'ing mode on\r
+\r
+ pop ax\r
+ sub ax,[_ScrnPhysicalHeight]\r
+ add ax,[_SplitScrnVisibleHeight]\r
+ mov [_MaxScrollY],ax\r
+\r
+ mov ax,dx ; return the D.B. pages' height\r
+ mov [_ErrorValue],OK\r
+ pop bp\r
+ ret\r
+_x_set_tripplebuffer endp\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; Set Clipping rectangle\r
+; C callable as:\r
+;\r
+;\r
+; int x_set_cliprect(WORD left,WORD top, WORD right, WORD bottom);\r
+;\r
+;\r
+; NOTE clipping is byte oriented. "left" and "right" are in bytes not pixels.\r
+; Only selected functions perform any clipping at all.\r
+;\r
+; Written by Themie Gouthas\r
+;------------------------------------------------------------------------\r
+\r
+_x_set_cliprect proc\r
+ARG left:word,top:word,right:word,bottom:word\r
+ push bp\r
+ mov bp,sp\r
+ mov ax,[left]\r
+ mov bx,[right]\r
+ cmp bx,ax\r
+ jns @@CorrectXOrder\r
+ xchg bx,ax\r
+@@CorrectXOrder:\r
+ mov [_LeftClip],ax\r
+ mov [_RightClip],bx\r
+ mov ax,[top]\r
+ mov bx,[bottom]\r
+ cmp bx,ax\r
+ jns @@CorrectYOrder\r
+ xchg bx,ax\r
+@@CorrectYOrder:\r
+ mov [_TopClip],ax\r
+ mov [_BottomClip],bx\r
+ pop bp\r
+ ret\r
+_x_set_cliprect endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; Return to text mode\r
+;\r
+_x_text_mode proc\r
+ push bp\r
+ call clear_vram\r
+ mov ax,03h ; Restore Text Mode\r
+ int 10h\r
+\r
+ pop bp\r
+ ret\r
+_x_text_mode endp\r
+\r
+;-----------------------------------------------------------------------\r
+; Wait for Vertical sync\r
+_x_wait_vsync proc\r
+ push bp\r
+ WaitVsyncStart\r
+ pop bp\r
+ ret\r
+_x_wait_vsync endp\r
+\r
+\r
+ end\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XMAIN - Include file\r
+;\r
+; XMAIN.ASM export functions\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+ global _x_set_mode :proc\r
+ global _x_page_flip :proc\r
+ global _x_set_start_addr :proc\r
+ global _x_set_splitscreen :proc\r
+ global _x_text_mode :proc\r
+ global _x_set_mode :proc\r
+ global _x_select_default_plane :proc\r
+ global _x_hide_splitscreen :proc\r
+ global _x_show_splitscreen :proc\r
+ global _x_adjust_splitscreen :proc\r
+ global _x_set_doublebuffer :proc\r
+ global _x_set_tripplebuffer :proc\r
+ global _x_set_cliprect :proc\r
+ global _x_wait_vsync :proc
\ No newline at end of file
--- /dev/null
+/*----------------------------------------------------------------------\r
+; MODULE XMAKEVBM\r
+;\r
+; Implements function to generate a Video bitmap (VBM) from a linear bitmap\r
+; (LBM)\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+;\r
+; Based on "CreateMaskedAlignedImage" published in Dr Dobbs Journal\r
+; by Michael Abrash (Jul - Aug 1991)\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+; ****** Aeronautical Research Laboratory ****************\r
+; ****** Defence Science and Technology Organisation ****************\r
+; ****** Australia ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------*/\r
+/*\r
+ Here is an outline of the XLIB image formats\r
+\r
+\r
+ PLANAR BITMAPS\r
+ --------------\r
+\r
+ Planar bitmaps as used by these functions have the following structure:\r
+\r
+ BYTE 0 The bitmap width in bytes (4 pixel groups) range 1..255\r
+ BYTE 1 The bitmap height in rows range 1..255\r
+ BYTE 2..n1 The plane 0 pixels width*height bytes\r
+ BYTE n1..n2 The plane 1 pixels width*height bytes\r
+ BYTE n2..n3 The plane 2 pixels width*height bytes\r
+ BYTE n3..n4 The plane 3 pixels width*height bytes\r
+\r
+ LINEAR BITMAPS\r
+ --------------\r
+\r
+ Linear bitmaps have the following structure:\r
+\r
+ BYTE 0 The bitmap width in pixels range 1..255\r
+ BYTE 1 The bitmap height in rows range 1..255\r
+ BYTE 2..n The width*height bytes of the bitmap\r
+\r
+\r
+ VIDEO BITMAPS\r
+ -------------\r
+\r
+ WORD 0 Size Total size of this VBM structure in bytes\r
+ WORD 1 ImageWidth Width in bytes of the image (for all alignments)\r
+ WORD 2 ImageHeight Height in scan lines of the image\r
+\r
+ WORD 3 Alignment 0 ImagePtr Offset in VidRAM of this aligned image\r
+ +--WORD 4 MaskPtr Offset (within this structure's DS) of\r
+ | . alignment masks\r
+ | .\r
+ | .\r
+ | WORD 9 Alignment 3 ImagePtr Offset in VidRAM of this aligned image\r
+ +|--WORD 10 MaskPtr Offset (within this structure's DS) of\r
+ || alignment masks\r
+ ||\r
+ |+->BYTE 21 (WORD 11) -------+-- Image masks for alignment 0\r
+ | . |\r
+ | . |\r
+ | BYTE 21 + ImageWidth*ImageHeight -----+\r
+ |\r
+ | .\r
+ | . (similaly for alignments 1 - 2 )\r
+ | .\r
+ |\r
+ +-->BYTE 21 + 3*ImageWidth*ImageHeight + 1-+-- Image masks for alignment 3\r
+ . |\r
+ . |\r
+ BYTE 21 + 4*(ImageWidth*ImageHeight) --+\r
+\r
+ .\r
+ .\r
+ << Similarly for alignments 2 and 3 >>\r
+ .\r
+ .\r
+ BYTE 21 + 4*(ImageWidth*ImageHeight)\r
+ -------------\r
+\r
+ (And dont forget the corresponding data in video ram)\r
+\r
+\r
+*/\r
+\r
+\r
+\r
+#include <alloc.h>\r
+#include <dos.h>\r
+\r
+/* function to store the linear bitmap in the required video RAM offset */\r
+/* and in the required alignment */\r
+\r
+extern unsigned int x_store_vbm_image(unsigned int, int, char far *);\r
+\r
+\r
+/* Alignment structures, 4 of which make up the header section of the */\r
+/* video bitmap */\r
+\r
+typedef struct {\r
+ unsigned int size;\r
+ unsigned int ImageWidth;\r
+ unsigned int ImageHeight;\r
+ struct {\r
+ unsigned int ImagePtr;\r
+ unsigned int MaskPtr;\r
+ } alignments[4];\r
+} alignment_header;\r
+\r
+/* Structure to extract width/height frol LBM (linear bit map) */\r
+\r
+typedef struct {\r
+ unsigned char width;\r
+ unsigned char height;\r
+} lbm_header;\r
+\r
+\r
+/*************************************************************************/\r
+/* */\r
+/* Generates all four possible mode X image/mask alignments, stores */\r
+/* image alignments in display memory, allocates memory for and generates*/\r
+/* mask alignments, and fills out a VBM aligned masked image structure. */\r
+/* Each non-zero byte in source bitmap corresponds to image pixel to be */\r
+/* drawn. */\r
+/* On success returns a far pointer to the new VBM structure otherwise */\r
+/* it returns NULL */\r
+/* */\r
+/* Source Language: C */\r
+/* */\r
+/* Parameters: */\r
+/* lbm pointer to linear bitmap */\r
+/* vramStart contains the next available video offset which is */\r
+/* also updated after calling this function */\r
+/* */\r
+/*************************************************************************/\r
+\r
+char far *x_make_vbm(char far *lbm, unsigned int *VramStart)\r
+{\r
+\r
+ lbm_header far *lbm_headr;\r
+ alignment_header far *vbm_headr;\r
+ char far *vbm_mask_ptr,*p;\r
+ char far *lbm_pixel_ptr;\r
+ int align,BitNum,TempImageWidth;\r
+ unsigned int TempWidth,TempHeight,TempSize,MaskSize,VramOffs,MaskSpace=0;\r
+ int scanline;\r
+ unsigned char MaskTemp;\r
+\r
+ VramOffs = *VramStart;\r
+ lbm_headr = (lbm_header far *) lbm;\r
+\r
+ TempWidth = (lbm_headr->width+3)/4+1;\r
+ TempHeight = lbm_headr->height;\r
+ TempSize = TempWidth*TempHeight;\r
+\r
+ vbm_headr = (alignment_header far *) farmalloc(22+TempSize*4);\r
+ if (!vbm_headr) return NULL;\r
+\r
+ MaskSpace=22;\r
+\r
+ vbm_headr->ImageWidth = TempWidth;\r
+ vbm_headr->ImageHeight = TempHeight;\r
+ vbm_headr->size = 22+TempSize*4;\r
+ for (align=0;align<4;align++){\r
+ vbm_headr->alignments[align].ImagePtr = VramOffs;\r
+ x_store_vbm_image(VramOffs,align,lbm);\r
+ MaskSpace+=TempSize;\r
+ VramOffs+=TempSize;\r
+ }\r
+\r
+\r
+ vbm_mask_ptr = (char far *)vbm_headr+22;\r
+\r
+ for (align=0;align<4;align++){\r
+ lbm_pixel_ptr = lbm + 2;\r
+ vbm_headr->alignments[align].MaskPtr = FP_OFF(vbm_mask_ptr);\r
+ for (scanline=0;scanline<TempHeight;scanline++){\r
+ BitNum=align;\r
+ MaskTemp=0;\r
+ TempImageWidth=lbm_headr->width;\r
+ do {\r
+ MaskTemp |= (*lbm_pixel_ptr++ !=0) << BitNum;\r
+ if (++BitNum > 3) {\r
+ *vbm_mask_ptr++=MaskTemp;\r
+ MaskTemp=BitNum=0;\r
+ }\r
+ } while (--TempImageWidth);\r
+ *vbm_mask_ptr++=(BitNum != 0)?MaskTemp:0;\r
+ }\r
+\r
+ }\r
+\r
+ *VramStart=VramOffs;\r
+ return (char far *) vbm_headr;\r
+}\r
+\r
+\r
+\1a
\ No newline at end of file
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XMOUSE\r
+;\r
+; Mouse functions functions for all MODE X 256 Color resolutions\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; This module is based on Shane Hyde's module of the same name,\r
+; posted to Rec.Games.Programmer, October 92.\r
+;\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; mouse cursor shape by Tiaan A Geldenhuys\r
+;\r
+;-----------------------------------------------------------------------\r
+\r
+COMMENT $\r
+\r
+\r
+This is a module implementing very basic mouse functions.\r
+\r
+It does not support the full functionality of:\r
+\r
+ SPLIT SCREENS\r
+ SCROLLED WINDOWS\r
+ VIRTUAL WINDOWS\r
+\r
+ --------------------------------------\r
+\r
+ MS Mouse Driver Functions\r
+\r
+ Mouse Initialization 0\r
+ Show Cursor 1\r
+ Hide Cursor 2\r
+ Get Mouse Position & Button Status 3\r
+ Set Mouse Cursor Position 4\r
+ Get Button Press Information 5\r
+ Get Button Release Information 6\r
+ Set Min/Max Horizontal Position 7\r
+ Set Min/Max Vertical Position 8\r
+ Define Graphics Cursor Block 9\r
+ Define Text Cursor 10\r
+ Read Mouse Motion Counters 11\r
+ Define Event Handler 12\r
+ Light Pen Emulation Mode ON 13\r
+ Light Pen Emulation Mode OFF 14\r
+ Set Mouse Mickey/Pixel Ratio 15\r
+ Conditional Hide Cursor 16\r
+ Set Double-Speed Threshold 19\r
+ --------------------------------------\r
+$\r
+\r
+include xlib.inc\r
+include xdetect.inc\r
+\r
+.data\r
+\r
+global _MouseInstalled :word\r
+global _MouseHidden :word\r
+global _MouseButtonStatus :word\r
+global _MouseX :word\r
+global _MouseY :word\r
+global _MouseFrozen :byte\r
+global _MouseColor :byte\r
+\r
+global _x_define_mouse_cursor :proc\r
+global _x_show_mouse :proc\r
+global _x_hide_mouse :proc\r
+global _x_mouse_remove :proc\r
+global _x_position_mouse :proc\r
+global _x_put_cursor :proc\r
+global _x_update_mouse :proc\r
+global _x_mouse_init :proc\r
+global _x_mouse_window :proc\r
+\r
+\r
+ALIGN 2\r
+\r
+\r
+\r
+ InitMouseDef db 00000001b ; Default mouse mask, note the reverse order\r
+ db 00000011b\r
+ db 00000111b\r
+ db 00001111b\r
+ db 00011111b\r
+ db 00111111b\r
+ db 01111111b\r
+ db 11111111b\r
+ db 00011111b\r
+ db 00011011b\r
+ db 00110001b\r
+ db 00110000b\r
+ db 01100000b\r
+ db 01100000b\r
+\r
+\r
+\r
+COMMENT $\r
+\r
+ Old mouse definition\r
+\r
+ InitMouseDef db 00000001b ; Default mouse mask, note the reverse order\r
+ db 00000011b\r
+ db 00000111b\r
+ db 00001111b\r
+ db 00011111b\r
+ db 00111111b\r
+ db 01111111b\r
+ db 11111111b\r
+ db 00011100b\r
+ db 00111100b\r
+ db 01111100b\r
+ db 00000000b\r
+ db 00000000b\r
+ db 00000000b\r
+\r
+$\r
+\r
+ MouseMask db 168 dup(?)\r
+ OldHandlerSeg dw ?\r
+ OldHandlerOffs dw ?\r
+ OldHandlerMask dw ?\r
+ OldX dw ?\r
+ OldY dw ?\r
+ OldScrnOffs dw ?\r
+\r
+ BGSaveOffs dw 0\r
+\r
+ _MouseInstalled dw 0 ; Flag indicating whether mouse is installed\r
+ _MouseHidden dw 0 ; Flag indicating whether mouse is hidden\r
+ _MouseButtonStatus dw 0 ; Holds current button press information\r
+ _MouseX dw 0 ; Coords of cursor hot spot\r
+ _MouseY dw 0\r
+ _MouseFrozen db 0 ; Mouse motion enable/disable control\r
+ _MouseColor db 0 ; Mouse cursor colour\r
+\r
+ inhandler db 0\r
+.code\r
+\r
+;----------------------------------------------------------------------\r
+; Local function that updates the cursor position\r
+;\r
+; Destroys SI,DI,AX,BX\r
+;\r
+;----------------------------------------------------------------------\r
+proc update_cursor near\r
+ WaitVsyncStart\r
+\r
+ mov di,[OldScrnOffs] ; Delete cursor (restore old background)\r
+ mov ax,[OldY]\r
+ mov bx,[OldX]\r
+\r
+ call restorebg\r
+\r
+ mov si,[_VisiblePageOffs] ; Save cursor background\r
+ mov ax,[_MouseY]\r
+ mov bx,[_MouseX]\r
+ mov [OldScrnOffs],si\r
+ mov [OldY],ax\r
+ mov [OldX],bx\r
+ call getbg\r
+\r
+ push [_VisiblePageOffs] ; Draw the cursor\r
+ mov ax,[_ScrnPhysicalHeight]\r
+ push ax\r
+ mov ax,0\r
+ push ax\r
+ push [OldY]\r
+ push [OldX]\r
+ call _x_put_cursor\r
+ add sp,10\r
+ ret\r
+update_cursor endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_mouse_init - Initialise Mode X mouse handler\r
+;\r
+; C Prototype\r
+;\r
+; int x_mouse_init()\r
+;\r
+; This is the first function you must call before using any of the mouse\r
+; functions\r
+;\r
+; WARNING: This function uses and updates "NonVisual_Offset" to allocate\r
+; video ram for the saved mouse background.\r
+;\r
+; This mouse code uses the fastest possible techniques to save and restore\r
+; mouse backgrounds and to draw the mouse cursor.\r
+;\r
+; LIMITATIONS: No clipping is supported horizontally for the mouse cursor\r
+; No validity checking is performed for NonVisual_Offs\r
+;\r
+;\r
+; **WARNING** Hide or freeze mouse while drawing using any of the other\r
+; Modules. VGA register settings are not preserved which will\r
+; result in unpredictable drawing behavior.\r
+; If you know the drawing will occur away from the mouse cursor\r
+; set MouseFrozen to TRUE (1), do your drawing then set it to\r
+; FALSE (0). Alternatively call "x_hide_mouse", perform your\r
+; drawing and then call "x_show_mouse"\r
+;\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_mouse_init proc\r
+ push bp\r
+ mov bp,sp\r
+\r
+ cmp [_MouseButtonCount],0 ; Dont initialize if mouse detection\r
+ jne @@DontInitialize ; or initialization function previously\r
+ ; called\r
+ xor ax,ax ; FUNC 0: Mouse Initialization\r
+ int 33h ;\r
+ or ax,ax ; Is there a mouse installed ?\r
+ jz @@Done\r
+ mov [_MouseButtonCount],bx ; Set the button count\r
+\r
+@@DontInitialize:\r
+\r
+ mov [_MouseInstalled],ax\r
+ or ax,ax ; Do we have an installed mouse driver ?\r
+ jz @@Done ; Nop!\r
+\r
+ mov ax,[_NonVisual_Offs]; ; Allocate VRAM for saved background\r
+ mov BGSaveOffs,ax\r
+\r
+ add ax,14*3\r
+ mov [_NonVisual_Offs],ax ; Update NonVisualOffset\r
+\r
+ mov ax,02 ; FUNC 2: Hide Cursor\r
+ int 33h ; (hide the mouse driver's default cursor)\r
+ mov _MouseInstalled,TRUE ; Indicate user mouse driver present\r
+\r
+ mov ax,07h ; FUNC 7:Set min/max horizontal position\r
+ mov cx,0\r
+ mov dx,[_ScrnPhysicalPixelWidth]\r
+ shl dx,1 ; Mult X by 2 as cursor steps by 2 pixels\r
+ int 33h ; 0 < X < _ScrnPhysicalPixelWidth\r
+\r
+ mov ax,08h ; FUNC 8:Set min/max vertical position\r
+ mov cx,0\r
+ mov dx,_ScrnPhysicalHeight\r
+ int 33h ; 0 < Y < _ScrnPhysicalHeight\r
+\r
+ mov ax,0fh ; FUNC 15: Mouse Hor/Vert resolution\r
+ mov cx,4 ; Horiz speed >> Value => << Speed\r
+ mov dx,8 ; Vert Speed\r
+ int 33h\r
+\r
+ mov ax,3 ; FUNC 3: Get mouse pos & button status\r
+ int 33h\r
+ mov [_MouseY],dx\r
+ shr cx,1\r
+ mov [_MouseX],cx\r
+\r
+ mov ax,12 ; FUNC 12: Define Event Handler\r
+ mov bx,seg mouse_handler ; ES:DX -> Event handler\r
+ mov es,bx\r
+ mov dx,offset mouse_handler\r
+ mov cx,1fh ; Set handler for all events\r
+ int 33h\r
+\r
+\r
+\r
+ mov [_MouseHidden],TRUE ; Mouse initially hidden\r
+\r
+ push ds ; Set the default cursor shape\r
+ mov ax,offset InitMouseDef\r
+ push ax\r
+ call _x_define_mouse_cursor\r
+ add sp,04h\r
+\r
+ mov ax,[_MouseInstalled] ; Return MouseInstalled flag\r
+@@Done:\r
+ pop bp\r
+ ret\r
+_x_mouse_init endp\r
+\r
+;----------------------------------------------------------------------\r
+; x_mouse_window - Define a mouse window\r
+;\r
+; C Prototype\r
+;\r
+; void x_mouse_window(int x0, int y0, int x1, int y1);\r
+;\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_mouse_window proc\r
+ARG x0:word,y0:word,x1:word,y1:word\r
+ push bp\r
+ mov bp,sp\r
+\r
+ mov ax,7 ; FUNC 7: Set X range\r
+ mov cx,x0\r
+ shl cx,1\r
+ mov dx,x1\r
+ shl dx,1\r
+ int 33h\r
+\r
+ mov ax,8 ; FUNC 8: Set Y range\r
+ mov cx,y0\r
+ mov dx,y1\r
+ int 33h\r
+ pop bp\r
+ ret\r
+_x_mouse_window endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_define_mouse_cursor - Define a mouse cursor from an input bitmask\r
+;\r
+; C Prototype\r
+;\r
+; void x_define_mouse_cursor(char far *MouseDef, unsigned char MouseColor)\r
+;\r
+; WARNING: This function assumes MouseDef points to 14 bytes.\r
+;\r
+; Note: Bit order is in reverse. ie bit 7 represents pixel 0 ..\r
+; bit 0 represents pixel 7 in each "MouseDef" byte.\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_define_mouse_cursor proc\r
+ARG MouseDef:dword,MouseColor:byte\r
+ push bp\r
+ mov bp,sp\r
+\r
+ cmp [_MouseInstalled],FALSE ; Check whether we have installed\r
+ je @@Done ; our mouse handler and leave if not\r
+\r
+ mov al,[MouseColor] ; Set the mouse pointers color\r
+ mov [_MouseColor],al\r
+\r
+ push si\r
+ push di\r
+ push ds\r
+ mov ax,ds ; ES:DI -> Stored plane mask for all\r
+ mov es,ax ; pixel alignments of mouse cursor\r
+ mov di,offset MouseMask\r
+ lds si,MouseDef\r
+ xor cl,cl ; CL = current alignment (initially zero)\r
+@@AlignmentLoop:\r
+ push si ; save MouseDef ptr for next alignment\r
+ mov dh,14 ; Init Row counter to Cursor Height\r
+@@RowLoop:\r
+ lodsb ; Load first cursor def byte each bit\r
+ ; representing pixel in the row\r
+ xor ah,ah ; AH is the shift overflow byte\r
+ shl ax,cl ; Shift mask for current alignment\r
+\r
+ mov bl,al ; store first three nibbles of ax into\r
+ and bl,0fh ; consecutive bytes in the destination\r
+ mov es:[di],bl ; buffer\r
+ inc di\r
+ shr al,4\r
+ stosw\r
+\r
+ dec dh ; Next row for this alignment if there\r
+ jnz @@RowLoop ; are more to do\r
+\r
+ pop si ; point to the start of the cursor def.\r
+ inc cl ; Select next pixel alignment\r
+ cmp cl,4 ; If there are more alignments to do\r
+ jne @@AlignmentLoop ; then jump\r
+\r
+ pop ds\r
+ pop di\r
+ pop si\r
+@@Done:\r
+ pop bp\r
+ ret\r
+_x_define_mouse_cursor endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_show_mouse - Shows a previously hidden mouse cursor\r
+;\r
+; C Prototype\r
+;\r
+; void x_show_mouse()\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_show_mouse proc\r
+ push bp\r
+ mov bp,sp\r
+ cmp [_MouseInstalled],FALSE ; Make sure our handler is installed\r
+ je @@Done\r
+ cmp [_MouseHidden],FALSE ; If not hidden then exit\r
+ je @@Done\r
+ push si\r
+ push di\r
+\r
+\r
+@@WaitEndOfHandler: ; Make sure handler not currently active\r
+ mov cl,[inhandler]\r
+ or cl,cl\r
+ jnz @@WaitEndOfHandler\r
+\r
+\r
+ mov si,[_VisiblePageOffs] ; Save mouse background and pos details\r
+ mov ax,[_MouseY]\r
+ mov bx,[_MouseX]\r
+ mov [OldScrnOffs],si\r
+ mov [OldY],ax\r
+ mov [OldX],bx\r
+ call getbg\r
+\r
+ push [_VisiblePageOffs] ; Draw cursor\r
+ push [_ScrnLogicalHeight]\r
+ xor ax,ax\r
+ push ax\r
+ push [OldY]\r
+ push [OldX]\r
+ call _x_put_cursor\r
+ add sp,10\r
+\r
+ mov [_MouseHidden],FALSE ; Indicate mouse cursor no longer hidden\r
+\r
+ pop di\r
+ pop si\r
+@@Done:\r
+ pop bp\r
+ ret\r
+_x_show_mouse endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_hide_mouse - Hides a previously visible mouse cursor\r
+;\r
+; C Prototype\r
+;\r
+; void x_hide_mouse()\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_hide_mouse proc\r
+ push bp\r
+ mov bp,sp\r
+\r
+ cmp [_MouseInstalled],FALSE ; Make sure our handler is installed\r
+ je @@Done\r
+ cmp [_MouseHidden],FALSE ; If cursor is already hidden exit\r
+ jne @@Done\r
+ push si\r
+ push di\r
+\r
+@@WaitEndOfHandler: ; Make sure handler not currently active\r
+ mov cl,[inhandler]\r
+ or cl,cl\r
+ jnz @@WaitEndOfHandler\r
+\r
+ mov [_MouseHidden],TRUE ; Delete mouse cursor\r
+ mov di,[OldScrnOffs]\r
+ mov ax,[OldY]\r
+ mov bx,[OldX]\r
+ call restorebg\r
+ pop di\r
+ pop si\r
+@@Done:\r
+ pop bp\r
+ ret\r
+_x_hide_mouse endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_remove_mouse - removes mouse handler\r
+;\r
+; C Prototype\r
+;\r
+; void x_remove_mouse()\r
+;\r
+; NOTE: This function MUST be called before quitting the program if\r
+; a mouse handler has been installed\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_mouse_remove proc\r
+ push bp\r
+ mov bp,sp\r
+ cmp [_MouseInstalled],FALSE ; Check whether we have installed\r
+ je @@Done ; our mouse handler\r
+ call _x_hide_mouse\r
+ mov ax,12 ; FUNC 12: Install event handler\r
+ xor cx,cx ; Disable all events\r
+ int 33h\r
+ mov [_MouseInstalled],FALSE\r
+@@Done:\r
+ pop bp\r
+ ret\r
+_x_mouse_remove endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_position_mouse - Positions the mouse cursor at the specified location\r
+;\r
+; C Prototype\r
+;\r
+; void x_position_mouse(int x, int y)\r
+;\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_position_mouse proc\r
+ARG X:word,Y:word\r
+ push bp\r
+ mov bp,sp\r
+\r
+@@WaitEndOfHandler: ; Make sure handler not currently active\r
+ mov bl,[inhandler]\r
+\r
+ or bl,bl\r
+ jnz @@WaitEndOfHandler\r
+\r
+ mov ax,4\r
+ mov cx,X\r
+ mov dx,Y\r
+ mov [_MouseX],cx\r
+ mov [_MouseY],dx\r
+ shl cx,1\r
+\r
+ mov [inhandler],1\r
+ int 33h\r
+\r
+ ; The handler doesnt get called so need\r
+ ; to update manually;\r
+\r
+ cmp [_MouseHidden],FALSE\r
+ jne @@NotVisible\r
+ push di si\r
+ call update_cursor\r
+ pop si di\r
+\r
+@@NotVisible:\r
+ mov [inhandler],0\r
+ pop bp\r
+ ret\r
+_x_position_mouse endp\r
+\r
+;----------------------------------------------------------------------\r
+; x_update_mouse - Forces the mouse position to be updated and cursor\r
+; to be redrawn.\r
+;\r
+; C Prototype\r
+;\r
+; void x_update_mouse()\r
+;\r
+; Note this function is useful when you have set "MouseFrozen" to true.\r
+; Allows the cursor position to be updated manually rather than\r
+; automatically by the installed handler.\r
+;\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_update_mouse proc\r
+ push bp\r
+ mov bp,sp\r
+ cmp [_MouseInstalled],FALSE ; Make sure our handler is installed\r
+ je @@Done\r
+ cmp [_MouseHidden],FALSE ; If cursor is already hidden exit\r
+ jne @@Done\r
+ push si\r
+ push di\r
+ mov ax,03h ; FUNC 3: get cursor pos / button status\r
+ int 33h ; Update position variables first\r
+ shr cx,1\r
+ mov [_MouseX],cx\r
+ mov [_MouseY],dx\r
+ mov [_MouseButtonStatus],bx ; Update button status\r
+ call update_cursor\r
+ pop di\r
+ pop si\r
+@@Done:\r
+ pop bp\r
+ ret\r
+_x_update_mouse endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_put_cursor - Draws the mouse cursor\r
+;\r
+; C Prototype\r
+;\r
+; void x_put_cursor(int X, int Y, int TopClip, int BottomClip, WORD ScrnOffs)\r
+;\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+ALIGN 2\r
+_x_put_cursor proc\r
+ARG X:word,Y:word,TopClip,BottomClip,ScrnOffs\r
+LOCAL Height,TopRow,NextLineIncr:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ mov ax,@data\r
+ mov ds,ax\r
+ cld\r
+\r
+ mov ax,14 ; Get image height and save in AX\r
+ mov bx,Y\r
+ ; cx = top Row\r
+\r
+ ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;\r
+\r
+ mov dx,[TopClip] ; Compare u.l. Y coord with Top\r
+ sub dx,bx ; clipping border\r
+ jle @@NotTopClip ; jump if not clipped from above\r
+ cmp dx,ax\r
+ jnl @@NotVisible ; jump if is completely obscured\r
+ mov cx,dx\r
+ sub ax,dx\r
+ add bx,dx\r
+ jmp short @@VertClipDone\r
+\r
+ ;;;; EXIT FOR COMPLETELY OBSCURED ;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotVisible:\r
+ pop ds\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+\r
+ ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotTopClip:\r
+ mov dx,[BottomClip]\r
+ sub dx,bx\r
+ js @@NotVisible\r
+ mov cx,0\r
+ cmp dx,ax\r
+ jg @@VertClipDone\r
+ inc dx\r
+ mov ax,dx\r
+\r
+@@VertClipDone:\r
+\r
+ mov [Height],ax\r
+ mov [TopRow],cx\r
+\r
+ mov ax,SCREEN_SEG ; Point es to VGA segment\r
+ mov es,ax\r
+\r
+ mov ax,bx\r
+ mov cx,[_ScrnLogicalByteWidth] ; Find required screen address\r
+ mul cx\r
+ mov di,ax\r
+\r
+ sub cx,3 ; Distance to next screen row\r
+ mov [NextLineIncr],cx\r
+\r
+\r
+ mov cx,[X]\r
+ mov bx,cx\r
+ shr cx,2\r
+ add di,cx\r
+ and bx,3\r
+ add di,[ScrnOffs]\r
+\r
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+\r
+ mov ax,42\r
+ mul bx\r
+ mov si,offset MouseMask\r
+ add si,ax\r
+\r
+ mov ax,3 ; Increment DS:BX and DS:SI to\r
+ mul [TopRow] ; been clipped by the top border\r
+ add si,ax ; by the L.H.S border\r
+\r
+ mov dx,SC_INDEX ; Point SC register to map mask\r
+ mov al,MAP_MASK ; in preperation for masking data\r
+ out dx,al\r
+ inc dx ; Point dx to SC data register\r
+ mov ah,byte ptr [Height] ; AH = Scanline loop counter\r
+ mov bl,[_MouseColor]\r
+@@RowLoop:\r
+ mov cx,3 ; Width in bytes across\r
+@@ColLoop:\r
+ lodsb ; load plane mask and set MAP MASK\r
+ out dx,al\r
+ mov es:[di],bl ; store color to specified planes\r
+ inc di\r
+ loop @@ColLoop\r
+\r
+ add di,[NextLineIncr]\r
+ dec ah\r
+ jnz @@RowLoop\r
+\r
+ pop ds\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_put_cursor endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; getbg - saves cursor background\r
+;\r
+; C Prototype\r
+;\r
+; local function using register parameters\r
+;\r
+; si = screen offset\r
+; ax = y\r
+; bx = x\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+ALIGN 2\r
+getbg proc near\r
+\r
+ push bp\r
+ mov bp,sp\r
+ push ds\r
+ cld\r
+\r
+ mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen\r
+ mul cx ; width then adding screen offset\r
+ add si,ax ; Add Dest Screen Row to di\r
+ sub cx,3\r
+ shr bx,2\r
+ add si,bx\r
+ mov bx,cx\r
+\r
+ mov di,BGSaveOffs\r
+ mov ax,SCREEN_SEG ; Point es to VGA segment\r
+ mov es,ax\r
+ mov ds,ax\r
+\r
+ mov dx,GC_INDEX ; Set bit mask for all bits from\r
+ mov ax,BIT_MASK ; VGA latches and none from CPU\r
+ out dx,ax\r
+\r
+ mov dx,SC_INDEX ; Point SC register to map mask\r
+ mov al,MAP_MASK ; in preperation for masking data\r
+ out dx,al\r
+ inc dx\r
+ mov al,0fh\r
+ out dx,al\r
+\r
+ mov cx,14\r
+@@Loop:\r
+ movsb\r
+ movsb\r
+ movsb\r
+ add si,bx\r
+ loop @@Loop\r
+\r
+mov dx,GC_INDEX+1 ;restore the bit mask to its default,\r
+ mov al,0ffh ; which selects all bits from the CPU\r
+ out dx,al ; and none from the latches (the GC\r
+ ; Index still points to Bit Mask)\r
+\r
+ pop ds\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+getbg endp\r
+\r
+;----------------------------------------------------------------------\r
+; restorebg - restores cursor background\r
+;\r
+; C Prototype\r
+;\r
+; local function using register parameters\r
+;\r
+; di = screen offset\r
+; ax = y\r
+; bx = x\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+ALIGN 2\r
+restorebg proc near\r
+;di = scrn offs\r
+;ax = y\r
+;bx = x\r
+ push bp\r
+ mov bp,sp\r
+ push ds\r
+ cld\r
+\r
+ mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen\r
+ mul cx ; width then adding screen offset\r
+ add di,ax ; Add Dest Screen Row to di\r
+ sub cx,3\r
+ shr bx,2\r
+ add di,bx\r
+ mov si,BGSaveOffs\r
+ mov ax,SCREEN_SEG ; Point es to VGA segment\r
+ mov es,ax\r
+ mov ds,ax\r
+\r
+ mov dx,GC_INDEX ; Set bit mask for all bits from\r
+ mov ax,BIT_MASK ; VGA latches and none from CPU\r
+ out dx,ax\r
+\r
+ mov dx,SC_INDEX ; Point SC register to map mask\r
+ mov al,MAP_MASK ; in preperation for masking data\r
+ out dx,al\r
+ inc dx\r
+ mov al,0fh\r
+ out dx,al\r
+\r
+ mov bx,cx\r
+ mov cx,14\r
+@@Loop:\r
+ movsb\r
+ movsb\r
+ movsb\r
+ add di,bx\r
+ loop @@Loop\r
+ mov dx,GC_INDEX+1 ;restore the bit mask to its default,\r
+ mov al,0ffh ; which selects all bits from the CPU\r
+ out dx,al ; and none from the latches (the GC\r
+ ; Index still points to Bit Mask)\r
+ pop ds\r
+ pop bp\r
+ ret\r
+restorebg endp\r
+\r
+\r
+\r
+;********************** The Mouse event handler *************************\r
+\r
+ALIGN 2\r
+mouse_handler proc far\r
+ push bp\r
+ mov bp,sp\r
+ push ds\r
+\r
+ mov di,@data ; Make sure DS points to data segment\r
+ mov ds,di\r
+ cmp [inhandler],1\r
+ jne @@NotActive\r
+ pop ds\r
+ pop bp\r
+ ret\r
+\r
+@@NotActive:\r
+ mov [inhandler],1\r
+ mov [_MouseButtonStatus],bx ; Update button status\r
+ test ax,1 ; Is this a motion event ?\r
+ jz @@Done ; No Jump\r
+\r
+ shr cx,1 ; convert X coord to pixel coords\r
+ mov [_MouseX],cx ; save mouse position\r
+ mov [_MouseY],dx\r
+\r
+ cmp [_MouseHidden],TRUE ; If mouse hidden dont bother drawing\r
+ je @@Done\r
+\r
+ cmp [_MouseFrozen],TRUE ; If mouse hidden dont bother drawing\r
+ je @@Done\r
+\r
+ call update_cursor\r
+@@Done:\r
+ mov [inhandler],0\r
+ pop ds\r
+ pop bp\r
+ ret\r
+mouse_handler endp\r
+\r
+\r
+end\r
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XMOUSE - header file\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;-----------------------------------------------------------------------*/\r
+\r
+#ifndef _XMOUSE_H_\r
+#define _XMOUSE_H_\r
+\r
+#define LEFT_PRESSED 1\r
+#define RIGHT_PRESSED 2\r
+\r
+/* GLOBAL VARS ========================================================= */\r
+\r
+extern WORD MouseInstalled; /* Indicates whether mouse handler installed */\r
+extern WORD MouseHidden; /* Indicates whether mouse cursor is hidden */\r
+extern WORD MouseButtonStatus;/* Holds the mouse button status */\r
+extern WORD MouseX; /* Current X position of mouse cursor */\r
+extern WORD MouseY; /* Current Y position of mouse cursor */\r
+extern BYTE MouseFrozen; /* Disallows position updates if TRUE */\r
+extern BYTE MouseColor; /* The mouse cursors colour */\r
+\r
+/* FUNCTIONS =========================================================== */\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+\r
+\r
+void x_mouse_init(void); /* Initialize mouse cursor */\r
+\r
+void x_define_mouse_cursor( /* Define and set a cursor shape */\r
+ char far MouseDef,\r
+ int color);\r
+\r
+void x_update_mouse(void); /* Force mouse cursor position update */\r
+\r
+void x_show_mouse(void); /* Show mouse cursor if hidden */\r
+\r
+void x_hide_mouse(void); /* Hide mouse cursor if visible */\r
+\r
+void x_mouse_remove(void); /* Remove installed mouse handler */\r
+\r
+void x_position_mouse( /* Set the mouse position */\r
+ int x,\r
+ int y);\r
+\r
+void x_put_cursor( /* Draw the mouse cursor (NOT FOR */\r
+ int x, /* general use) */\r
+ int y,\r
+ int topclip,\r
+ int botclip,\r
+ WORD ScrnOff);\r
+\r
+\r
+void x_mouse_window(int x0, /* Define a mouse window */\r
+ int y0,\r
+ int x1,\r
+ int y1);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\1a\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XPAL\r
+;\r
+; Palette functions all MODE X 256 Color resolutions\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+COMMENT $\r
+\r
+\r
+\r
+ All the functions in this module operate on two variations of the\r
+ pallete buffer, the raw and annotated buffers.\r
+\r
+ All those functions ending in buff operate on the following palette\r
+ structure:\r
+\r
+ BYTE:r0,g0,b0,r1,g1,b1,...rn,gn,bn\r
+\r
+ No reference to the starting colour index or number of colours stored\r
+ is contained in the structure.\r
+\r
+ All those functions ending in struc operate on the following palette\r
+ structure:\r
+\r
+ BYTE:c,BYTE:n,BYTE:r0,g0,b0,r1,g1,b1,...rn,gn,bn\r
+\r
+ where c is the starting colour and n is the number of colours stored\r
+\r
+\r
+ NOTE: previously interrupts were disabled for DAC reads/writes but\r
+ they have been left enabled in this version to allow the mouse\r
+ interrupt to be invoked.\r
+\r
+$\r
+\r
+\r
+\r
+\r
+include xlib.inc\r
+include xpal.inc\r
+\r
+.code\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; Read DAC palette into annotated type buffer with interrupts disabled\r
+; ie BYTE colours to skip, BYTE colours to set, r1,g1,b1,r1,g2,b2...rn,gn,bn\r
+;\r
+; x_get_pal_struc(char far * pal, int num_colrs, int start_color)\r
+;\r
+; WARNING: memory for the palette buffers must all be pre-allocated\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_get_pal_struc proc\r
+ARG PalBuff:dword,NumColors:word,StartColor:word\r
+ push bp ; Set up stack frame\r
+ mov bp,sp\r
+ push di\r
+ push si\r
+ cld\r
+\r
+ les di,dword ptr [PalBuff] ; Point es:di to palette buffer\r
+ mov si,[StartColor] ; Store the Start Colour\r
+ mov ax,si\r
+ stosb\r
+ mov dx,[NumColors] ; Store the Number of Colours\r
+ mov al,dl\r
+ stosb\r
+\r
+ mov cx,dx ; setup regs and jump\r
+ jmp short ReadPalEntry\r
+\r
+_x_get_pal_struc endp\r
+\r
+\r
+\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; Read DAC palette into raw buffer with interrupts disabled\r
+; ie BYTE r1,g1,b1,r1,g2,b2...rn,gn,bn\r
+;\r
+; x_get_pal_raw(char far * pal, int num_colrs, int start_index)\r
+;\r
+; WARNING: memory for the palette buffers must all be pre-allocated\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_get_pal_raw proc\r
+ARG PalBuff:dword,NumColors:word,StartColor:word\r
+ push bp ; Set up stack frame\r
+ mov bp,sp\r
+ push di\r
+ push si\r
+\r
+ les di,dword ptr [PalBuff] ; Point es:di to palette buffer\r
+\r
+ mov si,[StartColor]\r
+ mov cx,[NumColors]\r
+\r
+ReadPalEntry:\r
+ cld\r
+ WaitVsyncStart\r
+ mov ax,si\r
+ mov dx,DAC_READ_INDEX\r
+ ;cli\r
+ out dx,al ; Tell DAC what colour to start reading\r
+ mov dx,DAC_DATA\r
+\r
+ mov bx,cx ; set cx to Num Colors * 3 ( size of\r
+ shl bx,1 ; palette buffer)\r
+ add cx,bx\r
+\r
+ rep insb ; read the palette enntries\r
+\r
+ ;sti\r
+ pop si\r
+ pop di\r
+ pop bp\r
+ ret\r
+_x_get_pal_raw endp\r
+\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; Write DAC palette from annotated type buffer with interrupts disabled\r
+; ie BYTE colours to skip, BYTE colours to set, r1,g1,b1,r1,g2,b2...rn,gn,bn\r
+;\r
+; x_put_pal_struc(char far * pal)\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+\r
+_x_put_pal_struc proc\r
+ARG CompPalBuff:dword\r
+ push bp ;preserve caller's stack frame\r
+ mov bp,sp ;point to local stack frame\r
+ push ds\r
+ push si\r
+ cld\r
+ lds si,[CompPalBuff] ; load the source compressed colour data\r
+ lodsb ; get the colours to skip\r
+ mov ah,0\r
+ mov bx,ax ; skip colours\r
+\r
+ lodsb ; get the count of colours to set\r
+ mov ah,0\r
+ mov cx,ax ; use it as a loop counter\r
+ jmp short WritePalEntry\r
+\r
+_x_put_pal_struc endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; Write DAC palette from annotated type buffer with interrupts disabled\r
+; starting at a new palette index\r
+;\r
+; ie BYTE colours to skip, BYTE colours to set, r1,g1,b1,r1,g2,b2...rn,gn,bn\r
+;\r
+; x_transpose_pal_struc(char far * pal, int StartColor)\r
+;\r
+; WARNING: memory for the palette buffers must all be pre-allocated\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+\r
+_x_transpose_pal_struc proc\r
+ARG CompPalBuff:dword,StartColor:word\r
+ push bp ;preserve caller's stack frame\r
+ mov bp,sp ;point to local stack frame\r
+ push ds\r
+ push si\r
+ cld\r
+ lds si,[CompPalBuff] ; load the source compressed colour data\r
+ mov bx,[StartColor]\r
+ mov [si],bl\r
+ inc si\r
+ lodsb ; get the count of colours to set\r
+ mov ah,0\r
+ mov cx,ax ; use it as a loop counter\r
+ jmp short WritePalEntry\r
+_x_transpose_pal_struc endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; Write DAC palette from raw buffer with interrupts disabled\r
+; ie BYTE r1,g1,b1,r1,g2,b2...rn,gn,bn\r
+;\r
+; _x_put_pal_raw(char far * pal, int num_colrs, int start_index)\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_put_pal_raw proc\r
+ARG PalBuff:dword,NumColors:word,StartColor:word\r
+ push bp ; Set up stack frame\r
+ mov bp,sp\r
+ push ds\r
+ push si\r
+\r
+ mov cx,[NumColors] ; Number of colours to set\r
+ mov bx,[StartColor]\r
+ lds si,[PalBuff] ; ds:si -> palette buffer\r
+\r
+\r
+WritePalEntry:\r
+ mov ax,@data\r
+ mov es,ax\r
+ cmp es:[_VsyncHandlerActive],TRUE\r
+ jne @@NoVsyncHandler\r
+@@WaitForLast:\r
+ cmp es:[_VsyncPaletteCount],0\r
+ jne @@WaitForLast\r
+ push cx\r
+ push es\r
+ mov di, offset _VsyncPaletteBuffer\r
+ mov ax,3\r
+ mul cx\r
+ mov cx,ax\r
+ rep movsb\r
+ pop ds\r
+ pop cx\r
+ mov [_VsyncPaletteStart],bx\r
+ mov [_VsyncPaletteCount],cx\r
+ jmp short @@Done\r
+@@NoVsyncHandler:\r
+\r
+\r
+ or cx,cx\r
+ jz @@Done\r
+ ;cli\r
+ cld ; Make sure we're going the right way\r
+ WaitVsyncStart ; Wait for vert sync to start\r
+ mov ax,bx\r
+ mov bx,60 ; set the vsync check timer (Vsync\r
+ ; is tested for at each bx'th entry to\r
+ ; prevent snow 60 is otimum for 10\r
+ ; MHz 286 or greater\r
+\r
+@@SetLoop:\r
+ mov dx,DAC_WRITE_INDEX ; Tell DAC what colour index to start\r
+ out dx,al ; writing from\r
+ mov dx,DAC_DATA\r
+\r
+ outsb ; Set the red component\r
+ outsb ; Set the green component\r
+ outsb ; Set the blue component\r
+ inc al ; increment the colour index\r
+ dec bx ; decrement vsync test counter\r
+ js @@test_vsync ; ready to test for vsync again ?\r
+ loop @@SetLoop ; No! - continue loop\r
+ jmp short @@Done ; All colours done\r
+\r
+@@test_vsync:\r
+ mov dx,INPUT_STATUS_0\r
+ push ax ; save current colour index\r
+@@Wait:\r
+ in al,dx ; wait for vsync leading edge pulse\r
+ test al,08h\r
+ jz @@Wait\r
+\r
+ pop ax ; restore current colour index\r
+ mov bx,60 ; reset vsync test counter\r
+ loop @@SetLoop ; loop for next colour index\r
+\r
+@@Done:\r
+ ;sti\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ ret\r
+_x_put_pal_raw endp\r
+\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; Set the RGB setting of a vga color\r
+;\r
+; _x_set_rgb(unsigned char color, unsigned char R,unsigned char G,\r
+; unsigned char B)\r
+;\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_set_rgb proc\r
+ARG ColorIndex:byte,R:byte,G:byte,B:byte\r
+ push bp ; Set up stack frame\r
+ mov bp,sp\r
+\r
+ mov al,[ColorIndex]\r
+ mov dx,DAC_WRITE_INDEX ; Tell DAC what colour index to\r
+ out dx,al ; write to\r
+ mov dx,DAC_DATA\r
+\r
+ mov al,[R] ; Set the red component\r
+ out dx,al\r
+ mov al,[G] ; Set the green component\r
+ out dx,al\r
+ mov al,[B] ; Set the blue component\r
+ out dx,al\r
+ pop bp\r
+ ret\r
+_x_set_rgb endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; Rotate annotated palette buffer entries\r
+;\r
+; x_rot_pal_struc(char far * pal, int direction)\r
+;\r
+; Direction : 0 = backward 1 = forward\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_rot_pal_struc proc\r
+ARG PalBuff:dword,Direction:word\r
+ push bp ; Set up stack frame\r
+ mov bp,sp\r
+ push ds\r
+ push si\r
+ push di\r
+\r
+ cld\r
+ lds si,dword ptr [PalBuff] ; point ds:si to Palette buffer\r
+ lodsw ; al = colorst ot skip, ah = num colors\r
+\r
+ xor ch,ch ; Set the number of palette entries to cycle in cx\r
+ mov cl,ah ;\r
+\r
+ jmp short RotatePalEntry\r
+\r
+_x_rot_pal_struc endp\r
+\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; Rotate raw palette buffer\r
+;\r
+; x_rot_pal_raw(char far * pal, int direction, int num_colrs)\r
+;\r
+; Direcction : 0 = backward 1 = forward\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_rot_pal_raw proc\r
+ARG PalBuff:dword,Direction:word,NumColors:word\r
+ push bp ; Set up stack frame\r
+ mov bp,sp\r
+ push ds\r
+ push si\r
+ push di\r
+\r
+ cld\r
+ mov cx,[NumColors] ; Set the number of palette entries to cycle\r
+ lds si,dword ptr [PalBuff] ; point ds:si to Palette buffer\r
+\r
+RotatePalEntry:\r
+\r
+\r
+ mov ax,ds ; copy ds to es\r
+ mov es,ax\r
+\r
+ dec cx\r
+ mov bx,cx ; Multiply cx by 3\r
+ shl bx,1\r
+ add cx,bx\r
+\r
+ cmp [Direction],0 ; are we going forward ?\r
+ jne @@forward ; yes - jump (colors move one position back)\r
+\r
+ std ; no - set reverse direction\r
+ add si,cx ; set si to last byte in palette\r
+ add si,2\r
+\r
+@@forward:\r
+ mov ax,si ; copy si to di\r
+ mov di,ax\r
+\r
+ lodsb ; load first color triplet into regs\r
+ mov dl,al\r
+ lodsb\r
+ mov dh,al\r
+ lodsb\r
+ mov bl,al\r
+\r
+ rep movsb ; move remaining triplets direction indicated\r
+ ; by direction flag\r
+\r
+ mov al,dl ; write color triplet from regs to last position\r
+ stosb\r
+ mov al,dh\r
+ stosb\r
+ mov al,bl\r
+ stosb\r
+\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ ret\r
+_x_rot_pal_raw endp\r
+\r
+;----------------------------------------------------------------------\r
+; Copy palette making intensity adjustment\r
+; x_cpcontrast_pal_struc(char far *src_pal, char far *dest_pal, unsigned char Intensity)\r
+;\r
+; WARNING: memory for the palette buffers must all be pre-allocated\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_cpcontrast_pal_struc proc\r
+ARG PalSrcBuff:dword,PalDestBuff:dword,Intensity:byte\r
+ push bp ; Set up stack frame\r
+ mov bp,sp\r
+ push ds\r
+ push si\r
+ push di\r
+\r
+ cld\r
+ mov bh,0ffh\r
+ sub bh,[Intensity]\r
+ and bh,07fh ; Palettes are 7 bit\r
+ lds si,dword ptr [PalSrcBuff] ; point ds:si to Source Palette buffer\r
+ les di,dword ptr [PalDestBuff] ; point ds:si to Source Palette buffer\r
+ lodsw ; al = colorst ot skip, ah = num color\r
+ stosw\r
+\r
+ xor ch,ch ; Set the number of palette entries to adjust\r
+ mov cl,ah ;\r
+\r
+ mov dx,0 ; flag set to 0 if all output palette entries zero\r
+@@MainLoop:\r
+ lodsw\r
+ sub al,bh ; adjust intensity and copy RED\r
+ jns @@DecrementOK_R\r
+ xor al,al\r
+@@DecrementOK_R:\r
+ sub ah,bh ; adjust intensity and copy GREEN\r
+ jns @@DecrementOK_G\r
+ xor ah,ah\r
+@@DecrementOK_G:\r
+ or dx,ax\r
+ or dl,ah\r
+ stosw\r
+ lodsb\r
+ sub al,bh ; adjust intensity and copy BLUE\r
+ jns @@DecrementOK_B\r
+ xor al,al\r
+@@DecrementOK_B:\r
+ or dl,al\r
+ stosb\r
+ loop @@MainLoop\r
+\r
+ mov ax,dx\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ ret\r
+_x_cpcontrast_pal_struc endp\r
+\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; Write DAC palette from annotated type buffer with specified intensity\r
+; ie BYTE colours to skip, BYTE colours to set, r1,g1,b1,r1,g2,b2...rn,gn,bn\r
+;\r
+; x_put_contrast_pal_struc(char far * pal, unsigned char intensity)\r
+;\r
+; Designed for fading in or out a palette without using an intermediate\r
+; working palette buffer ! (Slow but memory efficient ... OK for small\r
+; pal strucs}\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+\r
+_x_put_contrast_pal_struc proc\r
+ARG CompPalBuff:dword,Intensity:byte\r
+ push bp ;preserve caller's stack frame\r
+ mov bp,sp ;point to local stack frame\r
+ push ds\r
+ push si\r
+ push di\r
+ cld\r
+\r
+ mov bh,0ffh\r
+ sub bh,[Intensity]\r
+ and bh,07fh ; Palettes are 7 bit\r
+ mov di,40 ; set the vsync check timer (Vsync\r
+ ; is tested for at each di'th entry to\r
+ ; prevent snow 40 is otimum for 10\r
+ ; MHz 286 or greater)\r
+ lds si,[CompPalBuff] ; load the source compressed colour data\r
+ lodsb ; get the colours to skip\r
+ mov bl,al\r
+\r
+ lodsb ; get the count of colours to set\r
+ mov ah,0\r
+ mov cx,ax ; use it as a loop counter\r
+ or cx,cx\r
+ jz @@Done\r
+\r
+ WaitVsyncStart ; Wait for vert sync to start\r
+\r
+@@MainLoop:\r
+ mov al,bl\r
+ mov dx,DAC_WRITE_INDEX ; Tell DAC what colour index to start\r
+ out dx,al ; writing from\r
+ inc dx ; == mov dx,DAC_DATA\r
+\r
+ lodsb ; Load each colour component, modify for\r
+ sub al,bh ; intensity and write to DAC H/Ware\r
+ jns @@DecrementOK_R\r
+ xor al,al\r
+@@DecrementOK_R:\r
+ out dx,al\r
+\r
+ lodsb\r
+ sub al,bh\r
+ jns @@DecrementOK_G\r
+ xor al,al\r
+@@DecrementOK_G:\r
+ out dx,al\r
+\r
+ lodsb\r
+ sub al,bh\r
+ jns @@DecrementOK_B\r
+ xor al,al\r
+@@DecrementOK_B:\r
+ out dx,al\r
+\r
+ inc bl ; increment color index\r
+ dec di ; decrement vsync test flag\r
+ js @@test_vsync\r
+ loop @@MainLoop\r
+ jmp short @@Done\r
+\r
+\r
+@@test_vsync:\r
+ mov dx,INPUT_STATUS_0\r
+ push ax ; save current colour index\r
+@@Wait:\r
+ in al,dx ; wait for vsync leading edge pulse\r
+ test al,08h\r
+ jz @@Wait\r
+\r
+ pop ax ; restore current colour index\r
+ mov di,40 ; reset vsync test counter\r
+ loop @@MainLoop ; loop for next colour index\r
+\r
+@@Done:\r
+ ;sti\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ ret\r
+\r
+_x_put_contrast_pal_struc endp\r
+\r
+\r
+ end\r
+\r
+\r
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XPAL - header file\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;----------------------------------------------------------------------*/\r
+\r
+#ifndef _XPAL_H_\r
+#define _XPAL_H_\r
+\r
+#define PAL_ROTATE_DOWN 0\r
+#define PAL_ROTATE_UP 1\r
+\r
+/* FUNCTIONS =========================================================== */\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+\r
+ void x_get_pal_raw( /* Read DAC palette into raw buffer */\r
+ BYTE far * pal,\r
+ WORD num_colrs,\r
+ WORD start_index);\r
+\r
+ void x_get_pal_struc( /* Read DAC palette into annotated buffer */\r
+ BYTE far * pal,\r
+ WORD num_colrs,\r
+ WORD start_index);\r
+\r
+ void x_put_pal_raw( /* Write DAC palette from raw buffer */\r
+ BYTE far * pal,\r
+ WORD num_colrs,\r
+ WORD start_index);\r
+\r
+ void x_put_pal_struc( /* Write DAC palette from annotated buffer*/\r
+ BYTE far * pal);\r
+\r
+ x_set_rgb( /* Set the RGB components of a color index*/\r
+ BYTE color,\r
+ BYTE red_c,\r
+ BYTE green_c,\r
+ BYTE blue_c);\r
+\r
+ x_rot_pal_raw( /* Rotate a raw palette buffer */\r
+ BYTE far * pal,\r
+ WORD direction,\r
+ WORD num_colrs);\r
+\r
+ void x_rot_pal_struc( /* Rotate an anottated palette buffer */\r
+ BYTE far * pal,\r
+ WORD direction);\r
+\r
+ WORD x_cpcontrast_pal_struc( /* Copy and contrast adjust annotated */\r
+ BYTE far *src_pal, /* palette buffer */\r
+ BYTE far *dest_pal,\r
+ BYTE Intensity);\r
+\r
+ void x_transpose_pal_struc( /* Write DAC palette from annotated type*/\r
+ BYTE far * pal, /* buffer with a new offset */\r
+ WORD StartColor);\r
+\r
+ void x_put_contrast_pal_struc( /* Write DAC palette from annotated */\r
+ BYTE far * pal, /* type buffer with specified intensity */\r
+ BYTE intensity);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XPAL - Include file\r
+;\r
+; XPAL.ASM export functions\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+ global _x_get_pal_struc :proc\r
+ global _x_get_pal_raw :proc\r
+\r
+ global _x_put_pal_struc :proc\r
+ global _x_put_pal_raw :proc\r
+ global _x_set_rgb :proc\r
+\r
+ global _x_rot_pal_struc :proc\r
+ global _x_rot_pal_raw :proc\r
+\r
+\r
+ global _x_put_contrast_pal_struc:proc\r
+\r
+ global _x_transpose_pal_struc :proc\r
+\r
+ global _x_cpcontrast_pal_struc :proc\1a
\ No newline at end of file
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XPBITMAP\r
+;\r
+; Planar Bitmap functions - System Ram <-> Video Ram\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+COMMENT $\r
+\r
+ This module implements a set of functions to operate on planar bitmaps.\r
+ Planar bitmaps as used by these functions have the following structure:\r
+\r
+ BYTE 0 The bitmap width in bytes (4 pixel groups) range 1..255\r
+ BYTE 1 The bitmap height in rows range 1..255\r
+ BYTE 2..n1 The plane 0 pixels width*height bytes\r
+ BYTE n1..n2 The plane 1 pixels width*height bytes\r
+ BYTE n2..n3 The plane 2 pixels width*height bytes\r
+ BYTE n3..n4 The plane 3 pixels width*height bytes\r
+\r
+ These functions provide the fastest possible bitmap blts from system ram to\r
+ to video and further, the single bitmap is applicable to all pixel\r
+ allignments. The masked functions do not need separate masks since all non\r
+ zero pixels are considered to be masking pixels, hence if a pixel is 0 the\r
+ corresponding screen destination pixel is left unchanged.\r
+\r
+\r
+$\r
+\r
+include xlib.inc\r
+include xpbitmap.inc\r
+LOCALS\r
+ .code\r
+\r
+;----------------------------------------------------------------------\r
+; x_flip_masked_pbm - mask write a planar bitmap from system ram to video ram\r
+; all zero source bitmap bytes indicate destination byte to be left unchanged\r
+; If "Orientation" is set then the bitmap is flipped from left to right as\r
+; it is drawn\r
+;\r
+; Source Bitmap structure:\r
+;\r
+; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,\r
+; Bitmap data (plane 2)..,Bitmap data (plane 3)..\r
+;\r
+; note width is in bytes ie lots of 4 pixels\r
+;\r
+; x_flip_masked_pbm(X,Y,ScrnOffs,char far * Bitmap, Orientation)\r
+;\r
+;\r
+; LIMITATIONS: No clipping is supported\r
+; Only supports bitmaps with widths which are a multiple of\r
+; 4 pixels\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_flip_masked_pbm proc\r
+ ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword,Orientation:word\r
+ LOCAL Plane:byte,BMHeight:byte,LineInc:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+ mov ax,SCREEN_SEG\r
+ mov es,ax\r
+ mov ax,[Y] ; Calculate dest screen row\r
+ mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen\r
+ mul bx ; width then adding screen offset\r
+ mov di,[ScrnOffs] ; store result in DI\r
+ add di,ax\r
+ mov cx,[X] ; Load X coord into CX and make a\r
+ mov dx,cx ; copy in DX\r
+ shr dx,2 ; Find starting byte in dest row\r
+ add di,dx ; add to DI giving screen offset of\r
+ ; first pixel's byte\r
+ lds si,[Bitmap] ; DS:SI -> Bitmap data\r
+ lodsw ; Al = B.M. width (bytes) AH = B.M.\r
+ ; height\r
+ cmp Orientation,0\r
+ jz UnFlippedMasked\r
+\r
+ mov [BMHeight],ah ; Save source bitmap dimensions\r
+ xor ah,ah ; LineInc = bytes to the begin.\r
+ add bx,ax ; of bitmaps next row on screen\r
+ mov [LineInc],bx\r
+ mov bh,al ; Use bh as column loop count\r
+ and cx,0003h ; mask X coord giving plane of 1st\r
+ ; bitmap pixel(zero CH coincidentally)\r
+ mov ah,11h ; Init. mask for VGA plane selection\r
+ shl ah,cl ; Shift for starting pixel plane\r
+ mov dx,SC_INDEX ; Prepare VGA for cpu to video writes\r
+ mov al,MAP_MASK\r
+ out dx,al\r
+ inc dx\r
+ mov [Plane],4 ; Set plane counter to 4\r
+@@PlaneLoop:\r
+ push di ; Save bitmap's start dest. offset\r
+ mov bl,[BMHeight] ; Reset row counter (BL)\r
+ mov al,ah\r
+ out dx,al ; set vga write plane\r
+@@RowLoop:\r
+ mov cl,bh ; Reset Column counter cl\r
+@@ColLoop:\r
+ lodsb ; Get next source bitmap byte\r
+ or al,al ; If not zero then write to dest.\r
+ jz @@NoPixel ; otherwise skip to next byte\r
+ mov es:[di],al\r
+@@NoPixel:\r
+ dec di\r
+ loop @@ColLoop ; loop if more columns left\r
+ add di,[LineInc] ; Move to next row\r
+ dec bl ; decrement row counter\r
+ jnz @@RowLoop ; Jump if more rows left\r
+ pop di ; Restore bitmaps start dest byte\r
+ ror ah,1 ; Shift mask for next plane\r
+ sbb di,0 ; If wrapped increment dest address\r
+ dec [Plane] ; Decrement plane counter\r
+ jnz @@PlaneLoop ; Jump if more planes left\r
+\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_flip_masked_pbm endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_put_masked_pbm - mask write a planar bitmap from system ram to video ram\r
+; all zero source bitmap bytes indicate destination byte to be left unchanged\r
+;\r
+; Source Bitmap structure:\r
+;\r
+; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,\r
+; Bitmap data (plane 2)..,Bitmap data (plane 3)..\r
+;\r
+; note width is in bytes ie lots of 4 pixels\r
+;\r
+; x_put_masked_pbm(X,Y,ScrnOffs,char far * Bitmap)\r
+;\r
+;\r
+; LIMITATIONS: No clipping is supported\r
+; Only supports bitmaps with widths which are a multiple of\r
+; 4 pixels\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_put_masked_pbm proc\r
+ ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword\r
+ LOCAL Plane:byte,BMHeight:byte,LineInc:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+ mov ax,SCREEN_SEG\r
+ mov es,ax\r
+ mov ax,[Y] ; Calculate dest screen row\r
+ mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen\r
+ mul bx ; width then adding screen offset\r
+ mov di,[ScrnOffs] ; store result in DI\r
+ add di,ax\r
+ mov cx,[X] ; Load X coord into CX and make a\r
+ mov dx,cx ; copy in DX\r
+ shr dx,2 ; Find starting byte in dest row\r
+ add di,dx ; add to DI giving screen offset of\r
+ ; first pixel's byte\r
+ lds si,[Bitmap] ; DS:SI -> Bitmap data\r
+ lodsw ; Al = B.M. width (bytes) AH = B.M.\r
+ ; height\r
+UnFlippedMasked:\r
+ mov [BMHeight],ah ; Save source bitmap dimensions\r
+ xor ah,ah ; LineInc = bytes to the begin.\r
+ sub bx,ax ; of bitmaps next row on screen\r
+ mov [LineInc],bx\r
+ mov bh,al ; Use bh as column loop count\r
+ and cx,0003h ; mask X coord giving plane of 1st\r
+ ; bitmap pixel(zero CH coincidentally)\r
+ mov ah,11h ; Init. mask for VGA plane selection\r
+ shl ah,cl ; Shift for starting pixel plane\r
+ mov dx,SC_INDEX ; Prepare VGA for cpu to video writes\r
+ mov al,MAP_MASK\r
+ out dx,al\r
+ inc dx\r
+ mov [Plane],4 ; Set plane counter to 4\r
+@@PlaneLoop:\r
+ push di ; Save bitmap's start dest. offset\r
+ mov bl,[BMHeight] ; Reset row counter (BL)\r
+ mov al,ah\r
+ out dx,al ; set vga write plane\r
+@@RowLoop:\r
+ mov cl,bh ; Reset Column counter cl\r
+@@ColLoop:\r
+ lodsb ; Get next source bitmap byte\r
+ or al,al ; If not zero then write to dest.\r
+ jz @@NoPixel ; otherwise skip to next byte\r
+ mov es:[di],al\r
+@@NoPixel:\r
+ inc di\r
+ loop @@ColLoop ; loop if more columns left\r
+ add di,[LineInc] ; Move to next row\r
+ dec bl ; decrement row counter\r
+ jnz @@RowLoop ; Jump if more rows left\r
+ pop di ; Restore bitmaps start dest byte\r
+ rol ah,1 ; Shift mask for next plane\r
+ adc di,0 ; If wrapped increment dest address\r
+ dec [Plane] ; Decrement plane counter\r
+ jnz @@PlaneLoop ; Jump if more planes left\r
+\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_put_masked_pbm endp\r
+\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_put_pbm - Write a planar bitmap from system ram to video ram\r
+;\r
+; Source Bitmap structure:\r
+;\r
+; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,\r
+; Bitmap data (plane 2)..,Bitmap data (plane 3)..\r
+;\r
+; note width is in bytes ie lots of 4 pixels\r
+;\r
+; x_put_pbm(X,Y,ScrnOffs,char far * Bitmap)\r
+;\r
+;\r
+; LIMITATIONS: No clipping is supported\r
+; Only supports bitmaps with widths which are a multiple of\r
+; 4 pixels\r
+; FEATURES : Automatically selects REP MOVSB or REP MOVSW depending on\r
+; source bitmap width, by modifying opcode ;-).\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+\r
+\r
+_x_put_pbm proc\r
+ ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword\r
+ LOCAL Plane:byte,BMHeight:byte,LineInc:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+ mov ax,SCREEN_SEG\r
+ mov es,ax\r
+ mov ax,[Y] ; Calculate dest screen row\r
+ mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen\r
+ mul bx ; width then adding screen offset\r
+ mov di,[ScrnOffs] ; store result in DI\r
+ add di,ax\r
+ mov cx,[X] ; Load X coord into CX and make a\r
+ mov dx,cx ; copy in DX\r
+ shr dx,2 ; Find starting byte in dest row\r
+ add di,dx ; add to DI giving screen offset of\r
+ ; first pixel's byte\r
+ lds si,[Bitmap] ; DS:SI -> Bitmap data\r
+ lodsw ; Al = B.M. width (bytes) AH = B.M.\r
+ ; height\r
+UnFlipped:\r
+ mov [BMHeight],ah ; Save source bitmap dimensions\r
+ xor ah,ah ; LineInc = bytes to the begin.\r
+ sub bx,ax ; of bitmaps next row on screen\r
+ mov [LineInc],bx\r
+ mov bh,al\r
+ ; Self Modifying, Shame, shame shame..\r
+ and cx,0003h ; mask X coord giving plane of 1st\r
+ ; bitmap pixel(zero CH coincidentally)\r
+ mov ah,11h ; Init. mask for VGA plane selection\r
+ shl ah,cl ; Shift for starting pixel plane\r
+ mov dx,SC_INDEX ; Prepare VGA for cpu to video writes\r
+ mov al,MAP_MASK\r
+ out dx,al\r
+ inc dx\r
+ mov [Plane],4 ; Set plane counter to 4\r
+@@PlaneLoop:\r
+ push di\r
+ mov bl,[BMHeight]\r
+ mov al,ah\r
+ out dx,al\r
+@@RowLoop:\r
+ mov cl,bh\r
+ shr cl,1\r
+ rep movsw ; Copy a complete row for curr plane\r
+ adc cl,0\r
+ rep movsb\r
+ add di,[LineInc] ; Move to next row\r
+ dec bl ; decrement row counter\r
+ jnz @@RowLoop ; Jump if more rows left\r
+ pop di ; Restore bitmaps start dest byte\r
+ rol ah,1 ; Shift mask for next plane\r
+ adc di,0 ; If wrapped increment dest address\r
+ dec [Plane] ; Decrement plane counter\r
+ jnz @@PlaneLoop ; Jump if more planes left\r
+\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_put_pbm endp\r
+\r
+;----------------------------------------------------------------------\r
+; x_flip_pbm - Write a planar bitmap from system ram to video ram\r
+; If "Orientation" is set then the bitmap is flipped from left to right as\r
+; it is drawn\r
+\r
+;\r
+; Source Bitmap structure:\r
+;\r
+; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,\r
+; Bitmap data (plane 2)..,Bitmap data (plane 3)..\r
+;\r
+; note width is in bytes ie lots of 4 pixels\r
+;\r
+; x_flip_pbm(X,Y,ScrnOffs,char far * Bitmap, WORD orientation)\r
+;\r
+;\r
+; LIMITATIONS: No clipping is supported\r
+; Only supports bitmaps with widths which are a multiple of\r
+; 4 pixels\r
+;\r
+; NOTES: The flipped put function is slower than the standard put function\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_flip_pbm proc\r
+ ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword,Orientation:word\r
+ LOCAL Plane:byte,BMHeight:byte,LineInc:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+ mov ax,SCREEN_SEG\r
+ mov es,ax\r
+ mov ax,[Y] ; Calculate dest screen row\r
+ mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen\r
+ mul bx ; width then adding screen offset\r
+ mov di,[ScrnOffs] ; store result in DI\r
+ add di,ax\r
+ mov cx,[X] ; Load X coord into CX and make a\r
+ mov dx,cx ; copy in DX\r
+ shr dx,2 ; Find starting byte in dest row\r
+ add di,dx ; add to DI giving screen offset of\r
+ ; first pixel's byte\r
+ lds si,[Bitmap] ; DS:SI -> Bitmap data\r
+ lodsw ; Al = B.M. width (bytes) AH = B.M.\r
+ ; height\r
+ cmp Orientation,0\r
+ jz UnFlipped\r
+\r
+ mov [BMHeight],ah ; Save source bitmap dimensions\r
+ xor ah,ah ; LineInc = bytes to the begin.\r
+ add bx,ax ; of bitmaps next row on screen\r
+ mov [LineInc],bx\r
+ mov bh,al ; Use bh as column loop count\r
+ and cx,0003h ; mask X coord giving plane of 1st\r
+ ; bitmap pixel(zero CH coincidentally)\r
+ mov ah,11h ; Init. mask for VGA plane selection\r
+ shl ah,cl ; Shift for starting pixel plane\r
+ mov dx,SC_INDEX ; Prepare VGA for cpu to video writes\r
+ mov al,MAP_MASK\r
+ out dx,al\r
+ inc dx\r
+ mov [Plane],4 ; Set plane counter to 4\r
+@@PlaneLoop:\r
+ push di ; Save bitmap's start dest. offset\r
+ mov bl,[BMHeight] ; Reset row counter (BL)\r
+ mov al,ah\r
+ out dx,al ; set vga write plane\r
+@@RowLoop:\r
+ mov cl,bh ; Reset Column counter cl\r
+@@ColLoop:\r
+ lodsb\r
+ mov es:[di],al\r
+ dec di\r
+ sub di,2\r
+ loop @@ColLoop ; loop if more columns left\r
+@@DoneCol:\r
+ add di,[LineInc] ; Move to next row\r
+ dec bl ; decrement row counter\r
+ jnz @@RowLoop ; Jump if more rows left\r
+ pop di ; Restore bitmaps start dest byte\r
+ ror ah,1 ; Shift mask for next plane\r
+ sbb di,0 ; If wrapped increment dest address\r
+ dec [Plane] ; Decrement plane counter\r
+ jnz @@PlaneLoop ; Jump if more planes left\r
+\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_flip_pbm endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_get_pbm - Read a planar bitmap to system ram from video ram\r
+;\r
+; Source Bitmap structure:\r
+;\r
+; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,\r
+; Bitmap data (plane 2)..,Bitmap data (plane 3)..\r
+;\r
+; note width is in bytes ie lots of 4 pixels\r
+;\r
+; x_get_pbm(X,Y,BMwidth,BMheight,ScrnOffs,char far * Bitmap)\r
+;\r
+;\r
+; LIMITATIONS: No clipping is supported\r
+; Only supports bitmaps with widths which are a multiple of\r
+; 4 pixels\r
+; FEATURES : Automatically selects REP MOVSB or REP MOVSW depending on\r
+; source bitmap width, by modifying opcode ;-).\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_get_pbm proc\r
+ ARG X:word,Y:word,SrcWidth:byte,SrcHeight:byte,ScrnOffs:word,Bitmap:dword\r
+ LOCAL Plane:byte,LineInc:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+\r
+ mov ax,[Y] ; Calculate screen row\r
+ mov bx,[_ScrnLogicalByteWidth] ; by mult. Y coord by Screen\r
+ mul bx ; width then adding screen offset\r
+ mov si,[ScrnOffs] ; store result in SI\r
+ add si,ax\r
+ mov cx,[X] ; Load X coord into CX and make a\r
+ mov dx,cx ; copy in DX\r
+ shr dx,2 ; Find starting byte in screen row\r
+ add si,dx ; add to SI giving screen offset of\r
+ ; first pixel's byte\r
+ mov ax,SCREEN_SEG\r
+ mov ds,ax\r
+ les di,[Bitmap] ; ES:DI -> Bitmap data\r
+ mov al,[SrcWidth]\r
+ mov ah,[SrcHeight]\r
+ stosw ; Al = B.M. width (bytes) AH = B.M.\r
+ ; height\r
+ xor ah,ah ; LineInc = bytes to the begin.\r
+ sub bx,ax ; of bitmaps next row on screen\r
+ mov [LineInc],bx\r
+ mov bh,al\r
+ ; Self Modifying, Shame, shame shame..\r
+ and cx,0003h ; mask X coord giving plane of 1st\r
+ ; bitmap pixel(zero CH coincidentally)\r
+ mov ah,11h ; Init. mask for VGA plane selection\r
+ shl ah,cl ; Shift for starting pixel plane\r
+ mov dx,GC_INDEX ; Prepare VGA for cpu to video reads\r
+ mov al,READ_MAP\r
+ out dx,al\r
+ inc dx\r
+ mov [Plane],4 ; Set plane counter (BH) to 4\r
+ mov al,cl\r
+@@PlaneLoop:\r
+ push si\r
+ mov bl,[SrcHeight]\r
+ out dx,al\r
+@@RowLoop:\r
+ mov cl,bh\r
+ shr cl,1\r
+ rep movsw ; Copy a complete row for curr plane\r
+ adc cl,0\r
+ rep movsb\r
+ add si,[LineInc] ; Move to next row\r
+ dec bl ; decrement row counter\r
+ jnz @@RowLoop ; Jump if more rows left\r
+ pop si ; Restore bitmaps start dest byte\r
+\r
+ inc al ; Select next plane to read from\r
+ and al,3 ;\r
+\r
+ rol ah,1 ; Shift mask for next plane\r
+ adc si,0 ; If wrapped increment dest address\r
+ dec [Plane] ; Decrement plane counter\r
+ jnz @@PlaneLoop ; Jump if more planes left\r
+\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_get_pbm endp\r
+\r
+\r
+\r
+\r
+ end\r
+\r
+\r
+\r
+ ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword,Orientation:word\r
+ LOCAL Plane:byte,BMHeight:byte,LineInc:word,Columns:byte=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+ mov ax,SCREEN_SEG\r
+ mov es,ax\r
+ mov ax,[Y] ; Calculate dest screen row\r
+ mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen\r
+ mul bx ; width then adding screen offset\r
+ mov di,[ScrnOffs] ; store result in DI\r
+ add di,ax\r
+ mov cx,[X] ; Load X coord into CX and make a\r
+ mov dx,cx ; copy in DX\r
+ shr dx,2 ; Find starting byte in dest row\r
+ add di,dx ; add to DI giving screen offset of\r
+ ; first pixel's byte\r
+ lds si,[Bitmap] ; DS:SI -> Bitmap data\r
+ lodsw ; Al = B.M. width (bytes) AH = B.M.\r
+ ; height\r
+ cmp Orientation,0\r
+ jz UnFlipped\r
+\r
+ mov [BMHeight],ah ; Save source bitmap dimensions\r
+ xor ah,ah ; LineInc = bytes to the begin.\r
+ add bx,ax ; of bitmaps next row on screen\r
+ mov [LineInc],bx\r
+ mov [Columns],al ; Use bh as column loop count\r
+ and cx,0003h ; mask X coord giving plane of 1st\r
+ ; bitmap pixel(zero CH coincidentally)\r
+ mov ah,11h ; Init. mask for VGA plane selection\r
+ shl ah,cl ; Shift for starting pixel plane\r
+ mov bh,ah\r
+ mov dx,SC_INDEX ; Prepare VGA for cpu to video writes\r
+ mov al,MAP_MASK\r
+ out dx,al\r
+ inc dx\r
+ mov [Plane],4 ; Set plane counter to 4\r
+@@PlaneLoop:\r
+ push di ; Save bitmap's start dest. offset\r
+ mov bl,[BMHeight] ; Reset row counter (BL)\r
+ mov al,bh\r
+ out dx,al ; set vga write plane\r
+@@RowLoop:\r
+ mov cl,[Columns] ; Reset Column counter cl\r
+ shr cx,1\r
+ jnc @@ColLoop\r
+ lodsb\r
+ mov es:[di],al\r
+ dec di\r
+@@ColLoop:\r
+ lodsw ; Get next source bitmap byte\r
+ xchg al,ah\r
+ mov es:[di],ax\r
+ sub di,2\r
+ loop @@ColLoop ; loop if more columns left\r
+\r
+ add di,[LineInc] ; Move to next row\r
+ dec bl ; decrement row counter\r
+ jnz @@RowLoop ; Jump if more rows left\r
+ pop di ; Restore bitmaps start dest byte\r
+ ror bh,1 ; Shift mask for next plane\r
+ sbb di,0 ; If wrapped increment dest address\r
+ dec [Plane] ; Decrement plane counter\r
+ jnz @@PlaneLoop ; Jump if more planes left\r
+\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret
\ No newline at end of file
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XPBITMAP - header file\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+; ****** Aeronautical Research Laboratory ****************\r
+; ****** Defence Science and Technology Organisation ****************\r
+; ****** Australia ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;-----------------------------------------------------------------------*/\r
+\r
+#ifndef _XPBITMAP_H_\r
+#define _XPBITMAP_H_\r
+\r
+\r
+/* FUNCTIONS =========================================================== */\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+\r
+ void x_put_masked_pbm( /* Copy a planar bitmap from SRAM masking */\r
+ WORD X, /* only non zero pixels to VRAM */\r
+ WORD Y,\r
+ WORD ScrnOffs,\r
+ BYTE far * Bitmap);\r
+\r
+ void x_flip_masked_pbm( /* Copy a planar bitmap from SRAM masking */\r
+ WORD X, /* only non zero pixels to VRAM. Bitmap */\r
+ WORD Y, /* is mirrored. */\r
+ WORD ScrnOffs,\r
+ BYTE far * Bitmap,\r
+ WORD orientation);\r
+\r
+ void x_put_pbm( /* Copy a planar bitmap from SRAM to VRAM */\r
+ WORD X,\r
+ WORD Y,\r
+ WORD ScrnOffs,\r
+ BYTE far * Bitmap);\r
+\r
+ void x_flip_pbm( /* Copy a planar bitmap from SRAM to VRAM */\r
+ WORD X,\r
+ WORD Y,\r
+ WORD ScrnOffs,\r
+ BYTE far * Bitmap,\r
+ WORD orientation);\r
+\r
+ void x_get_pbm( /* Copy a planar bitmap from VRAM to SRAM */\r
+ WORD X,\r
+ WORD Y,\r
+ BYTE Bw,\r
+ BYTE Bh,\r
+ WORD ScrnOffs,\r
+ BYTE far * Bitmap);\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XPBITMAP - Include file\r
+;\r
+; XPBITMAP.ASM export functions\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+ global _x_put_masked_pbm :proc\r
+ global _x_flip_masked_pbm :proc\r
+ global _x_put_pbm :proc\r
+ global _x_flip_pbm :proc\r
+ global _x_get_pbm :proc\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XPBMCLIP\r
+;\r
+; Clipped Planar Bitmap functions - System Ram <-> Video Ram\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+COMMENT $\r
+\r
+ This module implements a set of functions to operate on planar bitmaps.\r
+ Planar bitmaps as used by these functions have the following structure:\r
+\r
+ BYTE 0 The bitmap width in bytes (4 pixel groups) range 1..255\r
+ BYTE 1 The bitmap height in rows range 1..255\r
+ BYTE 2..n1 The plane 0 pixels width*height bytes\r
+ BYTE n1..n2 The plane 1 pixels width*height bytes\r
+ BYTE n2..n3 The plane 2 pixels width*height bytes\r
+ BYTE n3..n4 The plane 3 pixels width*height bytes\r
+\r
+ These functions provide the fastest possible bitmap blts from system ram to\r
+ to video and further, the single bitmap is applicable to all pixel\r
+ allignments. The masked functions do not need separate masks since all non\r
+ zero pixels are considered to be masking pixels, hence if a pixel is 0 the\r
+ corresponding screen destination pixel is left unchanged.\r
+\r
+\r
+$\r
+LOCALS\r
+include xlib.inc\r
+include xpbmclip.inc\r
+\r
+ .code\r
+\r
+;----------------------------------------------------------------------\r
+; x_put_masked_pbm_clipx - mask write a planar bitmap from system ram to video\r
+; ram all zero source bitmap bytes indicate destination\r
+; byte to be left unchanged.\r
+; Performs clipping in x directions. similar to\r
+; "x_put_masked_pbm".\r
+;\r
+; See Also: x_put_masked_pbm, x_put_masked_pbm_clipxy\r
+;\r
+; Clipping region variables: LeftClip,RightClip\r
+;\r
+; Written by Themie Gouthas\r
+;\r
+; This code is a SLOW hack, any better ideas are welcome\r
+;----------------------------------------------------------------------\r
+_x_put_masked_pbm_clipx proc\r
+ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword\r
+LOCAL Plane:byte,CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+\r
+ les si,[Bitmap] ; Point ES:SI to start of bitmap\r
+\r
+ xor ax,ax ; Clear AX\r
+ mov [CType],ax ; Clear Clip type descision var\r
+ mov al,byte ptr es:[si] ; AX=width (byte coverted to word)\r
+\r
+\r
+ mov di,[X] ; DI = X coordinate of dest\r
+ mov cx,di ; copy to CX\r
+ sar di,2 ; convert to offset in row\r
+\r
+\r
+ ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+ mov dx,[_LeftClip] ; Is X Coord to the right of\r
+ sub dx,di ; LeftClip ?\r
+ jle @@NotLeftClip ; Yes! => no left clipping\r
+ cmp dx,ax ; Is dist of X Coord from\r
+ jnl @@NotVisible ; ClipLeft > Width ? yes => the\r
+ ; bitmap is not visible\r
+ add di,dx\r
+ mov [LeftSkip],dx\r
+ mov [DataInc],dx\r
+ sub ax,dx\r
+ mov [CType],1\r
+ jmp short @@HorizClipDone\r
+\r
+ ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotVisible:\r
+ mov ax,1\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+\r
+ ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotLeftClip:\r
+ mov dx,[_RightClip]\r
+ sub dx,di\r
+ js @@NotVisible\r
+ mov [LeftSkip],0\r
+ mov [DataInc],0\r
+ cmp dx,ax\r
+ jge @@HorizClipDone ; was jg\r
+ inc dx\r
+ sub ax,dx\r
+ mov [DataInc],ax\r
+ mov ax,dx\r
+ mov [CType],-1\r
+\r
+@@HorizClipDone:\r
+\r
+ xor bh,bh\r
+ mov bl,byte ptr es:[si+1] ; BX = height\r
+\r
+ mov [Width],ax ; Save width and height of clipped\r
+ mov [Height],bx ; image\r
+\r
+\r
+ add si,2 ; Skip dimension bytes in source\r
+ add si,[LeftSkip] ; Skip pixels in front of row that\r
+ ; are clipped\r
+\r
+\r
+ mov bx,[_ScrnLogicalByteWidth] ; Set BX to Logical Screen Width\r
+ mov dx,bx ; BX - Width of image = No. bytes\r
+ sub dx,ax ; to first byte of next screen\r
+ mov [LineInc],dx ; row.\r
+\r
+ mov ax,[Y] ; Calculate screen start row\r
+ mul bx ; then adding screen offset\r
+ add di,ax\r
+ add di,[ScrnOffs]\r
+ mov ax,es ; copy ES to DS\r
+ mov ds,ax\r
+ mov ax,SCREEN_SEG ; Point ES to VGA segment\r
+ mov es,ax\r
+\r
+ and cx,3\r
+ mov ah,11h ; Set up initial plane mask\r
+ shl ah,cl\r
+\r
+ mov dx,SC_INDEX ; Prepare VGA for cpu to video writes\r
+ mov al,MAP_MASK\r
+ out dx,al\r
+ inc dx\r
+ mov [Plane],4 ; Set plane counter to 4\r
+ mov bh,byte ptr [Width] ; set bh to width for fast looping\r
+@@PlaneLoop:\r
+ push di ; Save bitmap's start dest. offset\r
+ mov bl,byte ptr [Height] ; Reset row counter (BL)\r
+ mov al,ah\r
+ out dx,al ; set vga write plane\r
+@@RowLoop:\r
+ mov cl,bh ; Reset Column counter cl\r
+ jcxz @@NoWidth\r
+@@ColLoop:\r
+ lodsb ; Get next source bitmap byte\r
+ or al,al ; If not zero then write to dest.\r
+ jz @@NoPixel ; otherwise skip to next byte\r
+ mov es:[di],al\r
+@@NoPixel:\r
+ inc di\r
+ loop @@ColLoop\r
+@@NoWidth:\r
+ add si,[DataInc] ; Move to next source row\r
+ add di,[LineInc] ; Move to next screen row\r
+ dec bl ; decrement row counter\r
+ jnz @@RowLoop ; Jump if more rows left\r
+ pop di ; Restore bitmaps start dest byte\r
+ rol ah,1 ; Shift mask for next plane\r
+\r
+ ; Plane Transition (A HACK but it works!)\r
+\r
+ jnb @@Nocarry ; Jump if not plane transition\r
+ mov bl,ah ; Save Plane Mask\r
+ mov ax,[CType] ; set AX to clip type inc variable\r
+ add bh,al ; Update advancing variables\r
+ sub [DataInc],ax ;\r
+ sub [LineInc],ax ;\r
+ cmp al,0 ; What type of clip do we have\r
+ mov ah,bl ; restore Plane mask\r
+ jg @@RightAdvance ; jump on a right clip!\r
+ inc di ; otherwise increment DI\r
+ jmp @@Nocarry\r
+@@RightAdvance:\r
+ dec si\r
+@@Nocarry:\r
+ dec [Plane] ; Decrement plane counter\r
+ jnz @@PlaneLoop ; Jump if more planes left\r
+\r
+ xor ax,ax\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_put_masked_pbm_clipx endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_put_masked_pbm_clipy - mask write a planar bitmap from system ram to video\r
+; ram all zero source bitmap bytes indicate destination\r
+; byte to be left unchanged.\r
+; Performs clipping in y direction. similar to\r
+; "x_put_masked_pbm".\r
+;\r
+; See Also: x_put_masked_pbm, x_put_masked_pbm_clipx, x_put_masked_pbm_clipy\r
+;\r
+; Clipping region variables: TopClip,BottomClip\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_put_masked_pbm_clipy proc\r
+ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword\r
+LOCAL Width,Height,TopRow,LineInc,PlaneInc:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+\r
+ les si,[Bitmap]\r
+\r
+ xor bh,bh\r
+ mov bl,byte ptr es:[si+1] ; BX = height\r
+\r
+ xor ah,ah\r
+ mov al,byte ptr es:[si] ; AX = width\r
+\r
+ mov cx,ax ; Save AX\r
+ mul bx ; AX = AX*BX = bytes/plane\r
+ mov [PlaneInc],ax ; save as PlaneInc\r
+ mov ax,cx ; Restore AX\r
+\r
+ mov di,[X]\r
+ mov cx,di\r
+ shr di,2\r
+\r
+ ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;\r
+\r
+ mov dx,[_TopClip] ; Compare u.l. Y coord with Top\r
+ sub dx,[Y] ; clipping border\r
+ jle @@NotTopClip ; jump if VBM not clipped from above\r
+ cmp dx,bx\r
+ jnl @@NotVisible ; jump if VBM is completely obscured\r
+ mov [TopRow],dx\r
+ sub bx,dx\r
+ add [Y],dx\r
+ jmp short @@VertClipDone\r
+\r
+ ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotVisible:\r
+ mov ax,1\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+\r
+ ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotTopClip:\r
+ mov dx,[_BottomClip]\r
+ sub dx,[Y]\r
+ js @@NotVisible\r
+ mov [TopRow],0\r
+ cmp dx,bx\r
+ jg @@VertClipDone\r
+ inc dx\r
+ mov bx,dx\r
+\r
+@@VertClipDone:\r
+\r
+ mov [Width],ax\r
+ mov [Height],bx ; Calculate relative offset in data\r
+ mul [TopRow] ; of first visible scanline\r
+ add ax,2 ; Skip dimension bytes in source\r
+ add si,ax ; Skip top rows that arent visible\r
+\r
+\r
+ mov ax,[Y] ; Calculate screen row\r
+ mov bx,[_ScrnLogicalByteWidth] ; by mult. Y coord by Screen\r
+ mul bx ; width then adding screen offset\r
+ add di,ax\r
+ add di,[ScrnOffs]\r
+ sub bx,[Width] ; calculate difference from end of\r
+ mov [LineInc],bx ; b.m. in curr line to beginning of\r
+ ; b.m. on next scan line\r
+ mov ax,es ; copy ES to DS\r
+ mov ds,ax\r
+ mov ax,SCREEN_SEG ; Point ES to VGA segment\r
+ mov es,ax\r
+\r
+ mov ah,11h ; Set up initial plane mask\r
+ and cx,3\r
+ shl ah,cl\r
+\r
+ mov dx,SC_INDEX ; Prepare VGA for cpu to video writes\r
+ mov al,MAP_MASK\r
+ out dx,al\r
+ inc dx\r
+ mov bh,4 ; Set plane counter to 4\r
+@@PlaneLoop:\r
+ push di ; Save bitmap's start dest. offset\r
+ push si ; Save Bitmaps data offset\r
+ mov bl,byte ptr [Height] ; Reset row counter (BL)\r
+ mov al,ah\r
+ out dx,al ; set vga write plane\r
+@@RowLoop:\r
+ mov cl,byte ptr [Width] ; Reset Column counter cl\r
+@@ColLoop:\r
+ lodsb ; Get next source bitmap byte\r
+ or al,al ; If not zero then write to dest.\r
+ jz @@NoPixel ; otherwise skip to next byte\r
+ mov es:[di],al\r
+@@NoPixel:\r
+ inc di\r
+ loop @@ColLoop ; loop if more columns left\r
+ add di,[LineInc] ; Move to next row\r
+ dec bl ; decrement row counter\r
+ jnz @@RowLoop ; Jump if more rows left\r
+ pop si ; Restore SI and set to offset of\r
+ add si,[PlaneInc] ; first vis pixel in next plane data\r
+ pop di ; Restore bitmaps start dest byte\r
+ rol ah,1 ; Shift mask for next plane\r
+ adc di,0 ; if carry increment screen offset\r
+ dec bh ; Decrement plane counter\r
+ jnz @@PlaneLoop ; Jump if more planes left\r
+\r
+ xor ax,ax\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_put_masked_pbm_clipy endp\r
+\r
+;----------------------------------------------------------------------\r
+; x_put_masked_pbm_clipxy - Write a planar bitmap from system ram to video\r
+; RAM with clipping in x and y directions. similar to\r
+; "x_put_masked_pbm".\r
+;\r
+; See Also: x_put_masked_pbm, x_put_masked_pbm_clipx, x_put_masked_pbm_clipxy\r
+;\r
+; Clipping region variables: LeftClip,RightClip,TopClip,BottomClip\r
+;\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_put_masked_pbm_clipxy proc\r
+ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword\r
+LOCAL Plane:byte,CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc,PlaneInc:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+\r
+ les si,[Bitmap]\r
+\r
+ xor ax,ax\r
+ mov [CType],ax\r
+ mov al,byte ptr es:[si] ; AX = width\r
+ xor bh,bh\r
+ mov bl,byte ptr es:[si+1] ; BX = height\r
+\r
+ mov cx,ax ; Save AX\r
+ mul bx ; AX = AX*BX = bytes/plane\r
+ mov [PlaneInc],ax ; save as PlaneInc\r
+ mov ax,cx ; Restore AX\r
+\r
+\r
+ mov di,[X] ; DI = X coordinate of dest.\r
+ mov cx,di ; save in CX\r
+ sar di,2 ; convert to address byte\r
+\r
+\r
+ ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;\r
+\r
+ mov dx,[_TopClip] ; Compare u.l. Y coord with Top\r
+ sub dx,[Y] ; clipping border\r
+ jle @@NotTopClip ; jump if VBM not clipped from above\r
+ cmp dx,bx\r
+ jnl @@NotVisible ; jump if VBM is completely obscured\r
+ mov [TopRow],dx\r
+ sub bx,dx\r
+ add [Y],dx\r
+ jmp short @@VertClipDone\r
+\r
+ ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotVisible:\r
+ mov ax,1\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+\r
+ ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotTopClip:\r
+ mov dx,[_BottomClip]\r
+ sub dx,[Y]\r
+ js @@NotVisible\r
+ mov [TopRow],0\r
+ cmp dx,bx\r
+ jg @@VertClipDone\r
+ inc dx\r
+ mov bx,dx\r
+\r
+@@VertClipDone:\r
+\r
+ ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+ mov dx,[_LeftClip]\r
+ sub dx,di\r
+ jle @@NotLeftClip\r
+ cmp dx,ax\r
+ jnl @@NotVisible\r
+\r
+ add di,dx\r
+ mov [LeftSkip],dx\r
+ mov [DataInc],dx\r
+ sub ax,dx\r
+ mov [CType],1\r
+ jmp short @@HorizClipDone\r
+\r
+ ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotLeftClip:\r
+ mov dx,[_RightClip]\r
+ sub dx,di\r
+ js @@NotVisible\r
+ mov [LeftSkip],0\r
+ mov [DataInc],0\r
+ cmp dx,ax\r
+ jge @@HorizClipDone ; was jg\r
+ inc dx\r
+ sub ax,dx\r
+ mov [DataInc],ax\r
+ mov ax,dx\r
+\r
+\r
+ mov [CType],-1\r
+\r
+@@HorizClipDone:\r
+\r
+\r
+\r
+ mov [Width],ax ; Save width and height of clipped\r
+ mov [Height],bx ; image\r
+\r
+ add ax,[DataInc] ; AX = original width of image\r
+ mul [TopRow] ; Calculate bytes in clipped top\r
+ add si,ax ; rows\r
+ add si,2 ; Skip dimension bytes in source\r
+ add si,[LeftSkip] ; Skip pixels in front of row that\r
+ ; are clipped\r
+\r
+ mov bx,[_ScrnLogicalByteWidth] ; Set BX to Logical Screen Width\r
+ mov dx,bx ; BX - Width of image = No. bytes\r
+ sub dx,[Width] ; to first byte of next screen\r
+ mov [LineInc],dx ; row.\r
+\r
+ mov ax,[Y] ; Calculate screen start row\r
+ mul bx ; then adding screen offset\r
+ add di,ax\r
+ add di,[ScrnOffs]\r
+ mov ax,es ; copy ES to DS\r
+ mov ds,ax\r
+ mov ax,SCREEN_SEG ; Point ES to VGA segment\r
+ mov es,ax\r
+\r
+\r
+\r
+ and cx,3\r
+ mov ah,11h ; Set up initial plane mask\r
+ shl ah,cl\r
+\r
+ mov dx,SC_INDEX ; Prepare VGA for cpu to video writes\r
+ mov al,MAP_MASK\r
+ out dx,al\r
+ inc dx\r
+ mov [Plane],4 ; Set plane counter to 4\r
+ mov bh,byte ptr [Width] ; set bh to width for fast looping\r
+@@PlaneLoop:\r
+ push di ; Save bitmap's start dest. offset\r
+ push si\r
+ mov bl,byte ptr [Height] ; Reset row counter (BL)\r
+ mov al,ah\r
+ out dx,al ; set vga write plane\r
+@@RowLoop:\r
+ mov cl,bh ; Reset Column counter cl\r
+ jcxz @@NoWidth\r
+@@ColLoop:\r
+ lodsb ; Get next source bitmap byte\r
+ or al,al ; If not zero then write to dest.\r
+ jz @@NoPixel ; otherwise skip to next byte\r
+ mov es:[di],al\r
+@@NoPixel:\r
+ inc di\r
+ loop @@ColLoop\r
+@@NoWidth:\r
+ add si,[DataInc] ; Move to next source row\r
+ add di,[LineInc] ; Move to next screen row\r
+ dec bl ; decrement row counter\r
+ jnz @@RowLoop ; Jump if more rows left\r
+ pop si ; Restore SI and set to offset of\r
+ add si,[PlaneInc] ; first vis pixel in next plane data\r
+ pop di ; Restore bitmaps start dest byte\r
+ rol ah,1 ; Shift mask for next plane\r
+\r
+ ; Plane Transition (A HACK but it works!)\r
+\r
+ jnb @@Nocarry ; Jump if not plane transition\r
+ mov bl,ah ; Save Plane Mask\r
+ mov ax,[CType] ; set AX to clip type inc variable\r
+ add bh,al ; Update advancing variables\r
+ sub [DataInc],ax ;\r
+ sub [LineInc],ax ;\r
+ cmp al,0 ; What type of clip do we have\r
+ mov ah,bl ; restore Plane mask\r
+ jg @@RightAdvance ; jump on a right clip!\r
+ inc di ; otherwise increment DI\r
+ jmp @@Nocarry\r
+@@RightAdvance:\r
+ dec si\r
+@@Nocarry:\r
+ dec [Plane] ; Decrement plane counter\r
+ jnz @@PlaneLoop ; Jump if more planes left\r
+\r
+ xor ax,ax\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_put_masked_pbm_clipxy endp\r
+\r
+\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_put_pbm_clipx - Write a planar bitmap from system ram to video ram\r
+; with clipping in x and y directions. similar to\r
+; "x_put_pbm".\r
+;\r
+; See Also: x_put_pbm_clip\r
+;\r
+;\r
+; See Also: x_put_pbm,x_put_pbm_clipy,x_put_pbm_clipxy\r
+;\r
+; Clipping region variables: LeftClip,RightClip\r
+;\r
+; Written by Themie Gouthas\r
+;\r
+; This code is a SLOW hack, any better ideas are welcome\r
+;----------------------------------------------------------------------\r
+_x_put_pbm_clipx proc\r
+ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword\r
+LOCAL Plane:byte,CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+\r
+ les si,[Bitmap]\r
+\r
+ xor ax,ax\r
+ mov [CType],ax\r
+ mov al,byte ptr es:[si] ; AX = width\r
+\r
+\r
+ mov di,[X] ; DI = X coordinate of dest.\r
+ mov cx,di ; save in CX\r
+ sar di,2 ; convert to address byte\r
+\r
+\r
+\r
+ ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+ mov dx,[_LeftClip]\r
+ sub dx,di\r
+ jle @@NotLeftClip\r
+ cmp dx,ax\r
+ jnl @@NotVisible\r
+\r
+ add di,dx\r
+ mov [LeftSkip],dx\r
+ mov [DataInc],dx\r
+ sub ax,dx\r
+ mov [CType],1\r
+ jmp short @@HorizClipDone\r
+\r
+ ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotVisible:\r
+ mov ax,1\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+\r
+ ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotLeftClip:\r
+ mov dx,[_RightClip]\r
+ sub dx,di\r
+ js @@NotVisible\r
+ mov [LeftSkip],0\r
+ mov [DataInc],0\r
+ cmp dx,ax\r
+ jge @@HorizClipDone ; was jg\r
+ inc dx\r
+ sub ax,dx\r
+ mov [DataInc],ax\r
+ mov ax,dx\r
+ mov [CType],-1\r
+\r
+@@HorizClipDone:\r
+\r
+ xor bh,bh\r
+ mov bl,byte ptr es:[si+1] ; BX = height\r
+\r
+ mov [Width],ax ; Save width and height of clipped\r
+ mov [Height],bx ; image\r
+\r
+\r
+ add si,2 ; Skip dimension bytes in source\r
+ add si,[LeftSkip] ; Skip pixels in front of row that\r
+ ; are clipped\r
+\r
+\r
+ mov bx,[_ScrnLogicalByteWidth] ; Set BX to Logical Screen Width\r
+ mov dx,bx ; BX - Width of image = No. bytes\r
+ sub dx,ax ; to first byte of next screen\r
+ mov [LineInc],dx ; row.\r
+\r
+ mov ax,[Y] ; Calculate screen start row\r
+ mul bx ; then adding screen offset\r
+ add di,ax\r
+ add di,[ScrnOffs]\r
+ mov ax,es ; copy ES to DS\r
+ mov ds,ax\r
+ mov ax,SCREEN_SEG ; Point ES to VGA segment\r
+ mov es,ax\r
+\r
+ and cx,3\r
+ mov ah,11h ; Set up initial plane mask\r
+ shl ah,cl\r
+\r
+ mov dx,SC_INDEX ; Prepare VGA for cpu to video writes\r
+ mov al,MAP_MASK\r
+ out dx,al\r
+ inc dx\r
+ mov [Plane],4 ; Set plane counter to 4\r
+ mov bh,byte ptr [Width] ; set bh to width for fast looping\r
+@@PlaneLoop:\r
+ push di ; Save bitmap's start dest. offset\r
+ mov bl,byte ptr [Height] ; Reset row counter (BL)\r
+ mov al,ah\r
+ out dx,al ; set vga write plane\r
+@@RowLoop:\r
+ mov cl,bh ; Reset Column counter cl\r
+ shr cl,1\r
+ rep movsw ; Copy a complete row\r
+ adc cl,0\r
+ rep movsb\r
+ add si,[DataInc] ; Move to next source row\r
+ add di,[LineInc] ; Move to next screen row\r
+ dec bl ; decrement row counter\r
+ jnz @@RowLoop ; Jump if more rows left\r
+ pop di ; Restore bitmaps start dest byte\r
+ rol ah,1 ; Shift mask for next plane\r
+\r
+ ; Plane Transition (A HACK but it works!)\r
+\r
+ jnb @@Nocarry ; Jump if not plane transition\r
+ mov bl,ah ; Save Plane Mask\r
+ mov ax,[CType] ; set AX to clip type inc variable\r
+ add bh,al ; Update advancing variables\r
+ sub [DataInc],ax ;\r
+ sub [LineInc],ax ;\r
+ cmp al,0 ; What type of clip do we have\r
+ mov ah,bl ; restore Plane mask\r
+ jg @@RightAdvance ; jump on a right clip!\r
+ inc di ; otherwise increment DI\r
+ jmp @@Nocarry\r
+@@RightAdvance:\r
+ dec si\r
+@@Nocarry:\r
+ dec [Plane] ; Decrement plane counter\r
+ jnz @@PlaneLoop ; Jump if more planes left\r
+\r
+ xor ax,ax\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_put_pbm_clipx endp\r
+\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_put_pbm_clipy - Write a planar bitmap from system ram to video ram\r
+; with clipping in y direction only. similar to\r
+; "x_put_pbm".\r
+;\r
+; See Also: x_put_pbm,x_put_pbm_clipx,x_put_pbm_clipxy\r
+;\r
+; Clipping region variables: TopClip,BottomClip\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_put_pbm_clipy proc\r
+ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword\r
+LOCAL Width,Height,TopRow,LineInc,PlaneInc:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+\r
+ les si,[Bitmap]\r
+\r
+ xor bh,bh\r
+ mov bl,byte ptr es:[si+1] ; BX = height\r
+ ;mov [Height],bx\r
+\r
+ xor ah,ah\r
+ mov al,byte ptr es:[si] ; AX = width\r
+ mov [Width],ax\r
+\r
+ mov cx,ax ; Save AX\r
+ mul bx ; AX = AX*BX = bytes/plane\r
+ mov [PlaneInc],ax ; save as PlaneInc\r
+ mov ax,cx ; Restore AX\r
+\r
+ mov di,[X]\r
+ mov cx,di\r
+ and cx,3\r
+ shr di,2\r
+\r
+ ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;\r
+\r
+ mov dx,[_TopClip] ; Compare u.l. Y coord with Top\r
+ sub dx,[Y] ; clipping border\r
+ jle @@NotTopClip ; jump if VBM not clipped from above\r
+ cmp dx,bx\r
+ jnl @@NotVisible ; jump if VBM is completely obscured\r
+ mov [TopRow],dx\r
+ sub bx,dx\r
+ add [Y],dx\r
+ jmp short @@VertClipDone\r
+\r
+ ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotVisible:\r
+ mov ax,1\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+\r
+ ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotTopClip:\r
+ mov dx,[_BottomClip]\r
+ sub dx,[Y]\r
+ js @@NotVisible\r
+ mov [TopRow],0\r
+ cmp dx,bx\r
+ jg @@VertClipDone\r
+ inc dx\r
+ mov bx,dx\r
+\r
+@@VertClipDone:\r
+\r
+ mov [Height],bx ; Calculate relative offset in data\r
+ mul [TopRow] ; of first visible scanline\r
+ add ax,2 ; Skip dimension bytes in source\r
+ add si,ax ; Skip top rows that arent visible\r
+\r
+\r
+ mov ax,[Y] ; Calculate screen row\r
+ mov bx,[_ScrnLogicalByteWidth] ; by mult. Y coord by Screen\r
+ mul bx ; width then adding screen offset\r
+ add di,ax\r
+ add di,[ScrnOffs]\r
+ sub bx,[Width] ; calculate difference from end of\r
+ mov [LineInc],bx ; b.m. in curr line to beginning of\r
+ ; b.m. on next scan line\r
+ mov ax,es ; copy ES to DS\r
+ mov ds,ax\r
+ mov ax,SCREEN_SEG ; Point ES to VGA segment\r
+ mov es,ax\r
+\r
+ mov ah,11h ; Set up initial plane mask\r
+ shl ah,cl\r
+\r
+ mov dx,SC_INDEX ; Prepare VGA for cpu to video writes\r
+ mov al,MAP_MASK\r
+ out dx,al\r
+ inc dx\r
+ mov bh,4 ; Set plane counter to 4\r
+@@PlaneLoop:\r
+ push di ; Save bitmap's start dest. offset\r
+ push si ; Save Bitmaps data offset\r
+ mov bl,byte ptr [Height] ; Reset row counter (BL)\r
+ mov al,ah\r
+ out dx,al ; set vga write plane\r
+@@RowLoop:\r
+ mov cl,byte ptr [Width] ; Reset Column counter cl\r
+ shr cl,1\r
+ rep movsw ; Copy a complete row\r
+ adc cl,0\r
+ rep movsb\r
+\r
+ add di,[LineInc] ; Move to next row\r
+ dec bl ; decrement row counter\r
+ jnz @@RowLoop ; Jump if more rows left\r
+ pop si ; Restore SI and set to offset of\r
+ add si,[PlaneInc] ; first vis pixel in next plane data\r
+ pop di ; Restore bitmaps start dest byte\r
+ rol ah,1 ; Shift mask for next plane\r
+ adc di,0 ; if carry increment screen offset\r
+ dec bh ; Decrement plane counter\r
+ jnz @@PlaneLoop ; Jump if more planes left\r
+\r
+ xor ax,ax\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_put_pbm_clipy endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_put_pbm_clipxy - Write a planar bitmap from system ram to video ram\r
+; with clipping in x and y directions. similar to\r
+; "x_put_pbm".\r
+;\r
+; See Also: x_put_pbm,x_put_pbm_clipy,x_put_pbm_clipx\r
+;\r
+; Clipping region variables: LeftClip,RightClip,TopClip,BottomClip\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_put_pbm_clipxy proc\r
+ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword\r
+LOCAL Plane:byte,CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc,PlaneInc:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+\r
+ les si,[Bitmap]\r
+\r
+ xor ax,ax\r
+ mov [CType],ax\r
+ mov al,byte ptr es:[si] ; AX = width\r
+ xor bh,bh\r
+ mov bl,byte ptr es:[si+1] ; BX = height\r
+\r
+ mov cx,ax ; Save AX\r
+ mul bx ; AX = AX*BX = bytes/plane\r
+ mov [PlaneInc],ax ; save as PlaneInc\r
+ mov ax,cx ; Restore AX\r
+\r
+\r
+ mov di,[X] ; DI = X coordinate of dest.\r
+ mov cx,di ; save in CX\r
+ sar di,2 ; convert to address byte\r
+\r
+\r
+ ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;\r
+\r
+ mov dx,[_TopClip] ; Compare u.l. Y coord with Top\r
+ sub dx,[Y] ; clipping border\r
+ jle @@NotTopClip ; jump if VBM not clipped from above\r
+ cmp dx,bx\r
+ jnl @@NotVisible ; jump if VBM is completely obscured\r
+ mov [TopRow],dx\r
+ sub bx,dx\r
+ add [Y],dx\r
+ jmp short @@VertClipDone\r
+\r
+ ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotVisible:\r
+ mov ax,1\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+\r
+ ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotTopClip:\r
+ mov dx,[_BottomClip]\r
+ sub dx,[Y]\r
+ js @@NotVisible\r
+ mov [TopRow],0\r
+ cmp dx,bx\r
+ jg @@VertClipDone\r
+ inc dx\r
+ mov bx,dx\r
+\r
+@@VertClipDone:\r
+\r
+ ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+ mov dx,[_LeftClip]\r
+ sub dx,di\r
+ jle @@NotLeftClip\r
+ cmp dx,ax\r
+ jnl @@NotVisible\r
+\r
+ add di,dx\r
+ mov [LeftSkip],dx\r
+ mov [DataInc],dx\r
+ sub ax,dx\r
+ mov [CType],1\r
+ jmp short @@HorizClipDone\r
+\r
+ ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotLeftClip:\r
+ mov dx,[_RightClip]\r
+ sub dx,di\r
+ js @@NotVisible\r
+ mov [LeftSkip],0\r
+ mov [DataInc],0\r
+ cmp dx,ax\r
+ jge @@HorizClipDone ; was jg\r
+ inc dx\r
+ sub ax,dx\r
+ mov [DataInc],ax\r
+ mov ax,dx\r
+ mov [CType],-1\r
+\r
+@@HorizClipDone:\r
+\r
+\r
+\r
+ mov [Width],ax ; Save width and height of clipped\r
+ mov [Height],bx ; image\r
+\r
+ add ax,[DataInc] ; AX = original width of image\r
+ mul [TopRow] ; Calculate bytes in clipped top\r
+ add si,ax ; rows\r
+ add si,2 ; Skip dimension bytes in source\r
+ add si,[LeftSkip] ; Skip pixels in front of row that\r
+ ; are clipped\r
+\r
+ mov bx,[_ScrnLogicalByteWidth] ; Set BX to Logical Screen Width\r
+ mov dx,bx ; BX - Width of image = No. bytes\r
+ sub dx,[Width] ; to first byte of next screen\r
+ mov [LineInc],dx ; row.\r
+\r
+ mov ax,[Y] ; Calculate screen start row\r
+ mul bx ; then adding screen offset\r
+ add di,ax\r
+ add di,[ScrnOffs]\r
+ mov ax,es ; copy ES to DS\r
+ mov ds,ax\r
+ mov ax,SCREEN_SEG ; Point ES to VGA segment\r
+ mov es,ax\r
+\r
+\r
+\r
+ and cx,3\r
+ mov ah,11h ; Set up initial plane mask\r
+ shl ah,cl\r
+\r
+ mov dx,SC_INDEX ; Prepare VGA for cpu to video writes\r
+ mov al,MAP_MASK\r
+ out dx,al\r
+ inc dx\r
+ mov [Plane],4 ; Set plane counter to 4\r
+ mov bh,byte ptr [Width] ; set bh to width for fast looping\r
+@@PlaneLoop:\r
+ push di ; Save bitmap's start dest. offset\r
+ push si\r
+ mov bl,byte ptr [Height] ; Reset row counter (BL)\r
+ mov al,ah\r
+ out dx,al ; set vga write plane\r
+@@RowLoop:\r
+ mov cl,bh ; Reset Column counter cl\r
+ shr cl,1\r
+ rep movsw ; Copy a complete row\r
+ adc cl,0\r
+ rep movsb\r
+ add si,[DataInc] ; Move to next source row\r
+ add di,[LineInc] ; Move to next screen row\r
+ dec bl ; decrement row counter\r
+ jnz @@RowLoop ; Jump if more rows left\r
+ pop si ; Restore SI and set to offset of\r
+ add si,[PlaneInc] ; first vis pixel in next plane data\r
+ pop di ; Restore bitmaps start dest byte\r
+ rol ah,1 ; Shift mask for next plane\r
+\r
+ ; Plane Transition (A HACK but it works!)\r
+\r
+ jnb @@Nocarry ; Jump if not plane transition\r
+ mov bl,ah ; Save Plane Mask\r
+ mov ax,[CType] ; set AX to clip type inc variable\r
+ add bh,al ; Update advancing variables\r
+ sub [DataInc],ax ;\r
+ sub [LineInc],ax ;\r
+ cmp al,0 ; What type of clip do we have\r
+ mov ah,bl ; restore Plane mask\r
+ jg @@RightAdvance ; jump on a right clip!\r
+ inc di ; otherwise increment DI\r
+ jmp @@Nocarry\r
+@@RightAdvance:\r
+ dec si\r
+@@Nocarry:\r
+ dec [Plane] ; Decrement plane counter\r
+ jnz @@PlaneLoop ; Jump if more planes left\r
+\r
+ xor ax,ax\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_put_pbm_clipxy endp\r
+\r
+ end\r
+\r
+\r
+\r
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XPBMCLIP - header file\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;-----------------------------------------------------------------------*/\r
+\r
+#ifndef _XPBMCLIP_H_\r
+#define _XPBMCLIP_H_\r
+\r
+\r
+/* FUNCTIONS =========================================================== */\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+\r
+ int x_put_masked_pbm_clipx( /* Copy a planar bitmap from SRAM masking */\r
+ int X, /* only non zero pixels to VRAM */\r
+ int Y, /* Supports clipping in the X direction */\r
+ WORD ScrnOffs,\r
+ BYTE far * Bitmap);\r
+\r
+\r
+ int x_put_masked_pbm_clipy( /* Copy a planar bitmap from SRAM masking */\r
+ int X, /* only non zero pixels to VRAM */\r
+ int Y, /* Supports clipping in the Y direction */\r
+ WORD ScrnOffs,\r
+ BYTE far * Bitmap);\r
+\r
+ int x_put_masked_pbm_clipxy( /* Copy a planar bitmap from SRAM masking */\r
+ int X, /* only non zero pixels to VRAM */\r
+ int Y, /* Supports clipping in the Y direction */\r
+ WORD ScrnOffs,\r
+ BYTE far * Bitmap);\r
+\r
+ int x_put_pbm_clipx( /* Copy a planar bitmap from SRAM masking */\r
+ int X, /* Supports clipping in the x direction */\r
+ int Y,\r
+ WORD ScrnOffs,\r
+ BYTE far * Bitmap);\r
+\r
+ int x_put_pbm_clipy( /* Copy a planar bitmap from SRAM masking */\r
+ int X, /* Supports clipping in the Y direction */\r
+ int Y,\r
+ WORD ScrnOffs,\r
+ BYTE far * Bitmap);\r
+\r
+ int x_put_pbm_clipx( /* Copy a planar bitmap from SRAM masking */\r
+ int X, /* Supports clipping in the X direction */\r
+ int Y,\r
+ WORD ScrnOffs,\r
+ BYTE far * Bitmap);\r
+\r
+ int x_put_pbm_clipxy( /* Copy a planar bitmap from SRAM masking */\r
+ int X, /* Supports clipping in the X&Y directions */\r
+ int Y,\r
+ WORD ScrnOffs,\r
+ BYTE far * Bitmap);\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XPBMCLIP - Include file\r
+;\r
+; XPBMCLIP.ASM export functions\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+ global _x_put_masked_pbm_clipx :proc\r
+ global _x_put_masked_pbm_clipy :proc\r
+ global _x_put_masked_pbm_clipxy :proc\r
+\r
+ global _x_put_pbm_clipx :proc\r
+ global _x_put_pbm_clipy :proc\r
+ global _x_put_pbm_clipxy :proc\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XPOINT\r
+;\r
+; Point functions all MODE X 256 Color resolutions\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+include xlib.inc\r
+include xpoint.inc\r
+\r
+ .code\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; Mode X (256 color mode) write pixel routine.\r
+; No clipping is performed.\r
+;\r
+; Based on code originally published in DDJ Mag by M. Abrash\r
+;\r
+; C near-callable as:\r
+; void x_put_pix(int X, int Y, int PageOffset, int Color);\r
+;\r
+;\r
+\r
+_x_put_pix proc \r
+ ARG X:word,Y:word,PgOfs:word,Color:word\r
+ push bp ;preserve caller's stack frame\r
+ mov bp,sp ;point to local stack frame\r
+\r
+ mov ax,[_ScrnLogicalByteWidth]\r
+ mul [Y] ;offset of pixel's scan line in page\r
+ mov bx,[X]\r
+ shr bx,2 ;X/4 = offset of pixel in scan line\r
+ add bx,ax ;offset of pixel in page\r
+ add bx,[PgOfs] ;offset of pixel in display memory\r
+ mov ax,SCREEN_SEG\r
+ mov es,ax ;point ES:BX to the pixel's address\r
+\r
+ mov cl,byte ptr [X]\r
+ and cl,011b ;CL = pixel's plane\r
+ mov ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg\r
+ shl ah,cl ;set only the bit for the pixel's\r
+ ; plane to 1\r
+ mov dx,SC_INDEX ;set the Map Mask to enable only the\r
+ out dx,ax ; pixel's plane\r
+\r
+ mov al,byte ptr [Color]\r
+ mov es:[bx],al ;draw the pixel in the desired color\r
+\r
+ pop bp ;restore caller's stack frame\r
+ ret\r
+_x_put_pix endp\r
+\r
+;-------------------------------------------------------------------------\r
+; Mode X (320x240, 256 colors) read pixel routine. Works on all VGAs.\r
+; No clipping is performed.\r
+;\r
+; Based on code originally published in DDJ Mag by M. Abrash\r
+;\r
+; C near-callable as:\r
+; unsigned int x_get_pix(int X, int Y, unsigned int PageBase);\r
+\r
+\r
+_x_get_pix proc\r
+ ARG x:word,y:word,PageBase:word\r
+ push bp ;preserve caller's stack frame\r
+ mov bp,sp ;point to local stack frame\r
+\r
+ mov ax,[_ScrnLogicalByteWidth]\r
+ mul [Y] ;offset of pixel's scan line in page\r
+ mov bx,[X]\r
+ shr bx,1\r
+ shr bx,1 ;X/4 = offset of pixel in scan line\r
+ add bx,ax ;offset of pixel in page\r
+ add bx,[PageBase] ;offset of pixel in display memory\r
+ mov ax,SCREEN_SEG\r
+ mov es,ax ;point ES:BX to the pixel's address\r
+\r
+ mov ah,byte ptr [X]\r
+ and ah,011b ;AH = pixel's plane\r
+ mov al,READ_MAP ;AL = index in GC of the Read Map reg\r
+ mov dx,GC_INDEX ;set the Read Map to read the pixel's\r
+ out dx,ax ; plane\r
+\r
+ mov al,es:[bx] ;read the pixel's color\r
+ sub ah,ah ;convert it to an unsigned int\r
+\r
+ pop bp ;restore caller's stack frame\r
+ ret\r
+_x_get_pix endp\r
+ end\r
+\r
+\r
+ end\r
+\r
+\1a
\ No newline at end of file
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XPOINT - header file\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;-----------------------------------------------------------------------*/\r
+\r
+#ifndef _XPOINT_H_\r
+#define _XPOINT_H_\r
+\r
+\r
+/* FUNCTIONS =========================================================== */\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+\r
+ void x_put_pix( /* Draw a pixel on the screen */\r
+ WORD X,\r
+ WORD Y,\r
+ WORD PageOffset,\r
+ WORD Color);\r
+\r
+ WORD x_get_pix( /* Read a pixel from the screen */\r
+ WORD X,\r
+ WORD Y,\r
+ WORD PageBase);\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XPOINT - Include file\r
+;\r
+; XPOINT.ASM export functions\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+ global _x_put_pix :proc\r
+ global _x_get_pix :proc\r
+\1a
\ No newline at end of file
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XPOLYGON\r
+;\r
+; Filled Triangle function for all MODE X 256 Color resolutions\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; This module is based on code developed by Steve Dollind for his\r
+; XSPACE game.\r
+; Copyright (C) 1992 Steven Dollins -- sdollins@uiuc.edu\r
+;\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+include xlib.inc\r
+include xpolygon.inc\r
+\r
+.data\r
+; Plane masks for clipping left and right edges of rectangle.\r
+ LeftClipPlaneMask db 00fh,00eh,00ch,008h\r
+ RightClipPlaneMask db 00fh,001h,003h,007h\r
+\r
+.code\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; void HLineClipR\r
+;\r
+; Draws a horizontal line from (X1, Y) to (X2, Y).\r
+; Uses Watcom Parameter passing convention in registers\r
+;\r
+; X1 in AX\r
+; X2 in DX\r
+; Y in CX\r
+; Color in BX\r
+; PageOffset in DI\r
+;\r
+; By Themie Gouthas - Adapted from x_fill_rect.\r
+;-----------------------------------------------------------------------\r
+proc _HLineClipR near\r
+ push di\r
+ cmp dx,ax ; if (X2 < X1) then assume no line\r
+ jl @@Invisible ; is visible\r
+\r
+ cmp cx,[_TopClip] ; if (Y < TopClip) then no line\r
+ jl @@Invisible\r
+\r
+ cmp cx,[_BottomClip] ;if (Y > BottomClip) then no line\r
+ jg @@Invisible\r
+\r
+ mov di,[_RightClip] ;convert RightClip to pixel coords\r
+ sal di,2\r
+ cmp ax,di ; if (X1 > RightClip) then no line\r
+ jg @@Invisible\r
+\r
+ cmp dx,di ; if (X2 > RightClip) then\r
+ jle @@ClipLeft ; X2:=RightClip\r
+ mov dx,di\r
+\r
+@@ClipLeft:\r
+ mov di,[_LeftClip] ;convert LeftClip to pixel coords\r
+ sal di,2\r
+ cmp dx,di ; if (X2 < LeftClip) then no line\r
+ jl @@Invisible\r
+\r
+ cmp ax,di ;if (X1 > LeftClip) then were ready to plot\r
+ jge @@DoLine\r
+\r
+ mov ax,di ; X1:=LeftClip\r
+ jmp short @@DoLine\r
+\r
+@@Invisible:\r
+ pop di\r
+ ret\r
+\r
+@@DoLine:\r
+ pop di ; di = PageOffset\r
+ xchg cx,ax ; AX = Y, CX = X1\r
+ mov si,dx ; SI = DX = X2\r
+ mul [_ScrnLogicalByteWidth]\r
+ mov dx,si ; Reset DX to X1 since mul erases DX\r
+ add ax,di\r
+ mov di,cx\r
+ sar di,2 ; Convert to bytes\r
+ add di,ax ; DI->First byte\r
+\r
+ and si,03h ; look up right edge plane mask\r
+ mov ah,RightClipPlaneMask[si]\r
+ mov si,cx ; look up left edge plane mask\r
+ and si,03h\r
+ mov al,LeftClipPlaneMask[si]\r
+\r
+ cmp dx,cx ; No harm in being paranoid..\r
+ jle @@Invisible2\r
+\r
+ xchg cx,dx ;CX=X2, DX=X1\r
+ dec cx\r
+ and dx,not 03h\r
+ sub cx,dx\r
+ js @@Invisible2\r
+ shr cx,2\r
+ jnz @@MasksSet\r
+ and al,ah\r
+@@MasksSet:\r
+ mov dl,bl ; set BX=Plane Masks, AH=Color\r
+ mov bx,ax\r
+ mov ah,dl\r
+ mov dx,SC_INDEX+1 ;set the Sequence Controller Index to\r
+ mov al,bl\r
+ out dx,al\r
+ mov al,ah\r
+ stosb ; Plot left byte\r
+ dec cx\r
+ js @@Invisible2\r
+ jz @@RightEnd\r
+\r
+\r
+ mov al,0fh ; plot middle bytes\r
+ out dx,al\r
+ mov al,ah\r
+ shr cx,1\r
+ rep stosw\r
+ adc cx,cx\r
+ rep stosb\r
+\r
+\r
+\r
+@@RightEnd:\r
+ mov al,bh ; Plot right byte\r
+ out dx,al\r
+ mov al,ah\r
+ stosb\r
+@@Invisible2:\r
+ ret\r
+_HLineClipR endp\r
+\r
+\r
+;-----------------------------------------------------------------------\r
+; void x_triangle( int X0, int Y0, int X1, int Y1,\r
+; int X2, int Y2, unsigned Color, unsigned PageOffset );\r
+;\r
+;\r
+; Written by S. Dollins\r
+\r
+_x_triangle proc\r
+ARG X0:word,Y0:word,X1:word,Y1:word,X2:word,Y2:word,Color:word,PageOffset:word\r
+LOCAL DX01:word, DY01:word, DX02:word, DY02:word, DX12:word, DY12:word, \\r
+ DP01:word, DP02:word, DP12:word, XA01:word, XA02:word, XA12:word=STK\r
+\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,STK\r
+ push ds es si di ; Save es for polygon routine\r
+\r
+ mov ax,X0\r
+ mov bx,Y0\r
+ mov cx,X1\r
+ mov dx,Y1\r
+\r
+ cmp bx,dx ; Y0,Y1\r
+ jl tri_Y0lY1\r
+ je tri_Y0eY1\r
+ xchg ax,cx ; X0,X1\r
+ xchg bx,dx ; Y0,Y1\r
+tri_Y0lY1:\r
+ cmp dx,Y2 ; Y1,Y2\r
+ jg tri_a\r
+ jmp tri_sorted\r
+tri_a: xchg cx,X2 ; X1,X2\r
+ xchg dx,Y2 ; Y1,Y2\r
+ cmp bx,dx ; Y0,Y1\r
+ jge tri_b\r
+ jmp tri_sorted\r
+tri_b: je tri_bot\r
+ xchg ax,cx ; X0,X1\r
+ xchg bx,dx ; Y0,Y1\r
+ jmp tri_sorted\r
+tri_Y0eY1:\r
+ cmp bx,Y2 ; Y0,Y2\r
+ jl tri_bot\r
+ jg tri_c\r
+ jmp tri_done\r
+tri_c: xchg ax,X2 ; X0,X2\r
+ xchg bx,Y2 ; Y0,Y2\r
+ jmp tri_sorted\r
+\r
+tri_bot:\r
+ cmp ax,cx ; X0,X1\r
+ jl tri_bot_sorted\r
+ jg tri_bot_a\r
+ jmp tri_done\r
+tri_bot_a:\r
+ xchg ax,cx ; X0,X1\r
+tri_bot_sorted:\r
+ cmp bx,[_BottomClip]\r
+ jle tri_bot_y0ok\r
+ jmp tri_done\r
+tri_bot_y0ok:\r
+ mov si,Y2\r
+ cmp si,[_TopClip]\r
+ jge tri_bot_y2ok\r
+ jmp tri_done\r
+tri_bot_y2ok:\r
+ mov X0,ax\r
+ mov Y0,bx\r
+ mov X1,cx\r
+ mov Y1,dx\r
+\r
+ mov bx,Y2 ; bx <- Y2\r
+ sub bx,Y0 ; bx <- Y2 - Y0\r
+ mov DY02,bx ; DY02 <- Y2 - Y0\r
+ mov ax,X2 ; ax <- X2\r
+ sub ax,X0 ; ax <- X2 - X0\r
+ mov DX02,ax ; DX02 <- X2 - X0\r
+ mov cx,ax ; cx <- DX02\r
+ cwd ; dx:ax <- DX02\r
+ idiv bx ; ax <- DX02 / DY02\r
+ cmp cx,0\r
+ jge short tri_bot02\r
+ dec ax ; ax <- DX02 / DY02 - 1\r
+tri_bot02:\r
+ mov XA02,ax ; XA02 <- DX02 / DY02\r
+ imul bx ; ax <- XA02 * DY02\r
+ sub cx,ax ; cx <- DX02 - XA02 * DY02\r
+ mov DP02,cx ; DP02 <- DX02 - XA02 * DY02\r
+\r
+ mov bx,Y2 ; bx <- Y2\r
+ sub bx,Y1 ; bx <- Y2 - Y1\r
+ mov DY12,bx ; DY02 <- Y2 - Y1\r
+ mov ax,X2 ; ax <- X2\r
+ sub ax,X1 ; ax <- X2 - X1\r
+ mov DX12,ax ; DX12 <- X2 - X1\r
+ mov cx,ax ; cx <- DX12\r
+ cwd ; dx:ax <- DX12\r
+ idiv bx ; ax <- DX12 / DY12\r
+ cmp cx,0\r
+ jge short tri_bot12\r
+ dec ax ; ax <- DX12 / DY12 - 1\r
+tri_bot12:\r
+ mov XA12,ax ; XA12 <- DX12 / DY12\r
+ imul bx ; ax <- XA12 * DY12\r
+ sub cx,ax ; cx <- DX12 - XA12 * DY12\r
+ mov DP12,cx ; DP12 <- DX12 - XA12 * DY12\r
+\r
+ mov ax,0 ; PL <- 0\r
+ mov bx,0 ; PS <- 0\r
+ mov cx,Y0 ; Y <- Y0\r
+ mov si,X0\r
+ mov di,X1\r
+ dec di\r
+tri_bot_loop:\r
+ inc cx ; Y\r
+\r
+ add ax,DP02 ; PL,DP02\r
+ jle short tri_bot_shortl\r
+ sub ax,DY02 ; PL,DY02\r
+ inc si ; XL\r
+tri_bot_shortl:\r
+ add si,XA02 ; XL,XA02\r
+\r
+ add bx,DP12 ; PS,DP12\r
+ jle short tri_bot_shortr\r
+ sub bx,DY12 ; PS,DY12\r
+ inc di ; XS\r
+tri_bot_shortr:\r
+ add di,XA12 ; XS,XA12\r
+\r
+ push di ; XS\r
+ push si ; XL\r
+ cmp cx,Y2 ; Y,Y2\r
+ jl short tri_bot_loop\r
+\r
+ jmp tri_draw_lines\r
+\r
+\r
+tri_sorted:\r
+ cmp bx,[_BottomClip]\r
+ jle tri_y0ok\r
+ jmp tri_done\r
+tri_y0ok:\r
+ mov si,Y2\r
+ cmp si,[_TopClip]\r
+ jge tri_y2ok\r
+ jmp tri_done\r
+tri_y2ok:\r
+ mov X0,ax\r
+ mov Y0,bx\r
+ mov X1,cx\r
+ mov Y1,dx\r
+\r
+ mov bx,dx ; bx <- Y1\r
+ sub bx,Y0 ; bx <- Y1 - Y0\r
+ mov DY01,bx ; DY01 <- Y1 - Y0\r
+ mov ax,X1 ; ax <- X1\r
+ sub ax,X0 ; ax <- X1 - X0\r
+ mov DX01,ax ; DX01 <- X1 - X0\r
+ mov cx,ax ; cx <- DX01\r
+ cwd ; dx:ax <- DX01\r
+ idiv bx ; ax <- DX01 / DY01\r
+ cmp cx,0 ; DX01 ? 0\r
+ jge short tri_psl01\r
+ dec ax ; ax <- DX01 / DY01 - 1\r
+tri_psl01:\r
+ mov XA01,ax ; XA01 <- DX01 / DY01\r
+ imul bx ; ax <- XA01 * DY01\r
+ sub cx,ax ; cx <- DX01 - XA01 * DY01\r
+ mov DP01,cx ; DP01 <- DX01 - XA01 * DY01\r
+\r
+ mov bx,Y2 ; bx <- Y2\r
+ sub bx,Y0 ; bx <- Y2 - Y0\r
+ mov DY02,bx ; DY02 <- Y2 - Y0\r
+ mov ax,X2 ; ax <- X2\r
+ sub ax,X0 ; ax <- X2 - X0\r
+ mov DX02,ax ; DX02 <- X2 - X0\r
+ mov cx,ax ; cx <- DX02\r
+ cwd ; dx:ax <- DX02\r
+ idiv bx ; ax <- DX02 / DY02\r
+ cmp cx,0\r
+ jge short tri_psl02\r
+ dec ax ; ax <- DX02 / DY02 - 1\r
+tri_psl02:\r
+ mov XA02,ax ; XA02 <- DX02 / DY02\r
+ imul bx ; ax <- XA02 * DY02\r
+ sub cx,ax ; cx <- DX02 - XA02 * DY02\r
+ mov DP02,cx ; DP02 <- DX02 - XA02 * DY02\r
+\r
+ mov bx,Y2 ; bx <- Y2\r
+ sub bx,Y1 ; bx <- Y2 - Y1\r
+ jle short tri_const_computed\r
+ mov DY12,bx ; DY12 <- Y2 - Y1\r
+ mov ax,X2 ; ax <- X2\r
+ sub ax,X1 ; ax <- X2 - X1\r
+ mov DX12,ax ; DX12 <- X2 - X1\r
+ mov cx,ax ; cx <- DX12\r
+ cwd ; dx:ax <- DX12\r
+ idiv bx ; ax <- DX12 / DY12\r
+ cmp cx,0\r
+ jge short tri_psl12\r
+ dec ax ; ax <- DX12 / DY12 - 1\r
+tri_psl12:\r
+ mov XA12,ax ; XA12 <- DX12 / DY12\r
+ imul bx ; ax <- XA12 * DY12\r
+ sub cx,ax ; cx <- DX12 - XA12 * DY12\r
+ mov DP12,cx ; DP12 <- DX12 - XA12 * DY12\r
+\r
+tri_const_computed:\r
+ mov ax,DX01\r
+ imul word ptr DY02\r
+ mov bx,ax\r
+ mov cx,dx ; DX01 * DY02 in cx:bx\r
+\r
+ mov ax,DX02\r
+ imul word ptr DY01 ; DX02 * DY01 in dx:ax\r
+ cmp cx,dx\r
+ jg tri_pt1rt\r
+ jl tri_pt1lt\r
+ cmp bx,ax\r
+ ja tri_pt1rt\r
+ jb tri_pt1lt\r
+ jmp tri_done\r
+\r
+;------------------------------------\r
+; Short sides are on the left\r
+;\r
+tri_pt1lt:\r
+ mov ax,0 ; PL <- 0\r
+ mov bx,0 ; PS <- 0\r
+ mov cx,Y0 ; Y <- Y0\r
+ mov si,X0\r
+ mov di,si\r
+ dec si\r
+tri_lt_loop:\r
+ inc cx ; Y\r
+\r
+ add ax,DP02 ; PL,DP02\r
+ jle short tri_lt_shortl\r
+ sub ax,DY02 ; PL,DY02\r
+ inc si ; XL\r
+tri_lt_shortl:\r
+ add si,XA02 ; XL,XA02\r
+\r
+ add bx,DP01 ; PS,DP01\r
+ jle short tri_lt_shortr\r
+ sub bx,DY01 ; PS,DY01\r
+ inc di ; XS\r
+tri_lt_shortr:\r
+ add di,XA01 ; XS,XA01\r
+\r
+ push si ; XL\r
+ push di ; XS\r
+ cmp cx,Y1 ; Y,Y1\r
+ jl short tri_lt_loop\r
+\r
+ jmp short tri_lb_start\r
+tri_lb_loop:\r
+ inc cx ; Y\r
+\r
+ add ax,DP02 ; PL,DP02\r
+ jle short tri_lb_shortl\r
+ sub ax,DY02 ; PL,DY02\r
+ inc si ; XL\r
+tri_lb_shortl:\r
+ add si,XA02 ; XL,XA02\r
+\r
+ add bx,DP12 ; PS,DP12\r
+ jle short tri_lb_shortr\r
+ sub bx,DY12 ; PS,DY12\r
+ inc di ; XS\r
+tri_lb_shortr:\r
+ add di,XA12 ; XS,XA12\r
+\r
+ push si ; XL\r
+ push di ; XS\r
+tri_lb_start:\r
+ cmp cx,Y2 ; Y,Y2\r
+ jl tri_lb_loop\r
+ jmp short tri_draw_lines\r
+\r
+;------------------------------------\r
+; short sides are on the right\r
+;\r
+tri_pt1rt:\r
+ mov ax,0 ; PL <- 0\r
+ mov bx,0 ; PS <- 0\r
+ mov cx,Y0 ; Y <- Y0\r
+ mov si,X0\r
+ mov di,si\r
+ dec di\r
+tri_rt_loop:\r
+ inc cx ; Y\r
+\r
+ add ax,DP02 ; PL,DP02\r
+ jle short tri_rt_shortl\r
+ sub ax,DY02 ; PL,DY02\r
+ inc si ; XL\r
+tri_rt_shortl:\r
+ add si,XA02 ; XL,XA02\r
+\r
+ add bx,DP01 ; PS,DP01\r
+ jle short tri_rt_shortr\r
+ sub bx,DY01 ; PS,DY01\r
+ inc di ; XS\r
+tri_rt_shortr:\r
+ add di,XA01 ; XS,XA01\r
+\r
+ push di ; XS\r
+ push si ; XL\r
+ cmp cx,Y1 ; Y,Y1\r
+ jl short tri_rt_loop\r
+\r
+ jmp short tri_rb_start\r
+tri_rb_loop:\r
+ inc cx ; Y\r
+\r
+ add ax,DP02 ; PL,DP02\r
+ jle short tri_rb_shortl\r
+ sub ax,DY02 ; PL,DY02\r
+ inc si ; XL\r
+tri_rb_shortl:\r
+ add si,XA02 ; XL,XA02\r
+\r
+ add bx,DP12 ; PS,DP12\r
+ jle short tri_rb_shorts\r
+ sub bx,DY12 ; PS,DY12\r
+ inc di ; XS\r
+tri_rb_shorts:\r
+ add di,XA12 ; XS,XA12\r
+\r
+ push di ; XS\r
+ push si ; XL\r
+tri_rb_start:\r
+ cmp cx,Y2 ; Y,Y2\r
+ jl short tri_rb_loop\r
+\r
+;------------------------------------\r
+; Draw the horizontal lines\r
+;\r
+\r
+\r
+tri_draw_lines:\r
+\r
+ mov cx,SCREEN_SEG ;point ES to video segment\r
+ mov es,cx\r
+ mov dx,SC_INDEX ;set the Sequence Controller Index to\r
+ mov al,MAP_MASK ; point to the Map Mask register\r
+ out dx,al\r
+\r
+\r
+line_loop:\r
+ pop ax\r
+ pop dx\r
+ cmp ax,dx\r
+ jg tri_draw_next\r
+ mov bx,Color\r
+ mov cx,Y2\r
+ add dx,2\r
+ mov di,PageOffset\r
+ call _HLineClipR\r
+tri_draw_next:\r
+ dec word ptr Y2\r
+ dec word ptr DY02\r
+ jnz line_loop\r
+\r
+tri_done:\r
+ pop di si es ds\r
+ mov sp,bp\r
+ pop bp\r
+ ret\r
+_x_triangle endp\r
+\r
+;-----------------------------------------------------------------------\r
+; void x_polygon( VERTEX vertices[], int num_vertices,unsigned Color,\r
+; unsigned PageOffset );\r
+;\r
+; Where VERTEX is defined as:\r
+;\r
+; typedef struct {\r
+; int X;\r
+; int Y;\r
+; } far VERTEX;\r
+;\r
+;\r
+; Written by T. Gouthas\r
+;\r
+;\r
+;\r
+; Note: This is just a quick hack of a generalized polygon routine.\r
+; The way it works is by splitting up polygons into triangles and\r
+; drawing each individual triangle.\r
+;\r
+; Obviously this is not as fast as it could be, but for polygons of\r
+; 4 vertices it should perform quite respectably.\r
+;\r
+; Warning: Only works for convex polygons (convex polygons are such\r
+; that if you draw a line from any two vertices, every point on that\r
+; line will be within the polygon)\r
+;\r
+;\r
+\r
+_x_polygon proc\r
+ ARG vertices:dword,numvertices:word,Color:word,PageOffset:word\r
+ LOCAL x0:word,y0:word,tri_count:word=STK\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,STK\r
+ push di si\r
+\r
+ mov cx,numvertices\r
+ cmp cx,3\r
+ jl @@Done\r
+\r
+ sub cx,3\r
+ mov tri_count,cx ; Number of triangles to draw\r
+ les di,vertices ; ES:DI -> Vertices\r
+\r
+ mov ax,es:[di] ; Save first vertex\r
+ mov x0,ax\r
+ mov ax,es:[di+2]\r
+ mov y0,ax\r
+\r
+ ; Set up permanent parameter stack frame for\r
+ ; triangle parameters\r
+\r
+ mov ax,PageOffset\r
+ push ax\r
+ mov ax,Color\r
+ push ax\r
+\r
+ sub sp,12\r
+ mov si,sp\r
+\r
+@@NextTriangle:\r
+\r
+ add di,4\r
+ mov ax,es:[di] ; Vertex 2\r
+ mov ss:[si],ax\r
+ mov ax,es:[di+2]\r
+ mov ss:[si+2],ax\r
+\r
+ mov ax,es:[di+4] ; Vertex 1\r
+ mov ss:[si+4],ax\r
+ mov ax,es:[di+6]\r
+ mov ss:[si+6],ax\r
+\r
+ mov ax,x0 ; Vertex 0: The first vertex is\r
+ mov ss:[si+8],ax ; part of every triangle\r
+ mov ax,y0\r
+ mov ss:[si+10],ax\r
+\r
+ call _x_triangle\r
+ dec tri_count\r
+ jns @@NextTriangle\r
+\r
+ add sp,16 ; Remove triangle stack frame\r
+\r
+@@Done:\r
+ pop si di\r
+ mov sp,bp\r
+ pop bp\r
+ ret\r
+_x_polygon endp\r
+ end
\ No newline at end of file
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XPOLYGON - header file\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;----------------------------------------------------------------------*/\r
+\r
+#ifndef _XPOLYGON_H_\r
+#define _XPOLYGON_H_\r
+\r
+\r
+typedef struct {\r
+ int X;\r
+ int Y;\r
+} far VERTEX;\r
+\r
+/* FUNCTIONS =========================================================== */\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+void x_triangle( /* Draw a triangle */\r
+ int x0,\r
+ int y0,\r
+ int x1,\r
+ int y1,\r
+ int x2,\r
+ int y2,\r
+ WORD color,\r
+ WORD PageBase);\r
+\r
+void x_polygon( /* Draw a convex polygon */\r
+ VERTEX *vertices,\r
+ int num_vertices,\r
+ WORD color,\r
+ WORD PageBase);\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XPOLYGON - Include file\r
+;\r
+; XPOLYGON.ASM export functions\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+ global _x_triangle :proc\r
+ global _x_polygon :proc\r
--- /dev/null
+#include <stdarg.h>\r
+#include <string.h>\r
+#include "xlib.h"\r
+#include "xrect.h"\r
+#include "xtext.h"\r
+\r
+\r
+extern unsigned char CharWidth;\r
+extern unsigned char CharHeight;\r
+\r
+void x_printf(WORD x, WORD y,WORD ScrnOffs,WORD color,char *ln,...){\r
+ char dlin[100],*dl=dlin;\r
+ char ch;\r
+ va_list ap;\r
+\r
+ va_start(ap,ln);\r
+ vsprintf(dlin,ln,ap);\r
+ va_end(ap);\r
+\r
+ while(*dl){\r
+ x+=x_char_put(*dl++,x,y,ScrnOffs,color);\r
+ }\r
+\r
+}\r
+\r
+void x_bgprintf(WORD x, WORD y,WORD ScrnOffs,WORD fgcolor,\r
+ WORD bgcolor, char *ln,...){\r
+ char dlin[100],*dl=dlin;\r
+ char ch;\r
+ va_list ap;\r
+\r
+ va_start(ap,ln);\r
+ vsprintf(dlin,ln,ap);\r
+ va_end(ap);\r
+\r
+ while(*dl){\r
+ x_rect_fill(x,y,x+x_get_char_width(*dl),y+CharHeight,ScrnOffs,bgcolor);\r
+ x+=x_char_put(*dl++,x,y,ScrnOffs,fgcolor);\r
+ }\r
+\r
+}\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XRECT\r
+;\r
+; Rectangle functions all MODE X 256 Color resolutions\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+include xlib.inc\r
+include xrect.inc\r
+\r
+\r
+ .data\r
+; Plane masks for clipping left and right edges of rectangle.\r
+ LeftClipPlaneMask db 00fh,00eh,00ch,008h\r
+ RightClipPlaneMask db 00fh,001h,003h,007h\r
+ .code\r
+\r
+;---------------------------------------------------------------------------\r
+; Mode X (320x240, 256 colors) rectangle solid colour fill routine.\r
+;\r
+; Based on code originally published in DDJ Mag by M. Abrash\r
+;\r
+; with TASM 2. C near-callable as:\r
+;\r
+; void x_rect_fill_clipped(int StartX, int StartY, int EndX, int EndY,\r
+; unsigned int PageBase, unsigne int color);\r
+;\r
+;\r
+\r
+\r
+_x_rect_fill_clipped proc\r
+ARG StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Color:word\r
+ push bp ;preserve caller's stack frame\r
+ mov bp,sp ;point to local stack frame\r
+ push si ;preserve caller's register variables\r
+ push di\r
+\r
+ mov dx,[_TopClip] ; Compare u.l. Y coord with Top\r
+ mov cx,[_BottomClip]\r
+ mov ax,[StartY]\r
+ mov bx,[EndY]\r
+ cmp dx,ax\r
+ jle @@CheckBottomClip\r
+ cmp dx,bx\r
+ jg @@NotVisible\r
+ mov [StartY],dx\r
+\r
+@@CheckBottomClip:\r
+ cmp cx,bx\r
+ jg @@CheckLeftClip\r
+ cmp cx,ax\r
+ jl @@NotVisible\r
+ mov [EndY],cx\r
+\r
+@@CheckLeftClip:\r
+ mov dx,[_LeftClip] ; Compare u.l. Y coord with Top\r
+ mov cx,[_RightClip]\r
+ mov ax,[StartX]\r
+ mov bx,[EndX]\r
+ sal dx,2\r
+ sal cx,2\r
+ cmp dx,ax\r
+ jle @@CheckRightClip\r
+ cmp dx,bx\r
+ jg @@NotVisible\r
+ mov [StartX],dx\r
+\r
+@@CheckRightClip:\r
+ cmp cx,bx\r
+ jg RFClipDone\r
+ cmp cx,ax\r
+ jl @@NotVisible\r
+ mov [EndX],cx\r
+ jmp RFClipDone\r
+\r
+@@NotVisible:\r
+ mov ax,1\r
+ pop di ; restore registers\r
+ pop si\r
+ pop bp\r
+ ret\r
+_x_rect_fill_clipped endp\r
+\r
+\r
+\r
+;---------------------------------------------------------------------------\r
+; Mode X (320x240, 256 colors) rectangle solid colour fill routine.\r
+;\r
+; Based on code originally published in DDJ Mag by M. Abrash\r
+;\r
+; with TASM 2. C near-callable as:\r
+;\r
+; void x_rect_fill(int StartX, int StartY, int EndX, int EndY,\r
+; unsigned int PageBase, unsigne int color);\r
+;\r
+;\r
+\r
+\r
+_x_rect_fill proc\r
+ARG StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Color:word\r
+ push bp ;preserve caller's stack frame\r
+ mov bp,sp ;point to local stack frame\r
+ push si ;preserve caller's register variables\r
+ push di\r
+\r
+RFClipDone:\r
+ cld\r
+ mov ax,[_ScrnLogicalByteWidth]\r
+ mul [StartY] ;offset in page of top rectangle scan line\r
+ mov di,[StartX]\r
+ sar di,2 ;X/4 = offset of first rectangle pixel in scan\r
+ add di,ax ;offset of first rectangle pixel in page\r
+ add di,[PageBase] ;offset of first rectangle pixel in\r
+ ; display memory\r
+ mov ax,SCREEN_SEG ;point ES:DI to the first rectangle\r
+ mov es,ax ; pixel's address\r
+ mov dx,SC_INDEX ;set the Sequence Controller Index to\r
+ mov al,MAP_MASK ; point to the Map Mask register\r
+ out dx,al\r
+ inc dx ;point DX to the SC Data register\r
+ mov si,[StartX]\r
+ and si,0003h ;look up left edge plane mask\r
+ mov bh,LeftClipPlaneMask[si] ; to clip & put in BH\r
+ mov si,[EndX]\r
+ and si,0003h ;look up right edge plane\r
+ mov bl,RightClipPlaneMask[si] ; mask to clip & put in BL\r
+\r
+ mov cx,[EndX] ;calculate # of addresses across rect\r
+ mov si,[StartX]\r
+ cmp cx,si\r
+ jle @@FillDone ;skip if 0 or negative width\r
+ dec cx\r
+ and si,not 011b\r
+ sub cx,si\r
+ sar cx,2 ;# of addresses across rectangle to fill - 1\r
+ jnz @@MasksSet ;there's more than one byte to draw\r
+ and bh,bl ;there's only one byte, so combine the left\r
+ ; and right edge clip masks\r
+@@MasksSet:\r
+ mov si,[EndY]\r
+ sub si,[StartY] ;BX = height of rectangle\r
+ jle @@FillDone ;skip if 0 or negative height\r
+ mov ah,byte ptr [Color] ;color with which to fill\r
+ mov bp,[_ScrnLogicalByteWidth] ;stack frame isn't needed any more\r
+ sub bp,cx ;distance from end of one scan line to start\r
+ dec bp ; of next\r
+@@FillRowsLoop:\r
+ push cx ;remember width in addresses - 1\r
+ mov al,bh ;put left-edge clip mask in AL\r
+ out dx,al ;set the left-edge plane (clip) mask\r
+ mov al,ah ;put color in AL\r
+ stosb ;draw the left edge\r
+ dec cx ;count off left edge byte\r
+ js @@FillLoopBottom ;that's the only byte\r
+ jz @@DoRightEdge ;there are only two bytes\r
+ mov al,00fh ;middle addresses drawn 4 pixels at a pop\r
+ out dx,al ;set the middle pixel mask to no clip\r
+ mov al,ah ;put color in AL\r
+ rep stosb ;draw middle addresses four pixels apiece\r
+@@DoRightEdge:\r
+ mov al,bl ;put right-edge clip mask in AL\r
+ out dx,al ;set the right-edge plane (clip) mask\r
+ mov al,ah ;put color in AL\r
+ stosb ;draw the right edge\r
+@@FillLoopBottom:\r
+ add di,bp ;point to start of the next scan line of\r
+ ; the rectangle\r
+ pop cx ;retrieve width in addresses - 1\r
+ dec si ;count down scan lines\r
+ jnz @@FillRowsLoop\r
+@@FillDone:\r
+ pop di ;restore caller's register variables\r
+ pop si\r
+ pop bp ;restore caller's stack frame\r
+ ret\r
+_x_rect_fill endp\r
+\r
+\r
+\r
+;---------------------------------------------------------------------------\r
+; Mode X (320x240, 256 colors) rectangle 4x4 pattern fill routine.\r
+; Upper left corner of pattern is always aligned to a multiple-of-4\r
+; row and column. Works on all VGAs. Uses approach of copying the\r
+; pattern to off-screen display memory, then loading the latches with\r
+; the pattern for each scan line and filling each scan line four\r
+; pixels at a time. Fills up to but not including the column at EndX\r
+; and the row at EndY. No clipping is performed. All ASM code tested\r
+;\r
+;\r
+; Based on code originally published in DDJ Mag by M. Abrash\r
+;\r
+;\r
+; C near-callable as:\r
+;\r
+; void x_rect_pattern_clipped(int StartX, int StartY, int EndX, int EndY,\r
+; unsigned int PageBase, char far * Pattern);\r
+;\r
+;\r
+\r
+_x_rect_pattern_clipped proc\r
+ARG StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Pattern:dword\r
+LOCAL NextScanOffset:word,RectAddrWidth:word,Height:word=LocalStk\r
+ push bp ;preserve caller's stack frame\r
+ mov bp,sp ;point to local stack frame\r
+ sub sp,LocalStk ;allocate space for local vars\r
+ push si ;preserve caller's register variables\r
+ push di\r
+ push ds\r
+\r
+ mov dx,[_TopClip] ; Compare u.l. Y coord with Top\r
+ mov cx,[_BottomClip]\r
+ mov ax,[StartY]\r
+ mov bx,[EndY]\r
+ cmp dx,ax\r
+ jle @@CheckBottomClip\r
+ cmp dx,bx\r
+ jg @@NotVisible\r
+ mov [StartY],dx\r
+\r
+@@CheckBottomClip:\r
+ cmp cx,bx\r
+ jg @@CheckLeftClip\r
+ cmp cx,ax\r
+ jl @@NotVisible\r
+ mov [EndY],cx\r
+\r
+@@CheckLeftClip:\r
+ mov dx,[_LeftClip] ; Compare u.l. Y coord with Top\r
+ mov cx,[_RightClip]\r
+ mov ax,[StartX]\r
+ mov bx,[EndX]\r
+ sal dx,2\r
+ sal cx,2\r
+ cmp dx,ax\r
+ jle @@CheckRightClip\r
+ cmp dx,bx\r
+ jg @@NotVisible\r
+ mov [StartX],dx\r
+\r
+@@CheckRightClip:\r
+ cmp cx,bx\r
+ jg RPClipDone\r
+ cmp cx,ax\r
+ jl @@NotVisible\r
+ mov [EndX],cx\r
+ jmp RPClipDone\r
+\r
+@@NotVisible:\r
+ mov ax,1\r
+ pop ds\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp\r
+ pop bp\r
+ ret\r
+\r
+_x_rect_pattern_clipped endp\r
+\r
+;---------------------------------------------------------------------------\r
+; Mode X (320x240, 256 colors) rectangle 4x4 pattern fill routine.\r
+; Upper left corner of pattern is always aligned to a multiple-of-4\r
+; row and column. Works on all VGAs. Uses approach of copying the\r
+; pattern to off-screen display memory, then loading the latches with\r
+; the pattern for each scan line and filling each scan line four\r
+; pixels at a time. Fills up to but not including the column at EndX\r
+; and the row at EndY. No clipping is performed. All ASM code tested\r
+;\r
+;\r
+; Based on code originally published in DDJ Mag by M. Abrash\r
+;\r
+;\r
+; C near-callable as:\r
+;\r
+; void x_rect_pattern(int StartX, int StartY, int EndX, int EndY,\r
+; unsigned int PageBase, char far * Pattern);\r
+\r
+\r
+\r
+_x_rect_pattern proc\r
+ARG StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Pattern:dword\r
+LOCAL NextScanOffset:word,RectAddrWidth:word,Height:word=LocalStk\r
+ push bp ;preserve caller's stack frame\r
+ mov bp,sp ;point to local stack frame\r
+ sub sp,LocalStk ;allocate space for local vars\r
+ push si ;preserve caller's register variables\r
+ push di\r
+ push ds\r
+\r
+RPClipDone:\r
+ cld\r
+ mov ax,SCREEN_SEG ;point ES to display memory\r
+ mov es,ax\r
+ ;copy pattern to display memory buffer\r
+ lds si,dword ptr [Pattern] ;point to pattern to fill with\r
+ mov di,PATTERN_BUFFER ;point ES:DI to pattern buffer\r
+ mov dx,SC_INDEX ;point Sequence Controller Index to\r
+ mov al,MAP_MASK ; Map Mask\r
+ out dx,al\r
+ inc dx ;point to SC Data register\r
+ mov cx,4 ;4 pixel quadruplets in pattern\r
+@@DownloadPatternLoop:\r
+ mov al,1 ;\r
+ out dx,al ;select plane 0 for writes\r
+ movsb ;copy over next plane 0 pattern pixel\r
+ dec di ;stay at same address for next plane\r
+ mov al,2 ;\r
+ out dx,al ;select plane 1 for writes\r
+ movsb ;copy over next plane 1 pattern pixel\r
+ dec di ;stay at same address for next plane\r
+ mov al,4 ;\r
+ out dx,al ;select plane 2 for writes\r
+ movsb ;copy over next plane 2 pattern pixel\r
+ dec di ;stay at same address for next plane\r
+ mov al,8 ;\r
+ out dx,al ;select plane 3 for writes\r
+ movsb ;copy over next plane 3 pattern pixel\r
+ ; and advance address\r
+ loop @@DownloadPatternLoop\r
+ pop ds\r
+\r
+ mov dx,GC_INDEX ;set the bit mask to select all bits\r
+ mov ax,00000h+BIT_MASK ; from the latches and none from\r
+ out dx,ax ; the CPU, so that we can write the\r
+ ; latch contents directly to memory\r
+ mov ax,[StartY] ;top rectangle scan line\r
+ mov si,ax\r
+ and si,011b ;top rect scan line modulo 4\r
+ add si,PATTERN_BUFFER ;point to pattern scan line that\r
+ ; maps to top line of rect to draw\r
+ mov dx,[_ScrnLogicalByteWidth]\r
+ mul dx ;offset in page of top rect scan line\r
+ mov di,[StartX]\r
+ mov bx,di\r
+ sar di,2 ;X/4 = offset of first rectangle pixel in scan\r
+ add di,ax ;offset of first rectangle pixel in page\r
+ add di,[PageBase] ;offset of first rectangle pixel in\r
+ ; display memory\r
+ and bx,0003h ;look up left edge plane mask\r
+ mov ah,LeftClipPlaneMask[bx] ; to clip\r
+ mov bx,[EndX]\r
+ and bx,0003h ;look up right edge plane\r
+ mov al,RightClipPlaneMask[bx] ; mask to clip\r
+ mov bx,ax ;put the masks in BX\r
+\r
+ mov cx,[EndX] ;calculate # of addresses across rect\r
+ mov ax,[StartX]\r
+ cmp cx,ax\r
+ jle @@FillDone ;skip if 0 or negative width\r
+ dec cx\r
+ and ax,not 011b\r
+ sub cx,ax\r
+ sar cx,2 ;# of addresses across rectangle to fill - 1\r
+ jnz @@MasksSet ;there's more than one pixel to draw\r
+ and bh,bl ;there's only one pixel, so combine the left\r
+ ; and right edge clip masks\r
+@@MasksSet:\r
+ mov ax,[EndY]\r
+ sub ax,[StartY] ;AX = height of rectangle\r
+ jle @@FillDone ;skip if 0 or negative height\r
+ mov [Height],ax\r
+ mov ax,[_ScrnLogicalByteWidth]\r
+ sub ax,cx ;distance from end of one scan line to start\r
+ dec ax ; of next\r
+ mov [NextScanOffset],ax\r
+ mov [RectAddrWidth],cx ;remember width in addresses - 1\r
+ mov dx,SC_INDEX+1 ;point to Sequence Controller Data reg\r
+ ; (SC Index still points to Map Mask)\r
+@@FillRowsLoop:\r
+ mov cx,[RectAddrWidth] ;width across - 1\r
+ mov al,es:[si] ;read display memory to latch this scan\r
+ ; line's pattern\r
+ inc si ;point to the next pattern scan line, wrapping\r
+ jnz short @@NoWrap ; back to the start of the pattern if\r
+ sub si,4 ; we've run off the end\r
+@@NoWrap:\r
+ mov al,bh ;put left-edge clip mask in AL\r
+ out dx,al ;set the left-edge plane (clip) mask\r
+ stosb ;draw the left edge (pixels come from latches;\r
+ ; value written by CPU doesn't matter)\r
+ dec cx ;count off left edge address\r
+ js @@FillLoopBottom ;that's the only address\r
+ jz @@DoRightEdge ;there are only two addresses\r
+ mov al,00fh ;middle addresses drawn 4 pixels at a pop\r
+ out dx,al ;set middle pixel mask to no clip\r
+ rep stosb ;draw middle addresses four pixels apiece\r
+ ; (from latches; value written doesn't matter)\r
+@@DoRightEdge:\r
+ mov al,bl ;put right-edge clip mask in AL\r
+ out dx,al ;set the right-edge plane (clip) mask\r
+ stosb ;draw the right edge (from latches; value\r
+ ; written doesn't matter)\r
+@@FillLoopBottom:\r
+ add di,[NextScanOffset] ;point to the start of the next scan\r
+ ; line of the rectangle\r
+ dec word ptr [Height] ;count down scan lines\r
+ jnz @@FillRowsLoop\r
+@@FillDone:\r
+ mov dx,GC_INDEX+1 ;restore the bit mask to its default,\r
+ mov al,0ffh ; which selects all bits from the CPU\r
+ out dx,al ; and none from the latches (the GC\r
+ ; Index still points to Bit Mask)\r
+\r
+ pop di ;restore caller's register variables\r
+ pop si\r
+ mov sp,bp ;discard storage for local variables\r
+ pop bp ;restore caller's stack frame\r
+ ret\r
+_x_rect_pattern endp\r
+\r
+;-----------------------------------------------------------------------\r
+; Mode X (320x240, 256 colors) display memory to display memory copy\r
+; routine. Left edge of source rectangle modulo 4 must equal left edge\r
+; of destination rectangle modulo 4. Works on all VGAs. Uses approach\r
+; of reading 4 pixels at a time from the source into the latches, then\r
+; writing the latches to the destination. Copies up to but not\r
+; including the column at SrcEndX and the row at SrcEndY. No\r
+; clipping is performed. Results are not guaranteed if the source and\r
+; destination overlap.\r
+;\r
+;\r
+; Based on code originally published in DDJ Mag by M. Abrash\r
+;\r
+;C near-callable as:\r
+; void x_cp_vid_rect(int SrcStartX, int SrcStartY,\r
+; int SrcEndX, int SrcEndY, int DestStartX,\r
+; int DestStartY, unsigned int SrcPageBase,\r
+; unsigned int DestPageBase, int SrcBitmapWidth,\r
+; int DestBitmapWidth);\r
+\r
+_x_cp_vid_rect proc\r
+ ARG SrcStartX:word,SrcStartY:word,SrcEndX:word,SrcEndY:word,DestStartX:word,DestStartY:word,SrcPageBase:word,DestPageBase:word,SrcBitmapW:word,DestBitmapW:word\r
+ LOCAL SrcNextOffs:word,DestNextOffs:word,RectAddrW:word,Height:word=LocalStk\r
+ push bp ;preserve caller's stack frame\r
+ mov bp,sp ;point to local stack frame\r
+ sub sp,LocalStk ;allocate space for local vars\r
+ push si ;preserve caller's register variables\r
+ push di\r
+ push ds\r
+\r
+ cld\r
+ mov dx,GC_INDEX ;set the bit mask to select all bits\r
+ mov ax,00000h+BIT_MASK ; from the latches and none from\r
+ out dx,ax ; the CPU, so that we can write the\r
+ ; latch contents directly to memory\r
+ mov ax,SCREEN_SEG ;point ES to display memory\r
+ mov es,ax\r
+ mov ax,[DestBitmapW]\r
+ shr ax,2 ;convert to width in addresses\r
+ mul [DestStartY] ;top dest rect scan line\r
+ mov di,[DestStartX]\r
+ sar di,2 ;X/4 = offset of first dest rect pixel in\r
+ ; scan line\r
+ add di,ax ;offset of first dest rect pixel in page\r
+ add di,[DestPageBase] ;offset of first dest rect pixel\r
+ ; in display memory\r
+ mov ax,[SrcBitmapW]\r
+ sar ax,2 ;convert to width in addresses\r
+ mul [SrcStartY] ;top source rect scan line\r
+ mov si,[SrcStartX]\r
+ mov bx,si\r
+ sar si,2 ;X/4 = offset of first source rect pixel in\r
+ ; scan line\r
+ add si,ax ;offset of first source rect pixel in page\r
+ add si,[SrcPageBase] ;offset of first source rect\r
+ ; pixel in display memory\r
+ and bx,0003h ;look up left edge plane mask\r
+ mov ah,LeftClipPlaneMask[bx] ; to clip\r
+ mov bx,[SrcEndX]\r
+ and bx,0003h ;look up right edge plane\r
+ mov al,RightClipPlaneMask[bx] ; mask to clip\r
+ mov bx,ax ;put the masks in BX\r
+\r
+ mov cx,[SrcEndX] ;calculate # of addresses across\r
+ mov ax,[SrcStartX] ; rect\r
+ cmp cx,ax\r
+ jle @@CopyDone ;skip if 0 or negative width\r
+ dec cx\r
+ and ax,not 011b\r
+ sub cx,ax\r
+ sar cx,2 ;# of addresses across rectangle to copy - 1\r
+ jnz @@MasksSet ;there's more than one address to draw\r
+ and bh,bl ;there's only one address, so combine the left\r
+ ; and right edge clip masks\r
+@@MasksSet:\r
+ mov ax,[SrcEndY]\r
+ sub ax,[SrcStartY] ;AX = height of rectangle\r
+ jle @@CopyDone ;skip if 0 or negative height\r
+ mov [Height],ax\r
+ mov ax,[DestBitmapW]\r
+ sar ax,2 ;convert to width in addresses\r
+ sub ax,cx ;distance from end of one dest scan line\r
+ dec ax ; to start of next\r
+ mov [DestNextOffs],ax\r
+ mov ax,[SrcBitmapW]\r
+ sar ax,2 ;convert to width in addresses\r
+ sub ax,cx ;distance from end of one source scan line\r
+ dec ax ; to start of next\r
+ mov [SrcNextOffs],ax\r
+ mov [RectAddrW],cx ;remember width in addresses - 1\r
+ mov dx,SC_INDEX+1 ;point to Sequence Controller Data reg\r
+ ; (SC Index still points to Map Mask)\r
+ mov ax,es ;DS=ES=screen segment for MOVS\r
+ mov ds,ax\r
+@@CopyRowsLoop:\r
+ mov cx,[RectAddrW] ;width across - 1\r
+ mov al,bh ;put left-edge clip mask in AL\r
+ out dx,al ;set the left-edge plane (clip) mask\r
+ movsb ;copy the left edge (pixels go through\r
+ ; latches)\r
+ dec cx ;count off left edge address\r
+ js @@CopyLoopBottom ;that's the only address\r
+ jz @@DoRightEdge ;there are only two addresses\r
+ mov al,00fh ;middle addresses are drawn 4 pix per go\r
+ out dx,al ;set the middle pixel mask to no clip\r
+ rep movsb ;draw the middle addresses four pix per go\r
+ ; (pixels copied through latches)\r
+@@DoRightEdge:\r
+ mov al,bl ;put right-edge clip mask in AL\r
+ out dx,al ;set the right-edge plane (clip) mask\r
+ movsb ;draw the right edge (pixels copied through\r
+ ; latches)\r
+@@CopyLoopBottom:\r
+ add si,[SrcNextOffs] ;point to the start of\r
+ add di,[DestNextOffs] ; next source & dest lines\r
+ dec word ptr [Height] ;count down scan lines\r
+ jnz @@CopyRowsLoop\r
+@@CopyDone:\r
+ mov dx,GC_INDEX+1 ;restore the bit mask to its default,\r
+ mov al,0ffh ; which selects all bits from the CPU\r
+ out dx,al ; and none from the latches (the GC\r
+ ; Index still points to Bit Mask)\r
+ pop ds\r
+ pop di ;restore caller's register variables\r
+ pop si\r
+ mov sp,bp ;discard storage for local variables\r
+ pop bp ;restore caller's stack frame\r
+ ret\r
+_x_cp_vid_rect endp\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; Copy a rectangular region of a VGA screen, with x coordinates\r
+; rounded to the nearest byte -- source and destination may overlap.\r
+;\r
+; C near-callable as:\r
+;\r
+; void x_shift_rect (WORD SrcLeft, WORD SrcTop,\r
+; WORD SrcRight, WORD SrcBottom,\r
+; WORD DestLeft, WORD DestTop, WORD ScreenOffs);\r
+;\r
+; SrcRight is rounded up, and the left edges are rounded down, to ensure\r
+; that the pixels pointed to by the arguments are inside the rectangle.\r
+;\r
+; The width of the rectangle in bytes (width in pixels / 4)\r
+; cannot exceed 255.\r
+;\r
+; ax, bx, cx, dx, and es eat hot lead.\r
+;\r
+; This function was written by Matthew MacKenzie\r
+; matm@eng.umd.edu\r
+\r
+ align 2\r
+_x_shift_rect proc\r
+ARG SrcLeft,SrcTop,SrcRight,SrcBottom,DestLeft,DestTop,ScreenOffs:word\r
+LOCAL width_temp:word=LocalStk\r
+\r
+ push bp\r
+ mov bp, sp\r
+ sub sp, LocalStk\r
+ push si\r
+ push di\r
+ push ds\r
+\r
+ ; find values for width & x motion\r
+ mov si, SrcLeft ; source x in bytes\r
+ sar si, 2\r
+\r
+ mov di, DestLeft ; destination x in bytes\r
+ sar di, 2\r
+\r
+ mov bx, SrcRight ; right edge of source in bytes, rounded up\r
+ add bx, 3\r
+ sar bx, 2\r
+ sub bx, si\r
+ mov ax, bx ; width - 1\r
+ inc bx ; we'll use this as an offset for moving up or down\r
+ mov width_temp, bx\r
+\r
+ cld ; by default, strings increment\r
+\r
+ cmp si, di\r
+ jge @@MovingLeft\r
+\r
+; we're moving our rectangle right, so we copy it from right to left\r
+ add si, ax ; source & destination will start on the right edge\r
+ add di, ax\r
+ neg bx\r
+ std ; strings decrement\r
+\r
+@@MovingLeft:\r
+\r
+; find values for height & y motion\r
+ mov cx, _ScrnLogicalByteWidth ; bytes to move to advance one line\r
+ mov ax, SrcTop\r
+ mov dx, DestTop ; default destination y\r
+ cmp ax, dx\r
+ jge @@MovingUp\r
+\r
+; we're moving our rectangle down, so we copy it from bottom to top\r
+ mov ax, SrcBottom ; source starts at bottom\r
+ add dx, ax ; add (height - 1) to destination y\r
+ sub dx, SrcTop\r
+ neg cx ; advance up screen rather than down\r
+\r
+@@MovingUp:\r
+ push dx ; save destination y during multiply\r
+ mul _ScrnLogicalByteWidth\r
+ add si, ax ; add y in bytes to source\r
+ pop ax ; restore destination y\r
+ mul _ScrnLogicalByteWidth\r
+ add di, ax ; add y in bytes to destination\r
+\r
+ sub cx, bx ; final value for moving up or down\r
+\r
+ add si, ScreenOffs ; source & destination are on the same screen\r
+ add di, ScreenOffs\r
+\r
+ mov dx, SC_INDEX ; set map mask to all four planes\r
+ mov ax, 00f02h\r
+ out dx, ax\r
+\r
+ mov dx, GC_INDEX ; set bit mask to take data from latches\r
+ mov ax, BIT_MASK ; rather than CPU\r
+ out dx, ax\r
+\r
+ mov ax, SCREEN_SEG ; source and destination are VGA memory\r
+ mov es, ax\r
+ mov ds, ax\r
+\r
+ mov ah, byte ptr width_temp ; width in bytes should fit in 8 bits\r
+\r
+ mov bx, SrcBottom ; height - 1\r
+ sub bx, SrcTop\r
+\r
+ mov dx, cx ; bytes to add to advance one line\r
+\r
+ xor ch, ch ; ready to rock\r
+\r
+@@LineLoop:\r
+ mov cl, ah ; load width in bytes\r
+ rep movsb ; move 4 pixels at a time using latches (YOW!)\r
+\r
+ add si, dx ; advance source by one line\r
+ add di, dx ; advance destination by one line\r
+\r
+ dec bx ; line counter\r
+ jge @@LineLoop ; 0 still means one more to go\r
+\r
+ mov dx, GC_INDEX + 1; set bit mask to take data from CPU (normal setting)\r
+ mov al, 0ffh\r
+ out dx, al\r
+\r
+; kick\r
+ pop ds\r
+ pop di\r
+ pop si\r
+ mov sp, bp\r
+ pop bp\r
+\r
+ ret\r
+_x_shift_rect endp\r
+\r
+ end\r
+\r
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XRECT - header file\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;-----------------------------------------------------------------------*/\r
+\r
+#ifndef _XRECT_H_\r
+#define _XRECT_H_\r
+\r
+\r
+/* FUNCTIONS =========================================================== */\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+ void x_rect_pattern( /* draw a pattern filled rectangle */\r
+ WORD StartX,\r
+ WORD StartY,\r
+ WORD EndX,\r
+ WORD EndY,\r
+ WORD PageBase,\r
+ BYTE far * Pattern);\r
+\r
+ void x_rect_pattern_clipped( /* draw a pattern filled clipped */\r
+ WORD StartX, /* rectangle */\r
+ WORD StartY,\r
+ WORD EndX,\r
+ WORD EndY,\r
+ WORD PageBase,\r
+ BYTE far * Pattern);\r
+\r
+ void x_rect_fill( /* draw a single colour filled rectangle */\r
+ WORD StartX,\r
+ WORD StartY,\r
+ WORD EndX,\r
+ WORD EndY,\r
+ WORD PageBase,\r
+ WORD color);\r
+\r
+ void x_rect_fill_clipped( /* draw a single colour filled */\r
+ WORD StartX, /* and clipped rectangle */\r
+ WORD StartY,\r
+ WORD EndX,\r
+ WORD EndY,\r
+ WORD PageBase,\r
+ WORD color);\r
+\r
+ void x_cp_vid_rect( /* Copy rect region within VRAM */\r
+ WORD SourceStartX,\r
+ WORD SourceStartY,\r
+ WORD SourceEndX,\r
+ WORD SourceEndY,\r
+ WORD DestStartX,\r
+ WORD DestStartY,\r
+ WORD SourcePageBase,\r
+ WORD DestPageBase,\r
+ WORD SourceBitmapWidth,\r
+ WORD DestBitmapWidth);\r
+\r
+/* Copy a rectangular region of a VGA screen, with x coordinates\r
+ rounded to the nearest byte -- source and destination may overlap. */\r
+\r
+ void x_shift_rect (WORD SrcLeft, WORD SrcTop,\r
+ WORD SrcRight, WORD SrcBottom,\r
+ WORD DestLeft, WORD DestTop, WORD ScreenOffs);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XRECT - Include file\r
+;\r
+; XRECT.ASM export functions\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+ global _x_rect_fill :proc\r
+ global _x_rect_fill_clipped :proc\r
+ global _x_rect_pattern :proc\r
+ global _x_rect_pattern_clipped :proc\r
+ global _x_cp_vid_rect :proc\r
+ global _x_shift_rect :proc\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XRLETOOL\r
+;\r
+; Hardware detection module\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+COMMENT $\r
+\r
+Firstly, please note that this module has been built from the ground up\r
+in a rush so although I'm confident all the functions work, I have'nt\r
+extensively checked them. If any should surface please let me know.\r
+\r
+\r
+This module implements a number of functions comprising an RLE encoding\r
+decoding system.\r
+\r
+RLE stands for RUN LENGTH ENCODING. It is a quick simple data compression\r
+scheme which is commonly used for image data compression or compression\r
+of any data. Although not the most efficient system, it is fast, which is\r
+why it is used in image storage systems like PCX. This implementation is\r
+more efficient than the one used in PCX files because it uses 1 bit to\r
+identify a Run Length byte as opposed to two in PCX files, but more on this\r
+later.\r
+\r
+This set of functions can be used to implement your own compressed image\r
+file format or for example compress game mapse for various levels etc.\r
+The uses are limited by your imagination.\r
+\r
+I opted for trading off PCX RLE compatibility for the improved compression\r
+efficiency.\r
+\r
+Here is how the data is un-compressed to give an idea of its structure.\r
+\r
+\r
+STEP 1 read a byte from the RLE compressed source buffer.\r
+\r
+STEP 2 if has its high bit then the lower 7 bits represent the number of\r
+ times the next byte is to be repeated in the destination buffer.\r
+ if the count (lower 7 bits) is zero then\r
+ we have finished decoding goto STEP 5\r
+ else goto STEP 4\r
+\r
+STEP 3 Read a data from the source buffer and copy it directly to the\r
+ destination buffer.\r
+ goto STEP 1\r
+\r
+STEP 4 Read a data from the source buffer and copy it to the destination\r
+ buffer the number of times specified by step 2.\r
+ goto STEP 1\r
+\r
+STEP 5 Stop, decoding done.\r
+\r
+If the byte does not have the high bit set then the byte itself is transfered\r
+ to the destination buffer.\r
+\r
+Data bytes that have the high bit already set and are unique in the input\r
+ stream are represented as a Run Length of 1 (ie 81 which includes high bit)\r
+ followed by the data byte.\r
+\r
+If your original uncompressed data contains few consecutive bytes and most\r
+have high bit set (ie have values > 127) then your so called\r
+compressed data would require up to 2x the space of the uncompressed data,\r
+so be aware that the compression ratio is extremely variable depending on the\r
+type of data being compressed.\r
+\r
+Apologies for this poor attempt at a description, but you can look up\r
+RLE in any good text. Alternatively, any text that describes the PCX file\r
+structure in any depth should have a section on RLE compression.\r
+\r
+\r
+\r
+$\r
+\r
+LOCALS\r
+.286\r
+\r
+include model.inc\r
+include xrletool.inc\r
+\r
+ .data\r
+\r
+_RLE_last_buff_offs dw (0)\r
+RLEbuff db 2 dup (?)\r
+\r
+ .code\r
+\r
+;****************************************************************\r
+;*\r
+;* NAME: x_buff_RLEncode\r
+;*\r
+;*\r
+;* RLE Compresses a source buffer to a destination buffer and returns\r
+;* the size of the resultant compressed data.\r
+;*\r
+;* C PROTOTYPE:\r
+;*\r
+;* extern unsigned int x_buff_RLEncode(char far * source_buff,\r
+;* char far * dest_buff,unsigned int count);\r
+;*\r
+;* source_buff - The buffer to compress\r
+;* dest_buff - The destination buffer\r
+;* count - The size of the source data in bytes\r
+;*\r
+;* WARNING: buffers must be pre allocated.\r
+;*\r
+proc _x_buff_RLEncode\r
+ARG src:dword,dest:dword,count:word\r
+ push bp\r
+ mov bp,sp\r
+ push ds\r
+ push si\r
+ push di\r
+\r
+ lds si,[src]\r
+ les di,[dest]\r
+ mov dx,[count]\r
+\r
+ push di\r
+\r
+ lodsb ; Load first byte into BL\r
+ mov bl,al\r
+ xor cx,cx ; Set number characters packed to zero\r
+ cld ; All moves are forward\r
+\r
+@@RepeatByte:\r
+ lodsb ; Get byte into AL\r
+ inc cx ; Increment compressed byte count\r
+ sub dx,1 ; Decrement bytes left\r
+ je @@LastByte ; Finished when dx = 1\r
+ cmp cx,7fh ; Filled block yet\r
+ jne @@NotFilled ; Nope!\r
+\r
+ or cl,80h ; Set bit to indicate value is repeat count\r
+ mov es:[di],cl ; store it\r
+ inc di\r
+ xor cx,cx ; clear compressed byte count\r
+ mov es:[di],bl ; store byte to be repeated\r
+ inc di\r
+\r
+@@NotFilled:\r
+ cmp al,bl ; hase there been a byte transition ?\r
+ je @@RepeatByte ; No!\r
+\r
+ cmp cl,1 ; do we have a unique byte ?\r
+ jne @@NotUnique ; No\r
+\r
+ test bl,80h ; Can this byte be mistaken for repeat count\r
+ jz @@Unambiguous ; No ! Dont bother with repeat count\r
+\r
+@@NotUnique:\r
+ or cl,80h ; Set bit to indicate value is repeat count\r
+ mov es:[di],cl ; store it\r
+ inc di\r
+@@Unambiguous:\r
+ xor cx,cx ; clear compressed byte count\r
+ mov es:[di],bl ; store byte to be repeated\r
+ inc di\r
+ mov bl,al ; move latest byte into bl\r
+ jmp short @@RepeatByte\r
+\r
+@@LastByte:\r
+ cmp cl,1 ; Is this a unique byte\r
+ jne @@FinalCount ; No\r
+\r
+ test bl,80h ; Can this byte be mistaken for repeat count\r
+ jz @@FinalByte ; No, so dont bother with the repeat count\r
+\r
+@@FinalCount: ; Output the repeat count\r
+ or cl,80h\r
+ mov al,cl\r
+ stosb\r
+\r
+@@FinalByte:\r
+ mov al,bl\r
+ stosb\r
+\r
+ mov al,80h ; store terminating null length\r
+ stosb\r
+\r
+ ; Calculate encoded length of buffer\r
+\r
+ mov ax,di\r
+ pop di\r
+ sub ax,di\r
+\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ ret\r
+_x_buff_RLEncode endp\r
+\r
+\r
+\r
+;****************************************************************\r
+;*\r
+;* NAME: x_buff_RLE_size\r
+;*\r
+;*\r
+;* Returns the size the input data would compress to.\r
+;*\r
+;* C PROTOTYPE:\r
+;*\r
+;* extern unsigned int x_buff_RLE_size(char far * source_buff,\r
+;* unsigned int count);\r
+;*\r
+;* source_buff - The uncompressed data buffer\r
+;* count - The size of the source data in bytes\r
+;*\r
+;*\r
+proc _x_buff_RLE_size\r
+ARG src:dword,count:word\r
+ push bp\r
+ mov bp,sp\r
+ push ds\r
+ push si\r
+ push di\r
+\r
+ lds si,[src]\r
+ mov dx,[count]\r
+\r
+ xor di,di\r
+\r
+ lodsb ; Load first byte into BL\r
+ mov bl,al\r
+ xor cx,cx ; Set number characters packed to zero\r
+ cld ; All moves are forward\r
+\r
+@@RepeatByte:\r
+ lodsb ; Get byte into AL\r
+ inc cx ; Increment compressed byte count\r
+ sub dx,1 ; Decrement bytes left\r
+ je @@LastByte ; Finished when dx = 1\r
+ cmp cx,7fh ; Filled block yet\r
+ jne @@NotFilled ; Nope!\r
+\r
+ add di,2 ; RL/BYTE pair stub\r
+\r
+@@NotFilled:\r
+ cmp al,bl ; hase there been a byte transition ?\r
+ je @@RepeatByte ; No!\r
+\r
+ cmp cl,1 ; do we have a unique byte ?\r
+ jne @@NotUnique ; No\r
+\r
+ test bl,80h ; Can this byte be mistaken for repeat count\r
+ jz @@Unambiguous ; No ! Dont bother with repeat count\r
+\r
+@@NotUnique:\r
+ inc di ; RL stub\r
+\r
+@@Unambiguous:\r
+ xor cx,cx ; clear compressed byte count\r
+ inc di ; BYTE stub\r
+ mov bl,al ; move latest byte into bl\r
+ jmp short @@RepeatByte\r
+\r
+@@LastByte:\r
+ cmp cl,1 ; Is this a unique byte\r
+ jne @@FinalCount ; No\r
+\r
+ test bl,80h ; Can this byte be mistaken for repeat count\r
+ jz @@FinalByte ; No, so dont bother with the repeat count\r
+\r
+@@FinalCount: ; Output the repeat count\r
+ inc di ; RL stub\r
+\r
+@@FinalByte:\r
+ inc di ; BYTE stub\r
+ inc di ; RL stub - Account for termiating null\r
+ mov ax,di\r
+\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ pop bp\r
+ ret\r
+_x_buff_RLE_size endp\r
+\r
+;****************************************************************\r
+;*\r
+;* NAME: x_buff_RLDecode\r
+;*\r
+;*\r
+;* Expands an RLE compresses source buffer to a destination buffer.\r
+;* returns the size of the resultant uncompressed data.\r
+;*\r
+;* C PROTOTYPE:\r
+;*\r
+;* extern unsigned int x_buff_RLDecode(char far * source_buff,\r
+;* char far * dest_buff);\r
+;*\r
+;* source_buff - The buffer to compress\r
+;* dest_buff - The destination buffer\r
+;*\r
+;* WARNING: buffers must be pre allocated.\r
+;*\r
+proc _x_buff_RLDecode\r
+ARG src:dword,dest:dword\r
+LOCAL si_ini:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk\r
+ push ds\r
+ push si\r
+ push di\r
+\r
+ mov dx,-1 ; zero output data buffer size - 1 (compensate for\r
+ ; terminating null RL)\r
+ xor cx,cx ; clear CX\r
+ cld ; Move forward\r
+\r
+ lds si,[src] ; point ds:si -> RLE source\r
+ les di,[dest] ; point es:di -> uncompressed buffer\r
+ mov [si_ini],si\r
+\r
+@@UnpackLoop:\r
+ lodsb ; load a byte into AL\r
+ cmp al,80h ; is it terminating null RL code\r
+ je @@done ; if so jump\r
+\r
+ test al,80h ; is AL a RL code (is high bit set ?)\r
+ jz @@NoRepeats ; if not the no RL encoding for this byte, jump\r
+\r
+ mov cl,al ; set CL to RL (run length) taking care\r
+ xor cl,80h ; to remove the bit identifying it as a RL\r
+ add dx,cx ; increment buffer size\r
+\r
+ lodsb ; get the next byte which should be a data byte\r
+\r
+ shr cx,1 ; divide RL by 2 to use word stos\r
+ jcxz @@NoRepeats ; result is zero, jump\r
+\r
+ mov ah,al ; copy data byte to AH since going to use stosw\r
+ rep stosw ; copy AX to outbut buffer RL times\r
+ jnb @@UnpackLoop ; when we shifted the RL if we had a carry =>\r
+ ; we had an odd number of repeats so store the\r
+ ; last BYTE if carry was set otherwise jump\r
+ stosb ; store AL in destination buffer\r
+ jmp short @@UnpackLoop\r
+\r
+@@NoRepeats:\r
+ inc dx ; increment buffer size\r
+ stosb ; store AL in destination buffer\r
+ jmp short @@UnpackLoop\r
+\r
+@@done:\r
+\r
+ mov bx,si\r
+ sub bx,[si_ini]\r
+ mov ax,dx\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ mov [_RLE_last_buff_offs],bx\r
+ mov sp,bp\r
+ pop bp\r
+ ret\r
+_x_buff_RLDecode endp\r
+\r
+;==========================================================================\r
+;==========================================================================\r
+; RLEncode to file / RLDecode from file\r
+; WARNING the following functions are *MUCH* slower than the above\r
+; Its best to use the above functions with intermediate buffers where\r
+; disk i/o is concearned... See demo 4\r
+;==========================================================================\r
+;==========================================================================\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+;\r
+; put_cx\r
+;\r
+; Local utility proc for x_file_RLEncode - write cx to file\r
+;\r
+; Entry:\r
+; es:dx -> output buffer\r
+; cx = word to write\r
+;\r
+;\r
+put_cx proc near\r
+ push ds ; preserve critical registers\r
+ push ax\r
+ push bx\r
+ mov ax,ds ; set up DS to output buffers segment\r
+ mov ds,ax\r
+ mov word ptr [RLEbuff],cx ; copy CX to output buffer\r
+ mov ah,40h ; select "write to file or device" DOS service\r
+ mov bx,[handle] ; select handle of file to write\r
+ mov cx,2 ; sending 2 bytes\r
+ int 21h ; call DOS service\r
+ pop bx ; recover registers\r
+ pop ax\r
+ pop ds\r
+ ret\r
+put_cx endp\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+;\r
+; put_cx\r
+;\r
+; Local utility proc for x_file_RLEncode - write cx to file\r
+;\r
+; Entry:\r
+; es:dx -> output buffer\r
+; cx = word to write\r
+;\r
+;\r
+put_cl proc near\r
+ push ds ; preserve critical registers\r
+ push ax\r
+ push bx\r
+ mov ax,ds ; set up DS to output buffers segment\r
+ mov ds,ax\r
+ mov byte ptr [RLEbuff],cl\r
+ mov ah,40h ; select "write to file or device" DOS service\r
+ mov bx,[handle] ; select handle of file to write\r
+ mov cx,1 ; sending 1 byte\r
+ int 21h ; call DOS service\r
+ pop bx ; recover registers\r
+ pop ax\r
+ pop ds\r
+ ret\r
+put_cl endp\r
+\r
+\r
+;****************************************************************\r
+;*\r
+;* NAME: x_file_RLEncode\r
+;*\r
+;*\r
+;* RLE Compresses a source buffer to an output file returning\r
+;* the size of the resultant compressed data or 0 if it fails.\r
+;*\r
+;* C PROTOTYPE:\r
+;*\r
+;* extern unsigned int x_file_RLEncode(int handle,\r
+;* char far * source_buff,unsigned int count);\r
+;*\r
+;* source_buff - The buffer to compress\r
+;* handle - The file handler\r
+;* count - The size of the source data in bytes\r
+;*\r
+;*\r
+proc _x_file_RLEncode\r
+ARG handle:word,src:dword,count:word\r
+LOCAL filesize:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk\r
+ push ds\r
+ push si\r
+ push di\r
+\r
+ mov [filesize],0\r
+ mov dx,offset [RLEbuff]\r
+ mov ax,ds\r
+ mov es,ax\r
+ lds si,[src]\r
+ mov di,[count]\r
+\r
+ lodsb ; Load first byte into BL\r
+ mov bl,al\r
+ xor cx,cx ; Set number characters packed to zero\r
+ cld ; All moves are forward\r
+\r
+@@RepeatByte:\r
+ lodsb ; Get byte into AL\r
+ inc cx ; Increment compressed byte count\r
+ sub di,1 ; Decrement bytes left\r
+ je @@LastByte ; Finished when di = 1\r
+ cmp cx,7fh ; Filled block yet\r
+ jne @@NotFilled ; Nope!\r
+\r
+ or cl,80h ; Set bit to indicate value is repeat count\r
+ mov ch,bl\r
+ add [filesize],2\r
+ call put_cx\r
+ jb @@FileError ; if carry set then file I/O error\r
+ xor cx,cx ; clear compressed byte count\r
+\r
+@@NotFilled:\r
+ cmp al,bl ; hase there been a byte transition ?\r
+ je @@RepeatByte ; No!\r
+\r
+ cmp cl,1 ; do we have a unique byte ?\r
+ jne @@NotUnique ; No\r
+\r
+ test bl,80h ; Can this byte be mistaken for repeat count\r
+ jz @@Unambiguous ; No ! Dont bother with repeat count\r
+\r
+@@NotUnique:\r
+ or cl,80h ; Set bit to indicate value is repeat count\r
+ inc [filesize]\r
+ call put_cl ; store it\r
+ jb @@FileError ; if carry set then file I/O error\r
+@@Unambiguous:\r
+\r
+ mov cl,bl ; store byte to be repeated\r
+ inc [filesize]\r
+ call put_cl\r
+ jb @@FileError ; if carry set then file I/O error\r
+ mov bl,al ; move latest byte into bl\r
+ xor cx,cx ; clear compressed byte count\r
+ jmp short @@RepeatByte\r
+\r
+@@FileError:\r
+ mov ax,0\r
+ jmp short @@exit\r
+\r
+@@LastByte:\r
+ cmp cl,1 ; Is this a unique byte\r
+ jne @@FinalCount ; No\r
+\r
+ test bl,80h ; Can this byte be mistaken for repeat count\r
+ jz @@FinalByte ; No, so dont bother with the repeat count\r
+\r
+@@FinalCount: ; Output the repeat count\r
+ or cl,80h\r
+ inc [filesize]\r
+ call put_cl\r
+ jb @@FileError ; if carry set then file I/O error\r
+\r
+@@FinalByte:\r
+ mov cl,bl\r
+ mov ch,80h\r
+ add [filesize],2\r
+ call put_cx ; store terminating null length\r
+ jb @@FileError ; if carry set then file I/O error\r
+\r
+ mov ax,[filesize]\r
+ jmp short @@exit\r
+\r
+@@exit:\r
+ pop di\r
+ pop si\r
+ pop ds\r
+ mov sp,bp\r
+ pop bp\r
+ ret\r
+_x_file_RLEncode endp\r
+\r
+\r
+\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+;\r
+; GET_BYTE\r
+;\r
+; macro to read a byte from the input file into al\r
+;\r
+GET_BYTE macro\r
+ push bx\r
+ mov ah,3fh ; select "read from file or device" DOS service\r
+ mov bx,[handle] ; Select handle of file to close\r
+ mov cx,1 ; Want to read 1 byte\r
+ int 21h ; call DOS service\r
+ pop bx\r
+ jb @@FileError ; failed if carry flag set\r
+ mov al,[RLEbuff]\r
+ endm\r
+\r
+\r
+;****************************************************************\r
+;*\r
+;* NAME: x_file_RLDecode\r
+;*\r
+;*\r
+;* Expands an RLE compresses file to a destination RAM buffer.\r
+;* returns the size of the resultant uncompressed data.\r
+;*\r
+;* C PROTOTYPE:\r
+;*\r
+;* extern unsigned int x_buff_RLDecode(int handle,\r
+;* char far * dest_buff);\r
+;*\r
+;* handle - Input file handle\r
+;* dest_buff - The destination buffer\r
+;*\r
+;*\r
+proc _x_file_RLDecode\r
+ARG handle:word,dest:dword\r
+ push bp\r
+ mov bp,sp\r
+ push si\r
+ push di\r
+\r
+\r
+ mov bx,-1 ; zero output data buffer size - 1 (compensate for\r
+ ; terminating null RL)\r
+ mov dx,offset [RLEbuff] ; setup DS:DX -> RLEBuffer\r
+ xor cx,cx ; clear CX\r
+ cld ; Move forward\r
+\r
+ les di,[dest] ; point es:di -> uncompressed buffer\r
+\r
+@@UnpackLoop:\r
+\r
+ GET_BYTE ; Load a byte from file into AL\r
+\r
+ cmp al,80h ; is it terminating null RL code\r
+ je @@done ; if so jump\r
+\r
+ test al,80h ; is AL a RL code (is high bit set ?)\r
+ jz @@NoRepeats ; if not the no RL encoding for this byte, jump\r
+\r
+ mov cl,al ; set CL to RL (run length) taking care\r
+ xor cl,80h ; to remove the bit identifying it as a RL\r
+ add bx,cx ; increment buffer size\r
+ mov si,cx ; save the CX value\r
+ GET_BYTE ; Load a byte from file into AL\r
+ mov cx,si ; restore CX value\r
+ shr cx,1 ; divide RL by 2 to use word stos\r
+ jcxz @@NoRepeats ; result is zero, jump\r
+\r
+ mov ah,al ; copy data byte to AH since going to use stosw\r
+ rep stosw ; copy AX to outbut buffer RL times\r
+ jnb @@UnpackLoop ; when we shifted the RL if we had a carry =>\r
+ ; we had an odd number of repeats so store the\r
+ ; last BYTE if carry was set otherwise jump\r
+ stosb ; store AL in destination buffer\r
+ jmp short @@UnpackLoop\r
+\r
+@@NoRepeats:\r
+ inc bx\r
+ stosb ; store AL in destination buffer\r
+ jmp short @@UnpackLoop\r
+\r
+@@FileError:\r
+ mov ax,0\r
+ jmp short @@exit\r
+\r
+@@done:\r
+ mov ax,bx\r
+@@exit:\r
+ pop di\r
+ pop si\r
+ pop bp\r
+ ret\r
+_x_file_RLDecode endp\r
+\r
+ end\r
+\r
+\1a
\ No newline at end of file
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XRLETOOL - header file\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+;-----------------------------------------------------------------------*/\r
+\r
+#ifndef _XRLETOOL_H_\r
+#define _XRLETOOL_H_\r
+\r
+extern unsigned int RLE_last_buff_offs;\r
+\r
+/* FUNCTIONS =========================================================== */\r
+\r
+extern unsigned int x_buff_RLEncode( /* Compress data buffer */\r
+ char far * source_buff,\r
+ char far * dest_buff,\r
+ unsigned int count);\r
+\r
+extern unsigned int x_buff_RLE_size( /* Calculate buffer's compressed size */\r
+ char far * source_buff,\r
+ unsigned int count);\r
+\r
+\r
+extern unsigned int x_buff_RLDecode( /* Uncompress data buffer */\r
+ char far * source_buff,\r
+ char far * dest_buff);\r
+\r
+extern int x_file_RLEncode( /* Compress data buffer to file */\r
+ int handle,\r
+ char far * src_buff,\r
+ unsigned int count);\r
+\r
+extern int x_file_RLDecode( /* Uncompress data file */\r
+ int file_handle,\r
+ char far * dest_buff);\r
+\r
+\r
+#endif\r
+\r
+\r
+\1a
\ No newline at end of file
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XRLETOOL - Include file\r
+;\r
+; XRLETOOL.ASM export functions\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+ global _x_buff_RLEncode :proc\r
+ global _x_buff_RLE_size :proc\r
+ global _x_buff_RLDecode :proc\r
+ global _x_file_RLEncode :proc\r
+ global _x_file_RLDecode :proc\r
+\r
+ global _RLE_last_buff_offs :word\r
+ \r
+\1a
\ No newline at end of file
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XTEXT\r
+;\r
+; Point functions all MODE X 256 Color resolutions\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+include xlib.inc\r
+include xtext.inc\r
+\r
+.data\r
+\r
+_FontDriverActive db 0\r
+\r
+\r
+_CharHeight db 0\r
+_CharWidth db 0\r
+_FontPtr dw 2 dup (0)\r
+_FirstChar db 0\r
+\r
+_UserFontPtr dw 2 dup (0)\r
+_UserChHeight db 0\r
+_UserChWidth db 0\r
+_UserFirstCh db 0\r
+\r
+\r
+F8x8Ptr dw 2 dup (0)\r
+F8x14Ptr dw 2 dup (0)\r
+\r
+; This is a look up table for the mirror image of a byte eg\r
+; a byte with the value 11001010 has a corresponding byte in the table\r
+; 01010011. This is necessary as the VGA rom font bits are the reverse\r
+; order of what we need for the Mode X. If you know a better-faster way\r
+; TELL ME!\r
+\r
+MirrorTable label byte\r
+ db 0,128, 64,192, 32,160, 96,224, 16,144, 80,208, 48,176,112,240\r
+ db 8,136, 72,200, 40,168,104,232, 24,152, 88,216, 56,184,120,248\r
+ db 4,132, 68,196, 36,164,100,228, 20,148, 84,212, 52,180,116,244\r
+ db 12,140, 76,204, 44,172,108,236, 28,156, 92,220, 60,188,124,252\r
+ db 2,130, 66,194, 34,162, 98,226, 18,146, 82,210, 50,178,114,242\r
+ db 10,138, 74,202, 42,170,106,234, 26,154, 90,218, 58,186,122,250\r
+ db 6,134, 70,198, 38,166,102,230, 22,150, 86,214, 54,182,118,246\r
+ db 14,142, 78,206, 46,174,110,238, 30,158, 94,222, 62,190,126,254\r
+ db 1,129, 65,193, 33,161, 97,225, 17,145, 81,209, 49,177,113,241\r
+ db 9,137, 73,201, 41,169,105,233, 25,153, 89,217, 57,185,121,249\r
+ db 5,133, 69,197, 37,165,101,229, 21,149, 85,213, 53,181,117,245\r
+ db 13,141, 77,205, 45,173,109,237, 29,157, 93,221, 61,189,125,253\r
+ db 3,131, 67,195, 35,163, 99,227, 19,147, 83,211, 51,179,115,243\r
+ db 11,139, 75,203, 43,171,107,235, 27,155, 91,219, 59,187,123,251\r
+ db 7,135, 71,199, 39,167,103,231, 23,151, 87,215, 55,183,119,247\r
+ db 15,143, 79,207, 47,175,111,239, 31,159, 95,223, 63,191,127,255\r
+\r
+MirrorTableOffs dw ?\r
+.code\r
+\r
+;----------------------------------------------------------------------\r
+; x_text_init - Initializes the Mode X text driver and sets the\r
+; default font (VGA ROM 8x8)\r
+;\r
+; C caller:\r
+;\r
+; x_text_init()\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_text_init proc\r
+ push bp\r
+\r
+ mov [_FontDriverActive],TRUE\r
+ mov ax,1130h ; AH = BIOS generator function\r
+ ; AL = BIOS get font pointer subfunction\r
+ push ax ; Save Video interrupt function parameters\r
+ mov bh,3 ; Select 8x8 VGA ROM font\r
+ int 10h ; Call BIOS video interrupt\r
+ mov word ptr [F8x8Ptr],bp ; Save 8x8 Font address in FontPtr table\r
+ mov word ptr [F8x8Ptr+2],es\r
+\r
+ mov word ptr [_FontPtr],bp ; Default font = 8x8 ROM font\r
+ mov word ptr [_FontPtr+2],es\r
+\r
+ pop ax ; Recall Video interrupt function parameters\r
+ mov bh,2 ; Select 8x14 VGA ROM font\r
+ int 10h ; Call BIOS video interrupt\r
+ mov word ptr [F8x14Ptr],bp ; Save 8x14 Font address in FontPtr table\r
+ mov word ptr [F8x14Ptr+2],es\r
+\r
+\r
+ mov al,8\r
+ mov [_CharHeight],al ; Set the font character heights\r
+ mov [_CharWidth] ,al ; Set the font character widths\r
+\r
+ mov dx,offset MirrorTable ; Initialize mirror table offset\r
+ mov [MirrorTableOffs],dx\r
+\r
+ pop bp\r
+ ret\r
+_x_text_init endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_set_font - Mode X Set current font for text drawing\r
+;\r
+; C caller:\r
+;\r
+; x_set_font(int FontID)\r
+;\r
+; PARAMETERS FontID 0 = VGA ROM 8x8\r
+; 1 = VGA ROM 8x14\r
+; 2 = User defined bitmapped font\r
+;\r
+;\r
+; WARNING: A user font must be registered before setting FontID 2\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+\r
+_x_set_font proc\r
+ ARG FontID:word\r
+ push bp\r
+ mov bp,sp\r
+\r
+ xor dx,dx ; Clear DX - Mirror table offset (0 for non ROM fonts)\r
+ mov cx,FontID\r
+ cmp cx,2\r
+\r
+ jne @@not_userfont ; Do we have a user font\r
+ mov ax,[_UserFontPtr] ; Yes - Activate it\r
+ mov [_FontPtr],ax\r
+\r
+ mov ax,[_UserFontPtr+2]\r
+ mov [_FontPtr+2],ax\r
+\r
+ mov al,[_UserChHeight]\r
+ mov [_CharHeight],al ; Set the font character heights\r
+\r
+ mov al,[_UserChWidth]\r
+ mov [_CharWidth],al ; Set the font character heights\r
+\r
+ mov al,[_UserFirstCh]\r
+ mov [_FirstChar],al\r
+ jmp short @@done\r
+\r
+@@not_userfont: ; We have a ROM font\r
+\r
+ mov dx,offset MirrorTable\r
+ mov [_CharWidth],8 ; Set the font character widths\r
+ mov [_FirstChar],0 ; Character sets start at ascii 0\r
+ cmp cx,1 ; Do we have an 8x14 ROM font\r
+ jne @@not_8x14font ; No, we have 8x8 - jump\r
+\r
+ mov ax,[F8x14Ptr] ; Yes Activate it\r
+ mov [_FontPtr],ax\r
+\r
+ mov ax,[F8x14Ptr+2]\r
+ mov [_FontPtr+2],ax\r
+\r
+ mov [_CharHeight],14 ; Set the font character heights\r
+ jmp short @@done\r
+\r
+@@not_8x14font:\r
+ mov ax,[F8x8Ptr] ; Activate the 8x8 ROM Font\r
+ mov [_FontPtr],ax\r
+\r
+ mov ax,[F8x8Ptr+2]\r
+ mov [_FontPtr+2],ax\r
+\r
+ mov [_CharHeight],8 ; Set the font character heights\r
+\r
+@@done:\r
+ mov [MirrorTableOffs],dx\r
+\r
+ pop bp\r
+ ret\r
+_x_set_font endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_register_userfont - Mode X register user font\r
+;\r
+; C caller:\r
+;\r
+; x_register_userfont(void far *user_font)\r
+;\r
+;\r
+; NOTES registering a user font deregisters the previous user font\r
+; User fonts may be at most 8 pixels wide\r
+;\r
+;\r
+; USER FONT STRUCTURE\r
+;\r
+; Word: ascii code of first char in font\r
+; Byte: Height of chars in font\r
+; Byte: Width of chars in font\r
+; n*h*Byte: the font data where n = number of chars and h = height\r
+; of chars\r
+;\r
+; WARNING: The onus is on the program to ensure that all characters\r
+; drawn whilst this font is active, are within the range of\r
+; characters defined.\r
+;\r
+;\r
+; UPDATE: Variable width fonts are now available (up to 8 pixels max)\r
+; If the Width byte in the font header is 0 then it is assumed that\r
+; the font is variable width. For variable width fonts each characters\r
+; data is followed by one byte representing the characters pixel width.\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_register_userfont proc\r
+ ARG FontToRegister:dword\r
+ push bp\r
+ mov bp,sp\r
+ push si\r
+\r
+ mov ax,word ptr [FontToRegister]\r
+ mov bx,word ptr [FontToRegister+2]\r
+ add ax,4\r
+ mov [_UserFontPtr],ax\r
+ mov [_UserFontPtr+2],bx\r
+\r
+ push ds\r
+ lds si,[FontToRegister]\r
+ lodsw\r
+ mov bx,ax\r
+ lodsw\r
+ pop ds\r
+\r
+ mov [_UserChHeight],al\r
+ mov [_UserChWidth],ah\r
+ mov [_UserFirstCh],bl\r
+ pop si\r
+ pop bp\r
+ ret\r
+_x_register_userfont endp\r
+\r
+\r
+_x_get_char_width proc\r
+ ARG Chr:byte\r
+ push bp\r
+ mov bp,sp\r
+\r
+ xor ah,ah\r
+ mov al,[_CharWidth]\r
+ or al,al\r
+ jz @@NotFixed\r
+ pop bp\r
+ ret\r
+\r
+@@NotFixed:\r
+ push si\r
+ mov al,[_CharHeight]\r
+ mov bx,ax\r
+ inc al\r
+ mov dl,[Chr] ; User fonts may have incomplete charsets\r
+ sub dl,[_FirstChar] ; this compensates for fonts not starting at\r
+ ; ascii value 0\r
+ mul dl ; Mult AX by character to draw giving offset\r
+ ; of first character byte in font table\r
+ add ax,bx\r
+ les si,dword ptr [_FontPtr]\r
+ add si,ax\r
+ xor ah,ah\r
+ mov al,es:[si]\r
+ pop si\r
+ pop bp\r
+ ret\r
+_x_get_char_width endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_char_put - Mode X Draw a text character at the specified location\r
+;\r
+;\r
+; C caller:\r
+;\r
+; x_char_put(char ch, int x, int y, unsigned ScrnOffs, unsigned Color)\r
+;\r
+; PARAMETERS ch char to draw\r
+; x,y screen coords at which to draw ch\r
+; ScrnOffs Starting offset of page on whih to draw\r
+; Color Color of the text\r
+;\r
+; NOTES: Uses the current font settings. See SetFont, InitTextDriver,\r
+; RegisterUserFont\r
+;\r
+; WARNING: InitTextDriver must be called before using this function\r
+;\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_char_put proc\r
+ ARG Chr:byte,X:word,Y:word,ScrnOffs:word,Color:word\r
+ LOCAL ScreenInc:word,Hold:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk\r
+ push si\r
+ push di\r
+ push ds\r
+\r
+ cld\r
+ mov ax,[_ScrnLogicalByteWidth] ; AX = Virtual screen width\r
+ mov bx,ax ; copy Virt screen width and decrement\r
+ sub bx,3 ; by the max number of bytes (whole or part)\r
+ ; that a character row may occupy on the screen\r
+ mov [ScreenInc],bx ; Save it to the local stack var. SceenInc\r
+ mul [Y] ; Find the starting dest. screen address of\r
+ mov di,[X] ; the character to draw\r
+ mov cx,di\r
+ shr di,2\r
+ add di,ax\r
+ add di,[ScrnOffs] ; Dont forget to compensate for page\r
+\r
+ mov ax,SCREEN_SEG ; ES:DI -> first screen dest. byte of char\r
+ mov es,ax\r
+\r
+ and cx,3 ; CH = 0, CL = Plane of first pixel\r
+\r
+ mov bx,[MirrorTableOffs] ; set BX to offset of mirror table for XLAT\r
+ mov al,[_CharHeight] ; AL = Character height, AH = 0\r
+ xor ah,ah\r
+ mov ch,al ; CH = Character height\r
+\r
+ cmp [_CharWidth],0\r
+ jne @@NoWidthByte\r
+ inc al\r
+@@NoWidthByte:\r
+\r
+ mov dl,[Chr] ; User fonts may have incomplete charsets\r
+ sub dl,[_FirstChar] ; this compensates for fonts not starting at\r
+ ; ascii value 0\r
+ mul dl ; Mult AX by character to draw giving offset\r
+ ; of first character byte in font table\r
+\r
+ lds si,dword ptr [_FontPtr] ; DS:SI -> beggining of required font\r
+ add si,ax ; DS:SI -> first byte of req. char\r
+\r
+ mov dx,SC_INDEX ; Prepare for VGA out's\r
+\r
+@@MainLoop:\r
+\r
+ lodsb ; load character byte into AL\r
+ or al,al\r
+ jz @@NoCharPixels ; Dont bother if no pixels to draw\r
+\r
+ or bx,bx ; if BX=0 -> User font, so no need to mirror data\r
+ jz @@DontMirror\r
+ push ds\r
+ mov dx,@data ; Set DS to the Mirror lookup table's segment\r
+ mov ds,dx ; - BX should already contain the offset addr of table\r
+ xlatb ; AL is now replaced by the corresponding table entry\r
+ pop ds ; Restore previous data segment\r
+ mov dx,SC_INDEX ; Restore DX\r
+\r
+@@DontMirror:\r
+ xor ah,ah ; shift the byte for the dest plane and save it\r
+ shl ax,cl\r
+ mov [Hold],ax\r
+\r
+ mov ah,al ; output high nibble of first byte of shifted char\r
+ and ah,0fh ; 4 pixels at a time !\r
+ jnz @@p1 ; if nibble has pixels, draw them\r
+ inc di ; otherwise go to next nibble\r
+ jmp @@SecondNibble\r
+\r
+@@p1:\r
+ mov al,MAP_MASK\r
+ out dx,ax\r
+ mov al,byte ptr [Color]\r
+ stosb\r
+\r
+@@SecondNibble:\r
+ ; output low nibble of first byte of shifted char\r
+ mov ax,[Hold]\r
+ shl ax,4\r
+ and ah,0fh\r
+ jnz @@p2\r
+ inc di\r
+ jmp @@ThirdNibble\r
+\r
+@@p2:\r
+ mov al,MAP_MASK\r
+ out dx,ax\r
+ mov al,byte ptr [Color]\r
+ stosb\r
+\r
+@@ThirdNibble:\r
+ mov ax,[Hold] ; output high nibble of last byte of shifted char\r
+ and ah,0fh\r
+ jnz @@p3\r
+ inc di\r
+ jmp short @@NextCharRow\r
+\r
+@@p3:\r
+ mov al,MAP_MASK ; completing the drawing of one character row\r
+ out dx,ax\r
+ mov al,byte ptr [Color]\r
+ stosb\r
+\r
+@@NextCharRow:\r
+ add di,[ScreenInc] ; Now move to the next screen row and do the same\r
+ dec ch ; any remaining character bytes\r
+ jnz @@MainLoop\r
+\r
+@@done:\r
+ pop es\r
+ mov ah,0\r
+ mov al,es:[_CharWidth] ; return the character width (for string fuctions\r
+ or al,al\r
+ jnz @@FixedSpacing ; using this character drawing function).\r
+ lodsb\r
+@@FixedSpacing:\r
+\r
+ mov bx,es\r
+ mov ds,bx\r
+\r
+ pop di\r
+ pop si\r
+ mov sp,bp\r
+ pop bp\r
+ ret\r
+\r
+@@NoCharPixels:\r
+ add di,3\r
+ add di,[ScreenInc] ; Now move to the next screen row and do the same\r
+ dec ch ; any remaining character bytes\r
+ jnz @@MainLoop\r
+ jmp short @@done\r
+\r
+_x_char_put endp\r
+\r
+\r
+end\r
+\r
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XTEXT - header file\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;-----------------------------------------------------------------------*/\r
+\r
+#ifndef _XTEXT_H_\r
+#define _XTEXT_H_\r
+\r
+\r
+#define FONT_8x8 0\r
+#define FONT_8x15 1\r
+#define FONT_USER 2\r
+\r
+/* FUNCTIONS =========================================================== */\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+WORD x_text_init(void); /* Initialize text functionns */\r
+\r
+void x_set_font(\r
+ WORD FontId); /* Set the font style */\r
+\r
+void x_register_userfont( /* register a user defined font */\r
+ char far *UserFontPtr);\r
+\r
+unsigned int x_char_put( /* Draw a text character using */\r
+ char ch, /* the currently active font */\r
+ WORD X,\r
+ WORD Y,\r
+ WORD PgOffs,\r
+ WORD Color);\r
+\r
+\r
+unsigned int x_get_char_width( /* Get the character width */\r
+ char ch);\r
+\r
+\r
+/* the folowing function is from xprintf.c but is included due to its */\r
+/* close relationship with this module */\r
+\r
+void x_printf( /* formatted text output */\r
+ WORD x,\r
+ WORD y,\r
+ WORD ScrnOffs,\r
+ WORD color,\r
+ char *ln,...);\r
+\r
+void x_bgprintf( /* formatted text output */\r
+ WORD x,\r
+ WORD y,\r
+ WORD ScrnOffs,\r
+ WORD fgcolor,\r
+ WORD bgcolor,\r
+ char *ln,...);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+/* VARIABLES =========================================================== */\r
+\r
+extern BYTE CharHeight; /* Char height of currently active font */\r
+extern BYTE CharWidth; /* Char width of currently active font */\r
+extern BYTE FirstChar; /* First char in the curr. active font */\r
+\r
+extern BYTE UserCharHeight; /* Char height of currentle regist'd user font */\r
+extern BYTE UserCharWidth; /* Char height of currentle regist'd user font */\r
+extern BYTE UserFirstChar; /* First char of the curr. regist'd usera font */\r
+\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XPOINT - Include file\r
+;\r
+; XPOINT.ASM export functions\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+ global _x_text_init :proc\r
+ global _x_set_font :proc\r
+ global _x_char_put :proc\r
+ global _x_register_userfont :proc\r
+ global _x_get_char_width :proc\r
+\r
+ global _CharHeight :byte\r
+ global _CharWidth :byte\r
+ global _FontPtr :word:2\r
+ global _FirstChar :byte\r
+ global _UserFontPtr :word:2\r
+ global _UserChHeight :byte\r
+ global _UserChWidth :byte\r
+ global _UserFirstCh :byte\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XVBITMAP\r
+;\r
+; Video Bitmap functions - Video Ram <-> Video Ram\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+COMMENT $\r
+\r
+The XVBITMAP module implements yet another type of bitmap to complement\r
+planar and compiled bitmaps, VRAM based bitmaps. If a 4 cylinder car is\r
+analagous to planar bitmaps, that is thrifty on memory consumption but low\r
+performance and and a V8 is analagous to Compiled bitmaps, memory guzzlers\r
+that really fly, then VRAM based bitmaps are the 6 cylinder modest performers\r
+with acceptable memory consumption.\r
+\r
+To summarise their selling points, VBM's are moderately fast with fair memory\r
+consumption, and unlike compiled bitmaps, can be clipped. The disadvantages\r
+are that they are limited by the amount of free video ram and have a complex\r
+structure.\r
+\r
+The VRAM bitmap format is rather complex consisting of components stored in\r
+video ram and components in system ram working together. This complexity\r
+necessitates the existence of a creation function "x_make_vbm" which takes\r
+an input linear bitmap and generates the equivalent VBM (VRAM Bit Map).\r
+\r
+VBM structure:\r
+\r
+ WORD 0 Size Total size of this VBM structure in bytes\r
+ WORD 1 ImageWidth Width in bytes of the image (for all alignments)\r
+ WORD 2 ImageHeight Height in scan lines of the image\r
+\r
+ WORD 3 Alignment 0 ImagePtr Offset in VidRAM of this aligned image\r
+ +--WORD 4 MaskPtr Offset (within this structure's DS) of\r
+ | . alignment masks\r
+ | .\r
+ | .\r
+ | WORD 9 Alignment 3 ImagePtr Offset in VidRAM of this aligned image\r
+ +|--WORD 10 MaskPtr Offset (within this structure's DS) of\r
+ || alignment masks\r
+ ||\r
+ |+->BYTE 21 (WORD 11) -------+-- Image masks for alignment 0\r
+ | . |\r
+ | . |\r
+ | BYTE 21 + ImageWidth*ImageHeight -----+\r
+ |\r
+ | .\r
+ | . (similaly for alignments 1 - 2 )\r
+ | .\r
+ |\r
+ +-->BYTE 21 + 3*ImageWidth*ImageHeight + 1-+-- Image masks for alignment 3\r
+ . |\r
+ . |\r
+ BYTE 21 + 4*(ImageWidth*ImageHeight) --+\r
+\r
+ .\r
+ .\r
+ << Similarly for alignments 2 and 3 >>\r
+ .\r
+ .\r
+ BYTE 21 + 4*(ImageWidth*ImageHeight)\r
+ -------------\r
+\r
+ (And dont forget the corresponding data in video ram)\r
+\r
+$\r
+\r
+\r
+include xlib.inc\r
+include xvbitmap.inc\r
+\r
+VBM_info_struc struc\r
+ Size dw ?\r
+ ImageWidth dw ?\r
+ ImageHeight dw ?\r
+; AlignData dw ?\r
+VBM_info_struc ends\r
+\r
+AlignData equ 6\r
+\r
+VBM_alignment_struc struc\r
+ ImagePtr dw ?\r
+ MaskPtr dw ?\r
+VBM_alignment_struc ends\r
+\r
+\r
+ .code\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_store_vbm_image\r
+;\r
+; Store the linear bitmap in video RAM using the specified alignment and\r
+; start address. Returns number video ram bytes used.\r
+;\r
+; THIS FUNCTION IS FOR USE BY x_make_masked_vbm\r
+;\r
+; Prototype:\r
+;\r
+; x_store_vbm_image(unsigned int vramoffs, unsigned int Align,\r
+; char far *lbm);\r
+;\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_store_vbm_image proc\r
+ ARG VramOffs:word,Align:word,LBitmap:dword\r
+ LOCAL BMWidth:byte=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+\r
+ mov ax,SCREEN_SEG ; Point ES to screen segment\r
+ mov es,ax\r
+ mov di,[VramOffs] ; Point ES:DI to VRAM dest start\r
+ mov bx,[Align] ; Set BL to first pixel plane align\r
+ and bl,03h\r
+\r
+ lds si,[LBitmap] ; DS:SI -> source linear Bitmap\r
+ lodsw ; Al = B.M. width (bytes) AH = B.M.\r
+ mov bh,ah ; Save source bitmap dimensions\r
+ mov [BMWidth],al ;\r
+\r
+ mov dx,SC_INDEX ; Initialize Map Mask for plane\r
+ mov al,MAP_MASK ; selection\r
+ out dx,al\r
+ inc dx\r
+ xor ch,ch ; clear CH\r
+@@RowLoop:\r
+ mov cl,bl ; Set initial plane for current\r
+ mov ah,11h ; allignment\r
+ shl ah,cl\r
+\r
+ mov cl,[BMWidth] ; Initialize column counter\r
+@@ColLoop:\r
+ mov al,ah\r
+ out dx,al ; set vga write plane\r
+ lodsb ; load next LBM pixel\r
+ mov es:[di],al ; store it in Video Ram\r
+ shl ah,1 ; rotate plane mask\r
+ jnb @@NoAddrIncr ; Time to increment dest address ?\r
+ inc di ; Yes: increment addr and reset\r
+ mov ah,11h ; plane mask to plane 0\r
+@@NoAddrIncr:\r
+ loop @@ColLoop ; Loop to next pixel column\r
+ cmp ah,11h\r
+; je @@skip\r
+ inc di ; Increment dest addr\r
+;@@skip:\r
+ dec bh ; Decrement row counter\r
+ jnz @@RowLoop ; Jump if more rows to go\r
+ mov ax,di ; calculate video RAM consumed and\r
+ sub ax,[VramOffs] ; return value\r
+\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_store_vbm_image endp\r
+\r
+\r
+_x_put_masked_vbm proc\r
+ ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword\r
+ LOCAL VBMWidth:word,VBMHeight:word,NextLineIncr:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+\r
+ mov ax,SCREEN_SEG ; Point es to VGA segment\r
+ mov es,ax\r
+ mov ax,[Y] ; Calculate dest screen row\r
+ mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen\r
+ mul cx ; width then adding screen offset\r
+\r
+ mov di,[ScrnOffs] ; store result in DI\r
+ add di,ax\r
+ mov si,[X] ; Load X coord into CX and make a\r
+ mov bx,si ; copy in DX\r
+ shr bx,2 ; Find starting byte in dest row\r
+ add di,bx ; add to DI giving screen offset of\r
+ ; first pixel's byte\r
+\r
+ and si,3 ; get pixel alignment in si\r
+\r
+ lds bx,[SrcVBM] ; DS:BX -> VBM data structure\r
+ shl si,2 ; si = offset of data for curr\r
+ ; alignment\r
+\r
+ mov ax,word ptr [bx+ImageHeight] ; Get image height\r
+ mov [VBMHeight],ax\r
+ mov ax,word ptr [bx+ImageWidth] ; Get image width\r
+ mov [VBMWidth],ax\r
+\r
+ sub cx,ax ; NextLineIncr = bytes to the begin.\r
+ mov [NextLineIncr],cx ; of bitmaps next row on screen\r
+ mov dx,[bx+MaskPtr+AlignData+si] ; DS:SI -> mask data\r
+ mov bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap\r
+ mov si,dx\r
+\r
+ mov dx,GC_INDEX ; Set bit mask for all bits from\r
+ mov ax,BIT_MASK ; VGA latches and none from CPU\r
+ out dx,ax\r
+\r
+ mov dx,SC_INDEX ; Point SC register to map mask\r
+ mov al,MAP_MASK ; in preperation for masking data\r
+ out dx,al\r
+ inc dx ; Point dx to SC data register\r
+ mov ah,byte ptr [VBMHeight] ; AH = Scanline loop counter\r
+\r
+@@RowLoop:\r
+ mov cx,[VBMWidth] ; Width in bytes across\r
+\r
+@@ColumnLoop:\r
+ lodsb\r
+ out dx,al\r
+ mov al,es:[bx] ; load latches from source bitmap\r
+ stosb ; store latches to dest. bitmap\r
+ inc bx\r
+ loop @@ColumnLoop\r
+\r
+ add di,[NextLineIncr] ; point to start of next dest row\r
+ dec ah ; decrement scan line counter\r
+ jnz @@RowLoop ; jump if more scanlines left\r
+\r
+ mov dx,GC_INDEX+1 ; Restore bitmask to the default -\r
+ mov al,0ffh ; all data from cpu\r
+ out dx,al\r
+\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_put_masked_vbm endp\r
+\r
+\r
+_x_put_masked_vbm_clipx proc\r
+ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword\r
+LOCAL DataInc,LeftSkip,VBMWidth,VBMHeight,NextLineIncr:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+\r
+ mov di,[X] ; load X coord int DI and make a\r
+ mov si,di ; copy in SI\r
+ sar di,2 ; Find Byte offset of X coord\r
+\r
+ and si,3 ; Calculate pixels plane alignment\r
+ shl si,2 ; Prepare to lookup mask & data\r
+ les bx,[SrcVBM] ; ES:BX -> begining of VBM data\r
+\r
+ mov cx,es:[bx+ImageWidth] ; Get image width and save in CX\r
+\r
+\r
+\r
+ ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+ mov dx,[_LeftClip]\r
+ sub dx,di\r
+ jle @@NotLeftClip\r
+ cmp dx,cx\r
+ jnl @@NotVisible\r
+ add di,dx\r
+ mov [LeftSkip],dx\r
+ mov [DataInc],dx\r
+ sub cx,dx\r
+ jmp short @@HorizClipDone\r
+\r
+ ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotVisible:\r
+ mov ax,1\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+\r
+ ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotLeftClip:\r
+ mov dx,[_RightClip]\r
+ sub dx,di\r
+ js @@NotVisible\r
+ mov [LeftSkip],0\r
+ mov [DataInc],0\r
+ cmp dx,cx\r
+ jge @@HorizClipDone\r
+ inc dx\r
+ sub cx,dx\r
+ mov [DataInc],cx\r
+ mov cx,dx\r
+\r
+@@HorizClipDone:\r
+\r
+\r
+ add di,[ScrnOffs] ; Add the current page offset\r
+ mov [VBMWidth],cx\r
+ mov ax,es:[bx+ImageHeight] ; Get image height and save in AX\r
+ mov [VBMHeight],ax\r
+\r
+\r
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+ mov ax,[Y] ; Calculate dest screen row\r
+ mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen\r
+ mul cx ; width then adding screen offset\r
+ add di,ax ; Add Dest Screen Row to di\r
+ sub cx,[VBMWidth]\r
+ mov [NextLineIncr],cx\r
+\r
+ mov ax,es ; copy ES to DS\r
+ mov ds,ax\r
+ mov ax,SCREEN_SEG ; Point es to VGA segment\r
+ mov es,ax\r
+\r
+ mov ax,[bx+MaskPtr+AlignData+si] ; DS:SI -> mask data\r
+ mov bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap\r
+ mov si,ax\r
+\r
+ mov ax,[LeftSkip] ; Skip data/mask bytes in\r
+ add bx,ax ; each row that have been clipped\r
+ add si,ax ; by the L.H.S border\r
+\r
+\r
+ mov dx,GC_INDEX ; Set bit mask for all bits from\r
+ mov ax,BIT_MASK ; VGA latches and none from CPU\r
+ out dx,ax\r
+ mov dx,SC_INDEX ; Point SC register to map mask\r
+ mov al,MAP_MASK ; in preperation for masking data\r
+ out dx,al\r
+ inc dx ; Point dx to SC data register\r
+ mov ah,byte ptr [VBMHeight] ; AH = Scanline loop counter\r
+\r
+@@RowLoop:\r
+ mov cx,[VBMWidth] ; Width in bytes across\r
+\r
+@@ColumnLoop:\r
+ lodsb\r
+ out dx,al\r
+ mov al,es:[bx] ; load latches from source bitmap\r
+ stosb ; store latches to dest. bitmap\r
+ inc bx\r
+ loop @@ColumnLoop\r
+ add bx,[DataInc]\r
+ add si,[DataInc]\r
+ add di,[NextLineIncr] ; point to start of next dest row\r
+ dec byte ptr ah ; decrement scan line counter\r
+ jnz @@RowLoop ; jump if more scanlines left\r
+\r
+ mov dx,GC_INDEX+1 ; Restore bitmask to the default -\r
+ mov al,0ffh ; all data from cpu\r
+ out dx,al\r
+ xor ax,ax\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_put_masked_vbm_clipx endp\r
+\r
+\r
+_x_put_masked_vbm_clipy proc\r
+ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword\r
+LOCAL VBMWidth,VBMHeight,TopRow,NextLineIncr:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+\r
+ mov di,[X] ; load X coord int DI and make a\r
+ mov si,di ; copy in SI\r
+\r
+\r
+ and si,3 ; Calculate pixels plane alignment\r
+ shl si,2 ; Prepare to lookup mask & data\r
+ les bx,[SrcVBM] ; ES:BX -> begining of VBM data\r
+\r
+\r
+ mov ax,es:[bx+ImageHeight] ; Get image height and save in AX\r
+\r
+\r
+\r
+ ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;\r
+\r
+ mov dx,[_TopClip] ; Compare u.l. Y coord with Top\r
+ sub dx,[Y] ; clipping border\r
+ jle @@NotTopClip ; jump if VBM not clipped from above\r
+ cmp dx,ax\r
+ jnl @@NotVisible ; jump if VBM is completely obscured\r
+ mov [TopRow],dx\r
+ sub ax,dx\r
+ add [Y],dx\r
+ jmp short @@VertClipDone\r
+\r
+ ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotVisible:\r
+ mov ax,1\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+\r
+ ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotTopClip:\r
+ mov dx,[_BottomClip]\r
+ sub dx,[Y]\r
+ js @@NotVisible\r
+ mov [TopRow],0\r
+ cmp dx,ax\r
+ jg @@VertClipDone\r
+ inc dx\r
+ mov ax,dx\r
+\r
+@@VertClipDone:\r
+\r
+\r
+ shr di,2 ; Find Byte offset of X coord\r
+ add di,[ScrnOffs] ; Add the current page offset\r
+ mov cx,es:[bx+ImageWidth] ; Get image width and save in CX\r
+ mov [VBMWidth],cx\r
+ mov [VBMHeight],ax\r
+\r
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+ mov ax,[Y] ; Calculate dest screen row\r
+ mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen\r
+ mul cx ; width then adding screen offset\r
+ add di,ax ; Add Dest Screen Row to di\r
+ sub cx,[VBMWidth]\r
+ mov [NextLineIncr],cx\r
+\r
+ mov ax,es ; copy ES to DS\r
+ mov ds,ax\r
+ mov ax,SCREEN_SEG ; Point es to VGA segment\r
+ mov es,ax\r
+\r
+ mov ax,[bx+MaskPtr+AlignData+si] ; DS:SI -> mask data\r
+ mov bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap\r
+ mov si,ax\r
+\r
+\r
+\r
+ mov ax,[VBMWidth] ; Increment DS:BX and DS:SI to\r
+ mul [TopRow] ; skip image/mask data that has\r
+ add bx,ax ; been clipped by the top border\r
+ add si,ax\r
+\r
+\r
+ mov dx,GC_INDEX ; Set bit mask for all bits from\r
+ mov ax,BIT_MASK ; VGA latches and none from CPU\r
+ out dx,ax\r
+ mov dx,SC_INDEX ; Point SC register to map mask\r
+ mov al,MAP_MASK ; in preperation for masking data\r
+ out dx,al\r
+ inc dx ; Point dx to SC data register\r
+ mov ah,byte ptr [VBMHeight] ; AH = Scanline loop counter\r
+\r
+@@RowLoop:\r
+ mov cx,[VBMWidth] ; Width in bytes across\r
+\r
+@@ColumnLoop:\r
+ lodsb\r
+ out dx,al\r
+ mov al,es:[bx] ; load latches from source bitmap\r
+ stosb ; store latches to dest. bitmap\r
+ inc bx\r
+ loop @@ColumnLoop\r
+ add di,[NextLineIncr] ; point to start of next dest row\r
+ dec byte ptr ah ; decrement scan line counter\r
+ jnz @@RowLoop ; jump if more scanlines left\r
+\r
+ mov dx,GC_INDEX+1 ; Restore bitmask to the default -\r
+ mov al,0ffh ; all data from cpu\r
+ out dx,al\r
+\r
+ xor ax,ax\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_put_masked_vbm_clipy endp\r
+\r
+_x_put_masked_vbm_clipxy proc\r
+ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword\r
+LOCAL DataInc,LeftSkip,VBMWidth,VBMHeight,TopRow,NextLineIncr:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk ; Create space for local variables\r
+ push si\r
+ push di\r
+ push ds\r
+ cld\r
+\r
+ mov di,[X] ; load X coord int DI and make a\r
+ mov si,di ; copy in SI\r
+ sar di,2 ; Find Byte offset of X coord\r
+ and si,3 ; Calculate pixels plane alignment\r
+ shl si,2 ; Prepare to lookup mask & data\r
+ les bx,[SrcVBM] ; ES:BX -> begining of VBM data\r
+\r
+ mov cx,es:[bx+ImageWidth] ; Get image width and save in CX\r
+ mov ax,es:[bx+ImageHeight] ; Get image height and save in AX\r
+\r
+\r
+\r
+ ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;\r
+\r
+ mov dx,[_TopClip] ; Compare u.l. Y coord with Top\r
+ sub dx,[Y] ; clipping border\r
+ jle @@NotTopClip ; jump if VBM not clipped from above\r
+ cmp dx,ax\r
+ jnl @@NotVisible ; jump if VBM is completely obscured\r
+ mov [TopRow],dx\r
+ sub ax,dx\r
+ add [Y],dx\r
+ jmp short @@VertClipDone\r
+\r
+ ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotVisible:\r
+ mov ax,1\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+\r
+ ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotTopClip:\r
+ mov dx,[_BottomClip]\r
+ sub dx,[Y]\r
+ js @@NotVisible\r
+ mov [TopRow],0\r
+ cmp dx,ax\r
+ jg @@VertClipDone\r
+ inc dx\r
+ mov ax,dx\r
+\r
+@@VertClipDone:\r
+\r
+ ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+\r
+ mov dx,[_LeftClip]\r
+ sub dx,di\r
+ jle @@NotLeftClip\r
+ cmp dx,cx\r
+ jnl @@NotVisible\r
+ add di,dx\r
+ mov [LeftSkip],dx\r
+ mov [DataInc],dx\r
+ sub cx,dx\r
+ jmp short @@HorizClipDone\r
+\r
+ ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
+\r
+@@NotLeftClip:\r
+ mov dx,[_RightClip]\r
+ sub dx,di\r
+ js @@NotVisible\r
+ mov [LeftSkip],0\r
+ mov [DataInc],0\r
+ cmp dx,cx\r
+ jge @@HorizClipDone\r
+ inc dx\r
+ sub cx,dx\r
+ mov [DataInc],cx\r
+ mov cx,dx\r
+\r
+@@HorizClipDone:\r
+\r
+ add di,[ScrnOffs] ; Add the current page offset\r
+ mov [VBMWidth],cx\r
+ mov [VBMHeight],ax\r
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+\r
+ mov ax,[Y] ; Calculate dest screen row\r
+ mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen\r
+ mul cx ; width then adding screen offset\r
+ add di,ax ; Add Dest Screen Row to di\r
+ sub cx,[VBMWidth]\r
+ mov [NextLineIncr],cx\r
+\r
+ mov ax,es ; copy ES to DS\r
+ mov ds,ax\r
+ mov ax,SCREEN_SEG ; Point es to VGA segment\r
+ mov es,ax\r
+\r
+ mov ax,[bx+MaskPtr+AlignData+si] ; DS:SI -> mask data\r
+ mov bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap\r
+ mov si,ax\r
+\r
+\r
+\r
+ mov ax,[VBMWidth] ; Increment DS:BX and DS:SI to\r
+ add ax,[DataInc] ; skip image/mask data that has\r
+ mul [TopRow] ; been clipped by the top border\r
+ add ax,[LeftSkip] ; Skip also data/mask bytes in\r
+ add bx,ax ; each row that have been clipped\r
+ add si,ax ; by the L.H.S border\r
+\r
+\r
+ mov dx,GC_INDEX ; Set bit mask for all bits from\r
+ mov ax,BIT_MASK ; VGA latches and none from CPU\r
+ out dx,ax\r
+ mov dx,SC_INDEX ; Point SC register to map mask\r
+ mov al,MAP_MASK ; in preperation for masking data\r
+ out dx,al\r
+ inc dx ; Point dx to SC data register\r
+ mov ah,byte ptr [VBMHeight] ; AH = Scanline loop counter\r
+\r
+@@RowLoop:\r
+ mov cx,[VBMWidth] ; Width in bytes across\r
+\r
+@@ColumnLoop:\r
+ lodsb\r
+ out dx,al\r
+ mov al,es:[bx] ; load latches from source bitmap\r
+ stosb ; store latches to dest. bitmap\r
+ inc bx\r
+ loop @@ColumnLoop\r
+ add bx,[DataInc]\r
+ add si,[DataInc]\r
+ add di,[NextLineIncr] ; point to start of next dest row\r
+ dec byte ptr ah ; decrement scan line counter\r
+ jnz @@RowLoop ; jump if more scanlines left\r
+\r
+ mov dx,GC_INDEX+1 ; Restore bitmask to the default -\r
+ mov al,0ffh ; all data from cpu\r
+ out dx,al\r
+ xor ax,ax\r
+ pop ds ; restore data segment\r
+ pop di ; restore registers\r
+ pop si\r
+ mov sp,bp ; dealloc local variables\r
+ pop bp\r
+ ret\r
+_x_put_masked_vbm_clipxy endp\r
+\r
+\r
+ end\r
+\r
+\1a
\ No newline at end of file
--- /dev/null
+/*-----------------------------------------------------------------------\r
+;\r
+; XVBITMAP - header file\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;\r
+; Terminology & notes:\r
+; VRAM == Video RAM\r
+; SRAM == System RAM\r
+; X coordinates are in pixels unless explicitly stated\r
+;\r
+;-----------------------------------------------------------------------*/\r
+\r
+#ifndef _XVBITMAP_H_\r
+#define _XVBITMAP_H_\r
+\r
+\r
+/* FUNCTIONS =========================================================== */\r
+\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+\r
+\r
+void x_put_masked_vbm( /* Copy a planar bitmap from SRAM masking */\r
+ int X, /* only non zero pixels to VRAM */\r
+ int Y,\r
+ WORD ScrnOffs,\r
+ BYTE far * VBitmap);\r
+\r
+int x_put_masked_vbm_clipx(/* Copy a planar bitmap from SRAM masking */\r
+ int X, /* only non zero pixels to VRAM. Clip X */\r
+ int Y,\r
+ WORD ScrnOffs,\r
+ BYTE far * VBitmap);\r
+\r
+int x_put_masked_vbm_clipy(/* Copy a planar bitmap from SRAM masking */\r
+ int X, /* only non zero pixels to VRAM. Clip Y */\r
+ int Y,\r
+ WORD ScrnOffs,\r
+ BYTE far * VBitmap);\r
+\r
+int x_put_masked_vbm_clipxy(/* Copy a planar bitmap from SRAM masking */\r
+ int X, /* only non zero pixels to VRAM. Clip X & Y */\r
+ int Y,\r
+ WORD ScrnOffs,\r
+ BYTE far * VBitmap);\r
+\r
+char far * x_make_vbm(\r
+ char far *lbm,\r
+ WORD *VramStart);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XVBITMAP - Include file\r
+;\r
+; XVBITMAP.ASM export functions\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+ global _x_store_vbm_image :proc\r
+ global _x_put_masked_vbm :proc\r
+ global _x_put_masked_vbm_clipx :proc\r
+ global _x_put_masked_vbm_clipy :proc\r
+ global _x_put_masked_vbm_clipxy :proc\r
+\1a
\ No newline at end of file
--- /dev/null
+;-----------------------------------------------------------------------\r
+;\r
+; XVBMTOOL - Include file\r
+;\r
+; XVBMTOOL.ASM export functions\r
+;\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+; ****** Aeronautical Research Laboratory ****************\r
+; ****** Defence Science and Technology Organisation ****************\r
+; ****** Australia ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+ global _x_store_vbm_image :proc\r
+\1a
\ No newline at end of file
--- /dev/null
+; MODULE XVSYNC\r
+; Xlib comptible vsync handler\r
+; Written by Tore Bastiansen\r
+; based on REND386 by Dave Stampe and Bernie Roehl\r
+\r
+include xlib.inc\r
+include xmain.inc\r
+include xvsync.inc\r
+\r
+\r
+TIMER_VECT equ 08h\r
+\r
+PIC_CMD equ 20h\r
+NONSPEC_EOI equ 20h\r
+TIMER_MODE equ 34h\r
+TIMER_CONTROL equ 43h\r
+TIMER_0 equ 40h\r
+\r
+LATCH_COUNT equ 00h\r
+\r
+INT_IN_ADVANCE equ 100\r
+\r
+DOS_GETVECT equ 3500h\r
+DOS_SETVECT equ 2500h\r
+\r
+\r
+.data\r
+_TicksPerSecond dw 0\r
+_VsyncIntTicks label dword\r
+VsyncIntTicksLo dw 0\r
+VsyncIntTicksHi dw 0\r
+_VsyncPeriod dw 0 ;Time (in clicks) between each vsync\r
+ ;1 click = 1.193 microseconds\r
+\r
+ClockRate dw 0 ;Clock rate (in clicks) for timer 0\r
+ClockCounter dw 0 ;Counts total clicks modulo 65536\r
+UserVsyncHandler label dword ;Pointer to user routine called\r
+UserVsyncOffs dw 0 ;called once each vsync period.\r
+UserVsyncSeg dw 0\r
+InUserHandler dw 0\r
+ db 100h dup(?)\r
+LocalStack label byte ;Local stack for user handler\r
+StackSeg dw 0\r
+StackPtr dw 0\r
+\r
+\r
+ElapsedVrts dw 0\r
+VrtsToSkip dw 1\r
+\r
+.code\r
+get_vsync_period proc near\r
+ mov al,TIMER_MODE ;Start timer\r
+ out TIMER_CONTROL,al\r
+ mov al,0\r
+ out TIMER_0,al\r
+ out TIMER_0,al\r
+\r
+ WaitVsyncStart\r
+\r
+ mov al,LATCH_COUNT\r
+ out TIMER_CONTROL,al\r
+ in al,TIMER_0\r
+ mov cl,al\r
+ in al,TIMER_0\r
+ mov ch,al ;cx=65536-clicks\r
+\r
+ WaitVsyncStart\r
+\r
+ mov al,LATCH_COUNT\r
+ out TIMER_CONTROL,al\r
+ in al,TIMER_0\r
+ mov dl,al\r
+ in al,TIMER_0\r
+ mov dh,al ;dx=65536-clicks\r
+\r
+ sub cx,dx ;cx=clicks between two vsyncs\r
+ mov ax,cx ;return in ax\r
+ ret\r
+get_vsync_period endp\r
+\r
+vsync_int proc far\r
+ pusha ;Save regs\r
+ push ds\r
+ push es\r
+\r
+ mov ax,@data ;Set the right datasegment\r
+ mov ds,ax\r
+ add [VsyncIntTicksLo],1 ;Increment _VsyncIntTicks\r
+ adc [VsyncIntTicksHi],0\r
+\r
+ inc [ElapsedVrts]\r
+ mov cx,[ElapsedVrts]\r
+ cmp cx,[VrtsToSkip]\r
+ jl @@StopClock\r
+\r
+ cmp [_StartAddressFlag],1 ;Change in start address\r
+ jne @@StopClock\r
+\r
+ mov dx,CRTC_INDEX ;Yes, set start address\r
+ mov ax,[_WaitingStartLow]\r
+ mov bx,[_WaitingStartHigh]\r
+ out dx,ax\r
+ mov ax,bx\r
+ out dx,ax\r
+\r
+@@StopClock:\r
+ cli\r
+ mov al,TIMER_MODE ;Stop the timer\r
+ out TIMER_CONTROL,al ;Dont want any interrupts\r
+ mov al,255\r
+ out TIMER_0,al\r
+ out TIMER_0,al\r
+ sti\r
+\r
+ cli\r
+ mov dx,INPUT_STATUS_0 ;Wait for vsync\r
+@@WaitVS:\r
+ in al,dx\r
+ test al,08h\r
+ jz @@WaitVS\r
+\r
+ mov al,TIMER_MODE ;Start timer again\r
+ out TIMER_CONTROL,al\r
+ mov ax,[ClockRate]\r
+ out TIMER_0,al\r
+ mov al,ah\r
+ out TIMER_0,al\r
+\r
+ cmp cx,[VrtsToSkip]\r
+ jl @@PaletteInt\r
+\r
+ cmp [_StartAddressFlag],1 ;Any change in start address ?\r
+ jne @@PaletteInt\r
+\r
+ xor cx,cx\r
+ mov [ElapsedVrts],cx\r
+\r
+ mov ax,[_WaitingPelPan] ;Yes, set pel pan register\r
+ mov dx,AC_INDEX\r
+ out dx,al\r
+ mov al,ah\r
+ out dx,al\r
+ mov [_StartAddressFlag],0\r
+\r
+@@PaletteInt:\r
+ cmp [_VsyncPaletteCount],0 ;Any changes in the palette\r
+ je @@MouseInt\r
+ mov si, offset _VsyncPaletteBuffer ;Yes\r
+ mov cx, [_VsyncPaletteCount]\r
+ mov ax, [_VsyncPaletteStart]\r
+ mov dx, DAC_WRITE_INDEX\r
+ out dx, al\r
+ mov dx, DAC_DATA\r
+\r
+@@DacOutLoop:\r
+ outsb\r
+ outsb\r
+ outsb\r
+ loop @@DacOutLoop\r
+ mov [_VsyncPaletteCount],0\r
+\r
+@@MouseInt:\r
+ cmp [_MouseRefreshFlag],1 ; Does the mouse need refresh\r
+ jne @@UserInt\r
+ call dword ptr [_MouseVsyncHandler] ; Yes\r
+ ;(this is not yet implemented)\r
+\r
+@@UserInt:\r
+ cmp [UserVsyncSeg], 0 ;Is the a user interrupt routine?\r
+ je short @@Sim182\r
+ cmp [InUserHandler],0 ;Yes, but is it already active?\r
+ jne short @@Sim182\r
+ mov [InUserHandler],1 ;No, mark it as active\r
+ mov [StackSeg],ss ;make a local stack\r
+ mov [StackPtr],sp\r
+ push ds\r
+ pop ss\r
+ mov sp, offset LocalStack\r
+ sti\r
+ call dword ptr [UserVsyncHandler]\r
+ cli\r
+ mov sp, [StackPtr] ;Restore old stack\r
+ mov ss, [StackSeg]\r
+ mov [InUserHandler],0 ;Mark as not active\r
+\r
+; SIM 18.2 Hz\r
+@@Sim182:\r
+ mov ax,[_VsyncPeriod] ;Count number of clicks\r
+ add [ClockCounter],ax ;If it is bigger than 65536\r
+ jnc short @@DontChainOld\r
+ pop es ;more than 1/18.2 secs has gone\r
+ pop ds\r
+ popa\r
+ sti\r
+ db 0eah ; jmp instruction\r
+ OldTimerInt dd 0 ; Pointer to old int8 routine\r
+ ; Selfmodyfiing code\r
+ ;jmp dword ptr [OldTimerInt] Chain to old\r
+@@DontChainOld:\r
+\r
+; CLEAN UP AND RETURN\r
+ mov al,NONSPEC_EOI\r
+ out PIC_CMD,al\r
+\r
+\r
+ pop es\r
+ pop ds\r
+ popa\r
+ sti\r
+ iret\r
+vsync_int endp\r
+\r
+\r
+_x_install_vsync_handler proc\r
+ARG VrtSkipCount:word\r
+ push bp\r
+ mov bp,sp\r
+ mov ax,[VrtSkipCount]\r
+ or ax,ax\r
+ jnz @@NonZeroCount\r
+ mov ax,1\r
+@@NonZeroCount:\r
+ mov [VrtsToSkip],ax\r
+ mov [ElapsedVrts],0\r
+ cmp [_VsyncHandlerActive],TRUE ;Is it already active\r
+ je short @@Return\r
+ call get_vsync_period ;no, get the vsync period\r
+\r
+ mov [_VsyncPeriod],ax\r
+ sub ax,INT_IN_ADVANCE ;We need a little extra\r
+ mov [ClockRate],ax ;time\r
+\r
+ mov dx,18 ;dx:ax=1193000\r
+ mov ax,13352\r
+ idiv [_VsyncPeriod]\r
+ mov [_TicksPerSecond],ax ;1193/_VsyncPeriod\r
+\r
+ mov word ptr [_VsyncIntTicks],0\r
+ mov word ptr [_VsyncIntTicks+2],0\r
+\r
+ cli\r
+ mov ax, DOS_GETVECT+TIMER_VECT ;Get address of old timer int\r
+ int 21h\r
+ mov ax,es\r
+ mov word ptr cs:[OldTimerInt],bx ;Store in OldTimerInt\r
+ mov word ptr cs:[OldTimerInt+2],ax\r
+\r
+ mov [_VsyncHandlerActive],TRUE ;Mark handler as active\r
+ mov ax,DOS_SETVECT+TIMER_VECT ;Set the new timer int\r
+ push ds\r
+ mov dx,seg vsync_int\r
+ mov ds,dx\r
+ mov dx,offset vsync_int\r
+ int 21h\r
+ pop ds\r
+\r
+ mov al,TIMER_MODE ;Reprogram timer 0\r
+ out TIMER_CONTROL,al\r
+ mov ax,ClockRate\r
+ out TIMER_0,al\r
+ mov al,ah\r
+ out TIMER_0,al\r
+ sti\r
+@@Return:\r
+ pop bp\r
+ ret\r
+_x_install_vsync_handler endp\r
+\r
+_x_remove_vsync_handler proc\r
+ cmp [_VsyncHandlerActive],FALSE\r
+ je short @@Return\r
+ mov dx, word ptr cs:[OldTimerInt]\r
+ mov ax, word ptr cs:[OldTimerInt+2]\r
+ push ds\r
+ mov ds,ax\r
+ mov ax,DOS_SETVECT+TIMER_VECT ;Restore the old timer int\r
+ cli\r
+ int 21h\r
+ pop ds\r
+ mov al,TIMER_MODE ;Restore timer 0\r
+ out TIMER_CONTROL,al\r
+ mov al,0\r
+ out TIMER_0,al\r
+ out TIMER_0,al\r
+ sti\r
+@@Return:\r
+ ret\r
+_x_remove_vsync_handler endp\r
+\r
+\r
+; WARNING: The user vsync handler cannot use the 386 specific registers\r
+; (EAX,EBX,ECX,EDX,ESI,EDI,ESP,EBP,FS,GS)\r
+; whithout saving them first.\r
+; It must not do any drawing.\r
+; Only 256 butes of stack is provided.\r
+\r
+_x_set_user_vsync_handler proc\r
+ARG handler_proc:dword\r
+ push bp\r
+ mov bp,sp\r
+ mov ax, word ptr [handler_proc]\r
+ mov dx, word ptr [handler_proc+2]\r
+ cli\r
+ mov word ptr [UserVsyncHandler],ax\r
+ mov word ptr [UserVsyncHandler+2],dx\r
+ sti\r
+ pop bp\r
+ ret\r
+_x_set_user_vsync_handler endp\r
+\r
+end\r
--- /dev/null
+#ifndef _XVSYNC_H_\r
+#define _XVSYNC_H_\r
+\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+ void x_install_vsync_handler(int skipcount);\r
+ void x_remove_vsync_handler(void);\r
+ void x_set_user_vsync_handler(void far (*)());\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+extern WORD TicksPerSecond;\r
+extern volatile long VsyncIntTicks;\r
+extern WORD VsyncPeriod;\r
+\r
+#endif\r
--- /dev/null
+global _x_install_vsync_handler :proc\r
+global _x_remove_vsync_handler :proc\r
+global _x_set_user_vsync_handler :proc\r
+global _TicksPerSecond :word\r
+global _VsyncIntTicks :dword\r
+global _VsyncPeriod :word\r
--- /dev/null
+pkzip -a xlib06.zip MAKEFILE\r
+\r
+pkzip -a xlib06.zip XBEZIER.ASM\r
+pkzip -a xlib06.zip XBMTOOLS.ASM\r
+pkzip -a xlib06.zip XCBITMAP.ASM\r
+pkzip -a xlib06.zip XCOMPPBM.ASM\r
+pkzip -a xlib06.zip XDETECT.ASM\r
+pkzip -a xlib06.zip XFILEIO.ASM\r
+pkzip -a xlib06.zip XLINE.ASM\r
+pkzip -a xlib06.zip XMAIN.ASM\r
+pkzip -a xlib06.zip XMOUSE.ASM\r
+pkzip -a xlib06.zip XPAL.ASM\r
+pkzip -a xlib06.zip XPBITMAP.ASM\r
+pkzip -a xlib06.zip XPBMCLIP.ASM\r
+pkzip -a xlib06.zip XPOINT.ASM\r
+pkzip -a xlib06.zip XRECT.ASM\r
+pkzip -a xlib06.zip XRLETOOL.ASM\r
+pkzip -a xlib06.zip XTEXT.ASM\r
+pkzip -a xlib06.zip XVBITMAP.ASM\r
+pkzip -a xlib06.zip XCIRCLE.ASM\r
+pkzip -a xlib06.zip XCLIPPBM.ASM\r
+pkzip -a xlib06.zip XPOLYGON.ASM\r
+pkzip -a xlib06.zip XFILL.ASM\r
+pkzip -a xlib06.zip XVSYNC.ASM\r
+\r
+pkzip -a xlib06.zip XCBITM32.C\r
+pkzip -a xlib06.zip DEMO1.C\r
+pkzip -a xlib06.zip DEMO2.C\r
+pkzip -a xlib06.zip DEMO3.C\r
+pkzip -a xlib06.zip DEMO4.C\r
+pkzip -a xlib06.zip DEMO5.C\r
+pkzip -a xlib06.zip DEMO6.C\r
+pkzip -a xlib06.zip DEMO7.C\r
+pkzip -a xlib06.zip DEMO8.C\r
+pkzip -a xlib06.zip DEMO9.C\r
+pkzip -a xlib06.zip DEMO10.CPP\r
+\r
+pkzip -a xlib06.zip XMAKEVBM.C\r
+pkzip -a xlib06.zip XPRINTF.C\r
+pkzip -a xlib06.zip UPDATES.DOC\r
+pkzip -a xlib06.zip XLIBREF1.DOC\r
+pkzip -a xlib06.zip XLIBREF2.DOC\r
+pkzip -a xlib06.zip DEMO7.EXE\r
+pkzip -a xlib06.zip DEMO1.EXE\r
+pkzip -a xlib06.zip DEMO2.EXE\r
+pkzip -a xlib06.zip DEMO3.EXE\r
+pkzip -a xlib06.zip DEMO4.EXE\r
+pkzip -a xlib06.zip DEMO5.EXE\r
+pkzip -a xlib06.zip DEMO6.EXE\r
+pkzip -a xlib06.zip DEMO8.EXE\r
+pkzip -a xlib06.zip DEMO9.EXE\r
+pkzip -a xlib06.zip DEMO10.EXE\r
+\r
+pkzip -a xlib06.zip FIXED6X8.FNT\r
+pkzip -a xlib06.zip VAR6X8.FNT\r
+pkzip -a xlib06.zip VARSWISL.FNT\r
+pkzip -a xlib06.zip VARSWISB.FNT\r
+pkzip -a xlib06.zip TIMPANI.FNT\r
+pkzip -a xlib06.zip MODERNB.FNT\r
+pkzip -a xlib06.zip CRISP6X9.FNT\r
+pkzip -a xlib06.zip TINY4.FNT\r
+pkzip -a xlib06.zip SMALTHIN.FNT\r
+\r
+pkzip -a xlib06.zip XBEZIER.H\r
+pkzip -a xlib06.zip XBMTOOLS.H\r
+pkzip -a xlib06.zip XCBITMAP.H\r
+pkzip -a xlib06.zip XCOMPPBM.H\r
+pkzip -a xlib06.zip XDETECT.H\r
+pkzip -a xlib06.zip XFILEIO.H\r
+pkzip -a xlib06.zip XLIB.H\r
+pkzip -a xlib06.zip XLIB_ALL.H\r
+pkzip -a xlib06.zip XLINE.H\r
+pkzip -a xlib06.zip XMOUSE.H\r
+pkzip -a xlib06.zip XPAL.H\r
+pkzip -a xlib06.zip XPBITMAP.H\r
+pkzip -a xlib06.zip XPBMCLIP.H\r
+pkzip -a xlib06.zip XPOINT.H\r
+pkzip -a xlib06.zip XRECT.H\r
+pkzip -a xlib06.zip XRLETOOL.H\r
+pkzip -a xlib06.zip XTEXT.H\r
+pkzip -a xlib06.zip XVBITMAP.H\r
+pkzip -a xlib06.zip XCIRCLE.H\r
+pkzip -a xlib06.zip XCLIPPBM.H\r
+pkzip -a xlib06.zip XPOLYGON.H\r
+pkzip -a xlib06.zip XFILL.H\r
+pkzip -a xlib06.zip XVSYNC.H\r
+pkzip -a xlib06.zip XCBITM32.H\r
+\r
+pkzip -a xlib06.zip MODEL.INC\r
+pkzip -a xlib06.zip XBEZIER.INC\r
+pkzip -a xlib06.zip XBMTOOLS.INC\r
+pkzip -a xlib06.zip XCBITMAP.INC\r
+pkzip -a xlib06.zip XCOMPPBM.INC\r
+pkzip -a xlib06.zip XDETECT.INC\r
+pkzip -a xlib06.zip XFILEIO.INC\r
+pkzip -a xlib06.zip XLIB.INC\r
+pkzip -a xlib06.zip XLINE.INC\r
+pkzip -a xlib06.zip XMAIN.INC\r
+pkzip -a xlib06.zip XPAL.INC\r
+pkzip -a xlib06.zip XPBITMAP.INC\r
+pkzip -a xlib06.zip XPBMCLIP.INC\r
+pkzip -a xlib06.zip XPOINT.INC\r
+pkzip -a xlib06.zip XRECT.INC\r
+pkzip -a xlib06.zip XRLETOOL.INC\r
+pkzip -a xlib06.zip XTEXT.INC\r
+pkzip -a xlib06.zip XVBITMAP.INC\r
+pkzip -a xlib06.zip XVBMTOOL.INC\r
+pkzip -a xlib06.zip XCIRCLE.INC\r
+pkzip -a xlib06.zip XCLIPPBM.INC\r
+pkzip -a xlib06.zip XPOLYGON.INC\r
+pkzip -a xlib06.zip XFILL.INC\r
+pkzip -a xlib06.zip XVSYNC.INC\r
+\r
+pkzip -a xlib06.zip XLIB04S.LIB\r
+pkzip -a xlib06.zip XLIB04C.LIB\r
+pkzip -a xlib06.zip XLIB04L.LIB\r
+pkzip -a xlib06.zip ZIP.BAT\r
+\r
--- /dev/null
+# makefile MAKE V2.0 or higher\r
+\r
+\r
+# Set the required model here, either s, c or l (LOWER CASE ONLY)\r
+#\r
+\r
+MODEL=h\r
+\r
+XLIB_VERSION=06\r
+\r
+# Set the compiler: either BCC or TCC\r
+#\r
+CC=wcc\r
+\r
+TLIB=wlib\r
+\r
+AFLAGS = /ml /zi /d$(MODEL)\r
+CFLAGS = -m$(MODEL)\r
+CPPFLAGS= -m$(MODEL)\r
+LDFLAGS = -m$(MODEL)\r
+\r
+\r
+%.c.obj:\r
+ $(CC) -c $(CFLAGS) $<\r
+\r
+%.asm.obj:\r
+ wasm $(AFLAGS) $* \\r
+\r
+\r
+XLIBOBJS= xprintf.obj xpoint.obj xline.obj xmain.obj xpal.obj xpbitmap.obj \\r
+ xrect.obj xtext.obj xcbitmap.obj xdetect.obj xbmtools.obj \\r
+ xfileio.obj xrletool.obj xbezier.obj xpbmclip.obj xvbitmap.obj \\r
+ xmakevbm.obj xmouse.obj xcircle.obj xclippbm.obj xcomppbm.obj \\r
+ xpolygon.obj xvsync.obj xfill.obj xcbitm32.obj\r
+\r
+\r
+all: demo1.exe demo2.exe demo3.exe demo4.exe demo5.exe demo6.exe demo7.exe \\r
+ demo8.exe demo9.exe demo10.exe\r
+\r
+demo1.exe : demo1.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+ $(CC) $(CFLAGS) demo1.obj xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo2.exe : demo2.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+ $(CC) $(CFLAGS) demo2.obj xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo3.exe : demo3.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+ $(CC) $(CFLAGS) demo3.obj xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo4.exe : demo4.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+ $(CC) $(CFLAGS) demo4.obj xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo5.exe : demo5.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+ $(CC) $(CFLAGS) demo5.obj xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo6.exe : demo6.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+ $(CC) $(CFLAGS) demo6.obj xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo7.exe : demo7.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+ $(CC) $(CFLAGS) demo7.obj xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo8.exe : demo8.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+ $(CC) $(CFLAGS) demo8.obj xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo9.exe : demo9.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+ $(CC) $(CFLAGS) demo9.obj xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo10.exe : demo10.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+ $(CC) $(CFLAGS) demo10.obj xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+\r
+xlib$(XLIB_VERSION)$(MODEL).lib: $(XLIBOBJS)\r
+ $(TLIB) xlib$(XLIB_VERSION)$(MODEL).lib \\r
+ -+xmain -+xpoint -+xline -+xpal -+xrect -+xtext -+xprintf -+xbezier -+xfill -+xcbitm32\r
+ $(TLIB) xlib$(XLIB_VERSION)$(MODEL).lib \\r
+ -+xpbitmap -+xcbitmap -+xdetect -+xbmtools -+xfileio -+xrletool -+xpbmclip\r
+ $(TLIB) xlib$(XLIB_VERSION)$(MODEL).lib \\r
+ -+xvbitmap -+xmakevbm -+xmouse -+xcircle -+xclippbm -+xcomppbm -+xpolygon -+xvsync\r
+\r
+# Object modules\r
+\r
+xprintf.obj : xprintf.c\r
+xpoint.obj : xpoint.asm xpoint.inc xlib.inc model.inc\r
+xline.obj : xline.asm xline.inc xlib.inc model.inc\r
+xmain.obj : xmain.asm xmain.inc xlib.inc model.inc\r
+xpal.obj : xpal.asm xpal.inc xlib.inc model.inc\r
+xpbitmap.obj: xpbitmap.asm xpbitmap.inc xlib.inc model.inc\r
+xpbmclip.obj: xpbmclip.asm xpbmclip.inc xlib.inc model.inc\r
+xclippbm.obj: xclippbm.asm xclippbm.inc xlib.inc model.inc\r
+xrect.obj : xpal.asm xpal.inc xlib.inc model.inc\r
+xtext.obj : xtext.asm xtext.inc xlib.inc model.inc\r
+xcbitmap.obj: xcbitmap.asm xcbitmap.inc xlib.inc model.inc\r
+xcomppbm.obj: xcomppbm.asm xcomppbm.inc xlib.inc model.inc\r
+xcbitm32.obj: xcbitm32.c \r
+xdetect.obj : xdetect.asm xdetect.inc model.inc\r
+xbmtools.obj: xbmtools.asm xbmtools.inc model.inc\r
+xfileio.obj : xfileio.asm xfileio.inc model.inc\r
+xrletool.obj: xrletool.asm xrletool.inc model.inc\r
+xvbitmap.obj: xvbitmap.asm xvbitmap.inc xlib.inc model.inc\r
+xmakevbm.obj: xmakevbm.c xvbitmap.h\r
+xmouse.obj : xmouse.asm xlib.inc model.inc\r
+xcircle.obj : xcircle.asm xcircle.inc xlib.inc model.inc\r
+xpolygon.obj: xpolygon.asm xpolygon.inc xlib.inc model.inc\r
+xvsync.obj : xvsync.asm xvsync.inc xlib.inc model.inc\r
+xfill.obj : xfill.asm xfill.inc xlib.inc model.inc\r