]> 4ch.mooo.com Git - 16.git/commitdiff
added xlib to the project and i gotta convert the damn makefile -.-
authorsparky4 <sparky4@cock.li>
Wed, 11 Nov 2015 09:42:14 +0000 (03:42 -0600)
committersparky4 <sparky4@cock.li>
Wed, 11 Nov 2015 09:42:14 +0000 (03:42 -0600)
106 files changed:
16/xlib/crisp6x9.fnt [new file with mode: 0755]
16/xlib/demo1.c [new file with mode: 0755]
16/xlib/demo1.exe [new file with mode: 0755]
16/xlib/demo10.exe [new file with mode: 0755]
16/xlib/demo2.c [new file with mode: 0755]
16/xlib/demo2.exe [new file with mode: 0755]
16/xlib/demo3.c [new file with mode: 0755]
16/xlib/demo3.exe [new file with mode: 0755]
16/xlib/demo4.c [new file with mode: 0755]
16/xlib/demo4.exe [new file with mode: 0755]
16/xlib/demo5.c [new file with mode: 0755]
16/xlib/demo5.exe [new file with mode: 0755]
16/xlib/demo6.c [new file with mode: 0755]
16/xlib/demo6.exe [new file with mode: 0755]
16/xlib/demo7.c [new file with mode: 0755]
16/xlib/demo7.exe [new file with mode: 0755]
16/xlib/demo8.c [new file with mode: 0755]
16/xlib/demo8.exe [new file with mode: 0755]
16/xlib/demo9.exe [new file with mode: 0755]
16/xlib/fixed6x8.fnt [new file with mode: 0755]
16/xlib/makefile [new file with mode: 0755]
16/xlib/model.inc [new file with mode: 0755]
16/xlib/modernb.fnt [new file with mode: 0755]
16/xlib/readme.txt [new file with mode: 0755]
16/xlib/smalthin.fnt [new file with mode: 0755]
16/xlib/timpani.fnt [new file with mode: 0755]
16/xlib/tiny4.fnt [new file with mode: 0755]
16/xlib/updates.doc [new file with mode: 0755]
16/xlib/var6x8.fnt [new file with mode: 0755]
16/xlib/varswisb.fnt [new file with mode: 0755]
16/xlib/varswisl.fnt [new file with mode: 0755]
16/xlib/xbezier.asm [new file with mode: 0755]
16/xlib/xbezier.h [new file with mode: 0755]
16/xlib/xbezier.inc [new file with mode: 0755]
16/xlib/xbmtools.asm [new file with mode: 0755]
16/xlib/xbmtools.h [new file with mode: 0755]
16/xlib/xbmtools.inc [new file with mode: 0755]
16/xlib/xcbitm32.c [new file with mode: 0755]
16/xlib/xcbitm32.h [new file with mode: 0755]
16/xlib/xcbitmap.asm [new file with mode: 0755]
16/xlib/xcbitmap.h [new file with mode: 0755]
16/xlib/xcbitmap.inc [new file with mode: 0755]
16/xlib/xcircle.asm [new file with mode: 0755]
16/xlib/xcircle.h [new file with mode: 0755]
16/xlib/xcircle.inc [new file with mode: 0755]
16/xlib/xclippbm.asm [new file with mode: 0755]
16/xlib/xclippbm.h [new file with mode: 0755]
16/xlib/xclippbm.inc [new file with mode: 0755]
16/xlib/xcomppbm.asm [new file with mode: 0755]
16/xlib/xcomppbm.h [new file with mode: 0755]
16/xlib/xcomppbm.inc [new file with mode: 0755]
16/xlib/xdetect.asm [new file with mode: 0755]
16/xlib/xdetect.h [new file with mode: 0755]
16/xlib/xdetect.inc [new file with mode: 0755]
16/xlib/xfileio.asm [new file with mode: 0755]
16/xlib/xfileio.h [new file with mode: 0755]
16/xlib/xfileio.inc [new file with mode: 0755]
16/xlib/xfill.asm [new file with mode: 0755]
16/xlib/xfill.h [new file with mode: 0755]
16/xlib/xfill.inc [new file with mode: 0755]
16/xlib/xlib.h [new file with mode: 0755]
16/xlib/xlib.inc [new file with mode: 0755]
16/xlib/xlib_all.h [new file with mode: 0755]
16/xlib/xlibref1.doc [new file with mode: 0755]
16/xlib/xlibref2.doc [new file with mode: 0755]
16/xlib/xline.asm [new file with mode: 0755]
16/xlib/xline.h [new file with mode: 0755]
16/xlib/xline.inc [new file with mode: 0755]
16/xlib/xmain.asm [new file with mode: 0755]
16/xlib/xmain.inc [new file with mode: 0755]
16/xlib/xmakevbm.c [new file with mode: 0755]
16/xlib/xmouse.asm [new file with mode: 0755]
16/xlib/xmouse.h [new file with mode: 0755]
16/xlib/xpal.asm [new file with mode: 0755]
16/xlib/xpal.h [new file with mode: 0755]
16/xlib/xpal.inc [new file with mode: 0755]
16/xlib/xpbitmap.asm [new file with mode: 0755]
16/xlib/xpbitmap.h [new file with mode: 0755]
16/xlib/xpbitmap.inc [new file with mode: 0755]
16/xlib/xpbmclip.asm [new file with mode: 0755]
16/xlib/xpbmclip.h [new file with mode: 0755]
16/xlib/xpbmclip.inc [new file with mode: 0755]
16/xlib/xpoint.asm [new file with mode: 0755]
16/xlib/xpoint.h [new file with mode: 0755]
16/xlib/xpoint.inc [new file with mode: 0755]
16/xlib/xpolygon.asm [new file with mode: 0755]
16/xlib/xpolygon.h [new file with mode: 0755]
16/xlib/xpolygon.inc [new file with mode: 0755]
16/xlib/xprintf.c [new file with mode: 0755]
16/xlib/xrect.asm [new file with mode: 0755]
16/xlib/xrect.h [new file with mode: 0755]
16/xlib/xrect.inc [new file with mode: 0755]
16/xlib/xrletool.asm [new file with mode: 0755]
16/xlib/xrletool.h [new file with mode: 0755]
16/xlib/xrletool.inc [new file with mode: 0755]
16/xlib/xtext.asm [new file with mode: 0755]
16/xlib/xtext.h [new file with mode: 0755]
16/xlib/xtext.inc [new file with mode: 0755]
16/xlib/xvbitmap.asm [new file with mode: 0755]
16/xlib/xvbitmap.h [new file with mode: 0755]
16/xlib/xvbitmap.inc [new file with mode: 0755]
16/xlib/xvbmtool.inc [new file with mode: 0755]
16/xlib/xvsync.asm [new file with mode: 0755]
16/xlib/xvsync.h [new file with mode: 0755]
16/xlib/xvsync.inc [new file with mode: 0755]
16/xlib/zip.bat [new file with mode: 0755]

diff --git a/16/xlib/crisp6x9.fnt b/16/xlib/crisp6x9.fnt
new file mode 100755 (executable)
index 0000000..0b8a209
Binary files /dev/null and b/16/xlib/crisp6x9.fnt differ
diff --git a/16/xlib/demo1.c b/16/xlib/demo1.c
new file mode 100755 (executable)
index 0000000..0ba8c1a
--- /dev/null
@@ -0,0 +1,571 @@
+/* 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
diff --git a/16/xlib/demo1.exe b/16/xlib/demo1.exe
new file mode 100755 (executable)
index 0000000..7d8a4d6
Binary files /dev/null and b/16/xlib/demo1.exe differ
diff --git a/16/xlib/demo10.exe b/16/xlib/demo10.exe
new file mode 100755 (executable)
index 0000000..3f1b352
Binary files /dev/null and b/16/xlib/demo10.exe differ
diff --git a/16/xlib/demo2.c b/16/xlib/demo2.c
new file mode 100755 (executable)
index 0000000..9926e9f
--- /dev/null
@@ -0,0 +1,221 @@
+/*************************************************************************\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
diff --git a/16/xlib/demo2.exe b/16/xlib/demo2.exe
new file mode 100755 (executable)
index 0000000..d6dfd06
Binary files /dev/null and b/16/xlib/demo2.exe differ
diff --git a/16/xlib/demo3.c b/16/xlib/demo3.c
new file mode 100755 (executable)
index 0000000..cfc6559
--- /dev/null
@@ -0,0 +1,62 @@
+#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
diff --git a/16/xlib/demo3.exe b/16/xlib/demo3.exe
new file mode 100755 (executable)
index 0000000..ef3a06a
Binary files /dev/null and b/16/xlib/demo3.exe differ
diff --git a/16/xlib/demo4.c b/16/xlib/demo4.c
new file mode 100755 (executable)
index 0000000..b91a576
--- /dev/null
@@ -0,0 +1,170 @@
+/*************************************************************************\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
diff --git a/16/xlib/demo4.exe b/16/xlib/demo4.exe
new file mode 100755 (executable)
index 0000000..54c567d
Binary files /dev/null and b/16/xlib/demo4.exe differ
diff --git a/16/xlib/demo5.c b/16/xlib/demo5.c
new file mode 100755 (executable)
index 0000000..6bc35d5
--- /dev/null
@@ -0,0 +1,148 @@
+/*************************************************************************\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
diff --git a/16/xlib/demo5.exe b/16/xlib/demo5.exe
new file mode 100755 (executable)
index 0000000..30993d2
Binary files /dev/null and b/16/xlib/demo5.exe differ
diff --git a/16/xlib/demo6.c b/16/xlib/demo6.c
new file mode 100755 (executable)
index 0000000..28b542c
--- /dev/null
@@ -0,0 +1,22 @@
+#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
diff --git a/16/xlib/demo6.exe b/16/xlib/demo6.exe
new file mode 100755 (executable)
index 0000000..7e26f1f
Binary files /dev/null and b/16/xlib/demo6.exe differ
diff --git a/16/xlib/demo7.c b/16/xlib/demo7.c
new file mode 100755 (executable)
index 0000000..e5cce45
--- /dev/null
@@ -0,0 +1,38 @@
+/* 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
diff --git a/16/xlib/demo7.exe b/16/xlib/demo7.exe
new file mode 100755 (executable)
index 0000000..3762184
Binary files /dev/null and b/16/xlib/demo7.exe differ
diff --git a/16/xlib/demo8.c b/16/xlib/demo8.c
new file mode 100755 (executable)
index 0000000..5241eed
--- /dev/null
@@ -0,0 +1,154 @@
+/*************************************************************************\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
diff --git a/16/xlib/demo8.exe b/16/xlib/demo8.exe
new file mode 100755 (executable)
index 0000000..98c480e
Binary files /dev/null and b/16/xlib/demo8.exe differ
diff --git a/16/xlib/demo9.exe b/16/xlib/demo9.exe
new file mode 100755 (executable)
index 0000000..6c2954b
Binary files /dev/null and b/16/xlib/demo9.exe differ
diff --git a/16/xlib/fixed6x8.fnt b/16/xlib/fixed6x8.fnt
new file mode 100755 (executable)
index 0000000..8d04a27
Binary files /dev/null and b/16/xlib/fixed6x8.fnt differ
diff --git a/16/xlib/makefile b/16/xlib/makefile
new file mode 100755 (executable)
index 0000000..35ec877
--- /dev/null
@@ -0,0 +1,104 @@
+# 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
+%.o: %.c\r
+   $(CC) -c $(CFLAGS) $<\r
+\r
+%.o: *.asm\r
+   wasm $(AFLAGS) $* \\r
+\r
+\r
+XLIBOBJS= xprintf.o xpoint.o xline.o xmain.o xpal.o xpbitmap.o \\r
+        xrect.o xtext.o xcbitmap.o xdetect.o xbmtools.o         \\r
+        xfileio.o xrletool.o xbezier.o xpbmclip.o xvbitmap.o    \\r
+        xmakevbm.o xmouse.o xcircle.o xclippbm.o xcomppbm.o     \\r
+        xpolygon.o xvsync.o xfill.o xcbitm32.o\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.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+  $(CC) $(CFLAGS) demo1.o xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo2.exe : demo2.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+  $(CC) $(CFLAGS) demo2.o xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo3.exe : demo3.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+  $(CC) $(CFLAGS) demo3.o xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo4.exe : demo4.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+  $(CC) $(CFLAGS) demo4.o xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo5.exe : demo5.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+  $(CC) $(CFLAGS) demo5.o xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo6.exe : demo6.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+  $(CC) $(CFLAGS) demo6.o xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo7.exe : demo7.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+  $(CC) $(CFLAGS) demo7.o xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo8.exe : demo8.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+  $(CC) $(CFLAGS) demo8.o xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo9.exe : demo9.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+  $(CC) $(CFLAGS) demo9.o xlib$(XLIB_VERSION)$(MODEL).lib\r
+\r
+demo10.exe : demo10.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib\r
+  $(CC) $(CFLAGS) demo10.o 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.o : xprintf.c\r
+xpoint.o  : xpoint.asm   xpoint.inc   xlib.inc  model.inc\r
+xline.o   : xline.asm    xline.inc    xlib.inc  model.inc\r
+xmain.o   : xmain.asm    xmain.inc    xlib.inc  model.inc\r
+xpal.o    : xpal.asm     xpal.inc     xlib.inc  model.inc\r
+xpbitmap.o: xpbitmap.asm xpbitmap.inc xlib.inc  model.inc\r
+xpbmclip.o: xpbmclip.asm xpbmclip.inc xlib.inc  model.inc\r
+xclippbm.o: xclippbm.asm xclippbm.inc xlib.inc  model.inc\r
+xrect.o   : xpal.asm     xpal.inc     xlib.inc  model.inc\r
+xtext.o   : xtext.asm    xtext.inc    xlib.inc  model.inc\r
+xcbitmap.o: xcbitmap.asm xcbitmap.inc xlib.inc  model.inc\r
+xcomppbm.o: xcomppbm.asm xcomppbm.inc xlib.inc  model.inc\r
+xcbitm32.o: xcbitm32.c   \r
+xdetect.o : xdetect.asm  xdetect.inc            model.inc\r
+xbmtools.o: xbmtools.asm xbmtools.inc           model.inc\r
+xfileio.o : xfileio.asm  xfileio.inc            model.inc\r
+xrletool.o: xrletool.asm xrletool.inc           model.inc\r
+xvbitmap.o: xvbitmap.asm xvbitmap.inc xlib.inc  model.inc\r
+xmakevbm.o: xmakevbm.c   xvbitmap.h\r
+xmouse.o  : xmouse.asm                xlib.inc  model.inc\r
+xcircle.o : xcircle.asm  xcircle.inc  xlib.inc  model.inc\r
+xpolygon.o: xpolygon.asm xpolygon.inc xlib.inc  model.inc\r
+xvsync.o  : xvsync.asm   xvsync.inc   xlib.inc  model.inc\r
+xfill.o   : xfill.asm    xfill.inc    xlib.inc  model.inc\r
diff --git a/16/xlib/model.inc b/16/xlib/model.inc
new file mode 100755 (executable)
index 0000000..afcdced
--- /dev/null
@@ -0,0 +1,21 @@
+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
diff --git a/16/xlib/modernb.fnt b/16/xlib/modernb.fnt
new file mode 100755 (executable)
index 0000000..a71a5d8
Binary files /dev/null and b/16/xlib/modernb.fnt differ
diff --git a/16/xlib/readme.txt b/16/xlib/readme.txt
new file mode 100755 (executable)
index 0000000..08359e4
--- /dev/null
@@ -0,0 +1,32 @@
+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
diff --git a/16/xlib/smalthin.fnt b/16/xlib/smalthin.fnt
new file mode 100755 (executable)
index 0000000..63c07f4
Binary files /dev/null and b/16/xlib/smalthin.fnt differ
diff --git a/16/xlib/timpani.fnt b/16/xlib/timpani.fnt
new file mode 100755 (executable)
index 0000000..8907f0a
Binary files /dev/null and b/16/xlib/timpani.fnt differ
diff --git a/16/xlib/tiny4.fnt b/16/xlib/tiny4.fnt
new file mode 100755 (executable)
index 0000000..d213c3d
Binary files /dev/null and b/16/xlib/tiny4.fnt differ
diff --git a/16/xlib/updates.doc b/16/xlib/updates.doc
new file mode 100755 (executable)
index 0000000..c767fee
--- /dev/null
@@ -0,0 +1,277 @@
+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
diff --git a/16/xlib/var6x8.fnt b/16/xlib/var6x8.fnt
new file mode 100755 (executable)
index 0000000..6cd3b0d
Binary files /dev/null and b/16/xlib/var6x8.fnt differ
diff --git a/16/xlib/varswisb.fnt b/16/xlib/varswisb.fnt
new file mode 100755 (executable)
index 0000000..a4a357b
Binary files /dev/null and b/16/xlib/varswisb.fnt differ
diff --git a/16/xlib/varswisl.fnt b/16/xlib/varswisl.fnt
new file mode 100755 (executable)
index 0000000..d1b2e56
Binary files /dev/null and b/16/xlib/varswisl.fnt differ
diff --git a/16/xlib/xbezier.asm b/16/xlib/xbezier.asm
new file mode 100755 (executable)
index 0000000..cc16fb2
--- /dev/null
@@ -0,0 +1,675 @@
+\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
diff --git a/16/xlib/xbezier.h b/16/xlib/xbezier.h
new file mode 100755 (executable)
index 0000000..cb7818d
--- /dev/null
@@ -0,0 +1,25 @@
+/*********************************************************************\\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
diff --git a/16/xlib/xbezier.inc b/16/xlib/xbezier.inc
new file mode 100755 (executable)
index 0000000..274a1c8
--- /dev/null
@@ -0,0 +1,10 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xbmtools.asm b/16/xlib/xbmtools.asm
new file mode 100755 (executable)
index 0000000..4638d42
--- /dev/null
@@ -0,0 +1,195 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xbmtools.h b/16/xlib/xbmtools.h
new file mode 100755 (executable)
index 0000000..3007d1f
--- /dev/null
@@ -0,0 +1,63 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xbmtools.inc b/16/xlib/xbmtools.inc
new file mode 100755 (executable)
index 0000000..fe5415c
--- /dev/null
@@ -0,0 +1,20 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xcbitm32.c b/16/xlib/xcbitm32.c
new file mode 100755 (executable)
index 0000000..1d70e6a
--- /dev/null
@@ -0,0 +1,188 @@
+#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
diff --git a/16/xlib/xcbitm32.h b/16/xlib/xcbitm32.h
new file mode 100755 (executable)
index 0000000..f43c594
--- /dev/null
@@ -0,0 +1,34 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xcbitmap.asm b/16/xlib/xcbitmap.asm
new file mode 100755 (executable)
index 0000000..2fbc84b
--- /dev/null
@@ -0,0 +1,422 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xcbitmap.h b/16/xlib/xcbitmap.h
new file mode 100755 (executable)
index 0000000..dd747ce
--- /dev/null
@@ -0,0 +1,47 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xcbitmap.inc b/16/xlib/xcbitmap.inc
new file mode 100755 (executable)
index 0000000..b9c9568
--- /dev/null
@@ -0,0 +1,21 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xcircle.asm b/16/xlib/xcircle.asm
new file mode 100755 (executable)
index 0000000..4e75031
--- /dev/null
@@ -0,0 +1,710 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xcircle.h b/16/xlib/xcircle.h
new file mode 100755 (executable)
index 0000000..1826377
--- /dev/null
@@ -0,0 +1,39 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xcircle.inc b/16/xlib/xcircle.inc
new file mode 100755 (executable)
index 0000000..3b49d7c
--- /dev/null
@@ -0,0 +1,21 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xclippbm.asm b/16/xlib/xclippbm.asm
new file mode 100755 (executable)
index 0000000..bbe50b5
--- /dev/null
@@ -0,0 +1,507 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xclippbm.h b/16/xlib/xclippbm.h
new file mode 100755 (executable)
index 0000000..c66b433
--- /dev/null
@@ -0,0 +1,56 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xclippbm.inc b/16/xlib/xclippbm.inc
new file mode 100755 (executable)
index 0000000..f9d7586
--- /dev/null
@@ -0,0 +1,26 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xcomppbm.asm b/16/xlib/xcomppbm.asm
new file mode 100755 (executable)
index 0000000..b3ff621
--- /dev/null
@@ -0,0 +1,322 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xcomppbm.h b/16/xlib/xcomppbm.h
new file mode 100755 (executable)
index 0000000..11db9aa
--- /dev/null
@@ -0,0 +1,23 @@
+#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
diff --git a/16/xlib/xcomppbm.inc b/16/xlib/xcomppbm.inc
new file mode 100755 (executable)
index 0000000..f260205
--- /dev/null
@@ -0,0 +1,2 @@
+global _x_compile_pbm         : proc\r
+global _x_sizeof_cpbm         : proc\r
diff --git a/16/xlib/xdetect.asm b/16/xlib/xdetect.asm
new file mode 100755 (executable)
index 0000000..4b92168
--- /dev/null
@@ -0,0 +1,269 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xdetect.h b/16/xlib/xdetect.h
new file mode 100755 (executable)
index 0000000..2687a18
--- /dev/null
@@ -0,0 +1,71 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xdetect.inc b/16/xlib/xdetect.inc
new file mode 100755 (executable)
index 0000000..8c0a72a
--- /dev/null
@@ -0,0 +1,26 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xfileio.asm b/16/xlib/xfileio.asm
new file mode 100755 (executable)
index 0000000..0854612
--- /dev/null
@@ -0,0 +1,433 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xfileio.h b/16/xlib/xfileio.h
new file mode 100755 (executable)
index 0000000..9b98fb0
--- /dev/null
@@ -0,0 +1,96 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xfileio.inc b/16/xlib/xfileio.inc
new file mode 100755 (executable)
index 0000000..1a38b73
--- /dev/null
@@ -0,0 +1,27 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xfill.asm b/16/xlib/xfill.asm
new file mode 100755 (executable)
index 0000000..af3943c
--- /dev/null
@@ -0,0 +1,533 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xfill.h b/16/xlib/xfill.h
new file mode 100755 (executable)
index 0000000..3517b40
--- /dev/null
@@ -0,0 +1,51 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xfill.inc b/16/xlib/xfill.inc
new file mode 100755 (executable)
index 0000000..6870b46
--- /dev/null
@@ -0,0 +1,2 @@
+global _x_flood_fill:proc\r
+global _x_boundary_fill:proc
\ No newline at end of file
diff --git a/16/xlib/xlib.h b/16/xlib/xlib.h
new file mode 100755 (executable)
index 0000000..8249e8c
--- /dev/null
@@ -0,0 +1,160 @@
+/*----------------------------------------------------------------------\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
diff --git a/16/xlib/xlib.inc b/16/xlib/xlib.inc
new file mode 100755 (executable)
index 0000000..58e256d
--- /dev/null
@@ -0,0 +1,166 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xlib_all.h b/16/xlib/xlib_all.h
new file mode 100755 (executable)
index 0000000..9fca71f
--- /dev/null
@@ -0,0 +1,42 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xlibref1.doc b/16/xlib/xlibref1.doc
new file mode 100755 (executable)
index 0000000..0c363e3
--- /dev/null
@@ -0,0 +1,1655 @@
+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
diff --git a/16/xlib/xlibref2.doc b/16/xlib/xlibref2.doc
new file mode 100755 (executable)
index 0000000..c8aea80
--- /dev/null
@@ -0,0 +1,1097 @@
+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
diff --git a/16/xlib/xline.asm b/16/xlib/xline.asm
new file mode 100755 (executable)
index 0000000..6c9c5c5
--- /dev/null
@@ -0,0 +1,317 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xline.h b/16/xlib/xline.h
new file mode 100755 (executable)
index 0000000..c8688a4
--- /dev/null
@@ -0,0 +1,46 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xline.inc b/16/xlib/xline.inc
new file mode 100755 (executable)
index 0000000..2e92d7e
--- /dev/null
@@ -0,0 +1,19 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xmain.asm b/16/xlib/xmain.asm
new file mode 100755 (executable)
index 0000000..a8fd418
--- /dev/null
@@ -0,0 +1,1539 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xmain.inc b/16/xlib/xmain.inc
new file mode 100755 (executable)
index 0000000..44b40fc
--- /dev/null
@@ -0,0 +1,31 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xmakevbm.c b/16/xlib/xmakevbm.c
new file mode 100755 (executable)
index 0000000..58a9d99
--- /dev/null
@@ -0,0 +1,205 @@
+/*----------------------------------------------------------------------\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
diff --git a/16/xlib/xmouse.asm b/16/xlib/xmouse.asm
new file mode 100755 (executable)
index 0000000..fea4642
--- /dev/null
@@ -0,0 +1,884 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xmouse.h b/16/xlib/xmouse.h
new file mode 100755 (executable)
index 0000000..144bde5
--- /dev/null
@@ -0,0 +1,80 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xpal.asm b/16/xlib/xpal.asm
new file mode 100755 (executable)
index 0000000..558f266
--- /dev/null
@@ -0,0 +1,576 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xpal.h b/16/xlib/xpal.h
new file mode 100755 (executable)
index 0000000..04c1c70
--- /dev/null
@@ -0,0 +1,87 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xpal.inc b/16/xlib/xpal.inc
new file mode 100755 (executable)
index 0000000..1e8c607
--- /dev/null
@@ -0,0 +1,32 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xpbitmap.asm b/16/xlib/xpbitmap.asm
new file mode 100755 (executable)
index 0000000..e0a2d96
--- /dev/null
@@ -0,0 +1,603 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xpbitmap.h b/16/xlib/xpbitmap.h
new file mode 100755 (executable)
index 0000000..6f452f9
--- /dev/null
@@ -0,0 +1,77 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xpbitmap.inc b/16/xlib/xpbitmap.inc
new file mode 100755 (executable)
index 0000000..a87f638
--- /dev/null
@@ -0,0 +1,22 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xpbmclip.asm b/16/xlib/xpbmclip.asm
new file mode 100755 (executable)
index 0000000..872f86b
--- /dev/null
@@ -0,0 +1,1078 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xpbmclip.h b/16/xlib/xpbmclip.h
new file mode 100755 (executable)
index 0000000..b025ee7
--- /dev/null
@@ -0,0 +1,83 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xpbmclip.inc b/16/xlib/xpbmclip.inc
new file mode 100755 (executable)
index 0000000..fa5b18d
--- /dev/null
@@ -0,0 +1,25 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xpoint.asm b/16/xlib/xpoint.asm
new file mode 100755 (executable)
index 0000000..a2be8bf
--- /dev/null
@@ -0,0 +1,107 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xpoint.h b/16/xlib/xpoint.h
new file mode 100755 (executable)
index 0000000..a820ca2
--- /dev/null
@@ -0,0 +1,51 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xpoint.inc b/16/xlib/xpoint.inc
new file mode 100755 (executable)
index 0000000..58b36dc
--- /dev/null
@@ -0,0 +1,20 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xpolygon.asm b/16/xlib/xpolygon.asm
new file mode 100755 (executable)
index 0000000..c8bac0b
--- /dev/null
@@ -0,0 +1,608 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xpolygon.h b/16/xlib/xpolygon.h
new file mode 100755 (executable)
index 0000000..bdad73e
--- /dev/null
@@ -0,0 +1,59 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xpolygon.inc b/16/xlib/xpolygon.inc
new file mode 100755 (executable)
index 0000000..c8d2bff
--- /dev/null
@@ -0,0 +1,19 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xprintf.c b/16/xlib/xprintf.c
new file mode 100755 (executable)
index 0000000..921b658
--- /dev/null
@@ -0,0 +1,41 @@
+#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
diff --git a/16/xlib/xrect.asm b/16/xlib/xrect.asm
new file mode 100755 (executable)
index 0000000..9b00356
--- /dev/null
@@ -0,0 +1,684 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xrect.h b/16/xlib/xrect.h
new file mode 100755 (executable)
index 0000000..04724b6
--- /dev/null
@@ -0,0 +1,89 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xrect.inc b/16/xlib/xrect.inc
new file mode 100755 (executable)
index 0000000..278ba57
--- /dev/null
@@ -0,0 +1,22 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xrletool.asm b/16/xlib/xrletool.asm
new file mode 100755 (executable)
index 0000000..5a9143f
--- /dev/null
@@ -0,0 +1,655 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xrletool.h b/16/xlib/xrletool.h
new file mode 100755 (executable)
index 0000000..0ec859e
--- /dev/null
@@ -0,0 +1,50 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xrletool.inc b/16/xlib/xrletool.inc
new file mode 100755 (executable)
index 0000000..6fda4ff
--- /dev/null
@@ -0,0 +1,26 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xtext.asm b/16/xlib/xtext.asm
new file mode 100755 (executable)
index 0000000..378ed26
--- /dev/null
@@ -0,0 +1,446 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xtext.h b/16/xlib/xtext.h
new file mode 100755 (executable)
index 0000000..d4dbd92
--- /dev/null
@@ -0,0 +1,91 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xtext.inc b/16/xlib/xtext.inc
new file mode 100755 (executable)
index 0000000..37a2197
--- /dev/null
@@ -0,0 +1,31 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xvbitmap.asm b/16/xlib/xvbitmap.asm
new file mode 100755 (executable)
index 0000000..b57220c
--- /dev/null
@@ -0,0 +1,681 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xvbitmap.h b/16/xlib/xvbitmap.h
new file mode 100755 (executable)
index 0000000..856dbab
--- /dev/null
@@ -0,0 +1,69 @@
+/*-----------------------------------------------------------------------\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
diff --git a/16/xlib/xvbitmap.inc b/16/xlib/xvbitmap.inc
new file mode 100755 (executable)
index 0000000..38caa4d
--- /dev/null
@@ -0,0 +1,22 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xvbmtool.inc b/16/xlib/xvbmtool.inc
new file mode 100755 (executable)
index 0000000..6fbc871
--- /dev/null
@@ -0,0 +1,22 @@
+;-----------------------------------------------------------------------\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
diff --git a/16/xlib/xvsync.asm b/16/xlib/xvsync.asm
new file mode 100755 (executable)
index 0000000..452ec65
--- /dev/null
@@ -0,0 +1,311 @@
+; 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
diff --git a/16/xlib/xvsync.h b/16/xlib/xvsync.h
new file mode 100755 (executable)
index 0000000..be2be0c
--- /dev/null
@@ -0,0 +1,22 @@
+#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
diff --git a/16/xlib/xvsync.inc b/16/xlib/xvsync.inc
new file mode 100755 (executable)
index 0000000..d93ddad
--- /dev/null
@@ -0,0 +1,6 @@
+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
diff --git a/16/xlib/zip.bat b/16/xlib/zip.bat
new file mode 100755 (executable)
index 0000000..00ecf62
--- /dev/null
@@ -0,0 +1,118 @@
+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