From 8a4b836c5347897d1a8279a46310fc79fd555574 Mon Sep 17 00:00:00 2001 From: sparky4 Date: Wed, 11 Nov 2015 03:42:14 -0600 Subject: [PATCH] added xlib to the project and i gotta convert the damn makefile -.- --- 16/xlib/crisp6x9.fnt | Bin 0 -> 964 bytes 16/xlib/demo1.c | 571 +++++++++++++++ 16/xlib/demo1.exe | Bin 0 -> 41502 bytes 16/xlib/demo10.exe | Bin 0 -> 21082 bytes 16/xlib/demo2.c | 221 ++++++ 16/xlib/demo2.exe | Bin 0 -> 38496 bytes 16/xlib/demo3.c | 62 ++ 16/xlib/demo3.exe | Bin 0 -> 9516 bytes 16/xlib/demo4.c | 170 +++++ 16/xlib/demo4.exe | Bin 0 -> 22750 bytes 16/xlib/demo5.c | 148 ++++ 16/xlib/demo5.exe | Bin 0 -> 19556 bytes 16/xlib/demo6.c | 22 + 16/xlib/demo6.exe | Bin 0 -> 13604 bytes 16/xlib/demo7.c | 38 + 16/xlib/demo7.exe | Bin 0 -> 14268 bytes 16/xlib/demo8.c | 154 ++++ 16/xlib/demo8.exe | Bin 0 -> 21266 bytes 16/xlib/demo9.exe | Bin 0 -> 32808 bytes 16/xlib/fixed6x8.fnt | Bin 0 -> 788 bytes 16/xlib/makefile | 104 +++ 16/xlib/model.inc | 21 + 16/xlib/modernb.fnt | Bin 0 -> 1060 bytes 16/xlib/readme.txt | 32 + 16/xlib/smalthin.fnt | Bin 0 -> 676 bytes 16/xlib/timpani.fnt | Bin 0 -> 1156 bytes 16/xlib/tiny4.fnt | Bin 0 -> 484 bytes 16/xlib/updates.doc | 277 +++++++ 16/xlib/var6x8.fnt | Bin 0 -> 877 bytes 16/xlib/varswisb.fnt | Bin 0 -> 964 bytes 16/xlib/varswisl.fnt | Bin 0 -> 964 bytes 16/xlib/xbezier.asm | 675 +++++++++++++++++ 16/xlib/xbezier.h | 25 + 16/xlib/xbezier.inc | 10 + 16/xlib/xbmtools.asm | 195 +++++ 16/xlib/xbmtools.h | 63 ++ 16/xlib/xbmtools.inc | 20 + 16/xlib/xcbitm32.c | 188 +++++ 16/xlib/xcbitm32.h | 34 + 16/xlib/xcbitmap.asm | 422 +++++++++++ 16/xlib/xcbitmap.h | 47 ++ 16/xlib/xcbitmap.inc | 21 + 16/xlib/xcircle.asm | 710 ++++++++++++++++++ 16/xlib/xcircle.h | 39 + 16/xlib/xcircle.inc | 21 + 16/xlib/xclippbm.asm | 507 +++++++++++++ 16/xlib/xclippbm.h | 56 ++ 16/xlib/xclippbm.inc | 26 + 16/xlib/xcomppbm.asm | 322 ++++++++ 16/xlib/xcomppbm.h | 23 + 16/xlib/xcomppbm.inc | 2 + 16/xlib/xdetect.asm | 269 +++++++ 16/xlib/xdetect.h | 71 ++ 16/xlib/xdetect.inc | 26 + 16/xlib/xfileio.asm | 433 +++++++++++ 16/xlib/xfileio.h | 96 +++ 16/xlib/xfileio.inc | 27 + 16/xlib/xfill.asm | 533 ++++++++++++++ 16/xlib/xfill.h | 51 ++ 16/xlib/xfill.inc | 2 + 16/xlib/xlib.h | 160 ++++ 16/xlib/xlib.inc | 166 +++++ 16/xlib/xlib_all.h | 42 ++ 16/xlib/xlibref1.doc | 1655 ++++++++++++++++++++++++++++++++++++++++++ 16/xlib/xlibref2.doc | 1097 ++++++++++++++++++++++++++++ 16/xlib/xline.asm | 317 ++++++++ 16/xlib/xline.h | 46 ++ 16/xlib/xline.inc | 19 + 16/xlib/xmain.asm | 1539 +++++++++++++++++++++++++++++++++++++++ 16/xlib/xmain.inc | 31 + 16/xlib/xmakevbm.c | 205 ++++++ 16/xlib/xmouse.asm | 884 ++++++++++++++++++++++ 16/xlib/xmouse.h | 80 ++ 16/xlib/xpal.asm | 576 +++++++++++++++ 16/xlib/xpal.h | 87 +++ 16/xlib/xpal.inc | 32 + 16/xlib/xpbitmap.asm | 603 +++++++++++++++ 16/xlib/xpbitmap.h | 77 ++ 16/xlib/xpbitmap.inc | 22 + 16/xlib/xpbmclip.asm | 1078 +++++++++++++++++++++++++++ 16/xlib/xpbmclip.h | 83 +++ 16/xlib/xpbmclip.inc | 25 + 16/xlib/xpoint.asm | 107 +++ 16/xlib/xpoint.h | 51 ++ 16/xlib/xpoint.inc | 20 + 16/xlib/xpolygon.asm | 608 ++++++++++++++++ 16/xlib/xpolygon.h | 59 ++ 16/xlib/xpolygon.inc | 19 + 16/xlib/xprintf.c | 41 ++ 16/xlib/xrect.asm | 684 +++++++++++++++++ 16/xlib/xrect.h | 89 +++ 16/xlib/xrect.inc | 22 + 16/xlib/xrletool.asm | 655 +++++++++++++++++ 16/xlib/xrletool.h | 50 ++ 16/xlib/xrletool.inc | 26 + 16/xlib/xtext.asm | 446 ++++++++++++ 16/xlib/xtext.h | 91 +++ 16/xlib/xtext.inc | 31 + 16/xlib/xvbitmap.asm | 681 +++++++++++++++++ 16/xlib/xvbitmap.h | 69 ++ 16/xlib/xvbitmap.inc | 22 + 16/xlib/xvbmtool.inc | 22 + 16/xlib/xvsync.asm | 311 ++++++++ 16/xlib/xvsync.h | 22 + 16/xlib/xvsync.inc | 6 + 16/xlib/zip.bat | 118 +++ 106 files changed, 19808 insertions(+) create mode 100755 16/xlib/crisp6x9.fnt create mode 100755 16/xlib/demo1.c create mode 100755 16/xlib/demo1.exe create mode 100755 16/xlib/demo10.exe create mode 100755 16/xlib/demo2.c create mode 100755 16/xlib/demo2.exe create mode 100755 16/xlib/demo3.c create mode 100755 16/xlib/demo3.exe create mode 100755 16/xlib/demo4.c create mode 100755 16/xlib/demo4.exe create mode 100755 16/xlib/demo5.c create mode 100755 16/xlib/demo5.exe create mode 100755 16/xlib/demo6.c create mode 100755 16/xlib/demo6.exe create mode 100755 16/xlib/demo7.c create mode 100755 16/xlib/demo7.exe create mode 100755 16/xlib/demo8.c create mode 100755 16/xlib/demo8.exe create mode 100755 16/xlib/demo9.exe create mode 100755 16/xlib/fixed6x8.fnt create mode 100755 16/xlib/makefile create mode 100755 16/xlib/model.inc create mode 100755 16/xlib/modernb.fnt create mode 100755 16/xlib/readme.txt create mode 100755 16/xlib/smalthin.fnt create mode 100755 16/xlib/timpani.fnt create mode 100755 16/xlib/tiny4.fnt create mode 100755 16/xlib/updates.doc create mode 100755 16/xlib/var6x8.fnt create mode 100755 16/xlib/varswisb.fnt create mode 100755 16/xlib/varswisl.fnt create mode 100755 16/xlib/xbezier.asm create mode 100755 16/xlib/xbezier.h create mode 100755 16/xlib/xbezier.inc create mode 100755 16/xlib/xbmtools.asm create mode 100755 16/xlib/xbmtools.h create mode 100755 16/xlib/xbmtools.inc create mode 100755 16/xlib/xcbitm32.c create mode 100755 16/xlib/xcbitm32.h create mode 100755 16/xlib/xcbitmap.asm create mode 100755 16/xlib/xcbitmap.h create mode 100755 16/xlib/xcbitmap.inc create mode 100755 16/xlib/xcircle.asm create mode 100755 16/xlib/xcircle.h create mode 100755 16/xlib/xcircle.inc create mode 100755 16/xlib/xclippbm.asm create mode 100755 16/xlib/xclippbm.h create mode 100755 16/xlib/xclippbm.inc create mode 100755 16/xlib/xcomppbm.asm create mode 100755 16/xlib/xcomppbm.h create mode 100755 16/xlib/xcomppbm.inc create mode 100755 16/xlib/xdetect.asm create mode 100755 16/xlib/xdetect.h create mode 100755 16/xlib/xdetect.inc create mode 100755 16/xlib/xfileio.asm create mode 100755 16/xlib/xfileio.h create mode 100755 16/xlib/xfileio.inc create mode 100755 16/xlib/xfill.asm create mode 100755 16/xlib/xfill.h create mode 100755 16/xlib/xfill.inc create mode 100755 16/xlib/xlib.h create mode 100755 16/xlib/xlib.inc create mode 100755 16/xlib/xlib_all.h create mode 100755 16/xlib/xlibref1.doc create mode 100755 16/xlib/xlibref2.doc create mode 100755 16/xlib/xline.asm create mode 100755 16/xlib/xline.h create mode 100755 16/xlib/xline.inc create mode 100755 16/xlib/xmain.asm create mode 100755 16/xlib/xmain.inc create mode 100755 16/xlib/xmakevbm.c create mode 100755 16/xlib/xmouse.asm create mode 100755 16/xlib/xmouse.h create mode 100755 16/xlib/xpal.asm create mode 100755 16/xlib/xpal.h create mode 100755 16/xlib/xpal.inc create mode 100755 16/xlib/xpbitmap.asm create mode 100755 16/xlib/xpbitmap.h create mode 100755 16/xlib/xpbitmap.inc create mode 100755 16/xlib/xpbmclip.asm create mode 100755 16/xlib/xpbmclip.h create mode 100755 16/xlib/xpbmclip.inc create mode 100755 16/xlib/xpoint.asm create mode 100755 16/xlib/xpoint.h create mode 100755 16/xlib/xpoint.inc create mode 100755 16/xlib/xpolygon.asm create mode 100755 16/xlib/xpolygon.h create mode 100755 16/xlib/xpolygon.inc create mode 100755 16/xlib/xprintf.c create mode 100755 16/xlib/xrect.asm create mode 100755 16/xlib/xrect.h create mode 100755 16/xlib/xrect.inc create mode 100755 16/xlib/xrletool.asm create mode 100755 16/xlib/xrletool.h create mode 100755 16/xlib/xrletool.inc create mode 100755 16/xlib/xtext.asm create mode 100755 16/xlib/xtext.h create mode 100755 16/xlib/xtext.inc create mode 100755 16/xlib/xvbitmap.asm create mode 100755 16/xlib/xvbitmap.h create mode 100755 16/xlib/xvbitmap.inc create mode 100755 16/xlib/xvbmtool.inc create mode 100755 16/xlib/xvsync.asm create mode 100755 16/xlib/xvsync.h create mode 100755 16/xlib/xvsync.inc create mode 100755 16/xlib/zip.bat diff --git a/16/xlib/crisp6x9.fnt b/16/xlib/crisp6x9.fnt new file mode 100755 index 0000000000000000000000000000000000000000..0b8a209b8cac3df93c1a36a636ab3ac75171b130 GIT binary patch literal 964 zcmZ9LL2KkN4289>*Y$=T!VpR+CK$5}i|HwcQcB2A+uy$5lieOxGZV{Ck=~Q+srJjh zEe4qdv#>17fTL{}A2zAmN~3rq&$sv^8dFs4!3Xa5Y+N4={x+Dwq@ z>lo8;1^aKAuq%W;1gRe$ZITrfN literal 0 HcmV?d00001 diff --git a/16/xlib/demo1.c b/16/xlib/demo1.c new file mode 100755 index 00000000..0ba8c1ae --- /dev/null +++ b/16/xlib/demo1.c @@ -0,0 +1,571 @@ +/* VERY QUICK AND ULTRA-DIRTY DEMO USING XLIB */ + +/* Simple Demo of MODE X Split screen and panning */ +/* Compile using Turbo C and Tasm */ + +#include +#include +#include +#include +#include +#include +#include "Xlib_all.h" + +#define MAX_OBJECTS 10 + +static char *texttest[6] = + {"This is a demonstration of the fonts ", + "available in XLIB. Notice fixed and ", + "variabe spaced fonts are supported but", + "are limited to a maximum of 8 pixels in", + "width. Height of the characters is ", + "ofcourse unlimited..."}; + +typedef struct { + int X,Y,Width,Height,XDir,YDir,XOtherPage,YOtherPage; + char far * Image; + char far * bg; + char far * bgOtherPage; +} AnimatedObject; + +AnimatedObject objects[MAX_OBJECTS]; +int object_count=0; + +static char bm[] = {4,12, + /* plane 0 */ + 2,2,2,2,2,1,1,1,2,1,1,1,2,3,3,1, + 2,0,0,3,2,0,0,3,2,0,0,3,2,0,0,3, + 2,3,3,1,2,1,1,1,2,1,1,1,2,2,2,2, + /* plane 1 */ + 2,2,2,2,1,1,1,1,1,1,1,1,1,3,3,1, + 1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1, + 1,3,3,1,1,1,1,1,1,1,1,1,2,2,2,2, + /* plane 2 */ + 2,2,2,2,1,1,1,1,1,1,1,1,1,3,3,1, + 1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1, + 1,3,3,1,1,1,1,1,1,1,1,1,2,2,2,2, + /* plane 3 */ + 2,2,2,2,1,1,1,2,1,1,1,2,1,3,3,2, + 3,0,0,2,3,0,0,2,3,0,0,2,3,0,0,2, + 1,3,3,2,1,1,1,2,1,1,1,2,2,2,2,2}; + +static char bm2[] = {4,12, + /* plane 0 */ + 2,2,2,2,2,4,4,4,2,4,4,4,2,2,2,4, + 2,0,0,2,2,0,0,2,2,0,0,2,2,0,0,2, + 2,2,2,4,2,4,4,4,2,4,4,4,2,2,2,2, + /* plane 1 */ + 2,2,2,2,4,4,4,4,4,4,4,4,4,2,2,4, + 4,0,0,4,4,0,0,4,4,0,0,4,4,0,0,4, + 4,2,2,4,4,4,4,4,4,4,4,4,2,2,2,2, + /* plane 2 */ + 2,2,2,2,4,4,4,4,4,4,4,4,4,2,2,4, + 4,0,0,4,4,0,0,4,4,0,0,4,4,0,0,4, + 4,2,2,4,4,4,4,4,4,4,4,4,2,2,2,2, + /* plane 2 */ + 2,2,2,2,4,4,4,2,4,4,4,2,4,2,2,2, + 2,0,0,2,2,0,0,2,2,0,0,2,2,0,0,2, + 4,2,2,2,4,4,4,2,4,4,4,2,2,2,2,2}; + +int textwindow_x=0,textwindow_y=0; +char far * pal,far * pal2; +char palscrolldir=1; +char far * userfnt1; + + + +void drawtext(int height){ + int i; + for (i=0;i<6;i++) + x_printf(textwindow_x+5,50+i*(height+2),VisiblePageOffs,9,texttest[i]); +} + +/* initialize a new object */ +void init_object(int x,int y,int width, int height, int xdir, int ydir, + char far * image){ + int i; + objects[object_count].X = objects[object_count].XOtherPage = x; + objects[object_count].Y = objects[object_count].YOtherPage = y; + objects[object_count].Width = width; + objects[object_count].Height = height; + objects[object_count].XDir = xdir; + objects[object_count].YDir = ydir; + objects[object_count].Image = image; + objects[object_count].bg = (char far *) farmalloc(4*width*height+20); + objects[object_count].bgOtherPage = (char far *) farmalloc(4*width*height+20); + x_get_pbm(x,y,(unsigned)width,height,VisiblePageOffs, + objects[object_count].bg); + x_get_pbm(x,y,(unsigned)width,height,HiddenPageOffs, + objects[object_count].bgOtherPage); + object_count++; +} + +/* Move the specified object, bouncing at the edges of the screen and + remembering where the object was before the move for erasing next time */ +void MoveObject(AnimatedObject * ObjectToMove) { + int X, Y; + char far *cptr; + X = ObjectToMove->X + ObjectToMove->XDir; + Y = ObjectToMove->Y + ObjectToMove->YDir; + if ((X < 0) || (X > (ScrnLogicalPixelWidth-((ObjectToMove->Width)<<2)))) { + ObjectToMove->XDir = -ObjectToMove->XDir; + X = ObjectToMove->X + ObjectToMove->XDir; + } + if ((Y < 0) || (Y > (ScrnLogicalHeight-ObjectToMove->Height))) { + ObjectToMove->YDir = -ObjectToMove->YDir; + Y = ObjectToMove->Y + ObjectToMove->YDir; + } + /* Remember previous location for erasing purposes */ + ObjectToMove->XOtherPage = ObjectToMove->X; + ObjectToMove->YOtherPage = ObjectToMove->Y; + ObjectToMove->X = X; /* set new location */ + ObjectToMove->Y = Y; + cptr = ObjectToMove->bg; + ObjectToMove->bg = ObjectToMove->bgOtherPage; + ObjectToMove->bgOtherPage = cptr; +} + +void animate(void){ + int i; + for(i=object_count-1;i>=0;i--){ + x_put_pbm(objects[i].XOtherPage,objects[i].YOtherPage, + HiddenPageOffs,objects[i].bgOtherPage); + } + for(i=0;i=0;i--){ + x_put_pbm(objects[i].XOtherPage,objects[i].YOtherPage, + HiddenPageOffs,objects[i].bgOtherPage); + } +} + + +void textwindow(int Margin){ + int x0=0+Margin; + int y0=0+Margin; + int x1=ScrnPhysicalPixelWidth-Margin; + int y1=ScrnPhysicalHeight-Margin; + x_rect_fill(x0, y0, x1,y1,VisiblePageOffs,1); + x_line(x0,y0,x1,y0,2,VisiblePageOffs); + x_line(x0,y1,x1,y1,2,VisiblePageOffs); + x_line(x0,y0,x0,y1,2,VisiblePageOffs); + x_line(x1,y0,x1,y1,2,VisiblePageOffs); + x_line(x0+2,y0+2,x1-2,y0+2,2,VisiblePageOffs); + x_line(x0+2,y1-2,x1-2,y1-2,2,VisiblePageOffs); + x_line(x0+2,y0+2,x0+2,y1-2,2,VisiblePageOffs); + x_line(x1-2,y0+2,x1-2,y1-2,2,VisiblePageOffs); + textwindow_x=x0; + textwindow_y=y0; + +} + + +void wait_for_keypress(void){ + x_show_mouse(); + while(kbhit()) getch(); + palscrolldir^=1; + + do { + x_rot_pal_struc(pal,palscrolldir); + MouseFrozen=1; + x_put_pal_struc(pal); + x_update_mouse(); + } while (!kbhit() && !(MouseButtonStatus==LEFT_PRESSED)); + while(MouseButtonStatus==LEFT_PRESSED); + while(kbhit()) getch(); + +} + + +void exitfunc(void){ + x_mouse_remove(); + x_remove_vsync_handler(); + x_text_mode(); + printf("Thanks to everyone who assisted in the development of XLIB.\n"); + printf("\nSpecial thanks to Matthew Mackenzie for contributing \n"); + printf("lots of code, documentation and ideas.\n\n"); + printf("If you make any money using this code and you're the generous\n"); + printf("type please send us some, or at least a copy of your program!\n"); +} + +int terminate(void){ + exit(0); +} + +void intro_1(void){ + x_set_rgb(1,40,40,40); /* BG Gray */ + x_set_rgb(2,63,63,0); /* Bright Yellow */ + x_set_rgb(3,63,0,0); /* Bright Red */ + x_set_rgb(4,0,63,0); /* Bright Green */ + x_set_rgb(5,0,0,63); /* Bright Blue */ + x_set_rgb(6,0,0,28); /* Dark Blue */ + x_set_rgb(7,0,28,0); /* Dark Green */ + x_set_rgb(8,28,0,0); /* Dark red */ + x_set_rgb(9,0,0,38); /* Med Blue */ + + textwindow(20); + x_set_font(1); + x_printf(textwindow_x+54,textwindow_y+4,VisiblePageOffs,6," XLIB Version 6.0"); + x_printf(textwindow_x+53,textwindow_y+3,VisiblePageOffs,2," XLIB Version 6.0"); + x_set_font(0); + x_printf(textwindow_x+24,textwindow_y+18,VisiblePageOffs,6," Not the Unix version"); + x_printf(textwindow_x+23,textwindow_y+17,VisiblePageOffs,2," Not the Unix version"); + + x_printf(textwindow_x+24,168,VisiblePageOffs,6," Press any key to continue"); + x_printf(textwindow_x+23,167,VisiblePageOffs,2," Press any key to continue"); +} + +void subsequent_page(void){ + x_hide_mouse(); + textwindow(20); + x_set_font(1); + x_printf(textwindow_x+54,textwindow_y+4,VisiblePageOffs,6," XLIB Version 6.0"); + x_printf(textwindow_x+53,textwindow_y+3,VisiblePageOffs,2," XLIB Version 6.0"); + x_set_font(0); + x_printf(textwindow_x+24,168,VisiblePageOffs,6," Press any key to continue"); + x_printf(textwindow_x+23,167,VisiblePageOffs,2," Press any key to continue"); +} + +void load_user_fonts(void){ + FILE *f; + f=fopen("var6x8.fnt","rb"); + /* read char by char as fread wont read to far pointers in small model */ + { int i; char c; + for (i=0;i<256*8+4;i++){ + fread(&c,1,1,f); + *(userfnt1+i)=c; + } + } + + fclose(f); + + x_register_userfont(userfnt1); + +} + + + +void main(){ + int i, j, xinc, yinc, Margin; + char ch; + WORD curr_x=0, curr_y=0; + + pal = (char far *) farmalloc(256*3); + pal2 = (char far *) farmalloc(256*3); + userfnt1 = (char far *) farmalloc(256*16+4); + + + /* INITIALIZE XLIB */ + + /* we set up Mode X 360x200x256 with a logical width of ~ 500 */ + /* pixels; we actually get 496 due to the fact that the width */ + /* must be divisible by 8 */ + + x_text_mode(); /* make sure VGA is in color mode, if possible */ + x_set_mode(X_MODE_360x200,500); /* actually is set to 496 */ + x_install_vsync_handler(2); + x_set_splitscreen(ScrnPhysicalHeight-60); /* split screen 60 pixels high */ + x_set_doublebuffer(220); + x_text_init(); + x_hide_splitscreen(); + x_mouse_init(); + MouseColor=2; + atexit(exitfunc); + + /* DRAW BACKGROUND LINES */ + + for(j=0;jScrnPhysicalHeight-60;i--){ + x_adjust_splitscreen(i); + } + x_printf(10,25,SplitScrnOffs,2, " Even better for scrolling games etc."); + + x_cp_vid_rect(0,0,ScrnLogicalPixelWidth,ScrnLogicalHeight,0,0, + VisiblePageOffs,HiddenPageOffs, + ScrnLogicalPixelWidth,ScrnLogicalPixelWidth); + + + x_show_mouse(); + wait_for_keypress(); + + curr_x=curr_y=0; + + + init_object(60,90,4, 12, -1, 1, MK_FP(FP_SEG(bm2),FP_OFF(bm2))); + init_object(30,30,4, 12, 1, 1, MK_FP(FP_SEG(bm),FP_OFF(bm))); + init_object(80,120,4, 12, 2, 1, MK_FP(FP_SEG(bm),FP_OFF(bm))); + init_object(300,200,4, 12, 1, -2, MK_FP(FP_SEG(bm),FP_OFF(bm))); + init_object(360,30,4, 12, -1, -1, MK_FP(FP_SEG(bm),FP_OFF(bm))); + init_object(360,10,4, 12, -2, 2, MK_FP(FP_SEG(bm),FP_OFF(bm))); + + x_hide_mouse(); + + while (!kbhit()&& !(MouseButtonStatus==LEFT_PRESSED)){ + animate(); + if (objects[0].X>=curr_x+ScrnPhysicalPixelWidth-32 && + curr_x < MaxScrollX) curr_x++; + else if (objects[0].X < curr_x+16 && curr_x > 0) curr_x--; + if (objects[0].Y>=curr_y+ScrnPhysicalHeight-92 && + curr_y < MaxScrollY) curr_y++; + else if (objects[0].Y < curr_y+16 && curr_y > 0) curr_y--; + x_page_flip(curr_x,curr_y); + while(StartAddressFlag); + } + while(MouseButtonStatus==LEFT_PRESSED); + while(kbhit()) getch(); + + clear_objects(); + x_page_flip(curr_x,curr_y); + while(StartAddressFlag); + + + x_set_start_addr(0,0); + + + for (j=0;j<4;j++){ + x_hide_splitscreen(); + delay(100); + x_show_splitscreen(); + delay(100); + } + + + for (i=ScrnPhysicalHeight-60;i<=ScrnPhysicalHeight;i++){ + x_adjust_splitscreen(i); + } + + x_hide_mouse(); + subsequent_page(); + x_printf(textwindow_x+24,textwindow_y+18,VisiblePageOffs,6," Palette functions."); + x_printf(textwindow_x+23,textwindow_y+17,VisiblePageOffs,3," Palette functions."); + x_set_font(2); + x_printf(textwindow_x+5,50 ,VisiblePageOffs,9, " A number of palette manipulation functions"); + x_printf(textwindow_x+5,50+8 ,VisiblePageOffs,9, " are provided. You have already seen some of"); + x_printf(textwindow_x+5,50+16,VisiblePageOffs,9, " them in action. Another common operation is"); + x_printf(textwindow_x+5,50+24,VisiblePageOffs,9, " palette fading. "); + + i=0; + ch=255; + while (x_cpcontrast_pal_struc(pal, pal2,ch-=2)){ + x_put_pal_struc(pal2); + x_rot_pal_struc(pal,palscrolldir); + i++; + }; + for (j=0;jm-cYN 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 wCULL(co{leDxBGk5O0 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 +#include +#include +#include +#include +#include +#include "xlib.h" +#include "xcbitmap.h" +#include "xpbitmap.h" +#include "xvbitmap.h" +#include "xbmtools.h" +#include "xtext.h" +#include "xrect.h" +#include "xrect.h" + +/* Macro to make pointer parameters model independent */ +#define FARPTR(x) (MK_FP(FP_SEG(x),FP_OFF(x))) + +char turtle[] = { + 20,30, +/* | . | . | . | . */ + 8,14, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 2,14, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 2,14, 0, 0,14,14,14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 2, 5, 0, 4, 4, 4, 4,14,14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 2, 2, 4, 4, 0, 4, 4, 0, 4,14, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 4, 4, 4, 0, 4, 4, 0, 4, 4,14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 4, 4, 4, 0, 0, 0, 0, 4, 4,14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, 4, 4, 4, 0, 0, 0, 4, 0, 0, 2, 2, 0, 0, 0, + 0, 0, 0, 4, 0, 4, 4, 4, 0, 4, 4, 4, 0,14, 0, 0, 2, 2, 0, 0, + 0, 0, 0, 4, 4, 0, 0, 0, 4, 4, 0, 4, 0, 4, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 4, 4, 4, 0, 4, 4, 0, 4, 4, 0, 4,14, 2, 2, 2, 0, 0, + 0, 0, 0, 4, 4, 4, 0, 0, 0, 4, 4, 0, 4, 0, 0, 2, 2, 0, 0, 0, + 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4,14, 2, 0, 0, 0, 0, + 0, 0, 2, 2, 0, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 4, 0, 0, 4, 4, 0, 4, 4, 0, 4,14, 0, 0, 0, 0, 0, + 0, 2, 2, 0, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 4, 0, 4, 4, 4, 0, 4, 4, 2,14, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 0, 4, 0, 2, 2,14,14, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 4, 4, 2, 2, 2, 2, 2,14, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 5,14, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 2, 0, 0, 2, 2, 2, 0, 2,14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2,14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + +char far *pbm, far *vbm; +char far *newfnt; + +char far * +AllocatedSprite(int width, int height, int logical_width, char far * bitmap) +{ + char far * result; + int size; + + pbm = farmalloc(width * height + 2); + x_bm_to_pbm(bitmap,pbm); + + result = farmalloc((width * height * 7) / 2 + 25); + if (result == 0) + return(0); + size = x_compile_bitmap(logical_width, bitmap, result); + + return farrealloc(result, size); +} + + + +void load_user_fonts(){ + FILE *f; + int i; char c; +// f=fopen("c:\\font.fnt","rb"); + f=fopen("smalbold.fnt","rb"); + newfnt = farmalloc(256*16+4); + for (i=0;i<256*16+4;i++){ + fread(&c,1,1,f); + *(newfnt+i)=c; + } + fclose(f); + x_text_init(); + x_register_userfont(newfnt); + x_set_font(2); +} + +void +main() +{ + int i,j,k; + + double ratio,ratio2; + struct time pbm_t0,pbm_t1,cbm_t0,cbm_t1,vbm_t0,vbm_t1; + long vbm_ticks,pbm_ticks,cbm_ticks; + char far * TurtleSprite; + + x_set_mode(X_MODE_320x240,360); + + TurtleSprite = AllocatedSprite(20, 30, 90,FARPTR(turtle)); + + vbm = x_make_vbm(MK_FP(_DS,turtle),&NonVisual_Offs); + if (!vbm) { + sound(1000); + delay(100); + nosound(); + } + + load_user_fonts(); + x_bgprintf(0,0,0,14,0, + "This is a demo to show the speed difference between"); + x_bgprintf(0,8,0,14,0, + "compiled, planar and video bitmaps. The bitmap:"); + + x_put_cbitmap(140, 18, 0, TurtleSprite); + + x_bgprintf(0,48,0,14,0, + "This demo uses the NON CLIPPED, MASKED versions of"); + x_bgprintf(0,56,0,14,0, + " 'PBM' and VBM' put functions"); + x_bgprintf(0,78,0,14,0, + "Press a key to start with PLANAR BITMAP demo"); + + getch(); + x_rect_fill(0,0,ScrnPhysicalPixelWidth,ScrnPhysicalHeight,0,0); + + + gettime(&pbm_t0); + for (k=0;k<3;k++) + for (j=0;j<(ScrnPhysicalHeight/30);j++) + for (i=0;i<(ScrnPhysicalPixelWidth/20);i++) + x_put_masked_pbm(i*20, j*30, 0, pbm); + gettime(&pbm_t1); + pbm_ticks = (((long)pbm_t1.ti_hund + +((long)pbm_t1.ti_sec*100) + +((long)pbm_t1.ti_min*6000)) - + (((long)pbm_t0.ti_hund + +((long)pbm_t0.ti_sec*100) + +((long)pbm_t0.ti_min*6000)))); + + + x_bgprintf(0,0,0,14,0, + "Press a key to start with the VIDEO BITMAP demo"); + + getch(); + x_rect_fill(0,0,ScrnPhysicalPixelWidth,ScrnPhysicalHeight,0,0); + + + gettime(&vbm_t0); + for (k=0;k<3;k++) + for (j=0;j<(ScrnPhysicalHeight/30);j++) + for (i=0;i<(ScrnPhysicalPixelWidth/20);i++) + x_put_masked_vbm(i*20, j*30, 0, vbm); + gettime(&vbm_t1); + vbm_ticks = (((long)vbm_t1.ti_hund + +((long)vbm_t1.ti_sec*100) + +((long)vbm_t1.ti_min*6000)) - + (((long)vbm_t0.ti_hund + +((long)vbm_t0.ti_sec*100) + +((long)vbm_t0.ti_min*6000)))); + + + + + x_bgprintf(0,0,0,14,0, + "Now Press a key to start with COMPILED BITMAP demo"); + + getch(); + x_rect_fill(0,0,ScrnPhysicalPixelWidth,ScrnPhysicalHeight,0,0); + + gettime(&cbm_t0); + for (k=0;k<3;k++) + for (j=0;j<(ScrnPhysicalHeight/30);j++) + for (i=0;i<(ScrnPhysicalPixelWidth/20);i++) + x_put_cbitmap(i*20, j*30, 0, TurtleSprite); + gettime(&cbm_t1); + cbm_ticks = (((long)cbm_t1.ti_hund + +((long)cbm_t1.ti_sec*100) + +((long)cbm_t1.ti_min*6000)) - + (((long)cbm_t0.ti_hund + +((long)cbm_t0.ti_sec*100) + +((long)cbm_t0.ti_min*6000)))); + if (cbm_ticks==0){ + cbm_ticks=1; + pbm_ticks+=1; + vbm_ticks+=1; + } + ratio = pbm_ticks*(double)1.0/cbm_ticks; + ratio2 = vbm_ticks*(double)1.0/cbm_ticks; + + x_set_font(1); + x_bgprintf(0,ScrnPhysicalHeight-30,0,14,0, + "s/100 PBM=%ld VBM=%ld CBM=%ld - %4.1lf:%4.1lf:1", + pbm_ticks,vbm_ticks,cbm_ticks,ratio,ratio2); + x_set_font(2); + x_bgprintf(0,ScrnPhysicalHeight-16,0,14,0, + "Timing is rough but still, quite impressive ! "); + x_bgprintf(0,ScrnPhysicalHeight-8,0,14,0, + "Clipping slows things down considerably. "); + + + getch(); + x_text_mode(); +} + diff --git a/16/xlib/demo2.exe b/16/xlib/demo2.exe new file mode 100755 index 0000000000000000000000000000000000000000..d6dfd068ee779e9c2e9c8a528a3b4a037439f937 GIT binary patch literal 38496 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 Fe*;Cgs_*~+ literal 0 HcmV?d00001 diff --git a/16/xlib/demo3.c b/16/xlib/demo3.c new file mode 100755 index 00000000..cfc6559e --- /dev/null +++ b/16/xlib/demo3.c @@ -0,0 +1,62 @@ +#include +#include "xlib.h" +#include "xdetect.h" +int processor; +void main(void){ + printf("Hardware detection demo...\n\n"); + printf("Graphics Card : "); + switch (x_graphics_card()){ + case NoGraphics: printf("None\n"); break; + case MDA: printf("MDA\n"); break; + case CGA: printf("CGA\n"); break; + case EGAMono: printf("EGA Mono\n"); break; + case EGAColor: printf("EGA Color\n"); break; + case VGAMono: printf("VGA Mono\n"); + case VGAColor: printf("VGA Color\n"); break; + case MCGAMono: printf("MCGA mono\n"); break; + case MCGAColor: printf("MCGA Color\n"); break; + }; + printf("Processor : "); + switch (processor=x_processor()){ + case I8086: printf("8088 or 8086\n"); break; + case I80186: printf("80186\n"); break; + case I80286: printf("80286\n"); break; + case I80386SX: printf("80386-SX\n"); break; + case I80386DX: printf("80386-DX\n"); break; + }; + + if (processor==I80486){ + if (x_coprocessor()) printf("80486-DX or 80486-SX+FPU\n"); + else printf("80486-SX\n"); + } else { + printf("Math Co-Processor: "); + switch (x_coprocessor()){ + case 0: printf("8088 Assumed\n"); break; + case 1: switch (processor=x_processor()){ + case I8086: printf("80287 Assumed\n"); break; + case I80186: printf("80187 Assumed\n"); break; + case I80286: printf("0287 Assumed\n"); break; + case I80386SX: + case I80386DX: printf("80387 Assumed\n"); break; + }; + }; + }; + printf("Mouse Driver : "); + switch (x_mousedriver()){ + case 0: printf("not installed\n"); break; + case 1: { + printf("installed (Mouse Driver vers %d.%d)\n", + (MouseVersion>>8),(MouseVersion&0xff)); + printf(" "); + switch (MouseType) { + case BUS_MOUSE: printf("Bus Mouse on IRQ");break; + case SERIAL_MOUSE: printf("Serial Mouse on IRQ ");break; + case INPORT_MOUSE: printf("Inport Mouse on IRQ ");break; + case PS2_MOUSE: printf("PS/2 Mouse on IRQ ");break; + case HP_MOUSE: printf("HP Mouse on IRQ ");break; + default : printf("Unknown Mouse on IRQ ");break; + } + printf("%d with %d buttons.",MouseIRQ, MouseButtonCount); + } + } + } \ No newline at end of file diff --git a/16/xlib/demo3.exe b/16/xlib/demo3.exe new file mode 100755 index 0000000000000000000000000000000000000000..ef3a06a2b7037cf10439b7ec0f3880eb055affa2 GIT binary patch literal 9516 zcmeG?Yjjgpy8Ap6laK})il}o4Y9mmnN}Ph0M-k>!bS!~tN=1q&Euzpe=}9_{(3X`M zXtGNL*Q^ss z2{ihty;KOw@1O*s{0zzpC=Wro3(7<&7APZVFLfTuS5Ug3ybk3#C=F1ag0cw8bST+S zCPL|=Pf#B~ISS>*>wi#{e|P@BEO6)qmFv&iNjKfmF&XF52n*9uuy^lf)W|=J{6Y=# z=k7%E!_=M{6bw7UxCdW6sMf{K{<&}ALi=paGg#kIKXk%x_Mn3_>hANkSbTj0e&HF^ z*p+kU?GscmV#o8&uv=6_SL@$KwA~M_{cQJlh56rAGto;F{*3AM3x1Hb9qoA*<@5x@ zP4|~{OkUOf^>DBYe?1ZcCSi@t5zYgrcHKC3h z{8?L&-|Rz%uw)7qz?k3Ki0o}T%JGdR`|xi#5HBAo_c#4CAc8Un&FIkWD9TVm2>rNYvR_yM)?SH1tkzfsjnyc` zX^khKQI0~q)>sRTbtr_g8;=Hi4@p$VHS?SNcdJ?a4(|4~@Je6)$I^|s7rMB~N zwA$4Yc>S%V2_;!f&{&x4v)58?-X2&>B^Z49PZ&fJ48ko<1=`%S92C%@xhOX%?4;#0 zYKTF^axZ`rv*Cwvzi(a}ZS!y;3Mn^Xp^e^8clTjYk6pZf+iuSP+uw64-$pyaE8E)v z+l9S)lXVrF6B~ZCaZC_z7uD@id zw&0%bQ{ATrPt?C-=~j&0?e$U1^Nw)$>2{r&H@>&oG}JxR>1&~Uok+QzX{lznG$TtO zx}WX(lD-g-yJhBB;7E1``T_LL9D;rZ&@Tb{*E3J%bdM%Tn1nSBZW`~4FRx_|mmq&$ zkPZBD2m1mZP{s^>>Wkk|7me^iR#p9Zbtt5&Fld?#8f?kBqlsJ2^P(`$O7XUR}ZF@O!hWzM&Zzjp&s7}wB7q@ zpJiuG*U-70L+A1utYV)*86ZtkH-#)m&MZ>Bx{N>7Kb8==>uO4Os<}74D&VBH=+9^M-CT9-x?d;p~rwUfR+;ne1G(j5| z8L&$ai=I|Er~FC$#g*+#12SwynwbNA-AXCb9{2?8?d!|P@AT05EiDH*ly6?cR?o&K zI{PBqDp-W@JBO@j=nU>@+tx#?$rg8bn;-xT3evADh zTD=@Xv~!66h(@%eIXJj6c#fmXxl9NFBS3E*>uWXb?oZHeO3|K4)1FDt(nuLiD{Hh3 zgtjHnCetX;eB8426jZjJVt3qTEx7IV7MS2I{l7u3l8E>%LJ_gw314RrQtmG~sH!u= zXa79Zxp-AeUISMcFY5O=ikB|qw{Lw)&AFIGUd|HLYf`-i)n$h9a6n2Wm{7IfZa@5# zs(Yk#MGGGzRex;^*T!1Cy!{Q>Ovla1mc}Nz)_o)YNmbJ zh#0q_hN24*@uI3m#6eY6X!{#8zre?EPrYKRA9<`gGw_FVtZ!t3mx=CRI{R|fKlu#N ztxWx8RCCc+6sMFAN%b43(n>3-p02OGkRve-t_w<&uOj}L!UD{8fK&d1Kpz|uFt-s8AKK6@)@gvdIq)~nJ z0IQ0F(TCLMr{D1c5YkzZlxYVG4Q^ z9WNFZ`n^01%7P>=508gtExWz;Etsxx#x9T9S38J2ro1)|;fP`diR?0GR!Jc8f-@iv zJB#H>u`F0_gT}7SO!Pd8sze?z++KSKm$7;3tc45xWh}6_A<2@5Cuq$qogBQp@1EDQ zbdSitx=eV3N(e?Uvc2d~&ZTW10>k{yIvRII_aI=FR+iW}O9$G`{36fK9i&jS^$J`Q z;u({N=MpqQXH*qqUMp#^jbUTN!wI^#`&n7MoL@BPWpL48blVkTXu?j!9OO|}$SN12V__l+9(cf4d6wQxfCw=~XF(D0Oq0Uzv&kD` z59FVy8-%U`BpLVJAwL=mh$FHqhFxbt&D(O0=JeVF?3@{revVCI=j3>F_BZ5NvBeK; zJKCoM{OPgNm!LW>=Y;)@)H-BfwoeZjPu5bd6y< z18BjXgrZankR}MjjVBoaAT9R2G-^DVFTn9SG05{MD6k-tNA^ajz`#B-1W&erzC_WM z+&v!|V3(QP*u85wcr1_L=QRRpV-|~o-7jl2gt$c`Bpe8ooDi-O=;|TIrLjxOfB_vh zcsO}~9Q4dkH3O_FTiNc^YG4Vc{4)kj0Vk(qJ!C;S$4HG*Uh=oy$Bm82^4^VPx%Gn^%bA2v0AHRwm z3`)q0mksrB7UVby(mH97_J}5qxmW2RoN@0|FgB9~X6=Ra)ejDWdo?ScOep}CaCBjj zSFVE^7z3*KUE|TDb)+&b6ZyK3d%;lifa=L7kwo`t!)eWRz-~6Ezyx$j<8W`V_ihkY zeG|^&QGT~)K(?#OB>8V~|j>lY-5>P>f*=vHRa<5gvl=?%W?iHM60&i#?Zj$TV+m_rtVNM1ckw7fzR|5lhvc5lnl+x3a{Cign1BD zCQS@Z(QC-v`-#DLQo4tjUYeh@d4Xp0dr~$B&e)7l{=05-jShE%G-a}Uud3W6zY|v` zEOVOWIdKrDn2MqLBcc+RJZ)f*3_&k1=Hxw#d~Ngh^WER(=WXRYKRy{`C2FUW>t(+2qyq0N(v@^m# z2b+W=41qOEqF8M9L&CicK~{rBR<63>wqY|c7oJOXJ$j*LOd`sam#ZY=BAX{kd&n~N z_3QU+M~<%jtlW5x;W6<>Mr1Qxyl*&TQ$`&J%gd`jq^g9-g|i^R#t0YjaFENJ&iP$& zzZgrYAfG+&{`(c-aV*B<&(7C0g8&SJ_lv`R*G1JESG_U$gE(v}uVDy5#ETG-x2X0Y z2kJE44>K1OAyIH^YVxq~Jm;2c8G{Qq13n6!20Jd%+x>-R zyT8Pw+^^i1kj2{>T>&1jPo3qw7RkBH9w=nBKz*&w*Q(ENlQIbrD1vB@-tJpMTcXQV zGI1mi^!2l@5?EJxYuLuJctngHr$7U1ud4AO~pFFKlYn(@1MfHZ+=0rD)=ATTCeV)Bb|zbmE@ zXDegWq8O1~Ki}Y?MEuTT5Y?|(p-UC7>4l7rBv6{`fy0{<85C%`GF}SlN#bOF%onFT z6UgX6xmto#EdNw}ajIyT=rWP+Eo^%uL9xe2Jf=O`35OJv`a~BqeAqq^GJ7Fw&LHtEZjE!~0;i^GPK;_%x zV4T=QR~*A1ET}IN4qwvP+gi&X@j_r|?u^FH{jr*QHQ1XtMabz1eiSMl?-W9iwIw)h z7Y$Ci?5qZAEz{f83`n$!10t_ECI|Z^pI{ALuLwLr@y%B^KV(;RWGUEjjmfSSngUq@ z4;N+))}UxeE+r=V5LG`<;0=<2yvD#{T1b&B&P&$gsu-DlF!JpbS&6w+)J_rR;CMR_ zct5-$3^i!-U?C{Iq_$-VjVQaX4kD2%;wh4*EN~l};C6r@;X+89?Ee2-y#weP^(0WnHmj%C+M$rfE!0UKmtnA=nLP$v}&9^w-KtuQo4yao)Bu_oM}&KhEPsF zmqMON37Eh;Q&I?@y-BcSPI7@=fr)+--!1S>C^47GdF0LVqj1tBCd$`OyGn4a-d`I} zE@a3na+RAC8+vP*L4_F#=w5J|<=Y66wn`k~=wS*+mcWdB9NiBSk=g;6=#+%PL3BH8 zg>`)Ox|HR4vfuo6STodNLPA#4s0DJBeG*VIuD^c^!%k-ODJs(cCWKh}{0IoTgNklY zqti4su#SmrvJ;UW6F7=Jr;vxaRji5O09lr%065n@>L{jajoGf&m;nBD%-0HTM0PkP zLfnF?Getju`TSS)&Hg9)GHHG5Q52%8X9-KqH;)q)fGr@NNNfz+Wg5)C8G9{cvq>Cx z9-~jC>-a5kwa%-ZeBVQ2(g+!1#+F)MhSMg(H*yeaSbg&X&^rctkJBDL!Uv$2upx^r z>&o5roDEg)X9H|U_geXCo=u9)Lw&N1IfWIVZP z5!~ku*CY2F4dRVCx^f15y~vg2B+{#hbbJg#iE-NDLt?O{AT$Sr{)A98YVnt^b{K)* z{9L`732rlny|=pH&dm*XZotl#W@iR=(thB?H0QLDMB0=NE3{irVk!zjRK+2uGFfOU z(C$7>N66jhBzJ~WL)!8j9GsTr3hR`+qS~oKf||pS0{%ciV@w7#d4r{;MI@ksOY_f3 zC_xS}A@pnHeCe4?1d*>0+Mlk!G!`A9aF1_9U-N)=OE;DlLPyeIB~J*oBV|Ac9Ye|) zA@p~od?AEBL&~Q@=u8?*2%SgD`$9-XN}CWeP)b+`WlxIy4ib$DH5h)@?q&O+%Q{TK@9OwDbOHp6}p${*F9-$Og2uW9H9}_~g=~fC+ z2d9K&Q5FfI=hHAH?`lnM(=@pZKkw|mf-_DC{gFRW9cHD0iXepUqlq6cLXf>Mv?}&uWa8(9j02Tqtr2KI&}|KK#A~q1?@xs zgZ_$|(HwL?av~Rc6g`eAk%WE$84g9$EJJfVt=H*EoP%!Yu*|u^GroSrRA-#2&io=b zunkhQyJ0mecQuWB%Yr&Az7dOLZ5sEcrNd%SArxhhGLhtQ){e2a-Vv7BnP0$tn{E!{ zISPB9=6SmylzVyC@@zCP7Y%qam%<9$Ke_u>vq`ywK2s3&S+=i}>Rj0B0L!hi z{X&=y-HJLKexaFe$Ze$?%tvUr{KW69YzOP1d#l{*S68mFEzHTW&9E)3+W3rn-P$K5 z+nsmceWxu2TwE!w&qa&YdDpEex0SoyRqio{1&>!&xi_p{Z`|5% zEv>7n90ONE|LS9dA&q+OTkT#`v)Wy5TT?ETKS7v5Z9`RVZmz+A3f-$WKDq9RYTH7< zvcYqY4HZ>YmK)H6ixwEr!b14^N#O$9gH@GPiQ2-d^;K>Ia-};-E!p`X;M+E6s9H7I z?Q~Z?QC?kLMUGiT4TjcVRGx_K?oF&g+_m8ZJgw#dEC zTb>vPFt4nVZ0jnkrPb@#6YlA%ZOT>HKv8YWUXz=>W~u>c2DthQ-Rr3a3lsh@Ig6Jq zMaAXrb>Il2`)p`&<;E(vbWNwT`1YCCblvB?rsLttrz@*!DzE9yUSq3S2L^-p;~q(> zs;tgUdky@Sh*AZi>&WHksOLDe4K)12$fyT?rb0Ai8l#^WG#5fnJ^Hag^IjT$i5vCY zdNs-@$iJ)qXaOst9;4yI?xuJDBlMb{OxVjgUa!|%$8(wHEDnzGsne&BM|*MH)Cm*J zqo0iFx6sowrU63cjW^LWmqAaMGA(mj66F^2O;aY^lASpPAv$_X zG_o?R^*S!~kiO)TF(E?_Rh=~})ngr#u30UHjEoGu!D{8L +#include +#include +#include +#include +#include +#include "xlib.h" +#include "xvbitmap.h" +#include "xbmtools.h" +#include "xtext.h" +#include "xrect.h" +#include "xrletool.h" +#include "xfileio.h" +/* Macro to make pointer parameters model independent */ +#define FARPTR(x) (MK_FP(FP_SEG(x),FP_OFF(x))) + +char turtle[] = { + 20,30, +/* | . | . | . | . */ + 8,14, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 2,14, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 2,14, 0, 0,14,14,14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 2, 5, 0, 4, 4, 4, 4,14,14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 2, 2, 4, 4, 0, 4, 4, 0, 4,14, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 4, 4, 4, 0, 4, 4, 0, 4, 4,14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 4, 4, 4, 0, 0, 0, 0, 4, 4,14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, 4, 4, 4, 0, 0, 0, 4, 0, 0, 2, 2, 0, 0, 0, + 0, 0, 0, 4, 0, 4, 4, 4, 0, 4, 4, 4, 0,14, 0, 0, 2, 2, 0, 0, + 0, 0, 0, 4, 4, 0, 0, 0, 4, 4, 0, 4, 0, 4, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 4, 4, 4, 0, 4, 4, 0, 4, 4, 0, 4,14, 2, 2, 2, 0, 0, + 0, 0, 0, 4, 4, 4, 0, 0, 0, 4, 4, 0, 4, 0, 0, 2, 2, 0, 0, 0, + 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4,14, 2, 0, 0, 0, 0, + 0, 0, 2, 2, 0, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 4, 0, 0, 4, 4, 0, 4, 4, 0, 4,14, 0, 0, 0, 0, 0, + 0, 2, 2, 0, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 4, 0, 4, 4, 4, 0, 4, 4, 2,14, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 0, 4, 0, 2, 2,14,14, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 4, 4, 2, 2, 2, 2, 2,14, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 5,14, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 2, 0, 0, 2, 2, 2, 0, 2,14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2,14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + +char far *pbm; +char far *newfnt; +int far *buffsize; + +void error(char * string){ + x_text_mode(); + printf("%s\n",string); + exit(0); +} + +void load_user_fonts(){ + FILE *f; + int i; char c; + f=fopen("var6x8.fnt","rb"); + newfnt = farmalloc(256*16+4); + for (i=0;i<256*16+4;i++){ + fread(&c,1,1,f); + *(newfnt+i)=c; + } + fclose(f); + x_text_init(); + x_register_userfont(newfnt); + x_set_font(2); +} + +void main(){ + int i,j,handle,size,comp_size; + char far * tempbuff,far * diskbuff; + + pbm = farmalloc(20 * 30 + 2); + x_bm_to_pbm( MK_FP(FP_SEG(turtle),FP_OFF(turtle)), pbm); + + x_set_mode(X_MODE_360x240,360); + load_user_fonts(); + + x_bgprintf(0,0,0,14,0, + "This is a demo of RLE compression of 360x240 video screen to "); + x_bgprintf(0,8,0,14,0, + "disk. Uncompressed, this screen requires a file of size "); + x_bgprintf(0,16,0,14,0,"86400 (360x240) bytes."); + x_bgprintf(0,48,0,14,0, + "Press a key to draw the image and save it to screen:"); + + getch(); + x_rect_fill(0,0,ScrnPhysicalPixelWidth,ScrnPhysicalHeight,0,0); + + for (j=0;j<(ScrnPhysicalHeight/30);j++) + for (i=0;i<(ScrnPhysicalPixelWidth/20);i++) + x_put_masked_pbm(i*20, j*30, 0, pbm); + + x_set_start_addr(0,240); + + x_bgprintf(0,0,240*90,14,0, + "Now compressing and writing to file 'screen.dat'."); + x_bgprintf(0,8,240*90,14,0,"Please wait... "); + + + if((handle=f_open("screen.dat",F_WRONLY))==FILE_ERR) + error("Unable to open 'screen.dat' for writing."); + size=0; + tempbuff=farmalloc(90*240); + diskbuff=farmalloc(90*240); + buffsize=(int far *)farmalloc(2); + + for (i=0;i<4;i++){ + x_select_default_plane(i); + if (!(j=x_buff_RLEncode(MK_FP(0xA000,0),tempbuff,90*240))) + error("Error buff compressing"); + *buffsize=j; + f_writefar(handle,(char far *)buffsize,2); + f_writefar(handle,tempbuff,j); + size+=j; + } + comp_size=size; + f_close(handle); + + if((handle=f_open("screen.raw",F_WRONLY))==FILE_ERR) + error("Unable to open 'screen.dat' for writing."); + for (i=0;i<4;i++){ + x_select_default_plane(i); + f_writefar(handle,MK_FP(0xA000,0),90*240); + } + f_close(handle); + + x_bgprintf(0,8,240*90,14,0,"Done. Press a key to restore."); + getch(); + + x_rect_fill(0,0,ScrnPhysicalPixelWidth,ScrnPhysicalHeight,0,0); + x_set_start_addr(0,0); + + if((handle=f_open("screen.dat",F_RDONLY))==FILE_ERR) + error("Unable to open 'screen.dat' for reading."); + + size=0; + for (i=0;i<4;i++){ + x_select_default_plane(i); + f_readfar(handle,(char far *)buffsize,2); + f_readfar(handle,diskbuff,*buffsize); + j=x_buff_RLDecode(diskbuff,MK_FP(0xA000,0)); + size+=j; + } + f_close(handle); + + getch(); + x_text_mode(); + printf("screen size = 86400 compressed = %u",comp_size); +} + + \ No newline at end of file diff --git a/16/xlib/demo4.exe b/16/xlib/demo4.exe new file mode 100755 index 0000000000000000000000000000000000000000..54c567da28eabcd246c89cf9b586c7efb0136252 GIT binary patch literal 22750 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 literal 0 HcmV?d00001 diff --git a/16/xlib/demo5.c b/16/xlib/demo5.c new file mode 100755 index 00000000..6bc35d5f --- /dev/null +++ b/16/xlib/demo5.c @@ -0,0 +1,148 @@ +/************************************************************************* + +DEMO 5 + +Demonstrates Planar Bitmap Clipping Functions + +Themie Gouthas +**************************************************************************/ + + + +#include +#include +#include +#include +#include +#include +#include "xlib.h" +#include "xpbitmap.h" +#include "xpbmclip.h" +#include "xrect.h" +#include "xbmtools.h" +#include "xline.h" +#include "xtext.h" +/* Macro to make pointer parameters model independent */ +#define FARPTR(x) (MK_FP(FP_SEG(x),FP_OFF(x))) + +int i,j; + +char turtle[] = { + 20,30, +/* | . | . | . | . */ + 8,14, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 2,14, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 2,14, 0, 0,14,14,14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 2, 5, 0, 4, 4, 4, 4,14,14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 2, 2, 4, 4, 0, 4, 4, 0, 4,14, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 4, 4, 4, 0, 4, 4, 0, 4, 4,14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 4, 4, 4, 0, 0, 0, 0, 4, 4,14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, 4, 4, 4, 0, 0, 0, 4, 0, 0, 2, 2, 0, 0, 0, + 0, 0, 0, 4, 0, 4, 4, 4, 0, 4, 4, 4, 0,14, 0, 0, 2, 2, 0, 0, + 0, 0, 0, 4, 4, 0, 0, 0, 4, 4, 0, 4, 0, 4, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 4, 4, 4, 0, 4, 4, 0, 4, 4, 0, 4,14, 2, 2, 2, 0, 0, + 0, 0, 0, 4, 4, 4, 0, 0, 0, 4, 4, 0, 4, 0, 0, 2, 2, 0, 0, 0, + 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4,14, 2, 0, 0, 0, 0, + 0, 0, 2, 2, 0, 4, 4, 4, 4, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 4, 0, 0, 4, 4, 0, 4, 4, 0, 4,14, 0, 0, 0, 0, 0, + 0, 2, 2, 0, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 4, 0, 4, 4, 4, 0, 4, 4, 2,14, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 0, 4, 0, 2, 2,14,14, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 4, 4, 2, 2, 2, 2, 2,14, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 5,14, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 2, 0, 0, 2, 2, 2, 0, 2,14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2,14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + +char far *vbm; + +void error(char * string){ + x_text_mode(); + printf("%s\n",string); + exit(0); +} + +typedef struct { + unsigned int size; /* valid only for the first header */ + unsigned char ImageWidth; + unsigned char ImageHeight; + unsigned int ImagePtr; + unsigned int MaskPtr; +} alignment_header; + + +void main(){ + int i,j,k,handle,size,comp_size; + char far *bm; + + alignment_header far * tempbuff; + x_set_mode(X_MODE_360x240,360); + ;NonVisual_Offs=16384; + + x_text_init(); + x_set_font(FONT_8x15); + x_bgprintf(0,0,0,14,0," This is a demo of PBM clipping."); + getch(); + + bm=farmalloc(20*30+2); + x_bm_to_pbm(MK_FP(_DS,turtle),bm); + + x_set_cliprect(4,5,50,150); + + x_line(0,TopClip-1,320,TopClip-1,23,0); + x_line(0,BottomClip+1,320,BottomClip+1,23,0); + x_line((LeftClip<<2)-1,0,(LeftClip<<2)-1,200,23,0); + x_line((RightClip<<2)+4,0,(RightClip<<2)+4,200,23,0); + + for (k=0;k<8;k++){ + for (j=1;j=0;k--){ + for (j=1;j=0;k--){ + for (j=1;jS!shB1OI7B2>_}v>|u@=ia1ES;ldH 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 + +#include "xlib.h" +#include "xcircle.h" + +void main(void) +{ + int i; + + x_set_mode(1, 320); + for (i = 0; i < 120; i++) { + x_circle(0, 0, i, 121 - i, 0); + x_circle(319 - i, 0, i, i - 20, 0); + x_circle(0, 239 - i, i, i - 20, 0); + x_circle(319 - i, 239 - i, i, 121 - i, 0); + x_filled_circle(40 + i, i, 241 - (i << 1), i+1, 0); + } + getch(); + + x_text_mode(); +} + \ No newline at end of file diff --git a/16/xlib/demo6.exe b/16/xlib/demo6.exe new file mode 100755 index 0000000000000000000000000000000000000000..7e26f1f6f78b206425cd0b009e2769502758db88 GIT binary patch literal 13604 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 + +#include "xlib.h" +#include "xbezier.h" +#include "xpal.h" + +void main(void) +{ + int i, r, g, b; + + x_set_mode(X_MODE_360x480, 360); + + for (b = 0; b < 6; b++) + for (g = 0; g < 6; g++) + for (r = 0; r < 6; r++) + x_set_rgb(b + 6 * g + 36 * r, + 12 * b + 3, 12 * g + 3, 12 * r + 3); + for (i = 216; i < 256; i++) + x_set_rgb(i, i - 193, i - 193, 279 - i); + + for (i = 0; i <= 1080; i++) { + x_bezier(i, 240, 90, i, 270, 479-i, 359 - i, 240, + 6, i ,0); + } + for (i = 720; i >= 0; i--) { + x_bezier(360 - i, i/3, 360 - i, i, i, i, i, i/3, + 4, i ,0); + x_bezier(360 - i, 479-i/3, 360 - i, 479-i, i, 479-i, i, 479-i/3, + 4, i ,0); + } + + getch(); + + x_text_mode(); +} + diff --git a/16/xlib/demo7.exe b/16/xlib/demo7.exe new file mode 100755 index 0000000000000000000000000000000000000000..3762184bc87c290f11e651cbef9c921f016bc3f2 GIT binary patch literal 14268 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%0A^zq{C1voalA;y|dm zZHhAvWxQ=}_Ir=gF4|ub4hKprcp^rNv!VC7j$QPm1OAb(gNFZ^q>8-c&er(s@w!F3f&%5-nh&? z3H=M$0N$GQRp^h(I8DofD9vX|vQ1=Re7FI>k$A;x!o@%%PaEl#{h_w~p}zg0uFJ2( zcA>_7q42(y31K$uKkunC{Fd@_W#EGMn{U0zxYrW$){LeX`B`-{&f)uWQ=9QmZ|;vn zjBWeQo}~>pvM_?h;X4VqK$K=kSmNR9<|PznBb%4t({tlJ7G4a)oE&QyFg$xylcWXY z087^YkN?W|RX)NISe(a{pdaPPz0^O87EhwS$-!d$nt`Y8J8Axm zQ4V(o{WFB(j8xyPaUN38XB6BSsrk2FFDWDFzjaiSHRwwjl{6{npR8ht5t9nT*GB~W z0FC->^}Ryi6a4rwLllm;M}ihBvp-U)2`H+3lk0ngz{jNWR#9kd#~HdP2RNiU!^D;Z zaqe_cfK7tAX&~l@iH&jMV2)iB`r3PfIq9POFh^~WWScIwD>NN!)9qsWd1^@$g%&1# zib$bBygf;zxmIycx`;RYa-~h&lM-)D7HJMNxk?xr&7HzfXpT*k&jA7kxs${_Hb5qe z@}EiI!%2Z7lT?ctjLpc=RF6TmzzAZDYOcoILJQJo3F3?E;xFgWZm0b$w3nxY)JzQB|m>yr)-kTZQED5=HVyrX8 z(f$Zm_GLH-Ftr@u12N(`P^KHeZ{UJCGsK`}rs#;3)qCEeA1!R}VT73jo09}|-M}ET zFY~IVbbI}IUT6?Rtf;O4a=Y=Q<21Al*=LEGf+{I{#WR24v#}B%`zwh>o`rucu^ACWMBW9z=So_0^+eQ#atT6)l8`c=<*H{m~C!V*yblsCBPi4%{%*?nuWB&T* zUo3rQ&00^!ckaLcI~l{B3rjrfvdF{F_?~&{>5QjKOV^i3L>-$vERM`~UdJJ;=`!exv)oo}`h9-Gpl<-PW;C zahxGH=^^X+@%vLgOCuA`rHc%!j}V^W=P`Wa&2aL7b50^Z<_h^0LWQnaA7c1xfq!oN zSm;>V)VqfztYy?Gq=YNti-n!KAL@T5{?O2u^knjPtoMx%revqy1I)SUPfYB7ft$=- zKaQll_(*=v-DD(rH;&{q*Db^;@;Fe$$8rN!9(S5Mmo!%EIK^5}++;Kf>an8%ee(76 z)@|eeF=dU0^IUo@v&>rVuST4lly|ccfA_C3`;u1O6q9cwC&|~u$j#zj!~bBY!@W5bW0ELoi~Cu8-x^+--i)?_@to`F}h?8UPoqh!4&W8E_)KYseDF1 N!rR!|u&y5We*qA +#include +#include +#include +#include +#include +#include +#include + +#include "xlib.h" +#include "xtext.h" +#include "xrect.h" + +/* Macro to make pointer parameters model independent */ +#define FARPTR(x) (MK_FP(FP_SEG(x),FP_OFF(x))) + +char *swidth[10]={"0","1","2","3","4","5","6","7","8","9"}; +char far *fonts[20]; +char names[20][20]; +int i,fcount=0; + char c; + +typedef struct { + int dummy; + char height; + char width; +} header; + +void load_user_fonts(){ + FILE *f; + long len; + struct ffblk ffblock; + + if(findfirst("*.fnt",&ffblock,0)!=0){ + printf("No Fonts found in current directory!\n"); + exit(0); + }; + do { + printf("Loading font \"%s\"...\n",ffblock.ff_name); + strncpy(names[fcount],ffblock.ff_name,14); + + f=fopen(ffblock.ff_name,"rb"); + + fseek(f,0,SEEK_END); + len=ftell(f); + fseek(f,0,SEEK_SET); + + fonts[fcount] = farmalloc(len); + if (!fonts[fcount]){ + printf("Out of memory"); + if (fcount!=0){ + printf("- No more fonts can be loaded\n"); + fclose(f); + goto NoMoreFonts; + } else printf("\n"); + + exit(0); + }; + + for (i=0;i?,./ ", + NULL}; + + + + + +void main(){ + int textline; + int strindex; + int height; + load_user_fonts(); + + + + for (i=0;i$Krop}WQ8!? z*%f9wL~-}}V0Z5Zg1X}428~NV7xN-PBTB$k9$r9#+Cw8mUV&to{(jXx6M~n!_ulVu z|M_;X($!U`&N+4J)TvXas+}^cr)n6PO47;wM3QdP_=xgL!$Ui!=c#1!*W!U!*YUt-gwM38@X~ERuk98tEj` zH%Nz(zC=2J^cm7Vqz0rKq}@n=L3$7AU8L{~>PDnGq?fFORNiw-asH$59}@Tf}J;CZ_8C{R8-9hVa&VNZHYf zHKde#mISQDB#^v`2v4ZC6qB-=lp6jpe|49%HhkgT)(I2rBQ@SDzWu)TBLS0_>|)5F zR)4+4-`WmOLlnJ%G0z>O-X1jS%wg{q3|?-xj1M*=24(bsqk)#>Q-hbxJ_QL9S%QKr48+6eN(2SiFOM0y%2 zA89$#Q)Dv-v*voiBoIahc4zHrkikDC^KzP-`Lk7z1)b{s19q9n?)ylHRavXagZl>r ztg|8QxujYxzs$o+E~(bYFAMOJN2)pbWieisl4>%z^wYAVyFIG?1Nzqk#o)b(v(bhA z)@n7f^OURx*#%0LLv}IEHdhlB|22Qyal&((-8WY9nC!u+s^LF6_7$r6TKiJAP z1yL)NQ&CAEt(5YsviHrYajiLQedyBtbS4 zeQbT9dR-l{1VcO22ft%32Zciddmy-Xu$kNfyd{Z(p8@zafd4T3Skj^H4HS{60 zl4|lWpM#Nkaj=ibg7BXm=+5FAO7wh=&fj@g@f=?#Q;@|wO?;*W{p#t1Xgvmdqvqa> z_9N|w{YS{gqT{WWO-TpaFK%kTn7Sds*{T=Y=qt^~*LW{&%sk$Hg#A36nHp5zqc2pe zM~N)sRBu0Zu99rm@@@m~)X&S|znfcUijIs_q{B#H%&PUoRf+#{UBY}RI&$E*rFGpK zIR@!^)%c*(fOlvP@7BR$FrvmKd=q(9?h4SxI}Ki4X^x@EslVF-e7uv3cj~;_(xcVi z8$=F`P%<6EZjg$o{yd=dH|VCjgks5Bea3L3Tzfal6;9{Y=_!}~vkaPm(Uh8$gRbcf zIcmFqtb{4S5Rrw#&;pg#&TCylp%ifI15RDyMrQ;lX(N#OE)10MHJ)9(TTiDBy00Vd zmtOo$jfZJ(ZPjdQ|DLUVslAo`DyM#0P=HaEbtc$)NX%xNgWo`T{HO7d0kP zOK~j7-FeF&_rRBMk$UJva{lbuh^dZ|R{JOI*5qDOT^Bf^f&a*E3IYWpzIct|B z4X?TIZhOn5dG)CqG#Qc1v)+^$)24G9pZlehbTyGaTv>{0NNyAQsX0YO}wMn(qOe@<|}` zLX$IMBO5X=H#x6LQj_zFB#Dgu?ct~S1N>p1X!CVGS=cN1r)vg(XP+WA^a9(`nk>EX zWqjy4)_0v0U-f53RN@yj`y;Z9*g&(Vd?lBYJnRPdWwFY?C~`tnqt5n$Mtq&tPHA^W z7~&m@GTjF%@x_pX`L3(IUk995B6~x* z^ri6A57d(LO6YOv#e4351&xYt`+!;Ryc%D#x~1hLf1u@L%SpCQ<-8giF1P*tdgm2r z`Ul8X< z6>NIN6?AsEW(e_}i7-J|;t#H2LzhTMqV#}pW65qlN1ZB-m@pxbqXv2#@mNy%KJsg# zRw%n(Icj^Nc9!s)>l8OwBIrTq#?0MG*VcalgpQWA4BrykLV&D`St{d1Ew~$gIyIo# zr6Qq*8}%{~uQ8P$L&2=tcu9;;ZJ;me(wg`tug0qV_<})jUUy_(DPsA|E1~r_8sin# zncc;a#H?wF8*@IKF&#!|5DX6QjJ!!yp15iq0V=(y#a~@DM_j^XgUk!)>WHT=@4gy; zu%w6Zec0|BbFWu5DXFD|4Y)7RH&1-fc^O)rFx9?6<1e{DuskRPrOXRLRhVyw>hn2Q zVRk@rjD~o71s8St!ueh!g*l0S)qUUR9pP9k~qE@G~xgfni9qUL6sEg z$9G9z)JA1r?IOdRXIbYtdq4vqsF^k+!``GJBxDNnMQvrU-6i45!NTrNI`h5lzLK-9 zHLOt8sr8qffl^}q6lu3OirxJoS^?Fds3eUn3;||>+f$|>?eS;NLFFE!0pmu|^vx?lS zCH!H3Cs&*-+rUm^m8nuIq^ZQB@;PYka7NZFlQJXXV)+#k5a&wHusE|k54A7`$^Nvb zjKnh}Xn)cOO@e8|#7M{N2&cP*-$!5+Haf4$PM`2zM6?Fokzi4{irGnoqaEv zB$%_pCq!~a%5$PrO)-L7W*Jq^aQQsBJiO+PO3sBUSNU9|9HeasT-lE2^gy)vL~b`w;S&=jyH}$8gEQ7LSofl8=}jpBG-*hy-ToOlcg#4g})&= z)sR+0j!tsw?4z_Ex;z@FAA;S2_XNxV^)RY>zHbqU58~@-{JE-a*>Se@!AaTNlU`T92)owCz44 zxu#pImm6Ke)(CXRAnc=$m{YTLkphbXQVC~|R97rDHgSuMh#ZlvbB$Z)7%^eh($*Yf z`2zZ!XPjHV+hY{j-K&gny`o#JT|>z35@S{R{sEy)Fn~9H$&SR3*)yW-XqlBE{xpWb ze*li(62Wb2P?OoG_nY3c2E9F@5 z8@S!#p_6jO43{vLR?HqFNuIt4%Rtrv5Gg}|gpfcYgAf6!PpNse{uV7YT`fm~qPK4{ zZxU~64uR6uf&F;Ht^Ky8*xjvX)VrC zvZD`ySm7OfB1asDylsMA68j5(jfnk(B1!BGend<0C1Fs6x9Vh8(19*F&q(G|e=@uA z_oCTt5(*^r1^yT_yS{%}9cP`vqYvT9AFB!94yWbfYaltIv?jf*ru1-n+2IrkF2$$o zt`SQSyNg&_zNP;zzD9S&MV8VU4Y5!_`Zz2el4+WR&g)cMREWtAOcu{0d?$Ogtcm|A zsm&fpg;r8&aW1Nl*zO!+TViUBAW8tUOw{0^Bm6~^P)SkoU&#Zaz_W*E(AguA7!6s> zA}7n3ZeX!pj*1vc@sl~Z;-WeJm}e9fy=QDx=IOG`N5y0g%)E&Z$G!qnv6epsYT^K4 zyd>Ts)JDWU(_JQEbOhu?!wh8aq%1+?T>=JWETEh-DfL<6ZydXWJ9N&G`nu8E6Jrlo zp<*Lck|(hGq7!xB^NE`X-^e0t=%|CkbAdKyW87Uus{VB<|dZhbyhH1(%qqq2V&W=gW* zr285~gXlEH!oOuBNjbPfExdP*<#?)%tW({~&G|dbtIcaQm|jJ?-I7H8CO4mmxFb*a zOb+h2u=QNP9f5ZcV?p??t>AArh)1xR3kTbZ>p*}<=L61;fcvUc6p@O;!sjsIo5A7<29Z0ac`Vrpe`2Ds?8|utZ}jCgA{{bO*a#m5tyD zg+W&oDA~a?Qaq}lliT_xR-~wh!??5f5)NKY7CatcKuM&@8CDTTk!6jZ|2j}a zUnPm}5QhRsw?-E)(GGE0!Wm=~#PHr0t61zloDtR;b~JhScb68NIxZT?qfr{+H<#x& zOZH0YP9cB;^=%ROeX@6rI7iCC+3gpDhpR|1aiQ@q2!;e(h8@`8mV&K8r$pm3viifn zvh#hYTjl8EG43Q)j8J`rz6Sb4>PDeufjZLo9=ul_N~p&r(=t$1Pz&vJPYt!?odyTD z)Y#=xU~>(LL4Y(4B|IrXFAx*@8OSAoEKqzuVGKaR;uHRoOW3-hmtpF^cDRJO5;)Qc z_A5|Z#9BE!Kf>?i7`hAg+zF6K6z)O90E6Gan+15B(0-W$V_65Vp5dFOVr;fyLn!y| z=;dy%J}gVjqrOe?sCz~uByz}Zy5PNtK&{*jh12OmBoYmoK?FH^SyMP=L$eR=5%x6) z97l@pbzCbR>Nv4>u;W7UfQQ`b;yWBg>a~5aSL+oom6+qNl*Ic>)TAWlgJCIGL<=hv zOn%b1!zRYdA~*Y;I%d4XtuAScLaaMmPNF=+;~u4w+4i!b`&GUYwF*T;R1v2k;?zf+ zx`>nWm6$jbZh|weuOf&N805d4{8uOcMR|I(0w$pYfjk4EMNdj7Q^2}6p?N_4*x3zA zsi(*UhjepOg~AOqXsV+GLYozaVuWQ<6G5?yr5hYA>CRF2PTa@??d<=6qc*orXg6w1>HJf*F`!x3{=spCSx5eb0VNzAe%)FZp@U>%(=}~ zEPVPGF7kEt!bOSBusN7vNpZ=SL%G;2dh=%Q$FEafHHZytD1?vU?O5wnw4E}TQwPvx}FYqq#&+X<8X!% zaowp9ohU#?)Lgpvz_2M%Xco~Sd5UKAbU3Nby(qu>*TPZ057A_@#*8^M13fAs*)+~t zNTJ&^7&Y;j?NYHGiAIu{%h}nq#ljPRpAz;N{~loH=`w7JnKu z)RNu57NLv*N_^He9jGkAr^0lqs+-R!_?j{-aFn9^b$66$O7IR<&nWBtzulLTEE9an4Z|AdMJu^)9K$bzA zEKZ~i_zcd@YSZ~P`_K`tp97%-v2KeN#MK>*o?f&O7$J;TXZKHKETNeabza zKY*K2)ep-a*8EH?d9tGYA^W#g{bu#wKVaG)qvudFgtG5{-UK>THFf`hTLI@P!2YvX z6XC=PMGq;;`jv1F&)-7BH7s)erGsA4hMLT^G#jLJZ;{9BMzs* z9yAAQM;CZ?yH#WlR$i;`TCrENn_)$r?^>=mem4{Mv5)M5|4RLeU!f6Npq=kp5|x1g zyZW_V@JuCqL;`pDEbn#9KMzcQAyyZE=U{Vu* zfUkR#_&lut^YkXJQI9}6*PwsrK4p!Q*S@iQBQ?pg5kT)1+aFtR!Y&~Ry}@v1P{&}H ztf^~8z$?S59q&|QO{eP~B(jmi;8Dm88ESpangp7awN=*Pl!NHuQd$-p?9tz0UU=eY z(YmP^YI+1gU*vJ`+VyvZO{gmbDz6$~P|*(4D_W8l&dwIgX-h@v-Edn>)T+rRQs_`@ z80jF&^Qcqy^c@>bp ziifJmOc4d$Yg9#ICL=3!6d@JM-RLXsN8xS7|(?ZhH$>j0A`X+e1bX) z8~PwT2gG0nvi!wV&jS>_WM17H#7%a-*kG4347eN+R96u(x*>q{oh;pLz{~gU!j{9c zo%)$D4tK&V>ZlGykJqSIS)z}ZWOv!ipMd3c8d44l$4)Ea^LMC<2N$U0YYO|vBo|i3 zQ}{H(yTeHbrl%a7+1@Tb#1|QyVlNqk9D)>Pp9;8j0VkKqH-hs7r8y)(l|k4@_X*fQ z8W(Gj5YnRbraWP_cb3QJ@j$NwanX(6wDHKi`8j^9VEZFC&G6XY5yhAab|xqv$? zHy#W*WQJuG8LRiIoP6yh*!8m_6g`Y^CFW|kQkY(5r(qa7Q_czl6ff5FV3W9qQEI=0@<3v#(ps%!?>?|7Vsp8n*2k^R1^a=5!aRr-LJ} z-`KQug=^tgM<)_R8=Ha4X`|SPNM0Rn%7(UfEe34pIU)liR(+TrPZFJH0S-x{sIcaC zp&F>5>VS((xu6?C&y$!5%Jk??^y;@!PK}gYY_s?a9*(se?ll#+A}nECaU>~F7L#K6g z+~GH{!VXwEOoL)N%Whi8x~)+e^q84~1+?)sC2@BDV&())+fZ6W=c`2~y*6UBA!?Dq zh(=l=FWqz@!)n{L7vb!ZmX5gzG2LvqJ<7&3wphyx^O4wCl=P!Al*~YW^Yo0a=AgVf zpV|?N%Db38Rm3w-R-vhkk0^#k_DF0Y?zO7<9_htCehrHk|95E~U4Gq|hUp>)ZYmTED2WhlkIJuf$axXM#42$j!m zmXDTALY$PHExT7)rAHe|xV=RH!){7-Q%)m5XTo~3*yzWsRD z-2!#eCrJlsP&RsHLSD*wper%7HoZ5jjv#?+gHgNU5kjV{z)_62ED0 zY$G14qPTQP7$@;KWW`D4XCw=Dpx@z7HTQ%oDNDs1N_ux>M5C_yg0G_S8#3%v?1KUd4%)*1*d- zkW@EI%T%gxouj=LM}hiEroC28yi6rQfP&l6HZW7KudNzG!xQ}=EJOeXOVvi=<8vaw z1mgmKf^HO!eiJp^)prhsLgE5}!lQg-BA$@7fI2S{)LB0RTPfLL)=*K&b#5BS8EK&) zxYV)caZIxAlO~ur67fg-hJ-SlPeCu?>$0K8Rlc;57QIJLA4V)_6I4JBx)9}_OS1pY zhVD~QS2d>f^S%+19EPQ^-EU>Lquzf&*;19GP zwg>)m_C6p#V{aSjVy}OUy%$I*M+yaDFmyk+*|&GM*-9V>s>yV2EU++U+s08`%EU#S~Ojl>N+&qb>}@KIzeaNF6?kCF0`$~33bRvAamB+Nlr zR2e7)aj2W1Lj;MMNO>$g$>Km5dffKuIzfEJWfF$aM)JazQWM&vQi2>`hjw5fVv9B# zx?2%ANH=4zvX(1c8k0OnC4c3DJdS&46S@F)Thnfmk5WtJlX(o?jyhMdR8aw#-SW`ozVO{?vcq}KpNu_s~A6VQtAP-u71%quehY)U{g#h*K0g~3mq{o>q(UAPHnb$749R<9|88B2xf#82eggXFc{-+jq+3KvG0@SS zyj~6o96KDUB=F$U$1tS8c+<8XWB<=ke7fD}GF!E@&oC!H2T%9H&5nqR_{>NH;+qlv zco?^L`g!gjZS-iipSmdaKXsm)LDhMq^Lipo4E4=C6xnPoZYx~h?&$O~;)~)y8K(Wn z?KQ4x3edq{n8Df0GMLgD?QA>WAKKT5n*;Q|qr9)6(m+AA>0TNL zs{ zG4ah8-c34UEo~}0fmZ9AFK*+TFK+LDlQ*;OY#FY%;he#N+t#=;O>g!b{To)A=maR# zK<5YGB6mw`)cx*t!<5r?{;jX5GRCUYz3?ca(}ULjh(%Es`j$`t<6<{6~p9QT9RdDRl&h8$CVcEdh+8I1NOTK=cvXqEy~W`%60L z7V;VCW+ZfbS9F&f;miWu$wA%*t(=fdOgR`HUGNo1x8T0NIAe-m5x%x zB%>E8&8{1h7uO-+aV+^#9zAM|Qm({y5e~$E3I|X@V1^;?6Wc|!i^?v-NdXE@bl+v} z!Fl#AB1W;6-m}@+nREk!yUpL;X!i@ac2MWfu;xxyxi&w3CqYN`@X>o)t6eAe_t%UKx?Kx>Ti9Z{FXZmP9vvH}pu^ zqHX2|%J9**=kNws(@i&YpdGV4^fc}UWQSCAb@P~>6q2`oMCe8Gz{}a@!1^q6?43tG zetovt>$Fxs-_;v`+DEt;VYOEOv8yOb_lw&pw$KJ58m!eHb=7utzlqyx#0}5~6>w@6 z6_=#J=-Pb6Mtfk0k#6`?mYKEgHI_FRss5tjmc7PT9qx|RbzTHDuNHiG6HSTxh{)rx zc|C?8>hrx2u~zTt;$rjc-h^yzF#6IOjBZbF`Y7_4HkWEfvt0~s))9feQMNY!hKxqQ zL`uyzOQ~7r&F`QpJDW;=^TRaT6`_D5WD?r0E1e7dN=32B5Xewm=h4lvDw?G=3&;+v zs0Lbrp|6fpD(REf>c~soYPU?`?!`T9+B%x;2E#)-bkL}z5E)~Me7V}D7W>~+6U<;= z0T^Nc{L3#9e*NzV4)D4+4Q4Q}xFFmc+GnjcsAbNnrEg%1BK!#o z!>`{%;@8&@Z?inIQ5A7O5wK1BRYV?G#kB1HlCA7@ZaiP>;2!1HFnoQjz@DQXWW@rm z;#n?e1ZpVST|C+JH(8x{X z=obQXaSE869DP>}ukl}F*J2~K_4jep5H6Lfdy)N?Y)VVbftKq0hr_s*Z`mXK2zu99 zy}OP*M=J??o_4awx$$T3T6=CXt~kFP-1pA;Q{kJr1Y^W^@vV0%9_1>Y;P}I}0#h-G zd#7RwEG&-Pzk+us8`EGW=ld4jQyn}F1m}a_R;qV@&YoA6$&@Spv}yRt10NN+5b)GB za#J}K+EEcy-oLws1rr9_;%D(4=Klo0oYEG*wwX{R$^$q7H(;}wkGqy607JZDOPN-fI_XJmw#qm}Q zOl!q#u3|1%F^_}vllIBqMPU3KTrpR|%A*L_r?^eQtHHCO7wDN8y~TkcMc>=MrF~L) zhWgWHa4PR~-ug7R-kOh8$OVw+t;@Ly{!Z4*q#O$%FQ(prc$)L4F6UI@pj%?>Eo1bU zSZ+2a8t_#J7ci~kST3LAKd%ij0n-|et)(ozZ`@(>6394w9g{Sg%LTr3}$9cZ?d}mA#F${cT$GITHM8}85Yrq~I zF_lLvkJ#L1f0~n1uf4!qr*K;qb4m3OPD%}=85^J0NB>VoM<)CCs6Np}l@4V6{}|yM z&S8Cmd&V8>^ZzUA@+|2Rb`!T8r+}b|dk^5C{u!8|?%L^Uw?h;6@z&W;xO|SSr>guk zbOXkwiGyyEnbZuiT$XH#>TZZPIvc5;;ksgUY`e&P$Rf1V-ud68IghI-jM2t~_z!7g zR^w)Yj%A%oF&^)7#lv7 zPDp)HCg*u(RYLm_pkJTE1#o>K$FM#}7eJ&b$B>kx!-nQ1vP#{4to^urYvrm_W{OmCX5UoLRw3VUOcl`dzcGXSBb z5c~0ETu}$DsmGF=69GP4>OmJYGuh4<&{Lvf(Y#jc*th!rK&F9DTm=}a4pc#EPcgOMG7bf@M*z17n%5=*k_%+&MdJ(b zwql#itT0_;7vWA5S1U2>Rkp+w(~L?6OL!4SZRAIPh(lnQ=KfF~2VtVv@p(zwB>(r} zq|a-wFu|6iyJ}MXYsU22mgyo*?EwX$ZmN4eDf4kJAQgv?IROInTP5*w z#h7sDMow2U5?e^fJE?XeJg`7!c=uj>-4e#Jq0`Iy8VNGsl>fwW{ELZ{my{1Q`?zXaZySbG&^I*b>8yf(t%tB9hWe~;@~ zx8nK{`4fV^KqWJdqil*c)`<>uqO_(AJ?{Yj+q(GQhOyoT=Mgv7q|B?{lS&u5j|u#E zD>wsR3eQxI^=xe?lXRS~$Hzz!e9o~(OTXl3KX#or!A@Z`+!jY2uFhdQdmzcJYdn>lObw#BKc z@9*K-$?mrVlHZRjbAZXxApb7-5G&^d&&w9VAS;|7w%q!m9tek@4hp`s*W++}(GBxn87~HcI?l^+ zLpa`wZ~V)Se%&8s!%rVNiIbV&N#AL+SDhj1UZAGdY1)np1hpsCwbx`Ztti}IX1JMSyjRrdCrzS^k1SXatGKE=IqU%N` z;btDW${mhW9I!WVvHIScRpmzsu0SM%N8oW5#cM ze!;Tb6$@<>l9Fuq+9u?$Tvf1i@e+^ifrlP?z!s~Vw8FD2nLNC-Xz9W{TV6pyet}Ux zZvKk=g5|l(Y%2@$7Z>C%w|VjkmM>kA>sgw=!ido4fAu#C*Q&bxQdPaxBaucSjYdjC zN=F)x^e~bWX(AFKXYjWN(_7sW=^>;ik=7%Y0k z3zrt;E%4+QtQw#vkLBksT)JX0fKV}TaN)q@>d})&WG&;x893^#tHFmFX6c(fJdEy_dx7UWUF3&CiC4Ya}aa@uKv z&MbvA<+9vD zXq1eX;vvvJ^_WBo~aM zJ@BC?MY#nlmKH9_TSyk>gIVC2lI!u<#(N8%%7Zu-dw~@_&tGmU^yKF+w2}FFp5i<( zMsd+D=0@2o%v(^9hrR&=B{~soC)*%BK<3#z#Y@3EctHNC75Ve!mK1EIm(rHYW%^5i za#Ackzp9dji2!FBhHM8lO{j<*p$qvu4&U}JpP0`Yi9N=86f(Hf1xQ0Va%6+g4;SGM~f7@qQr2UACke8@&h2BZ(VYjBQz*xf_t zC9Qt)-Z68YT{C;`sDX|lqtnLTlYE~{lPa#Pjkbwn1~0rPYs}z6;?6Btnmd149#Ir6 zSJo*y$Sd-m@yKckmPxCQ%u|hJ#S$l(gE{>jy$ExW@fQv>Ksjw!Y={*4?Vh2)6qd)B236pX%m*#HA}ec|moHo}~Z0 zCnr^{tkNP~g%(O*eg>7UI;r|0t~=LCizR4ri{3wzwy63CaAEx>WtT`Xlve4Dn1&fhMSVPxFWu9~}N(!3BMA@~6YL|ME<~&9jb<+Wo5z?m1_p{q;rPC%)wVD)lc#S4?G@pC`Y& z;+*wga*n6%DT%1ojjJ87CHLDNo2Ioqu;b~U;sTRC8T#hZ&~2|~A9-lks%x6xJhFH2 zYkA-G{^uwD_TUHJ%f^jU_TT%?@*nT~2zSoCJIS*K4(;1YVqn-UUwBp4F9 z>dDPo2g)ikVd@muxM^f%!BRL{h4AJV*+$tG!JU`g*p>OT7{1l=TzHi$@;$a?OIJLV aw=lYs!U-*YpPIjr{}Cn&ackTsH2p8OYRakr literal 0 HcmV?d00001 diff --git a/16/xlib/demo9.exe b/16/xlib/demo9.exe new file mode 100755 index 0000000000000000000000000000000000000000..6c2954bf67a283681e48c3a4e2ca45958637a80e GIT binary patch literal 32808 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 J1U3PaAOLne4`~1Z literal 0 HcmV?d00001 diff --git a/16/xlib/fixed6x8.fnt b/16/xlib/fixed6x8.fnt new file mode 100755 index 0000000000000000000000000000000000000000..8d04a2774aceb4997686c90ae4509405399d8f50 GIT binary patch literal 788 zcmYjP(Q@1%3|xrp1M0)*Tz8U5YC4lIXdn7|ACnL1uV)uur;9QQjY z_xrI(pJEaiN_jX+=L6U=)vv1o?_088KQZSi?)e*LivyS}#%Kxr690i>-IT+q88+ku z_lHFl@uLwPfa)*%<`p*U0F`#D!MpU*=npyP&eT1uO?LILI(2VMzyg(qY%YiPS@-`h zs*27BusmP>t1|HnXTR0=@7Hj^ihFkllk25Fgur~4?C$x39>OJr{?I}DFRII3hB>N^ z&+|9R@aO4i$_{3sbolGO3+LO;IO4eor(y&QTfE9v9P?N8LlPybGw@nV8TP)vGM^V6 zeQ4qO;FbJwEHRP~b>GM{IZTN>7ymZ~5;DiXL#pjyy&!tozb2#p8@;4<*lVa*Zt=pz z!zSbP#5*TS?`=UF4BQrym&u*H6kW70B7pk3G2t1{{CF^+dd$a@UN`Xp93)_6yviw_ vQ3HSWFI)Xni-56zdlR5@ydBSG(d?Pmfm7x;C(d2hA7$bKq_^K6AAj%(eRdtd literal 0 HcmV?d00001 diff --git a/16/xlib/makefile b/16/xlib/makefile new file mode 100755 index 00000000..35ec877b --- /dev/null +++ b/16/xlib/makefile @@ -0,0 +1,104 @@ +# makefile MAKE V2.0 or higher + + +# Set the required model here, either s, c or l (LOWER CASE ONLY) +# + +MODEL=h + +XLIB_VERSION=06 + +# Set the compiler: either BCC or TCC +# +CC=wcc + +TLIB=wlib + +AFLAGS = /ml /zi /d$(MODEL) +CFLAGS = -m$(MODEL) +CPPFLAGS= -m$(MODEL) +LDFLAGS = -m$(MODEL) + + +%.o: %.c + $(CC) -c $(CFLAGS) $< + +%.o: *.asm + wasm $(AFLAGS) $* \ + + +XLIBOBJS= xprintf.o xpoint.o xline.o xmain.o xpal.o xpbitmap.o \ + xrect.o xtext.o xcbitmap.o xdetect.o xbmtools.o \ + xfileio.o xrletool.o xbezier.o xpbmclip.o xvbitmap.o \ + xmakevbm.o xmouse.o xcircle.o xclippbm.o xcomppbm.o \ + xpolygon.o xvsync.o xfill.o xcbitm32.o + + +all: demo1.exe demo2.exe demo3.exe demo4.exe demo5.exe demo6.exe demo7.exe \ + demo8.exe demo9.exe demo10.exe + +demo1.exe : demo1.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo1.o xlib$(XLIB_VERSION)$(MODEL).lib + +demo2.exe : demo2.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo2.o xlib$(XLIB_VERSION)$(MODEL).lib + +demo3.exe : demo3.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo3.o xlib$(XLIB_VERSION)$(MODEL).lib + +demo4.exe : demo4.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo4.o xlib$(XLIB_VERSION)$(MODEL).lib + +demo5.exe : demo5.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo5.o xlib$(XLIB_VERSION)$(MODEL).lib + +demo6.exe : demo6.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo6.o xlib$(XLIB_VERSION)$(MODEL).lib + +demo7.exe : demo7.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo7.o xlib$(XLIB_VERSION)$(MODEL).lib + +demo8.exe : demo8.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo8.o xlib$(XLIB_VERSION)$(MODEL).lib + +demo9.exe : demo9.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo9.o xlib$(XLIB_VERSION)$(MODEL).lib + +demo10.exe : demo10.o $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo10.o xlib$(XLIB_VERSION)$(MODEL).lib + + +xlib$(XLIB_VERSION)$(MODEL).lib: $(XLIBOBJS) + $(TLIB) xlib$(XLIB_VERSION)$(MODEL).lib \ + -+xmain -+xpoint -+xline -+xpal -+xrect -+xtext -+xprintf -+xbezier -+xfill -+xcbitm32 + $(TLIB) xlib$(XLIB_VERSION)$(MODEL).lib \ + -+xpbitmap -+xcbitmap -+xdetect -+xbmtools -+xfileio -+xrletool -+xpbmclip + $(TLIB) xlib$(XLIB_VERSION)$(MODEL).lib \ + -+xvbitmap -+xmakevbm -+xmouse -+xcircle -+xclippbm -+xcomppbm -+xpolygon -+xvsync + +# Object modules + +xprintf.o : xprintf.c +xpoint.o : xpoint.asm xpoint.inc xlib.inc model.inc +xline.o : xline.asm xline.inc xlib.inc model.inc +xmain.o : xmain.asm xmain.inc xlib.inc model.inc +xpal.o : xpal.asm xpal.inc xlib.inc model.inc +xpbitmap.o: xpbitmap.asm xpbitmap.inc xlib.inc model.inc +xpbmclip.o: xpbmclip.asm xpbmclip.inc xlib.inc model.inc +xclippbm.o: xclippbm.asm xclippbm.inc xlib.inc model.inc +xrect.o : xpal.asm xpal.inc xlib.inc model.inc +xtext.o : xtext.asm xtext.inc xlib.inc model.inc +xcbitmap.o: xcbitmap.asm xcbitmap.inc xlib.inc model.inc +xcomppbm.o: xcomppbm.asm xcomppbm.inc xlib.inc model.inc +xcbitm32.o: xcbitm32.c +xdetect.o : xdetect.asm xdetect.inc model.inc +xbmtools.o: xbmtools.asm xbmtools.inc model.inc +xfileio.o : xfileio.asm xfileio.inc model.inc +xrletool.o: xrletool.asm xrletool.inc model.inc +xvbitmap.o: xvbitmap.asm xvbitmap.inc xlib.inc model.inc +xmakevbm.o: xmakevbm.c xvbitmap.h +xmouse.o : xmouse.asm xlib.inc model.inc +xcircle.o : xcircle.asm xcircle.inc xlib.inc model.inc +xpolygon.o: xpolygon.asm xpolygon.inc xlib.inc model.inc +xvsync.o : xvsync.asm xvsync.inc xlib.inc model.inc +xfill.o : xfill.asm xfill.inc xlib.inc model.inc diff --git a/16/xlib/model.inc b/16/xlib/model.inc new file mode 100755 index 00000000..afcdced4 --- /dev/null +++ b/16/xlib/model.inc @@ -0,0 +1,21 @@ +IFDEF s + DISPLAY "XLIB04 Small Model" + .model small +ELSE + IFDEF c + DISPLAY "XLIB04 Compact Model" + .model compact + ELSE + IFDEF l + DISPLAY "XLIB04 Large Model" + .model large + ELSE + DISPLAY "WARNING: Model was not defined at the command line." + DISPLAY " Using default small model ie /ds " + DISPLAY " Include in TASM commandline either /ds, /dc or /dl" + .model small + ENDIF + ENDIF +ENDIF + + \ No newline at end of file diff --git a/16/xlib/modernb.fnt b/16/xlib/modernb.fnt new file mode 100755 index 0000000000000000000000000000000000000000..a71a5d8fc9adb6fd0290f6dda54a0cd45c25099f GIT binary patch literal 1060 zcmYjQv5MP35FMnw@p3E<94R)(B3!r#uEY@*6+&sQI8x>dL;_n0mxl`>@&);d6yeI$ zsa3i52c)<%n6}&L=7wlx!|u9j z-|m9tuOD{RpYPv(5!q%K{Lkm~7on_QV5~C?7-vm^J7BnwR3?<5+s;}%<`l>UvP5g8 z7`>A$D6KU>Q9xOMG$3GE-L&s&0AYxA?HzYZ=<8YuKHT2EdG9^4t>fx$$%e>PuF%!q zi!@yprL@$Q|90VOd(~X3F%H`yLmSWRHxMY&JNz^(TwOb8R5^ZelAHS+^#T|rcI3^c7^^P+ zPnf`+f1l5%Sv91z-#!TE;DB!>naIg0->Xbv~33r+`t+ zmlKDvP`GO`I?1wnDNZ6AnRT#zKZ?jvvu&DK^#*>Wt%>sCt8bjO1F~dkMx*%Cl3gp@-PmQg z@o};(_0)ehOW(Kr{IwLN^lWoV;bxO6!X}Tvo%VkA-BQkH&KGF-1lDOU&nByx%z0_8 zEjHJCtyNx*Z5Rbh*(jekU+YTHR|PlfLMd#SUNJ&VV9LY6c^Y^FL;|LrwJJv?EcVQy9!XL$3O=$+K8<&Ui6?Qs_^eQmeycRChX~ z8HlXA!$_YY5Pf#(BPe#;hQ1t`Pfuwq4m_KWp>LKfME?T=@ET$O literal 0 HcmV?d00001 diff --git a/16/xlib/timpani.fnt b/16/xlib/timpani.fnt new file mode 100755 index 0000000000000000000000000000000000000000..8907f0a7662d9847556e2847d90a4e27b0d51f44 GIT binary patch literal 1156 zcmYjR!D`$v5FNByRk)@Y;loml5het)^iXozgK>iqf#kU7oc059=(&_)`UU$LKK3K> zS)uQZ?2wnpejYu|j7Fo4@>xE>8ba_dVv3^Jrfdj5f({Yqn`2QP`eWn8xyRee+q=i_ zBA;wgSbGfN8#LD1ZSBsN>eiNCtZ~)@)){aOqcX(ve)OInZd+)L?8v`l!@EO>4O|fP zV4E(Z!P39zp23Hdk`B~% zm{2WarUAU|CZcP>k-up%xW|nnfTRBBG+mydq4+l+;E-mBm`V{siG0#cU6%Dt`ir=m zgg)o_^>taUSLQQ4JUl&}FBke5=nr5%Bi@XSxU2nq8SYm*MXz8)K`7dnm_{q0Q=jYdp+MbaJMDxWM>RpLz~I65f!ley3>QuvsfAT z=um(aJjEssIAhr1lI_4cvnRO)?F}>-6j`J8G279NIStXi&6?QK_Vtzv=u>dH2);L- zEunBlP)+{UdH8?164)d7yC01Umrc$s=ZW~RuW=*!$9&3Qy`D89s~wx={bFW!ytB&d znuQ}r^_Rr@gQH2x5OP1`cOaD3?%3Nc`x*7w!+_g}QR=;3cOba#0Pm{XZU|Q4&gwHi F?0>ggUdR9d literal 0 HcmV?d00001 diff --git a/16/xlib/tiny4.fnt b/16/xlib/tiny4.fnt new file mode 100755 index 0000000000000000000000000000000000000000..d213c3d75b1fbbae057525a75ca35149c3da6874 GIT binary patch literal 484 zcmXYu!D<6B3`C7>O_m_sVoEW^h?3*dgAc`&67>1`g#Db*aZ<5steq!m?EMTmtjIt> zIC&c1vI}5)I@Olrz}Q5wxlJ3a8Y;k4s+JMP=;tf0LsyeS8 64k + XDETECT: added numeric co-pro detection + added mouse driver detection + XMAIN : added new resolution tweaks + added clipping rectangle setting proc and vars + further bug fixes (I can't remember exactly what) + XCBITMAP:Improved performance of compilation and compiled bitmaps + and added a function to calculate mem required for + a bitmap compilation + XPBITMAP:Improved performance of planar bitmaps + XRECT :Added "x_shift_rect" function + XPBMTOOL:Added several utility macros + + New Modules + ----------- + XPBMCLIP:Implements clipping versions of functions in XPBITMAP + XVBITMAP:Video based masked bitmap functions. Contains standard + and clipping versions of all functions. + XMAKEVBM:Support module for XVBITMAP + XMOUSE :Basic mouse support module + XBEZIER :Fast Bezier curves (For scalable fonts etc..) + + +Xlib version 4b modifications + +10-12-92 BUG FIX RELEASE + + Files Modified + -------------- + + XMAIN.* + XPBMCLIP.* + XVBMCLIP.* + XCLIPPBM.* + + Modifications/Additions + ------------------------ + Some minor fixes and modifications in xmain.asm + fixed the split screen starting scan line problem + + This fix is a cludge - Sam Thompson has suggested a more + elegant fix but I just dont have much time these days + + changed mode setting code to allow 320x200 mode to have same + aspect ratio as mode 13h + + The clipped functions were modified to return 1 if the image being + clipped was completely off the logical screen. + Minor clipping bugs which gave inconsistent results when clipping + to the left and right screen borders were fixed in the XPBMCLIP & + VBMCLIP modules. + A bug in demo 2 which caused crashing on 486 machines was also + fixed. (The speed of the 486 resulted in 0 time delay which inturn + caused a division by zero error) + +28-12-92 Modified PEL panning code to be smoother on snail paced PC's + Added quick & dirty planar bitmap compiler + + +15-2-93 Converted text module to allow variable width user fonts + + Added a function x_get_char_width in module xtext + Added fonts var6x8.fnt varswisl.fnt varswisb.fnt + Clened up virt screen start address setting code in xmain.asm + + Added demo 8 to preview user defined fonts + + Added x_wait_vsync in module xmain + + Fixed a bug with mode sets on some VGA bios'es that dont + preserve CX on an int 10h + +18-8-93 XLIB05 Final Release + ----------------------------------------------- + + GENERAL: + Added C++ compatability in header files + Added new fonts + XDETECT: now can differentiate between 386sx 386dx and 486 + (486sx can be verified by absence of FPU) + XMOUSE: + Fixed x_mouse_position bug and general xmouse improvements + Added x_mouse_window function + XFILEIO: + Modified f_read and f_write functions xfileio module + f_read - now reads into near buffer reguardless of model + f_readfar " " " far " " " " + f_write " writes " near " " " " + f_writefar " " " far " " " " + Added f_tell function to get file position. I beleive I + improved the error handling a little but I cant remember + for sure. + XMAIN: + Added 2 new resolutions 256x200 & 256x240. + I dont know why you'd want them but theyre there if you do. + These came from Draeden of VLA (Did you write them Ben ?) + I think they may have originally been posted on R.G.P ??? + XRECT: + Added x_rect_fill_clipped & x_rect_pattern_clipped, probably + useless but what the heck! + XPOLYGON: + New function x_triangle - a fast clipped and filled trinagle + function ideal for 3D work. + x_polygon - a clipped and filled polygon function (convex + polygons only). This one's not the fastest - it splits + polygons into component triangles and uses the above + triangle routine to draw them, but still it should + perform fast enough for most 3D applications. + MISCELLANEOUS: + xdiscuss.zip: Included Robert Schmidt's excellent mode X article + for those interested in the hows and why's of Mode X progamming + xlibtl02.zip: Some bitmap conversion code and a TSR bitmap + capture program. + + + Aknowledgements + --------------- + Gerald Dalley - For getting me off my butt and doing + this release. + + Steve Dollins - Never returned my mail asking for + permission to use his code so I + assumed it'd be OK ;) + + Christian Harms - For suggesting xdetect improvements and + promising to make XLIB for T.P. freeware + when its complete. good on ya mate! + + Jason Truong - For spotting the bug in xmouse and + general suggestions for improvements + + Chris Kirby - For suggestion to make .h files C++ + compliant + + Robert Scmidt - For his mode X article. + + jeremi@ee.ualberta.ca - Thanks for the xtext suggestions + (name unknown) even if they didnt make this release + + And others whom I may have forgotten. + + Also Greetings to my internet pals, + Mat Mackenzie, Jari Karjala, Draeden, Victor Putz, + Josh Jensen, Chicken and the rest of you dudes... + Thanks for helping my productivity live up to + "Public Servant" standards ;-)) + +5-10-93 + ----------------------------------------------- + XCBITM32: + 32 bit compiled bitmaps, originally developed by Matthew + Mackenzie for our game. NOTE: The compiler is written in C - + conversion to assembler is left as an excersise for the user :-) + + XMOUSE: Finished x_mouse_window this time. I had overlooked + its semi-completed x_mouse_window function in the last release. + + XPBITMAP: + Added x_flip_pbm and x_flip_masked_pbm + Identical to x_put_pbm and x_put_masked_pbm but have an + extra parameter which indicates whether the bitmap is flipped + from left to right as drawn or not - Ideal for saving bitmap + memory. + + XFILL: + Added a new module containing 2 flood fill variants. Both return + the number of pixels filled. + + XVSYNC: + New module to synchronise timer 0 to the vertical retrace. This + allows for smoother animation due to the elimination of + unnecessary vsync waiting. + + XMAIN: + Modifications to allow standard vsync polling or optional + timer0/vsync synchronization and new support for tripple + buffering for super-smooth animation. This stuff's way cool! + + BUGS: + fixed the odd bug here and there - nothing too serious. + + + Aknowledgements: + + Tiaan A Geldenhuys - for pointing out that I forgot to finish + some code in xmouse.asm, for the new cursor shape and stuff. + + Thanks to Tore Jahn Bastiansen (toreba@ifi.uio.no) for the + tripple buffering extensions to XMAIN and the excellent + Timer vsync sunchronization which is the highlight of this + release. This module is a "MUST HAVE" if youre going to do + any animation. + + Also thanks to any others, whom I may have lost track of, + for bug fixes'n stuff. + + Apologies to the person who sent me the pbm flipping code. diff --git a/16/xlib/var6x8.fnt b/16/xlib/var6x8.fnt new file mode 100755 index 0000000000000000000000000000000000000000..6cd3b0d607148733a4c61d3f8521fda6eb66d7f6 GIT binary patch literal 877 zcmYL{3v$~q3`9YNqCQn^^I*2C7rY_gZ%4NQVh_4o7Pm9!#8)#mE0Cht}-j;2uBwyo2p^mJ?C zsh)1GP;V5X8Og417+2&#Lt|>hFd$0H;2d;dRCp5+p(sNt#`)_tUGUl6ySo({>8nsm zNiCMm-M5AADJ>~Mbr>mf-h&1ipn=yAnz6Q0Eh+|9u~x^ZcM7@0w^Bk=$bi(wR+86AVr2G-RoWy{>qG#Ky)d zSz(g%-+K8=7o8p?A^D0bYZg&xD>SF6k}lteJb+Y0)a6uKXT5cf+T z?vvR!2_*RIBT%Xw`j`!cq8F80W-Yu*YCj zhS`j4dhoa`XLcmAwpj~3VVK7cGziN2S8gETKq}SF=%R!JZx+=f0vD`_s9`}tv(`DE zEu3;@A3EoleXq^YT2yOAgrw-GqwdNYHgGy2=W!_lWAN~#4oLJ;d475M z#)&T0qFd!1eQCGbcDps8tzZ`gu4Zru;aWAxRG?Xrf%N>g^XtC9A$!!i)p`JV-7d0I zvIvhR@==pZ|Ff#HKaS(R@2Du(*1nbky=|A+z~x$#(KSx)d*^Ds;<*&rg@`q{;aIQ( za79DVW3RQYD^wo){eUw;AlCW-`c=dip1YvChV?v_^Yj;;CfNXu{n(6IM$8M^*gGjd z8S65dsDasVAw}r%EXSs21TM0o6*(LjvchF{Ko}7$h`yi}*_?ut+KdN986O0u=|nsX z$S#Z5b-Pn!iN2tLckF}c^I0ov{BoQxOrT sM5XojNV3pY4%z7Jf~-da(VIzzRQhEnwJx_o-Xr08N@x3YN_*G%4~5!=mH+?% literal 0 HcmV?d00001 diff --git a/16/xlib/varswisl.fnt b/16/xlib/varswisl.fnt new file mode 100755 index 0000000000000000000000000000000000000000..d1b2e5653395fc22d251f79555b6c8dbd9aa0e5d GIT binary patch literal 964 zcmX|A!HU~J3{_=icIpmh7)%Mlm|}(!Lg;B(dN83F(@Xy#$5ITv?4jqd9}(C?f22Q9 z=&$tFZ|IZ8StZ2E(@5`)B)_BA^kTwl#6(=zD=KY!!lxy2u^U1hIw41&-$(!LE76_Q z_lJ~@h$68Vmom&!u@vLVxiwnhDUImwdfW(!8vT32pg=QCP8E_`AlisHg^7SgFR2Hn zUbLtWq3(SLtmh^cEHF1Ew@=<%E;5pSEjM*Bss}>Q>&;isRC!_XMO9-0K@CK3NKAnW z-i*`F=jZP{l8ds`Oz{Q*W7a&f6`jEYoy8=d2!pZC>F0nfEcqkKjdjg>4>K1T$CZ zL-kW-Q-kL!dD*Kn{T{rGCYoV4LhKTFHp4*X literal 0 HcmV?d00001 diff --git a/16/xlib/xbezier.asm b/16/xlib/xbezier.asm new file mode 100755 index 00000000..cc16fb2a --- /dev/null +++ b/16/xlib/xbezier.asm @@ -0,0 +1,675 @@ + +;----------------------------------------------------------------------- +; MODULE XBEZIER +; +; +; Compile with TASM. +; C near-callable. +; +; This module was written by Matthew MacKenzie +; matm@eng.umd.edu +;----------------------------------------------------------------------- +include xlib.inc +include xbezier.inc + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; _x_bezier +; +; Plot a Bezier curve, which is described by a box of two endpoints +; and two control points: +; C1--------C2 +; / \ +; / \ +; E1..............E2 +; +; All coordinates must be in the range -1024 to 3071. +; No clipping is performed. +; +; C near-callable as: +; x_bezier (int E1x, int E1y, int C1x, int C1y, int C2x, int C2y, +; int E2x, int E2y, int levels, char color, +; unsigned int PageOffset); +; +; All four main registers are totaled. +; This function may use as many as 162 bytes of stack space. + +; Bezier curves need 32-bit precision, so we'll define macros and +; constants for operations on 32-bit virtual registers V0, V1, and V2. +; V0 is made up of DI and AX, V1 of SI and BX, and V2 of CX and DX. + +LowWord equ 0 +HighWord equ 2 + +; to load data -- + +LoadV0 macro loc, field + mov ax, word ptr [bp + loc + field + LowWord] + mov di, word ptr [bp + loc + field + HighWord] + endm + +LoadV1 macro loc, field + mov bx, word ptr [bp + loc + field + LowWord] + mov si, word ptr [bp + loc + field + HighWord] + endm + +LoadV2 macro loc, field + mov dx, word ptr [bp + loc + field + LowWord] + mov cx, word ptr [bp + loc + field + HighWord] + endm + +; to store data -- + +StoreV0 macro loc, field + mov word ptr [bp + loc + field + LowWord], ax + mov word ptr [bp + loc + field + HighWord], di + endm + +StoreV1 macro loc, field + mov word ptr [bp + loc + field + LowWord], bx + mov word ptr [bp + loc + field + HighWord], si + endm + + +; to take the average of two registers (result is in first register) -- + +AverageV0nV1 macro + add ax, bx + adc di, si + shr di, 1 + rcr ax, 1 + endm + +AverageV0nV2 macro + add ax, dx + adc di, cx + shr di, 1 + rcr ax, 1 + endm + +AverageV1nV2 macro + add bx, dx + adc si, cx + shr si, 1 + rcr bx, 1 + endm + + +; to take the average of a register and data -- + +AverageV1nData macro loc, field + add bx, word ptr [bp + loc + field + LowWord] + adc si, word ptr [bp + loc + field + HighWord] + shr si, 1 + rcr bx, 1 + endm + +AverageV2nData macro loc, field + add dx, word ptr [bp + loc + field + LowWord] + adc cx, word ptr [bp + loc + field + HighWord] + shr cx, 1 + rcr dx, 1 + endm + + +; to turn a 32-bit fixed point data into a regular integer -- + +Extract macro reg, source, field + mov reg, word ptr [bp + source + field + HighWord] + shr reg, 3 + adc reg, 0 ; round + endm + + +; to turn an integer argument into a 32-bit fixed point number +; and store it as local data -- + +Convert macro source, dest, field + mov ax, source + add ax, 1024 + shl ax, 3 + push ax + push 0 + endm + + +; useful numbers for dealing with Bezier boxes (sets of four points) -- + +XCoord equ 4 +YCoord equ 0 + +; stack offsets for splitting boxes +E1Src equ 48 +C1Src equ 40 +C2Src equ 32 +E2Src equ 24 + +E1Dest equ 48 +P1Dest equ 40 +P4Dest equ 32 +P6Dest equ 24 +P5Dest equ 16 +P2Dest equ 8 +E2Dest equ 0 + +; stack offsets for drawing boxes +E1Draw equ 24 +C1Draw equ 16 +C2Draw equ 8 +E2Draw equ 0 + + .data + + align 2 + +; depth of recursion at which to plot +WhenToDraw label byte + db 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 + db 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5 + + +; since we'll be moving bp and sp in our recursion, +; we need to put local storage in the data segment +level dw (?) +gencount dw (?) +AdjustedOffs dw (?) +p1xt dw (?) +p1yt dw (?) +p2xt dw (?) +p2yt dw (?) +p4xt dw (?) +p4yt dw (?) +p5xt dw (?) +p5yt dw (?) +c1xt dw (?) +c1yt dw (?) +c2xt dw (?) +c2yt dw (?) +xdiff dw (?) +ydiff dw (?) +moveline dw (?) +stepper dw (?) +bptemp dw (?) + +; by the same token we need a copy of this argument +Colort dw (?) + + +ColumnMasks label byte + db 011h, 022h, 044h, 088h + + .code + + align 2 +_x_bezier proc +ARG E1x, E1y, C1x, C1y, C2x, C2y, E2x, E2y, Levels, Color, PageOffs:word + + push bp + mov bp, sp ; caller's stack frame + push si + push di + push es + + ; set local variables + mov ax, -1024 ; 1024 rows + imul [_ScrnLogicalByteWidth] + add ax, PageOffs + sub ax, 256 ; 1024 columns + mov AdjustedOffs, ax ; subtract 1024 rows and 1024 columns + +; copy color into data segment so we can change bp & sp + mov ax, Color + mov Colort, ax + + mov cx, Levels + dec cx ; gencount (number of boxes we will actually plot) = + mov ax,1 ; 2^(Levels - 1) + shl ax,cl + dec ax + mov gencount, ax + + mov [level], 0 ; variable to tell us where we are in the stack + mov bptemp, bp ; when the dust settles at the end + +; translate coordinates for adjusted offset, convert 'em to fixed-point +; with 13 bits for the integer part and 19 for the fractional part, +; and push them onto the stack in the right order to for a Bezier box + + Convert E2x + Convert E2y + + Convert C2x + Convert C2y + + Convert C1x + Convert C1y + + Convert E1x + Convert E1y + + mov bp, sp ; we are using them as basically one pointer + + mov ax, 0a000h ; point extra segment to VGA memory + mov es, ax + + mov dx, SC_INDEX + mov al, MAP_MASK + out dx, al + +MainLoop: + mov si, gencount + mov ax, 0 + mov al, WhenToDraw[si] + cmp ax, level ; are we at a terminal curve? + jne Recurse + jmp PlotCurve + +Recurse: +; not at a terminal -- so expand this curve into two more and recurse + +; start with: +; C1___C2 +; | | +; E1...E2 +; +; stack looks like: E1 C1 C2 E2 + +; expand like this: +; C1.....P3.....C2 +; . . . . +; . _P4_P6__P5_ . +; P1- .. .. P2 +; | .. .. | +; |.. ..| +; E1............E2 +; +; stack looks like: E1 P1 P4 P6 P5 P2 E2 +; Since P6 is part of both new boxes, we use it twice. + + sub sp, 24 + sub bp, 24 + +; new points for X -- + LoadV0 E1Src, XCoord + LoadV1 E2Src, XCoord + StoreV1 E2Dest, XCoord + LoadV2 C1Src, XCoord + AverageV0nV2 + StoreV0 P1Dest, XCoord + AverageV1nData C2Src, XCoord + StoreV1 P2Dest, XCoord + AverageV2nData C2Src, XCoord + AverageV0nV2 + StoreV0 P4Dest, XCoord + AverageV1nV2 + StoreV1 P5Dest, XCoord + AverageV0nV1 + StoreV0 P6Dest, XCoord + +; same thing for Y -- + LoadV0 E1Src, YCoord + LoadV1 E2Src, YCoord + StoreV1 E2Dest, YCoord + LoadV2 C1Src, YCoord + AverageV0nV2 + StoreV0 P1Dest, YCoord + AverageV1nData C2Src, YCoord + StoreV1 P2Dest, YCoord + AverageV2nData C2Src, YCoord + AverageV0nV2 + StoreV0 P4Dest, YCoord + AverageV1nV2 + StoreV1 P5Dest, YCoord + AverageV0nV1 + StoreV0 P6Dest, YCoord + + inc level ; one level further into stack + jmp MainLoop + +PlotCurve: +; pull 16-bit coordinates back out of 32-bit fixed-point coordinates; +; integer part is highest 13 bits + + Extract cx, C1Draw, XCoord + Extract di, E1Draw, XCoord + mov c1xt, cx + add cx, di + shr cx, 1 + mov p1xt, cx + + Extract ax, C1Draw, YCoord + Extract si, E1Draw, YCoord + mov c1yt, ax + add ax, si + shr ax, 1 + mov p1yt, ax + call ShortLine ; line from P1 to E1 + + Extract cx, E2Draw, XCoord + Extract di, C2Draw, XCoord + mov c2xt, di + add di, cx + shr di, 1 + mov p2xt, di + + Extract ax, E2Draw, YCoord + Extract si, C2Draw, YCoord + mov c2yt, si + add si, ax + shr si, 1 + mov p2yt, si + call ShortLine ; line from E2 to P2 + +; P3 is not in any line we draw, so we'll use it now to find both P5 +; for the line after this on, and P4 for this line, then discard it -- + mov bx, c1xt + add bx, c2xt + shr bx, 1 + mov dx, c1yt + add dx, c2yt + shr dx, 1 + +; find P5 x and save for later lines + mov cx, p2xt + add cx, bx + shr cx, 1 + mov p5xt, cx +; find P4 x for this line + mov cx, p1xt + add cx, bx + shr cx, 1 + mov p4xt, cx + mov di, p1xt + +; find P5 y and save for later lines + mov ax, p2yt + add ax, dx + shr ax, 1 + mov p5yt, ax +; find P4 y for this line + mov ax, p1yt + add ax, dx + shr ax, 1 + mov p4yt, ax + mov si, p1yt + call ShortLine ; line from P4 to P1 -- finally! + +; we've already done all the work for these last two -- + mov cx, p2xt + mov di, p5xt + mov ax, p2yt + mov si, p5yt + call ShortLine ; line from P2 to P5 + + mov cx, p5xt + mov di, p4xt + mov ax, p5yt + mov si, p4yt + call ShortLine ; line from P5 to P4 + +; we've drawn our five lines; this bezier box +; can be dropped off the stack + add bp, 24 + add sp, 24 + + dec gencount + mov cx, gencount + cmp cx, -1 + + je WrapUp ; if we've generated all the terminal nodes we + ; are supposed to, we pack our bags and go. + dec level + jmp MainLoop + +WrapUp: +; plot the final point, which is simply the original E1 + + mov bp, bptemp ; back where we started + mov ax, E1y + add ax, 1024 + mul [_ScrnLogicalByteWidth] + mov di, E1x + add di, 1024 + mov si, di + shr di, 2 + add di, ax + add di, AdjustedOffs + and si, 3 + mov al, ColumnMasks[si] + mov ah, byte ptr Color + mov dx, SC_INDEX + 1 + out dx, al + mov es:[di], ah + + pop es + pop di + pop si + mov sp, bp + pop bp + ret ; git + +; ShortLine subfunction -- +; +; This is designed for short line segments. For longer lines, +; especially horizontal ones, the x_line routine in the XLINE module +; would be faster. But calling that from here it would be a lot of +; extra complication. This is part of the x_bezier routine because +; it has no particular outside use, and we can call it much faster +; through registers than through the stack. +; +; Since our line segments overlap, the second endpoint is not drawn. +; These routines are all out of order for the sake of conditional jumps. + +LRHorz: + dec di +LRHorzLoop: + rol al, 1 + adc bx, 0 + out dx, al + mov es:[bx], ah + sub di, 1 + jg LRHorzLoop + retn + +; You are in a maze of little subroutines, all alike... + + +LR45Deg: + dec si +LR45DegLoop: + add bx, cx + rol al, 1 + adc bx, 0 + out dx, al + mov es:[bx], ah + sub si, 1 + jg LR45DegLoop + retn + + +LRXMajor: + mov cx, di + dec cx + shr di, 1 +LRXMajorLoop: + sub di, si + jge LRXMajorIterate + add di, xdiff + add bx, moveline +LRXMajorIterate: + rol al, 1 + adc bx, 0 + out dx, al + mov es:[bx], ah + sub cx, 1 + jg LRXMajorLoop + retn + + +LeftToRight: + mov xdiff, di ; store distance across line + + mov cx, [_ScrnLogicalByteWidth] + cmp si, 0 ; check if height is positive, negative, or zero + je LRHorz + jg LRTopToBottom + neg si + neg cx +LRTopToBottom: + mov ydiff, si + mov moveline, cx + cmp di, si + jg LRXMajor + je LR45Deg + + +LRYMajor: + mov cx, si + dec cx + shr si, 1 +LRYMajorLoop: + add bx, moveline + sub si, di + jge LRYMajorIterate + add si, ydiff + rol al, 1 + adc bx, 0 +LRYMajorIterate: + out dx, al + mov es:[bx], ah + sub cx, 1 + jg LRYMajorLoop + retn + + +; This is the actual starting point. +; On entry, registers look like this: +; X1: cx +; Y1: ax +; X2: di +; Y2: si +ShortLine: + sub si, ax ; height goes out in si + sub di, cx ; width goes out in di + + mul [_ScrnLogicalByteWidth] + mov dx, cx + shr dx, 2 + add ax, dx + add ax, AdjustedOffs + mov bx, ax ; starting byte of X1, Y1 goes out in bx + and cx, 3 + mov ax, 011h + shl al, cl ; column mask goes out in al + mov dx, SC_INDEX + 1 + mov ah, byte ptr Colort; color goes out in ah + out dx, al + mov es:[bx], ah ; plot first point + + cmp di, 0 + + jg LeftToRight + je VerticalLine + + +RightToLeft: + neg di ; much more useful this way + mov xdiff, di + + mov cx, [_ScrnLogicalByteWidth] + cmp si, 0 ; check if height is positive, negative, or zero + je RLHorz + jg RLTopToBottom + neg si + neg cx +RLTopToBottom: + mov ydiff, si + mov moveline, cx + cmp di, si + jg RLXMajor + je RL45Deg + + +RLYMajor: + mov cx, si + dec cx + shr si, 1 +RLYMajorLoop: + add bx, moveline + sub si, di + jge RLYMajorIterate + add si, ydiff + ror al, 1 + sbb bx, 0 +RLYMajorIterate: + out dx, al + mov es:[bx], ah + sub cx, 1 + jg RLYMajorLoop + retn + + +VerticalLine: + mov cx, [_ScrnLogicalByteWidth] + cmp si, 0 ; check if height is positive + jg VTopToBottom + neg si + neg cx +VTopToBottom: + dec si +VLoop: + add bx, cx + mov es:[bx], ah + sub si, 1 + jg VLoop + retn + + +RLHorz: + dec di +RLHorzLoop: + ror al, 1 + sbb bx, 0 + out dx, al + mov es:[bx], ah + sub di, 1 + jg RLHorzLoop + retn + + +RL45Deg: + dec si +RL45DegLoop: + add bx, cx + ror al, 1 + sbb bx, 0 + out dx, al + mov es:[bx], ah + sub si, 1 + jg RL45DegLoop + retn + + +RLXMajor: + mov cx, di + dec cx + shr di, 1 +RLXMajorLoop: + sub di, si + jge RLXMajorIterate + add di, xdiff + add bx, moveline +RLXMajorIterate: + ror al, 1 + sbb bx, 0 + out dx, al + mov es:[bx], ah + sub cx,1 + jg RLXMajorLoop + retn + + +_x_bezier endp + + end + diff --git a/16/xlib/xbezier.h b/16/xlib/xbezier.h new file mode 100755 index 00000000..cb7818da --- /dev/null +++ b/16/xlib/xbezier.h @@ -0,0 +1,25 @@ +/*********************************************************************\ +| XBEZIER header file +| +| +| This module was written by Matthew MacKenzie +| matm@eng.umd.edu +\*********************************************************************/ + +#ifndef _XBEZIER_H_ +#define _XBEZIER_H_ +#ifdef __cplusplus + +extern "C" { +#endif + +void x_bezier (int E1x, int E1y, int C1x, int C1y, int C2x, int C2y, + int E2x, int E2y, int levels, char color, + unsigned PageOffset); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/16/xlib/xbezier.inc b/16/xlib/xbezier.inc new file mode 100755 index 00000000..274a1c81 --- /dev/null +++ b/16/xlib/xbezier.inc @@ -0,0 +1,10 @@ +;----------------------------------------------------------------------- +; XBEZIER include file +; +; +; This module was written by Matthew MacKenzie +; matm@eng.umd.edu +;----------------------------------------------------------------------- + +global _x_bezier : proc + diff --git a/16/xlib/xbmtools.asm b/16/xlib/xbmtools.asm new file mode 100755 index 00000000..4638d42a --- /dev/null +++ b/16/xlib/xbmtools.asm @@ -0,0 +1,195 @@ +;----------------------------------------------------------------------- +; MODULE XBMTOOLS +; +; Bitmap conversion / manipulation tools +; +; Compile with Tasm. +; C callable. +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- +COMMENT $ + + This module implements a set of functions to manipulate both planar + bitmaps and linear bitmaps (as used by x_compile_bitmap): + + PLANAR BITMAPS + + Planar bitmaps as used by these functions have the following structure: + + BYTE 0 The bitmap width in bytes (4 pixel groups) range 1..255 + BYTE 1 The bitmap height in rows range 1..255 + BYTE 2..n1 The plane 0 pixels width*height bytes + BYTE n1..n2 The plane 1 pixels width*height bytes + BYTE n2..n3 The plane 2 pixels width*height bytes + BYTE n3..n4 The plane 3 pixels width*height bytes + + LINEAR BITMAPS + + Linear bitmaps have the following structure: + + BYTE 0 The bitmap width in pixels range 1..255 + BYTE 1 The bitmap height in rows range 1..255 + BYTE 2..n The width*height bytes of the bitmap + + + +$ + +LOCALS +.286 + +include model.inc +include xbmtools.inc + + .code + + + +;----------------------------------------------------------------------- +; x_pbm_to_bm +; +; This function converts a bitmap in the planar format to the linear format +; as used by x_compile_bitmap. +; +; WARNING: the source and destination bitmaps must be pre - allocated +; +; NOTE: This function can only convert planar bitmaps that are suitable. +; If the source planar bitmap's width (per plane) is >= 256/4 +; it cannot be converted. In this situation an error code +; BM_WIDTH_ERROR. On successful conversion 0 is returned. +; +; C callable as: +; int x_pbm_to_bm(char far * source_pbm, char far * dest_bm); +; +; Written By Themie Gouthas + +proc _x_pbm_to_bm +ARG src_pbm:dword,dest_bm:dword + push bp ; Preserve caller's stack frame + mov bp,sp + push ds + push di + push si + + les di,[dest_bm] ; es:di -> destination bitmap + lds si,[src_pbm] ; ds:si -> source planar bitmap + lodsb ; load AL with source pbm pixel width per plane + mov bl,al ; save in CL + xor ah,ah ; convert to word + shl ax,2 ; mult by 4 giving source image width + cmp ax,255 ; if the result > 255 then we have exceeded + ja @@WidthError ; the max width of linear bm. + + stosb ; write do dest_bm + + lodsb ; tranfer source pbm height in pixels to + stosb ; dest_bm + + xor ah,ah ; convert to word + mul bl ; AX = AX * BL ie. total no. pixels per plane + mov dx,di ; save DI, the pointer to the destination bm + mov bl,3 ; set plane loop counter (BL) + +@@PlaneLoop: + mov cx,ax ; set CX to total number of pixels per plane + +@@PixelLoop: + movsb ; transfer pixel + add di,3 ; increment destination to compensate for plane + loop @@PixelLoop + + inc dx ; increment original di for next pixel plane + mov di,dx ; and restore di from incremented original + dec bl ; decrement plane counter + jns @@PlaneLoop ; loop if more planes left + xor ax,ax + jmp short @@Done +@@WidthError: + mov ax,1 + +@@Done: + pop si + pop di + pop ds + pop bp ;restore caller's stack frame + ret +_x_pbm_to_bm endp + + +;----------------------------------------------------------------------- +; x_bm_to_pbm +; +; This function converts a bitmap in the linear format as used by +; x_compile_bitmap to the planar formap. +; +; WARNING: the source and destination bitmaps must be pre - allocated +; +; NOTE: This function can only convert linear bitmaps that are suitable. +; If the source linear bitmap's width is not a multiple of 4 +; it cannot be converted. In this situation an error code +; BM_WIDTH_ERROR. On successful conversion 0 is returned. +; +; +; C callable as: +; int x_bm_to_pbm(char far * source_pbm, char far * dest_bm); +; +; Written By Themie Gouthas + +proc _x_bm_to_pbm +ARG src_bm:dword,dest_pbm:dword + push bp ; Preserve caller's stack frame + mov bp,sp + push ds + push di + push si + + les di,[dest_pbm] ; es:di -> destination planar bitmap + lds si,[src_bm] ; ds:si -> source bitmap + lodsb ; load AX with source bitmap width + test al,03h ; Check that width is a multiple of 4 + jnz @@WidthIncompatible + shr al,2 ; divide by 4 giving width of plane + stosb ; store destination planar bitmap width + mov bl,al ; and copy to bl + lodsb + stosb ; Transfer source bitmap height to dest pbm + xor ah,ah ; Conver height to word + mul bl ; calculate the total no. of pixels / plane + mov dx,si ; save source offset + mov bl,3 + +@@PlaneLoop: + mov cx,ax ; set CX to total number of pixels per plane + +@@PixelLoop: + movsb ; transfer pixel + add si,3 ; increment src offset to compensate for plane + loop @@PixelLoop + + inc dx ; increment original si for next pixel plane + mov si,dx ; and restore si from incremented original + dec bl ; decrement plane counter + jns @@PlaneLoop ; loop if more planes left + xor ax,ax + jmp short @@Done +@@WidthIncompatible: + mov ax,1 + +@@Done: + pop si + pop di + pop ds + pop bp ;restore caller's stack frame + ret +_x_bm_to_pbm endp + + + end + diff --git a/16/xlib/xbmtools.h b/16/xlib/xbmtools.h new file mode 100755 index 00000000..3007d1f4 --- /dev/null +++ b/16/xlib/xbmtools.h @@ -0,0 +1,63 @@ +/*----------------------------------------------------------------------- +; +; XPOINT - header file +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; Macros written by Mathew Mackenzie +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;-----------------------------------------------------------------------*/ + +#ifndef _XBMTOOLS_H_ +#define _XBMTOOLS_H_ + +#define BM_WIDTH_ERROR 1 + +#define LBMHeight(lbitmap) lbitmap[1] +#define LBMWidth(lbitmap) lbitmap[0] +#define PBMHeight(pbitmap) pbitmap[1] +#define PBMWidth(pbitmap) (pbitmap[0]<<2) +#define PBMByteWidth(pbitmap) pbitmap[0] + +#define LBMPutPix(x,y,lbitmap,color) \ + lbitmap[2 + (x) + (y) * LBMWidth(lbitmap)] = color + +#define LBMGetPix(x,y,lbitmap) \ + (lbitmap[2 + (x) + (y) * LBMWidth(lbitmap)]) + + + +/* FUNCTIONS =========================================================== */ + +#ifdef __cplusplus +extern "C" { +#endif + + int x_pbm_to_bm( /* Convert from planar bitmap to linear */ + char far * source_pbm, + char far * dest_bm); + + int x_bm_to_pbm( /* Convert from linear bitmap to planar */ + char far * source_pbm, + char far * dest_bm); + +#ifdef __cplusplus +} +#endif + + +#endif + + diff --git a/16/xlib/xbmtools.inc b/16/xlib/xbmtools.inc new file mode 100755 index 00000000..fe5415c6 --- /dev/null +++ b/16/xlib/xbmtools.inc @@ -0,0 +1,20 @@ +;----------------------------------------------------------------------- +; +; XBMTOOLS - Include file +; +; XBMTOOLS.ASM export functions +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + + global _x_pbm_to_bm :proc + global _x_bm_to_pbm :proc + \ No newline at end of file diff --git a/16/xlib/xcbitm32.c b/16/xlib/xcbitm32.c new file mode 100755 index 00000000..1d70e6a0 --- /dev/null +++ b/16/xlib/xcbitm32.c @@ -0,0 +1,188 @@ +#include "xbmtools.h" + +/* these are here instead of the header file because they're not part + of the library interface */ + +// rol al +#define ROL_AL 0xc0d0 +// mov [si + disp8], imm8 +#define SHORT_STORE_8 0x44c6 +// mov [si + disp16], imm8 +#define STORE_8 0x84c6 +// mov [si + disp8], imm16 +#define SHORT_STORE_16 0x44c7 +// mov [si + disp16], imm16 +#define STORE_16 0x84c7 +// adc si, imm8 +#define ADC_SI_IMMED 0xd683 +// out dx, al +#define OUT_AL 0xee +// ret +#define RETURN 0xcb +// 32-bit prefix +#define DWORD_PREFIX 0x66 + +#define Emitb(x) *(output + output_used) = (x); output_used++ + +#define Emitw(x) *(output + output_used) = (x) & 255; \ + *(output + output_used + 1) = (x) >> 8; \ + output_used += 2 + + +int x_compile_bitmap_32 (int logical_screen_width, char far * bitmap, + char far * output) +{ + int pix0, pix1, pix2, pix3, numpix, pos; + int column = 0, set_column = 0; + int scanx = 0, scany = 0; + int output_used = 0; + + int height = LBMHeight(bitmap); + int width = LBMWidth(bitmap); + int margin = width - 1; + int margin2 = margin - 4; + int margin4 = margin - 12; + + while (column < 4) { + numpix = 1; + pix0 = LBMGetPix(scanx, scany, bitmap); + if (pix0 != 0) { + if (set_column != column) { + do { + Emitw (ROL_AL); + Emitw (ADC_SI_IMMED); + Emitb (0); + set_column++; + } while (set_column != column); + Emitb (OUT_AL); + } + if (scanx <= margin2) { + pix1 = LBMGetPix(scanx + 4, scany, bitmap); + if ((pix1 != 0) + &&(scanx <= margin4)) { + numpix = 2; + pix2 = LBMGetPix(scanx + 8, scany, bitmap); + pix3 = LBMGetPix(scanx + 12, scany, bitmap); + if ((pix2 != 0) && (pix3 != 0)) { + numpix = 4; + Emitb (DWORD_PREFIX); + } + } + } + pos = (scany * logical_screen_width) + (scanx >> 2) - 128; + if ((pos >= -128) && (pos <= 127)) { + if (numpix == 1) { + Emitw (SHORT_STORE_8); + Emitb (pos); + Emitb (pix0); + } else { + Emitw (SHORT_STORE_16); + Emitb (pos); + Emitb (pix0); + Emitb (pix1); + if (numpix == 4) { + Emitb (pix2); + Emitb (pix3); + } + } + } else { + if (numpix == 1) { + Emitw (STORE_8); + Emitw (pos); + Emitb (pix0); + } else { + Emitw (STORE_16); + Emitw (pos); + Emitb (pix0); + Emitb (pix1); + if (numpix == 4) { + Emitb (pix2); + Emitb (pix3); + } + } + } + } + scanx += (numpix << 2); + if (scanx > margin) { + scanx = column; + scany++; + if (scany == height) { + scany = 0; + column++; + } + } + } + Emitb(RETURN); + return(output_used); +} + + +int x_sizeof_cbitmap_32 (int logical_screen_width, char far * bitmap) +{ + int pix0, pix1, pix2, pix3, numpix, pos; + int column = 0, set_column = 0; + int scanx = 0, scany = 0; + int output_used = 1; + + int height = LBMHeight(bitmap); + int width = LBMWidth(bitmap); + int margin = width - 1; + int margin2 = margin - 4; + int margin4 = margin - 12; + + while (column < 4) { + numpix = 1; + pix0 = LBMGetPix(scanx, scany, bitmap); + if (pix0 != 0) { + if (set_column != column) { + do { + output_used += 5; + set_column++; + } while (set_column != column); + output_used++; + } + if (scanx <= margin2) { + pix1 = LBMGetPix(scanx + 4, scany, bitmap); + if ((pix1 != 0) + &&(scanx <= margin4)) { + numpix = 2; + pix2 = LBMGetPix(scanx + 8, scany, bitmap); + pix3 = LBMGetPix(scanx + 12, scany, bitmap); + if ((pix2 != 0) && (pix3 != 0)) { + numpix = 4; + output_used++; + } + } + } + pos = (scany * logical_screen_width) + (scanx >> 2) - 128; + if ((pos >= -128) && (pos <= 127)) { + if (numpix == 1) { + output_used += 4; + } else { + output_used += 5; + if (numpix == 4) + output_used += 2; + } + } else { + if (numpix == 1) { + output_used += 5; + } else { + output_used += 6; + if (numpix == 4) + output_used += 2; + } + } + } + scanx += (numpix << 2); + if (scanx > margin) { + scanx = column; + scany++; + if (scany == height) { + scany = 0; + column++; + } + } + } + return(output_used); +} + diff --git a/16/xlib/xcbitm32.h b/16/xlib/xcbitm32.h new file mode 100755 index 00000000..f43c5946 --- /dev/null +++ b/16/xlib/xcbitm32.h @@ -0,0 +1,34 @@ +/*----------------------------------------------------------------------- +; +; XCBITM32 - header file +; +; This module was written by Matthew MacKenzie +; matm@eng.umd.edu +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +;----------------------------------------------------------------------*/ +/* Notice that there is no function in this module to plot a + compiled bitmap. Use x_put_cbitmap in module XCBITMAP. */ + +/* This module is only for 386+ class computers. */ + +#ifndef _XCBITM32_H_ +#define _XCBITM32_H_ + +extern int x_compile_bitmap_32 ( /* Compile a linear bitmap to generate */ + WORD logical_screen_width, /* machine code to plot it at any */ + char far * bitmap, /* required screen coordinates FAST. */ + char far * output); + +extern int x_sizeof_cbitmap_32 ( /* Find the size of the code which a */ + WORD logical_screen_width, /* bitmap would result in, if it */ + char far * bitmap); /* were compiled (used for allocation). */ + +#endif diff --git a/16/xlib/xcbitmap.asm b/16/xlib/xcbitmap.asm new file mode 100755 index 00000000..2fbc84b9 --- /dev/null +++ b/16/xlib/xcbitmap.asm @@ -0,0 +1,422 @@ +;----------------------------------------------------------------------- +; MODULE XCBITMAP +; This module was written by Matthew MacKenzie +; matm@eng.umd.edu +; +; Compiled bitmap functions all MODE X 256 Color resolutions +; +; Compile with Tasm. +; C callable. +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; ****** Aeronautical Research Laboratory **************** +; ****** Defence Science and Technology Organisation **************** +; ****** Australia **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + +include xlib.inc +include xcbitmap.inc + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; _x_compile_bitmap +; +; Compile a linear bitmap to generate machine code to plot it +; at any required screen coordinates FAST. Faster than blits +; using planar bitmaps as in module XPBIITMAP +; +; C near-callable as: +; int x_compile_bitmap (WORD logical_screen_width, +; char far * bitmap, char far * output); +; +; The logical width is in bytes rather than pixels. +; +; All four main registers are totaled. +; +; The source linear bitmaps have the following structure: +; +; BYTE 0 The bitmap width in pixels range 1..255 +; BYTE 1 The bitmap height in rows range 1..255 +; BYTE 2..n The width*height bytes of the bitmap in +; cloumn row order +; +; The returned value is the size of the compiled bitmap, in bytes. + + +; accessory macros to save typing (what else?) +Emitb macro arg + mov byte ptr es:[di],&arg& + inc di + endm + +Emitw macro arg + mov word ptr es:[di],&arg& + add di,2 + endm + +; opcodes emitted by _x_compile_sprite +ROL_AL equ 0c0d0h ; rol al +SHORT_STORE_8 equ 044c6h ; mov [si]+disp8, imm8 +STORE_8 equ 084c6h ; mov [si]+disp16, imm8 +SHORT_STORE_16 equ 044c7h ; mov [si]+disp8, imm16 +STORE_16 equ 084c7h ; mov [si]+disp16, imm16 +ADC_SI_IMMED equ 0d683h ; adc si,imm8 +OUT_AL equ 0eeh ; out dx,al +RETURN equ 0cbh ; ret + + +.data + +align 2 +ColumnMask db 011h,022h,044h,088h + + +.code + + align 2 +_x_compile_bitmap proc +ARG logical_width:word,bitmap:dword,output:dword +LOCAL bwidth,scanx,scany,outputx,outputy,column,set_column,input_size:word=LocalStk + push bp + mov bp, sp ; caller's stack frame + sub sp,LocalStk ; local space + push si + push di + push ds + + mov word ptr [scanx],0 + mov word ptr [scany],0 + mov word ptr [outputx],0 + mov word ptr [outputy],0 + mov word ptr [column],0 + mov word ptr [set_column],0 + + lds si,[bitmap] ; 32-bit pointer to source bitmap + + les di,[output] ; 32-bit pointer to destination stream + + lodsb ; load width byte + xor ah, ah ; convert to word + mov [bwidth], ax ; save for future reference + mov bl, al ; copy width byte to bl + lodsb ; load height byte -- already a word since ah=0 + mul bl ; mult height word by width byte + mov [input_size], ax; to get pixel total + +@@MainLoop: + mov bx, [scanx] ; position in original bitmap + add bx, [scany] + + mov al, [si+bx] ; get pixel + or al, al ; skip empty pixels + jnz @@NoAdvance + jmp @@Advance +@@NoAdvance: + + mov dx, [set_column] + cmp dx, [column] + je @@SameColumn +@@ColumnLoop: + Emitw ROL_AL ; emit code to move to new column + Emitw ADC_SI_IMMED + Emitb 0 + + inc dx + cmp dx, [column] + jl @@ColumnLoop + + Emitb OUT_AL ; emit code to set VGA mask for new column + mov [set_column], dx +@@SameColumn: + mov dx, [outputy] ; calculate output position + add dx, [outputx] + sub dx, 128 + + add word ptr [scanx], 4 + mov cx, [scanx] ; within four pixels of right edge? + cmp cx, [bwidth] + jge @@OnePixel + + inc word ptr [outputx] + mov ah, [si+bx+4] ; get second pixel + or ah, ah + jnz @@TwoPixels +@@OnePixel: + cmp dx, 127 ; can we use shorter form? + jg @@OnePixLarge + cmp dx, -128 + jl @@OnePixLarge + Emitw SHORT_STORE_8 + Emitb dl ; 8-bit position in output + jmp @@EmitOnePixel +@@OnePixLarge: + Emitw STORE_8 + Emitw dx ; position in output +@@EmitOnePixel: + Emitb al + jmp short @@Advance +@@TwoPixels: + cmp dx, 127 + jg @@TwoPixLarge + cmp dx, -128 + jl @@TwoPixLarge + Emitw SHORT_STORE_16 + Emitb dl ; 8-bit position in output + jmp @@EmitTwoPixels +@@TwoPixLarge: + Emitw STORE_16 + Emitw dx ; position in output +@@EmitTwoPixels: + Emitw ax + +@@Advance: + inc word ptr [outputx] + mov ax, [scanx] + add ax, 4 + cmp ax, [bwidth] + jl @@AdvanceDone + mov dx, [outputy] + add dx, [logical_width] + mov cx, [scany] + add cx, [bwidth] + cmp cx, [input_size] + jl @@NoNewColumn + inc word ptr [column] + mov cx, [column] + cmp cx, 4 + je @@Exit ; Column 4: there is no column 4. + xor cx, cx ; scany and outputy are 0 again for + mov dx, cx ; the new column +@@NoNewColumn: + mov [outputy], dx + mov [scany], cx + mov word ptr [outputx], 0 + mov ax,[column] +@@AdvanceDone: + mov [scanx], ax + jmp @@MainLoop + +@@Exit: + Emitb RETURN + mov ax,di + sub ax,word ptr [output] ; size of generated code + + pop ds + pop di + pop si + mov sp, bp + pop bp + + ret +_x_compile_bitmap endp + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; _x_sizeof_cbitmap +; +; This function follows the same algorithm as the one above, +; but does not generate a new object. Its sole purpose is to +; determine how much space the compiled bitmap will require. +; +; C near-callable as: +; int x_sizeof_cbitmap (WORD logical_screen_width, +; char far * bitmap); +; +; The logical width is in bytes rather than pixels. +; +; All four main registers are totaled. +; +; The source linear bitmaps have the following structure: +; +; BYTE 0 The bitmap width in pixels range 1..255 +; BYTE 1 The bitmap height in rows range 1..255 +; BYTE 2..n The width*height bytes of the bitmap in +; cloumn row order +; +; The returned value is the size of the compiled bitmap, in bytes. + + + align 2 +_x_sizeof_cbitmap proc +ARG logical_width:word,bitmap:dword +LOCAL bwidth,scanx,scany,outputx,outputy,column,set_column,input_size:word=LocalStk + push bp + mov bp, sp ; caller's stack frame + sub sp,LocalStk ; local space + push si + push di + push ds + + mov word ptr [scanx], 0 + mov word ptr [scany], 0 + mov word ptr [outputx], 0 + mov word ptr [outputy], 0 + mov word ptr [column], 0 + mov word ptr [set_column], 0 + + lds si,[bitmap] ; 32-bit pointer to source bitmap + + mov di, 1 ; initial size is just the size of the far RET + + lodsb ; load width byte + xor ah, ah ; convert to word + mov [bwidth], ax ; save for future reference + mov bl, al ; copy width byte to bl + lodsb ; load height byte -- already a word since ah=0 + mul bl ; mult height word by width byte + mov [input_size], ax; to get pixel total + +@@MainLoop: + mov bx, [scanx] ; position in original bitmap + add bx, [scany] + + mov al, [si+bx] ; get pixel + or al, al ; skip empty pixels + jnz @@NoAdvance + jmp @@Advance +@@NoAdvance: + + mov dx, [set_column] + cmp dx, [column] + je @@SameColumn +@@ColumnLoop: + add di, 5 ; size of code to move to new column + inc dx + cmp dx,[column] + jl @@ColumnLoop + + inc di ; size of code to set VGA mask + mov [set_column], dx +@@SameColumn: + mov dx, [outputy] ; calculate output position + add dx, [outputx] + sub dx, 128 + + add word ptr [scanx], 4 + mov cx, [scanx] ; within four pixels of right edge? + cmp cx, [bwidth] + jge @@OnePixel + + inc word ptr [outputx] + mov ah,[si+bx+4] ; get second pixel + or ah, ah + jnz @@TwoPixels +@@OnePixel: + cmp dx, 127 ; can we use shorter form? + jg @@OnePixLarge + cmp dx, -128 + jl @@OnePixLarge + add di, 4 ; size of 8-bit position in output plus one pixel + jmp @@EmitOnePixel +@@OnePixLarge: + add di, 5 ; size of position in output plus one pixels +@@EmitOnePixel: + jmp short @@Advance +@@TwoPixels: + cmp dx, 127 + jg @@TwoPixLarge + cmp dx, -128 + jl @@TwoPixLarge + add di, 5 ; size of 8-bit position in output plus two pixels + jmp @@EmitTwoPixels +@@TwoPixLarge: + add di, 6 ; size of 16-bit position in output plus two pixels +@@EmitTwoPixels: + +@@Advance: + inc word ptr [outputx] + mov ax, [scanx] + add ax,4 + cmp ax, [bwidth] + jl @@AdvanceDone + mov dx, [outputy] + add dx, [logical_width] + mov cx, [scany] + add cx, [bwidth] + cmp cx, [input_size] + jl @@NoNewColumn + inc word ptr [column] + mov cx, [column] + cmp cx, 4 + je @@Exit ; Column 4: there is no column 4. + xor cx,cx ; scany and outputy are 0 again for + mov dx,cx ; the new column +@@NoNewColumn: + mov [outputy], dx + mov [scany], cx + mov word ptr [outputx], 0 + mov ax,[column] +@@AdvanceDone: + mov [scanx], ax + jmp @@MainLoop + +@@Exit: + mov ax, di ; size of generated code + + pop ds + pop di + pop si + mov sp,bp + pop bp + + ret +_x_sizeof_cbitmap endp + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; _x_put_cbitmap +; +; Displays a compiled bitmap generated by x_compile_bitmap at given +; coordinates, on a given screen page. +; +; C near-callable as: +; void x_put_cbitmap (int XPos, int YPos, +; unsigned int PageOffset, char far * Sprite); +; ax, bx, cx, and dx are squashed like insignificant insects. + + align 2 +_x_put_cbitmap proc +ARG XPos:word,YPos:word,PageOffset:word,Sprite:dword + + push bp + mov bp, sp + push si + push ds + + mov ax, [_ScrnLogicalByteWidth] ; global Xlib variable + mul word ptr [YPos] ; height in bytes + mov si, [XPos] + mov bx, si + sar si, 2 ; width in bytes + add si, ax + add si, [PageOffset]; (YPos * screen width) + + add si, 128 ; (Xpos / 4) + page base + 128 ==> starting pos + + and bx, 3 + mov ah, ColumnMask[bx] + + mov dx, SC_INDEX + mov al, MAP_MASK + out dx, ax + inc dx ; ready to send out other masks as bytes + mov al, ah + + mov bx, SCREEN_SEG + mov ds, bx ; We do this so the compiled shape won't need + ; segment overrides. + + call dword ptr [Sprite] ; the business end of the routine + + pop ds + pop si + pop bp + + ret +_x_put_cbitmap endp + +end + diff --git a/16/xlib/xcbitmap.h b/16/xlib/xcbitmap.h new file mode 100755 index 00000000..dd747ce9 --- /dev/null +++ b/16/xlib/xcbitmap.h @@ -0,0 +1,47 @@ +/*----------------------------------------------------------------------- +; +; XCBITMAP - header file +; +; This module was written by Matthew MacKenzie +; matm@eng.umd.edu +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +;----------------------------------------------------------------------*/ + +#ifndef _XCBITMAP_H_ +#define _XCBITMAP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + + int x_compile_bitmap ( /* Compile a linear bitmap to generate */ + WORD logical_screen_width, /* machine code to plot it at any */ + char far * bitmap, /* required screen coordinates FAST. */ + char far * output); + + int x_sizeof_cbitmap ( /* Find the size of the code which a */ + WORD logical_screen_width, /* bitmap would result in, if it */ + char far * bitmap); /* were compiled (used for allocation). */ + + void x_put_cbitmap ( /* Displays a compiled bitmap generated */ + WORD XPos, /* by x_compile_bitmap. */ + WORD YPos, + WORD PageOffset, + char far * CompiledBitmap); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/16/xlib/xcbitmap.inc b/16/xlib/xcbitmap.inc new file mode 100755 index 00000000..b9c9568d --- /dev/null +++ b/16/xlib/xcbitmap.inc @@ -0,0 +1,21 @@ +;----------------------------------------------------------------------- +; +; XCBITMAP - Include file +; This module was written by Matthew MacKenzie +; matm@eng.umd.edu +; +; XCBITMAP.ASM export functions +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + +global _x_compile_bitmap : proc +global _x_sizeof_cbitmap : proc +global _x_put_cbitmap : proc + + \ No newline at end of file diff --git a/16/xlib/xcircle.asm b/16/xlib/xcircle.asm new file mode 100755 index 00000000..4e750313 --- /dev/null +++ b/16/xlib/xcircle.asm @@ -0,0 +1,710 @@ +;----------------------------------------------------------------------- +; +; MODULE XCIRCLE +; +; This module was written by Matthew MacKenzie +; matm@eng.umd.edu +; +; Circles, full and empty. +; +; Compile with Tasm. +; C callable. +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + +include xlib.inc +include xcircle.inc + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; _x_circle +; +; Draw a circle. +; +; C near-callable as: +; int x_circle (WORD Left, WORD Top, WORD Diameter, +; WORD Color, WORD ScreenOffs); +; +; No clipping is performed. +; +; ax, bx, cx, and dx bite the dust, as Homer would say. + +; we plot into eight arcs at once: +; 4 0 +; 6 \|/ 2 +; --*-- +; 7 /|\ 3 +; 5 1 +; +; 0, 1, 4, and 5 are considered x-major; the rest, y-major. +; +; The x-major plots grow out from the top and bottom of the circle, +; while the y-major plots start at the left and right edges. + + .data + + align 2 + +ColumnMask db 011h,022h,044h,088h + + .code + + public _x_circle + align 2 +_x_circle proc +ARG Left:word, Top:word, Diameter:word, Color:word, ScreenOffs:word +LOCAL offset0,offset1,offset2,offset3,offset4,offset5,offset6,offset7,mask0n1,mask2n3,mask4n5,mask6n7,shrunk_radius,diameter_even,error:word=LocalStk +; Tasm 1.0 does not allow the \ line continuation +;LOCAL offset0:word, offset1:word, offset2:word, offset3:word, \ +; offset4:word, offset5:word, offset6:word, offset7:word, \ +; mask0n1:word, mask2n3:word, mask4n5:word, mask6n7:word, \ +; shrunk_radius:word, diameter_even:word, error:word=LocalStk + + push bp + mov bp, sp + sub sp, LocalStk + push si + push di + push ds + +; find starting locations of plots 2, 3, 6, and 7 + mov di, _ScrnLogicalByteWidth + xor dx, dx + + mov ax, Diameter ; find vertical midpoint + dec ax + shr ax, 1 + adc dx, 0 ; remember if it's rounded + mov shrunk_radius, ax ; radius, rounded down for adding + mov diameter_even, dx ; (diameter - 1) & 1, effectively + add ax, Top + mul di ; vertical midpoint in bytes + add ax, ScreenOffs + + mov bx, Left + mov cx, bx ; save for later + mov si, bx + shr si, 2 + add si, ax + mov offset6, si + and bx, 3 ; column of left side + mov bl, ColumnMask[bx] + mov mask6n7, bx + + add cx, Diameter + dec cx + mov bx, cx + shr cx, 2 + add cx, ax + mov offset2, cx + and bx, 3 ; column of right side + mov bl, ColumnMask[bx] + mov mask2n3, bx + + cmp diameter_even, 1 + jne @@MiddlePlotsOverlap + add si, di + add cx, di +@@MiddlePlotsOverlap: + mov offset7, si + mov offset3, cx + +; starting locations of 0, 1, 4, and 5 + mov bx, Left + add bx, shrunk_radius ; find horizontal midpoint + + mov ax, Top ; top in bytes + mul di + add ax, ScreenOffs + mov si, ax + + mov ax, Diameter ; bottom in bytes + dec ax + mul di + add ax, si + + mov di, bx ; horizontal midpoint in bytes + shr di, 2 + add si, di ; top midpoint in bytes + mov offset4, si + add di, ax ; bottom midpoint in bytes + mov offset5, di + and bx, 3 ; column of horizontal midpoint + mov bl, ColumnMask[bx] + mov mask4n5, bx + + cmp diameter_even, 1 + jne @@TopAndBottomPlotsOverlap + rol bl, 1 + jnc @@TopAndBottomPlotsOverlap + inc si + inc di +@@TopAndBottomPlotsOverlap: + mov offset0, si + mov offset1, di + mov mask0n1, bx + +; we've got our eight plots in their starting positions, so +; it's time to sort out the registers + mov bx, _ScrnLogicalByteWidth + + mov dx, SCREEN_SEG + mov ds, dx + + mov dx, SC_INDEX ; set VGA to accept column masks + mov al, MAP_MASK + out dx, al + inc dx ; gun the engine... + + mov si, Diameter ; initial y is radius -- 2 #s per pixel + inc si + + mov cx, si + neg cx + add cx, 2 + mov error, cx ; error = -y + one pixel since we're a step ahead + + xor cx, cx ; initial x = 0 + mov ah, byte ptr Color + jmp @@CircleCalc ; let's actually put something on the screen! + +; move the x-major plots horizontally and the y-major plots vertically +@@NoAdvance: + mov al, byte ptr mask0n1 + out dx, al + mov di, offset0 ; plot 0 + mov [di], ah + rol al, 1 ; advance 0 right + mov byte ptr mask0n1, al + adc di, 0 + mov offset0, di + mov di, offset1 + mov [di], ah ; plot 1 + ror al, 1 ; what was that bit again? + adc di, 0 ; advance 1 right + mov offset1, di + + mov al, byte ptr mask2n3 + out dx, al + mov di, offset2 + mov [di], ah ; plot 2 + sub di, bx ; advance 2 up + mov offset2, di + mov di, offset3 + mov [di], ah ; plot 3 + add di, bx ; advance 3 down + mov offset3, di + + mov al, byte ptr mask4n5 + out dx, al + mov di, offset4 + mov [di], ah + ror al, 1 + mov byte ptr mask4n5, al + sbb di, 0 + mov offset4, di + mov di, offset5 + mov [di], ah + rol al, 1 + sbb di, 0 + mov offset5, di + + mov al, byte ptr mask6n7 + out dx, al + mov di, offset6 + mov [di], ah + sub di, bx + mov offset6, di + mov di, offset7 + mov [di], ah + add di, bx + mov offset7, di + + jmp @@CircleCalc + +; move all plots diagonally +@@Advance: + mov al, byte ptr mask0n1 + out dx, al + mov di, offset0 + mov [di], ah ; plot 0 + rol al, 1 ; advance 0 right and down + mov byte ptr mask0n1, al + adc di, bx + mov offset0, di + mov di, offset1 + mov [di], ah ; plot 1 + ror al, 1 ; what was that bit again? + adc di, 0 ; advance 1 right and up + sub di, bx + mov offset1, di + + mov al, byte ptr mask2n3 + out dx, al + mov di, offset2 + mov [di], ah ; plot 2 + ror al, 1 ; advance 2 up and left + mov byte ptr mask2n3, al + sbb di, bx + mov offset2, di + mov di, offset3 + mov [di], ah ; plot 3 + rol al, 1 + sbb di, 0 ; advance 3 down and left + add di, bx + mov offset3, di + + mov al, byte ptr mask4n5 + out dx, al + mov di, offset4 + mov [di], ah + ror al, 1 + mov byte ptr mask4n5, al + sbb di, 0 + add di, bx + mov offset4, di + mov di, offset5 + mov [di], ah + rol al, 1 + sbb di, bx + mov offset5, di + + mov al, byte ptr mask6n7 + out dx, al + mov di, offset6 + mov [di], ah + rol al, 1 + mov byte ptr mask6n7, al + adc di, 0 + sub di, bx + mov offset6, di + mov di, offset7 + mov [di], ah + ror al, 1 + adc di, bx + mov offset7, di + +; do you realize the entire function has been set up for this little jot? +; keep in mind that radii values are 2 per pixel +@@CircleCalc: + add cx, 2 ; x += 1 + mov di, error + add di, cx ; error += (2 * x) + 1 + inc di + jl @@CircleNoError + cmp cx, si ; x > y? + ja @@FleeFlyFlowFum + sub si, 2 ; y -= 1 + sub di, si ; error -= (2 * y) + mov error, di + jmp @@Advance +@@CircleNoError: + mov error, di + jmp @@NoAdvance + +@@FleeFlyFlowFum: + pop ds + pop di + pop si + mov sp,bp + pop bp + + ret + +_x_circle endp + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; _x_filled_circle +; +; Draw a disc. +; +; C near-callable as: +; int x_filled_circle (WORD Left, WORD Top, WORD Diameter, +; WORD Color, WORD ScreenOffs); +; +; No clipping is performed. +; +; ax, bx, cx, dx, and es bite the dust, as Homer would say. +; DF is set to 0 (strings go forward). + + .data + + align 2 + +; the only entries of these tables which are used are positions +; 1, 2, 4, and 8 +LeftMaskTable db 0, 0ffh, 0eeh, 0, 0cch, 0, 0, 0, 088h +RightMaskTable db 0, 011h, 033h, 0, 077h, 0, 0, 0, 0ffh + + .code + + public _x_filled_circle + align 2 +_x_filled_circle proc +ARG Left:word, Top:word, Diameter:word, Color:word, ScreenOffs:word +; Tasm 1.0 does not allow the \ line continuation +;LOCAL offset0:word, offset1:word, offset2:word, offset3:word, \ +; offset4:word, offset5:word, offset6:word, offset7:word, \ +; mask0n1:word, mask2n3:word, mask4n5:word, mask6n7:word, \ +; shrunk_radius:word, diameter_even:word, error:word, \ +; jump_vector:word=LocalStk +LOCAL offset0,offset1,offset2,offset3,offset4,offset5,offset6,offset7,mask0n1,mask2n3,mask4n5,mask6n7,shrunk_radius,diameter_even,error,jump_vector:word=LocalStk + + push bp + mov bp, sp + sub sp, LocalStk + push si + push di + + cld ; strings march forward + +; this first part is identical to the other function -- +; the only differences, in fact, are in the drawing and moving around + +; find starting locations of plots 2, 3, 6, and 7 + mov di, _ScrnLogicalByteWidth + xor dx, dx + + mov ax, Diameter ; find vertical midpoint + dec ax + shr ax, 1 + adc dx, 0 ; remember if it's rounded + mov shrunk_radius, ax ; radius, rounded down for adding + mov diameter_even, dx ; (diameter - 1) & 1, effectively + add ax, Top + mul di ; vertical midpoint in bytes + add ax, ScreenOffs + + mov bx, Left + mov cx, bx ; save for later + mov si, bx + shr si, 2 + add si, ax + mov offset6, si + and bx, 3 ; column of left side + mov bl, ColumnMask[bx] + mov mask6n7, bx + + add cx, Diameter + dec cx + mov bx, cx + shr cx, 2 + add cx, ax + mov offset2, cx + and bx, 3 ; column of right side + mov bl, ColumnMask[bx] + mov mask2n3, bx + + cmp diameter_even, 1 + jne @@MiddlePlotsOverlap + add si, di + add cx, di +@@MiddlePlotsOverlap: + mov offset7, si + mov offset3, cx + +; starting locations of 0, 1, 4, and 5 + mov bx, Left + add bx, shrunk_radius ; find horizontal midpoint + + mov ax, Top ; top in bytes + mul di + add ax, ScreenOffs + mov si, ax + + mov ax, Diameter ; bottom in bytes + dec ax + mul di + add ax, si + + mov di, bx ; horizontal midpoint in bytes + shr di, 2 + add si, di ; top midpoint in bytes + mov offset4, si + add di, ax ; bottom midpoint in bytes + mov offset5, di + and bx, 3 ; column of horizontal midpoint + mov bl, ColumnMask[bx] + mov mask4n5, bx + + cmp diameter_even, 1 + jne @@TopAndBottomPlotsOverlap + rol bl, 1 + jnc @@TopAndBottomPlotsOverlap + inc si + inc di +@@TopAndBottomPlotsOverlap: + mov offset0, si + mov offset1, di + mov mask0n1, bx + +; we've got our eight plots in their starting positions, so +; it's time to sort out the registers + mov bx, _ScrnLogicalByteWidth + + mov dx, SCREEN_SEG + mov es, dx + + mov dx, SC_INDEX ; set VGA to accept column masks + mov al, MAP_MASK + out dx, al + inc dx ; gun the engine... + + mov si, Diameter ; initial y is radius -- 2 #s per pixel + inc si + + mov cx, si + neg cx + add cx, 2 + mov error, cx ; error = -y + one pixel since we're a step ahead + + xor cx, cx ; initial x = 0 + mov ah, byte ptr Color + jmp @@FilledCircleCalc ; let's actually put something on the screen! + + +; plotting is completely different from in the other function (naturally) +@@PlotLines: + push cx ; we'll need cx for string stores + +; draw x-major horz. lines, from plot 4 to plot 0 and from plot 5 to plot 1 + mov di, mask0n1 + and di, 0000fh ; we only want the lower nybble for the mask table + mov al, RightMaskTable[di] + mov di, offset0 ; left and right offsets the same? + cmp di, offset4 + jne @@PlotXMajorNontrivial ; try and say this one 10 times fast! + mov di, mask4n5 + and di, 0000fh + and al, LeftMaskTable[di] ; intersection of left & right masks + out dx, al ; set mask + mov di, offset4 + mov es:[di], ah + mov di, offset5 + mov es:[di], ah + jmp @@PlotYMajor +@@PlotXMajorNontrivial: + out dx, al ; draw right edge + mov es:[di], ah + mov di, offset1 + mov es:[di], ah + + mov di, mask4n5 ; draw left edge + and di, 0000fh + mov al, LeftMaskTable[di] + out dx, al + mov di, offset4 + mov es:[di], ah + mov di, offset5 + mov es:[di], ah + + mov al, 0ffh ; set mask for middle chunks + out dx, al + mov al, ah ; ready to store two pixels at a time + inc di ; move string start past left edge + mov cx, offset1 ; store line from plot 5 to plot 1, exclusive + sub cx, di ; width of section in bytes + push cx + shr cx, 1 ; draw midsection eight pixels at a time + rep stosw + adc cx, 0 ; draw last four pixels, if such there are + rep stosb + + mov di, offset4 ; draw line from plot 4 to plot 0 + inc di ; move past left edge + pop cx + shr cx, 1 + rep stosw + adc cx, 0 + rep stosb + +@@PlotYMajor: +; draw y-major horz. lines, from plot 6 to plot 2 and from plot 7 to plot 3 + mov di, mask2n3 + and di, 0000fh ; we only want the lower nybble for the mask table + mov al, RightMaskTable[di] + mov di, offset2 ; left and right offsets the same? + cmp di, offset6 + jne @@PlotYMajorNontrivial ; try and say this one 10 times fast! + mov di, mask6n7 + and di, 0000fh + and al, LeftMaskTable[di] ; intersection of left & right masks + out dx, al ; set mask + mov di, offset6 + mov es:[di], ah + mov di, offset7 + mov es:[di], ah + jmp @@ClimaxOfPlot +@@PlotYMajorNontrivial: + out dx, al ; draw right edge + mov es:[di], ah + mov di, offset3 + mov es:[di], ah + + mov di, mask6n7 ; draw left edge + and di, 0000fh + mov al, LeftMaskTable[di] + out dx, al + mov di, offset6 + mov es:[di], ah + mov di, offset7 + mov es:[di], ah + + mov al, 0ffh ; set mask for middle chunks + out dx, al + mov al, ah ; ready to store two pixels at a time + + inc di ; move string start past left edge + mov cx, offset3 ; draw line from plot 7 to plot 3, exclusive + sub cx, di ; width of section in bytes + push cx + shr cx, 1 ; store midsection + rep stosw + adc cx, 0 + rep stosb + + mov di, offset6 ; draw line from plot 6 to plot 2 + inc di ; move past left edge + pop cx + shr cx, 1 + rep stosw + adc cx, 0 + rep stosb + +@@ClimaxOfPlot: + pop cx + jmp [jump_vector] ; either @@Advance or @@NoAdvance + + +; unlike their counterparts in the other function, these do not draw -- +; they only move the eight pointers + +; move the x-major plots horizontally and the y-major plots vertically +@@NoAdvance: + mov al, byte ptr mask0n1 ; advance left x-major plots + mov di, offset0 + rol al, 1 ; advance 0 right + mov byte ptr mask0n1, al + adc di, 0 + mov offset0, di + mov di, offset1 + ror al, 1 ; what was that bit again? + adc di, 0 ; advance 1 right + mov offset1, di + + mov al, byte ptr mask4n5 ; advance left x-major plots + mov di, offset4 + ror al, 1 + mov byte ptr mask4n5, al + sbb di, 0 + mov offset4, di + mov di, offset5 + rol al, 1 + sbb di, 0 + mov offset5, di + + mov al, byte ptr mask2n3 + mov di, offset2 + sub di, bx ; advance 2 up + mov offset2, di + mov di, offset3 + add di, bx ; advance 3 down + mov offset3, di + + mov al, byte ptr mask6n7 + mov di, offset6 + sub di, bx + mov offset6, di + mov di, offset7 + add di, bx + mov offset7, di + + jmp @@FilledCircleCalc + +; move all plots diagonally +@@Advance: + mov al, byte ptr mask0n1 + mov di, offset0 + rol al, 1 ; advance 0 right and down + mov byte ptr mask0n1, al + adc di, bx + mov offset0, di + mov di, offset1 + ror al, 1 ; what was that bit again? + adc di, 0 ; advance 1 right and up + sub di, bx + mov offset1, di + + mov al, byte ptr mask2n3 + mov di, offset2 + ror al, 1 ; advance 2 up and left + mov byte ptr mask2n3, al + sbb di, bx + mov offset2, di + mov di, offset3 + rol al, 1 + sbb di, 0 ; advance 3 down and left + add di, bx + mov offset3, di + + mov al, byte ptr mask4n5 + mov di, offset4 + ror al, 1 + mov byte ptr mask4n5, al + sbb di, 0 + add di, bx + mov offset4, di + mov di, offset5 + rol al, 1 + sbb di, bx + mov offset5, di + + mov al, byte ptr mask6n7 + mov di, offset6 + rol al, 1 + mov byte ptr mask6n7, al + adc di, 0 + sub di, bx + mov offset6, di + mov di, offset7 + ror al, 1 + adc di, bx + mov offset7, di + +; do you realize the entire function has been set up around this little jot? +; keep in mind that radii values are 2 per pixel +@@FilledCircleCalc: + add cx, 2 ; x += 1 + mov di, error + add di, cx ; error += (2 * x) + 1 + inc di + jl @@FilledCircleNoError + cmp cx, si ; x > y? + ja @@FleeFlyFlowFum + sub si, 2 ; y -= 1 + sub di, si ; error -= (2 * y) + mov error, di + mov jump_vector, offset @@Advance + jmp @@PlotLines +@@FilledCircleNoError: + mov error, di + mov jump_vector, offset @@NoAdvance + jmp @@PlotLines + +@@FleeFlyFlowFum: + pop di + pop si + mov sp,bp + pop bp + + ret + +_x_filled_circle endp + + end + diff --git a/16/xlib/xcircle.h b/16/xlib/xcircle.h new file mode 100755 index 00000000..1826377a --- /dev/null +++ b/16/xlib/xcircle.h @@ -0,0 +1,39 @@ +/*----------------------------------------------------------------------- +; +; XCIRCLE - header file +; +; This module was written by Matthew MacKenzie +; matm@eng.umd.edu +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +;----------------------------------------------------------------------*/ + +#ifndef _XCIRCLE_H_ +#define _XCIRCLE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + void x_circle (WORD Left, WORD Top, WORD Diameter, + WORD Color, WORD ScreenOffs); + + void x_filled_circle (WORD Left, WORD Top, WORD Diameter, + WORD Color, WORD ScreenOffs); + + +#ifdef __cplusplus +} +#endif + + +#endif + diff --git a/16/xlib/xcircle.inc b/16/xlib/xcircle.inc new file mode 100755 index 00000000..3b49d7c3 --- /dev/null +++ b/16/xlib/xcircle.inc @@ -0,0 +1,21 @@ +;----------------------------------------------------------------------- +; +; XCIRCLE - Include file +; +; This module was written by Matthew MacKenzie +; matm@eng.umd.edu +; +; XCIRCLE.ASM export functions +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + global _x_circle : proc + global _x_filled_circle : proc + + \ No newline at end of file diff --git a/16/xlib/xclippbm.asm b/16/xlib/xclippbm.asm new file mode 100755 index 00000000..bbe50b53 --- /dev/null +++ b/16/xlib/xclippbm.asm @@ -0,0 +1,507 @@ +;----------------------------------------------------------------------- +; MODULE XCLIPPBM +; +; This module was written by Matthew MacKenzie +; matm@eng.umd.edu +; +; Clipped transfer of planar bitmaps from system memory to video memory. +; +; Compile with TASM. +; C near-callable. +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + +include xlib.inc +include xclippbm.inc + + + .data + + align 2 + +; global clipping variables +_TopBound dw (?) +_BottomBound dw (?) +_LeftBound dw (?) +_RightBound dw (?) + +; VGA plane masks +ColumnMask db 011h,022h,044h,088h + +; bit delay timers +LeftDelay db 0, 1, 2, 4 +RightDelay db 0, 4, 2, 1 + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; _x_clip_pbm +; +; C near-callable as: +; +; void x_clip_pbm (int X, int Y, int ScreenOffs, char far * Bitmap); +; +; Bitmap is a planar bitmap, in the regular Xlib format. +; +; ax, bx, cx, and dx go south. + + .code + + public _x_clip_pbm + align 2 +_x_clip_pbm proc +ARG X:word, Y:word, ScreenOffs:word, Bitmap:dword +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 +; Tasm 1.0 does not allow the \ line continuation +;LOCAL left_counter:word, right_counter:word, \ +; column:word, clipped_height:word, clipped_width:word, \ +; screen_pos:word, bitmap_pos:word, bitmap_size:word, \ +; VGA_mask:word, width_copy, height_temp:word, \ +; screen_width:word=LocalStk + + push bp + mov bp, sp + sub sp, LocalStk + push si + push di + push ds + +; sociopathic cases: are the clipping bounds out of order? + mov ax, _TopBound + cmp ax, _BottomBound + jg @@GetOut + mov ax, _LeftBound + cmp ax, _RightBound + jle @@ReasonableAndProper +@@GetOut: ; return a 1 -- no image drawn + pop ds + pop di + pop si + mov ax, 1 + mov sp, bp + pop bp + ret + +@@ReasonableAndProper: + +; we need to use both the tables in ds and the height and width of the bitmap + les si, Bitmap + +; vertical position + xor cx, cx + mov cl, byte ptr es:[si + 1] ; height of bitmap + xor ax, ax + mov al, byte ptr es:[si] ; width of bitmap + mul cx + mov bitmap_size, ax + mov ax, Y + cmp ax, _BottomBound ; top edge below clipping box? + jg @@GetOut + + mov bx, cx + add bx, ax + dec bx ; bottom edge = Y + height - 1 + cmp bx, _TopBound + jl @@GetOut + sub bx, _BottomBound ; bottom margin = bottom edge - BottomBound + jle @@NoBottomBound + sub cx, bx ; clip bottom margin from height +@@NoBottomBound: + mov bx, _TopBound + sub bx, ax ; top margin = TopBound - Y + jle @@NoTopBound + add ax, bx ; top edge = Y + top margin + sub cx, bx ; clip top margin from height + jmp @@KeepMargin +@@NoTopBound: + xor bx, bx +@@KeepMargin: + mov clipped_height, cx + + mul _ScrnLogicalByteWidth + mov di, ax + add di, ScreenOffs ; row of upper-left corner of blit + + mov cl, byte ptr es:[si] ; width of bitmap (ch is still 0 from height) + mov ax, cx + mul bx + add si, ax + add si, 2 ; starting position in bitmap + +; horizontal position + mov width_copy, cx + mov dx, X + cmp dx, _RightBound + jg @@GetOut + mov dx, 0 ; unclipped value for right delay + + mov ax, cx + shl ax, 2 ; width in pixels + add ax, X + dec ax ; right edge = X + width in pixels - 1 + cmp ax, _LeftBound + jl @@GetOut + sub ax, _RightBound ; right margin = right edge - RightBound + jle @@NoRightBound + mov bx, ax + and bx, 3 + mov dl, RightDelay[bx] + shr ax, 2 + sub cx, ax ; subtract clipped bytes from width +@@NoRightBound: + mov right_counter, dx + mov dx, 0 ; unclipped value for left delay + mov ax, _LeftBound + sub ax, X ; left margin = LeftBound - X + jle @@NoLeftBound + mov bx, ax + and bx, 3 + mov dl, LeftDelay[bx] + add ax, 3 + shr ax, 2 ; left margin/4, rounded up + sub cx, ax ; subtract clipped bytes from width + add si, ax ; move starting position in bitmap past margin + add di, ax ; move starting position on screen past margin +@@NoLeftBound: + mov left_counter, dx + mov clipped_width, cx + + mov ax, X ; add x coordinate to screen position + mov bx, ax + sar ax, 2 + add di, ax + + mov dx, SC_INDEX + mov al, MAP_MASK + out dx, al + inc dx + + and bx, 3 ; initial mask + xor ax, ax + mov al, ColumnMask[bx] + mov VGA_mask, ax + out dx, al ; initial mask + + mov column, 4 + mov bitmap_pos, si + mov screen_pos, di + mov ax, _ScrnLogicalByteWidth + mov screen_width, ax ; since we move ds + +; we've used all our tables, so we can change ds to point to the bitmap, +; and es to point to the screen + mov ds, word ptr [Bitmap + 2] + mov ax, SCREEN_SEG + mov es, ax + + cld ; strings go forward + mov bx, width_copy + sub bx, clipped_width ; bytes to advance one line in bitmap + +; let's actually draw something for a change +@@WritePlane: + mov ax, clipped_height + mov height_temp, ax + mov dx, screen_width + sub dx, clipped_width ; bytes to advance one line across screen + +@@WriteLine: + mov cx, clipped_width + shr cx, 1 + rep movsw ; in they went, two by two... + adc cx, 0 + rep movsb ; catch stray last byte, if it's there + add si, bx ; advance one bitmap line + add di, dx ; advance one screen line + + dec height_temp + jnz @@WriteLine + + dec column + jz @@OuttaHere ; only four columns per customer, please + mov dx, SC_INDEX + 1 + rol byte ptr VGA_mask, 1 + adc screen_pos, 0 ; add to location if we've wrapped to plane 0 + mov al, byte ptr VGA_mask + out dx, al ; set VGA for next column + + shr right_counter, 1 + jnc @@NoRightCounter + dec clipped_width ; cut off right edge for later planes + inc bx +@@NoRightCounter: + shr left_counter, 1 + jnc @@NoLeftCounter + inc clipped_width ; add to left edge for later planes + dec bx + dec bitmap_pos + dec screen_pos +@@NoLeftCounter: + mov si, bitmap_pos + add si, bitmap_size + mov bitmap_pos, si + mov di, screen_pos + jmp @@WritePlane + +@@OuttaHere: ; return a 0 -- something was inside the boundary + pop ds + pop di + pop si + mov ax, 0 + mov sp, bp + pop bp + ret +_x_clip_pbm endp + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; _x_clip_masked_pbm +; +; C near-callable as: +; +; void x_clip_masked_pbm (int X, int Y, int ScreenOffs, char far * Bitmap); +; +; Bitmap is a planar bitmap, in the regular Xlib format. +; The width of the bitmap cannot be greater than 90 bytes, however. +; Ain't that just criminal? +; +; ax, bx, cx, and dx go south. + + +; one branch per pixel is more than enough -- we'll unroll the line-writing +; loop all the way to try to get a little speed (at the expense, as usual, +; of a chunk of memory) + +MaskedPoint macro offset + mov al, [si + offset] + or al, al + jz $+6 + mov es:[di + offset], al + endm + +MaskedPointSize equ 11 + + public _x_clip_masked_pbm + align 2 +_x_clip_masked_pbm proc +ARG X:word, Y:word, ScreenOffs:word, Bitmap:dword +; Tasm 1.0 does not allow the \ line continuation +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 +;LOCAL left_counter:word, right_counter:word, \ +; column:word, clipped_height:word, \ +; screen_pos:word, bitmap_pos:word, bitmap_size:word, \ +; VGA_mask:word, width_copy, height_temp:word, \ +; screen_width:word=LocalStk + push bp + mov bp, sp + sub sp, LocalStk + push si + push di + push ds + +; sociopathic cases: are the clipping bounds out of order? + mov ax, _TopBound + cmp ax, _BottomBound + jg @@GetOut + mov ax, _LeftBound + cmp ax, _RightBound + jle @@ReasonableAndProper +@@GetOut: ; return a 1 -- no image drawn + pop ds + pop di + pop si + mov ax, 1 + mov sp, bp + pop bp + ret + +@@ReasonableAndProper: + +; we need to use both the tables in ds and the height and width of the bitmap + les si, Bitmap + +; vertical position + xor cx, cx + mov cl, byte ptr es:[si + 1] ; height of bitmap + xor ax, ax + mov al, byte ptr es:[si] ; width of bitmap + mul cx + mov bitmap_size, ax + mov ax, Y + cmp ax, _BottomBound ; top edge below clipping box? + jg @@GetOut + + mov bx, cx + add bx, ax + dec bx ; bottom edge = Y + height - 1 + cmp bx, _TopBound + jl @@GetOut + sub bx, _BottomBound ; bottom margin = bottom edge - BottomBound + jle @@NoBottomBound + sub cx, bx ; clip bottom margin from height +@@NoBottomBound: + mov bx, _TopBound + sub bx, ax ; top margin = TopBound - Y + jle @@NoTopBound + add ax, bx ; top edge = Y + top margin + sub cx, bx ; clip top margin from height + jmp @@KeepMargin +@@NoTopBound: + xor bx, bx +@@KeepMargin: + mov clipped_height, cx + + mul _ScrnLogicalByteWidth + mov di, ax + add di, ScreenOffs ; row of upper-left corner of blit + + mov cl, byte ptr es:[si] ; width of bitmap (ch is still 0 from height) + mov ax, cx + mul bx + add si, ax + add si, 2 ; starting position in bitmap + +; horizontal position + mov width_copy, cx + mov dx, X + cmp dx, _RightBound + jg @@GetOut + mov dx, 0 ; unclipped value for right delay + + mov ax, cx + shl ax, 2 ; width in pixels + add ax, X + dec ax ; right edge = X + width in pixels - 1 + cmp ax, _LeftBound + jl @@GetOut + sub ax, _RightBound ; right margin = right edge - RightBound + jle @@NoRightBound + mov bx, ax + and bx, 3 + mov dl, RightDelay[bx] + shr ax, 2 + sub cx, ax ; subtract clipped bytes from width +@@NoRightBound: + mov right_counter, dx + mov dx, 0 ; unclipped value for left delay + mov ax, _LeftBound + sub ax, X ; left margin = LeftBound - X + jle @@NoLeftBound + mov bx, ax + and bx, 3 + mov dl, LeftDelay[bx] + add ax, 3 + shr ax, 2 ; left margin/4, rounded up + sub cx, ax ; subtract clipped bytes from width + add si, ax ; move starting position in bitmap past margin + add di, ax ; move starting position on screen past margin +@@NoLeftBound: + mov left_counter, dx + mov ax, cx + imul ax, (-1 * MaskedPointSize) + add ax, offset @@LineDone + 2 + mov cx, ax ; jump offset for plotting + + mov ax, X ; add x coordinate to screen position + mov bx, ax + shr ax, 2 + add di, ax + + mov dx, SC_INDEX + mov al, MAP_MASK + out dx, al + inc dx + + and bx, 3 ; initial mask + xor ax, ax + mov al, ColumnMask[bx] + mov VGA_mask, ax + out dx, al + + mov column, 4 + mov bitmap_pos, si + mov screen_pos, di + mov ax, _ScrnLogicalByteWidth + mov screen_width, ax ; since we move ds + +; we've used all our tables, so we can change ds to point to the bitmap, +; and es to point to the screen + mov ds, word ptr [Bitmap + 2] + mov ax, SCREEN_SEG + mov es, ax + + mov bx, width_copy + +; let's actually draw something for a change + mov ax, clipped_height + mov height_temp, ax + mov dx, screen_width + jmp cx + +; 90 bottles of beer on the wall... + PointLoop = 89 + rept 89 + MaskedPoint PointLoop + PointLoop = PointLoop - 1 + endm +; one bottle of beer... + +; final point needs a different branch offset, so we don't use MaskedPoint + mov al, [si] + or al, al + jz @@LineDone + mov es:[di], al + +@@LineDone: + add si, bx ; advance one bitmap line + add di, dx ; advance one screen line + dec height_temp + jz @@PlaneDone + jmp cx + +@@PlaneDone: + dec column + jz @@OuttaHere ; only four columns per customer, please + mov dx, SC_INDEX + 1 + rol byte ptr VGA_mask, 1 + adc screen_pos, 0 ; move to new column if we've wrapped to plane 0 + mov al, byte ptr VGA_mask + out dx, al ; set VGA for next column + + shr right_counter, 1 + jnc @@NoRightCounter + add cx, MaskedPointSize ; cut off right edge for later planes +@@NoRightCounter: + shr left_counter, 1 + jnc @@NoLeftCounter + sub cx, MaskedPointSize ; add to left edge for later planes + dec bitmap_pos + dec screen_pos +@@NoLeftCounter: + mov si, bitmap_pos + add si, bitmap_size + mov bitmap_pos, si + mov di, screen_pos + + mov ax, clipped_height + mov height_temp, ax + mov dx, screen_width + jmp cx + +@@OuttaHere: ; return a 0 -- something was inside the boundary + pop ds + pop di + pop si + mov ax, 0 + mov sp, bp + pop bp + ret +_x_clip_masked_pbm endp + + end + diff --git a/16/xlib/xclippbm.h b/16/xlib/xclippbm.h new file mode 100755 index 00000000..c66b433c --- /dev/null +++ b/16/xlib/xclippbm.h @@ -0,0 +1,56 @@ +/*----------------------------------------------------------------------- +; MODULE XCLIPPBM +; +; This module was written by Matthew MacKenzie +; matm@eng.umd.edu +; +; Clipped transfer of planar bitmaps from system memory to video memory. +; +; Compile with TASM. +; C near-callable. +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;----------------------------------------------------------------------*/ + +#ifndef _XCLIPPBM_H_ +#define _XCLIPPBM_H_ + +/* unlike most global variables in Xlib, these are meant to be written to; + in fact they start off uninitialized -- all values are in pixels */ +extern int TopBound; +extern int BottomBound; +extern int LeftBound; +extern int RightBound; + +#ifdef __cplusplus +extern "C" { +#endif + + +/* for both functions, a return value of 1 indicates that the entire +bitmap was outside the bounding box, while a value of 0 means that +something may have ended up on the screen */ + +/* copies a planar bitmap from SRAM to VRAM, with clipping */ + + int x_clip_pbm (int X, int Y, int ScreenOffs, char far * Bitmap); + +/* copies a planar bitmap from SRAM to VRAM, with clipping -- 0 bytes + in the bitmap are not copied */ + + int x_clip_masked_pbm (int X, int Y, int ScreenOffs, char far * Bitmap); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/16/xlib/xclippbm.inc b/16/xlib/xclippbm.inc new file mode 100755 index 00000000..f9d75864 --- /dev/null +++ b/16/xlib/xclippbm.inc @@ -0,0 +1,26 @@ +;----------------------------------------------------------------------- +; +; XPBITMAP - Include file +; +; This module was written by Matthew MacKenzie +; matm@eng.umd.edu +; +; XPBITMAP.ASM export functions +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + global _x_clip_masked_pbm :proc + global _x_clip_pbm :proc + + global _LeftBound :word + global _RightBound :word + global _TopBound :word + global _BottomBound :word + + \ No newline at end of file diff --git a/16/xlib/xcomppbm.asm b/16/xlib/xcomppbm.asm new file mode 100755 index 00000000..b3ff621c --- /dev/null +++ b/16/xlib/xcomppbm.asm @@ -0,0 +1,322 @@ +;----------------------------------------------------------------------- +; module XCOMPPBM +; +; This module contains only the compiler and sizeof routines -- +; use the plotter from XCBITMAP. +; +;----------------------------------------------------------------------- + +include xlib.inc +include xcomppbm.inc + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; _x_compile_pbm +; +; I only changed five instructions, instead of rewriting this +; for PBMs. So it is amazingly inefficient. But, what the hell, +; It's only a game :). +; + +; accessory macros to save typing (what else?) +Emitb macro arg + mov byte ptr es:[di],&arg& + inc di + endm + +Emitw macro arg + mov word ptr es:[di],&arg& + add di,2 + endm + +; opcodes emitted by _x_compile_pbm +ROL_AL equ 0c0d0h ; rol al +SHORT_STORE_8 equ 044c6h ; mov [si]+disp8, imm8 +STORE_8 equ 084c6h ; mov [si]+disp16, imm8 +SHORT_STORE_16 equ 044c7h ; mov [si]+disp8, imm16 +STORE_16 equ 084c7h ; mov [si]+disp16, imm16 +ADC_SI_IMMED equ 0d683h ; adc si,imm8 +OUT_AL equ 0eeh ; out dx,al +RETURN equ 0cbh ; ret + + +.data + +align 2 +ColumnMask db 011h,022h,044h,088h + + +.code + + align 2 +_x_compile_pbm proc +ARG logical_width:word,bitmap:dword,output:dword +LOCAL bwidth,scanx,scany,outputx,outputy,column,set_column,input_size:word=LocalStk + push bp + mov bp, sp ; caller's stack frame + sub sp,LocalStk ; local space + push si + push di + push ds + + mov word ptr [scanx],0 + mov word ptr [scany],0 + mov word ptr [outputx],0 + mov word ptr [outputy],0 + mov word ptr [column],0 + mov word ptr [set_column],0 + + lds si,[bitmap] ; 32-bit pointer to source bitmap + + les di,[output] ; 32-bit pointer to destination stream + + lodsb ; load width byte + xor ah, ah ; convert to word + mov [bwidth], ax ; save for future reference + mov bl, al ; copy width byte to bl + lodsb ; load height byte -- already a word since ah=0 + mul bl ; mult height word by width byte + mov [input_size], ax; to get pixel total + +@@MainLoop: + mov bx, [scanx] ; position in original bitmap + add bx, [scany] + + mov al, [si+bx] ; get pixel + or al, al ; skip empty pixels + jnz @@NoAdvance + jmp @@Advance +@@NoAdvance: + + mov dx, [set_column] + cmp dx, [column] + je @@SameColumn +@@ColumnLoop: + Emitw ROL_AL ; emit code to move to new column + Emitw ADC_SI_IMMED + Emitb 0 + + inc dx + cmp dx, [column] + jl @@ColumnLoop + + Emitb OUT_AL ; emit code to set VGA mask for new column + mov [set_column], dx +@@SameColumn: + mov dx, [outputy] ; calculate output position + add dx, [outputx] + sub dx, 128 + + inc word ptr [scanx] + mov cx, [scanx] ; within four pixels of right edge? + cmp cx, [bwidth] + jge @@OnePixel + + inc word ptr [outputx] + mov ah, [si+bx+1] ; get second pixel + or ah, ah + jnz @@TwoPixels +@@OnePixel: + cmp dx, 127 ; can we use shorter form? + jg @@OnePixLarge + cmp dx, -128 + jl @@OnePixLarge + Emitw SHORT_STORE_8 + Emitb dl ; 8-bit position in output + jmp @@EmitOnePixel +@@OnePixLarge: + Emitw STORE_8 + Emitw dx ; position in output +@@EmitOnePixel: + Emitb al + jmp short @@Advance +@@TwoPixels: + cmp dx, 127 + jg @@TwoPixLarge + cmp dx, -128 + jl @@TwoPixLarge + Emitw SHORT_STORE_16 + Emitb dl ; 8-bit position in output + jmp @@EmitTwoPixels +@@TwoPixLarge: + Emitw STORE_16 + Emitw dx ; position in output +@@EmitTwoPixels: + Emitw ax + +@@Advance: + inc word ptr [outputx] + mov ax, [scanx] + inc ax + cmp ax, [bwidth] + jl @@AdvanceDone + mov dx, [outputy] + add dx, [logical_width] + mov cx, [scany] + add cx, [bwidth] + cmp cx, [input_size] + jl @@NoNewColumn + inc word ptr [column] + mov cx, [column] + cmp cx, 4 + je @@Exit ; Column 4: there is no column 4. + xor cx, cx ; scany and outputy are 0 again for + mov dx, cx ; the new column + add si, [input_size] +@@NoNewColumn: + mov [outputy], dx + mov [scany], cx + xor ax, ax + mov word ptr [outputx], 0 +@@AdvanceDone: + mov [scanx], ax + jmp @@MainLoop + +@@Exit: + Emitb RETURN + mov ax,di + sub ax,word ptr [output] ; size of generated code + + pop ds + pop di + pop si + mov sp, bp + pop bp + + ret +_x_compile_pbm endp + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; _x_sizeof_cpbm +; + + + align 2 +_x_sizeof_cpbm proc +ARG logical_width:word,bitmap:dword +LOCAL bwidth,scanx,scany,outputx,outputy,column,set_column,input_size:word=LocalStk + push bp + mov bp, sp ; caller's stack frame + sub sp,LocalStk ; local space + push si + push di + push ds + + mov word ptr [scanx], 0 + mov word ptr [scany], 0 + mov word ptr [outputx], 0 + mov word ptr [outputy], 0 + mov word ptr [column], 0 + mov word ptr [set_column], 0 + + lds si,[bitmap] ; 32-bit pointer to source bitmap + + mov di, 1 ; initial size is just the size of the far RET + + lodsb ; load width byte + xor ah, ah ; convert to word + mov [bwidth], ax ; save for future reference + mov bl, al ; copy width byte to bl + lodsb ; load height byte -- already a word since ah=0 + mul bl ; mult height word by width byte + mov [input_size], ax; to get pixel total + +@@MainLoop: + mov bx, [scanx] ; position in original bitmap + add bx, [scany] + + mov al, [si+bx] ; get pixel + or al, al ; skip empty pixels + jnz @@NoAdvance + jmp @@Advance +@@NoAdvance: + + mov dx, [set_column] + cmp dx, [column] + je @@SameColumn +@@ColumnLoop: + add di, 5 ; size of code to move to new column + inc dx + cmp dx,[column] + jl @@ColumnLoop + + inc di ; size of code to set VGA mask + mov [set_column], dx +@@SameColumn: + mov dx, [outputy] ; calculate output position + add dx, [outputx] + sub dx, 128 + + inc word ptr [scanx] + mov cx, [scanx] ; within four pixels of right edge? + cmp cx, [bwidth] + jge @@OnePixel + + inc word ptr [outputx] + mov ah,[si+bx+1] ; get second pixel + or ah, ah + jnz @@TwoPixels +@@OnePixel: + cmp dx, 127 ; can we use shorter form? + jg @@OnePixLarge + cmp dx, -128 + jl @@OnePixLarge + add di, 4 ; size of 8-bit position in output plus one pixel + jmp @@EmitOnePixel +@@OnePixLarge: + add di, 5 ; size of position in output plus one pixels +@@EmitOnePixel: + jmp short @@Advance +@@TwoPixels: + cmp dx, 127 + jg @@TwoPixLarge + cmp dx, -128 + jl @@TwoPixLarge + add di, 5 ; size of 8-bit position in output plus two pixels + jmp @@EmitTwoPixels +@@TwoPixLarge: + add di, 6 ; size of 16-bit position in output plus two pixels +@@EmitTwoPixels: + +@@Advance: + inc word ptr [outputx] + mov ax, [scanx] + inc ax + cmp ax, [bwidth] + jl @@AdvanceDone + mov dx, [outputy] + add dx, [logical_width] + mov cx, [scany] + add cx, [bwidth] + cmp cx, [input_size] + jl @@NoNewColumn + inc word ptr [column] + mov cx, [column] + cmp cx, 4 + je @@Exit ; Column 4: there is no column 4. + xor cx,cx ; scany and outputy are 0 again for + mov dx,cx ; the new column + add si, [input_size] +@@NoNewColumn: + mov [outputy], dx + mov [scany], cx + xor ax, ax + mov word ptr [outputx], ax +@@AdvanceDone: + mov [scanx], ax + jmp @@MainLoop + +@@Exit: + mov ax, di ; size of generated code + + pop ds + pop di + pop si + mov sp,bp + pop bp + + ret +_x_sizeof_cpbm endp + +end + diff --git a/16/xlib/xcomppbm.h b/16/xlib/xcomppbm.h new file mode 100755 index 00000000..11db9aad --- /dev/null +++ b/16/xlib/xcomppbm.h @@ -0,0 +1,23 @@ +#ifndef _XCOMPPBM_H_ +#define _XCOMPPBM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + int x_compile_pbm ( /* Compile a planar bitmap to generate */ + WORD logical_screen_width, /* machine code to plot it at any */ + char far * bitmap, /* required screen coordinates FAST. */ + char far * output); + + int x_sizeof_cpbm ( /* Find the size of the code which a */ + WORD logical_screen_width, /* pbm would result in, if it */ + char far * bitmap); /* were compiled (used for allocation). */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/16/xlib/xcomppbm.inc b/16/xlib/xcomppbm.inc new file mode 100755 index 00000000..f2602059 --- /dev/null +++ b/16/xlib/xcomppbm.inc @@ -0,0 +1,2 @@ +global _x_compile_pbm : proc +global _x_sizeof_cpbm : proc diff --git a/16/xlib/xdetect.asm b/16/xlib/xdetect.asm new file mode 100755 index 00000000..4b921682 --- /dev/null +++ b/16/xlib/xdetect.asm @@ -0,0 +1,269 @@ +;----------------------------------------------------------------------- +; MODULE XDETECT +; +; Hardware detection module +; +; Compile with Tasm. +; C callable. +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- +LOCALS +.286 + +include model.inc +include xdetect.inc + + .data + +_MouseButtonCount dw 0 +_MouseVersion dw 0 +_MouseType db 0 +_MouseIRQ db 0 + + .code + + +i86 equ 0 +i186 equ 1 +i286 equ 2 +i386sx equ 3 +i386dx equ 4 +i486 equ 5 + + +NONE equ 0 +MDA equ 1 +CGA equ 2 +EGAMono equ 3 +EGAColor equ 4 +VGAMono equ 5 +VGAColor equ 6 +MCGAMono equ 7 +MCGAColor equ 8 + +PS2_CARDS db 0,1,2,2,4,3,2,5,6,2,8,7,8 + + +;----------------------------------------------------------------------- +; PC Graphics detection routine. Returns graphics card type +; +; C callable as: +; unsigned int x_graphics_card(); +; +; + +proc _x_graphics_card + push bp ; Preserve caller's stack frame + mov bp,sp + mov ax,1A00h ; Try calling VGA Identity Adapter function + int 10h + cmp al,1Ah ; Do we have PS/2 video bios ? + jne @@not_PS2 ; No! + + cmp bl,0Ch ; bl > 0Ch => CGA hardware + jg @@is_CGA ; Jump if we have CGA + xor bh,bh + xor ah,ah + mov al,cs:PS2_CARDS[bx] ; Load ax from PS/2 hardware table + jmp short @@done ; return ax +@@is_CGA: + mov ax,CGA ; Have detected CGA, return id + jmp short @@done +@@not_PS2: ; OK We don't have PS/2 Video bios + mov ah,12h ; Set alternate function service + mov bx,10h ; Set to return EGA information + int 10h ; call video service + cmp bx,10h ; Is EGA there ? + je @@simple_adapter ; Nop! + mov ah,12h ; Since we have EGA bios, get details + mov bl,10h + int 10h + or bh,bh ; Do we have colour EGA ? + jz @@ega_color ; Yes + mov ax,EGAMono ; Otherwise we have Mono EGA + jmp short @@done +@@ega_color: + mov ax,EGAColor ; Have detected EGA Color, return id + jmp short @@done +@@simple_adapter: + int 11h ; Lets try equipment determination service + and al,30h + shr al,4 + xor ah,ah + or al,al ; Do we have any graphics card at all ? + jz @@done ; No ? This is a stupid machine! + cmp al,3 ; Do We have a Mono adapter + jne @@is_CGA ; No + mov ax,MDA ; Have detected MDA, return id +@@done: + pop bp ;restore caller's stack frame + ret +_x_graphics_card endp + + +;----------------------------------------------------------------------- +; PC Processor detection routine +; +; C callable as: +; unsigned int x_processor(); +; +; +proc _x_processor + push bp + mov bp,sp + pushf ; Save flags + xor ax,ax ; Clear AX + push ax ; Push it on the stack + popf ; Zero the flags + pushf ; Try to zero bits 12-15 + pop ax ; Recover flags + and ax,0F000h ; If bits 12-15 are 1 => i86 or i286 + cmp ax,0F000h + jne @@1 + + push cx ; save CX + mov ax,0FFFFh ; Set all AX bits + mov cl,33 ; Will shift once on 80186 + shl ax,cl ; or 33 x on 8086 + pop cx + mov ax,i186 + jnz @@done + mov ax,i86 ; 0 => 8086/8088 + jmp short @@done + +@@1: + mov ax,07000h ; Try to set bits 12-14 + push ax + popf + pushf + pop ax + and ax,07000h ; If bits 12-14 are 0 => i286 + mov ax,i286 + jz @@done + + ;; 386/486 resolution code taken from WHATCPU.ASM by + ;; Dave M. Walker + + + P386 + mov eax,cr0 + mov ebx,eax ;Original CR0 into EBX + or al,10h ;Set bit + mov cr0,eax ;Store it + mov eax,cr0 ;Read it back + mov cr0,ebx ;Restore CR0 + test al,10h ;Did it set? + mov ax,i386sx + jz @@done ;Jump if 386SX + + ;*** Test AC bit in EFLAGS (386DX won't change) + mov ecx,esp ;Original ESP in ECX + pushfd ;Original EFLAGS in EBX + pop ebx + and esp,not 3 ;Align stack to prevent 486 + ; fault when AC is flipped + mov eax,ebx ;EFLAGS => EAX + xor eax,40000h ;Flip AC flag + push eax ;Store it + popfd + pushfd ;Read it back + pop eax + push ebx ;Restore EFLAGS + popfd + mov esp,ecx ;Restore ESP + cmp eax,ebx ;Compare old/new AC bits + mov ax,i386dx + je @@done +is_486: ;Until the Pentium appears... + mov ax,i486 +@@done: + popf + .286 + pop bp + ret +_x_processor endp + +.8086 +;----------------------------------------------------------------------- +; PC Numeric coprocessor detection routine +; +; C callable as: +; unsigned int x_coprocessor(); +; +; Based on an article in PC Tech Journal, Aug 87 by Ted Forgeron +; +; Returns 1 if coprocessor found, zero otherwise + +_x_coprocessor proc +ARG control:word=StkSize + push bp + mov bp,sp + sub sp,StkSize + + fninit ; try to initialize the copro. + mov [control],0 ; clear control word variable + fnstcw control ; put control word in memory + mov ax,[control] ; + cmp ah,03h ; do we have a coprocessor ? + je @@HaveCopro ; jump if yes! + xor ax,ax ; return 0 since nothing found + jmp short @@done +@@HaveCopro: + mov ax,1 +@@done: + mov sp,bp + pop bp + ret +_x_coprocessor endp + + +;----------------------------------------------------------------------- +; PC Mouse Driver detection routine +; +; C callable as: +; unsigned int x_mousedriver(); +; +; +; Returns 1 if mouse driver found, zero otherwise +_x_mousedriver proc + push bp + mov bp,sp + mov ax,3533h ; Get int 33 interrupt vector + int 21h ; Call dos + xor cx,cx ; Clear "found" flag + mov ax,es ; Is the vector null (ES==0 && BX==0) ? + or bx,ax + jz @@NoMouseDriver ; Yes! No mouse driver installed - Jump + + ; Just make absolutely sure the vector points to the mouse + ; driver (just in case) + + xor ax,ax ; FUNC 0: Mouse Initialization + int 33h + or ax,ax ; Do we have an installed mouse driver ? + jz @@NoMouseDriver; No ? + mov [_MouseButtonCount],bx + + mov ax,24h + int 33h + mov [_MouseVersion],bx + mov [_MouseType],ch + mov [_MouseIRQ],cl + + mov cx,1 ; Yes! set flag + +@@NoMouseDriver: + mov ax,cx ; Return "found" flag + pop bp + ret +_x_mousedriver endp + + +end \ No newline at end of file diff --git a/16/xlib/xdetect.h b/16/xlib/xdetect.h new file mode 100755 index 00000000..2687a180 --- /dev/null +++ b/16/xlib/xdetect.h @@ -0,0 +1,71 @@ +/*----------------------------------------------------------------------- +; +; XDETECT - header file +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;-----------------------------------------------------------------------*/ + +#ifndef _XDETECT_H_ +#define _XDETECT_H_ + +#define I8086 0 +#define I80186 1 +#define I80286 2 +#define I80386SX 3 +#define I80386DX 4 +#define I80486 5 + +#define NoGraphics 0 +#define MDA 1 +#define CGA 2 +#define EGAMono 3 +#define EGAColor 4 +#define VGAMono 5 +#define VGAColor 6 +#define MCGAMono 7 +#define MCGAColor 8 + +#define BUS_MOUSE 1 +#define SERIAL_MOUSE 2 +#define INPORT_MOUSE 3 +#define PS2_MOUSE 4 +#define HP_MOUSE 5 + +/* VARIABLES =========================================================== */ + +extern WORD MouseButtonCount; /* number of mouse buttons */ +extern WORD MouseVersion; /* mouse driver version */ +extern WORD MouseType; /* mouse type */ +extern WORD MouseIRQ; /* mouse IRQ number */ + +/* FUNCTIONS =========================================================== */ + +#ifdef __cplusplus +extern "C" { +#endif + + int x_graphics_card(void); /* Detect installed Graphics card type */ + int x_processor(void); /* Detect processor type */ + int x_coprocessor(void); /* Detect math co-processor type */ + int x_mousedriver(void); /* Detect math co-processor type */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/16/xlib/xdetect.inc b/16/xlib/xdetect.inc new file mode 100755 index 00000000..8c0a72ae --- /dev/null +++ b/16/xlib/xdetect.inc @@ -0,0 +1,26 @@ +;----------------------------------------------------------------------- +; +; XDETECT - Include file +; +; XDETECT.ASM export functions +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + global _MouseButtonCount :word + global _MouseVersion :word + global _MouseType :byte + global _MouseIRQ :byte + + + global _x_graphics_card :proc + global _x_processor :proc + global _x_coprocessor :proc + global _x_mousedriver :proc + diff --git a/16/xlib/xfileio.asm b/16/xlib/xfileio.asm new file mode 100755 index 00000000..08546127 --- /dev/null +++ b/16/xlib/xfileio.asm @@ -0,0 +1,433 @@ +;----------------------------------------------------------------------- +; MODULE XFILEIO +; +; Sequential binary file I/O functions +; +; Some functions based on a r.g.p post by Joshua Jensen +; +; Compile with Tasm. +; C callable. +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- +COMMENT $ + + +$ + +LOCALS +.286 + +include model.inc +include xfileio.inc + .data + + _file_err dw (?) ; error value + + .code + +PUSH_DS macro + IFNDEF s + push ds + ENDIF + endm + +POP_DS macro + IFNDEF s + pop ds + ENDIF + endm + +LDS_M macro arg1,arg2 + IFNDEF s + lds &arg1&,&arg2& + ELSE + mov &arg1&,word ptr &arg2& + ENDIF + endm + + + +;**************************************************************** +; +; name: f_open +; +; C Prototype: +; +; extern int f_open(char * filename, char access) +; +; Opens a file according to the access char: +; +; 0 = read only - If doesnt exist return error +; 1 = write only - If doesnt exist create it otherwise clear it +; 2 = read/write - If doesnt exist create it +; +; Returns the file handle on success, -1 on failure +; +; +proc _f_open +IFNDEF s + ARG filename:dword,access:byte +ELSE + ARG filename:word,access:byte +ENDIF + push bp ; Preserve caller's stack frame + mov bp,sp + PUSH_DS + LDS_M dx,[filename] ; point DS:DX to file name string + mov [_file_err],0 + cmp [access],1 + je @@creat + + mov ah,3dh ; select "open file" DOS service + mov al,[access] ; select access type code + int 21h ; call DOS service + jnb @@Done ; If carry flag set we have failed + + + cmp [access],2 + jne @@error +@@creat: + mov ah,3ch ; select "creat file" DOS service + mov cx,0 + int 21h ; call DOS service + jnb @@Done ; If carry flag set we have failed +@@error: + mov [_file_err],ax + mov ax,-1 ; indicate failure +@@Done: ; otherwise return file handle + POP_DS + pop bp ;restore caller's stack frame + ret +_f_open endp + + +;**************************************************************** +; +; name: f_close +; +; C Prototype: +; +; extern int f_close(int handle) +; +; Closes the file associated with the specified handle +; +; Returns 0 on success, -1 on failure +; +proc _f_close +ARG handle:word + push bp ; Preserve caller's stack frame + mov bp,sp + + mov [_file_err],0 ; Clear error + mov ah,3eh ; select "close file handle" DOS service + mov bx,[handle] ; select handle of file to close + int 21h ; call DOS service + jnb @@Fix ; failed if carry flag set + mov [_file_err],ax; + mov ax,-1 ; return error + jmp short @@Done +@@Fix: ; otherwise + xor ax,ax ; return 0 +@@Done: + pop bp ;restore caller's stack frame + ret +_f_close endp + + +;**************************************************************** +; +; name: f_read +; +; C Prototype: +; +; extern int f_read(int handle, char *buffer, int count) +; +; Reads a block of count bytes from the file specified by the handle +; into the buffer +; +; Returns count on success, failure is detectable via _file_err +; +proc _f_read +IFNDEF s + ARG handle:word,buffer:dword,count:word +ELSE + ARG handle:word,buffer:word,count:word +ENDIF + push bp ; Preserve caller's stack frame + mov bp,sp + PUSH_DS + + mov [_file_err],0 ; Clear error + mov ah,3fh ; select "read from file or device" DOS service + mov bx,[handle] ; select handle of file to close + mov cx,[count] + LDS_M dx,[buffer] + int 21h ; call DOS service + jnb @@Done ; failed if carry flag set + mov [_file_err],ax + xor ax,ax ; return error + jmp short @@Done +@@Done: + POP_DS + pop bp ;restore caller's stack frame + ret +_f_read endp + +;**************************************************************** +; +; name: f_write +; +; C Prototype: +; +; extern int f_write(int handle, char *buffer, int count) +; +; Writes a block of count bytes to the file specified by the handle +; from the buffer +; +; Returns count on success, error is indicated by _file_err iff count = 0 +; +proc _f_write +IFNDEF s + ARG handle:word,buffer:dword,count:word +ELSE + ARG handle:word,buffer:word,count:word +ENDIF + push bp ; Preserve caller's stack frame + mov bp,sp + PUSH_DS + + mov [_file_err],0 ; Clear error + mov ah,40h ; select "write to file or device" DOS service + mov bx,[handle] ; select handle of file to write + mov cx,[count] + LDS_M dx,[buffer] + int 21h ; call DOS service + jnb @@Done ; has the function failed ? + mov [_file_err],ax + xor ax,ax ; yes, return error + jmp short @@Done +@@Done: ; otherwise return bytes written + POP_DS + pop bp ; restore caller's stack frame + ret +_f_write endp + +;**************************************************************** +; +; name: f_readfar +; +; C Prototype: +; +; extern int f_readfar(int handle, char far * buffer, int count) +; +; Reads a block of count bytes from the file specified by the handle +; into the buffer +; +; Returns count on success, failure is detectable via _file_err +; +proc _f_readfar +ARG handle:word,buffer:dword,count:word + push bp ; Preserve caller's stack frame + mov bp,sp + push ds + + mov [_file_err],0 ; Clear error + mov ah,3fh ; select "read from file or device" DOS service + mov bx,[handle] ; select handle of file to close + mov cx,[count] + lds dx,[buffer] + int 21h ; call DOS service + jnb @@Done ; failed if carry flag set + mov [_file_err],ax + xor ax,ax ; return error + jmp short @@Done +@@Done: + pop ds + pop bp ;restore caller's stack frame + ret +_f_readfar endp + +;**************************************************************** +; +; name: f_writefar +; +; C Prototype: +; +; extern int f_writefar(int handle, char far * buffer, int count) +; +; Writes a block of count bytes to the file specified by the handle +; from the buffer +; +; Returns count on success, error is indicated by _file_err iff count = 0 +; +proc _f_writefar +ARG handle:word,buffer:dword,count:word + push bp ; Preserve caller's stack frame + mov bp,sp + push ds + + mov [_file_err],0 ; Clear error + mov ah,40h ; select "write to file or device" DOS service + mov bx,[handle] ; select handle of file to write + mov cx,[count] + lds dx,[buffer] + int 21h ; call DOS service + jnb @@Done ; has the function failed ? + mov [_file_err],ax + xor ax,ax ; yes, return error + jmp short @@Done +@@Done: ; otherwise return bytes written + pop ds + pop bp ; restore caller's stack frame + ret +_f_writefar endp + + + +;**************************************************************** +; +; name: f_seek +; +; C Prototype: +; +; extern long int f_seek(int handle, long int position, char method_code) +; +; Moves the file pointer according to the position and method code +; +; Returns file pointer position on success, -1 on failure +; +proc _f_seek +ARG handle:word,position:dword,method_code:byte + push bp ; Preserve caller's stack frame + mov bp,sp + + mov [_file_err],0 ; Clear error + mov ah,42h ; select "move file pointer" DOS service + mov bx,[handle] ; select handle of file to close + mov al,[method_code] + mov cx,word ptr [position+2] + mov dx,word ptr [position] + int 21h ; call DOS service + jnb @@Done ; has the function failed ? + mov [_file_err],ax + mov ax,-1 ; yes, return error + mov dx,-1 ; + jmp short @@Done +@@Done: ; otherwise return bytes written + pop bp ; restore caller's stack frame + ret +_f_seek endp + +;**************************************************************** +; +; name: f_tell +; +; C Prototype: +; +; extern long int f_tell(int handle) +; +; Returns file pointer position on success, -1 on failure +; +proc _f_tell +ARG handle:word,position:dword,method_code:byte + push bp ; Preserve caller's stack frame + mov bp,sp + + mov [_file_err],0 ; Clear error + mov ah,42h ; select "move file pointer" DOS service + mov bx,[handle] ; select handle of file to close + xor dx,dx + mov cx,dx + int 21h + jnb @@Done + mov [_file_err],ax + mov ax,-1 ; yes, return error + mov dx,-1 ; + jmp short @@Done +@@Done: ; otherwise return bytes written + pop bp ; restore caller's stack frame + ret +_f_tell endp + + +;**************************************************************** +; +; name: f_filelength +; +; C Prototype: +; +; extern long int f_filelength(int handle) +; +; Returns the length of the file associated with the specified handle +; +; Returns file length on success, -1 on failure +; +proc _f_filelength +ARG handle:word +LOCAL low:word,high:word=LocalStk + push bp ; Preserve caller's stack frame + mov bp,sp + sub sp,LocalStk + + mov [_file_err],0 ; Clear error + + ; Get ptr's current location in file and save it + + mov ah,42h ; select "move file pointer" DOS service + mov al,1 ; select "from current location" method + mov bx,[handle] ; select handle of file to close + xor cx,cx + xor dx,dx + int 21h + jb @@Error + mov [low],ax + mov [high],dx + + ; Get ptr's value at end of file + + mov ah,42h ; select "move file pointer" DOS service + mov al,2 ; select "from end of file" method + mov bx,[handle] ; select handle of file to close + xor cx,cx + xor dx,dx + int 21h + jb @@Error + + ; Save the results while returning pointer to its previous location + + push ax + push dx + + mov ah,42h ; select "move file pointer" DOS service + mov al,0 ; select "from start of file" method + mov bx,[handle] ; select handle of file to close + mov cx,[high] + mov dx,[low] + int 21h + + ; restore resultant length + + pop dx + pop ax + + jnb @@Done ; Was the operation a success ? +@@Error: + mov [_file_err],ax + mov ax,-1 ; no, return error + mov dx,-1 ; +@@Done: ; otherwise return bytes written + mov sp,bp + pop bp ; restore caller's stack frame + ret +_f_filelength endp + + + end + diff --git a/16/xlib/xfileio.h b/16/xlib/xfileio.h new file mode 100755 index 00000000..9b98fb0e --- /dev/null +++ b/16/xlib/xfileio.h @@ -0,0 +1,96 @@ +/*----------------------------------------------------------------------- +; +; XFILEIO - header file +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;-----------------------------------------------------------------------*/ + +#ifndef _XFILEIO_H_ +#define _XFILEIO_H_ + +#define F_RDONLY 0 +#define F_WRONLY 1 +#define F_RDWR 2 + +#define SEEK_START 0 +#define SEEK_CURR 1 +#define SEEK_END 2 + +#define FILE_ERR -1 + +#define FIO_INVALID_METHOD 1 +#define FIO_FILE_NOT_FOUND 2 +#define FIO_PATH_NOT_FOUND 3 +#define FIO_HANDLE_UNAVAIL 4 +#define FIO_ACCESS_DENIED 5 +#define FIO_INVALID_HANDLE 6 + +extern int file_err; + +/* FUNCTIONS =========================================================== */ + +#ifdef __cplusplus +extern "C" { +#endif + + + int f_open( /* Open a file returning its handle */ + char * filename, + char access); + + int f_close( /* Close a file */ + int handle); + + int f_read( /* Read a block of data from a file */ + int handle, + char * buffer, + int count); + + int f_write( /* Write a block of data to a file */ + int handle, + char * buffer, + int count); + + int f_readfar( /* Read a block of data from a file */ + int handle, + char far * buffer, + int count); + + int f_writefar( /* Write a block of data to a file */ + int handle, + char far * buffer, + int count); + + long int f_seek( /* Position the file pointer */ + int handle, + long int position, + char method_code); + + long int f_tell( /* return position the file pointer */ + int handle); + + long int f_filelength( /* Return the length of the file */ + int handle); + + +#ifdef __cplusplus +} +#endif + + +#endif + + diff --git a/16/xlib/xfileio.inc b/16/xlib/xfileio.inc new file mode 100755 index 00000000..1a38b739 --- /dev/null +++ b/16/xlib/xfileio.inc @@ -0,0 +1,27 @@ +;----------------------------------------------------------------------- +; +; XFILEIO - Include file +; +; XFILEIO.ASM export functions +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + global _f_open :proc + global _f_close :proc + global _f_read :proc + global _f_write :proc + global _f_readfar :proc + global _f_writefar :proc + global _f_seek :proc + global _f_tell :proc + global _f_filelength :proc + + 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 index 00000000..af3943c7 --- /dev/null +++ b/16/xlib/xfill.asm @@ -0,0 +1,533 @@ +;----------------------------------------------------------------------- +; MODULE XFILL +; +; Point functions all MODE X 256 Color resolutions +; +; Compile with Tasm. +; C callable. +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + +COMMENT $ + + This code is my interpretation of a simple "C" flood filling algorithm + titled: + + * A Seed Fill Algorithm + * by Paul Heckbert + * from "Graphics Gems", Academic Press, 1990 + + The original C source is readily available at numerous internet archive + sites. + + Its been modified and optimized for tweaked 13h modes (Mode X derrivatives). + The most fundamental change is that it fills a column at a time rather + than a row at a time to minimize the number of plane setting "out"s. + And of course the border fill variant was a logical and useful further + modification. + + Both functions return the number of pixels filled.. + + WARNING: These fill functions make heavy use of the stack and no stack + checking is performed, so caution is advised. + +$ + + +include xlib.inc +include xfill.inc + + .code + +_x_flood_fill proc + ARG X:word,Y:word,PgOfs:word,Color:word + LOCAL len:word,y1:word,y2:word,deltax:word,floodval:word,\ + stackptr:word,FillCount:word=STK + push bp + mov bp,sp + sub sp,STK + mov [FillCount],0 + push di si + mov si,[Y] + mov ax,[_ScrnLogicalByteWidth] + mul si ;offset of pixel's scan line in page + mov di,[X] + mov bx,di + shr di,2 ;X/4 = offset of pixel in scan line + add di,ax ;offset of pixel in page + add di,[PgOfs] ;offset of pixel in display memory + mov ax,SCREEN_SEG + mov es,ax ;point ES:DI to the pixel's address + + ;---- Select read plane ------ + + mov ah,bl + and ah,011b ;AH = pixel's plane + mov al,READ_MAP ;AL = index in GC of the Read Map reg + mov dx,GC_INDEX ;set the Read Map to read the pixel's + out dx,ax ; plane + + mov al,es:[di] ;read the pixel's color + cmp al,byte ptr Color ;Is dest pixel the same color as the flood? + je @@Done2 ; if it is abort. + + mov cx,_LeftClip ; Is the dest. pixel out of the clipping window? + sal cx,2 ; if not abort. + cmp bx,cx + jl @@Done2 + + mov cx,_RightClip + sal cx,2 + cmp bx,cx + jg @@Done2 + + mov floodval,ax ; store the color to flood + + ;-- Push fill segment --- + + push bx ; X + push si ; Y + push si ; Y + mov cx,1 ; deltaX (either 1 or -1 indicating direction) + push cx + mov stackptr,1 + + mov deltax,-1 ; Initialize first column scan + mov y1,si ; then bypass some of the preliminary crap in + mov y2,si ; the main fill loop + jmp short @@entry + +@@Done2:mov ax,[FillCount] + pop si di + mov sp,bp + pop bp + ret + +@@NextScanCol: + dec stackptr + js @@Done2 + +@@WhileLoop: + pop cx ; get fill segment from stack + mov deltax,cx ; ie deltaX, Y1, Y2, X + pop ax + mov y2,ax + pop si + mov y1,si + pop bx + + sub ax,si ; Acculmulate number of filled pixels + jns @@PositiveY + neg ax +@@PositiveY: + add FillCount,ax + + + add bx,cx ; move to new column according to deltaX + + mov ax,bx ; Make sure the column is within the clipping + sar ax,2 ; rectangle + cmp ax,_LeftClip + jl @@NextScanCol + + cmp ax,_RightClip + jg @@NextScanCol + + + ;---- Select read plane ------ + + mov ah,bl + and ah,011b ;AH = pixel's plane + mov al,READ_MAP ;AL = index in GC of the Read Map reg + mov dx,GC_INDEX ;set the Read Map to read the pixel's + out dx,ax ; plane + +@@entry: + + ;---- Select write plane ------ + + mov cl,bl + and cl,011b ;CL = pixel's plane + mov ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg + shl ah,cl ;set only the bit for the pixel's + ; plane to 1 + mov dx,SC_INDEX ;set the Map Mask to enable only the + out dx,ax ; pixel's plane + + mov ax,_ScrnLogicalByteWidth ; store logical width in CX + mov cx,ax ; get offset of scan row + mul si ; set ES:DI -> + mov di,bx ; address of pixel at x,y1 + shr di,2 + add di,ax + add di,PgOfs ;ES:DI->first pixel of column segment to fill + mov dx,di ; save y1 offset for after upward fill + + mov al,byte ptr Color + mov ah,byte ptr floodval + +@@FillColUpward: + cmp si,_TopClip ; Dont fill beyond clip boundaries + jl @@UpwardFillDone + + cmp es:[di],ah ; if flood pixel color then replace + jne @@UpwardFillDone ; with new color otherwise column is done + + mov es:[di],al + sub di,cx + dec si + jmp short @@FillColUpward + +@@UpwardFillDone: + cmp si,y1 + jge @@Skip + + inc si + mov len,si + + cmp si,y1 + jge @@AtColumnTop + + push bx ; queue an upward leak check + push si + mov ax,y1 + dec ax + push ax + mov ax,deltax + neg ax + push ax + inc stackptr + +@@AtColumnTop: + mov si,y1 + mov di,dx + add di,cx + inc si + + +@@ColumnLoop: + mov ah,byte ptr floodval + mov al,byte ptr Color + +@@DownwardFill: + cmp si,_BottomClip + jg @@DownwardFillDone + cmp es:[di],ah + jne @@DownwardFillDone + mov es:[di],al + add di,cx + inc si + jmp short @@DownwardFill + +@@DownwardFillDone: + + push bx ; queue an upward leak check + mov ax,len + push ax + mov ax,si + dec ax + push ax + mov ax,deltax + push ax + inc stackptr + + mov ax,y2 + inc ax + cmp si,ax + jle @@Skip + + push bx ; queue a downward leak check + push ax + mov ax,si + dec ax + push ax + mov ax,deltax + neg ax + push ax + inc stackptr + +@@Skip: + mov ah,byte ptr floodval + mov dx,y2 + +@@Backtrack: + add di,cx + inc si + cmp si,dx + jg @@BacktrackDone + + cmp byte ptr es:[di],ah + jne @@Backtrack + +@@BacktrackDone: + mov len,si + cmp si,dx + jle @@ColumnLoop + + dec stackptr + js @@Done + jmp @@WhileLoop +@@Done: + mov ax,[FillCount] + pop si di + mov sp,bp + pop bp + ret +_x_flood_fill endp + + +_x_boundary_fill proc + ARG X:word,Y:word,PgOfs:word,BoundaryColor:word,Color:word + LOCAL len:word,y1:word,y2:word,deltax:word,y1_offs:word,\ + stackptr:word,FillCount:word=STK + push bp + mov bp,sp + sub sp,STK + mov [FillCount],0 + push di si + mov si,[Y] + mov ax,[_ScrnLogicalByteWidth] + mul si ;offset of pixel's scan line in page + mov di,[X] + mov bx,di + shr di,2 ;X/4 = offset of pixel in scan line + add di,ax ;offset of pixel in page + add di,[PgOfs] ;offset of pixel in display memory + mov ax,SCREEN_SEG + mov es,ax ;point ES:DI to the pixel's address + + ;---- Select read plane ------ + + mov ah,bl + and ah,011b ;AH = pixel's plane + mov al,READ_MAP ;AL = index in GC of the Read Map reg + mov dx,GC_INDEX ;set the Read Map to read the pixel's + out dx,ax ; plane + + mov al,es:[di] ;read the pixel's color + cmp al,byte ptr Color ;Is dest pixel the same color as the flood? + je @@Done2 + + cmp al,byte ptr BoundaryColor ;Is dest pixel the same color + je @@Done2 ; as the boundary color? + + + mov cx,_LeftClip ; Is the dest. pixel out of the clipping window? + sal cx,2 + cmp bx,cx + jl @@Done2 + + mov cx,_RightClip + sal cx,2 + cmp bx,cx + jg @@Done2 + + push bx ; X + push si ; Y + push si ; Y + mov cx,1 ; DX + push cx + mov stackptr,1 + mov al,byte ptr BoundaryColor + mov byte ptr [Color+1],al + + mov deltax,-1 + mov y1,si + mov y2,si + jmp short @@entry + +@@Done2:mov ax,[FillCount] + pop si di + mov sp,bp + pop bp + ret + +@@NextScanCol: + dec stackptr + js @@Done2 + +@@WhileLoop: + pop cx + mov deltax,cx + pop ax + mov y2,ax + pop si + mov y1,si + pop bx + add bx,cx ; bx = X + + sub ax,si ; Acculmulate number of filled pixels + jns @@PositiveY + neg ax +@@PositiveY: + add FillCount,ax + + + + mov ax,bx ; Make sure the column is within the clipping + sar ax,2 ; rectangle + cmp ax,_LeftClip + jl @@NextScanCol + cmp ax,_RightClip + jg @@NextScanCol + + + ;---- Select read plane ------ + + mov ah,bl + and ah,011b ;AH = pixel's plane + mov al,READ_MAP ;AL = index in GC of the Read Map reg + mov dx,GC_INDEX ;set the Read Map to read the pixel's + out dx,ax ; plane + +@@entry: + + ;---- Select write plane ------ + + mov cl,bl + and cl,011b ;CL = pixel's plane + mov ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg + shl ah,cl ;set only the bit for the pixel's + ; plane to 1 + mov dx,SC_INDEX ;set the Map Mask to enable only the + out dx,ax ; pixel's plane + + mov ax,_ScrnLogicalByteWidth ; store logical width in CX + mov cx,ax ; get offset of scan row + mul si ; set ES:DI -> + mov di,bx ; address of pixel at x,y1 + shr di,2 + add di,ax + add di,PgOfs + mov y1_offs,di ; save y1 offset for after upward fill + + mov ax,Color ; al = Color ah = BoundaryColor + +@@FillColUpward: + cmp si,_TopClip ; Dont fill beyond clip boundaries + jl @@UpwardFillDone + + mov dl,es:[di] + cmp dl,ah + je @@UpwardFillDone + + cmp dl,al + je @@UpwardFillDone + + mov es:[di],al + sub di,cx + dec si + jmp short @@FillColUpward + +@@UpwardFillDone: + cmp si,y1 + jge @@Skip + + inc si + mov len,si + + cmp si,y1 + jge @@AtColumnTop + + push bx ; queue an upward leak check + push si + mov ax,y1 + dec ax + push ax + mov ax,deltax + neg ax + push ax + inc stackptr + +@@AtColumnTop: + mov si,y1 + mov di,y1_offs + add di,cx + inc si + + +@@ColumnLoop: + mov ax,Color ; al = Color ah = BoundaryColor + +@@DownwardFill: + cmp si,_BottomClip + jg @@DownwardFillDone + + cmp es:[di],ah + je @@DownwardFillDone + + cmp es:[di],al + je @@DownwardFillDone + + mov es:[di],al + add di,cx + inc si + jmp short @@DownwardFill + +@@DownwardFillDone: + + push bx ; queue an upward leak check + mov ax,len + push ax + mov ax,si + dec ax + push ax + mov ax,deltax + push ax + inc stackptr + + mov ax,y2 + inc ax + cmp si,ax + jle @@Skip + + push bx ; queue a downward leak check + push ax + mov ax,si + dec ax + push ax + mov ax,deltax + neg ax + push ax + inc stackptr + +@@Skip: + mov ax,Color ; al = Color ah = BoundaryColor + +@@Backtrack: + add di,cx + inc si + cmp si,y2 + jg @@BacktrackDone + + mov dl,byte ptr es:[di] + cmp dl,al + je @@Backtrack + + cmp dl,ah + je @@Backtrack + +@@BacktrackDone: + mov len,si + cmp si,y2 + jle @@ColumnLoop + + dec stackptr + js @@Done + jmp @@WhileLoop +@@Done: + mov ax,[FillCount] + pop si di + mov sp,bp + pop bp + ret +_x_boundary_fill endp + +end diff --git a/16/xlib/xfill.h b/16/xlib/xfill.h new file mode 100755 index 00000000..3517b404 --- /dev/null +++ b/16/xlib/xfill.h @@ -0,0 +1,51 @@ +/*----------------------------------------------------------------------- +; +; XFILL - header file +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;----------------------------------------------------------------------*/ + +#ifndef _XFILL_H_ +#define _XFILL_H_ + + +/* FUNCTIONS =========================================================== */ + +#ifdef __cplusplus +extern "C" { +#endif + +int x_flood_fill(int x, + int y, + unsigned ofs, + int color + ); + +int x_boundary_fill(int x, + int y, + unsigned ofs, + int boundary, + int color + ); + + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/16/xlib/xfill.inc b/16/xlib/xfill.inc new file mode 100755 index 00000000..6870b464 --- /dev/null +++ b/16/xlib/xfill.inc @@ -0,0 +1,2 @@ +global _x_flood_fill:proc +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 index 00000000..8249e8c8 --- /dev/null +++ b/16/xlib/xlib.h @@ -0,0 +1,160 @@ +/*---------------------------------------------------------------------- +; +; XLIB - header file +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; Header file contributed by Darren Lyon (darren@nicky.DIALix.oz.au) +; +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;----------------------------------------------------------------------*/ + +#ifndef _XLIB_H_ +#define _XLIB_H_ + +#define BYTE unsigned char +#define WORD unsigned int + + +#define X_MODE_320x200 0 +#define X_MODE_320x240 1 +#define X_MODE_360x200 2 +#define X_MODE_360x240 3 +#define X_MODE_376x282 4 +#define X_MODE_320x400 5 +#define X_MODE_320x480 6 +#define X_MODE_360x400 7 +#define X_MODE_360x480 8 +#define X_MODE_360x360 9 +#define X_MODE_376x308 10 +#define X_MODE_376x564 11 +#define X_MODE_256x400 12 +#define X_MODE_256x480 13 + + +#define BACKWARD 0 +#define FORWARD 1 + +#define X_MODE_INVALID -1 +#define ERROR 1 +#define OK 0 + +/* FUNCTIONS =========================================================== */ + +#ifdef __cplusplus +extern "C" { +#endif + + WORD x_set_mode( + WORD mode, /* Initialize x mode */ + WORD WidthInPixels); + + void x_select_default_plane( /*Enables Read/Write access to a */ + BYTE plane); /* a specified plane */ + + void x_set_splitscreen( /* set the split screen start */ + WORD line); /*scan line (initialize) */ + + void x_set_start_addr( + WORD X, /* Set the screen start */ + WORD Y); /* address in video ram */ + + void x_hide_splitscreen(void); /* Disable the split screen (Split */ + /* Screen RAM remains reserved) */ + + void x_show_splitscreen(void); /* Enable the split screen (given it */ + /* was previously "hidden") */ + + + void x_adjust_splitscreen( /* Adjust the start scan line of the */ + WORD line); /* split screen */ + + + WORD x_set_doublebuffer( /* Enable double buffering with a */ + WORD PageHeight); /* specified page height */ + + WORD x_set_tripplebuffer( /* Enable tripple buffering with a */ + WORD PageHeight); /* specified page height */ + + + void x_page_flip( /* Swap visible page (only when double */ + WORD X, /* buffering is active) & sets virt start*/ + WORD Y); + + void x_set_cliprect( /* Define the clipping rectangle */ + WORD left, /* NOTE: left and right are in bytes */ + WORD top, + WORD righ, + WORD bottom); + + void x_text_mode(void); /* return to text mode */ + void x_wait_vsync(void); /* wait for vsync */ + +#ifdef __cplusplus +} +#endif + + +/* VARIABLES =========================================================== */ + +extern BYTE InGraphics; /* non zero if in X graphics mode */ +extern WORD CurrXMode; /* contains current X graphics mode id */ +extern WORD ScrnPhysicalByteWidth; /* Physical screen width in bytes */ +extern WORD ScrnPhysicalPixelWidth; /* Physical screen width in pixels */ +extern WORD ScrnPhysicalHeight; /* Physical screen height in pixels */ +extern WORD ErrorValue; /* Error return value */ +extern WORD SplitScrnOffs; /* Offset in VRAM of split screen */ +extern WORD SplitScrnScanLine; /* Scan line split screen starts at */ + /* initially. Resizing the split scrn */ + /* using the other functions does not */ + /* change this value */ +extern WORD SplitScrnVisibleHeight; /* Height of the visible portion of the*/ + /* split screen. */ +extern WORD Page0_Offs; /* Offset in VRAM of main virt. screen */ +extern WORD Page1_Offs; /* Offset in VRAM of 2nd virt. screen */ +extern WORD Page2_Offs; /* Offset in VRAM of 3rd virt. screen */ +extern WORD ScrnLogicalByteWidth; /* Virtual screen width in bytes */ +extern WORD ScrnLogicalPixelWidth; /* Virtual screen width in pixels */ +extern WORD ScrnLogicalHeight; /* Virtual screen height in pixels */ +extern WORD MaxScrollX; /* Max X position of physical screen */ + /* within virtual screen */ +extern WORD MaxScrollY; /* Max Y position of physical screen */ + /* within virtual screen */ +extern WORD DoubleBufferActive; /* Indicates whether double buffering */ + /* is active */ +extern WORD TrippleBufferActive; /* Indicates whether tripple */ + /* buffering is active */ +extern WORD VisiblePageIdx; /* Index number of visible page 0 or 1 */ +extern WORD HiddenPageOffs; /* Offset of Hidden Pg | only valid */ +extern WORD VisiblePageOffs; /* Offset of Visible Pg| for D.B. mode */ +extern WORD WaitingPageOffs; /* Offset of Waiting Pg| for T.B. mode */ +extern WORD NonVisual_Offs; /* Offset of first non-visible VRAM */ + +extern WORD StartAddressFlag; + +extern WORD TopClip; /* Clipping rectangle */ +extern WORD BottomClip; +extern WORD LeftClip; +extern WORD RightClip; + +extern WORD PhysicalStartPixelX; /* Coordinates of physical (visible) */ +extern WORD PhysicalStartByteX; /* screen relative to the virtual */ +extern WORD PhysicalStartY; /* screen's U.L. corner */ + +extern char* VsyncPaletteBuffer; + +#endif + + diff --git a/16/xlib/xlib.inc b/16/xlib/xlib.inc new file mode 100755 index 00000000..58e256dd --- /dev/null +++ b/16/xlib/xlib.inc @@ -0,0 +1,166 @@ +;----------------------------------------------------------------------- +; +; XLIB - Include file +; +; Global equates and variables +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; MODIFICATIONS: +; 26-9-92 : Pel panning code added +; 23-10-92: Added clip rectangle code +;----------------------------------------------------------------------- + +; + +LOCALS +.286 + +; First lets find out what memory model to use + +include model.inc + + +AC_INDEX equ 03c0h ;Attribute controller index register +MISC_OUTPUT equ 03c2h ;Miscellaneous Output register +SC_INDEX equ 03c4h ;Sequence Controller Index +GC_INDEX equ 03ceh ; Graphics controller Index +CRTC_INDEX equ 03d4h ;CRT Controller Index +DAC_READ_INDEX equ 03c7h ; +DAC_WRITE_INDEX equ 03c8h ; +DAC_DATA equ 03c9h ; +INPUT_STATUS_0 equ 03dah ;Input status 0 register + + +SCREEN_SEG equ 0a000h ;segment of display memory in mode X + +MAP_MASK equ 02h ;index in SC of Map Mask register +READ_MAP equ 04h ;index in GC of the Read Map register +BIT_MASK equ 08h ;index in GC of Bit Mask register + +OVERFLOW equ 07h ; CRTC overflow register index +MAX_SCAN_LINE equ 09h ; CRTC maximum scan line register index +ADDR_HIGH equ 0ch ;Index of Start Address High reg in CRTC +ADDR_LOW equ 0dh ; Low +CRTC_OFFSET equ 13h ; CRTC offset register index +UNDERLINE equ 14h ; CRTC underline location register index +MODE_CONTROL equ 17h ; CRTC mode control register index +LINE_COMPARE equ 18h ; CRTC line compare reg. index (bits 0-7 of + ; split screen scan line + +AC_MODE_CONTROL equ 10h ; Index of Mode COntrol register in AC +PEL_PANNING equ 13h ; Pel panning register index in AC + +PATTERN_BUFFER equ 0fffch ;offset in screen memory of pattern buffer + +TRUE equ 1 +FALSE equ 0 + + +OK equ 0 +ERROR equ 1 + + +;----------------------------------------------------------------------- +; Macro to wait for the vertical retrace leading edge + +WaitVsyncStart macro + LOCAL WaitNotVsync,WaitVsync + mov dx,INPUT_STATUS_0 +WaitNotVsync: + in al,dx + test al,08h + jnz WaitNotVsync +WaitVsync: + in al,dx + test al,08h + jz WaitVsync + endm + +;----------------------------------------------------------------------- +; Macro to wait for the vertical retrace trailing edge + +WaitVsyncEnd macro + LOCAL WaitNotVsync,WaitVsync + mov dx,INPUT_STATUS_0 +WaitVsync2: + in al,dx + test al,08h + jz WaitVsync2 +WaitNotVsync2: + in al,dx + test al,08h + jnz WaitNotVsync2 + endm + +;--- Word out macro ------------------------------------------ + + WORDOUT macro + IFDEF nw + out dx,al + inc dx + xchg al,ah + out dx,al + xchg al,ah + dec dx + ELSE + out dx,al + ENDIF + endm + +;------------------------------------------------------------------------ +; Global variables - XMAIN exports +; + global _InGraphics :byte + global _CurrXMode :word + global _ScrnPhysicalByteWidth :word + global _ScrnPhysicalPixelWidth :word + global _ScrnPhysicalHeight :word + global _ErrorValue :byte + + global _SplitScrnOffs :word + global _SplitScrnScanLine :word + global _SplitScrnVisibleHeight :word + global _Page0_Offs :word + global _Page1_Offs :word + global _Page2_Offs :word + global _ScrnLogicalByteWidth :word + global _ScrnLogicalPixelWidth :word + global _ScrnLogicalHeight :word + + global _MaxScrollX :word + global _MaxScrollY :word + global _DoubleBufferActive :word + global _TrippleBufferActive :word + global _VisiblePageIdx :word + global _VisiblePageOffs :word + global _HiddenPageOffs :word + global _WaitingPageOffs :word + global _NonVisual_Offs :word + global _TopClip :word + global _BottomClip :word + global _LeftClip :word + global _RightClip :word + + global _PhysicalStartByteX :word + global _PhysicalStartPixelX :word + global _PhysicalStartY :word + + global _VsyncHandlerActive :word + global _MouseRefreshFlag :word + global _MouseVsyncHandler :dword + global _StartAddressFlag :word + global _WaitingStartLow :word + global _WaitingStartHigh :word + global _WaitingPelPan :word + global _VsyncPaletteStart :word + global _VsyncPaletteCount :word + global _VsyncPaletteBuffer :byte + + diff --git a/16/xlib/xlib_all.h b/16/xlib/xlib_all.h new file mode 100755 index 00000000..9fca71f1 --- /dev/null +++ b/16/xlib/xlib_all.h @@ -0,0 +1,42 @@ +/*----------------------------------------------------------------------- +; +; XLIB_ALL - header file +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;----------------------------------------------------------------------*/ + +#include "XLIB.H" +#include "XPOINT.H" +#include "XRECT.H" +#include "XLINE.H" +#include "XPAL.H" +#include "XTEXT.H" +#include "XPBITMAP.H" +#include "XCBITMAP.H" +#include "XDETECT.H" +#include "XBMTOOLS.H" +#include "XFILEIO.H" +#include "XRLETOOL.H" +#include "XBEZIER.H" +#include "XVBITMAP.H" +#include "XMOUSE.H" +#include "XPBMCLIP.H" +#include "XCIRCLE.H" +#include "XCLIPPBM.H" +#include "XPOLYGON.H" +#include "XVSYNC.H" +#include "XFILL.H" +#include "XCBITM32.H" diff --git a/16/xlib/xlibref1.doc b/16/xlib/xlibref1.doc new file mode 100755 index 00000000..0c363e34 --- /dev/null +++ b/16/xlib/xlibref1.doc @@ -0,0 +1,1655 @@ +PART 1 of 2 +----------------------------------------------------------------------------- + + ********* XLIB - Mode X graphics library **************** + ********* **************** + ********* Written By Themie Gouthas **************** + ********* **************** + ********* egg@dstos3.dsto.gov.au **************** + ********* teg@bart.dsto.gov.au **************** + + Some of the code in this library has been contributed by : + + Matthew MacKenzie - matm@eng.umd.edu + + and others. See individual modules. + + I informally reserve all rights to the code in XLIB + Rights to contributed code is also assumed to be reserved by + the original authors. +----------------------------------------------------------------------------- + +DISCLAIMER + + This library is distributed AS IS. The author/s specifically disclaim + any responsibility for any loss of profit or any incidental, consequen- + tial or other damages. + +--------------------------------------------------------------------------- +INTRODUCTION +--------------------------------------------------------------------------- + +XLIB is a "user supported freeware" graphics library specifically designed +with game programming in mind. + +It has been placed in the public domain for the benefit of all, and +represents *MANY* hours of work so it is requested that all users comply +with the the wishes of the author/s as specified in the individual modules +and: +a) To leave the code in the public domain +b) Not distribute any modified or incomplete versions of this library + +New contribution and comments are welcome and hopefully there will be +more releases as the code evolves. + +Finally, do not trust this excuse for a manual if in doubt, as this code has +undergone several revisions. The place to get the answers is in the code +itself. + +REQUIREMENTS + +Minimum requirements + 286 processor, + Turbo C 2.0 or higher, or BORLANDC + MAKE 2.0 or higher + TLIB 2.0 or higher + Turbo Assembler 1.01 or higher + + +GENERAL FEATURES + + Support for a number of 256 colour tweaked graphics mode resolutions + 320x200 320x240 360x200 360x240 376x282 320x400 320x480 360x400 360x480 + 360x360 376x308 376x564 + + Please note that some of the new resolutions best suit monitors with + adjustable vertical height. + + Virtual screens larger than the physical screen (memory + permitting) that can be panned at pixel resolution in all directions + + A split screen capability for status displays etc. + + Text functions supporting 8x8 and 8x14 ROM fonts and user defined fonts + + Support for page flipping + + Graphics primitives such as line and rectangle drawing functions and + of course bit block manipulation functions + +MODULES COMPRISING XLIB + XMAIN - Main module containig mode setting code and basic functions + XPOINT - Pixel functions + XRECT - Filled Rectangle and VRAM to VRAM block move functions + XPAL - Palette functions + XLINE - Line Functions + XTEXT - Text and Font Functions + XPRINTF - Printf style string output + XPBITMAP - Planar Bitmap functions + XCBITMAP - Compiled Bitmap functions + XVBITMAP - Video Bitmap functions + XPBMCLIP - Clipped Planar Bitmap functions + XMAKEVBM - Support module for video bitmaps + XBMTOOLS - Bitmap format conversion tools + XDETECT - Hardware detection module + XFILEIO - File I/O functions + XRLETOOL - RLE encoding/decoding functions + XMOUSE - Mouse functions + XBEZIER - Bezier curve drawing + +------------------------------------------------------------------------- +BUILDING THE LIBRARIES +------------------------------------------------------------------------- + +Building the library had been made simple through the use of make. + +To build and examples for one of the two models: + +a) edit the makefile for the apropriate model (see note in the makefile) +b) edit the makefile for the apropriate compiler (again see note in the + makefile) +c) type "make" at the dos prompt. + +It should be as simple as that. If problems are encountered then check +to see if tasm, make, tlib, link and bcc (or tcc) are withinin your path. +If not either change your path or specify the full path for these programs +in the makefile. It is preferrable to have your path set correctly. + +Individual Compilation +---------------------- + +each ASM module can be compiled with the following commandline: + +tasm /ml /d + +where is s c or l. Where s = small model, c = compact model and +l = large model. + +The resulting libraries are: + + xlibs.lib - small model library + xlibc.lib - large model library + xlibl.lib - large model library + +To link the library with your programs just include the apropriate .lib +file in your project file or on the BCC or TCC command line. + +Using the library with your programs +------------------------------------ + +Using the XLIB library in your programs is simple. Knowing the particular +modules you require, just include the associated header files in your program +and link your program modules with the library. If you don't want to wory +about selecting the apropriate header file then just include "XLIB_ALL.H" +which automatically includes all XLIB header files in your program. + +For example compilations see the supplied makefile. + +-------------------------------------------------------------------------- +GLOBAL DEFINES (xlib.inc) +-------------------------------------------------------------------------- + +Types + + BYTE unsigned char + WORD unsigned int + +Available X mode resolutions + + X_MODE_320x200 0 + X_MODE_320x240 1 + X_MODE_360x200 2 + X_MODE_360x240 3 + X_MODE_360x282 4 + X_MODE_320x400 5 + X_MODE_320x480 6 + X_MODE_360x400 7 + X_MODE_360x480 8 + X_MODE_360x360 9 + X_MODE_376x308 10 + X_MODE_376x564 11 + +Palette rotation direction directiion + + BACKWARD 0 + FORWARD 1 + + + X_MODE_INVALID -1 + ERROR 1 + OK 0 + + +-------------------------------------------------------------------------- +MODULE XMAIN +-------------------------------------------------------------------------- + +The Xmain module is the base module of the XLIB library. It contains the +essential functions that initialize and customize the graphic environment. + + +ASM SOURCES + + xmain.asm xmain.inc xlib.inc model.inc + +C HEADER FILE + + xlib.h + +EXPORTED VARIABLES + + NOTE: All variables are read only unless otherwise specified. If you modify + them manually, the results may be unpredictable. + + InGraphics - BYTE - Flag indicating that the xlib graphics system is + active. Set by function "x_set_mode". + + CurrXMode - WORD - If the xlib graphics system is active, contains the id + of the x mode. Set by function "x_set_mode". + See also defines (ie X_MODE_320x200 ... ) + + ScrnPhysicalByteWidth - WORD - Physical screen width in bytes. Set by + function "x_set_mode" + + ScrnPhysicalPixelWidth - WORD - Physical screen width in pixels. Set by + function "x_set_mode" + + ScrnPhysicalHeight - WORD - Physical screen height in pixels. Set by + function "x_set_mode". + + ErrorValue - WORD - Contains error value. General use variable to + communicate the error status from several functions. The value + in this variable usually is only valid for the the last + function called that sets it. + + SplitScrnOffs - WORD - Offset in video ram of split screen. Set by + function "x_set_splitscrn". The value is only valid if a split + screen is active. See also global variable "SplitScrnActive". + + SplitScrnScanLine - WORD - Screen Scan Line the Split Screen starts at + initially when set by function "x_set_splitscrn". The value is only + valid if a split screen is active. See also global variable + "SplitScrnActive".This variable is not updated by "x_hide_splitscrn", + "x_adjust_splitscrn". + + SplitScrnVisibleHeight - WORD - The number of rows of the initial split + screen which are currently displayed. Modified by "x_hide_splitscrn", + "x_adjust_splitscrn" and "x_show_splitscrn". + + Page0_Offs - WORD - Offset in video ram of main virtual screen. Initially + set by function "x_set_mode" but is updated by functions + "x_set_splitscrn" and "x_set_doublebuffer". + + Page1_Offs - WORD - Offset in video ram of second virtual screen. Set by + and only is valid after a call to "x_set_doublebuffer". + + ScrnLogicalByteWidth - WORD - Virtual screen width in bytes. Set by + function "x_set_mode". + + ScrnLogicalPixelWidth - WORD - Virtual screen width in pixels. Set + by function "x_set_mode". + + ScrnLogicalHeight - WORD - Virtual screen height in pixels. Set + initially by function "x_set_mode" but is updated by functions + "x_set_splitscrn" and "x_set_doublebuffer". + + MaxScrollX - WORD - Max X pixel position of physical screen within + virtual screen. Set by function "x_set_mode". + + MaxScrollY - WORD - Max Y position of physical screen within virtual + screen. Set initially by function "x_set_mode" but is updated by + functions "x_set_splitscrn" and "x_set_doublebuffer". + + DoubleBufferActive - WORD - Indicates whether double-buffering is on. Set + by function "x_set_doublebuffer". + + VisiblePageIdx - WORD - Index number of current visible page. Initially + set by function "x_set_doublebuffer" but is updated by "x_page_flip". + This variable is only used while double buffering is on. + + HiddenPageOffs - WORD - Offset of hidden page. Initially set by function + "x_set_doublebuffer" but is updated by "x_page_flip". This variable + is only used while double buffering is on. + + VisiblePageOffs - WORD - Offset of visible page. Initially set by function + "x_set_doublebuffer" but is updated by "x_page_flip". This variable + is only used while double buffering is on. + + NonVisual_Offs - WORD - Offset of first byte of non-visual ram, the ram + that is available for bitmap storage etc. Set initially by function + "x_set_mode" but is updated by functions "x_set_splitscrn" and + "x_set_doublebuffer". + + TopClip, BottomClip, LeftClip RightClip - WORD - Define the clipping + rectangle for Linear and Video clipped bitmap put functions. Set + either manually or by "x_set_cliprect". Note X coordinates are in + bytes as all clip functions clip to byte boundaries. + + PhysicalStartPixelX - WORD - X pixel Offset of physical (visible) screen + relative to the upper left hand corner (0,0) of the virtual screen. + + PhysicalStartByteX - WORD - X byte Offset of physical (visible) screen + relative to the upper left hand corner (0,0) of the virtual screen. + + PhysicalStartY - WORD - Y pixel Offset of physical (visible) screen + relative to the upper left hand corner (0,0) of the virtual screen. + +EXPORTED FUNCTIONS + + x_set_mode + ---------- + C Prototype: extern WORD x_set_mode(WORD mode,WORD WidthInPixels); + + mode - The required mode as defined by the "Available X Mode + resolutions" set of defines in the xlib.h header file. + WidthInPixels - The required virtual screen width. + Returns - The actual width in pixels of the allocated virtual + screen + + This function initialises the graphics system, setting the apropriate + screen resolution and allocating a virtual screen. The virtual screen + allocated may not necessarily be of the same size as specified in the + "WidthInPixels" parameter as it is rounded down to the nearest + multiple of 4. + + The function returns the actual width of the allocated virtual screen + in pixels if a valid mode was selected otherwise returns + X_MODE_INVALID. + + Saves virtual screen pixel width in "ScrnLogicalPixelWidth". + Saves virtual screen byte width in "ScrnLogicalByteWidth". + Physical screen dimensions are set in "ScrnPhysicalPixelWidth". + "ScrnPhysicalByteWidth" and "ScrnPhysicalHeight". Other global + variables set are "CurrXMode","MaxScrollX", "MaxScrollY", + "InGraphics". The variable "SplitScrnScanline" is also initialized + to zero. + + See also: + Available X Mode resolutions + What is Mode X + + x_select_default_plane + ---------------------- + + C Prototype: void x_select_default_plane(BYTE plane); + + Enables default Read/Write access to a specified plane + + + x_set_splitscreen + ----------------- + + C Prototype: extern void x_set_splitscreen(WORD line); + + line - The starting scan line of the required split screen. + + This function activates Mode X split screen and sets starting scan + line. The split screen resides on the bottom half of the screen and has + a starting address of A000:0000 in video RAM. + + It also Updates Page0_Offs to reflect the existence of the split screen + region ie "MainScrnOffset" is set to the offset of the first pixel + beyond the split screen region. Other variable set are "Page1_Offs" which + is set to the same value as "Page0_Offs" (see graphics call sequence + below), "ScrnLogicalHeight","ScrnPhysicalHeight", "SplitScrnScanLine" and + "MaxScrollY". + + This function cannot be called after double buffering has been activated, + it will return an error. To configure your graphics environment the + sequence of graphics calls is as follows although either or both steps b + and c may be omitted: + a) x_set_mode + b) x_set_splitscreen + c) x_set_doublebuffer + Thus when you call this function successfully, double buffering is not + active so "Page1_Offs" is set to the same address as "Page0_Offs". + + WARNING: If you use one of the high resolution modes (376x564 as an + extreme example) you may not have enough video ram for split screen + and double buffering options since VGA video RAM is restricted to + 64K. + + See Also: + What is a Split Screen ? + What is double buffering ? + + x_set_doublebuffer + ------------------ + + C Prototype: extern WORD x_set_doublebuffer(WORD PageHeight); + + PageHeight - The height of the two double buffering virtual screens. + Returns - The closest possible height to the specified. + + This function sets up two double buffering virtual pages. 'ErrorValue" + is set according to the success or failure of this command. + + Other variables set are: + + _Page1_Offs Offset of second virtual page + _NonVisual_Offs Offset of first non visible video ram byte + _DoubleBufferActive Flag + _PageAddrTable Table of Double buffering pages start offsets + _ScrnLogicalHeight Logical height of the double buffering pages + _MaxScrollY Max vertical start address of physical screen + within the virtual screen + + WARNING: If you use one of the high resolution modes (376x564 as an + extreme example) you may not have enough video ram for split screen + and double buffering options since VGA video RAM is restricted to + 64K. + + See Also: + What is double buffering ? + + x_hide_splitscreen + ------------------ + + C Prototype: extern void x_hide_splitscreen(void); + + + This function hides an existing split screen by setting its starting + scan line to the last physical screen scan line. + "ScreenPhysicalHeight" is adjusted but the "SplitScreenScanLine" is not + altered as it is required for restoring the split screen at a later stage. + + WARNING: Only to be used if SplitScrnLine has been previously called + Disabled for mode 5-11 (320x400-376x564). The memory for + the initial split screen is reserved and the size limitations + of these modes means any change in the split screen scan line + will encroach on the split screen ram + Update: Now disabled for these modes + + See Also: + + What is a split screen ? + + x_show_splitscreen + ------------------ + + C Prototype: extern void x_show_splitscreen(void); + + Restores split screen start scan line to the initial split screen + starting scan line as set by "SplitScrnScanLine". + "ScreenPhysicalHeight" is adjusted. + + WARNING: Only to be used if SplitScrnLine has been previously called + Disabled for mode 4-10 (320x400-376x564). The memory for + the initial split screen is reserved and the size limitations + of these modes means any change in the split screen scan line + will encroach on the split screen ram + + + x_adjust_splitscreen + -------------------- + + C Prototype: extern void x_adjust_splitscreen(WORD line); + + line - The scan line at which the split screen is to start. + + Sets the split screen start scan line to a new scan line. Valid scan lines + are between the initial split screen starting scan line and the last + physical screen scan line. "ScreenPhysicalHeight" is also adjusted. + + WARNING: Only to be used if SplitScrnLine has been previously called + Disabled for mode 4-10 (320x400-376x564). The memory for + the initial split screen is reserved and the size limitations + of these modes means any change in the split screen scan line + will encroach on the split screen ram + + x_set_start_addr + ---------------- + + C Prototype: extern void x_set_start_addr(WORD X,WORD Y); + + X,Y - coordinates of top left corner of physical screen within current + virtual screen. + + Set Mode X non split screen physical start address within current virtual + page. + + X must not exceed (Logical screen width - Physical screen width) + ie "MaxScrollX" and Y must not exceed (Logical screen height - + Physical screen height) ie "MaxScrollY" + + x_page_flip + ----------- + + C Prototype: extern void x_page_flip(WORD X,WORD Y); + + X,Y - coordinates of top left corner of physical screen within the + the hidden virtual screen if double buffering is active, or + the current virtual screen otherwise. + + Sets the physical screen start address within currently hidden virtual + page and then flips pages. If double buffering is not active then this + function is functionally equivalent to "x_set_start_addr". + + X must not exceed (Logical screen width - Physical screen width) + ie "MaxScrollX" and Y must not exceed (Logical screen height - + Physical screen height) ie "MaxScrollY" + + x_text_mode + ----------- + + C Prototype: extern void x_text_mode(void); + + Disables graphics mode. + + x_set_cliprect + -------------- + + C Prototype: extern void x_set_cliprect(WORD left,WORD top,WORD right, + WORD bottom); + + Defines the clipping rectangle for clipping versions of planar and video + bitmap puts. + + NOTE: Compiled bitmaps cannot be clipped. + + +-------------------------------------------------------------------------- +MODULE XPOINT +-------------------------------------------------------------------------- + + Point functions all MODE X 256 Color resolutions + + ASM SOURCES + + xpoint.asm xpoint.inc xlib.inc model.inc + + C HEADER FILE + + xpoint.h + + EXPORTED FUNCTIONS + + x_put_pix + --------- + + C Prototype: extern void x_put_pix(WORD X,WORD Y,WORD PageOffset, + WORD Color); + + Draw a point of specified colour at coordinates X,Y + within the virtual page starting at offset PageOffset. + + x_get_pix + --------- + + C Prototype: extern WORD x_get_pix(WORD X, WORD Y, WORD PageBase); + + Read a point of at coordinates X,Y within the virtual page starting + at offset PageOffset. + + +-------------------------------------------------------------------------- +MODULE XRECT +-------------------------------------------------------------------------- + + Screen rectangle display and manipulation functions + + ASM SOURCES + + xrect.asm xrect.inc xlib.inc model.inc + + C HEADER FILE + + xrect.h + + + EXPORTED FUNCTIONS + + x_rect_pattern + -------------- + + C Prototype: extern void x_rect_pattern(WORD StartX, WORD StartY, + WORD EndX, WORD EndY, + WORD PageBase,BYTE far *Pattern); + + StartX,StartY - Coordinates of upper left hand corner of rectangle + EndX,EndY - Coordinates of lower right hand corner of rectangle + PageBase - Offset of virtual screen + *Pattern - Pointer to the user defined pattern (16 bytes) + + + Mode X rectangle 4x4 pattern fill routine. + + Upper left corner of pattern is always aligned to a multiple-of-4 + row and column. Works on all VGAs. Uses approach of copying the + pattern to off-screen display memory, then loading the latches with + the pattern for each scan line and filling each scan line four + pixels at a time. Fills up to but not including the column at EndX + and the row at EndY. No clipping is performed. + + Based on code originally published in DDJ Mag by M. Abrash + + Warning the VGA memory locations PATTERN_BUFFER (A000:FFFc) to + A000:FFFF are reserved for the pattern buffer + + + See Also: + Doctor Dobbs Journal references. + + + x_rect_pattern_clipped + ---------------------- + + As above but clipped. + + x_rect_fill + ----------- + + C Prototype: extern void x_rect_fill(WORD StartX,WORD StartY, + WORD EndX,WORD EndY, + WORD PageBase,WORD color); + + StartX,StartY - Coordinates of upper left hand corner of rectangle + EndX,EndY - Coordinates of lower right hand corner of rectangle + PageBase - Offset of virtual screen + Color -color to use for fill + + Mode X rectangle solid color fill routine. + Based on code originally published in DDJ Mag by M. Abrash + + See Also: + Doctor Dobbs Journal references. + + x_rect_fill_clipped + ------------------- + + as above but clipped. + + + x_cp_vid_rect + ------------- + + C Prototype: extern void x_cp_vid_rect(WORD SourceStartX,WORD SourceStartY, + WORD SourceEndX,WORD SourceEndY, + WORD DestStartX,WORD DestStartY, + WORD SourcePageBase,WORD DestPageBase, + WORD SourceBitmapWidth,WORD DestBitmapWidth); + + StartX,StartY- Coordinates of upper left hand corner of source rectangle + EndX,EndY - Coordinates of lower right hand corner of source rectangle + DestStartX,DestStartY - Coordinates of rectangle destination + SourcePageBase - source rectangle page offset + DestPageBase - destination rectangles page offset + SourceBitmapWidth - width of bitmap within the source virtual screen + containing the source rectangle + DestBitmapWidth - width of bitmap within the dest. virtual screen + containing the destination rectangle + + Mode X display memory to display memory copy + routine. Left edge of source rectangle modulo 4 must equal left edge + of destination rectangle modulo 4. Works on all VGAs. Uses approach + of reading 4 pixels at a time from the source into the latches, then + writing the latches to the destination. Copies up to but not + including the column at SrcEndX and the row at SrcEndY. No + clipping is performed. Results are not guaranteed if the source and + destination overlap. + + + Based on code originally published in DDJ Mag by M. Abrash + + See Also: + Doctor Dobbs Journal references. + + x_shift_rect + ------------ + + C Prototype: + extern void x_shift_rect (WORD SrcLeft, WORD SrcTop, + WORD SrcRight, WORD SrcBottom, + WORD DestLeft, WORD DestTop, WORD ScreenOffs); + + SrcLeft, SrcTop - Coordinates of upper left hand corner of rectangle + SrcRight, SrcBottom - Coordinates of lower right hand corner of rectangle + DestLeft, DestTop - Coordinates of upper left corner of destination + ScreenOffs - Offset of virtual screen + + This function copies a rectangle of VRAM onto another area of VRAM, + even if the destination overlaps with the source. It is designed + for scrolling text up and down, and for moving large areas of screens + around in tiling systems. It rounds all horizontal coordinates to + the nearest byte (4-column chunk) for the sake of speed. This means + that it can NOT perform smooth horizontal scrolling. For that, + either scroll the whole screen (minus the split screen), or copy + smaller areas through system memory using the functions in the + XPBITMAP module. + + SrcRight is rounded up, and the left edges are rounded down, to + ensure that the pixels pointed to by the arguments are inside the + the rectangle. That is, SrcRight is treated as (SrcRight+3) >> 2, + and SrcLeft as SrcLeft >> 2. + + The width of the rectangle in bytes (width in pixels / 4) + cannot exceed 255. + +--------------------------------------------------------------------------- +MODULE XPAL +--------------------------------------------------------------------------- + + Palette functions for VGA 256 color modes. + + All the functions in this module operate on two variations of the + pallete buffer, the raw and annotated buffers. + + All those functions ending in "raw" operate on the following palette + structure: + + BYTE:r0,g0,b0,r1,g1,b1,...rn,gn,bn + + No reference to the starting colour index or number of colours stored + is contained in the structure. + + All those functions ending in "struc" operate on the following palette + structure: + + BYTE:c,BYTE:n,BYTE:r0,g0,b0,r1,g1,b1,...rn,gn,bn + + where c is the starting colour and n is the number of colours stored + + + WARNING: There is no validity checking in these functions. The onus is + on the user to supply valid parameters to the functions. + + + ASM SOURCES + + xpal.asm xpal.inc xlib.inc model.inc + + C HEADER FILE: + + xpal.h + + EXPORTED FUNCTIONS + + x_get_pal_raw + ------------- + + C Prototype: extern void x_get_pal_raw(BYTE far * pal,WORD num_colrs, + WORD start_index); + + Read DAC palette into raw buffer with interrupts disabled + ie BYTE r1,g1,b1,r1,g2,b2...rn,gn,bn + + WARNING: Memory for the palette buffers must all be pre-allocated. + + x_get_pal_struc + --------------- + + C Prototype: extern void x_get_pal_struc(BYTE far * pal,WORD num_colrs, + WORD start_index); + + Read DAC palette into annotated type buffer with interrupts disabled + ie BYTE colours to skip, BYTE colours to set, r1,g1,b1,r1,g2,b2...rn,gn,bn + + WARNING: memory for the palette buffers must all be pre-allocated + + x_put_pal_raw + ------------- + + C Prototype: extern void x_put_pal_raw(BYTE far * pal,WORD num_colrs, + WORD start_index); + + Write DAC palette from raw buffer with interrupts disabled + ie BYTE r1,g1,b1,r1,g2,b2...rn,gn,bn + + x_put_pal_struc + -------------- + + C Prototype: extern void x_put_pal_struc(BYTE far * pal); + + Write DAC palette from annotated type buffer with interrupts disabled + ie BYTE colours to skip, BYTE colours to set, r1,g1,b1,r1,g2,b2...rn,gn,bn + + x_set_rgb + --------- + + C Prototype: extern x_set_rgb(BYTE color,BYTE red_c,BYTE green_c, + BYTE blue_c); + + Set the RGB components of a vga color + + x_rot_pal_struc + --------------- + + C Prototype: extern void x_rot_pal_struc(BYTE far * pal,WORD direction); + + Rotate annotated palette buffer entries. Direction 0 = backward, + 1 = forward. + + x_rot_pal_raw + ------------- + + C Prototype: extern x_rot_pal_raw(BYTE far * pal,WORD direction, + WORD num_colrs); + + Rotate a raw palette buffer. Direction 0 = backward, + 1 = forward. + + x_put_contrast_pal_struc + ------------------------ + + C Prototype: extern void x_put_contrast_pal_struc(BYTE far * pal, + BYTE intensity); + + Write DAC palette from annotated type buffer with specified intensity + adjustment (ie palette entries are decremented where possible by + "intensity" units). + + Designed for fading in or out a palette without using an intermediate + working palette buffer ! (Slow but memory efficient ... OK for small + pal strucs} + + + x_transpose_pal_struc + --------------------- + + C Prototype: extern void x_transpose_pal_struc(BYTE far * pal, + WORD StartColor); + + Write DAC palette from annotated type buffer with interrupts disabled + starting at a new palette index. + + + x_cpcontrast_pal_struc + ---------------------- + + C Prototype: extern WORD x_cpcontrast_pal_struc(BYTE far *src_pal, + BYTE far *dest_pal,BYTE Intensity); + + Copy one annotated palette buffer to another making the intensity + adjustment. Used in fading in and out fast and smoothly. + +--------------------------------------------------------------------------- +MODULE XLINE +--------------------------------------------------------------------------- + + Line Drawing functions. + + ASM SOURCES + + xline.asm xline.inc xlib.inc model.inc + + C HEADER FILE + + xline.h + + EXPORTED FUNCTIONS + + x_line + ------ + + C Prototype: extern void x_line(WORD x0,WORD y0,WORD x1,WORD y1, + WORD color,WORD PageBase); + + Draw a line with the specified end points in the page starting at + offset "PageBase". + + No Clipping is performed. + +--------------------------------------------------------------------------- +MODULE XTEXT +--------------------------------------------------------------------------- + + ASM SOURCES + + xtext.asm xtext.inc xlib.inc model.inc + + C HEADER FILE + + xtext.h + + MACROS + + FONT_8x8 0 + FONT_8x15 1 + FONT_USER 2 + + EXPORTED VARIABLES + + NOTE: All variables are read only. I you modify them the results may + be unpredictable. + + CharHeight - BYTE - Height of current inbuilt character set + + CharWidth - BYTE - Width of current inbuilt character set + + FirstChar - BYTE - First character of current inbuilt character set + + UserCharHeight - BYTE - Height of current user character set + + UserCharWidth - BYTE - Width of current user character set + + UserFirstCh - BYTE - First character of current user character set + + + EXPORTED FUNCTIONS + + x_text_init + ----------- + + C Prototype: extern WORD x_text_init(void); + + Initializes the Mode X text driver and sets the default font (VGA ROM 8x8) + + x_set_font + ---------- + + C Prototype: extern void x_set_font(WORD FontId); + + Select the working font where 0 = VGA ROM 8x8, 1 = VGA ROM 8x14 + 2 = User defined bitmapped font. + + WARNING: A user font must be registered before setting FontID 2 + + See Also: + + Defines for this module + + x_register_userfont + ------------------- + + C Prototype: extern void x_register_userfont(char far *UserFontPtr); + + + Register a user font for later selection. Only one user font can be + registered at any given time. Registering a user font deregisters the + previous user font. User fonts may be at most 8 pixels wide. + + USER FONT STRUCTURE + + Word: ascii code of first char in font + Byte: Height of chars in font + Byte: Width of chars in font + n*h*Byte: the font data where n = number of chars and h = height + of chars + + WARNING: The onus is on the program to ensure that all characters + drawn whilst this font is active, are within the range of + characters defined. + + x_put_char + ---------- + + C Prototype: extern void x_put_char(char ch,WORD X,WORD Y,WORD PgOffs, + WORD Color); + + Draw a text character at the specified location with the specified + color. + + ch - char to draw + x,y - screen coords at which to draw ch + ScrnOffs - Starting offset of page on whih to draw + Color - Color of the text + + WARNING: InitTextDriver must be called before using this function + + + **** NOTE **** + + The file "xprintf.c" implements a printf style formatted output function + + x_printf + -------- + + C Prototype: void x_printf(int x,int y,unsigned ScrnOffs,int color, + char *ln,...); + + x,y - screen coords at which to draw ch + ScrnOffs - Starting offset of page on whih to draw + Color - Color of the text + + Parameters beyond Color conform to the standard printf parameters. + + x_bgprintf + ---------- + + C Prototype: void x_bgprintf(int x,int y,unsigned ScrnOffs,int fgcolor, + int bgcolor, char *ln,...); + + x,y - screen coords at which to draw ch + ScrnOffs - Starting offset of page on whih to draw + fgcolor - Color of the text foreground + bgcolor - Color of the text background + + Parameters beyond bgolor conform to the standard printf parameters. + + + x_get_char_width + ---------------- + + C Prototype: unsigned int x_get_char_width(char ch) + + ch - character to get width of + +-------------------------------------------------------------------------- +MODULE XPBITMAP +-------------------------------------------------------------------------- + + This module implements a set of functions to operate on planar bitmaps. + Planar bitmaps as used by these functions have the following structure: + + BYTE 0 The bitmap width in bytes (4 pixel groups) range 1..255 + BYTE 1 The bitmap height in rows range 1..255 + BYTE 2..n1 The plane 0 pixels width*height bytes + BYTE n1..n2 The plane 1 pixels width*height bytes + BYTE n2..n3 The plane 2 pixels width*height bytes + BYTE n3..n4 The plane 3 pixels width*height bytes + + These functions provide the fastest possible bitmap blts from system ram to + to video and further, the single bitmap is applicable to all pixel + allignments. The masked functions do not need separate masks since all non + zero pixels are considered to be masking pixels, hence if a pixel is 0 the + corresponding screen destination pixel is left unchanged. + + + ASM SOURCES + + xpbitmap.asm xpbitmap.inc xlib.inc model.inc + + C HEADER FILE + + xpbitmap.h + + EXPORT FUNCTIONS + + x_put_masked_pbm + ---------------- + + C Prototype: extern void x_put_masked_pbm(WORD X,WORD Y,WORD ScrnOffs, + BYTE far * Bitmap); + + Mask write a planar bitmap from system ram to video ram. All zero source + bitmap bytes indicate destination byte to be left unchanged. + + Source Bitmap structure: + + Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1).., + Bitmap data (plane 2)..,Bitmap data (plane 3).. + + NOTE: width is in bytes ie lots of 4 pixels + + LIMITATIONS: No clipping is supported + Only supports bitmaps with widths which are a multiple of + 4 pixels + + See Also: XBMTOOLS module for linear <-> planar bitmap conversion + functions. + + x_put_pbm + --------- + + C Prototype: extern void x_put_pbm(WORD X, WORD Y, WORD ScrnOffs, + BYTE far * Bitmap); + + Write a planar bitmap from system ram to video ram. + + Source Bitmap structure: + + Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1).., + Bitmap data (plane 2)..,Bitmap data (plane 3).. + + NOTE: width is in bytes ie lots of 4 pixels + + LIMITATIONS: No clipping is supported + Only supports bitmaps with widths which are a multiple of + 4 pixels + + + See Also: XBMTOOLS module for linear <-> planar bitmap conversion + functions. + + x_get_pbm + --------- + + C Prototype: extern void x_get_pbm(WORD X, WORD Y,BYTE Bw,BYTE Bh, + WORD ScrnOffs, BYTE far * Bitmap); + + Read a planar bitmap to system ram from video ram. + + Source Bitmap structure: + + Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1).., + Bitmap data (plane 2)..,Bitmap data (plane 3).. + + NOTE: width is in bytes ie lots of 4 pixels + + LIMITATIONS: No clipping is supported + Only supports bitmaps with widths which are a multiple of + 4 pixels + + + See Also: XBMTOOLS module for linear <-> planar bitmap conversion + functions. + +-------------------------------------------------------------------------- +MODULE XPBMCLIP +-------------------------------------------------------------------------- + + This module implements a similar set of functions to operate on planar + bitmaps as "XPBITMAP" but incorporates clipping to a user defined + clipping rectangle (which is set by "x_set_cliprect" in module xmain). + + The planar bitmap format is identical to the above module + + There are three variations of the functions in XPBITMAP in this module + identified by the three function name extensions: _clipx, _clipy _clipxy. + Because speed is critical in games programming you do not want to be + checking for clipping if not necessary thus for sprites that move only + horizontally you would use the _clipx version of the put function, + for sprites that move vertically you would use the _clipy version and for + sprites that move both directions you would use the clipxy version. + Keep in mind also that the clipping components of these functions assume + that the clipping rectangle is equal to or larger than the size of the + bitmap ie. if a bitmap is top clipped, it is assumed that the bitmap's + bottom is not also clipped. Similarly with horizontal clipping. + + Note: performance in decreasing order is as follows. + _clipy,_clipx,_clipxy with masked puts being slower than unmasked + puts + + Horizontal clipping is performed to byte boundaries (4 pixels) rather than + pixels. This allows for the fastest implementation of the functions. It is + not such a handicap because for one, your screen width a multiple of 4 + pixels wide and for most purposes it is the screen edges that form the + clipping rectangle. + + Following is an example of setting a clipping rectangle to the logical + screen edges: + + x_set_cliprect(0,0,ScrnLogicalByteWidth,ScrnLogicalHeight) + + NOTE: the functions now return a value; + 1 if clipped image is fully clipped (ie no portion of it + appears on the screen) otherwise it returns 0 + + + ASM SOURCES + + xpbmclip.asm xpbmclip.inc xlib.inc model.inc + + C HEADER FILE + + xpbmclip.h + + EXPORT FUNCTIONS + + x_put_pbm_clipx + --------------- + x_put_pbm_clipy + --------------- + x_put_pbm_clipxy + ---------------- + x_put_masked_pbm_clipx + ---------------------- + x_put_masked_pbm_clipy + ---------------------- + x_put_masked_pbm_clipxy + ----------------------- + + For a detailed description of parameters etc. see equivalent functions + in module "XPBITMAP". + + +-------------------------------------------------------------------------- +MODULE XCBITMAP +-------------------------------------------------------------------------- + + XCBITMAP: + The Care and Feeding of Compiled Masked Blits + by Matthew MacKenzie + +The XCBITMAP module of the Xlib library is made up of the files +XCBITMAP.ASM, XCBITMAP.INC, and XCBITMAP.H. + +The XCBITMAP module is small, containing only three procedures: + o x_compile_bitmap compiles your bitmap into native code which writes + to the VGA screen in an X mode. + o x_put_cbitmap converts X and Y coordinates into a location on the + screen, sets up the necessary VGA registers, and executes the compiled + bitmap as a subroutine. + o x_sizeof_cbitmap takes a planar bitmap and returns an integer equal to + the size of the compiled bitmap which the planar bitmap would produce. + It is essentially a lobotomized version of x_compile_bitmap, with all + the code generation replaced with a size counter. + + x_compile_bitmap scans through a source bitmap and generates 8086 +instructions to plot every nonzero pixel. It is designed to be used +before the action begins rather than on-the-fly. The compiled bitmap +contains no branches, and no reference to the zero (transparent) pixels. +Where two pixels are exactly four columns apart they are plotted with a +single 16-bit store, and the VGA MAP_MASK register will be set at most +four times. As a result your bitmap may run several times faster than a +traditional memory-to-VGA masked blit routine. + There is no way to perform clipping on these bitmaps, or to plot a +pixel of color zero. + x_compile_bitmap works with bitmaps in the standard Xlib planar bitmap +format. On a time scale of 60 frames per second, it is actually relatively +slow. Since a compiled bitmap is relocatable you may just want to have it +saved to disk, and not include the source bitmap in your program at all. + The source bitmap format is an array of bytes, a little like this: + +char eye[] ={4, 7, /* four byte columns across, seven rows tall */ + 0, 0, 0, 0, 9, 1, 1, 1, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 1, 1, 1, 4, 4, 9, 9, 0, 0, 0, 0, 0, + 0, 9, 9, 1, 2, 0, 0, 4, 4, 1, 9, 9, 0, 0, 0, 0, + 9, 9, 9, 1, 0, 0, 0, 0, 1, 1, 9, 9, 9, 0, 0, 0, + 0, 9, 9, 1, 2, 0, 0, 2, 1, 1, 9, 9, 0, 0, 0, 0, + 0, 0, 9, 9, 1, 1, 1, 1, 1, 9, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 1, 1, 1, 9, 0, 0, 0, 0, 0, 0, 0}; + + This is actually a linear bitmap, which is the wrong format for +compilation, but is easier on human eyes. Use the module XBMTOOLS to +convert linear bitmaps into planar bitmaps, and vice-versa. + To compile this image for a mode 360 pixels (90 byte columns) across: + +char planar_eye[4*7 + 2]; +char far * EyeSize; + +(void) x_bm_to_pbm((char far *) eye, (char far *) planar_eye); +EyeSize = x_sizeof_cbitmap((far char *) planar_eye); +CompiledEye = farmalloc(EyeSize); +(void) x_compile_bitmap(90, (far char *) planar_eye, CompiledEye); + + Notice that both buffers must exist beforehand. Since x_compile_bitmap +returns the size of the compiled code, in bytes, you can reallocate the +bitmap immediately to the right size if using x_sizeof_xbitmap seems +inconvenient (reallocation may even be faster, though using the function is +cleaner). The pointers are 32-bit because compiled bitmaps take so much +space: they are at one end of the speed-versus-memory spectrum. A good +rule of thumb is to allocate (3.5 x buffer-height x buffer-width) + 25 +bytes (rounding up ;-), then pare your bitmap down when you find out how +much space you've actually used. + Since the compiled bitmap has to fit within one segment of memory, it +cannot contain more than about 19,000 pixels. This will not be a +limitation for most sane programmers. If you are not a sane programmer try +splitting your huge, unwieldy image up into smaller parts -- you can use +the same gigantic bitmap if you divide it into horizontal slices for +compilation. For that matter, dividing the source up that way will let +you use a source bitmap large than 64K, which is an even sicker idea... + Back to business. A bitmap is compiled for only one width of screen. +If you are using a logical screen larger than your physical screen, call +the bitmap compiler with the logical width -- the important thing is the +number of bytes per line. Notice that you do not have to be in a graphics +mode to use this routine. This allows you to develop and compile bitmaps +separately, with whatever utility programs you might cook up. + + The final function is x_put_cbitmap. To plot our eye at (99,4), on +the page which starts at location 0: +x_put_cbitmap(99, 4, 0, CompiledEye); + This function depends on the global variable ScrnLogicalByteWidth from +the module XMAIN, which should be the same number as the column parameter +you used to compile your bitmap. + The XCBITMAP module supports memory-to-VGA blits only. Xlib also +includes non-masking routines which can quickly save and restore the +background screen behind your bitmap, using fast string operations. + + This module is part of the Xlib package, and is in the public domain. +If you write something which uses it, though, please send me a copy as a +courtesy -- if for no other reason so I can tilt my chair back and reflect +that it may have been worth the trouble after all. + +The included program DEMO2.C demonstrates the performance difference +between planar bitmap masked blits and compiled bitmap blits. + +-------------------------------------------------------------------------- +MODULE XCOMPPBM +-------------------------------------------------------------------------- + +Identical to XCBITMAP except that the source bitmaps are the PBM form +rather than LBM. + +FUNCTIONS + +x_compile_pbm +------------- +x_sizeof_cpbm +------------- + +See XCBITMAP module + +-------------------------------------------------------------------------- +MODULE XVBITMAP +-------------------------------------------------------------------------- + +The XVBITMAP module implements yet another type of bitmap to complement +planar and compiled bitmaps, VRAM based bitmaps. If a 4 cylinder car is +analagous to planar bitmaps, that is thrifty on memory consumption but low +performance and and a V8 is analagous to Compiled bitmaps, memory guzzlers +that really fly, then VRAM based bitmaps are the 6 cylinder modest performers +with acceptable memory consumption. + +To summarise their selling points, VBM's are moderately fast with fair memory +consumption, and unlike compiled bitmaps, can be clipped. The disadvantages +are that they are limited by the amount of free video ram and have a complex +structure. + +The VRAM bitmap format is rather complex consisting of components stored in +video ram and components in system ram working together. This complexity +necessitates the existence of a creation function "x_make_vbm" which takes +an input linear bitmap and generates the equivalent VBM (VRAM Bit Map). + +VBM structure: + + WORD 0 Size Total size of this VBM structure in bytes + WORD 1 ImageWidth Width in bytes of the image (for all alignments) + WORD 2 ImageHeight Height in scan lines of the image + + WORD 3 Alignment 0 ImagePtr Offset in VidRAM of this aligned image + +--WORD 4 MaskPtr Offset (within this structure's DS) of + | . alignment masks + | . + | . + | WORD 9 Alignment 3 ImagePtr Offset in VidRAM of this aligned image + +|--WORD 10 MaskPtr Offset (within this structure's DS) of + || alignment masks + || + |+->BYTE 21 (WORD 11) -------+-- Image masks for alignment 0 + | . | + | . | + | BYTE 21 + ImageWidth*ImageHeight -----+ + | + | . + | . (similaly for alignments 1 - 2 ) + | . + | + +-->BYTE 21 + 3*ImageWidth*ImageHeight + 1-+-- Image masks for alignment 3 + . | + . | + BYTE 21 + 4*(ImageWidth*ImageHeight) --+ + + . + . + << Similarly for alignments 2 and 3 >> + . + . + BYTE 21 + 4*(ImageWidth*ImageHeight) + ------------- + + (And dont forget the corresponding data in video ram) + +You can see for yourself the complexity of this bitmap format. The image +is stored in video ram in its 4 different alignments with pointers to these +alignments in the VBM. Similarly there are 4 alignments of the corresponding +masks within the VBM itself (towards the end). The mask bytes contain the +plane settings for the corresponding video bytes so that one memory move can +move up to 4 pixels at a time (depending on the mask settings) using the +VGA's latches, theoretically giving you a 4x speed improvement over +conventional blits like the ones implemented in "XPBITMAP". In actual fact +its anywhere between 2 and 3 due to incurred overheads. + +These bitmaps are more difficult to store in files than PBM'S and CBM's but +still posible with a bit of work, so do not dismiss these as too difficult +to use. Consider all the bitmap formats carefully before deciding on which +to use. There may even be situations that a careful application of all three +types would be most effective ie. compiled bitmaps for Background tiles and +the main game character (which never need clipping), VRAM based bitmaps for +the most frequently occuring (oponent, alien etc) characters which get +clipped as they come into and leave your current location and planar bitmaps +for smaller or less frequently encountered characters. + +ASM SOURCES + + xvbitmap.asm xvbitmap.inc xlib.inc model.inc + xmakevbm.c - Additional C module implementing creation function + + C HEADER FILE + + xvbitmap.h + + EXPORTED FUNCTIONS + + x_make_vbm + ---------- + + C Prototype: extern char far * x_make_vbm(char far *lbm, WORD *VramStart); + + Create the VBM from the given linear bitmap and place the image alignments + in video ram starting at the offset in the variable pointed to by + "VramStart". "VramStart" is then updated to point to the next free VRAM byte + (just after the last byte of the image alignments). Usually you will point + "VramStart" to "NonVisual_Offs". + + lbm Pointer to the input linear bitmap + VramStart Pointer to variable containing Offset of first free VRAM byte + + x_put_masked_vbm + ---------------- + + C Prototype: extern int x_put_masked_vbm(int X, int Y, WORD ScrnOffs, + BYTE far * VBitmap); + + Draw a VRAM based bitmap at (X,Y) relative to the screen with starting + offset "ScrnOffs". + + Returns 1 if clipped image is fully clipped (ie no portion of it + appears on the screen) otherwise it returns 0 + + x_put_masked_vbm_clipx + ---------------------- + x_put_masked_vbm_clipy + ---------------------- + x_put_masked_vbm_clipxy + ----------------------- + + Clipping versions of "x_put_masked_vbm". + + See XPBMCLIP for more details on the type of clipping used as it is + identical to XVBITMAP. + +-------------------------------------------------------------------------- +MODULE XMOUSE +-------------------------------------------------------------------------- +The XMOUSE module implements very basic mouse handling functions. The way +in which it operates is by installing an event handler function during +initialization which subsequently intercepts and processes mouse events and +automatically updates status variables such as mouse position and button +pressed status. It does not support the full functionality of: + + SPLIT SCREENS + SCROLLED WINDOWS + VIRTUAL WINDOWS + +This was done to primarily prevent unecessary impedences to performance, +since the mouse handler function has the potential to degrade performance. +It also saves me alot of coding which I was too lazy to do. + +Programs communicate with the mouse driver as with other devices, through +an interrupt vector namely 33h. On generating an interrupt, the mouse driver +expects a function number in AX and possibly other parameters in other +registers and returns information via the registers. A brief description +of the mouse functions follows: + + -------------------------------------- + + MS Mouse Driver Functions + + Mouse Initialization 0 + Show Cursor 1 + Hide Cursor 2 + Get Mouse Position & Button Status 3 + Set Mouse Cursor Position 4 + Get Button Press Information 5 + Get Button Release Information 6 + Set Min/Max Horizontal Position 7 + Set Min/Max Vertical Position 8 + Define Graphics Cursor Block 9 + Define Text Cursor 10 + Read Mouse Motion Counters 11 + Define Event Handler 12 + Light Pen Emulation Mode ON 13 + Light Pen Emulation Mode OFF 14 + Set Mouse Mickey/Pixel Ratio 15 + Conditional Hide Cursor 16 + Set Double-Speed Threshold 19 + -------------------------------------- + +In practice only afew of these functions are used and even fewer when the +mouse status is monitored by an event handler function such as is used in +this module. + +The most important thing to note when using the mouse module is that the +mouse event handler must be removed before exiting the program. It is a good +idea to have an exit function (see the C "atexit" function) and include the +line "x_mouse_remove();" along with any other pre-exit cleanup code. + + + ASM SOURCES + + xmouse.asm xlib.inc model.inc + + C HEADER FILE + + xmouse.h + + EXPORTED VARIABLES + + MouseInstalled - WORD - Indicates whether mouse handler installed + MouseHidden - WORD - Indicates whether mouse cursor is hidden + MouseButtonStatus - WORD - Holds the mouse button status + MouseX - WORD - Current X position of mouse cursor + MouseY - WORD - Current Y position of mouse cursor + MouseFrozen - WORD - Disallows position updates if TRUE + MouseColor - BYTE - The mouse cursors colour + + EXPORTED FUNCTIONS + + x_mouse_init + ------------ + + C Prototype: int x_mouse_init() + + Initialize the mouse driver functions and install the mouse event handler + function. This is the first function you must call before using any of the + mouse functions. This mouse code uses the fastest possible techniques to + save and restore mouse backgrounds and to draw the mouse cursor. + + WARNING: This function uses and updates "NonVisual_Offset" to allocate + video ram for the saved mouse background. + + LIMITATIONS: No clipping is supported horizontally for the mouse cursor + No validity checking is performed for NonVisual_Offs + + **WARNING** You must Hide or at least Freeze the mouse cursor while drawing + using any of the other XLIB modules since the mouse handler may + modify vga register settings at any time. VGA register settings + are not preserved which will result in unpredictable drawing + behavior. If you know the drawing will occur away from the + mouse cursor set MouseFrozen to TRUE (1), do your drawing + then set it to FALSE (0). Alternatively call "x_hide_mouse", + perform your drawing and then call "x_show_mouse". Another + alternative is to disable interrupts while drawing but usually + drawing takes up alot of time and having interrupts disabled + for too long is not a good idea. + + x_define_mouse_cursor + --------------------- + + C Prototype: + void x_define_mouse_cursor(char far *MouseDef, unsigned char MouseColor) + + MouseDef - a pointer to 14 characters containing a bitmask for all the + cursor's rows. + MouseColor - The colour to use when drawing the mouse cursor. + + Define a mouse cursor shape for use in subsequent cursor redraws. XMouse + has a hardwired mouse cursor size of 8 pixels across by 14 pixels down. + + WARNING: This function assumes MouseDef points to 14 bytes. + + Note: Bit order is in reverse. ie bit 7 represents pixel 0 .. + bit 0 represents pixel 7 in each "MouseDef" byte. + + x_show_mouse + ------------ + + C Prototype: void x_show_mouse() + + Makes the cursor visible if it was previously hidden. + See Also: "x_hide_mouse". + + x_hide_mouse + ------------ + + C Prototype: void x_hide_mouse() + + Makes the cursor hidden if it was previously visible. + See Also: "x_show_mouse". + + x_mouse_remove + -------------- + + C Prototype: void x_mouse_remove() + + Stop mouse event handling and remove the mouse handler. + + NOTE: This function MUST be called before quitting the program if + a mouse handler has been installed + + x_position_mouse + ---------------- + + C Prototype void x_position_mouse(int x, int y) + + Positions the mouse cursor at the specified location + + x_mouse_window + ------------ + + C Prototype: void x_mouse_window(int x0, int y0, int x1, int y1) + + Defines a mouse window. + + x_update_mouse + -------------- + + C Prototype: void x_update_mouse() + + Forces the mouse position to be updated and cursor to be redrawn. + Note: this function is useful when you have set "MouseFrozen" to true. + Allows the cursor position to be updated manually rather than + automatically by the installed handler. + + +-------------------------------------------------------------------------- +MODULE XBMTOOLS +-------------------------------------------------------------------------- + + This module implements a set of functions to convert between planar + bitmaps and linear bitmaps. + + PLANAR BITMAPS + + Planar bitmaps as used by these functions have the following structure: + + BYTE 0 The bitmap width in bytes (4 pixel groups) range 1..255 + BYTE 1 The bitmap height in rows range 1..255 + BYTE 2..n1 The plane 0 pixels width*height bytes + BYTE n1..n2 The plane 1 pixels width*height bytes + BYTE n2..n3 The plane 2 pixels width*height bytes + BYTE n3..n4 The plane 3 pixels width*height bytes + + as used by x_put_pbm, x_get_pbm, x_put_masked_pbm. + + LINEAR BITMAPS + + Linear bitmaps have the following structure: + + BYTE 0 The bitmap width in pixels range 1..255 + BYTE 1 The bitmap height in rows range 1..255 + BYTE 2..n The width*height bytes of the bitmap + + ASM SOURCES + + xbmtools.asm xpbmtools.inc model.inc + + C HEADER FILE + + xbmtools.h + + MACROS + + BM_WIDTH_ERROR + + LBMHeight(lbitmap) - Height of linear bitmap "lbitmap" + LBMWidth(lbitmap) - Width of linear bitmap "lbitmap" + PBMHeight(pbitmap) - Height of planar bitmap "pbitmap" + PBMWidth(pbitmap) - Width of planar bitmap "pbitmap" + + LBMPutPix(x,y,lbitmap,color) - set pixel (x,y) colour in linear bitmap + LBMGetPix(x,y,lbitmap) - colour of pixel (x,y) in linear bitmap + + EXPORT FUNCTIONS + + x_pbm_to_bm + ------------ + C Prototype: extern int x_pbm_to_bm(char far * source_pbm, + char far * dest_bm); + + This function converts a bitmap in the planar format to the linear format + as used by x_compile_bitmap. + + WARNING: the source and destination bitmaps must be pre - allocated + + NOTE: This function can only convert planar bitmaps that are suitable. + If the source planar bitmap's width (per plane) is >= 256/4 + it cannot be converted. In this situation an error code + BM_WIDTH_ERROR. On successful conversion 0 is returned. + + x_bm_to_pbm + ------------ + C Prototype: extern int x_bm_to_pbm(char far * source_pbm, + char far * dest_bm); + + This function converts a bitmap in the linear format as used by + x_compile_bitmap to the planar formap. + + WARNING: the source and destination bitmaps must be pre - allocated + + NOTE: This function can only convert linear bitmaps that are suitable. + If the source linear bitmap's width is not a multiple of 4 + it cannot be converted. In this situation an error code + BM_WIDTH_ERROR. On successful conversion 0 is returned. + diff --git a/16/xlib/xlibref2.doc b/16/xlib/xlibref2.doc new file mode 100755 index 00000000..c8aea802 --- /dev/null +++ b/16/xlib/xlibref2.doc @@ -0,0 +1,1097 @@ +PART 2 of 2 +----------------------------------------------------------------------------- + + ********* XLIB - Mode X graphics library **************** + ********* **************** + ********* Written By Themie Gouthas **************** + ********* **************** + ********* egg@dstos3.dsto.gov.au **************** + ********* teg@bart.dsto.gov.au **************** + + Some of the code in this library has been contributed by : + + Matthew MacKenzie - matm@eng.umd.edu + + and others. See individual modules. + + I informally reserve all rights to the code in XLIB + Rights to contributed code is also assumed to be reserved by + the original authors. +----------------------------------------------------------------------------- +MODULE XCLIPPBM note: VERY SIMILAR to XPBMCLIP +This module implements blits of clipped planar bitmaps. Blits are +clipped to pixels, both horizontally. This makes the unmasked blit +function here slightly slower than the equivalent functions in the +XPBMCLIP module. +-------------------------------------------------------------------------- + XCLIPPBM: + Blits and Pieces + by Matthew MacKenzie + +The XCLIPPBM module contains clipping versions of two of the three routines +in the XPBITMAP module: + o x_clip_pbm transfers a planar bitmap to the screen, clipping off any + part outside a bounding box. + o x_clip_masked_pbm does the same thing, but transfers only nonzero + pixels. + + The planar bitmap format is described elsewhere. Here we will look at +the clipping itself, since it is the only distinguishing feature of this +module. + The bounding box is made up of four integers, TopBound, BottomBound, +LeftBound, and RightBound. Unlike most global variables in Xlib, these are +meant to be written to. In fact, they start out uninitialized. Be sure to +set them before you try plotting any clipped bitmaps. + Note that these are not the same variables which are used in the other +clipping modules in Xlib. This is because the two systems are incompatible: +the other modules clip horizontally to columns while this one clips to +pixels. As you might have guessed, those functions and these were developed +in different hemispheres of the planet... + If it's any consolation, this does give you two independent +bounding boxes to futz with, should the mood visit you. + Bitmaps cannot go outside the perimeter of the bounding box, but they +can overlap it. If TopBound equals BottomBound, for example, a horizontal +slice of a bitmap may still be plotted. It is safe to turn the box "inside +out" to make sure nothing will be plotted -- this is the first thing each +routine checks for. + To plot a bitmap, minus its zero pixels, minus anything outside the +bounding box: + +x_clip_masked_pbm (int X, int Y, int ScreenOffs, char far * Bitmap); + + The arguments are in the same order as those for x_put_masked_pbm in +the module XPBITMAP. The bounding box is relative to the given +ScreenOffs(et). This lets you perform page flipping without worrying about +what screen you are clipping to -- it's always the current screen. The +bitmap itself, of course, is not affected; clipping is performed on-the- +fly. Both functions return an integer which indicates whether any part +of the bitmap was inside the bounding box. If the entire bitmap was +outside, a 1 is returned; otherwise, a 0. + The third function in XPBITMAP, for which this module has no +equivalent, copies from video RAM to system RAM. The absence of such a +routine may seem at first like a disadvantage -- but this, like so many +things in this life, is an illusion. You can use the unclipped routine, +and clip the bitmap when you want to plot it back onto the screen. + + ASM SOURCES + + xclippbm.asm xclippbm.inc xlib.inc model.inc + + C HEADER FILE + + xclippbm.h + + EXPORTED VARIABLES + + TopBound - int + BottomBound - int + LeftBound - int + RightBound - int + + EXPORTED FUNCTIONS + + x_clip_pbm + ---------- + C Prototype: extern int x_clip_pbm (int X, int Y, int ScreenOffs, char + far * Bitmap); + + Copies a planar bitmap from SRAM to VRAM, with clipping. If the entire + bitmap turns out to be outside the bounding box, this function returns + a 1; otherwise it returns a 0. + + x_clip_masked_pbm + ----------------- + C Prototype: extern int x_clip_masked_pbm (int X, int Y, + int ScreenOffs, char far * Bitmap); + + Copies a planar bitmap from SRAM to VRAM, with clipping -- 0 bytes + in the bitmap are not copied. If the entire bitmap turns out to be + outside the bounding box, this function returns a 1; otherwise, + it returns a 0. + + +-------------------------------------------------------------------------- +MODULE XMOUSE +-------------------------------------------------------------------------- +The XMOUSE module implements very basic mouse handling functions. The way +in which it operates is by installing an event handler function during +initialization which subsequently intercepts and processes mouse events and +automatically updates status variables such as mouse position and button +pressed status. It does not support the full functionality of: + + SPLIT SCREENS + SCROLLED WINDOWS + VIRTUAL WINDOWS + +This was done to primarily prevent unecessary impedences to performance, +since the mouse handler function has the potential to degrade performance. +It also saves me alot of coding which I was too lazy to do. + +Programs communicate with the mouse driver as with other devices, through +an interrupt vector namely 33h. On generating an interrupt, the mouse driver +expects a function number in AX and possibly other parameters in other +registers and returns information via the registers. A brief description +of the mouse functions follows: + + -------------------------------------- + + MS Mouse Driver Functions + + Mouse Initialization 0 + Show Cursor 1 + Hide Cursor 2 + Get Mouse Position & Button Status 3 + Set Mouse Cursor Position 4 + Get Button Press Information 5 + Get Button Release Information 6 + Set Min/Max Horizontal Position 7 + Set Min/Max Vertical Position 8 + Define Graphics Cursor Block 9 + Define Text Cursor 10 + Read Mouse Motion Counters 11 + Define Event Handler 12 + Light Pen Emulation Mode ON 13 + Light Pen Emulation Mode OFF 14 + Set Mouse Mickey/Pixel Ratio 15 + Conditional Hide Cursor 16 + Set Double-Speed Threshold 19 + -------------------------------------- + +In practice only afew of these functions are used and even fewer when the +mouse status is monitored by an event handler function such as is used in +this module. + +The most important thing to note when using the mouse module is that the +mouse event handler must be removed before exiting the program. It is a good +idea to have an exit function (see the C "atexit" function) and include the +line "x_mouse_remove();" along with any other pre-exit cleanup code. + +See also: XDETECT for mouse detection. + + ASM SOURCES + + xmouse.asm xlib.inc model.inc + + C HEADER FILE + + xmouse.h + + EXPORTED VARIABLES + + MouseInstalled - WORD - Indicates whether mouse handler installed + MouseHidden - WORD - Indicates whether mouse cursor is hidden + MouseButtonStatus - WORD - Holds the mouse button status + MouseX - WORD - Current X position of mouse cursor + MouseY - WORD - Current Y position of mouse cursor + MouseFrozen - WORD - Disallows position updates if TRUE + MouseColor - BYTE - The mouse cursors colour + + EXPORTED FUNCTIONS + + x_mouse_init + ------------ + + C Prototype: int x_mouse_init() + + Initialize the mouse driver functions and install the mouse event handler + function. This is the first function you must call before using any of the + mouse functions. This mouse code uses the fastest possible techniques to + save and restore mouse backgrounds and to draw the mouse cursor. + + WARNING: This function uses and updates "NonVisual_Offset" to allocate + video ram for the saved mouse background. + + LIMITATIONS: No clipping is supported horizontally for the mouse cursor + No validity checking is performed for NonVisual_Offs + + **WARNING** You must Hide or at least Freeze the mouse cursor while drawing + using any of the other XLIB modules since the mouse handler may + modify vga register settings at any time. VGA register settings + are not preserved which will result in unpredictable drawing + behavior. If you know the drawing will occur away from the + mouse cursor set MouseFrozen to TRUE (1), do your drawing + then set it to FALSE (0). Alternatively call "x_hide_mouse", + perform your drawing and then call "x_show_mouse". Another + alternative is to disable interrupts while drawing but usually + drawing takes up alot of time and having interrupts disabled + for too long is not a good idea. + + x_define_mouse_cursor + --------------------- + + C Prototype: + void x_define_mouse_cursor(char far *MouseDef, unsigned char MouseColor) + + MouseDef - a pointer to 14 characters containing a bitmask for all the + cursor's rows. + MouseColor - The colour to use when drawing the mouse cursor. + + Define a mouse cursor shape for use in subsequent cursor redraws. XMouse + has a hardwired mouse cursor size of 8 pixels across by 14 pixels down. + + WARNING: This function assumes MouseDef points to 14 bytes. + + Note: Bit order is in reverse. ie bit 7 represents pixel 0 .. + bit 0 represents pixel 7 in each "MouseDef" byte. + + x_show_mouse + ------------ + + C Prototype: void x_show_mouse() + + Makes the cursor visible if it was previously hidden. + See Also: "x_hide_mouse". + + x_hide_mouse + ------------ + + C Prototype: void x_hide_mouse() + + Makes the cursor hidden if it was previously visible. + See Also: "x_show_mouse". + + x_remove_mouse + -------------- + + C Prototype: void x_remove_mouse() + + Stop mouse event handling and remove the mouse handler. + + NOTE: This function MUST be called before quitting the program if + a mouse handler has been installed + + x_position_mouse + ---------------- + + C Prototype void x_position_mouse(int x, int y) + + Positions the mouse cursor at the specified location + + x_update_mouse + -------------- + + C Prototype: void x_update_mouse() + + Forces the mouse position to be updated and cursor to be redrawn. + Note: this function is useful when you have set "MouseFrozen" to true. + Allows the cursor position to be updated manually rather than + automatically by the installed handler. + +-------------------------------------------------------------------------- +MODULE XCIRCLE +-------------------------------------------------------------------------- + XCIRCLE: + Wheel Have to See About That + by Matthew MacKenzie + +The XCIRCLE module contains two functions, neither of which should be +a big mystery: + o x_circle, oddly enough, draws a circle. + o x_filled_circle does too, only the circle is filled (in some + libraries this is called a disc). + + The word `circle' here refers to a round thing which is as many +pixels tall as across. It only looks like a circle in 320x240 mode -- +the original mode X -- and in 376x282 mode. + In both functions, the circle is specified by the coordinates of the +upper-left-hand corner of the smallest box which holds it, and the +diameter. Some circle functions have you specify a center point; +this system is kind of odd because a circle with an even diameter does +not have a particular pixel for a center. Every circle, on the other +hand, has a box with an upper-left corner. + No bounds are checked. A diameter of zero will draw nothing, and +a negative diameter will blow your VGA board into hundreds of thousands +of tiny little smoldering fragments. Neither function supports clipping. + The calculation of the circle is based on an algorithm described +by Michael P. Lindner in a letter to the editor on page 8 of Dr. Dobb's +Journal #169 (October 1990). The algorithm has been rearranged to +allow drawing and moving the plots in the eight octants to be performed +in one step, so that each pixel does not have to be loaded into the CPU +twice. x_filled_circle does not take advantage of this optimization +because it handles different parts of each plot at different times. + + ASM SOURCES + + xcircle.asm xcircle.inc xlib.inc model.inc + + C HEADER FILE + + xcircle.h + + EXPORTED FUNCTIONS + + x_circle + -------- + C Prototype: extern void x_circle (WORD Left, WORD Top, WORD Diameter, + WORD Color, WORD ScreenOffs); + + Draws a circle with the given upper-left-hand corner and diameter, + which are given in pixels. + + + x_filled_circle + --------------- + C Prototype: extern void x_filled_circle (WORD Left, WORD Top, + WORD Diameter, WORD Color, WORD ScreenOffs); + + Draws a filled circle with the given upper-left-hand corner and + diameter. + + +-------------------------------------------------------------------------- +MODULE XDETECT +-------------------------------------------------------------------------- + + This module implements a set of functions to detect the PC's hardware + configuration. + + ASM SOURCES + + xdetect.asm xdetect.inc model.inc + + C HEADER FILE + + xdetect.h + + EXPORTED MACROS + + I8086 0 + I80186 1 + I80286 2 + I80386 3 + + NoGraphics 0 + MDA 1 + CGA 2 + EGAMono 3 + EGAColor 4 + VGAMono 5 + VGAColor 6 + MCGAMono 7 + MCGAColor 8 + + BUS_MOUSE 1 + SERIAL_MOUSE 2 + INPORT_MOUSE 3 + PS2_MOUSE 4 + HP_MOUSE 5 + + + EXPORT VARIABLES + + MouseButtonCount - WORD - The number of buttons on the detected mouse + MouseVersion - WORD - Mouse driver version (High byte = Major version + Low byte = minor version) + MouseType - BYTE - The mouse type + MouseIRQ - BYTE - The IRQ number used by the mouse driver + + EXPORT FUNCTIONS + + + x_graphics_card + --------------- + C Prototype: extern int x_graphics_card(); + + This function returns the type of graphics card installed. See defines + above. + + x_processor + ----------- + C Prototype: extern int x_processor(); + + This function returns the type of processor installed. A 486 registers + as a 386. See defines above. + + x_coprocessor + ------------- + C Prototype: extern int x_coprocessor(); + + This function returns 1 of a numeric co-processor is present, 0 if not. + The type is not detected but it's mnot really necessary as the processor + type usually determines the numeric coprocessor type + + x_mousedriver + ------------- + C Prototype: extern int x_mousedriver(); + + This function returns 1 of a mouse driver is installed, 0 otherwise. + If a mouse driver is detected the mouse related variable (above) are + set accordingly. + +-------------------------------------------------------------------------- +MODULE XFILEIO +-------------------------------------------------------------------------- + + Handle based file I/O functions. + + See any good DOS programming reference for more information on int 21h + DOS services. + + ASM SOURCES + + xfileio.asm xfileio.inc model.inc + + C HEADER FILE + + xfileio.h + + EXPORTED MACROS + + file access modes + + F_RDONLY + F_WRONLY + F_RDWR + + seek codes + + SEEK_START + SEEK_CURR + SEEK_END + + file error value + + FILE_ERR + + EXPORT FUNCTIONS + + f_open + ------ + C Prototype: extern int f_open(char * filename, char access); + + Opens a file according to the access char: + + F_RDONLY = read only - If doesnt exist return error + F_WRONLY = write only - If doesnt exist create it otherwise clear it + F_RDWR = read/write - If doesnt exist create it + + Returns the file handle on success, FILE_ERR on failure + + + f_close + ------- + + C Prototype: extern int f_close(int handle); + + Closes the file associated with the specified handle + + Returns 0 on success, FILE_ERR on failure + + + f_read + ------ + + C Prototype: + + extern int f_read(int handle,char near * buffer, int count); + + Reads a block of count bytes from the file specified by the handle + into the near buffer + + Returns count on success, FILE_ERR on failure + + f_readfar + --------- + + C Prototype: + + extern int f_readfar(int handle,char far * buffer, int count); + + Reads a block of count bytes from the file specified by the handle + into the far buffer + + Returns count on success, FILE_ERR on failure + + + f_write + ------- + + C Prototype: extern int f_write(int handle, char near * buffer, int count); + + Writes a block of count bytes to the file specified by the handle + from the near buffer + + Returns count on success, FILE_ERR on failure + + f_writefar + ---------- + + C Prototype: extern int f_write(int handle, char far * buffer, int count); + + Writes a block of count bytes to the file specified by the handle + from the far buffer + + Returns count on success, FILE_ERR on failure + + + f_seek + ------ + + C Prototype: extern long int f_seek(int handle, long int position, + char method_code) + + Moves the file pointer according to the position and method code + + Returns file pointer position on success, FILE_ERR on failure + + + f_filelength + ------------ + + C Prototype: + + extern long int f_filelength(int handle) + + Returns the length of the file associated with the specified handle + + Returns file length on success, FILE_ERR on failure + + + f_tell + ------ + + C Prototype: + + extern long int f_tell(int handle) + + + Returns file pointer position on success, FILE_ERR on failure + +-------------------------------------------------------------------------- +MODULE XRLETOOL +-------------------------------------------------------------------------- + +This module implements a number of functions comprising an RLE encoding +decoding system. + +RLE stands for RUN LENGTH ENCODING. It is a quick simple data compression +scheme which is commonly used for image data compression or compression +of any data. Although not the most efficient system, it is fast, which is +why it is used in image storage systems like PCX. This implementation is +more efficient than the one used in PCX files because it uses 1 bit to +identify a Run Length byte as opposed to two in PCX files, but more on this +later. + +This set of functions can be used to implement your own compressed image +file format or for example compress game mapse for various levels etc. +The uses are limited by your imagination. + +I opted for trading off PCX RLE compatibility for the improved compression +efficiency. + +Here is how the data is un-compressed to give an idea of its structure. + + +STEP 1 read a byte from the RLE compressed source buffer. + +STEP 2 if has its high bit is set then the lower 7 bits represent the number + of times the next byte is to be repeated in the destination buffer. + if the count (lower 7 bits) is zero then + we have finished decoding goto STEP 5 + else goto STEP 4 + +STEP 3 Read a data from the source buffer and copy it directly to the + destination buffer. + goto STEP 1 + +STEP 4 Read a data byte from the source buffer and copy it to the destination + buffer the number of times specified by step 2. + goto STEP 1 + +STEP 5 Stop, decoding done. + +If the byte does not have the high bit set then the byte itself is transfered + to the destination buffer. + +Data bytes that have the high bit already set and are unique in the input + stream are represented as a Run Length of 1 (ie 81 which includes high bit) + followed by the data byte. + +If your original uncompressed data contains few consecutive bytes and most +have high bit set (ie have values > 127) then your so called +compressed data would require up to 2x the space of the uncompressed data, +so be aware that the compression ratio is extremely variable depending on the +type of data being compressed. + +Apologies for this poor attempt at a description, but you can look up +RLE in any good text. Alternatively, any text that describes the PCX file +structure in any depth should have a section on RLE compression. + + + + ASM SOURCES + + xrletool.asm xrletool.inc model.inc + + C HEADER FILE + + xrletool.h + + EXPORTED MACROS + + + EXPORT FUNCTIONS + + x_buff_RLDecode + --------------- + + Expands an RLE compresses source buffer to a destination buffer. + returns the size of the resultant uncompressed data. + + C PROTOTYPE: + + extern unsigned int x_buff_RLDecode(char far * source_buff, + char far * dest_buff); + + source_buff - The buffer to compress + dest_buff - The destination buffer + + WARNING: buffers must be pre allocated. + + + x_buff_RLEncode + --------------- + + RLE Compresses a source buffer to a destination buffer and returns + the size of the resultant compressed data. + + C PROTOTYPE: + + extern unsigned int x_buff_RLEncode(char far * source_buff, + char far * dest_buff,unsigned int count); + + source_buff - The buffer to compress + dest_buff - The destination buffer + count - The size of the source data in bytes + + WARNING: buffers must be pre allocated. + + x_buff_RLE_size + --------------- + + Returns the size the input data would compress to. + + C PROTOTYPE: + + extern unsigned int x_buff_RLE_size(char far * source_buff, + unsigned int count); + + source_buff - The uncompressed data buffer + count - The size of the source data in bytes + + + x_file_RLEncode + --------------- + + RLE Compresses a source buffer to an output file returning + the size of the resultant compressed data or 0 if it fails. + + C PROTOTYPE: + + extern unsigned int x_file_RLEncode(int handle, + char far * source_buff,unsigned int count); + + source_buff - The buffer to compress + handle - The file handler + count - The size of the source data in bytes + + x_file_RLDecode + --------------- + + Expands an RLE compresses file to a destination RAM buffer. + returns the size of the resultant uncompressed data. + + C PROTOTYPE: + + extern unsigned int x_buff_RLDecode(int handle, + char far * dest_buff); + + handle - Input file handle + dest_buff - The destination buffer + + + + +-------------------------------------------------------------------------- +MODULE XPOLYGON +-------------------------------------------------------------------------- + + This module implements eneral filled convex polygon and triangle + functions + + C HEADER FILE + + xpolygon.h + + TYPE DEFS + + typedef struct { + int X; + int Y; + } far VERTEX; + + + + EXPORT FUNCTIONS + + + x_triangle + ------------ + C Prototype: + + void x_triangle(int x0, int y0, int x1, int y1, int x2, int y2, + WORD color, WORD PageBase); + + This function draws a filled triangle which is clipped to the current + clipping window defined by TopClip,BottomClip,LeftClip,RightClip. + Remember: the X clipping variable are in BYTES not PIXELS so you + can only clip to 4 pixel byte boundaries. + + + x_polygon + --------- + + C Prototype: + + void x_polygon(VERTEX *vertices, int num_vertices, + WORD color, WORD PageBase); + + This function is similar to the triangle function but draws + convex polygons. The vertices are supplied in the form of a FAR + pointer. + + NOTE: a convex polygon is one such that if you draw a line from + any two vertices, every point on that line will be within the + polygon. + + This function works by splitting up a polygon into its component + triangles and calling the triangle routine above to draw each one. + Performance is respectable but a custom polygon routine might be + faster. + + +-------------------------------------------------------------------------- +MODULE XFILL +-------------------------------------------------------------------------- + + This module implements a couple of general purpose flood fill functions + functions + + C HEADER FILE + + xfill.h + + + EXPORT FUNCTIONS + + + x_flood_fill + ------------ + C Prototype: + + int x_flood_fill(int x, int y, unsigned ofs, int color); + + This function performs the familiar flood filling used by many + paint programs and of course the Borland BGI's flood fill function. + The pixel at x,y and all adjacent pixels of the same color are filled + to the new color. Filling stops when there are no more adjacent pixels + of the original pixel's color. The function returns the number of + pixels that have been filled. + + x_boundary_fill + ------------ + C Prototype: + + + int x_boundary_fill(int x,int y,unsigned ofs,int boundary,int color); + + This function is a variant of the flood fill described above. This + function, unlike the above function, can fill across color boundaries. + Filling stops when the area being filled is fully enclosed by pixels + of the color "boundary". Again, this function returns the number of + pixels filled. + +------------------------------------------------------------------------------- +MODULE VSYNC +------------------------------------------------------------------------------- + + VSYNC + + Simulated Vertical Retrace Interrupt Module + + by Tore Jahn Bastiansen + + Inspired by REND386 v3.01 by Dave Stampe and Bernie Roehl + +The xvsync module uses timer 0 to simulate a vertical retrace interrupt. +It's designed to significantly reduce the idle waiting time in Xlib. +Why simulate the VRT interrupt ? Simply because a true VRT interrupt is +not implemented on many VGA cards. Using a VRT interrupt as opposed to +polling, can result in huge performance improvements for your code and +help make animation much smoother than it would be using polling. + +Normally xlib waits for vsync when x_page_flip, x_set_start_address or +x_put_pal_??? is called. This waiting period could be better utilized to do +housekeeping calculations or whatever. The x_put_pal_??? functions also +doesn't work very smoothly in conjunction with other functions that wait for +the vertical retrace since each function introduces its own VRT delay. + +When using the vsync handler, the VRT delay is reduced to the absolute +minumum which can result in a huge performance boost for your programs. + +When using double buffering, you may still have to wait before drawing, +but you could do as much other work as possible, like this: + + x_page_flip(...) + ... + + + + ... + x_wait_start_address(); (Not needed with triple buffering) + ... + + ... + +ASM SOURCES + + xvsync.asm xmain.asm xvsync.inc xmain.inc + +C HEADER FILE + + xvsync.h + +EXPORTED VARIABLES + +VsyncPeriod - WORD -time in 1.193 us between two vsyncs + +TicksPerSecond - WORD - number of vsyncs per second + +VsyncTimerInt - long - number of vsyncs since x_install_vsync_handler was + called. Nice for game timing. + +EXPORTED FUNCTIONS + +x_install_vsync_handler +----------------------- + +C Prototype: void x_install_vsync_handler(int VrtsToSkip); + +This function installs the vsync handler using timer 0. It's called +about 100 microseconds before every vertical retrace. + +The VrtsToSkip value (>=1) defines the delay in VRT's between consecutive +physical screen start address changes, thus allowing you to limit the +maximum frame rate for page flips in animation systems. The frame rate +is calculated as Vertical refresh rate / VrtsToSkip, eg for +320x240 mode which refreshes at 60Hz a VrtsToSkip value of 3 will result +in a maximum page flipping rate of 20Hz (frames per second) + +WARNING: Be sure to remove it before exiting. + When used with a debugger, the system clock may speed up. + +x_remove_vsync_handler +---------------------- + +C Prototype: void x_remove_vsync_handler + +This routine _MUST_ be called before exiting (or aborting) the program, +or your system will crash. + +x_set_user_vsync_handler +------------------------ + +C Prototype: void x_set_user_vsync_handler(void far (*f)()); + +Installs a user routine to be called once each vertical retrace. The user +handler have its own stack of 256 bytes , so be careful with the stack +checking option in BC. +WARNING: This installs an interrupt driven handler, beware of the following: + Only 8086 registers are preserved. If you're using 386 code, save + all the 386 regs. + Don't do any drawing. + Don't call any DOS functions. + +So why use it? +Well, you can update global variables if you're careful. And it's nice for +palette animation. You can even do fades while loading from disk. You +should use this instead of installing your own int08h routine and chain +to the original. + +x_wait_start_addr +----------------- + +C Prototype: void x_wait_start_addr(void) + +You must call this function before drawing after a call to x_set_start_addr +or x_page_flip when you are using the vsync handler and not using +triple buffering. + +MODULE XMAIN additions + +EXPORTED VARIABLES + +Page2_Offs - WORD - Offset in video ram of third virtual screen. Set by + x_triple_buffer. + +WaitingPageOffs - WORD - Offset of page waiting to be invisible. Initially + set by x_set_triple_buffer but is updated by x_page_flip. This + variable is only used while triple buffering is on. + +VsyncHandlerActive - WORD - Indicates whether the vsync handler is installed. + +TripleBufferActive - WORD - Indicates whether triple-buffering is on. + Set by x_triple_buffer. + +StartAddressFlag - WORD - This flag is set if there is a new start + address waiting to be set by the vsync handler. + +WaitingStartLow - WORD - Needed by vsync handler. Keep off. +WaitingStartHigh - WORD - Needed by vsync handler. Keep off. +WaitingPelPan - WORD - Needed by vsync handler. Keep off. + +VsyncPaletteStart - WORD - Start index of video DAC register to be + updated next vsync. Set by palette functions. + +VsyncPaletteCount - WORD - Number of palette entries to be outed next + vsync. Set by palette functions. + +VsyncPaletteBuffer - BYTE[768] - Buffer containing values for the next + update of the DAC. + +EXPORTED FUNCTIONS + +x_triple_buffer +---------------- + +C Prototype: void x_triple_buffer(WORD PageHeight); + +This function behaves like x_double_buffer, but when used with +x_install_vsync_handler you can draw immediately after a page flip. +When x_page_flip is called, VisiblePageOffs is set to the page that +will be display next vsync. Until then, WaitingPageOffs will be displayed. +You can draw to HiddenPageOffs . + + + + +-------------------------------------------------------------------- +REFERENCE SECTION +-------------------------------------------------------------------- + + +REFERENCES +---------- + +In my opinion Doctor Dobbs Journal is the best reference text for +VGA Mode X graphics: + +Issue 178 Jul 1991 : First reference to Mode X +Article Abstract : VGA's undocumented Mode X supports page flipping, + makes off screen memory available, has square pixels, + and increases performance by as muck as 4 times. + +Issue 179 Aug 1991 : Continuation +Article Abstract : Michael discusses latches and VGA's undoccumented + Mode X. + +Issue 181 Sep 1991 : Continuation +Article Abstract : Michael puts the moves on animation using VGA's 256 + colors. + +Issue 184 Oct 1991 : First of a continuing series covering 3-D animation + using VGA's Mode X. This series is still ongoing + (October 1992) +Article Abstract : Michael moves into 3-D animation, starting with basic + polygon fills and page flips. + + +WHAT IS MODE X ? +---------------- + +Mode X is a derrivative of the VGA's standard mode 13h (320x200 256 color). +It is a (family) of undocumented video modes that are created by tweaking +the VGA's registers. The beauty of mode X is that it offers several +benefits to the programmer: + - Multiple graphice pages where mode 13h doesn't allowing for page flipping + (also known as double buffering) and storage of images and data in + offscreen video memory + - A planar video ram organization which although more difficult to program, + allows the VGA's plane-oriented hardware to be used to process pixels in + parallel, improving performance by up to 4 times over mode 13h + + See issue 178-179 of D.D.J. for a full description of VGA's Mode X. + +WHAT IS A SPLIT SCREEN ? +------------------------ + +A split screen is a neat hardware feature offered by the EGA and VGA video +cards. A split screen is a mode of graphics operationin which the Hardware +splits the visual graphics screen horizontally and treats both halves as +individual screens each starting at different locations in video RAM. + +The bottom half (which is usually referred to as the split screen) always +starts at address A000:0000 but the top half's starting address is user +definable. + +The most common application of split screens in games is the status display +in scrolling games. Split screens make this sort of game simpler to program +because when the top half window is scrolled the programmer does not have to +worry about redrawing the bottom half. + +WHAT IS DOUBLE BUFFERING ? +-------------------------- + +Double buffering (also known as page flipping) is the technique most often +used to do animation. it requires hardware that is capable of displaying +multiple graphics pages (or at least 2). Animation is achieved by drawing +an image in the non visible screen and then displaying the non visible +screen. Once the page has been flipped the process starts again. The next +frame of the animation is drawn on the non visible screen, the page is +flipped again etc. + + +WHAT IS TRIPPLE BUFFERING ? +-------------------------- + +Triple buffering is similar to double buffering in many ways, but it +relies on 3 pages being defined for animation. The main selling point +of triple buffering is that it eliminates the need to wait for the +vertical retrace to flip pages before drawing on the new page thus +alowing the programmer to start building the next animation frame +immediately after completing the current one. Heres how it works: + +With double buffering, once you complete drawing the hidden page and +youre ready to flip pages, you have to wait for the VGA hardware to +actually flip the page (during the vertical retrace) before you start +drawing the next page otherwise you will be drawing on the visible page. + +With triple buffering you cycle between three pages, thus the page you +draw on is guaranteed not to be visible. I know this is a poor +description but it really is quite simple + +Triple buffering can acheive the fastest possible animation under the +right conditions but the draw back is that more video RAM is required. If +you wish to store bitmaps in video ram such as background tiles, double +buffering would be the better alternative. + + +WHAT IS MODE X ? +---------------- + +Mode X is a derrivative of the VGA's standard mode 13h (320x200 256 color). +It is a (family) of undocumented video modes that are created by tweaking +the VGA's registers. The beauty of mode X is that it offers several +benefits to the programmer: + - Multiple graphice pages where mode 13h doesn't allowing for page flipping + (also known as double buffering) and storage of images and data in + offscreen video memory + - A planar video ram organization which although more difficult to program, + allows the VGA's plane-oriented hardware to be used to process pixels in + parallel, improving performance by up to 4 times over mode 13h + + Again see D.D.J. for an in depth discussion of animation using Mode X. + + ----------------------------------------------------------------------- + + diff --git a/16/xlib/xline.asm b/16/xlib/xline.asm new file mode 100755 index 00000000..6c9c5c56 --- /dev/null +++ b/16/xlib/xline.asm @@ -0,0 +1,317 @@ +;----------------------------------------------------------------------- +; MODULE XLINE +; +; Line drawing functions. +; +; Compile with Tasm. +; C callable. +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- +include xlib.inc +include xline.inc + + .code + + +ModeXAddr macro + mov cl,bl + push dx + mov dx,[_ScrnLogicalByteWidth] + mul dx + pop dx + shr bx,2 + add bx,ax + add bx,[PgOffs] + and cl,3 + endm + + +;----------------------------------------------------------------------- +; _x_line +; +; Line drawing function for all MODE X 256 Color resolutions +; Based on code from "PC and PS/2 Video Systems" by Richard Wilton. +; +; Compile with Tasm. +; C callable. +; + +_x_line proc +ARG x1:word,y1:word,x2:word,y2:word,Color:word,PgOffs:word +LOCAL vertincr:word,incr1:word,incr2:word,routine:word=LocalStk + push bp ; Set up stack frame + mov bp,sp + sub sp,LocalStk + push si + push di + + mov ax,0a000h + mov es,ax + + mov dx,SC_INDEX ; setup for plane mask access + +; check for vertical line + + mov si,[_ScrnLogicalByteWidth] + mov cx,[x2] + sub cx,[x1] + jz VertLine + +; force x1 < x2 + + jns L01 + + neg cx + + mov bx,[x2] + xchg bx,[x1] + mov [x2],bx + + mov bx,[y2] + xchg bx,[y1] + mov [y2],bx + +; calc dy = abs(y2 - y1) + +L01: + mov bx,[y2] + sub bx,[y1] + jnz short skip + jmp HorizLine +skip: jns L03 + + neg bx + neg si + +; select appropriate routine for slope of line + +L03: + mov [vertincr],si + mov [routine],offset LoSlopeLine + cmp bx,cx + jle L04 + mov [routine],offset HiSlopeLine + xchg bx,cx + +; calc initial decision variable and increments + +L04: + shl bx,1 + mov [incr1],bx + sub bx,cx + mov si,bx + sub bx,cx + mov [incr2],bx + +; calc first pixel address + + push cx + mov ax,[y1] + mov bx,[x1] + ModeXAddr + mov di,bx + mov al,1 + shl al,cl + mov ah,al ; duplicate nybble + shl al,4 + add ah,al + mov bl,ah + pop cx + inc cx + jmp [routine] + +; routine for verticle lines + +VertLine: + mov ax,[y1] + mov bx,[y2] + mov cx,bx + sub cx,ax + jge L31 + neg cx + mov ax,bx + +L31: + inc cx + mov bx,[x1] + push cx + ModeXAddr + + mov ah,1 + shl ah,cl + mov al,MAP_MASK + out dx,ax + pop cx + mov ax, word ptr [Color] + +; draw the line + +L32: + mov es:[bx],al + add bx,si + loop L32 + jmp Lexit + +; routine for horizontal line + +HorizLine: + push ds + + mov ax,[y1] + mov bx,[x1] + ModeXAddr + + mov di,bx ; set dl = first byte mask + mov dl,00fh + shl dl,cl + + mov cx,[x2] ; set dh = last byte mask + and cl,3 + mov dh,00eh + shl dh,cl + not dh + +; determine byte offset of first and last pixel in line + + mov ax,[x2] + mov bx,[x1] + + shr ax,2 ; set ax = last byte column + shr bx,2 ; set bx = first byte column + mov cx,ax ; cx = ax - bx + sub cx,bx + + mov ax,dx ; mov end byte masks to ax + mov dx,SC_INDEX ; setup dx for VGA outs + mov bx, [Color] + +; set pixels in leftmost byte of line + + or cx,cx ; is start and end pt in same byte + jnz L42 ; no ! + and ah,al ; combine start and end masks + jmp short L44 + +L42: push ax + mov ah,al + mov al,MAP_MASK + out dx,ax + mov al,bl + stosb + dec cx + +; draw remainder of the line + +L43: + mov ah,0Fh + mov al,MAP_MASK + out dx,ax + mov al,bl + rep stosb + pop ax + +; set pixels in rightmost byte of line + +L44: + mov al,MAP_MASK + out dx, ax + mov byte ptr es:[di],bl + pop ds + jmp short Lexit + + +; routine for dy >= dx (slope <= 1) + +LoSlopeLine: + mov al,MAP_MASK + mov bh,byte ptr [Color] +L10: + mov ah,bl + +L11: + or ah,bl + rol bl,1 + jc L14 + +; bit mask not shifted out + + or si,si + jns L12 + add si,[incr1] + loop L11 + + out dx,ax + mov es:[di],bh + jmp short Lexit + +L12: + add si,[incr2] + out dx,ax + mov es:[di],bh + add di,[vertincr] + loop L10 + jmp short Lexit + +; bit mask shifted out + +L14: out dx,ax + mov es:[di],bh + inc di + or si,si + jns L15 + add si,[incr1] + loop L10 + jmp short Lexit + +L15: + add si,[incr2] + add di,[vertincr] + loop L10 + jmp short Lexit + +; routine for dy > dx (slope > 1) + +HiSlopeLine: + mov bx,[vertincr] + mov al,MAP_MASK +L21: out dx,ax + push ax + mov ax,[Color] + mov es:[di],al + pop ax + add di,bx + +L22: + or si,si + jns L23 + + add si,[incr1] + loop L21 + jmp short Lexit + +L23: + add si,[incr2] + rol ah,1 + adc di,0 +lx21: loop L21 + +; return to caller + +Lexit: + pop di + pop si + mov sp,bp + pop bp + ret + +_x_line endp + +end + \ No newline at end of file diff --git a/16/xlib/xline.h b/16/xlib/xline.h new file mode 100755 index 00000000..c8688a42 --- /dev/null +++ b/16/xlib/xline.h @@ -0,0 +1,46 @@ +/*----------------------------------------------------------------------- +; +; XLINE - header file +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;----------------------------------------------------------------------*/ + +#ifndef _XLINE_H_ +#define _XLINE_H_ + + +/* FUNCTIONS =========================================================== */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern void x_line( /* Draw a line, what else */ + WORD x0, + WORD y0, + WORD x1, + WORD y1, + WORD color, + WORD PageBase); + + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/16/xlib/xline.inc b/16/xlib/xline.inc new file mode 100755 index 00000000..2e92d7ee --- /dev/null +++ b/16/xlib/xline.inc @@ -0,0 +1,19 @@ +;----------------------------------------------------------------------- +; +; XLINE - Include file +; +; XLINE.ASM export functions +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + + global _x_line :proc + \ No newline at end of file diff --git a/16/xlib/xmain.asm b/16/xlib/xmain.asm new file mode 100755 index 00000000..a8fd4184 --- /dev/null +++ b/16/xlib/xmain.asm @@ -0,0 +1,1539 @@ +;----------------------------------------------------------------------- +; MODULE XMAIN +; +; Initialization, panning and split screen functions for all MODE X 256 +; Color resolutions +; +; Compile with Tasm. +; C callable. +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; MODIFICATIONS: +; 26-9-92: Pel panning code added +; Dates forgotten: Numerous ;^) +; 05-10-93: Timer synchronized vsync handling extensions +; and tripple buffering - Tore Jahn Bastiansen +; (toreba@ifi.uio.no) for the +;----------------------------------------------------------------------- + + +include xlib.inc +include xmain.inc + + + .data + + +; Mode X CRTC register tweaks for various resolutions + + +LABEL X256Y200 word + db 0e3h ; dot clock + db 8 ; Number of CRTC Registers to update + dw 05f00h ; horz total + dw 03f01h ; horz displayed + dw 04202h ; start horz blanking + dw 09f03h ; end horz blanking + dw 04c04h ; start h sync + dw 00005h ; end h sync + dw 00014h ; turn off dword mode + dw 0e317h ; turn on byte mode + dw 256 + dw 200 + + +LABEL X256Y240 word + db 0e3h ; dot clock + db 16 ; Number of CRTC Registers to update + dw 05f00h ; horz total + dw 03f01h ; horz displayed + dw 04202h ; start horz blanking + dw 09f03h ; end horz blanking + dw 04c04h ; start h sync + dw 00005h ; end h sync + dw 00d06h ; vertical total + dw 03e07h ; overflow (bit 8 of vertical counts) + dw 04109h ; cell height (2 to double-scan) + dw 0ea10h ; v sync start + dw 0ac11h ; v sync end and protect cr0-cr7 + dw 0df12h ; vertical displayed + dw 00014h ; turn off dword mode + dw 0e715h ; v blank start + dw 00616h ; v blank end + dw 0e317h ; turn on byte mode + dw 256 + dw 240 + + +X320Y200 label word + db 00 ; 0e3h ; dot clock + db 02 ; Number of CRTC Registers to update + dw 00014h ; turn off dword mode + dw 0e317h ; turn on byte mode + dw 320 ; width + dw 200 ; height + +X320Y240 label word + db 0e3h ; dot clock + db 10 ; Number of CRTC Registers to update + dw 00d06h ; vertical total + dw 03e07h ; overflow (bit 8 of vertical counts) + dw 04109h ; cell height (2 to double-scan) + dw 0ea10h ; v sync start + dw 0ac11h ; v sync end and protect cr0-cr7 + dw 0df12h ; vertical displayed + dw 00014h ; turn off dword mode + dw 0e715h ; v blank start + dw 00616h ; v blank end + dw 0e317h ; turn on byte mode + dw 320 ; width + dw 240 ; height + +X360Y200 label word + db 0e7h ; dot clock + db 08 ; Number of CRTC Registers to update + dw 06b00h ; horz total + dw 05901h ; horz displayed + dw 05a02h ; start horz blanking + dw 08e03h ; end horz blanking + dw 05e04h ; start h sync + dw 08a05h ; end h sync + dw 00014h ; turn off dword mode + dw 0e317h ; turn on byte mode + dw 360 ; width + dw 200 ; height + +X360Y240 label word + db 0e7h ; dot clock + db 17 ; Number of CRTC Registers to update + dw 06b00h ; horz total + dw 05901h ; horz displayed + dw 05a02h ; start horz blanking + dw 08e03h ; end horz blanking + dw 05e04h ; start h sync + dw 08a05h ; end h sync + dw 00d06h ; vertical total + dw 03e07h ; overflow (bit 8 of vertical counts) + dw 04109h ; cell height (2 to double-scan) + dw 0ea10h ; v sync start + dw 0ac11h ; v sync end and protect cr0-cr7 + dw 0df12h ; vertical displayed + dw 02d13h ; offset; + dw 00014h ; turn off dword mode + dw 0e715h ; v blank start + dw 00616h ; v blank end + dw 0e317h ; turn on byte mode + dw 360 + dw 240 + +X376Y282 label word + db 0e7h + db 18 + dw 06e00h ; horz total + dw 05d01h ; horz displayed + dw 05e02h ; start horz blanking + dw 09103h ; end horz blanking + dw 06204h ; start h sync + dw 08f05h ; end h sync + dw 06206h ; vertical total + dw 0f007h ; overflow + dw 06109h ; cell height + dw 0310fh ; + dw 03710h ; v sync start + dw 08911h ; v sync end and protect cr0-cr7 + dw 03312h ; vertical displayed + dw 02f13h ; offset + dw 00014h ; turn off dword mode + dw 03c15h ; v blank start + dw 05c16h ; v blank end + dw 0e317h ; turn on byte mode + dw 376 + dw 282 + +LABEL X256Y400 word + db 0e3h ; dot clock + db 8 ; Number of CRTC Registers to update + dw 05f00h ; horz total + dw 03f01h ; horz displayed + dw 04202h ; start horz blanking + dw 09f03h ; end horz blanking + dw 04c04h ; start h sync + dw 00005h ; end h sync + dw 04009h ; cell height + dw 00014h ; turn off dword mode + dw 0e317h ; turn on byte mode + dw 256 + dw 400 + + +LABEL X256Y480 word + db 0e3h ; dot clock + db 16 ; Number of CRTC Registers to update + dw 05f00h ; horz total + dw 03f01h ; horz displayed + dw 04202h ; start horz blanking + dw 09f03h ; end horz blanking + dw 04c04h ; start h sync + dw 00005h ; end h sync + dw 00d06h ; vertical total + dw 03e07h ; overflow (bit 8 of vertical counts) + dw 04009h ; cell height (2 to double-scan) + dw 0ea10h ; v sync start + dw 0ac11h ; v sync end and protect cr0-cr7 + dw 0df12h ; vertical displayed + dw 00014h ; turn off dword mode + dw 0e715h ; v blank start + dw 00616h ; v blank end + dw 0e317h ; turn on byte mode + dw 256 + dw 480 + + + +X320Y400 label word + db 0e3h ; dot clock + db 03 ; Number of CRTC Registers to update + dw 04009h ; cell height + dw 00014h ; turn off dword mode + dw 0e317h ; turn on byte mode + dw 320 ; width + dw 400 ; height + +X320Y480 label word + db 0e3h ; dotclock + db 10 ; Number of CRTC Registers to update + dw 00d06h ; vertical total + dw 03e07h ; overflow (bit 8 of vertical counts) + dw 04009h ; cell height (2 to double-scan) + dw 0ea10h ; v sync start + dw 0ac11h ; v sync end and protect cr0-cr7 + dw 0df12h ; vertical displayed + dw 00014h ; turn off dword mode + dw 0e715h ; v blank start + dw 00616h ; v blank end + dw 0e317h ; turn on byte mode + dw 320 ; width + dw 480 ; height + +X360Y400 label word + db 0e7h ; dot clock + db 09 ; Number of CRTC Registers to update + dw 06b00h ; horz total + dw 05901h ; horz displayed + dw 05a02h ; start horz blanking + dw 08e03h ; end horz blanking + dw 05e04h ; start h sync + dw 08a05h ; end h sync + dw 04009h ; cell height + dw 00014h ; turn off dword mode + dw 0e317h ; turn on byte mode + dw 360 ; width + dw 400 ; height + + + +X360Y480 label word + db 0e7h + db 17 + dw 06b00h ; horz total + dw 05901h ; horz displayed + dw 05a02h ; start horz blanking + dw 08e03h ; end horz blanking + dw 05e04h ; start h sync + dw 08a05h ; end h sync + dw 00d06h ; vertical total + dw 03e07h ; overflow + dw 04009h ; cell height + dw 0ea10h ; v sync start + dw 0ac11h ; v sync end and protect cr0-cr7 + dw 0df12h ; vertical displayed + dw 02d13h ; offset + dw 00014h ; turn off dword mode + dw 0e715h ; v blank start + dw 00616h ; v blank end + dw 0e317h ; turn on byte mode + dw 360 + dw 480 + +X360Y360 label word + db 0e7h + db 15 + dw 06b00h ; horz total + dw 05901h ; horz displayed + dw 05a02h ; start horz blanking + dw 08e03h ; end horz blanking + dw 05e04h ; start h sync + dw 08a05h ; end h sync + dw 04009h ; cell height + dw 08810h ; v sync start + dw 08511h ; v sync end and protect cr0-cr7 + dw 06712h ; vertical displayed + dw 02d13h ; offset + dw 00014h ; turn off dword mode + dw 06d15h ; v blank start + dw 0ba16h ; v blank end + dw 0e317h ; turn on byte mode + dw 360 + dw 360 + + +X376Y308 label word + db 0e7h + db 18 + dw 06e00h ; horz total + dw 05d01h ; horz displayed + dw 05e02h ; start horz blanking + dw 09103h ; end horz blanking + dw 06204h ; start h sync + dw 08f05h ; end h sync + dw 06206h ; vertical total + dw 00f07h ; overflow + dw 04009h ; + dw 0310fh ; + dw 03710h ; v sync start + dw 08911h ; v sync end and protect cr0-cr7 + dw 03312h ; vertical displayed + dw 02f13h ; offset + dw 00014h ; turn off dword mode + dw 03c15h ; v blank start + dw 05c16h ; v blank end + dw 0e317h ; turn on byte mode + dw 376 + dw 308 + +X376Y564 label word + db 0e7h + db 18 + dw 06e00h ; horz total + dw 05d01h ; horz displayed + dw 05e02h ; start horz blanking + dw 09103h ; end horz blanking + dw 06204h ; start h sync + dw 08f05h ; end h sync + dw 06206h ; vertical total + dw 0f007h ; overflow + dw 06009h ; + dw 0310fh ; + dw 03710h ; v sync start + dw 08911h ; v sync end and protect cr0-cr7 + dw 03312h ; vertical displayed + dw 02f13h ; offset + dw 00014h ; turn off dword mode + dw 03c15h ; v blank start + dw 05c16h ; v blank end + dw 0e317h ; turn on byte mode + dw 376 + dw 564 + +LAST_X_MODE equ 13 +ModeTable label word ; Mode X tweak table + dw offset X320Y200 + dw offset X320Y240 + dw offset X360Y200 + dw offset X360Y240 + dw offset X376Y282 + dw offset X320Y400 + dw offset X320Y480 + dw offset X360Y400 + dw offset X360Y480 + dw offset X360Y360 + dw offset X376Y308 + dw offset X376Y564 + dw offset X256Y200 + dw offset X256Y240 + + +PARAMS label byte + + _CurrXMode dw 0 ; Current graphics mode index + _InGraphics db 0 ; Flag indicating graphics activity + _ScrnPhysicalByteWidth dw 0 ; Physical width in bytes of screen + _ScrnPhysicalPixelWidth dw 0 ; Physical width in pixels of screen + _ScrnPhysicalHeight dw 0 ; Physical Height of screen + _ErrorValue db 0 ; Set after function calls + + + _SplitScrnActive db 0 ; Flag indicating Split scrn activity + _DoubleBufferActive dw 0 ; Flag indicating double buffering + _TrippleBufferActive dw 0 ; Flag indicating tripple buffering + + _SplitScrnScanLine dw 0 ; Split Screen's starting scan line + _SplitScrnVisibleHeight dw 0 ; Split Screen's height on screen + + _SplitScrnOffs dw 0 ; Offset in video ram of Split Screen + ; always = 0 + _Page0_Offs dw 0 ; Ofset in video ram of Main virtual + ; screen ( = 0 if no split screen + ; otherwise = offset of first byte + ; after split screen + _Page1_Offs dw 0 ; Ofset in video ram of Second virtual + ; screen ( = 0 if no split screen + ; otherwise = offset of first byte + ; after split screen + ; = Page0_Offs if Doubble buffering + ; not enabled + _Page2_Offs dw 0 + + _NonVisual_Offs dw 0 ; Ofset in video ram of first byte + ; of non visible ram + _ScrnLogicalByteWidth dw 0 ; Logical width in bytes of screen + _ScrnLogicalPixelWidth dw 0 ; Logical width in pixels of screen + _ScrnLogicalHeight dw 0 ; Logical Height of screen + + _MaxScrollX dw 0 ; Max X start position of Physical + ; screen within virtual screen (in + ; bytes) + _MaxScrollY dw 0 ; Max Y start position of Physical + ; screen within virtual screen + + _VisiblePageIdx dw 0 ; Index of currently visible D.B. + ; page + + PageAddrTable label word + _VisiblePageOffs dw 0 ; Table containing starting offsets + _HiddenPageOffs dw 0 ; of the double buffer pages + _WaitingPageOffs dw 0 + + _TopClip dw 0 ; Clipping Rectangle + _BottomClip dw 0 ; + _LeftClip dw 0 ; Left/Right coordinates in bytes + _RightClip dw 0 ; + _PhysicalStartByteX dw 0 ; X byte coord of physical screen + ; relative to virtual virtual screen + _PhysicalStartPixelX dw 0 ; X pixel coord of physical screen + ; relative to virtual screen + _PhysicalStartY dw 0 ; Y pixel coord of physical screen + ; relative to virtual screen + +; NEW + _VsyncHandlerActive dw 0 + _MouseRefreshFlag dw 0 + _MouseVsyncHandler dd 0 + _StartAddressFlag dw 0 + _WaitingStartLow dw 0 + _WaitingStartHigh dw 0 + _WaitingPelPan dw 0 + _VsyncPaletteStart dw 0 + _VsyncPaletteCount dw 0 + _VsyncPaletteBuffer label byte + db 768 dup(?) + + +PARAMS_END label byte + +PARAM_COUNT equ ($-PARAMS) + + +; Index/data pairs for CRT Controller registers that differ between +; mode 13h and mode X. + + ;Pelpan values for 0,1,2,3 pixel panning to the left, respectively + PelPanMask db 000h,002h,004h,006h + +DoubleScanFlag db ? ; Flag to indicate double scanned mode + + .code + +;------------------------------------------------------------------------- +; Local Logical Screen Width setting function +; cx = Requitrd Logical Width +; +; WARNING: no registers are preserved + +SetLogicalScrWidth proc + mov dx,CRTC_INDEX + mov al,CRTC_OFFSET + out dx,al + inc dx + + mov ax,cx + cmp ax,[_ScrnPhysicalPixelWidth]; Is logical width >= physical width + jge @@ValidLogicalWidth ; yes - continue + mov ax,bx ; no - set logical width = physical + +@@ValidLogicalWidth: + shr ax,3 + out dx,al + + ; The EXACT logical pixel width may not have been possible since + ; it should be divisible by 8. Round down to the closest possible + ; width and update the status variables + + shl ax,1 + mov bx,ax + mov [_ScrnLogicalByteWidth],ax ; Store the byte width of virtual + mov [_RightClip],ax ; Set default Right clip column + ; screen + sub ax,[_ScrnPhysicalByteWidth] ; Calculate and store Max X position + shl ax,2 ; of physical screen in virtual + mov [_MaxScrollX],ax ; screen in pixels + mov ax,bx ; set ax to byte width of virt scrn + shl ax,2 ; convert to pixels + mov [_ScrnLogicalPixelWidth],ax ; store virt scrn pixel width + mov cx,ax ; save ax (return value) + + ; calculate no. non split screen rows in video ram + + mov ax,0ffffh ; cx = Maximum video ram offset + sub dx,dx ; DX:AX is divide operand, set DX = 0 + div bx ; divide ax by ScrnLogicalByteWidth + mov [_ScrnLogicalHeight],ax ; Save Screen Logical Height + mov [_BottomClip],ax ; Set default bottom clip row + sub ax,[_ScrnPhysicalHeight] ; Update the maximum Y position of + mov [_MaxScrollY],ax ; Physical screen in logical screen + mov ax,cx ; restore ax (return value) + + ; calculate initial NonVisual + mov ax,[_ScrnLogicalByteWidth] + mul [_ScrnPhysicalHeight] + mov [_NonVisual_Offs],ax + +@@Done: ret +SetLogicalScrWidth endp + +clear_vram proc + push di + mov dx,SC_INDEX + mov ax,0f02h + out dx,ax ; enable writes to all four planes + mov ax,SCREEN_SEG ; now clear all display memory, 8 pixels + mov es,ax ; at a time + sub di,di ; point ES:DI to display memory + + WaitVsyncEnd + + sub ax,ax ; clear to zero-value pixels + mov cx,0FFFFh ; # of words in display memory + rep stosw ; clear all of display memory + pop di + ret +clear_vram endp + + + +;----------------------------------------------------------------------- +; Mode X graphics mode set with a virtual screen +; logical screen width. +; C near-callable as: +; +; int x_set_mode(unsigned int mode,unsigned int WidthInPixels); +; +; returns the actual width of the allocated virtual screen in pixels +; if a valid mode was selected otherwise returns -1 +; +; Saves virtual screen pixel width in _ScrnLogicalPixelWidth. +; Saves virtual screen byte width in _ScrnLogicalByteWidth. +; Physical screen dimensions are set in _ScrnPhysicalPixelWidth, +; _ScrnPhysicalByteWidth and _ScrnPhysicalHeight +; +; +; Modes: 0 = 320 x 200 (256 color) NOTE: Some of these modes require +; 1 = 320 x 240 (256 color) vertical size adjustment. +; 2 = 360 x 200 (256 color) +; 3 = 360 x 240 (256 color) +; 4 = 320 x 400 (256 color) +; 5 = 320 x 480 (256 color) +; 6 = 360 x 200 (256 color) +; 7 = 360 x 480 (256 color) +; 8 = 360 x 360 (256 color) +; 9 = 376 x 308 (256 color) +; 10 = 376 x 564 (256 color) +; +; Written by Themie Gouthas, +; parts adapted from M. Abrash code. +;------------------------------------------------------------------------ +_x_set_mode proc + ARG mode:word,logicalscrwidth:word + push bp ;preserve caller's stack frame + mov bp,sp + + push si ;preserve C register vars + push di ; (don't count on BIOS preserving anything) + + cld + mov ax,ds + mov es,ax + mov di,offset PARAMS + xor ax,ax + mov cx,PARAM_COUNT + rep stosb + + mov cx,[mode] + cmp cx,LAST_X_MODE ; have we selected a valid mode + jle @@ValidMode ; Yes ! + + mov [_InGraphics],FALSE ; No return -1 + mov ax,-1 + pop di + pop si + pop bp + ret + +@@ValidMode: + + mov [_CurrXMode],cx + mov [_InGraphics],TRUE + + xor al,al + cmp cx,3 + jg @@SetDoubleScanFlag + mov al,TRUE +@@SetDoubleScanFlag: + mov [DoubleScanFlag],al + push cx ; some bios's dont preserve cx + + call clear_vram + + mov ax,13h ; let the BIOS set standard 256-color + int 10h ; mode (320x200 linear) + + + pop cx + + mov dx,SC_INDEX + mov ax,0604h + out dx,ax ; disable chain4 mode + mov ax,0100h + out dx,ax ; synchronous reset while setting Misc + ; Output for safety, even though clock + ; unchanged + + mov bx,offset ModeTable + shl cx,1 + add bx,cx + mov si, word ptr [bx] + lodsb + + or al,al + jz @@DontSetDot + mov dx,MISC_OUTPUT + out dx,al ; select the dot clock and Horiz + ; scanning rate +@@DontSetDot: + mov dx,SC_INDEX + mov ax,0300h + out dx,ax ; undo reset (restart sequencer) + + + mov dx,CRTC_INDEX ; reprogram the CRT Controller + mov al,11h ; VSync End reg contains register write + out dx,al ; protect bit + inc dx ; CRT Controller Data register + in al,dx ; get current VSync End register setting + and al,07fh ; remove write protect on various + out dx,al ; CRTC registers + dec dx ; CRT Controller Index + cld + xor cx,cx + lodsb + mov cl,al + +@@SetCRTParmsLoop: + lodsw ; get the next CRT Index/Data pair + out dx,ax ; set the next CRT Index/Data pair + loop @@SetCRTParmsLoop + + mov dx,SC_INDEX + mov ax,0f02h + out dx,ax ; enable writes to all four planes + mov ax,SCREEN_SEG ; now clear all display memory, 8 pixels + mov es,ax ; at a time + sub di,di ; point ES:DI to display memory + sub ax,ax ; clear to zero-value pixels + mov cx,8000h ; # of words in display memory + rep stosw ; clear all of display memory + + ; Set pysical screen dimensions + + lodsw ; Load scrn pixel width + mov [_ScrnPhysicalPixelWidth],ax ; from tweak table and store + mov [_SplitScrnScanLine],ax ; No splitscrn == + ; splitscrn=PhysicalscrnHeight + mov bx,ax ; Copy width for later use + shr ax,2 ; Convert to byte width + mov [_ScrnPhysicalByteWidth],ax ; Store for later use + lodsw ; Load Screen Phys. Height + mov [_ScrnPhysicalHeight],ax ; Store for later use + + + ; Mode X is set, now set the required logical page width. + + mov cx,[logicalscrwidth] + + call SetLogicalScrWidth + + pop di ;restore C register vars + pop si + pop bp ;restore caller's stack frame + ret +_x_set_mode endp + +;---------------------------------------------------------------------- +; Mode X (256 color mode) set default access video plane +; +; C near-callable as: +; void x_select_default_plane(unsigned char plane); +; +; Enables Read/Write access to a plane using general memory access +; methods +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_select_default_plane proc +ARG Plane:byte + push bp + mov bp,sp ; set up stack frame + mov cl,byte ptr [Plane] + + ; SELECT WRITE PLANE + and cl,011b ;CL = plane + mov ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg + shl ah,cl ;set only the bit for the required + ; plane to 1 + mov dx,SC_INDEX ;set the Map Mask to enable only the + out dx,ax ; pixel's plane + + ; SELECT READ PLANE + mov ah,cl ;AH = plane + mov al,READ_MAP ;AL = index in GC of the Read Map reg + mov dx,GC_INDEX ;set the Read Map to read the pixel's + out dx,ax ; plane + + pop bp + ret +_x_select_default_plane endp + + +;---------------------------------------------------------------------- +; Mode X (256 color mode) Set Mode X split screen starting row +; The split screen resides on the bottom half of the screen and has a +; starting address of A000:0000 +; +; C near-callable as: +; void x_set_splitscreen(unsigned int line); +; +; Updates _Page0_Offs to reflect the existence of the split screen region +; ie _MainScrnOffset is set to the offset of the first pixel beyond the split +; screen region +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- + +_x_set_splitscreen proc + ARG Line:word + push bp + mov bp,sp ; set up stack frame + push si + + xor si,si ; si=0 -> x virtual page start coord + + cmp [_DoubleBufferActive],0 + jne @@error + + cmp [_SplitScrnActive],0 + je @@NotPreviouslyCalled + +@@error: + mov [_ErrorValue],ERROR + pop si + pop bp ; Return if previously called + ret + +@@NotPreviouslyCalled: + + ; Turn on split screen pal pen suppression, so the split screen + ; wo'nt be subject to pel panning as is the non split screen portion. + + mov dx,INPUT_STATUS_0 + in al,dx ; Reset the AC Index/Data toggle to + ; index state + mov al,AC_MODE_CONTROL+20h ; Bit 5 set to prevent screen blanking + mov dx,AC_INDEX ; Point AC to Index/Data register + out dx,al + inc dx ; Point to AC Data reg (for reads only) + in al,dx ; Get the current AC Mode Control reg + or al,20h ; Enable split scrn Pel panning suppress. + dec dx ; Point to AC Index/Data reg (for writes only) + out dx,al ; Write the new AC Mode Control setting + ; with split screen pel panning + ; suppression turned on + + mov [_PhysicalStartByteX],ax ; Set the Phisical screen start + mov [_PhysicalStartPixelX],ax ; offset within virtual screen + mov [_PhysicalStartY],ax + mov [_SplitScrnActive],TRUE + mov ax,[Line] + jns @@NotNeg ; Check that Split Scrn start scan line is +ve + + mov ax,0 ; Since -ve set to 0 + +@@NotNeg: + mov [_SplitScrnScanLine],ax ; save the scanline + + + + or [DoubleScanFlag],0 + jz @@NotDoubleScanned + shl ax,1 + dec ax +@@NotDoubleScanned: + ;mov cl,[DoubleScanFlag] + ;shl ax,cl ; Mode X 200 and 240 line modes are actually + ; 400 and 480 lines that are double scanned + ; so for start scanline multiply required ModeX + ; scan line by 2 if its a double scanned mode + + + mov bx,ax ; save the scanline + + + WaitVsyncStart ; wait for vertical retrace + + cli ; Dont allow register setting to be interrupted + mov dx,CRTC_INDEX + mov ah,bl + mov al,LINE_COMPARE + out dx,ax ; Bits 7-0 of the split screen scan line + + mov ah,bh + and ah,1 + shl ah,4 + mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split + out dx,al ; screen scan line, + inc dx ; So using readability of VGA registers + in al,dx ; Read the OVERFLOW register, and set the + and al, not 10h ; bit corresponding to Bit 8 (above) + or al,ah + out dx,al + + dec dx + mov ah,bh + and ah,2 + ror ah,3 + mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register = + out dx,al ; Bit 9 of split screen scan line + inc dx ; As we did before, update the apropriate + in al,dx ; bit without disturbing the rest + and al, not 40h + or al,ah + out dx,al + sti ; Registers are set, so interrupts are safe + + mov ax,[_ScrnPhysicalHeight] ; Determine where the first byte + sub ax,[_SplitScrnScanLine] ; of the non split screen video ram + mov [_SplitScrnVisibleHeight],ax ; starts and store it for reference + + mov bx,[_ScrnLogicalByteWidth] + mul bx + mov [_Page0_Offs],ax + mov [_Page1_Offs],ax + mov [_Page2_Offs],ax + + ; calculate no. non split screen rows in video ram + mov cx,0ffffh ; cx = Maximum video ram offset + sub cx,ax ; cx = cx - _Page0_Offs + xchg cx,ax ; swap cx and ax + sub dx,dx ; DX:AX is divide operand, set DX = 0 + div bx ; divide ax (prev cx) by + ; ScrnLogicalByteWidth + + mov [_ScrnLogicalHeight],ax ; Save Screen Logical Height + cmp ax,[_BottomClip] + jle @@BottomClipOK ; Adjust Clip Rectangle if necessary + mov [_BottomClip],ax +@@BottomClipOK: + sub ax,[_SplitScrnScanLine] ; Update the maximum Y position of + mov [_MaxScrollY],ax ; Physical screen in logical screen + + xchg cx,ax ; restore original ax (MainScrnOfs) + mov bh,al ; Set the visible screen start address + mov ch,ah ; to the top left corner of the virtual + jmp StartAddrEntry ; screen +_x_set_splitscreen endp + + +;----------------------------------------------------------------------- +; Mode X (256 color mode) Page flip primer +; No clipping is performed. +; C near-callable as: +; +; void x_page_flip(unsigned int x, unsigned int y); +; +; Swaps visible and hidden page offsets and then executes the SetStartAddr +; to achieve a page flip. +; +; SEE x_set_start_addr below +; +; Written by Themie Gouthas +;------------------------------------------------------------------------ + +_x_page_flip proc + ARG x:word,y:word + push bp ;preserve caller's stack frame + mov bp,sp ;point to local stack frame + push si + + mov si,[x] + mov ax,[_ScrnLogicalByteWidth] ; Calculate Offset increment + mov cx,[y] + mul cx ; for Y + cmp [_DoubleBufferActive],TRUE ; Do we have double buffering ? + je @@DoubleBuffer + cmp [_TrippleBufferActive],TRUE + jne PageFlipEntry1 + +; TrippleBuffer + mov bx,[_HiddenPageOffs] + xchg bx,[_VisiblePageOffs] + xchg bx,[_WaitingPageOffs] + mov [_HiddenPageOffs],bx + mov bx,[_VisiblePageIdx] + inc bx + cmp bx,3 + jne @@IdxOk + xor bx,bx +@@IdxOk: + mov [_VisiblePageIdx],bx + jmp short PageFlipEntry2 +@@DoubleBuffer: + mov bx,[_HiddenPageOffs] + xchg bx,[_VisiblePageOffs] ; Swap the Page Offsete + xchg [_HiddenPageOffs],bx + xor [_VisiblePageIdx],01h ; Set the Visible page index + jmp short PageFlipEntry2 +_x_page_flip endp + + +;----------------------------------------------------------------------- +; Mode X (256 color mode) Set Mode X non split screen start address +; of logical screen. +; C near-callable as: +; +; void x_set_start_addr(unsigned int x, unsigned int y); +; +; Params: StartOffset is offset of first byte of logical screen ram +; (Useful if you want to double buffer by splitting your non +; split screen video ram into 2 pages) +; X,Y coordinates of the top left hand corner of the physical screen +; within the logical screen +; X must not exceed (Logical screen width - Physical screen width) +; Y must not exceed (Logical screen height - Physical screen height) +; +; +; Written by Themie Gouthas, +; Parts addapted from M. Abrash code published in DDJ Mag. +;------------------------------------------------------------------------ +_x_set_start_addr proc + ARG x:word,y:word + push bp + mov bp,sp + push si + + mov si,[x] + mov ax,[_ScrnLogicalByteWidth] ; Calculate Offset increment + mov cx,[y] ; for Y + mul cx + cmp [_DoubleBufferActive],TRUE ; Do we have double buffering ? + je @@PageResolution + cmp [_TrippleBufferActive],TRUE + je @@PageResolution +PageFlipEntry1: + add ax,[_Page0_Offs] ; no - add page 0 offset + jmp short @@AddColumn + +PageFlipEntry2: + + mov [_PhysicalStartPixelX],si + mov [_PhysicalStartY],cx + +@@PageResolution: + add ax,[_VisiblePageOffs] ; Add visible page offset + +@@AddColumn: + mov cx,si + shr cx,2 + mov [_PhysicalStartByteX],cx + add ax,cx ; add the column offset for X + mov bh,al ; setup CRTC start addr regs and + ; values in word registers for + mov ch,ah ; fast word outs + +StartAddrEntry: + mov bl,ADDR_LOW + mov cl,ADDR_HIGH + and si,0003h ; select pel pan register value for the + mov ah,PelPanMask[si] ; required x coordinate + mov al,PEL_PANNING+20h + mov si,ax + + cmp [_VsyncHandlerActive],TRUE + jne @@NoVsyncHandler +; NEW STUFF +@@WaitLast: + cmp [_StartAddressFlag],0 + jne @@WaitLast + cli + mov [_WaitingStartLow],bx + mov [_WaitingStartHigh],cx + mov [_WaitingPelPan],si + mov [_StartAddressFlag],1 + sti + jmp short @@Return + +@@NoVsyncHandler: + mov dx,INPUT_STATUS_0 ;Wait for trailing edge of Vsync pulse +@@WaitDE: + in al,dx + test al,01h + jnz @@WaitDE ;display enable is active low (0 = active) + + mov dx,CRTC_INDEX + mov ax,bx + cli + out dx,ax ;start address low + mov ax,cx + out dx,ax ;start address high + sti + +; Now wait for vertical sync, so the other page will be invisible when +; we start drawing to it. + mov dx,INPUT_STATUS_0 ;Wait for trailing edge of Vsync pulse +@@WaitVS: + in al,dx + test al,08h + jz @@WaitVS ;display enable is active low (0 = active) + + + mov dx,AC_INDEX + mov ax,si ; Point the attribute controller to pel pan + cli + out dx,al ; reg. Bit 5 also set to prevent blanking + mov al,ah + out dx,al ; load new Pel Pan setting. + sti + +@@Return: + mov [_ErrorValue],OK + pop si + pop bp + ret +_x_set_start_addr endp + + +;----------------------------------------------------------------------- +; Mode X (256 color mode) Mode X split screen hide +; C near-callable as: +; +; void x_hide_splitscreen() +; +; Hides an existing split screen by setting its starting scan line to +; the last physical screen scan line +; +; WARNING: Only to be used if SplitScrnLine has been previously called +; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for +; the initial split screen is reserved and the size limitations +; of these modes means any change in the split screen scan line +; will encroach on the split screen ram +; +; Written by Themie Gouthas +;------------------------------------------------------------------------ + +_x_hide_splitscreen proc + push bp + mov bp,sp + + cmp [_SplitScrnActive],TRUE + je @@SplitScreenEnabled + +@@error: + mov [_ErrorValue],ERROR + pop bp + ret + +@@SplitScreenEnabled: + cmp [_CurrXMode],4 ; Do nothing for Modes > 2 + jg @@error + mov bx,[_ScrnPhysicalHeight] + + mov ax,[_ScrnLogicalHeight] + sub ax,bx + mov [_MaxScrollY],ax + xor ax,ax + mov [_SplitScrnVisibleHeight],ax + + or [DoubleScanFlag],0 + jz @@NotDoubleScanned + shl bx,1 + dec bx +@@NotDoubleScanned: + ;mov cl,[DoubleScanFlag] ; Compensate for double scanned modes + ;shl bx,cl + + WaitVsyncStart ; wait for vertical retrace + + cli ; Dont allow register setting to be interrupted + mov dx,CRTC_INDEX + mov ah,bl + mov al,LINE_COMPARE + out dx,ax ; Bits 7-0 of the split screen scan line + + mov ah,bh + and ah,1 + shl ah,4 + mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split + out dx,al ; screen scan line, + inc dx ; So using readability of VGA registers + in al,dx ; Read the OVERFLOW register, and set the + and al, not 10h ; bit corresponding to Bit 8 (above) + or al,ah + out dx,al + + dec dx + mov ah,bh + and ah,2 + ror ah,3 + mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register = + out dx,al ; Bit 9 of split screen scan line + inc dx ; As we did before, update the apropriate + in al,dx ; bit without disturbing the rest + and al, not 40h + or al,ah + out dx,al + sti ; Registers are set, so interrupts are safe + +@@done: + + mov [_ErrorValue],OK + pop bp + ret +_x_hide_splitscreen endp + +;----------------------------------------------------------------------- +; Mode X (256 color mode) Mode X split screen show +; C near-callable as: +; +; void x_show_splitscreen() +; +; Restores split screen start scan line to the initial split screen +; starting scan line as set by SplitScrnLine. +; +; WARNING: Only to be used if SplitScrnLine has been previously called +; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for +; the initial split screen is reserved and the size limitations +; of these modes means any change in the split screen scan line +; will encroach on the split screen ram +; Update: Now disabled for these modes +; +; Written by Themie Gouthas +;------------------------------------------------------------------------ + + +_x_show_splitscreen proc + push bp + mov bp,sp + + cmp [_SplitScrnActive],TRUE + je @@SplitScreenEnabled + +@@error: + mov [_ErrorValue],ERROR + pop bp + ret + +@@SplitScreenEnabled: + cmp [_CurrXMode],4 ; Do nothing for Modes > 2 + jg @@error + + mov bx,[_SplitScrnScanLine] + mov ax,[_ScrnLogicalHeight] ; Update Max Scroll Y + sub ax,bx + mov [_MaxScrollY],ax + + mov ax,[_ScrnPhysicalHeight] + sub ax,bx + mov [_SplitScrnVisibleHeight],ax + + or [DoubleScanFlag],0 + jz @@NotDoubleScanned + shl bx,1 + dec bx +@@NotDoubleScanned: + ;mov cl,[DoubleScanFlag] ; Compensate for double scanned modes + ;shl bx,cl + WaitVsyncStart ; wait for vertical retrace + + cli ; Dont allow register setting to be interrupted + mov dx,CRTC_INDEX + mov ah,bl + mov al,LINE_COMPARE + out dx,ax ; Bits 7-0 of the split screen scan line + + mov ah,bh + and ah,1 + shl ah,4 + mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split + out dx,al ; screen scan line, + inc dx ; So using readability of VGA registers + in al,dx ; Read the OVERFLOW register, and set the + and al, not 10h ; bit corresponding to Bit 8 (above) + or al,ah + out dx,al + + dec dx + mov ah,bh + and ah,2 + ror ah,3 + mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register = + out dx,al ; Bit 9 of split screen scan line + inc dx ; As we did before, update the apropriate + in al,dx ; bit without disturbing the rest + and al, not 40h + or al,ah + out dx,al + sti ; Registers are set, so interrupts are safe + +@@Done: + mov [_ErrorValue],0 + pop bp + ret +_x_show_splitscreen endp + + +;----------------------------------------------------------------------- +; Mode X (256 color mode) Modify Mode X split screen starting scan line +; C near-callable as: +; +; void x_adjust_splitscreen(unsigned int ScanLine) +; +; Sets the split screen start scan line to a new scan line. Valid scan lines +; are between the initial split screen starting scan line and the last +; physical screen scan line. +; +; WARNING: Only to be used if SplitScrnLine has been previously called +; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for +; the initial split screen is reserved and the size limitations +; of these modes means any change in the split screen scan line +; will encroach on the split screen ram +; Update: Now disabled for these modes +; +; +; Written by Themie Gouthas +;------------------------------------------------------------------------ + + +_x_adjust_splitscreen proc + ARG ScanLine + push bp + mov bp,sp + + cmp [_SplitScrnActive],TRUE + je @@SplitScreenEnabled + +@@error: + mov [_ErrorValue],ERROR + pop bp + ret + +@@SplitScreenEnabled: + cmp [_CurrXMode],4 ; Do nothing for Modes > 2 + jg @@error + mov bx,[ScanLine] ; Is the required starting scan line + cmp bx,[_SplitScrnScanLine] ; valid ? + js @@Done ; No - Then do nothing + +@@ValidScanLine: + + mov ax,[_ScrnLogicalHeight] ; Update Max Scroll Y + sub ax,bx + mov [_MaxScrollY],ax + + mov ax,[_ScrnPhysicalHeight] + sub ax,bx + mov [_SplitScrnVisibleHeight],ax + + or [DoubleScanFlag],0 + jz @@NotDoubleScanned + shl bx,1 + dec bx +@@NotDoubleScanned: + ;mov cl,[DoubleScanFlag] ; Compensate for double scanned modes + ;shl bx,cl + + WaitVsyncStart ; wait for vertical retrace + + cli ; Dont allow register setting to be interrupted + + mov dx,CRTC_INDEX + mov ah,bl + mov al,LINE_COMPARE + out dx,ax ; Bits 7-0 of the split screen scan line + + mov ah,bh + and ah,1 + shl ah,4 + mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split + out dx,al ; screen scan line, + inc dx ; So using readability of VGA registers + in al,dx ; Read the OVERFLOW register, and set the + and al, not 10h ; bit corresponding to Bit 8 (above) + or al,ah + out dx,al + + dec dx + mov ah,bh + and ah,2 + ror ah,3 + mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register = + out dx,al ; Bit 9 of split screen scan line + inc dx ; As we did before, update the apropriate + in al,dx ; bit without disturbing the rest + and al, not 40h + or al,ah + out dx,al + sti ; Registers are set, so interrupts are safe +@@Done: + mov [_ErrorValue],OK + pop bp + ret +_x_adjust_splitscreen endp + + + +;----------------------------------------------------------------------- +; Mode X (256 color mode) Enable DoubleBuffering on non split screen area +; C near-callable as: +; +; int x_set_doublebuffer(unsigned int PageHeight); +; +; Params: PageHeight is the height of the virtual screen to double buffer +; Returns the closest possible height to the specified. +; +; Sets up two double buffering virtual pages +; GLOBAL variables set: +; +; _Page1_Offs Offset of second virtual page +; _NonVisual_Offs Offset of first non visible video ram byte +; _DoubleBufferActive Flag +; _PageAddrTable Table of Double buffering pages start offsets +; _ScrnLogicalHeight Logical height of the double buffering pages +; +; +; Written by Themie Gouthas +;------------------------------------------------------------------------ + + +_x_set_doublebuffer proc + ARG PageHeight:word + push bp + mov bp,sp + + cmp [_DoubleBufferActive],0 + je @@OkToContinue +@error: + mov [_ErrorValue],ERROR + pop bp + ret + +@@OkToContinue: + mov [_VisiblePageIdx],0 ; Set visible Page to 0 + mov ax,[_ScrnLogicalHeight] ; Set Maximum D.B. Page height to + shr ax,1 ; _ScrnLogicalHeight / 2 + + mov bx,[PageHeight] ; Is the require D.B. Page Height + cmp ax,bx ; > the Maximum D.B. Page Height ? + + js @@InvalidHeight ; no - jump + mov ax,bx ; yes - Set the D.B. Page height to + ; to the maximum allowed. + +@@InvalidHeight: + mov [_ScrnLogicalHeight],ax ; Update logical screen height to + ; reflect the height of a D.B. page + cmp ax,[_BottomClip] + jle @@BottomClipOK ; Adjust Clip Rectangle if necessary + mov [_BottomClip],ax +@@BottomClipOK: + push ax + mul [_ScrnLogicalByteWidth] ; Calculate the offset of the second + mov cx,ax ; D.B. Page in video ram + mov bx,[_Page0_Offs] + mov [_VisiblePageOffs],bx + + add ax,bx + mov [_Page1_Offs],ax ; Save it + mov [_HiddenPageOffs],ax + + add ax,cx ; Calculate the offset of first byte + mov [_NonVisual_Offs],ax ; beyond the D.B. pages and save it + mov [_DoubleBufferActive],TRUE ; Set flag indicating D.B'ing mode on + + pop ax + sub ax,[_ScrnPhysicalHeight] + add ax,[_SplitScrnVisibleHeight] + mov [_MaxScrollY],ax + + mov ax,dx ; return the D.B. pages' height + mov [_ErrorValue],OK + pop bp + ret +_x_set_doublebuffer endp + + +;----------------------------------------------------------------------- +; Mode X (256 color mode) Enable TrippleBuffering on non split screen area +; C near-callable as: +; +; int x_set_tripplebuffer(unsigned int PageHeight); +; +; Params: PageHeight is the height of the virtual screen to tripple buffer +; Returns the closest possible height to the specified. +; +; Sets up two tripple buffering virtual pages +; GLOBAL variables set: +; +; _Page1_Offs Offset of second virtual page +; _Page2_Offs Offset of third virtual page +; _NonVisual_Offs Offset of first non visible video ram byte +; _DoubleBufferActive Flag +; _PageAddrTable Table of Double buffering pages start offsets +; _ScrnLogicalHeight Logical height of the double buffering pages +; +; +; Almost written by Tore Bastiansen (cut & paste from _x_set_doublebuffer) +;------------------------------------------------------------------------ + +_x_set_tripplebuffer proc + ARG PageHeight:word + push bp + mov bp,sp + + cmp [_DoubleBufferActive],0 + jne @@Error + cmp [_TrippleBufferActive],0 + je @@OkToContinue +@@Error: + mov [_ErrorValue],ERROR + pop bp + ret + +@@OkToContinue: + mov [_VisiblePageIdx],0 ; Set visible Page to 0 + mov ax,[_ScrnLogicalHeight] ; Set Maximum T.B. Page height to + mov bx,3 + xor dx,dx + idiv bx ; _ScrnLogicalHeight / 3 + + mov bx,[PageHeight] ; Is the require T.B. Page Height + cmp ax,bx ; > the Maximum T.B. Page Height ? + + js @@InvalidHeight ; no - jump + mov ax,bx ; yes - Set the T.B. Page height to + ; to the maximum allowed. + +@@InvalidHeight: + mov [_ScrnLogicalHeight],ax ; Update logical screen height to + ; reflect the height of a T.B. page + cmp ax,[_BottomClip] + jle @@BottomClipOK ; Adjust Clip Rectangle if necessary + mov [_BottomClip],ax +@@BottomClipOK: + push ax + mul [_ScrnLogicalByteWidth] ; Calculate the offset of the second + mov cx,ax ; D.B. Page in video ram + mov bx,[_Page0_Offs] + mov [_VisiblePageOffs],bx + + add ax,bx + mov [_Page1_Offs],ax ; Save it + mov [_HiddenPageOffs],ax + + add ax,cx + mov [_Page2_Offs],ax ; Save the other it ? + mov [_WaitingPageOffs],ax + + add ax,cx ; Calculate the offset of first byte + mov [_NonVisual_Offs],ax ; beyond the D.B. pages and save it + mov [_TrippleBufferActive],TRUE ; Set flag indicating T.B'ing mode on + + pop ax + sub ax,[_ScrnPhysicalHeight] + add ax,[_SplitScrnVisibleHeight] + mov [_MaxScrollY],ax + + mov ax,dx ; return the D.B. pages' height + mov [_ErrorValue],OK + pop bp + ret +_x_set_tripplebuffer endp + + +;----------------------------------------------------------------------- +; Set Clipping rectangle +; C callable as: +; +; +; int x_set_cliprect(WORD left,WORD top, WORD right, WORD bottom); +; +; +; NOTE clipping is byte oriented. "left" and "right" are in bytes not pixels. +; Only selected functions perform any clipping at all. +; +; Written by Themie Gouthas +;------------------------------------------------------------------------ + +_x_set_cliprect proc +ARG left:word,top:word,right:word,bottom:word + push bp + mov bp,sp + mov ax,[left] + mov bx,[right] + cmp bx,ax + jns @@CorrectXOrder + xchg bx,ax +@@CorrectXOrder: + mov [_LeftClip],ax + mov [_RightClip],bx + mov ax,[top] + mov bx,[bottom] + cmp bx,ax + jns @@CorrectYOrder + xchg bx,ax +@@CorrectYOrder: + mov [_TopClip],ax + mov [_BottomClip],bx + pop bp + ret +_x_set_cliprect endp + + +;---------------------------------------------------------------------- +; Return to text mode +; +_x_text_mode proc + push bp + call clear_vram + mov ax,03h ; Restore Text Mode + int 10h + + pop bp + ret +_x_text_mode endp + +;----------------------------------------------------------------------- +; Wait for Vertical sync +_x_wait_vsync proc + push bp + WaitVsyncStart + pop bp + ret +_x_wait_vsync endp + + + end diff --git a/16/xlib/xmain.inc b/16/xlib/xmain.inc new file mode 100755 index 00000000..44b40fc2 --- /dev/null +++ b/16/xlib/xmain.inc @@ -0,0 +1,31 @@ +;----------------------------------------------------------------------- +; +; XMAIN - Include file +; +; XMAIN.ASM export functions +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + + global _x_set_mode :proc + global _x_page_flip :proc + global _x_set_start_addr :proc + global _x_set_splitscreen :proc + global _x_text_mode :proc + global _x_set_mode :proc + global _x_select_default_plane :proc + global _x_hide_splitscreen :proc + global _x_show_splitscreen :proc + global _x_adjust_splitscreen :proc + global _x_set_doublebuffer :proc + global _x_set_tripplebuffer :proc + global _x_set_cliprect :proc + 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 index 00000000..58a9d99d --- /dev/null +++ b/16/xlib/xmakevbm.c @@ -0,0 +1,205 @@ +/*---------------------------------------------------------------------- +; MODULE XMAKEVBM +; +; Implements function to generate a Video bitmap (VBM) from a linear bitmap +; (LBM) +; +; Compile with Tasm. +; C callable. +; +; +; Based on "CreateMaskedAlignedImage" published in Dr Dobbs Journal +; by Michael Abrash (Jul - Aug 1991) +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; ****** Aeronautical Research Laboratory **************** +; ****** Defence Science and Technology Organisation **************** +; ****** Australia **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;-----------------------------------------------------------------------*/ +/* + Here is an outline of the XLIB image formats + + + PLANAR BITMAPS + -------------- + + Planar bitmaps as used by these functions have the following structure: + + BYTE 0 The bitmap width in bytes (4 pixel groups) range 1..255 + BYTE 1 The bitmap height in rows range 1..255 + BYTE 2..n1 The plane 0 pixels width*height bytes + BYTE n1..n2 The plane 1 pixels width*height bytes + BYTE n2..n3 The plane 2 pixels width*height bytes + BYTE n3..n4 The plane 3 pixels width*height bytes + + LINEAR BITMAPS + -------------- + + Linear bitmaps have the following structure: + + BYTE 0 The bitmap width in pixels range 1..255 + BYTE 1 The bitmap height in rows range 1..255 + BYTE 2..n The width*height bytes of the bitmap + + + VIDEO BITMAPS + ------------- + + WORD 0 Size Total size of this VBM structure in bytes + WORD 1 ImageWidth Width in bytes of the image (for all alignments) + WORD 2 ImageHeight Height in scan lines of the image + + WORD 3 Alignment 0 ImagePtr Offset in VidRAM of this aligned image + +--WORD 4 MaskPtr Offset (within this structure's DS) of + | . alignment masks + | . + | . + | WORD 9 Alignment 3 ImagePtr Offset in VidRAM of this aligned image + +|--WORD 10 MaskPtr Offset (within this structure's DS) of + || alignment masks + || + |+->BYTE 21 (WORD 11) -------+-- Image masks for alignment 0 + | . | + | . | + | BYTE 21 + ImageWidth*ImageHeight -----+ + | + | . + | . (similaly for alignments 1 - 2 ) + | . + | + +-->BYTE 21 + 3*ImageWidth*ImageHeight + 1-+-- Image masks for alignment 3 + . | + . | + BYTE 21 + 4*(ImageWidth*ImageHeight) --+ + + . + . + << Similarly for alignments 2 and 3 >> + . + . + BYTE 21 + 4*(ImageWidth*ImageHeight) + ------------- + + (And dont forget the corresponding data in video ram) + + +*/ + + + +#include +#include + +/* function to store the linear bitmap in the required video RAM offset */ +/* and in the required alignment */ + +extern unsigned int x_store_vbm_image(unsigned int, int, char far *); + + +/* Alignment structures, 4 of which make up the header section of the */ +/* video bitmap */ + +typedef struct { + unsigned int size; + unsigned int ImageWidth; + unsigned int ImageHeight; + struct { + unsigned int ImagePtr; + unsigned int MaskPtr; + } alignments[4]; +} alignment_header; + +/* Structure to extract width/height frol LBM (linear bit map) */ + +typedef struct { + unsigned char width; + unsigned char height; +} lbm_header; + + +/*************************************************************************/ +/* */ +/* Generates all four possible mode X image/mask alignments, stores */ +/* image alignments in display memory, allocates memory for and generates*/ +/* mask alignments, and fills out a VBM aligned masked image structure. */ +/* Each non-zero byte in source bitmap corresponds to image pixel to be */ +/* drawn. */ +/* On success returns a far pointer to the new VBM structure otherwise */ +/* it returns NULL */ +/* */ +/* Source Language: C */ +/* */ +/* Parameters: */ +/* lbm pointer to linear bitmap */ +/* vramStart contains the next available video offset which is */ +/* also updated after calling this function */ +/* */ +/*************************************************************************/ + +char far *x_make_vbm(char far *lbm, unsigned int *VramStart) +{ + + lbm_header far *lbm_headr; + alignment_header far *vbm_headr; + char far *vbm_mask_ptr,*p; + char far *lbm_pixel_ptr; + int align,BitNum,TempImageWidth; + unsigned int TempWidth,TempHeight,TempSize,MaskSize,VramOffs,MaskSpace=0; + int scanline; + unsigned char MaskTemp; + + VramOffs = *VramStart; + lbm_headr = (lbm_header far *) lbm; + + TempWidth = (lbm_headr->width+3)/4+1; + TempHeight = lbm_headr->height; + TempSize = TempWidth*TempHeight; + + vbm_headr = (alignment_header far *) farmalloc(22+TempSize*4); + if (!vbm_headr) return NULL; + + MaskSpace=22; + + vbm_headr->ImageWidth = TempWidth; + vbm_headr->ImageHeight = TempHeight; + vbm_headr->size = 22+TempSize*4; + for (align=0;align<4;align++){ + vbm_headr->alignments[align].ImagePtr = VramOffs; + x_store_vbm_image(VramOffs,align,lbm); + MaskSpace+=TempSize; + VramOffs+=TempSize; + } + + + vbm_mask_ptr = (char far *)vbm_headr+22; + + for (align=0;align<4;align++){ + lbm_pixel_ptr = lbm + 2; + vbm_headr->alignments[align].MaskPtr = FP_OFF(vbm_mask_ptr); + for (scanline=0;scanlinewidth; + do { + MaskTemp |= (*lbm_pixel_ptr++ !=0) << BitNum; + if (++BitNum > 3) { + *vbm_mask_ptr++=MaskTemp; + MaskTemp=BitNum=0; + } + } while (--TempImageWidth); + *vbm_mask_ptr++=(BitNum != 0)?MaskTemp:0; + } + + } + + *VramStart=VramOffs; + return (char far *) vbm_headr; +} + + + \ No newline at end of file diff --git a/16/xlib/xmouse.asm b/16/xlib/xmouse.asm new file mode 100755 index 00000000..fea4642a --- /dev/null +++ b/16/xlib/xmouse.asm @@ -0,0 +1,884 @@ +;----------------------------------------------------------------------- +; MODULE XMOUSE +; +; Mouse functions functions for all MODE X 256 Color resolutions +; +; Compile with Tasm. +; C callable. +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; This module is based on Shane Hyde's module of the same name, +; posted to Rec.Games.Programmer, October 92. +; +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; mouse cursor shape by Tiaan A Geldenhuys +; +;----------------------------------------------------------------------- + +COMMENT $ + + +This is a module implementing very basic mouse functions. + +It does not support the full functionality of: + + SPLIT SCREENS + SCROLLED WINDOWS + VIRTUAL WINDOWS + + -------------------------------------- + + MS Mouse Driver Functions + + Mouse Initialization 0 + Show Cursor 1 + Hide Cursor 2 + Get Mouse Position & Button Status 3 + Set Mouse Cursor Position 4 + Get Button Press Information 5 + Get Button Release Information 6 + Set Min/Max Horizontal Position 7 + Set Min/Max Vertical Position 8 + Define Graphics Cursor Block 9 + Define Text Cursor 10 + Read Mouse Motion Counters 11 + Define Event Handler 12 + Light Pen Emulation Mode ON 13 + Light Pen Emulation Mode OFF 14 + Set Mouse Mickey/Pixel Ratio 15 + Conditional Hide Cursor 16 + Set Double-Speed Threshold 19 + -------------------------------------- +$ + +include xlib.inc +include xdetect.inc + +.data + +global _MouseInstalled :word +global _MouseHidden :word +global _MouseButtonStatus :word +global _MouseX :word +global _MouseY :word +global _MouseFrozen :byte +global _MouseColor :byte + +global _x_define_mouse_cursor :proc +global _x_show_mouse :proc +global _x_hide_mouse :proc +global _x_mouse_remove :proc +global _x_position_mouse :proc +global _x_put_cursor :proc +global _x_update_mouse :proc +global _x_mouse_init :proc +global _x_mouse_window :proc + + +ALIGN 2 + + + + InitMouseDef db 00000001b ; Default mouse mask, note the reverse order + db 00000011b + db 00000111b + db 00001111b + db 00011111b + db 00111111b + db 01111111b + db 11111111b + db 00011111b + db 00011011b + db 00110001b + db 00110000b + db 01100000b + db 01100000b + + + +COMMENT $ + + Old mouse definition + + InitMouseDef db 00000001b ; Default mouse mask, note the reverse order + db 00000011b + db 00000111b + db 00001111b + db 00011111b + db 00111111b + db 01111111b + db 11111111b + db 00011100b + db 00111100b + db 01111100b + db 00000000b + db 00000000b + db 00000000b + +$ + + MouseMask db 168 dup(?) + OldHandlerSeg dw ? + OldHandlerOffs dw ? + OldHandlerMask dw ? + OldX dw ? + OldY dw ? + OldScrnOffs dw ? + + BGSaveOffs dw 0 + + _MouseInstalled dw 0 ; Flag indicating whether mouse is installed + _MouseHidden dw 0 ; Flag indicating whether mouse is hidden + _MouseButtonStatus dw 0 ; Holds current button press information + _MouseX dw 0 ; Coords of cursor hot spot + _MouseY dw 0 + _MouseFrozen db 0 ; Mouse motion enable/disable control + _MouseColor db 0 ; Mouse cursor colour + + inhandler db 0 +.code + +;---------------------------------------------------------------------- +; Local function that updates the cursor position +; +; Destroys SI,DI,AX,BX +; +;---------------------------------------------------------------------- +proc update_cursor near + WaitVsyncStart + + mov di,[OldScrnOffs] ; Delete cursor (restore old background) + mov ax,[OldY] + mov bx,[OldX] + + call restorebg + + mov si,[_VisiblePageOffs] ; Save cursor background + mov ax,[_MouseY] + mov bx,[_MouseX] + mov [OldScrnOffs],si + mov [OldY],ax + mov [OldX],bx + call getbg + + push [_VisiblePageOffs] ; Draw the cursor + mov ax,[_ScrnPhysicalHeight] + push ax + mov ax,0 + push ax + push [OldY] + push [OldX] + call _x_put_cursor + add sp,10 + ret +update_cursor endp + + +;---------------------------------------------------------------------- +; x_mouse_init - Initialise Mode X mouse handler +; +; C Prototype +; +; int x_mouse_init() +; +; This is the first function you must call before using any of the mouse +; functions +; +; WARNING: This function uses and updates "NonVisual_Offset" to allocate +; video ram for the saved mouse background. +; +; This mouse code uses the fastest possible techniques to save and restore +; mouse backgrounds and to draw the mouse cursor. +; +; LIMITATIONS: No clipping is supported horizontally for the mouse cursor +; No validity checking is performed for NonVisual_Offs +; +; +; **WARNING** Hide or freeze mouse while drawing using any of the other +; Modules. VGA register settings are not preserved which will +; result in unpredictable drawing behavior. +; If you know the drawing will occur away from the mouse cursor +; set MouseFrozen to TRUE (1), do your drawing then set it to +; FALSE (0). Alternatively call "x_hide_mouse", perform your +; drawing and then call "x_show_mouse" +; +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_mouse_init proc + push bp + mov bp,sp + + cmp [_MouseButtonCount],0 ; Dont initialize if mouse detection + jne @@DontInitialize ; or initialization function previously + ; called + xor ax,ax ; FUNC 0: Mouse Initialization + int 33h ; + or ax,ax ; Is there a mouse installed ? + jz @@Done + mov [_MouseButtonCount],bx ; Set the button count + +@@DontInitialize: + + mov [_MouseInstalled],ax + or ax,ax ; Do we have an installed mouse driver ? + jz @@Done ; Nop! + + mov ax,[_NonVisual_Offs]; ; Allocate VRAM for saved background + mov BGSaveOffs,ax + + add ax,14*3 + mov [_NonVisual_Offs],ax ; Update NonVisualOffset + + mov ax,02 ; FUNC 2: Hide Cursor + int 33h ; (hide the mouse driver's default cursor) + mov _MouseInstalled,TRUE ; Indicate user mouse driver present + + mov ax,07h ; FUNC 7:Set min/max horizontal position + mov cx,0 + mov dx,[_ScrnPhysicalPixelWidth] + shl dx,1 ; Mult X by 2 as cursor steps by 2 pixels + int 33h ; 0 < X < _ScrnPhysicalPixelWidth + + mov ax,08h ; FUNC 8:Set min/max vertical position + mov cx,0 + mov dx,_ScrnPhysicalHeight + int 33h ; 0 < Y < _ScrnPhysicalHeight + + mov ax,0fh ; FUNC 15: Mouse Hor/Vert resolution + mov cx,4 ; Horiz speed >> Value => << Speed + mov dx,8 ; Vert Speed + int 33h + + mov ax,3 ; FUNC 3: Get mouse pos & button status + int 33h + mov [_MouseY],dx + shr cx,1 + mov [_MouseX],cx + + mov ax,12 ; FUNC 12: Define Event Handler + mov bx,seg mouse_handler ; ES:DX -> Event handler + mov es,bx + mov dx,offset mouse_handler + mov cx,1fh ; Set handler for all events + int 33h + + + + mov [_MouseHidden],TRUE ; Mouse initially hidden + + push ds ; Set the default cursor shape + mov ax,offset InitMouseDef + push ax + call _x_define_mouse_cursor + add sp,04h + + mov ax,[_MouseInstalled] ; Return MouseInstalled flag +@@Done: + pop bp + ret +_x_mouse_init endp + +;---------------------------------------------------------------------- +; x_mouse_window - Define a mouse window +; +; C Prototype +; +; void x_mouse_window(int x0, int y0, int x1, int y1); +; +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_mouse_window proc +ARG x0:word,y0:word,x1:word,y1:word + push bp + mov bp,sp + + mov ax,7 ; FUNC 7: Set X range + mov cx,x0 + shl cx,1 + mov dx,x1 + shl dx,1 + int 33h + + mov ax,8 ; FUNC 8: Set Y range + mov cx,y0 + mov dx,y1 + int 33h + pop bp + ret +_x_mouse_window endp + + +;---------------------------------------------------------------------- +; x_define_mouse_cursor - Define a mouse cursor from an input bitmask +; +; C Prototype +; +; void x_define_mouse_cursor(char far *MouseDef, unsigned char MouseColor) +; +; WARNING: This function assumes MouseDef points to 14 bytes. +; +; Note: Bit order is in reverse. ie bit 7 represents pixel 0 .. +; bit 0 represents pixel 7 in each "MouseDef" byte. +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_define_mouse_cursor proc +ARG MouseDef:dword,MouseColor:byte + push bp + mov bp,sp + + cmp [_MouseInstalled],FALSE ; Check whether we have installed + je @@Done ; our mouse handler and leave if not + + mov al,[MouseColor] ; Set the mouse pointers color + mov [_MouseColor],al + + push si + push di + push ds + mov ax,ds ; ES:DI -> Stored plane mask for all + mov es,ax ; pixel alignments of mouse cursor + mov di,offset MouseMask + lds si,MouseDef + xor cl,cl ; CL = current alignment (initially zero) +@@AlignmentLoop: + push si ; save MouseDef ptr for next alignment + mov dh,14 ; Init Row counter to Cursor Height +@@RowLoop: + lodsb ; Load first cursor def byte each bit + ; representing pixel in the row + xor ah,ah ; AH is the shift overflow byte + shl ax,cl ; Shift mask for current alignment + + mov bl,al ; store first three nibbles of ax into + and bl,0fh ; consecutive bytes in the destination + mov es:[di],bl ; buffer + inc di + shr al,4 + stosw + + dec dh ; Next row for this alignment if there + jnz @@RowLoop ; are more to do + + pop si ; point to the start of the cursor def. + inc cl ; Select next pixel alignment + cmp cl,4 ; If there are more alignments to do + jne @@AlignmentLoop ; then jump + + pop ds + pop di + pop si +@@Done: + pop bp + ret +_x_define_mouse_cursor endp + + +;---------------------------------------------------------------------- +; x_show_mouse - Shows a previously hidden mouse cursor +; +; C Prototype +; +; void x_show_mouse() +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_show_mouse proc + push bp + mov bp,sp + cmp [_MouseInstalled],FALSE ; Make sure our handler is installed + je @@Done + cmp [_MouseHidden],FALSE ; If not hidden then exit + je @@Done + push si + push di + + +@@WaitEndOfHandler: ; Make sure handler not currently active + mov cl,[inhandler] + or cl,cl + jnz @@WaitEndOfHandler + + + mov si,[_VisiblePageOffs] ; Save mouse background and pos details + mov ax,[_MouseY] + mov bx,[_MouseX] + mov [OldScrnOffs],si + mov [OldY],ax + mov [OldX],bx + call getbg + + push [_VisiblePageOffs] ; Draw cursor + push [_ScrnLogicalHeight] + xor ax,ax + push ax + push [OldY] + push [OldX] + call _x_put_cursor + add sp,10 + + mov [_MouseHidden],FALSE ; Indicate mouse cursor no longer hidden + + pop di + pop si +@@Done: + pop bp + ret +_x_show_mouse endp + + +;---------------------------------------------------------------------- +; x_hide_mouse - Hides a previously visible mouse cursor +; +; C Prototype +; +; void x_hide_mouse() +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_hide_mouse proc + push bp + mov bp,sp + + cmp [_MouseInstalled],FALSE ; Make sure our handler is installed + je @@Done + cmp [_MouseHidden],FALSE ; If cursor is already hidden exit + jne @@Done + push si + push di + +@@WaitEndOfHandler: ; Make sure handler not currently active + mov cl,[inhandler] + or cl,cl + jnz @@WaitEndOfHandler + + mov [_MouseHidden],TRUE ; Delete mouse cursor + mov di,[OldScrnOffs] + mov ax,[OldY] + mov bx,[OldX] + call restorebg + pop di + pop si +@@Done: + pop bp + ret +_x_hide_mouse endp + + +;---------------------------------------------------------------------- +; x_remove_mouse - removes mouse handler +; +; C Prototype +; +; void x_remove_mouse() +; +; NOTE: This function MUST be called before quitting the program if +; a mouse handler has been installed +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_mouse_remove proc + push bp + mov bp,sp + cmp [_MouseInstalled],FALSE ; Check whether we have installed + je @@Done ; our mouse handler + call _x_hide_mouse + mov ax,12 ; FUNC 12: Install event handler + xor cx,cx ; Disable all events + int 33h + mov [_MouseInstalled],FALSE +@@Done: + pop bp + ret +_x_mouse_remove endp + + +;---------------------------------------------------------------------- +; x_position_mouse - Positions the mouse cursor at the specified location +; +; C Prototype +; +; void x_position_mouse(int x, int y) +; +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_position_mouse proc +ARG X:word,Y:word + push bp + mov bp,sp + +@@WaitEndOfHandler: ; Make sure handler not currently active + mov bl,[inhandler] + + or bl,bl + jnz @@WaitEndOfHandler + + mov ax,4 + mov cx,X + mov dx,Y + mov [_MouseX],cx + mov [_MouseY],dx + shl cx,1 + + mov [inhandler],1 + int 33h + + ; The handler doesnt get called so need + ; to update manually; + + cmp [_MouseHidden],FALSE + jne @@NotVisible + push di si + call update_cursor + pop si di + +@@NotVisible: + mov [inhandler],0 + pop bp + ret +_x_position_mouse endp + +;---------------------------------------------------------------------- +; x_update_mouse - Forces the mouse position to be updated and cursor +; to be redrawn. +; +; C Prototype +; +; void x_update_mouse() +; +; Note this function is useful when you have set "MouseFrozen" to true. +; Allows the cursor position to be updated manually rather than +; automatically by the installed handler. +; +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_update_mouse proc + push bp + mov bp,sp + cmp [_MouseInstalled],FALSE ; Make sure our handler is installed + je @@Done + cmp [_MouseHidden],FALSE ; If cursor is already hidden exit + jne @@Done + push si + push di + mov ax,03h ; FUNC 3: get cursor pos / button status + int 33h ; Update position variables first + shr cx,1 + mov [_MouseX],cx + mov [_MouseY],dx + mov [_MouseButtonStatus],bx ; Update button status + call update_cursor + pop di + pop si +@@Done: + pop bp + ret +_x_update_mouse endp + + +;---------------------------------------------------------------------- +; x_put_cursor - Draws the mouse cursor +; +; C Prototype +; +; void x_put_cursor(int X, int Y, int TopClip, int BottomClip, WORD ScrnOffs) +; +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +ALIGN 2 +_x_put_cursor proc +ARG X:word,Y:word,TopClip,BottomClip,ScrnOffs +LOCAL Height,TopRow,NextLineIncr:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + mov ax,@data + mov ds,ax + cld + + mov ax,14 ; Get image height and save in AX + mov bx,Y + ; cx = top Row + + ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;; + + mov dx,[TopClip] ; Compare u.l. Y coord with Top + sub dx,bx ; clipping border + jle @@NotTopClip ; jump if not clipped from above + cmp dx,ax + jnl @@NotVisible ; jump if is completely obscured + mov cx,dx + sub ax,dx + add bx,dx + jmp short @@VertClipDone + + ;;;; EXIT FOR COMPLETELY OBSCURED ;;;;;;;;;;;;;;;;;;;;;; + +@@NotVisible: + pop ds + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret + + ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;; + +@@NotTopClip: + mov dx,[BottomClip] + sub dx,bx + js @@NotVisible + mov cx,0 + cmp dx,ax + jg @@VertClipDone + inc dx + mov ax,dx + +@@VertClipDone: + + mov [Height],ax + mov [TopRow],cx + + mov ax,SCREEN_SEG ; Point es to VGA segment + mov es,ax + + mov ax,bx + mov cx,[_ScrnLogicalByteWidth] ; Find required screen address + mul cx + mov di,ax + + sub cx,3 ; Distance to next screen row + mov [NextLineIncr],cx + + + mov cx,[X] + mov bx,cx + shr cx,2 + add di,cx + and bx,3 + add di,[ScrnOffs] + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + + mov ax,42 + mul bx + mov si,offset MouseMask + add si,ax + + mov ax,3 ; Increment DS:BX and DS:SI to + mul [TopRow] ; been clipped by the top border + add si,ax ; by the L.H.S border + + mov dx,SC_INDEX ; Point SC register to map mask + mov al,MAP_MASK ; in preperation for masking data + out dx,al + inc dx ; Point dx to SC data register + mov ah,byte ptr [Height] ; AH = Scanline loop counter + mov bl,[_MouseColor] +@@RowLoop: + mov cx,3 ; Width in bytes across +@@ColLoop: + lodsb ; load plane mask and set MAP MASK + out dx,al + mov es:[di],bl ; store color to specified planes + inc di + loop @@ColLoop + + add di,[NextLineIncr] + dec ah + jnz @@RowLoop + + pop ds + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_put_cursor endp + + +;---------------------------------------------------------------------- +; getbg - saves cursor background +; +; C Prototype +; +; local function using register parameters +; +; si = screen offset +; ax = y +; bx = x +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +ALIGN 2 +getbg proc near + + push bp + mov bp,sp + push ds + cld + + mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen + mul cx ; width then adding screen offset + add si,ax ; Add Dest Screen Row to di + sub cx,3 + shr bx,2 + add si,bx + mov bx,cx + + mov di,BGSaveOffs + mov ax,SCREEN_SEG ; Point es to VGA segment + mov es,ax + mov ds,ax + + mov dx,GC_INDEX ; Set bit mask for all bits from + mov ax,BIT_MASK ; VGA latches and none from CPU + out dx,ax + + mov dx,SC_INDEX ; Point SC register to map mask + mov al,MAP_MASK ; in preperation for masking data + out dx,al + inc dx + mov al,0fh + out dx,al + + mov cx,14 +@@Loop: + movsb + movsb + movsb + add si,bx + loop @@Loop + +mov dx,GC_INDEX+1 ;restore the bit mask to its default, + mov al,0ffh ; which selects all bits from the CPU + out dx,al ; and none from the latches (the GC + ; Index still points to Bit Mask) + + pop ds + mov sp,bp ; dealloc local variables + pop bp + ret +getbg endp + +;---------------------------------------------------------------------- +; restorebg - restores cursor background +; +; C Prototype +; +; local function using register parameters +; +; di = screen offset +; ax = y +; bx = x +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +ALIGN 2 +restorebg proc near +;di = scrn offs +;ax = y +;bx = x + push bp + mov bp,sp + push ds + cld + + mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen + mul cx ; width then adding screen offset + add di,ax ; Add Dest Screen Row to di + sub cx,3 + shr bx,2 + add di,bx + mov si,BGSaveOffs + mov ax,SCREEN_SEG ; Point es to VGA segment + mov es,ax + mov ds,ax + + mov dx,GC_INDEX ; Set bit mask for all bits from + mov ax,BIT_MASK ; VGA latches and none from CPU + out dx,ax + + mov dx,SC_INDEX ; Point SC register to map mask + mov al,MAP_MASK ; in preperation for masking data + out dx,al + inc dx + mov al,0fh + out dx,al + + mov bx,cx + mov cx,14 +@@Loop: + movsb + movsb + movsb + add di,bx + loop @@Loop + mov dx,GC_INDEX+1 ;restore the bit mask to its default, + mov al,0ffh ; which selects all bits from the CPU + out dx,al ; and none from the latches (the GC + ; Index still points to Bit Mask) + pop ds + pop bp + ret +restorebg endp + + + +;********************** The Mouse event handler ************************* + +ALIGN 2 +mouse_handler proc far + push bp + mov bp,sp + push ds + + mov di,@data ; Make sure DS points to data segment + mov ds,di + cmp [inhandler],1 + jne @@NotActive + pop ds + pop bp + ret + +@@NotActive: + mov [inhandler],1 + mov [_MouseButtonStatus],bx ; Update button status + test ax,1 ; Is this a motion event ? + jz @@Done ; No Jump + + shr cx,1 ; convert X coord to pixel coords + mov [_MouseX],cx ; save mouse position + mov [_MouseY],dx + + cmp [_MouseHidden],TRUE ; If mouse hidden dont bother drawing + je @@Done + + cmp [_MouseFrozen],TRUE ; If mouse hidden dont bother drawing + je @@Done + + call update_cursor +@@Done: + mov [inhandler],0 + pop ds + pop bp + ret +mouse_handler endp + + +end diff --git a/16/xlib/xmouse.h b/16/xlib/xmouse.h new file mode 100755 index 00000000..144bde53 --- /dev/null +++ b/16/xlib/xmouse.h @@ -0,0 +1,80 @@ +/*----------------------------------------------------------------------- +; +; XMOUSE - header file +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;-----------------------------------------------------------------------*/ + +#ifndef _XMOUSE_H_ +#define _XMOUSE_H_ + +#define LEFT_PRESSED 1 +#define RIGHT_PRESSED 2 + +/* GLOBAL VARS ========================================================= */ + +extern WORD MouseInstalled; /* Indicates whether mouse handler installed */ +extern WORD MouseHidden; /* Indicates whether mouse cursor is hidden */ +extern WORD MouseButtonStatus;/* Holds the mouse button status */ +extern WORD MouseX; /* Current X position of mouse cursor */ +extern WORD MouseY; /* Current Y position of mouse cursor */ +extern BYTE MouseFrozen; /* Disallows position updates if TRUE */ +extern BYTE MouseColor; /* The mouse cursors colour */ + +/* FUNCTIONS =========================================================== */ + +#ifdef __cplusplus +extern "C" { +#endif + + + +void x_mouse_init(void); /* Initialize mouse cursor */ + +void x_define_mouse_cursor( /* Define and set a cursor shape */ + char far MouseDef, + int color); + +void x_update_mouse(void); /* Force mouse cursor position update */ + +void x_show_mouse(void); /* Show mouse cursor if hidden */ + +void x_hide_mouse(void); /* Hide mouse cursor if visible */ + +void x_mouse_remove(void); /* Remove installed mouse handler */ + +void x_position_mouse( /* Set the mouse position */ + int x, + int y); + +void x_put_cursor( /* Draw the mouse cursor (NOT FOR */ + int x, /* general use) */ + int y, + int topclip, + int botclip, + WORD ScrnOff); + + +void x_mouse_window(int x0, /* Define a mouse window */ + int y0, + int x1, + int y1); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/16/xlib/xpal.asm b/16/xlib/xpal.asm new file mode 100755 index 00000000..558f2665 --- /dev/null +++ b/16/xlib/xpal.asm @@ -0,0 +1,576 @@ +;----------------------------------------------------------------------- +; MODULE XPAL +; +; Palette functions all MODE X 256 Color resolutions +; +; Compile with Tasm. +; C callable. +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + +COMMENT $ + + + + All the functions in this module operate on two variations of the + pallete buffer, the raw and annotated buffers. + + All those functions ending in buff operate on the following palette + structure: + + BYTE:r0,g0,b0,r1,g1,b1,...rn,gn,bn + + No reference to the starting colour index or number of colours stored + is contained in the structure. + + All those functions ending in struc operate on the following palette + structure: + + BYTE:c,BYTE:n,BYTE:r0,g0,b0,r1,g1,b1,...rn,gn,bn + + where c is the starting colour and n is the number of colours stored + + + NOTE: previously interrupts were disabled for DAC reads/writes but + they have been left enabled in this version to allow the mouse + interrupt to be invoked. + +$ + + + + +include xlib.inc +include xpal.inc + +.code + + +;---------------------------------------------------------------------- +; Read DAC palette into annotated type buffer with interrupts disabled +; ie BYTE colours to skip, BYTE colours to set, r1,g1,b1,r1,g2,b2...rn,gn,bn +; +; x_get_pal_struc(char far * pal, int num_colrs, int start_color) +; +; WARNING: memory for the palette buffers must all be pre-allocated +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_get_pal_struc proc +ARG PalBuff:dword,NumColors:word,StartColor:word + push bp ; Set up stack frame + mov bp,sp + push di + push si + cld + + les di,dword ptr [PalBuff] ; Point es:di to palette buffer + mov si,[StartColor] ; Store the Start Colour + mov ax,si + stosb + mov dx,[NumColors] ; Store the Number of Colours + mov al,dl + stosb + + mov cx,dx ; setup regs and jump + jmp short ReadPalEntry + +_x_get_pal_struc endp + + + + + +;---------------------------------------------------------------------- +; Read DAC palette into raw buffer with interrupts disabled +; ie BYTE r1,g1,b1,r1,g2,b2...rn,gn,bn +; +; x_get_pal_raw(char far * pal, int num_colrs, int start_index) +; +; WARNING: memory for the palette buffers must all be pre-allocated +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_get_pal_raw proc +ARG PalBuff:dword,NumColors:word,StartColor:word + push bp ; Set up stack frame + mov bp,sp + push di + push si + + les di,dword ptr [PalBuff] ; Point es:di to palette buffer + + mov si,[StartColor] + mov cx,[NumColors] + +ReadPalEntry: + cld + WaitVsyncStart + mov ax,si + mov dx,DAC_READ_INDEX + ;cli + out dx,al ; Tell DAC what colour to start reading + mov dx,DAC_DATA + + mov bx,cx ; set cx to Num Colors * 3 ( size of + shl bx,1 ; palette buffer) + add cx,bx + + rep insb ; read the palette enntries + + ;sti + pop si + pop di + pop bp + ret +_x_get_pal_raw endp + + + +;---------------------------------------------------------------------- +; Write DAC palette from annotated type buffer with interrupts disabled +; ie BYTE colours to skip, BYTE colours to set, r1,g1,b1,r1,g2,b2...rn,gn,bn +; +; x_put_pal_struc(char far * pal) +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- + +_x_put_pal_struc proc +ARG CompPalBuff:dword + push bp ;preserve caller's stack frame + mov bp,sp ;point to local stack frame + push ds + push si + cld + lds si,[CompPalBuff] ; load the source compressed colour data + lodsb ; get the colours to skip + mov ah,0 + mov bx,ax ; skip colours + + lodsb ; get the count of colours to set + mov ah,0 + mov cx,ax ; use it as a loop counter + jmp short WritePalEntry + +_x_put_pal_struc endp + + +;---------------------------------------------------------------------- +; Write DAC palette from annotated type buffer with interrupts disabled +; starting at a new palette index +; +; ie BYTE colours to skip, BYTE colours to set, r1,g1,b1,r1,g2,b2...rn,gn,bn +; +; x_transpose_pal_struc(char far * pal, int StartColor) +; +; WARNING: memory for the palette buffers must all be pre-allocated +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- + +_x_transpose_pal_struc proc +ARG CompPalBuff:dword,StartColor:word + push bp ;preserve caller's stack frame + mov bp,sp ;point to local stack frame + push ds + push si + cld + lds si,[CompPalBuff] ; load the source compressed colour data + mov bx,[StartColor] + mov [si],bl + inc si + lodsb ; get the count of colours to set + mov ah,0 + mov cx,ax ; use it as a loop counter + jmp short WritePalEntry +_x_transpose_pal_struc endp + + +;---------------------------------------------------------------------- +; Write DAC palette from raw buffer with interrupts disabled +; ie BYTE r1,g1,b1,r1,g2,b2...rn,gn,bn +; +; _x_put_pal_raw(char far * pal, int num_colrs, int start_index) +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_put_pal_raw proc +ARG PalBuff:dword,NumColors:word,StartColor:word + push bp ; Set up stack frame + mov bp,sp + push ds + push si + + mov cx,[NumColors] ; Number of colours to set + mov bx,[StartColor] + lds si,[PalBuff] ; ds:si -> palette buffer + + +WritePalEntry: + mov ax,@data + mov es,ax + cmp es:[_VsyncHandlerActive],TRUE + jne @@NoVsyncHandler +@@WaitForLast: + cmp es:[_VsyncPaletteCount],0 + jne @@WaitForLast + push cx + push es + mov di, offset _VsyncPaletteBuffer + mov ax,3 + mul cx + mov cx,ax + rep movsb + pop ds + pop cx + mov [_VsyncPaletteStart],bx + mov [_VsyncPaletteCount],cx + jmp short @@Done +@@NoVsyncHandler: + + + or cx,cx + jz @@Done + ;cli + cld ; Make sure we're going the right way + WaitVsyncStart ; Wait for vert sync to start + mov ax,bx + mov bx,60 ; set the vsync check timer (Vsync + ; is tested for at each bx'th entry to + ; prevent snow 60 is otimum for 10 + ; MHz 286 or greater + +@@SetLoop: + mov dx,DAC_WRITE_INDEX ; Tell DAC what colour index to start + out dx,al ; writing from + mov dx,DAC_DATA + + outsb ; Set the red component + outsb ; Set the green component + outsb ; Set the blue component + inc al ; increment the colour index + dec bx ; decrement vsync test counter + js @@test_vsync ; ready to test for vsync again ? + loop @@SetLoop ; No! - continue loop + jmp short @@Done ; All colours done + +@@test_vsync: + mov dx,INPUT_STATUS_0 + push ax ; save current colour index +@@Wait: + in al,dx ; wait for vsync leading edge pulse + test al,08h + jz @@Wait + + pop ax ; restore current colour index + mov bx,60 ; reset vsync test counter + loop @@SetLoop ; loop for next colour index + +@@Done: + ;sti + pop si + pop ds + pop bp + ret +_x_put_pal_raw endp + + + +;---------------------------------------------------------------------- +; Set the RGB setting of a vga color +; +; _x_set_rgb(unsigned char color, unsigned char R,unsigned char G, +; unsigned char B) +; +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_set_rgb proc +ARG ColorIndex:byte,R:byte,G:byte,B:byte + push bp ; Set up stack frame + mov bp,sp + + mov al,[ColorIndex] + mov dx,DAC_WRITE_INDEX ; Tell DAC what colour index to + out dx,al ; write to + mov dx,DAC_DATA + + mov al,[R] ; Set the red component + out dx,al + mov al,[G] ; Set the green component + out dx,al + mov al,[B] ; Set the blue component + out dx,al + pop bp + ret +_x_set_rgb endp + + +;---------------------------------------------------------------------- +; Rotate annotated palette buffer entries +; +; x_rot_pal_struc(char far * pal, int direction) +; +; Direction : 0 = backward 1 = forward +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_rot_pal_struc proc +ARG PalBuff:dword,Direction:word + push bp ; Set up stack frame + mov bp,sp + push ds + push si + push di + + cld + lds si,dword ptr [PalBuff] ; point ds:si to Palette buffer + lodsw ; al = colorst ot skip, ah = num colors + + xor ch,ch ; Set the number of palette entries to cycle in cx + mov cl,ah ; + + jmp short RotatePalEntry + +_x_rot_pal_struc endp + + + +;---------------------------------------------------------------------- +; Rotate raw palette buffer +; +; x_rot_pal_raw(char far * pal, int direction, int num_colrs) +; +; Direcction : 0 = backward 1 = forward +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_rot_pal_raw proc +ARG PalBuff:dword,Direction:word,NumColors:word + push bp ; Set up stack frame + mov bp,sp + push ds + push si + push di + + cld + mov cx,[NumColors] ; Set the number of palette entries to cycle + lds si,dword ptr [PalBuff] ; point ds:si to Palette buffer + +RotatePalEntry: + + + mov ax,ds ; copy ds to es + mov es,ax + + dec cx + mov bx,cx ; Multiply cx by 3 + shl bx,1 + add cx,bx + + cmp [Direction],0 ; are we going forward ? + jne @@forward ; yes - jump (colors move one position back) + + std ; no - set reverse direction + add si,cx ; set si to last byte in palette + add si,2 + +@@forward: + mov ax,si ; copy si to di + mov di,ax + + lodsb ; load first color triplet into regs + mov dl,al + lodsb + mov dh,al + lodsb + mov bl,al + + rep movsb ; move remaining triplets direction indicated + ; by direction flag + + mov al,dl ; write color triplet from regs to last position + stosb + mov al,dh + stosb + mov al,bl + stosb + + pop di + pop si + pop ds + pop bp + ret +_x_rot_pal_raw endp + +;---------------------------------------------------------------------- +; Copy palette making intensity adjustment +; x_cpcontrast_pal_struc(char far *src_pal, char far *dest_pal, unsigned char Intensity) +; +; WARNING: memory for the palette buffers must all be pre-allocated +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_cpcontrast_pal_struc proc +ARG PalSrcBuff:dword,PalDestBuff:dword,Intensity:byte + push bp ; Set up stack frame + mov bp,sp + push ds + push si + push di + + cld + mov bh,0ffh + sub bh,[Intensity] + and bh,07fh ; Palettes are 7 bit + lds si,dword ptr [PalSrcBuff] ; point ds:si to Source Palette buffer + les di,dword ptr [PalDestBuff] ; point ds:si to Source Palette buffer + lodsw ; al = colorst ot skip, ah = num color + stosw + + xor ch,ch ; Set the number of palette entries to adjust + mov cl,ah ; + + mov dx,0 ; flag set to 0 if all output palette entries zero +@@MainLoop: + lodsw + sub al,bh ; adjust intensity and copy RED + jns @@DecrementOK_R + xor al,al +@@DecrementOK_R: + sub ah,bh ; adjust intensity and copy GREEN + jns @@DecrementOK_G + xor ah,ah +@@DecrementOK_G: + or dx,ax + or dl,ah + stosw + lodsb + sub al,bh ; adjust intensity and copy BLUE + jns @@DecrementOK_B + xor al,al +@@DecrementOK_B: + or dl,al + stosb + loop @@MainLoop + + mov ax,dx + pop di + pop si + pop ds + pop bp + ret +_x_cpcontrast_pal_struc endp + + + +;---------------------------------------------------------------------- +; Write DAC palette from annotated type buffer with specified intensity +; ie BYTE colours to skip, BYTE colours to set, r1,g1,b1,r1,g2,b2...rn,gn,bn +; +; x_put_contrast_pal_struc(char far * pal, unsigned char intensity) +; +; Designed for fading in or out a palette without using an intermediate +; working palette buffer ! (Slow but memory efficient ... OK for small +; pal strucs} +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- + +_x_put_contrast_pal_struc proc +ARG CompPalBuff:dword,Intensity:byte + push bp ;preserve caller's stack frame + mov bp,sp ;point to local stack frame + push ds + push si + push di + cld + + mov bh,0ffh + sub bh,[Intensity] + and bh,07fh ; Palettes are 7 bit + mov di,40 ; set the vsync check timer (Vsync + ; is tested for at each di'th entry to + ; prevent snow 40 is otimum for 10 + ; MHz 286 or greater) + lds si,[CompPalBuff] ; load the source compressed colour data + lodsb ; get the colours to skip + mov bl,al + + lodsb ; get the count of colours to set + mov ah,0 + mov cx,ax ; use it as a loop counter + or cx,cx + jz @@Done + + WaitVsyncStart ; Wait for vert sync to start + +@@MainLoop: + mov al,bl + mov dx,DAC_WRITE_INDEX ; Tell DAC what colour index to start + out dx,al ; writing from + inc dx ; == mov dx,DAC_DATA + + lodsb ; Load each colour component, modify for + sub al,bh ; intensity and write to DAC H/Ware + jns @@DecrementOK_R + xor al,al +@@DecrementOK_R: + out dx,al + + lodsb + sub al,bh + jns @@DecrementOK_G + xor al,al +@@DecrementOK_G: + out dx,al + + lodsb + sub al,bh + jns @@DecrementOK_B + xor al,al +@@DecrementOK_B: + out dx,al + + inc bl ; increment color index + dec di ; decrement vsync test flag + js @@test_vsync + loop @@MainLoop + jmp short @@Done + + +@@test_vsync: + mov dx,INPUT_STATUS_0 + push ax ; save current colour index +@@Wait: + in al,dx ; wait for vsync leading edge pulse + test al,08h + jz @@Wait + + pop ax ; restore current colour index + mov di,40 ; reset vsync test counter + loop @@MainLoop ; loop for next colour index + +@@Done: + ;sti + pop di + pop si + pop ds + pop bp + ret + +_x_put_contrast_pal_struc endp + + + end + + diff --git a/16/xlib/xpal.h b/16/xlib/xpal.h new file mode 100755 index 00000000..04c1c704 --- /dev/null +++ b/16/xlib/xpal.h @@ -0,0 +1,87 @@ +/*----------------------------------------------------------------------- +; +; XPAL - header file +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;----------------------------------------------------------------------*/ + +#ifndef _XPAL_H_ +#define _XPAL_H_ + +#define PAL_ROTATE_DOWN 0 +#define PAL_ROTATE_UP 1 + +/* FUNCTIONS =========================================================== */ + +#ifdef __cplusplus +extern "C" { +#endif + + + void x_get_pal_raw( /* Read DAC palette into raw buffer */ + BYTE far * pal, + WORD num_colrs, + WORD start_index); + + void x_get_pal_struc( /* Read DAC palette into annotated buffer */ + BYTE far * pal, + WORD num_colrs, + WORD start_index); + + void x_put_pal_raw( /* Write DAC palette from raw buffer */ + BYTE far * pal, + WORD num_colrs, + WORD start_index); + + void x_put_pal_struc( /* Write DAC palette from annotated buffer*/ + BYTE far * pal); + + x_set_rgb( /* Set the RGB components of a color index*/ + BYTE color, + BYTE red_c, + BYTE green_c, + BYTE blue_c); + + x_rot_pal_raw( /* Rotate a raw palette buffer */ + BYTE far * pal, + WORD direction, + WORD num_colrs); + + void x_rot_pal_struc( /* Rotate an anottated palette buffer */ + BYTE far * pal, + WORD direction); + + WORD x_cpcontrast_pal_struc( /* Copy and contrast adjust annotated */ + BYTE far *src_pal, /* palette buffer */ + BYTE far *dest_pal, + BYTE Intensity); + + void x_transpose_pal_struc( /* Write DAC palette from annotated type*/ + BYTE far * pal, /* buffer with a new offset */ + WORD StartColor); + + void x_put_contrast_pal_struc( /* Write DAC palette from annotated */ + BYTE far * pal, /* type buffer with specified intensity */ + BYTE intensity); + +#ifdef __cplusplus +} +#endif + + +#endif + + diff --git a/16/xlib/xpal.inc b/16/xlib/xpal.inc new file mode 100755 index 00000000..1e8c607b --- /dev/null +++ b/16/xlib/xpal.inc @@ -0,0 +1,32 @@ +;----------------------------------------------------------------------- +; +; XPAL - Include file +; +; XPAL.ASM export functions +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + global _x_get_pal_struc :proc + global _x_get_pal_raw :proc + + global _x_put_pal_struc :proc + global _x_put_pal_raw :proc + global _x_set_rgb :proc + + global _x_rot_pal_struc :proc + global _x_rot_pal_raw :proc + + + global _x_put_contrast_pal_struc:proc + + global _x_transpose_pal_struc :proc + + global _x_cpcontrast_pal_struc :proc \ No newline at end of file diff --git a/16/xlib/xpbitmap.asm b/16/xlib/xpbitmap.asm new file mode 100755 index 00000000..e0a2d961 --- /dev/null +++ b/16/xlib/xpbitmap.asm @@ -0,0 +1,603 @@ +;----------------------------------------------------------------------- +; MODULE XPBITMAP +; +; Planar Bitmap functions - System Ram <-> Video Ram +; +; Compile with Tasm. +; C callable. +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + +COMMENT $ + + This module implements a set of functions to operate on planar bitmaps. + Planar bitmaps as used by these functions have the following structure: + + BYTE 0 The bitmap width in bytes (4 pixel groups) range 1..255 + BYTE 1 The bitmap height in rows range 1..255 + BYTE 2..n1 The plane 0 pixels width*height bytes + BYTE n1..n2 The plane 1 pixels width*height bytes + BYTE n2..n3 The plane 2 pixels width*height bytes + BYTE n3..n4 The plane 3 pixels width*height bytes + + These functions provide the fastest possible bitmap blts from system ram to + to video and further, the single bitmap is applicable to all pixel + allignments. The masked functions do not need separate masks since all non + zero pixels are considered to be masking pixels, hence if a pixel is 0 the + corresponding screen destination pixel is left unchanged. + + +$ + +include xlib.inc +include xpbitmap.inc +LOCALS + .code + +;---------------------------------------------------------------------- +; x_flip_masked_pbm - mask write a planar bitmap from system ram to video ram +; all zero source bitmap bytes indicate destination byte to be left unchanged +; If "Orientation" is set then the bitmap is flipped from left to right as +; it is drawn +; +; Source Bitmap structure: +; +; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1).., +; Bitmap data (plane 2)..,Bitmap data (plane 3).. +; +; note width is in bytes ie lots of 4 pixels +; +; x_flip_masked_pbm(X,Y,ScrnOffs,char far * Bitmap, Orientation) +; +; +; LIMITATIONS: No clipping is supported +; Only supports bitmaps with widths which are a multiple of +; 4 pixels +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_flip_masked_pbm proc + ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword,Orientation:word + LOCAL Plane:byte,BMHeight:byte,LineInc:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + mov ax,SCREEN_SEG + mov es,ax + mov ax,[Y] ; Calculate dest screen row + mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen + mul bx ; width then adding screen offset + mov di,[ScrnOffs] ; store result in DI + add di,ax + mov cx,[X] ; Load X coord into CX and make a + mov dx,cx ; copy in DX + shr dx,2 ; Find starting byte in dest row + add di,dx ; add to DI giving screen offset of + ; first pixel's byte + lds si,[Bitmap] ; DS:SI -> Bitmap data + lodsw ; Al = B.M. width (bytes) AH = B.M. + ; height + cmp Orientation,0 + jz UnFlippedMasked + + mov [BMHeight],ah ; Save source bitmap dimensions + xor ah,ah ; LineInc = bytes to the begin. + add bx,ax ; of bitmaps next row on screen + mov [LineInc],bx + mov bh,al ; Use bh as column loop count + and cx,0003h ; mask X coord giving plane of 1st + ; bitmap pixel(zero CH coincidentally) + mov ah,11h ; Init. mask for VGA plane selection + shl ah,cl ; Shift for starting pixel plane + mov dx,SC_INDEX ; Prepare VGA for cpu to video writes + mov al,MAP_MASK + out dx,al + inc dx + mov [Plane],4 ; Set plane counter to 4 +@@PlaneLoop: + push di ; Save bitmap's start dest. offset + mov bl,[BMHeight] ; Reset row counter (BL) + mov al,ah + out dx,al ; set vga write plane +@@RowLoop: + mov cl,bh ; Reset Column counter cl +@@ColLoop: + lodsb ; Get next source bitmap byte + or al,al ; If not zero then write to dest. + jz @@NoPixel ; otherwise skip to next byte + mov es:[di],al +@@NoPixel: + dec di + loop @@ColLoop ; loop if more columns left + add di,[LineInc] ; Move to next row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop di ; Restore bitmaps start dest byte + ror ah,1 ; Shift mask for next plane + sbb di,0 ; If wrapped increment dest address + dec [Plane] ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_flip_masked_pbm endp + + +;---------------------------------------------------------------------- +; x_put_masked_pbm - mask write a planar bitmap from system ram to video ram +; all zero source bitmap bytes indicate destination byte to be left unchanged +; +; Source Bitmap structure: +; +; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1).., +; Bitmap data (plane 2)..,Bitmap data (plane 3).. +; +; note width is in bytes ie lots of 4 pixels +; +; x_put_masked_pbm(X,Y,ScrnOffs,char far * Bitmap) +; +; +; LIMITATIONS: No clipping is supported +; Only supports bitmaps with widths which are a multiple of +; 4 pixels +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_put_masked_pbm proc + ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword + LOCAL Plane:byte,BMHeight:byte,LineInc:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + mov ax,SCREEN_SEG + mov es,ax + mov ax,[Y] ; Calculate dest screen row + mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen + mul bx ; width then adding screen offset + mov di,[ScrnOffs] ; store result in DI + add di,ax + mov cx,[X] ; Load X coord into CX and make a + mov dx,cx ; copy in DX + shr dx,2 ; Find starting byte in dest row + add di,dx ; add to DI giving screen offset of + ; first pixel's byte + lds si,[Bitmap] ; DS:SI -> Bitmap data + lodsw ; Al = B.M. width (bytes) AH = B.M. + ; height +UnFlippedMasked: + mov [BMHeight],ah ; Save source bitmap dimensions + xor ah,ah ; LineInc = bytes to the begin. + sub bx,ax ; of bitmaps next row on screen + mov [LineInc],bx + mov bh,al ; Use bh as column loop count + and cx,0003h ; mask X coord giving plane of 1st + ; bitmap pixel(zero CH coincidentally) + mov ah,11h ; Init. mask for VGA plane selection + shl ah,cl ; Shift for starting pixel plane + mov dx,SC_INDEX ; Prepare VGA for cpu to video writes + mov al,MAP_MASK + out dx,al + inc dx + mov [Plane],4 ; Set plane counter to 4 +@@PlaneLoop: + push di ; Save bitmap's start dest. offset + mov bl,[BMHeight] ; Reset row counter (BL) + mov al,ah + out dx,al ; set vga write plane +@@RowLoop: + mov cl,bh ; Reset Column counter cl +@@ColLoop: + lodsb ; Get next source bitmap byte + or al,al ; If not zero then write to dest. + jz @@NoPixel ; otherwise skip to next byte + mov es:[di],al +@@NoPixel: + inc di + loop @@ColLoop ; loop if more columns left + add di,[LineInc] ; Move to next row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop di ; Restore bitmaps start dest byte + rol ah,1 ; Shift mask for next plane + adc di,0 ; If wrapped increment dest address + dec [Plane] ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_put_masked_pbm endp + + + +;---------------------------------------------------------------------- +; x_put_pbm - Write a planar bitmap from system ram to video ram +; +; Source Bitmap structure: +; +; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1).., +; Bitmap data (plane 2)..,Bitmap data (plane 3).. +; +; note width is in bytes ie lots of 4 pixels +; +; x_put_pbm(X,Y,ScrnOffs,char far * Bitmap) +; +; +; LIMITATIONS: No clipping is supported +; Only supports bitmaps with widths which are a multiple of +; 4 pixels +; FEATURES : Automatically selects REP MOVSB or REP MOVSW depending on +; source bitmap width, by modifying opcode ;-). +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- + + +_x_put_pbm proc + ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword + LOCAL Plane:byte,BMHeight:byte,LineInc:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + mov ax,SCREEN_SEG + mov es,ax + mov ax,[Y] ; Calculate dest screen row + mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen + mul bx ; width then adding screen offset + mov di,[ScrnOffs] ; store result in DI + add di,ax + mov cx,[X] ; Load X coord into CX and make a + mov dx,cx ; copy in DX + shr dx,2 ; Find starting byte in dest row + add di,dx ; add to DI giving screen offset of + ; first pixel's byte + lds si,[Bitmap] ; DS:SI -> Bitmap data + lodsw ; Al = B.M. width (bytes) AH = B.M. + ; height +UnFlipped: + mov [BMHeight],ah ; Save source bitmap dimensions + xor ah,ah ; LineInc = bytes to the begin. + sub bx,ax ; of bitmaps next row on screen + mov [LineInc],bx + mov bh,al + ; Self Modifying, Shame, shame shame.. + and cx,0003h ; mask X coord giving plane of 1st + ; bitmap pixel(zero CH coincidentally) + mov ah,11h ; Init. mask for VGA plane selection + shl ah,cl ; Shift for starting pixel plane + mov dx,SC_INDEX ; Prepare VGA for cpu to video writes + mov al,MAP_MASK + out dx,al + inc dx + mov [Plane],4 ; Set plane counter to 4 +@@PlaneLoop: + push di + mov bl,[BMHeight] + mov al,ah + out dx,al +@@RowLoop: + mov cl,bh + shr cl,1 + rep movsw ; Copy a complete row for curr plane + adc cl,0 + rep movsb + add di,[LineInc] ; Move to next row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop di ; Restore bitmaps start dest byte + rol ah,1 ; Shift mask for next plane + adc di,0 ; If wrapped increment dest address + dec [Plane] ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_put_pbm endp + +;---------------------------------------------------------------------- +; x_flip_pbm - Write a planar bitmap from system ram to video ram +; If "Orientation" is set then the bitmap is flipped from left to right as +; it is drawn + +; +; Source Bitmap structure: +; +; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1).., +; Bitmap data (plane 2)..,Bitmap data (plane 3).. +; +; note width is in bytes ie lots of 4 pixels +; +; x_flip_pbm(X,Y,ScrnOffs,char far * Bitmap, WORD orientation) +; +; +; LIMITATIONS: No clipping is supported +; Only supports bitmaps with widths which are a multiple of +; 4 pixels +; +; NOTES: The flipped put function is slower than the standard put function +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_flip_pbm proc + ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword,Orientation:word + LOCAL Plane:byte,BMHeight:byte,LineInc:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + mov ax,SCREEN_SEG + mov es,ax + mov ax,[Y] ; Calculate dest screen row + mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen + mul bx ; width then adding screen offset + mov di,[ScrnOffs] ; store result in DI + add di,ax + mov cx,[X] ; Load X coord into CX and make a + mov dx,cx ; copy in DX + shr dx,2 ; Find starting byte in dest row + add di,dx ; add to DI giving screen offset of + ; first pixel's byte + lds si,[Bitmap] ; DS:SI -> Bitmap data + lodsw ; Al = B.M. width (bytes) AH = B.M. + ; height + cmp Orientation,0 + jz UnFlipped + + mov [BMHeight],ah ; Save source bitmap dimensions + xor ah,ah ; LineInc = bytes to the begin. + add bx,ax ; of bitmaps next row on screen + mov [LineInc],bx + mov bh,al ; Use bh as column loop count + and cx,0003h ; mask X coord giving plane of 1st + ; bitmap pixel(zero CH coincidentally) + mov ah,11h ; Init. mask for VGA plane selection + shl ah,cl ; Shift for starting pixel plane + mov dx,SC_INDEX ; Prepare VGA for cpu to video writes + mov al,MAP_MASK + out dx,al + inc dx + mov [Plane],4 ; Set plane counter to 4 +@@PlaneLoop: + push di ; Save bitmap's start dest. offset + mov bl,[BMHeight] ; Reset row counter (BL) + mov al,ah + out dx,al ; set vga write plane +@@RowLoop: + mov cl,bh ; Reset Column counter cl +@@ColLoop: + lodsb + mov es:[di],al + dec di + sub di,2 + loop @@ColLoop ; loop if more columns left +@@DoneCol: + add di,[LineInc] ; Move to next row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop di ; Restore bitmaps start dest byte + ror ah,1 ; Shift mask for next plane + sbb di,0 ; If wrapped increment dest address + dec [Plane] ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_flip_pbm endp + + +;---------------------------------------------------------------------- +; x_get_pbm - Read a planar bitmap to system ram from video ram +; +; Source Bitmap structure: +; +; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1).., +; Bitmap data (plane 2)..,Bitmap data (plane 3).. +; +; note width is in bytes ie lots of 4 pixels +; +; x_get_pbm(X,Y,BMwidth,BMheight,ScrnOffs,char far * Bitmap) +; +; +; LIMITATIONS: No clipping is supported +; Only supports bitmaps with widths which are a multiple of +; 4 pixels +; FEATURES : Automatically selects REP MOVSB or REP MOVSW depending on +; source bitmap width, by modifying opcode ;-). +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_get_pbm proc + ARG X:word,Y:word,SrcWidth:byte,SrcHeight:byte,ScrnOffs:word,Bitmap:dword + LOCAL Plane:byte,LineInc:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + + mov ax,[Y] ; Calculate screen row + mov bx,[_ScrnLogicalByteWidth] ; by mult. Y coord by Screen + mul bx ; width then adding screen offset + mov si,[ScrnOffs] ; store result in SI + add si,ax + mov cx,[X] ; Load X coord into CX and make a + mov dx,cx ; copy in DX + shr dx,2 ; Find starting byte in screen row + add si,dx ; add to SI giving screen offset of + ; first pixel's byte + mov ax,SCREEN_SEG + mov ds,ax + les di,[Bitmap] ; ES:DI -> Bitmap data + mov al,[SrcWidth] + mov ah,[SrcHeight] + stosw ; Al = B.M. width (bytes) AH = B.M. + ; height + xor ah,ah ; LineInc = bytes to the begin. + sub bx,ax ; of bitmaps next row on screen + mov [LineInc],bx + mov bh,al + ; Self Modifying, Shame, shame shame.. + and cx,0003h ; mask X coord giving plane of 1st + ; bitmap pixel(zero CH coincidentally) + mov ah,11h ; Init. mask for VGA plane selection + shl ah,cl ; Shift for starting pixel plane + mov dx,GC_INDEX ; Prepare VGA for cpu to video reads + mov al,READ_MAP + out dx,al + inc dx + mov [Plane],4 ; Set plane counter (BH) to 4 + mov al,cl +@@PlaneLoop: + push si + mov bl,[SrcHeight] + out dx,al +@@RowLoop: + mov cl,bh + shr cl,1 + rep movsw ; Copy a complete row for curr plane + adc cl,0 + rep movsb + add si,[LineInc] ; Move to next row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop si ; Restore bitmaps start dest byte + + inc al ; Select next plane to read from + and al,3 ; + + rol ah,1 ; Shift mask for next plane + adc si,0 ; If wrapped increment dest address + dec [Plane] ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_get_pbm endp + + + + + end + + + + ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword,Orientation:word + LOCAL Plane:byte,BMHeight:byte,LineInc:word,Columns:byte=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + mov ax,SCREEN_SEG + mov es,ax + mov ax,[Y] ; Calculate dest screen row + mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen + mul bx ; width then adding screen offset + mov di,[ScrnOffs] ; store result in DI + add di,ax + mov cx,[X] ; Load X coord into CX and make a + mov dx,cx ; copy in DX + shr dx,2 ; Find starting byte in dest row + add di,dx ; add to DI giving screen offset of + ; first pixel's byte + lds si,[Bitmap] ; DS:SI -> Bitmap data + lodsw ; Al = B.M. width (bytes) AH = B.M. + ; height + cmp Orientation,0 + jz UnFlipped + + mov [BMHeight],ah ; Save source bitmap dimensions + xor ah,ah ; LineInc = bytes to the begin. + add bx,ax ; of bitmaps next row on screen + mov [LineInc],bx + mov [Columns],al ; Use bh as column loop count + and cx,0003h ; mask X coord giving plane of 1st + ; bitmap pixel(zero CH coincidentally) + mov ah,11h ; Init. mask for VGA plane selection + shl ah,cl ; Shift for starting pixel plane + mov bh,ah + mov dx,SC_INDEX ; Prepare VGA for cpu to video writes + mov al,MAP_MASK + out dx,al + inc dx + mov [Plane],4 ; Set plane counter to 4 +@@PlaneLoop: + push di ; Save bitmap's start dest. offset + mov bl,[BMHeight] ; Reset row counter (BL) + mov al,bh + out dx,al ; set vga write plane +@@RowLoop: + mov cl,[Columns] ; Reset Column counter cl + shr cx,1 + jnc @@ColLoop + lodsb + mov es:[di],al + dec di +@@ColLoop: + lodsw ; Get next source bitmap byte + xchg al,ah + mov es:[di],ax + sub di,2 + loop @@ColLoop ; loop if more columns left + + add di,[LineInc] ; Move to next row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop di ; Restore bitmaps start dest byte + ror bh,1 ; Shift mask for next plane + sbb di,0 ; If wrapped increment dest address + dec [Plane] ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret \ No newline at end of file diff --git a/16/xlib/xpbitmap.h b/16/xlib/xpbitmap.h new file mode 100755 index 00000000..6f452f9a --- /dev/null +++ b/16/xlib/xpbitmap.h @@ -0,0 +1,77 @@ +/*----------------------------------------------------------------------- +; +; XPBITMAP - header file +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; ****** Aeronautical Research Laboratory **************** +; ****** Defence Science and Technology Organisation **************** +; ****** Australia **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;-----------------------------------------------------------------------*/ + +#ifndef _XPBITMAP_H_ +#define _XPBITMAP_H_ + + +/* FUNCTIONS =========================================================== */ + +#ifdef __cplusplus +extern "C" { +#endif + + + void x_put_masked_pbm( /* Copy a planar bitmap from SRAM masking */ + WORD X, /* only non zero pixels to VRAM */ + WORD Y, + WORD ScrnOffs, + BYTE far * Bitmap); + + void x_flip_masked_pbm( /* Copy a planar bitmap from SRAM masking */ + WORD X, /* only non zero pixels to VRAM. Bitmap */ + WORD Y, /* is mirrored. */ + WORD ScrnOffs, + BYTE far * Bitmap, + WORD orientation); + + void x_put_pbm( /* Copy a planar bitmap from SRAM to VRAM */ + WORD X, + WORD Y, + WORD ScrnOffs, + BYTE far * Bitmap); + + void x_flip_pbm( /* Copy a planar bitmap from SRAM to VRAM */ + WORD X, + WORD Y, + WORD ScrnOffs, + BYTE far * Bitmap, + WORD orientation); + + void x_get_pbm( /* Copy a planar bitmap from VRAM to SRAM */ + WORD X, + WORD Y, + BYTE Bw, + BYTE Bh, + WORD ScrnOffs, + BYTE far * Bitmap); + + +#ifdef __cplusplus +} +#endif + + +#endif + + diff --git a/16/xlib/xpbitmap.inc b/16/xlib/xpbitmap.inc new file mode 100755 index 00000000..a87f6389 --- /dev/null +++ b/16/xlib/xpbitmap.inc @@ -0,0 +1,22 @@ +;----------------------------------------------------------------------- +; +; XPBITMAP - Include file +; +; XPBITMAP.ASM export functions +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + + global _x_put_masked_pbm :proc + global _x_flip_masked_pbm :proc + global _x_put_pbm :proc + global _x_flip_pbm :proc + global _x_get_pbm :proc diff --git a/16/xlib/xpbmclip.asm b/16/xlib/xpbmclip.asm new file mode 100755 index 00000000..872f86bb --- /dev/null +++ b/16/xlib/xpbmclip.asm @@ -0,0 +1,1078 @@ +;----------------------------------------------------------------------- +; MODULE XPBMCLIP +; +; Clipped Planar Bitmap functions - System Ram <-> Video Ram +; +; Compile with Tasm. +; C callable. +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + +COMMENT $ + + This module implements a set of functions to operate on planar bitmaps. + Planar bitmaps as used by these functions have the following structure: + + BYTE 0 The bitmap width in bytes (4 pixel groups) range 1..255 + BYTE 1 The bitmap height in rows range 1..255 + BYTE 2..n1 The plane 0 pixels width*height bytes + BYTE n1..n2 The plane 1 pixels width*height bytes + BYTE n2..n3 The plane 2 pixels width*height bytes + BYTE n3..n4 The plane 3 pixels width*height bytes + + These functions provide the fastest possible bitmap blts from system ram to + to video and further, the single bitmap is applicable to all pixel + allignments. The masked functions do not need separate masks since all non + zero pixels are considered to be masking pixels, hence if a pixel is 0 the + corresponding screen destination pixel is left unchanged. + + +$ +LOCALS +include xlib.inc +include xpbmclip.inc + + .code + +;---------------------------------------------------------------------- +; x_put_masked_pbm_clipx - mask write a planar bitmap from system ram to video +; ram all zero source bitmap bytes indicate destination +; byte to be left unchanged. +; Performs clipping in x directions. similar to +; "x_put_masked_pbm". +; +; See Also: x_put_masked_pbm, x_put_masked_pbm_clipxy +; +; Clipping region variables: LeftClip,RightClip +; +; Written by Themie Gouthas +; +; This code is a SLOW hack, any better ideas are welcome +;---------------------------------------------------------------------- +_x_put_masked_pbm_clipx proc +ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword +LOCAL Plane:byte,CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + + les si,[Bitmap] ; Point ES:SI to start of bitmap + + xor ax,ax ; Clear AX + mov [CType],ax ; Clear Clip type descision var + mov al,byte ptr es:[si] ; AX=width (byte coverted to word) + + + mov di,[X] ; DI = X coordinate of dest + mov cx,di ; copy to CX + sar di,2 ; convert to offset in row + + + ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;; + + mov dx,[_LeftClip] ; Is X Coord to the right of + sub dx,di ; LeftClip ? + jle @@NotLeftClip ; Yes! => no left clipping + cmp dx,ax ; Is dist of X Coord from + jnl @@NotVisible ; ClipLeft > Width ? yes => the + ; bitmap is not visible + add di,dx + mov [LeftSkip],dx + mov [DataInc],dx + sub ax,dx + mov [CType],1 + jmp short @@HorizClipDone + + ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;; + +@@NotVisible: + mov ax,1 + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret + + ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;; + +@@NotLeftClip: + mov dx,[_RightClip] + sub dx,di + js @@NotVisible + mov [LeftSkip],0 + mov [DataInc],0 + cmp dx,ax + jge @@HorizClipDone ; was jg + inc dx + sub ax,dx + mov [DataInc],ax + mov ax,dx + mov [CType],-1 + +@@HorizClipDone: + + xor bh,bh + mov bl,byte ptr es:[si+1] ; BX = height + + mov [Width],ax ; Save width and height of clipped + mov [Height],bx ; image + + + add si,2 ; Skip dimension bytes in source + add si,[LeftSkip] ; Skip pixels in front of row that + ; are clipped + + + mov bx,[_ScrnLogicalByteWidth] ; Set BX to Logical Screen Width + mov dx,bx ; BX - Width of image = No. bytes + sub dx,ax ; to first byte of next screen + mov [LineInc],dx ; row. + + mov ax,[Y] ; Calculate screen start row + mul bx ; then adding screen offset + add di,ax + add di,[ScrnOffs] + mov ax,es ; copy ES to DS + mov ds,ax + mov ax,SCREEN_SEG ; Point ES to VGA segment + mov es,ax + + and cx,3 + mov ah,11h ; Set up initial plane mask + shl ah,cl + + mov dx,SC_INDEX ; Prepare VGA for cpu to video writes + mov al,MAP_MASK + out dx,al + inc dx + mov [Plane],4 ; Set plane counter to 4 + mov bh,byte ptr [Width] ; set bh to width for fast looping +@@PlaneLoop: + push di ; Save bitmap's start dest. offset + mov bl,byte ptr [Height] ; Reset row counter (BL) + mov al,ah + out dx,al ; set vga write plane +@@RowLoop: + mov cl,bh ; Reset Column counter cl + jcxz @@NoWidth +@@ColLoop: + lodsb ; Get next source bitmap byte + or al,al ; If not zero then write to dest. + jz @@NoPixel ; otherwise skip to next byte + mov es:[di],al +@@NoPixel: + inc di + loop @@ColLoop +@@NoWidth: + add si,[DataInc] ; Move to next source row + add di,[LineInc] ; Move to next screen row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop di ; Restore bitmaps start dest byte + rol ah,1 ; Shift mask for next plane + + ; Plane Transition (A HACK but it works!) + + jnb @@Nocarry ; Jump if not plane transition + mov bl,ah ; Save Plane Mask + mov ax,[CType] ; set AX to clip type inc variable + add bh,al ; Update advancing variables + sub [DataInc],ax ; + sub [LineInc],ax ; + cmp al,0 ; What type of clip do we have + mov ah,bl ; restore Plane mask + jg @@RightAdvance ; jump on a right clip! + inc di ; otherwise increment DI + jmp @@Nocarry +@@RightAdvance: + dec si +@@Nocarry: + dec [Plane] ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + xor ax,ax + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_put_masked_pbm_clipx endp + + +;---------------------------------------------------------------------- +; x_put_masked_pbm_clipy - mask write a planar bitmap from system ram to video +; ram all zero source bitmap bytes indicate destination +; byte to be left unchanged. +; Performs clipping in y direction. similar to +; "x_put_masked_pbm". +; +; See Also: x_put_masked_pbm, x_put_masked_pbm_clipx, x_put_masked_pbm_clipy +; +; Clipping region variables: TopClip,BottomClip +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_put_masked_pbm_clipy proc +ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword +LOCAL Width,Height,TopRow,LineInc,PlaneInc:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + + les si,[Bitmap] + + xor bh,bh + mov bl,byte ptr es:[si+1] ; BX = height + + xor ah,ah + mov al,byte ptr es:[si] ; AX = width + + mov cx,ax ; Save AX + mul bx ; AX = AX*BX = bytes/plane + mov [PlaneInc],ax ; save as PlaneInc + mov ax,cx ; Restore AX + + mov di,[X] + mov cx,di + shr di,2 + + ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;; + + mov dx,[_TopClip] ; Compare u.l. Y coord with Top + sub dx,[Y] ; clipping border + jle @@NotTopClip ; jump if VBM not clipped from above + cmp dx,bx + jnl @@NotVisible ; jump if VBM is completely obscured + mov [TopRow],dx + sub bx,dx + add [Y],dx + jmp short @@VertClipDone + + ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;; + +@@NotVisible: + mov ax,1 + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret + + ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;; + +@@NotTopClip: + mov dx,[_BottomClip] + sub dx,[Y] + js @@NotVisible + mov [TopRow],0 + cmp dx,bx + jg @@VertClipDone + inc dx + mov bx,dx + +@@VertClipDone: + + mov [Width],ax + mov [Height],bx ; Calculate relative offset in data + mul [TopRow] ; of first visible scanline + add ax,2 ; Skip dimension bytes in source + add si,ax ; Skip top rows that arent visible + + + mov ax,[Y] ; Calculate screen row + mov bx,[_ScrnLogicalByteWidth] ; by mult. Y coord by Screen + mul bx ; width then adding screen offset + add di,ax + add di,[ScrnOffs] + sub bx,[Width] ; calculate difference from end of + mov [LineInc],bx ; b.m. in curr line to beginning of + ; b.m. on next scan line + mov ax,es ; copy ES to DS + mov ds,ax + mov ax,SCREEN_SEG ; Point ES to VGA segment + mov es,ax + + mov ah,11h ; Set up initial plane mask + and cx,3 + shl ah,cl + + mov dx,SC_INDEX ; Prepare VGA for cpu to video writes + mov al,MAP_MASK + out dx,al + inc dx + mov bh,4 ; Set plane counter to 4 +@@PlaneLoop: + push di ; Save bitmap's start dest. offset + push si ; Save Bitmaps data offset + mov bl,byte ptr [Height] ; Reset row counter (BL) + mov al,ah + out dx,al ; set vga write plane +@@RowLoop: + mov cl,byte ptr [Width] ; Reset Column counter cl +@@ColLoop: + lodsb ; Get next source bitmap byte + or al,al ; If not zero then write to dest. + jz @@NoPixel ; otherwise skip to next byte + mov es:[di],al +@@NoPixel: + inc di + loop @@ColLoop ; loop if more columns left + add di,[LineInc] ; Move to next row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop si ; Restore SI and set to offset of + add si,[PlaneInc] ; first vis pixel in next plane data + pop di ; Restore bitmaps start dest byte + rol ah,1 ; Shift mask for next plane + adc di,0 ; if carry increment screen offset + dec bh ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + xor ax,ax + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_put_masked_pbm_clipy endp + +;---------------------------------------------------------------------- +; x_put_masked_pbm_clipxy - Write a planar bitmap from system ram to video +; RAM with clipping in x and y directions. similar to +; "x_put_masked_pbm". +; +; See Also: x_put_masked_pbm, x_put_masked_pbm_clipx, x_put_masked_pbm_clipxy +; +; Clipping region variables: LeftClip,RightClip,TopClip,BottomClip +; +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_put_masked_pbm_clipxy proc +ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword +LOCAL Plane:byte,CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc,PlaneInc:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + + les si,[Bitmap] + + xor ax,ax + mov [CType],ax + mov al,byte ptr es:[si] ; AX = width + xor bh,bh + mov bl,byte ptr es:[si+1] ; BX = height + + mov cx,ax ; Save AX + mul bx ; AX = AX*BX = bytes/plane + mov [PlaneInc],ax ; save as PlaneInc + mov ax,cx ; Restore AX + + + mov di,[X] ; DI = X coordinate of dest. + mov cx,di ; save in CX + sar di,2 ; convert to address byte + + + ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;; + + mov dx,[_TopClip] ; Compare u.l. Y coord with Top + sub dx,[Y] ; clipping border + jle @@NotTopClip ; jump if VBM not clipped from above + cmp dx,bx + jnl @@NotVisible ; jump if VBM is completely obscured + mov [TopRow],dx + sub bx,dx + add [Y],dx + jmp short @@VertClipDone + + ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;; + +@@NotVisible: + mov ax,1 + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret + + ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;; + +@@NotTopClip: + mov dx,[_BottomClip] + sub dx,[Y] + js @@NotVisible + mov [TopRow],0 + cmp dx,bx + jg @@VertClipDone + inc dx + mov bx,dx + +@@VertClipDone: + + ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;; + + mov dx,[_LeftClip] + sub dx,di + jle @@NotLeftClip + cmp dx,ax + jnl @@NotVisible + + add di,dx + mov [LeftSkip],dx + mov [DataInc],dx + sub ax,dx + mov [CType],1 + jmp short @@HorizClipDone + + ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;; + +@@NotLeftClip: + mov dx,[_RightClip] + sub dx,di + js @@NotVisible + mov [LeftSkip],0 + mov [DataInc],0 + cmp dx,ax + jge @@HorizClipDone ; was jg + inc dx + sub ax,dx + mov [DataInc],ax + mov ax,dx + + + mov [CType],-1 + +@@HorizClipDone: + + + + mov [Width],ax ; Save width and height of clipped + mov [Height],bx ; image + + add ax,[DataInc] ; AX = original width of image + mul [TopRow] ; Calculate bytes in clipped top + add si,ax ; rows + add si,2 ; Skip dimension bytes in source + add si,[LeftSkip] ; Skip pixels in front of row that + ; are clipped + + mov bx,[_ScrnLogicalByteWidth] ; Set BX to Logical Screen Width + mov dx,bx ; BX - Width of image = No. bytes + sub dx,[Width] ; to first byte of next screen + mov [LineInc],dx ; row. + + mov ax,[Y] ; Calculate screen start row + mul bx ; then adding screen offset + add di,ax + add di,[ScrnOffs] + mov ax,es ; copy ES to DS + mov ds,ax + mov ax,SCREEN_SEG ; Point ES to VGA segment + mov es,ax + + + + and cx,3 + mov ah,11h ; Set up initial plane mask + shl ah,cl + + mov dx,SC_INDEX ; Prepare VGA for cpu to video writes + mov al,MAP_MASK + out dx,al + inc dx + mov [Plane],4 ; Set plane counter to 4 + mov bh,byte ptr [Width] ; set bh to width for fast looping +@@PlaneLoop: + push di ; Save bitmap's start dest. offset + push si + mov bl,byte ptr [Height] ; Reset row counter (BL) + mov al,ah + out dx,al ; set vga write plane +@@RowLoop: + mov cl,bh ; Reset Column counter cl + jcxz @@NoWidth +@@ColLoop: + lodsb ; Get next source bitmap byte + or al,al ; If not zero then write to dest. + jz @@NoPixel ; otherwise skip to next byte + mov es:[di],al +@@NoPixel: + inc di + loop @@ColLoop +@@NoWidth: + add si,[DataInc] ; Move to next source row + add di,[LineInc] ; Move to next screen row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop si ; Restore SI and set to offset of + add si,[PlaneInc] ; first vis pixel in next plane data + pop di ; Restore bitmaps start dest byte + rol ah,1 ; Shift mask for next plane + + ; Plane Transition (A HACK but it works!) + + jnb @@Nocarry ; Jump if not plane transition + mov bl,ah ; Save Plane Mask + mov ax,[CType] ; set AX to clip type inc variable + add bh,al ; Update advancing variables + sub [DataInc],ax ; + sub [LineInc],ax ; + cmp al,0 ; What type of clip do we have + mov ah,bl ; restore Plane mask + jg @@RightAdvance ; jump on a right clip! + inc di ; otherwise increment DI + jmp @@Nocarry +@@RightAdvance: + dec si +@@Nocarry: + dec [Plane] ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + xor ax,ax + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_put_masked_pbm_clipxy endp + + + + +;---------------------------------------------------------------------- +; x_put_pbm_clipx - Write a planar bitmap from system ram to video ram +; with clipping in x and y directions. similar to +; "x_put_pbm". +; +; See Also: x_put_pbm_clip +; +; +; See Also: x_put_pbm,x_put_pbm_clipy,x_put_pbm_clipxy +; +; Clipping region variables: LeftClip,RightClip +; +; Written by Themie Gouthas +; +; This code is a SLOW hack, any better ideas are welcome +;---------------------------------------------------------------------- +_x_put_pbm_clipx proc +ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword +LOCAL Plane:byte,CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + + les si,[Bitmap] + + xor ax,ax + mov [CType],ax + mov al,byte ptr es:[si] ; AX = width + + + mov di,[X] ; DI = X coordinate of dest. + mov cx,di ; save in CX + sar di,2 ; convert to address byte + + + + ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;; + + mov dx,[_LeftClip] + sub dx,di + jle @@NotLeftClip + cmp dx,ax + jnl @@NotVisible + + add di,dx + mov [LeftSkip],dx + mov [DataInc],dx + sub ax,dx + mov [CType],1 + jmp short @@HorizClipDone + + ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;; + +@@NotVisible: + mov ax,1 + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret + + ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;; + +@@NotLeftClip: + mov dx,[_RightClip] + sub dx,di + js @@NotVisible + mov [LeftSkip],0 + mov [DataInc],0 + cmp dx,ax + jge @@HorizClipDone ; was jg + inc dx + sub ax,dx + mov [DataInc],ax + mov ax,dx + mov [CType],-1 + +@@HorizClipDone: + + xor bh,bh + mov bl,byte ptr es:[si+1] ; BX = height + + mov [Width],ax ; Save width and height of clipped + mov [Height],bx ; image + + + add si,2 ; Skip dimension bytes in source + add si,[LeftSkip] ; Skip pixels in front of row that + ; are clipped + + + mov bx,[_ScrnLogicalByteWidth] ; Set BX to Logical Screen Width + mov dx,bx ; BX - Width of image = No. bytes + sub dx,ax ; to first byte of next screen + mov [LineInc],dx ; row. + + mov ax,[Y] ; Calculate screen start row + mul bx ; then adding screen offset + add di,ax + add di,[ScrnOffs] + mov ax,es ; copy ES to DS + mov ds,ax + mov ax,SCREEN_SEG ; Point ES to VGA segment + mov es,ax + + and cx,3 + mov ah,11h ; Set up initial plane mask + shl ah,cl + + mov dx,SC_INDEX ; Prepare VGA for cpu to video writes + mov al,MAP_MASK + out dx,al + inc dx + mov [Plane],4 ; Set plane counter to 4 + mov bh,byte ptr [Width] ; set bh to width for fast looping +@@PlaneLoop: + push di ; Save bitmap's start dest. offset + mov bl,byte ptr [Height] ; Reset row counter (BL) + mov al,ah + out dx,al ; set vga write plane +@@RowLoop: + mov cl,bh ; Reset Column counter cl + shr cl,1 + rep movsw ; Copy a complete row + adc cl,0 + rep movsb + add si,[DataInc] ; Move to next source row + add di,[LineInc] ; Move to next screen row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop di ; Restore bitmaps start dest byte + rol ah,1 ; Shift mask for next plane + + ; Plane Transition (A HACK but it works!) + + jnb @@Nocarry ; Jump if not plane transition + mov bl,ah ; Save Plane Mask + mov ax,[CType] ; set AX to clip type inc variable + add bh,al ; Update advancing variables + sub [DataInc],ax ; + sub [LineInc],ax ; + cmp al,0 ; What type of clip do we have + mov ah,bl ; restore Plane mask + jg @@RightAdvance ; jump on a right clip! + inc di ; otherwise increment DI + jmp @@Nocarry +@@RightAdvance: + dec si +@@Nocarry: + dec [Plane] ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + xor ax,ax + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_put_pbm_clipx endp + + + +;---------------------------------------------------------------------- +; x_put_pbm_clipy - Write a planar bitmap from system ram to video ram +; with clipping in y direction only. similar to +; "x_put_pbm". +; +; See Also: x_put_pbm,x_put_pbm_clipx,x_put_pbm_clipxy +; +; Clipping region variables: TopClip,BottomClip +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_put_pbm_clipy proc +ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword +LOCAL Width,Height,TopRow,LineInc,PlaneInc:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + + les si,[Bitmap] + + xor bh,bh + mov bl,byte ptr es:[si+1] ; BX = height + ;mov [Height],bx + + xor ah,ah + mov al,byte ptr es:[si] ; AX = width + mov [Width],ax + + mov cx,ax ; Save AX + mul bx ; AX = AX*BX = bytes/plane + mov [PlaneInc],ax ; save as PlaneInc + mov ax,cx ; Restore AX + + mov di,[X] + mov cx,di + and cx,3 + shr di,2 + + ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;; + + mov dx,[_TopClip] ; Compare u.l. Y coord with Top + sub dx,[Y] ; clipping border + jle @@NotTopClip ; jump if VBM not clipped from above + cmp dx,bx + jnl @@NotVisible ; jump if VBM is completely obscured + mov [TopRow],dx + sub bx,dx + add [Y],dx + jmp short @@VertClipDone + + ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;; + +@@NotVisible: + mov ax,1 + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret + + ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;; + +@@NotTopClip: + mov dx,[_BottomClip] + sub dx,[Y] + js @@NotVisible + mov [TopRow],0 + cmp dx,bx + jg @@VertClipDone + inc dx + mov bx,dx + +@@VertClipDone: + + mov [Height],bx ; Calculate relative offset in data + mul [TopRow] ; of first visible scanline + add ax,2 ; Skip dimension bytes in source + add si,ax ; Skip top rows that arent visible + + + mov ax,[Y] ; Calculate screen row + mov bx,[_ScrnLogicalByteWidth] ; by mult. Y coord by Screen + mul bx ; width then adding screen offset + add di,ax + add di,[ScrnOffs] + sub bx,[Width] ; calculate difference from end of + mov [LineInc],bx ; b.m. in curr line to beginning of + ; b.m. on next scan line + mov ax,es ; copy ES to DS + mov ds,ax + mov ax,SCREEN_SEG ; Point ES to VGA segment + mov es,ax + + mov ah,11h ; Set up initial plane mask + shl ah,cl + + mov dx,SC_INDEX ; Prepare VGA for cpu to video writes + mov al,MAP_MASK + out dx,al + inc dx + mov bh,4 ; Set plane counter to 4 +@@PlaneLoop: + push di ; Save bitmap's start dest. offset + push si ; Save Bitmaps data offset + mov bl,byte ptr [Height] ; Reset row counter (BL) + mov al,ah + out dx,al ; set vga write plane +@@RowLoop: + mov cl,byte ptr [Width] ; Reset Column counter cl + shr cl,1 + rep movsw ; Copy a complete row + adc cl,0 + rep movsb + + add di,[LineInc] ; Move to next row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop si ; Restore SI and set to offset of + add si,[PlaneInc] ; first vis pixel in next plane data + pop di ; Restore bitmaps start dest byte + rol ah,1 ; Shift mask for next plane + adc di,0 ; if carry increment screen offset + dec bh ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + xor ax,ax + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_put_pbm_clipy endp + + +;---------------------------------------------------------------------- +; x_put_pbm_clipxy - Write a planar bitmap from system ram to video ram +; with clipping in x and y directions. similar to +; "x_put_pbm". +; +; See Also: x_put_pbm,x_put_pbm_clipy,x_put_pbm_clipx +; +; Clipping region variables: LeftClip,RightClip,TopClip,BottomClip +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_put_pbm_clipxy proc +ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword +LOCAL Plane:byte,CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc,PlaneInc:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + + les si,[Bitmap] + + xor ax,ax + mov [CType],ax + mov al,byte ptr es:[si] ; AX = width + xor bh,bh + mov bl,byte ptr es:[si+1] ; BX = height + + mov cx,ax ; Save AX + mul bx ; AX = AX*BX = bytes/plane + mov [PlaneInc],ax ; save as PlaneInc + mov ax,cx ; Restore AX + + + mov di,[X] ; DI = X coordinate of dest. + mov cx,di ; save in CX + sar di,2 ; convert to address byte + + + ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;; + + mov dx,[_TopClip] ; Compare u.l. Y coord with Top + sub dx,[Y] ; clipping border + jle @@NotTopClip ; jump if VBM not clipped from above + cmp dx,bx + jnl @@NotVisible ; jump if VBM is completely obscured + mov [TopRow],dx + sub bx,dx + add [Y],dx + jmp short @@VertClipDone + + ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;; + +@@NotVisible: + mov ax,1 + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret + + ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;; + +@@NotTopClip: + mov dx,[_BottomClip] + sub dx,[Y] + js @@NotVisible + mov [TopRow],0 + cmp dx,bx + jg @@VertClipDone + inc dx + mov bx,dx + +@@VertClipDone: + + ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;; + + mov dx,[_LeftClip] + sub dx,di + jle @@NotLeftClip + cmp dx,ax + jnl @@NotVisible + + add di,dx + mov [LeftSkip],dx + mov [DataInc],dx + sub ax,dx + mov [CType],1 + jmp short @@HorizClipDone + + ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;; + +@@NotLeftClip: + mov dx,[_RightClip] + sub dx,di + js @@NotVisible + mov [LeftSkip],0 + mov [DataInc],0 + cmp dx,ax + jge @@HorizClipDone ; was jg + inc dx + sub ax,dx + mov [DataInc],ax + mov ax,dx + mov [CType],-1 + +@@HorizClipDone: + + + + mov [Width],ax ; Save width and height of clipped + mov [Height],bx ; image + + add ax,[DataInc] ; AX = original width of image + mul [TopRow] ; Calculate bytes in clipped top + add si,ax ; rows + add si,2 ; Skip dimension bytes in source + add si,[LeftSkip] ; Skip pixels in front of row that + ; are clipped + + mov bx,[_ScrnLogicalByteWidth] ; Set BX to Logical Screen Width + mov dx,bx ; BX - Width of image = No. bytes + sub dx,[Width] ; to first byte of next screen + mov [LineInc],dx ; row. + + mov ax,[Y] ; Calculate screen start row + mul bx ; then adding screen offset + add di,ax + add di,[ScrnOffs] + mov ax,es ; copy ES to DS + mov ds,ax + mov ax,SCREEN_SEG ; Point ES to VGA segment + mov es,ax + + + + and cx,3 + mov ah,11h ; Set up initial plane mask + shl ah,cl + + mov dx,SC_INDEX ; Prepare VGA for cpu to video writes + mov al,MAP_MASK + out dx,al + inc dx + mov [Plane],4 ; Set plane counter to 4 + mov bh,byte ptr [Width] ; set bh to width for fast looping +@@PlaneLoop: + push di ; Save bitmap's start dest. offset + push si + mov bl,byte ptr [Height] ; Reset row counter (BL) + mov al,ah + out dx,al ; set vga write plane +@@RowLoop: + mov cl,bh ; Reset Column counter cl + shr cl,1 + rep movsw ; Copy a complete row + adc cl,0 + rep movsb + add si,[DataInc] ; Move to next source row + add di,[LineInc] ; Move to next screen row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop si ; Restore SI and set to offset of + add si,[PlaneInc] ; first vis pixel in next plane data + pop di ; Restore bitmaps start dest byte + rol ah,1 ; Shift mask for next plane + + ; Plane Transition (A HACK but it works!) + + jnb @@Nocarry ; Jump if not plane transition + mov bl,ah ; Save Plane Mask + mov ax,[CType] ; set AX to clip type inc variable + add bh,al ; Update advancing variables + sub [DataInc],ax ; + sub [LineInc],ax ; + cmp al,0 ; What type of clip do we have + mov ah,bl ; restore Plane mask + jg @@RightAdvance ; jump on a right clip! + inc di ; otherwise increment DI + jmp @@Nocarry +@@RightAdvance: + dec si +@@Nocarry: + dec [Plane] ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + xor ax,ax + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_put_pbm_clipxy endp + + end + + + diff --git a/16/xlib/xpbmclip.h b/16/xlib/xpbmclip.h new file mode 100755 index 00000000..b025ee77 --- /dev/null +++ b/16/xlib/xpbmclip.h @@ -0,0 +1,83 @@ +/*----------------------------------------------------------------------- +; +; XPBMCLIP - header file +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;-----------------------------------------------------------------------*/ + +#ifndef _XPBMCLIP_H_ +#define _XPBMCLIP_H_ + + +/* FUNCTIONS =========================================================== */ + +#ifdef __cplusplus +extern "C" { +#endif + + + int x_put_masked_pbm_clipx( /* Copy a planar bitmap from SRAM masking */ + int X, /* only non zero pixels to VRAM */ + int Y, /* Supports clipping in the X direction */ + WORD ScrnOffs, + BYTE far * Bitmap); + + + int x_put_masked_pbm_clipy( /* Copy a planar bitmap from SRAM masking */ + int X, /* only non zero pixels to VRAM */ + int Y, /* Supports clipping in the Y direction */ + WORD ScrnOffs, + BYTE far * Bitmap); + + int x_put_masked_pbm_clipxy( /* Copy a planar bitmap from SRAM masking */ + int X, /* only non zero pixels to VRAM */ + int Y, /* Supports clipping in the Y direction */ + WORD ScrnOffs, + BYTE far * Bitmap); + + int x_put_pbm_clipx( /* Copy a planar bitmap from SRAM masking */ + int X, /* Supports clipping in the x direction */ + int Y, + WORD ScrnOffs, + BYTE far * Bitmap); + + int x_put_pbm_clipy( /* Copy a planar bitmap from SRAM masking */ + int X, /* Supports clipping in the Y direction */ + int Y, + WORD ScrnOffs, + BYTE far * Bitmap); + + int x_put_pbm_clipx( /* Copy a planar bitmap from SRAM masking */ + int X, /* Supports clipping in the X direction */ + int Y, + WORD ScrnOffs, + BYTE far * Bitmap); + + int x_put_pbm_clipxy( /* Copy a planar bitmap from SRAM masking */ + int X, /* Supports clipping in the X&Y directions */ + int Y, + WORD ScrnOffs, + BYTE far * Bitmap); + + +#ifdef __cplusplus +} +#endif + + +#endif + + diff --git a/16/xlib/xpbmclip.inc b/16/xlib/xpbmclip.inc new file mode 100755 index 00000000..fa5b18d0 --- /dev/null +++ b/16/xlib/xpbmclip.inc @@ -0,0 +1,25 @@ +;----------------------------------------------------------------------- +; +; XPBMCLIP - Include file +; +; XPBMCLIP.ASM export functions +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + + global _x_put_masked_pbm_clipx :proc + global _x_put_masked_pbm_clipy :proc + global _x_put_masked_pbm_clipxy :proc + + global _x_put_pbm_clipx :proc + global _x_put_pbm_clipy :proc + global _x_put_pbm_clipxy :proc + diff --git a/16/xlib/xpoint.asm b/16/xlib/xpoint.asm new file mode 100755 index 00000000..a2be8bfe --- /dev/null +++ b/16/xlib/xpoint.asm @@ -0,0 +1,107 @@ +;----------------------------------------------------------------------- +; MODULE XPOINT +; +; Point functions all MODE X 256 Color resolutions +; +; Compile with Tasm. +; C callable. +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + +include xlib.inc +include xpoint.inc + + .code + + +;----------------------------------------------------------------------- +; Mode X (256 color mode) write pixel routine. +; No clipping is performed. +; +; Based on code originally published in DDJ Mag by M. Abrash +; +; C near-callable as: +; void x_put_pix(int X, int Y, int PageOffset, int Color); +; +; + +_x_put_pix proc + ARG X:word,Y:word,PgOfs:word,Color:word + push bp ;preserve caller's stack frame + mov bp,sp ;point to local stack frame + + mov ax,[_ScrnLogicalByteWidth] + mul [Y] ;offset of pixel's scan line in page + mov bx,[X] + shr bx,2 ;X/4 = offset of pixel in scan line + add bx,ax ;offset of pixel in page + add bx,[PgOfs] ;offset of pixel in display memory + mov ax,SCREEN_SEG + mov es,ax ;point ES:BX to the pixel's address + + mov cl,byte ptr [X] + and cl,011b ;CL = pixel's plane + mov ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg + shl ah,cl ;set only the bit for the pixel's + ; plane to 1 + mov dx,SC_INDEX ;set the Map Mask to enable only the + out dx,ax ; pixel's plane + + mov al,byte ptr [Color] + mov es:[bx],al ;draw the pixel in the desired color + + pop bp ;restore caller's stack frame + ret +_x_put_pix endp + +;------------------------------------------------------------------------- +; Mode X (320x240, 256 colors) read pixel routine. Works on all VGAs. +; No clipping is performed. +; +; Based on code originally published in DDJ Mag by M. Abrash +; +; C near-callable as: +; unsigned int x_get_pix(int X, int Y, unsigned int PageBase); + + +_x_get_pix proc + ARG x:word,y:word,PageBase:word + push bp ;preserve caller's stack frame + mov bp,sp ;point to local stack frame + + mov ax,[_ScrnLogicalByteWidth] + mul [Y] ;offset of pixel's scan line in page + mov bx,[X] + shr bx,1 + shr bx,1 ;X/4 = offset of pixel in scan line + add bx,ax ;offset of pixel in page + add bx,[PageBase] ;offset of pixel in display memory + mov ax,SCREEN_SEG + mov es,ax ;point ES:BX to the pixel's address + + mov ah,byte ptr [X] + and ah,011b ;AH = pixel's plane + mov al,READ_MAP ;AL = index in GC of the Read Map reg + mov dx,GC_INDEX ;set the Read Map to read the pixel's + out dx,ax ; plane + + mov al,es:[bx] ;read the pixel's color + sub ah,ah ;convert it to an unsigned int + + pop bp ;restore caller's stack frame + ret +_x_get_pix endp + end + + + end + + \ No newline at end of file diff --git a/16/xlib/xpoint.h b/16/xlib/xpoint.h new file mode 100755 index 00000000..a820ca26 --- /dev/null +++ b/16/xlib/xpoint.h @@ -0,0 +1,51 @@ +/*----------------------------------------------------------------------- +; +; XPOINT - header file +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;-----------------------------------------------------------------------*/ + +#ifndef _XPOINT_H_ +#define _XPOINT_H_ + + +/* FUNCTIONS =========================================================== */ + +#ifdef __cplusplus +extern "C" { +#endif + + + void x_put_pix( /* Draw a pixel on the screen */ + WORD X, + WORD Y, + WORD PageOffset, + WORD Color); + + WORD x_get_pix( /* Read a pixel from the screen */ + WORD X, + WORD Y, + WORD PageBase); + + +#ifdef __cplusplus +} +#endif + + +#endif + + diff --git a/16/xlib/xpoint.inc b/16/xlib/xpoint.inc new file mode 100755 index 00000000..58b36dce --- /dev/null +++ b/16/xlib/xpoint.inc @@ -0,0 +1,20 @@ +;----------------------------------------------------------------------- +; +; XPOINT - Include file +; +; XPOINT.ASM export functions +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + + global _x_put_pix :proc + global _x_get_pix :proc + \ No newline at end of file diff --git a/16/xlib/xpolygon.asm b/16/xlib/xpolygon.asm new file mode 100755 index 00000000..c8bac0b4 --- /dev/null +++ b/16/xlib/xpolygon.asm @@ -0,0 +1,608 @@ +;----------------------------------------------------------------------- +; MODULE XPOLYGON +; +; Filled Triangle function for all MODE X 256 Color resolutions +; +; Compile with Tasm. +; C callable. +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; This module is based on code developed by Steve Dollind for his +; XSPACE game. +; Copyright (C) 1992 Steven Dollins -- sdollins@uiuc.edu +; +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- +include xlib.inc +include xpolygon.inc + +.data +; Plane masks for clipping left and right edges of rectangle. + LeftClipPlaneMask db 00fh,00eh,00ch,008h + RightClipPlaneMask db 00fh,001h,003h,007h + +.code + + +;----------------------------------------------------------------------- +; void HLineClipR +; +; Draws a horizontal line from (X1, Y) to (X2, Y). +; Uses Watcom Parameter passing convention in registers +; +; X1 in AX +; X2 in DX +; Y in CX +; Color in BX +; PageOffset in DI +; +; By Themie Gouthas - Adapted from x_fill_rect. +;----------------------------------------------------------------------- +proc _HLineClipR near + push di + cmp dx,ax ; if (X2 < X1) then assume no line + jl @@Invisible ; is visible + + cmp cx,[_TopClip] ; if (Y < TopClip) then no line + jl @@Invisible + + cmp cx,[_BottomClip] ;if (Y > BottomClip) then no line + jg @@Invisible + + mov di,[_RightClip] ;convert RightClip to pixel coords + sal di,2 + cmp ax,di ; if (X1 > RightClip) then no line + jg @@Invisible + + cmp dx,di ; if (X2 > RightClip) then + jle @@ClipLeft ; X2:=RightClip + mov dx,di + +@@ClipLeft: + mov di,[_LeftClip] ;convert LeftClip to pixel coords + sal di,2 + cmp dx,di ; if (X2 < LeftClip) then no line + jl @@Invisible + + cmp ax,di ;if (X1 > LeftClip) then were ready to plot + jge @@DoLine + + mov ax,di ; X1:=LeftClip + jmp short @@DoLine + +@@Invisible: + pop di + ret + +@@DoLine: + pop di ; di = PageOffset + xchg cx,ax ; AX = Y, CX = X1 + mov si,dx ; SI = DX = X2 + mul [_ScrnLogicalByteWidth] + mov dx,si ; Reset DX to X1 since mul erases DX + add ax,di + mov di,cx + sar di,2 ; Convert to bytes + add di,ax ; DI->First byte + + and si,03h ; look up right edge plane mask + mov ah,RightClipPlaneMask[si] + mov si,cx ; look up left edge plane mask + and si,03h + mov al,LeftClipPlaneMask[si] + + cmp dx,cx ; No harm in being paranoid.. + jle @@Invisible2 + + xchg cx,dx ;CX=X2, DX=X1 + dec cx + and dx,not 03h + sub cx,dx + js @@Invisible2 + shr cx,2 + jnz @@MasksSet + and al,ah +@@MasksSet: + mov dl,bl ; set BX=Plane Masks, AH=Color + mov bx,ax + mov ah,dl + mov dx,SC_INDEX+1 ;set the Sequence Controller Index to + mov al,bl + out dx,al + mov al,ah + stosb ; Plot left byte + dec cx + js @@Invisible2 + jz @@RightEnd + + + mov al,0fh ; plot middle bytes + out dx,al + mov al,ah + shr cx,1 + rep stosw + adc cx,cx + rep stosb + + + +@@RightEnd: + mov al,bh ; Plot right byte + out dx,al + mov al,ah + stosb +@@Invisible2: + ret +_HLineClipR endp + + +;----------------------------------------------------------------------- +; void x_triangle( int X0, int Y0, int X1, int Y1, +; int X2, int Y2, unsigned Color, unsigned PageOffset ); +; +; +; Written by S. Dollins + +_x_triangle proc +ARG X0:word,Y0:word,X1:word,Y1:word,X2:word,Y2:word,Color:word,PageOffset:word +LOCAL DX01:word, DY01:word, DX02:word, DY02:word, DX12:word, DY12:word, \ + DP01:word, DP02:word, DP12:word, XA01:word, XA02:word, XA12:word=STK + + push bp + mov bp,sp + sub sp,STK + push ds es si di ; Save es for polygon routine + + mov ax,X0 + mov bx,Y0 + mov cx,X1 + mov dx,Y1 + + cmp bx,dx ; Y0,Y1 + jl tri_Y0lY1 + je tri_Y0eY1 + xchg ax,cx ; X0,X1 + xchg bx,dx ; Y0,Y1 +tri_Y0lY1: + cmp dx,Y2 ; Y1,Y2 + jg tri_a + jmp tri_sorted +tri_a: xchg cx,X2 ; X1,X2 + xchg dx,Y2 ; Y1,Y2 + cmp bx,dx ; Y0,Y1 + jge tri_b + jmp tri_sorted +tri_b: je tri_bot + xchg ax,cx ; X0,X1 + xchg bx,dx ; Y0,Y1 + jmp tri_sorted +tri_Y0eY1: + cmp bx,Y2 ; Y0,Y2 + jl tri_bot + jg tri_c + jmp tri_done +tri_c: xchg ax,X2 ; X0,X2 + xchg bx,Y2 ; Y0,Y2 + jmp tri_sorted + +tri_bot: + cmp ax,cx ; X0,X1 + jl tri_bot_sorted + jg tri_bot_a + jmp tri_done +tri_bot_a: + xchg ax,cx ; X0,X1 +tri_bot_sorted: + cmp bx,[_BottomClip] + jle tri_bot_y0ok + jmp tri_done +tri_bot_y0ok: + mov si,Y2 + cmp si,[_TopClip] + jge tri_bot_y2ok + jmp tri_done +tri_bot_y2ok: + mov X0,ax + mov Y0,bx + mov X1,cx + mov Y1,dx + + mov bx,Y2 ; bx <- Y2 + sub bx,Y0 ; bx <- Y2 - Y0 + mov DY02,bx ; DY02 <- Y2 - Y0 + mov ax,X2 ; ax <- X2 + sub ax,X0 ; ax <- X2 - X0 + mov DX02,ax ; DX02 <- X2 - X0 + mov cx,ax ; cx <- DX02 + cwd ; dx:ax <- DX02 + idiv bx ; ax <- DX02 / DY02 + cmp cx,0 + jge short tri_bot02 + dec ax ; ax <- DX02 / DY02 - 1 +tri_bot02: + mov XA02,ax ; XA02 <- DX02 / DY02 + imul bx ; ax <- XA02 * DY02 + sub cx,ax ; cx <- DX02 - XA02 * DY02 + mov DP02,cx ; DP02 <- DX02 - XA02 * DY02 + + mov bx,Y2 ; bx <- Y2 + sub bx,Y1 ; bx <- Y2 - Y1 + mov DY12,bx ; DY02 <- Y2 - Y1 + mov ax,X2 ; ax <- X2 + sub ax,X1 ; ax <- X2 - X1 + mov DX12,ax ; DX12 <- X2 - X1 + mov cx,ax ; cx <- DX12 + cwd ; dx:ax <- DX12 + idiv bx ; ax <- DX12 / DY12 + cmp cx,0 + jge short tri_bot12 + dec ax ; ax <- DX12 / DY12 - 1 +tri_bot12: + mov XA12,ax ; XA12 <- DX12 / DY12 + imul bx ; ax <- XA12 * DY12 + sub cx,ax ; cx <- DX12 - XA12 * DY12 + mov DP12,cx ; DP12 <- DX12 - XA12 * DY12 + + mov ax,0 ; PL <- 0 + mov bx,0 ; PS <- 0 + mov cx,Y0 ; Y <- Y0 + mov si,X0 + mov di,X1 + dec di +tri_bot_loop: + inc cx ; Y + + add ax,DP02 ; PL,DP02 + jle short tri_bot_shortl + sub ax,DY02 ; PL,DY02 + inc si ; XL +tri_bot_shortl: + add si,XA02 ; XL,XA02 + + add bx,DP12 ; PS,DP12 + jle short tri_bot_shortr + sub bx,DY12 ; PS,DY12 + inc di ; XS +tri_bot_shortr: + add di,XA12 ; XS,XA12 + + push di ; XS + push si ; XL + cmp cx,Y2 ; Y,Y2 + jl short tri_bot_loop + + jmp tri_draw_lines + + +tri_sorted: + cmp bx,[_BottomClip] + jle tri_y0ok + jmp tri_done +tri_y0ok: + mov si,Y2 + cmp si,[_TopClip] + jge tri_y2ok + jmp tri_done +tri_y2ok: + mov X0,ax + mov Y0,bx + mov X1,cx + mov Y1,dx + + mov bx,dx ; bx <- Y1 + sub bx,Y0 ; bx <- Y1 - Y0 + mov DY01,bx ; DY01 <- Y1 - Y0 + mov ax,X1 ; ax <- X1 + sub ax,X0 ; ax <- X1 - X0 + mov DX01,ax ; DX01 <- X1 - X0 + mov cx,ax ; cx <- DX01 + cwd ; dx:ax <- DX01 + idiv bx ; ax <- DX01 / DY01 + cmp cx,0 ; DX01 ? 0 + jge short tri_psl01 + dec ax ; ax <- DX01 / DY01 - 1 +tri_psl01: + mov XA01,ax ; XA01 <- DX01 / DY01 + imul bx ; ax <- XA01 * DY01 + sub cx,ax ; cx <- DX01 - XA01 * DY01 + mov DP01,cx ; DP01 <- DX01 - XA01 * DY01 + + mov bx,Y2 ; bx <- Y2 + sub bx,Y0 ; bx <- Y2 - Y0 + mov DY02,bx ; DY02 <- Y2 - Y0 + mov ax,X2 ; ax <- X2 + sub ax,X0 ; ax <- X2 - X0 + mov DX02,ax ; DX02 <- X2 - X0 + mov cx,ax ; cx <- DX02 + cwd ; dx:ax <- DX02 + idiv bx ; ax <- DX02 / DY02 + cmp cx,0 + jge short tri_psl02 + dec ax ; ax <- DX02 / DY02 - 1 +tri_psl02: + mov XA02,ax ; XA02 <- DX02 / DY02 + imul bx ; ax <- XA02 * DY02 + sub cx,ax ; cx <- DX02 - XA02 * DY02 + mov DP02,cx ; DP02 <- DX02 - XA02 * DY02 + + mov bx,Y2 ; bx <- Y2 + sub bx,Y1 ; bx <- Y2 - Y1 + jle short tri_const_computed + mov DY12,bx ; DY12 <- Y2 - Y1 + mov ax,X2 ; ax <- X2 + sub ax,X1 ; ax <- X2 - X1 + mov DX12,ax ; DX12 <- X2 - X1 + mov cx,ax ; cx <- DX12 + cwd ; dx:ax <- DX12 + idiv bx ; ax <- DX12 / DY12 + cmp cx,0 + jge short tri_psl12 + dec ax ; ax <- DX12 / DY12 - 1 +tri_psl12: + mov XA12,ax ; XA12 <- DX12 / DY12 + imul bx ; ax <- XA12 * DY12 + sub cx,ax ; cx <- DX12 - XA12 * DY12 + mov DP12,cx ; DP12 <- DX12 - XA12 * DY12 + +tri_const_computed: + mov ax,DX01 + imul word ptr DY02 + mov bx,ax + mov cx,dx ; DX01 * DY02 in cx:bx + + mov ax,DX02 + imul word ptr DY01 ; DX02 * DY01 in dx:ax + cmp cx,dx + jg tri_pt1rt + jl tri_pt1lt + cmp bx,ax + ja tri_pt1rt + jb tri_pt1lt + jmp tri_done + +;------------------------------------ +; Short sides are on the left +; +tri_pt1lt: + mov ax,0 ; PL <- 0 + mov bx,0 ; PS <- 0 + mov cx,Y0 ; Y <- Y0 + mov si,X0 + mov di,si + dec si +tri_lt_loop: + inc cx ; Y + + add ax,DP02 ; PL,DP02 + jle short tri_lt_shortl + sub ax,DY02 ; PL,DY02 + inc si ; XL +tri_lt_shortl: + add si,XA02 ; XL,XA02 + + add bx,DP01 ; PS,DP01 + jle short tri_lt_shortr + sub bx,DY01 ; PS,DY01 + inc di ; XS +tri_lt_shortr: + add di,XA01 ; XS,XA01 + + push si ; XL + push di ; XS + cmp cx,Y1 ; Y,Y1 + jl short tri_lt_loop + + jmp short tri_lb_start +tri_lb_loop: + inc cx ; Y + + add ax,DP02 ; PL,DP02 + jle short tri_lb_shortl + sub ax,DY02 ; PL,DY02 + inc si ; XL +tri_lb_shortl: + add si,XA02 ; XL,XA02 + + add bx,DP12 ; PS,DP12 + jle short tri_lb_shortr + sub bx,DY12 ; PS,DY12 + inc di ; XS +tri_lb_shortr: + add di,XA12 ; XS,XA12 + + push si ; XL + push di ; XS +tri_lb_start: + cmp cx,Y2 ; Y,Y2 + jl tri_lb_loop + jmp short tri_draw_lines + +;------------------------------------ +; short sides are on the right +; +tri_pt1rt: + mov ax,0 ; PL <- 0 + mov bx,0 ; PS <- 0 + mov cx,Y0 ; Y <- Y0 + mov si,X0 + mov di,si + dec di +tri_rt_loop: + inc cx ; Y + + add ax,DP02 ; PL,DP02 + jle short tri_rt_shortl + sub ax,DY02 ; PL,DY02 + inc si ; XL +tri_rt_shortl: + add si,XA02 ; XL,XA02 + + add bx,DP01 ; PS,DP01 + jle short tri_rt_shortr + sub bx,DY01 ; PS,DY01 + inc di ; XS +tri_rt_shortr: + add di,XA01 ; XS,XA01 + + push di ; XS + push si ; XL + cmp cx,Y1 ; Y,Y1 + jl short tri_rt_loop + + jmp short tri_rb_start +tri_rb_loop: + inc cx ; Y + + add ax,DP02 ; PL,DP02 + jle short tri_rb_shortl + sub ax,DY02 ; PL,DY02 + inc si ; XL +tri_rb_shortl: + add si,XA02 ; XL,XA02 + + add bx,DP12 ; PS,DP12 + jle short tri_rb_shorts + sub bx,DY12 ; PS,DY12 + inc di ; XS +tri_rb_shorts: + add di,XA12 ; XS,XA12 + + push di ; XS + push si ; XL +tri_rb_start: + cmp cx,Y2 ; Y,Y2 + jl short tri_rb_loop + +;------------------------------------ +; Draw the horizontal lines +; + + +tri_draw_lines: + + mov cx,SCREEN_SEG ;point ES to video segment + mov es,cx + mov dx,SC_INDEX ;set the Sequence Controller Index to + mov al,MAP_MASK ; point to the Map Mask register + out dx,al + + +line_loop: + pop ax + pop dx + cmp ax,dx + jg tri_draw_next + mov bx,Color + mov cx,Y2 + add dx,2 + mov di,PageOffset + call _HLineClipR +tri_draw_next: + dec word ptr Y2 + dec word ptr DY02 + jnz line_loop + +tri_done: + pop di si es ds + mov sp,bp + pop bp + ret +_x_triangle endp + +;----------------------------------------------------------------------- +; void x_polygon( VERTEX vertices[], int num_vertices,unsigned Color, +; unsigned PageOffset ); +; +; Where VERTEX is defined as: +; +; typedef struct { +; int X; +; int Y; +; } far VERTEX; +; +; +; Written by T. Gouthas +; +; +; +; Note: This is just a quick hack of a generalized polygon routine. +; The way it works is by splitting up polygons into triangles and +; drawing each individual triangle. +; +; Obviously this is not as fast as it could be, but for polygons of +; 4 vertices it should perform quite respectably. +; +; Warning: Only works for convex polygons (convex polygons are such +; that if you draw a line from any two vertices, every point on that +; line will be within the polygon) +; +; + +_x_polygon proc + ARG vertices:dword,numvertices:word,Color:word,PageOffset:word + LOCAL x0:word,y0:word,tri_count:word=STK + push bp + mov bp,sp + sub sp,STK + push di si + + mov cx,numvertices + cmp cx,3 + jl @@Done + + sub cx,3 + mov tri_count,cx ; Number of triangles to draw + les di,vertices ; ES:DI -> Vertices + + mov ax,es:[di] ; Save first vertex + mov x0,ax + mov ax,es:[di+2] + mov y0,ax + + ; Set up permanent parameter stack frame for + ; triangle parameters + + mov ax,PageOffset + push ax + mov ax,Color + push ax + + sub sp,12 + mov si,sp + +@@NextTriangle: + + add di,4 + mov ax,es:[di] ; Vertex 2 + mov ss:[si],ax + mov ax,es:[di+2] + mov ss:[si+2],ax + + mov ax,es:[di+4] ; Vertex 1 + mov ss:[si+4],ax + mov ax,es:[di+6] + mov ss:[si+6],ax + + mov ax,x0 ; Vertex 0: The first vertex is + mov ss:[si+8],ax ; part of every triangle + mov ax,y0 + mov ss:[si+10],ax + + call _x_triangle + dec tri_count + jns @@NextTriangle + + add sp,16 ; Remove triangle stack frame + +@@Done: + pop si di + mov sp,bp + pop bp + ret +_x_polygon endp + end \ No newline at end of file diff --git a/16/xlib/xpolygon.h b/16/xlib/xpolygon.h new file mode 100755 index 00000000..bdad73e4 --- /dev/null +++ b/16/xlib/xpolygon.h @@ -0,0 +1,59 @@ +/*----------------------------------------------------------------------- +; +; XPOLYGON - header file +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;----------------------------------------------------------------------*/ + +#ifndef _XPOLYGON_H_ +#define _XPOLYGON_H_ + + +typedef struct { + int X; + int Y; +} far VERTEX; + +/* FUNCTIONS =========================================================== */ + +#ifdef __cplusplus +extern "C" { +#endif + +void x_triangle( /* Draw a triangle */ + int x0, + int y0, + int x1, + int y1, + int x2, + int y2, + WORD color, + WORD PageBase); + +void x_polygon( /* Draw a convex polygon */ + VERTEX *vertices, + int num_vertices, + WORD color, + WORD PageBase); + + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/16/xlib/xpolygon.inc b/16/xlib/xpolygon.inc new file mode 100755 index 00000000..c8d2bff8 --- /dev/null +++ b/16/xlib/xpolygon.inc @@ -0,0 +1,19 @@ +;----------------------------------------------------------------------- +; +; XPOLYGON - Include file +; +; XPOLYGON.ASM export functions +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + + global _x_triangle :proc + global _x_polygon :proc diff --git a/16/xlib/xprintf.c b/16/xlib/xprintf.c new file mode 100755 index 00000000..921b6582 --- /dev/null +++ b/16/xlib/xprintf.c @@ -0,0 +1,41 @@ +#include +#include +#include "xlib.h" +#include "xrect.h" +#include "xtext.h" + + +extern unsigned char CharWidth; +extern unsigned char CharHeight; + +void x_printf(WORD x, WORD y,WORD ScrnOffs,WORD color,char *ln,...){ + char dlin[100],*dl=dlin; + char ch; + va_list ap; + + va_start(ap,ln); + vsprintf(dlin,ln,ap); + va_end(ap); + + while(*dl){ + x+=x_char_put(*dl++,x,y,ScrnOffs,color); + } + +} + +void x_bgprintf(WORD x, WORD y,WORD ScrnOffs,WORD fgcolor, + WORD bgcolor, char *ln,...){ + char dlin[100],*dl=dlin; + char ch; + va_list ap; + + va_start(ap,ln); + vsprintf(dlin,ln,ap); + va_end(ap); + + while(*dl){ + x_rect_fill(x,y,x+x_get_char_width(*dl),y+CharHeight,ScrnOffs,bgcolor); + x+=x_char_put(*dl++,x,y,ScrnOffs,fgcolor); + } + +} diff --git a/16/xlib/xrect.asm b/16/xlib/xrect.asm new file mode 100755 index 00000000..9b00356c --- /dev/null +++ b/16/xlib/xrect.asm @@ -0,0 +1,684 @@ +;----------------------------------------------------------------------- +; MODULE XRECT +; +; Rectangle functions all MODE X 256 Color resolutions +; +; Compile with Tasm. +; C callable. +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + +include xlib.inc +include xrect.inc + + + .data +; Plane masks for clipping left and right edges of rectangle. + LeftClipPlaneMask db 00fh,00eh,00ch,008h + RightClipPlaneMask db 00fh,001h,003h,007h + .code + +;--------------------------------------------------------------------------- +; Mode X (320x240, 256 colors) rectangle solid colour fill routine. +; +; Based on code originally published in DDJ Mag by M. Abrash +; +; with TASM 2. C near-callable as: +; +; void x_rect_fill_clipped(int StartX, int StartY, int EndX, int EndY, +; unsigned int PageBase, unsigne int color); +; +; + + +_x_rect_fill_clipped proc +ARG StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Color:word + push bp ;preserve caller's stack frame + mov bp,sp ;point to local stack frame + push si ;preserve caller's register variables + push di + + mov dx,[_TopClip] ; Compare u.l. Y coord with Top + mov cx,[_BottomClip] + mov ax,[StartY] + mov bx,[EndY] + cmp dx,ax + jle @@CheckBottomClip + cmp dx,bx + jg @@NotVisible + mov [StartY],dx + +@@CheckBottomClip: + cmp cx,bx + jg @@CheckLeftClip + cmp cx,ax + jl @@NotVisible + mov [EndY],cx + +@@CheckLeftClip: + mov dx,[_LeftClip] ; Compare u.l. Y coord with Top + mov cx,[_RightClip] + mov ax,[StartX] + mov bx,[EndX] + sal dx,2 + sal cx,2 + cmp dx,ax + jle @@CheckRightClip + cmp dx,bx + jg @@NotVisible + mov [StartX],dx + +@@CheckRightClip: + cmp cx,bx + jg RFClipDone + cmp cx,ax + jl @@NotVisible + mov [EndX],cx + jmp RFClipDone + +@@NotVisible: + mov ax,1 + pop di ; restore registers + pop si + pop bp + ret +_x_rect_fill_clipped endp + + + +;--------------------------------------------------------------------------- +; Mode X (320x240, 256 colors) rectangle solid colour fill routine. +; +; Based on code originally published in DDJ Mag by M. Abrash +; +; with TASM 2. C near-callable as: +; +; void x_rect_fill(int StartX, int StartY, int EndX, int EndY, +; unsigned int PageBase, unsigne int color); +; +; + + +_x_rect_fill proc +ARG StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Color:word + push bp ;preserve caller's stack frame + mov bp,sp ;point to local stack frame + push si ;preserve caller's register variables + push di + +RFClipDone: + cld + mov ax,[_ScrnLogicalByteWidth] + mul [StartY] ;offset in page of top rectangle scan line + mov di,[StartX] + sar di,2 ;X/4 = offset of first rectangle pixel in scan + add di,ax ;offset of first rectangle pixel in page + add di,[PageBase] ;offset of first rectangle pixel in + ; display memory + mov ax,SCREEN_SEG ;point ES:DI to the first rectangle + mov es,ax ; pixel's address + mov dx,SC_INDEX ;set the Sequence Controller Index to + mov al,MAP_MASK ; point to the Map Mask register + out dx,al + inc dx ;point DX to the SC Data register + mov si,[StartX] + and si,0003h ;look up left edge plane mask + mov bh,LeftClipPlaneMask[si] ; to clip & put in BH + mov si,[EndX] + and si,0003h ;look up right edge plane + mov bl,RightClipPlaneMask[si] ; mask to clip & put in BL + + mov cx,[EndX] ;calculate # of addresses across rect + mov si,[StartX] + cmp cx,si + jle @@FillDone ;skip if 0 or negative width + dec cx + and si,not 011b + sub cx,si + sar cx,2 ;# of addresses across rectangle to fill - 1 + jnz @@MasksSet ;there's more than one byte to draw + and bh,bl ;there's only one byte, so combine the left + ; and right edge clip masks +@@MasksSet: + mov si,[EndY] + sub si,[StartY] ;BX = height of rectangle + jle @@FillDone ;skip if 0 or negative height + mov ah,byte ptr [Color] ;color with which to fill + mov bp,[_ScrnLogicalByteWidth] ;stack frame isn't needed any more + sub bp,cx ;distance from end of one scan line to start + dec bp ; of next +@@FillRowsLoop: + push cx ;remember width in addresses - 1 + mov al,bh ;put left-edge clip mask in AL + out dx,al ;set the left-edge plane (clip) mask + mov al,ah ;put color in AL + stosb ;draw the left edge + dec cx ;count off left edge byte + js @@FillLoopBottom ;that's the only byte + jz @@DoRightEdge ;there are only two bytes + mov al,00fh ;middle addresses drawn 4 pixels at a pop + out dx,al ;set the middle pixel mask to no clip + mov al,ah ;put color in AL + rep stosb ;draw middle addresses four pixels apiece +@@DoRightEdge: + mov al,bl ;put right-edge clip mask in AL + out dx,al ;set the right-edge plane (clip) mask + mov al,ah ;put color in AL + stosb ;draw the right edge +@@FillLoopBottom: + add di,bp ;point to start of the next scan line of + ; the rectangle + pop cx ;retrieve width in addresses - 1 + dec si ;count down scan lines + jnz @@FillRowsLoop +@@FillDone: + pop di ;restore caller's register variables + pop si + pop bp ;restore caller's stack frame + ret +_x_rect_fill endp + + + +;--------------------------------------------------------------------------- +; Mode X (320x240, 256 colors) rectangle 4x4 pattern fill routine. +; Upper left corner of pattern is always aligned to a multiple-of-4 +; row and column. Works on all VGAs. Uses approach of copying the +; pattern to off-screen display memory, then loading the latches with +; the pattern for each scan line and filling each scan line four +; pixels at a time. Fills up to but not including the column at EndX +; and the row at EndY. No clipping is performed. All ASM code tested +; +; +; Based on code originally published in DDJ Mag by M. Abrash +; +; +; C near-callable as: +; +; void x_rect_pattern_clipped(int StartX, int StartY, int EndX, int EndY, +; unsigned int PageBase, char far * Pattern); +; +; + +_x_rect_pattern_clipped proc +ARG StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Pattern:dword +LOCAL NextScanOffset:word,RectAddrWidth:word,Height:word=LocalStk + push bp ;preserve caller's stack frame + mov bp,sp ;point to local stack frame + sub sp,LocalStk ;allocate space for local vars + push si ;preserve caller's register variables + push di + push ds + + mov dx,[_TopClip] ; Compare u.l. Y coord with Top + mov cx,[_BottomClip] + mov ax,[StartY] + mov bx,[EndY] + cmp dx,ax + jle @@CheckBottomClip + cmp dx,bx + jg @@NotVisible + mov [StartY],dx + +@@CheckBottomClip: + cmp cx,bx + jg @@CheckLeftClip + cmp cx,ax + jl @@NotVisible + mov [EndY],cx + +@@CheckLeftClip: + mov dx,[_LeftClip] ; Compare u.l. Y coord with Top + mov cx,[_RightClip] + mov ax,[StartX] + mov bx,[EndX] + sal dx,2 + sal cx,2 + cmp dx,ax + jle @@CheckRightClip + cmp dx,bx + jg @@NotVisible + mov [StartX],dx + +@@CheckRightClip: + cmp cx,bx + jg RPClipDone + cmp cx,ax + jl @@NotVisible + mov [EndX],cx + jmp RPClipDone + +@@NotVisible: + mov ax,1 + pop ds + pop di ; restore registers + pop si + mov sp,bp + pop bp + ret + +_x_rect_pattern_clipped endp + +;--------------------------------------------------------------------------- +; Mode X (320x240, 256 colors) rectangle 4x4 pattern fill routine. +; Upper left corner of pattern is always aligned to a multiple-of-4 +; row and column. Works on all VGAs. Uses approach of copying the +; pattern to off-screen display memory, then loading the latches with +; the pattern for each scan line and filling each scan line four +; pixels at a time. Fills up to but not including the column at EndX +; and the row at EndY. No clipping is performed. All ASM code tested +; +; +; Based on code originally published in DDJ Mag by M. Abrash +; +; +; C near-callable as: +; +; void x_rect_pattern(int StartX, int StartY, int EndX, int EndY, +; unsigned int PageBase, char far * Pattern); + + + +_x_rect_pattern proc +ARG StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Pattern:dword +LOCAL NextScanOffset:word,RectAddrWidth:word,Height:word=LocalStk + push bp ;preserve caller's stack frame + mov bp,sp ;point to local stack frame + sub sp,LocalStk ;allocate space for local vars + push si ;preserve caller's register variables + push di + push ds + +RPClipDone: + cld + mov ax,SCREEN_SEG ;point ES to display memory + mov es,ax + ;copy pattern to display memory buffer + lds si,dword ptr [Pattern] ;point to pattern to fill with + mov di,PATTERN_BUFFER ;point ES:DI to pattern buffer + mov dx,SC_INDEX ;point Sequence Controller Index to + mov al,MAP_MASK ; Map Mask + out dx,al + inc dx ;point to SC Data register + mov cx,4 ;4 pixel quadruplets in pattern +@@DownloadPatternLoop: + mov al,1 ; + out dx,al ;select plane 0 for writes + movsb ;copy over next plane 0 pattern pixel + dec di ;stay at same address for next plane + mov al,2 ; + out dx,al ;select plane 1 for writes + movsb ;copy over next plane 1 pattern pixel + dec di ;stay at same address for next plane + mov al,4 ; + out dx,al ;select plane 2 for writes + movsb ;copy over next plane 2 pattern pixel + dec di ;stay at same address for next plane + mov al,8 ; + out dx,al ;select plane 3 for writes + movsb ;copy over next plane 3 pattern pixel + ; and advance address + loop @@DownloadPatternLoop + pop ds + + mov dx,GC_INDEX ;set the bit mask to select all bits + mov ax,00000h+BIT_MASK ; from the latches and none from + out dx,ax ; the CPU, so that we can write the + ; latch contents directly to memory + mov ax,[StartY] ;top rectangle scan line + mov si,ax + and si,011b ;top rect scan line modulo 4 + add si,PATTERN_BUFFER ;point to pattern scan line that + ; maps to top line of rect to draw + mov dx,[_ScrnLogicalByteWidth] + mul dx ;offset in page of top rect scan line + mov di,[StartX] + mov bx,di + sar di,2 ;X/4 = offset of first rectangle pixel in scan + add di,ax ;offset of first rectangle pixel in page + add di,[PageBase] ;offset of first rectangle pixel in + ; display memory + and bx,0003h ;look up left edge plane mask + mov ah,LeftClipPlaneMask[bx] ; to clip + mov bx,[EndX] + and bx,0003h ;look up right edge plane + mov al,RightClipPlaneMask[bx] ; mask to clip + mov bx,ax ;put the masks in BX + + mov cx,[EndX] ;calculate # of addresses across rect + mov ax,[StartX] + cmp cx,ax + jle @@FillDone ;skip if 0 or negative width + dec cx + and ax,not 011b + sub cx,ax + sar cx,2 ;# of addresses across rectangle to fill - 1 + jnz @@MasksSet ;there's more than one pixel to draw + and bh,bl ;there's only one pixel, so combine the left + ; and right edge clip masks +@@MasksSet: + mov ax,[EndY] + sub ax,[StartY] ;AX = height of rectangle + jle @@FillDone ;skip if 0 or negative height + mov [Height],ax + mov ax,[_ScrnLogicalByteWidth] + sub ax,cx ;distance from end of one scan line to start + dec ax ; of next + mov [NextScanOffset],ax + mov [RectAddrWidth],cx ;remember width in addresses - 1 + mov dx,SC_INDEX+1 ;point to Sequence Controller Data reg + ; (SC Index still points to Map Mask) +@@FillRowsLoop: + mov cx,[RectAddrWidth] ;width across - 1 + mov al,es:[si] ;read display memory to latch this scan + ; line's pattern + inc si ;point to the next pattern scan line, wrapping + jnz short @@NoWrap ; back to the start of the pattern if + sub si,4 ; we've run off the end +@@NoWrap: + mov al,bh ;put left-edge clip mask in AL + out dx,al ;set the left-edge plane (clip) mask + stosb ;draw the left edge (pixels come from latches; + ; value written by CPU doesn't matter) + dec cx ;count off left edge address + js @@FillLoopBottom ;that's the only address + jz @@DoRightEdge ;there are only two addresses + mov al,00fh ;middle addresses drawn 4 pixels at a pop + out dx,al ;set middle pixel mask to no clip + rep stosb ;draw middle addresses four pixels apiece + ; (from latches; value written doesn't matter) +@@DoRightEdge: + mov al,bl ;put right-edge clip mask in AL + out dx,al ;set the right-edge plane (clip) mask + stosb ;draw the right edge (from latches; value + ; written doesn't matter) +@@FillLoopBottom: + add di,[NextScanOffset] ;point to the start of the next scan + ; line of the rectangle + dec word ptr [Height] ;count down scan lines + jnz @@FillRowsLoop +@@FillDone: + mov dx,GC_INDEX+1 ;restore the bit mask to its default, + mov al,0ffh ; which selects all bits from the CPU + out dx,al ; and none from the latches (the GC + ; Index still points to Bit Mask) + + pop di ;restore caller's register variables + pop si + mov sp,bp ;discard storage for local variables + pop bp ;restore caller's stack frame + ret +_x_rect_pattern endp + +;----------------------------------------------------------------------- +; Mode X (320x240, 256 colors) display memory to display memory copy +; routine. Left edge of source rectangle modulo 4 must equal left edge +; of destination rectangle modulo 4. Works on all VGAs. Uses approach +; of reading 4 pixels at a time from the source into the latches, then +; writing the latches to the destination. Copies up to but not +; including the column at SrcEndX and the row at SrcEndY. No +; clipping is performed. Results are not guaranteed if the source and +; destination overlap. +; +; +; Based on code originally published in DDJ Mag by M. Abrash +; +;C near-callable as: +; void x_cp_vid_rect(int SrcStartX, int SrcStartY, +; int SrcEndX, int SrcEndY, int DestStartX, +; int DestStartY, unsigned int SrcPageBase, +; unsigned int DestPageBase, int SrcBitmapWidth, +; int DestBitmapWidth); + +_x_cp_vid_rect proc + ARG SrcStartX:word,SrcStartY:word,SrcEndX:word,SrcEndY:word,DestStartX:word,DestStartY:word,SrcPageBase:word,DestPageBase:word,SrcBitmapW:word,DestBitmapW:word + LOCAL SrcNextOffs:word,DestNextOffs:word,RectAddrW:word,Height:word=LocalStk + push bp ;preserve caller's stack frame + mov bp,sp ;point to local stack frame + sub sp,LocalStk ;allocate space for local vars + push si ;preserve caller's register variables + push di + push ds + + cld + mov dx,GC_INDEX ;set the bit mask to select all bits + mov ax,00000h+BIT_MASK ; from the latches and none from + out dx,ax ; the CPU, so that we can write the + ; latch contents directly to memory + mov ax,SCREEN_SEG ;point ES to display memory + mov es,ax + mov ax,[DestBitmapW] + shr ax,2 ;convert to width in addresses + mul [DestStartY] ;top dest rect scan line + mov di,[DestStartX] + sar di,2 ;X/4 = offset of first dest rect pixel in + ; scan line + add di,ax ;offset of first dest rect pixel in page + add di,[DestPageBase] ;offset of first dest rect pixel + ; in display memory + mov ax,[SrcBitmapW] + sar ax,2 ;convert to width in addresses + mul [SrcStartY] ;top source rect scan line + mov si,[SrcStartX] + mov bx,si + sar si,2 ;X/4 = offset of first source rect pixel in + ; scan line + add si,ax ;offset of first source rect pixel in page + add si,[SrcPageBase] ;offset of first source rect + ; pixel in display memory + and bx,0003h ;look up left edge plane mask + mov ah,LeftClipPlaneMask[bx] ; to clip + mov bx,[SrcEndX] + and bx,0003h ;look up right edge plane + mov al,RightClipPlaneMask[bx] ; mask to clip + mov bx,ax ;put the masks in BX + + mov cx,[SrcEndX] ;calculate # of addresses across + mov ax,[SrcStartX] ; rect + cmp cx,ax + jle @@CopyDone ;skip if 0 or negative width + dec cx + and ax,not 011b + sub cx,ax + sar cx,2 ;# of addresses across rectangle to copy - 1 + jnz @@MasksSet ;there's more than one address to draw + and bh,bl ;there's only one address, so combine the left + ; and right edge clip masks +@@MasksSet: + mov ax,[SrcEndY] + sub ax,[SrcStartY] ;AX = height of rectangle + jle @@CopyDone ;skip if 0 or negative height + mov [Height],ax + mov ax,[DestBitmapW] + sar ax,2 ;convert to width in addresses + sub ax,cx ;distance from end of one dest scan line + dec ax ; to start of next + mov [DestNextOffs],ax + mov ax,[SrcBitmapW] + sar ax,2 ;convert to width in addresses + sub ax,cx ;distance from end of one source scan line + dec ax ; to start of next + mov [SrcNextOffs],ax + mov [RectAddrW],cx ;remember width in addresses - 1 + mov dx,SC_INDEX+1 ;point to Sequence Controller Data reg + ; (SC Index still points to Map Mask) + mov ax,es ;DS=ES=screen segment for MOVS + mov ds,ax +@@CopyRowsLoop: + mov cx,[RectAddrW] ;width across - 1 + mov al,bh ;put left-edge clip mask in AL + out dx,al ;set the left-edge plane (clip) mask + movsb ;copy the left edge (pixels go through + ; latches) + dec cx ;count off left edge address + js @@CopyLoopBottom ;that's the only address + jz @@DoRightEdge ;there are only two addresses + mov al,00fh ;middle addresses are drawn 4 pix per go + out dx,al ;set the middle pixel mask to no clip + rep movsb ;draw the middle addresses four pix per go + ; (pixels copied through latches) +@@DoRightEdge: + mov al,bl ;put right-edge clip mask in AL + out dx,al ;set the right-edge plane (clip) mask + movsb ;draw the right edge (pixels copied through + ; latches) +@@CopyLoopBottom: + add si,[SrcNextOffs] ;point to the start of + add di,[DestNextOffs] ; next source & dest lines + dec word ptr [Height] ;count down scan lines + jnz @@CopyRowsLoop +@@CopyDone: + mov dx,GC_INDEX+1 ;restore the bit mask to its default, + mov al,0ffh ; which selects all bits from the CPU + out dx,al ; and none from the latches (the GC + ; Index still points to Bit Mask) + pop ds + pop di ;restore caller's register variables + pop si + mov sp,bp ;discard storage for local variables + pop bp ;restore caller's stack frame + ret +_x_cp_vid_rect endp + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copy a rectangular region of a VGA screen, with x coordinates +; rounded to the nearest byte -- source and destination may overlap. +; +; C near-callable as: +; +; void x_shift_rect (WORD SrcLeft, WORD SrcTop, +; WORD SrcRight, WORD SrcBottom, +; WORD DestLeft, WORD DestTop, WORD ScreenOffs); +; +; SrcRight is rounded up, and the left edges are rounded down, to ensure +; that the pixels pointed to by the arguments are inside the rectangle. +; +; The width of the rectangle in bytes (width in pixels / 4) +; cannot exceed 255. +; +; ax, bx, cx, dx, and es eat hot lead. +; +; This function was written by Matthew MacKenzie +; matm@eng.umd.edu + + align 2 +_x_shift_rect proc +ARG SrcLeft,SrcTop,SrcRight,SrcBottom,DestLeft,DestTop,ScreenOffs:word +LOCAL width_temp:word=LocalStk + + push bp + mov bp, sp + sub sp, LocalStk + push si + push di + push ds + + ; find values for width & x motion + mov si, SrcLeft ; source x in bytes + sar si, 2 + + mov di, DestLeft ; destination x in bytes + sar di, 2 + + mov bx, SrcRight ; right edge of source in bytes, rounded up + add bx, 3 + sar bx, 2 + sub bx, si + mov ax, bx ; width - 1 + inc bx ; we'll use this as an offset for moving up or down + mov width_temp, bx + + cld ; by default, strings increment + + cmp si, di + jge @@MovingLeft + +; we're moving our rectangle right, so we copy it from right to left + add si, ax ; source & destination will start on the right edge + add di, ax + neg bx + std ; strings decrement + +@@MovingLeft: + +; find values for height & y motion + mov cx, _ScrnLogicalByteWidth ; bytes to move to advance one line + mov ax, SrcTop + mov dx, DestTop ; default destination y + cmp ax, dx + jge @@MovingUp + +; we're moving our rectangle down, so we copy it from bottom to top + mov ax, SrcBottom ; source starts at bottom + add dx, ax ; add (height - 1) to destination y + sub dx, SrcTop + neg cx ; advance up screen rather than down + +@@MovingUp: + push dx ; save destination y during multiply + mul _ScrnLogicalByteWidth + add si, ax ; add y in bytes to source + pop ax ; restore destination y + mul _ScrnLogicalByteWidth + add di, ax ; add y in bytes to destination + + sub cx, bx ; final value for moving up or down + + add si, ScreenOffs ; source & destination are on the same screen + add di, ScreenOffs + + mov dx, SC_INDEX ; set map mask to all four planes + mov ax, 00f02h + out dx, ax + + mov dx, GC_INDEX ; set bit mask to take data from latches + mov ax, BIT_MASK ; rather than CPU + out dx, ax + + mov ax, SCREEN_SEG ; source and destination are VGA memory + mov es, ax + mov ds, ax + + mov ah, byte ptr width_temp ; width in bytes should fit in 8 bits + + mov bx, SrcBottom ; height - 1 + sub bx, SrcTop + + mov dx, cx ; bytes to add to advance one line + + xor ch, ch ; ready to rock + +@@LineLoop: + mov cl, ah ; load width in bytes + rep movsb ; move 4 pixels at a time using latches (YOW!) + + add si, dx ; advance source by one line + add di, dx ; advance destination by one line + + dec bx ; line counter + jge @@LineLoop ; 0 still means one more to go + + mov dx, GC_INDEX + 1; set bit mask to take data from CPU (normal setting) + mov al, 0ffh + out dx, al + +; kick + pop ds + pop di + pop si + mov sp, bp + pop bp + + ret +_x_shift_rect endp + + end + diff --git a/16/xlib/xrect.h b/16/xlib/xrect.h new file mode 100755 index 00000000..04724b6a --- /dev/null +++ b/16/xlib/xrect.h @@ -0,0 +1,89 @@ +/*----------------------------------------------------------------------- +; +; XRECT - header file +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;-----------------------------------------------------------------------*/ + +#ifndef _XRECT_H_ +#define _XRECT_H_ + + +/* FUNCTIONS =========================================================== */ + +#ifdef __cplusplus +extern "C" { +#endif + + void x_rect_pattern( /* draw a pattern filled rectangle */ + WORD StartX, + WORD StartY, + WORD EndX, + WORD EndY, + WORD PageBase, + BYTE far * Pattern); + + void x_rect_pattern_clipped( /* draw a pattern filled clipped */ + WORD StartX, /* rectangle */ + WORD StartY, + WORD EndX, + WORD EndY, + WORD PageBase, + BYTE far * Pattern); + + void x_rect_fill( /* draw a single colour filled rectangle */ + WORD StartX, + WORD StartY, + WORD EndX, + WORD EndY, + WORD PageBase, + WORD color); + + void x_rect_fill_clipped( /* draw a single colour filled */ + WORD StartX, /* and clipped rectangle */ + WORD StartY, + WORD EndX, + WORD EndY, + WORD PageBase, + WORD color); + + void x_cp_vid_rect( /* Copy rect region within VRAM */ + WORD SourceStartX, + WORD SourceStartY, + WORD SourceEndX, + WORD SourceEndY, + WORD DestStartX, + WORD DestStartY, + WORD SourcePageBase, + WORD DestPageBase, + WORD SourceBitmapWidth, + WORD DestBitmapWidth); + +/* Copy a rectangular region of a VGA screen, with x coordinates + rounded to the nearest byte -- source and destination may overlap. */ + + void x_shift_rect (WORD SrcLeft, WORD SrcTop, + WORD SrcRight, WORD SrcBottom, + WORD DestLeft, WORD DestTop, WORD ScreenOffs); + +#ifdef __cplusplus +} +#endif + + +#endif + + diff --git a/16/xlib/xrect.inc b/16/xlib/xrect.inc new file mode 100755 index 00000000..278ba576 --- /dev/null +++ b/16/xlib/xrect.inc @@ -0,0 +1,22 @@ +;----------------------------------------------------------------------- +; +; XRECT - Include file +; +; XRECT.ASM export functions +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + global _x_rect_fill :proc + global _x_rect_fill_clipped :proc + global _x_rect_pattern :proc + global _x_rect_pattern_clipped :proc + global _x_cp_vid_rect :proc + global _x_shift_rect :proc diff --git a/16/xlib/xrletool.asm b/16/xlib/xrletool.asm new file mode 100755 index 00000000..5a9143fe --- /dev/null +++ b/16/xlib/xrletool.asm @@ -0,0 +1,655 @@ +;----------------------------------------------------------------------- +; MODULE XRLETOOL +; +; Hardware detection module +; +; Compile with Tasm. +; C callable. +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + +COMMENT $ + +Firstly, please note that this module has been built from the ground up +in a rush so although I'm confident all the functions work, I have'nt +extensively checked them. If any should surface please let me know. + + +This module implements a number of functions comprising an RLE encoding +decoding system. + +RLE stands for RUN LENGTH ENCODING. It is a quick simple data compression +scheme which is commonly used for image data compression or compression +of any data. Although not the most efficient system, it is fast, which is +why it is used in image storage systems like PCX. This implementation is +more efficient than the one used in PCX files because it uses 1 bit to +identify a Run Length byte as opposed to two in PCX files, but more on this +later. + +This set of functions can be used to implement your own compressed image +file format or for example compress game mapse for various levels etc. +The uses are limited by your imagination. + +I opted for trading off PCX RLE compatibility for the improved compression +efficiency. + +Here is how the data is un-compressed to give an idea of its structure. + + +STEP 1 read a byte from the RLE compressed source buffer. + +STEP 2 if has its high bit then the lower 7 bits represent the number of + times the next byte is to be repeated in the destination buffer. + if the count (lower 7 bits) is zero then + we have finished decoding goto STEP 5 + else goto STEP 4 + +STEP 3 Read a data from the source buffer and copy it directly to the + destination buffer. + goto STEP 1 + +STEP 4 Read a data from the source buffer and copy it to the destination + buffer the number of times specified by step 2. + goto STEP 1 + +STEP 5 Stop, decoding done. + +If the byte does not have the high bit set then the byte itself is transfered + to the destination buffer. + +Data bytes that have the high bit already set and are unique in the input + stream are represented as a Run Length of 1 (ie 81 which includes high bit) + followed by the data byte. + +If your original uncompressed data contains few consecutive bytes and most +have high bit set (ie have values > 127) then your so called +compressed data would require up to 2x the space of the uncompressed data, +so be aware that the compression ratio is extremely variable depending on the +type of data being compressed. + +Apologies for this poor attempt at a description, but you can look up +RLE in any good text. Alternatively, any text that describes the PCX file +structure in any depth should have a section on RLE compression. + + + +$ + +LOCALS +.286 + +include model.inc +include xrletool.inc + + .data + +_RLE_last_buff_offs dw (0) +RLEbuff db 2 dup (?) + + .code + +;**************************************************************** +;* +;* NAME: x_buff_RLEncode +;* +;* +;* RLE Compresses a source buffer to a destination buffer and returns +;* the size of the resultant compressed data. +;* +;* C PROTOTYPE: +;* +;* extern unsigned int x_buff_RLEncode(char far * source_buff, +;* char far * dest_buff,unsigned int count); +;* +;* source_buff - The buffer to compress +;* dest_buff - The destination buffer +;* count - The size of the source data in bytes +;* +;* WARNING: buffers must be pre allocated. +;* +proc _x_buff_RLEncode +ARG src:dword,dest:dword,count:word + push bp + mov bp,sp + push ds + push si + push di + + lds si,[src] + les di,[dest] + mov dx,[count] + + push di + + lodsb ; Load first byte into BL + mov bl,al + xor cx,cx ; Set number characters packed to zero + cld ; All moves are forward + +@@RepeatByte: + lodsb ; Get byte into AL + inc cx ; Increment compressed byte count + sub dx,1 ; Decrement bytes left + je @@LastByte ; Finished when dx = 1 + cmp cx,7fh ; Filled block yet + jne @@NotFilled ; Nope! + + or cl,80h ; Set bit to indicate value is repeat count + mov es:[di],cl ; store it + inc di + xor cx,cx ; clear compressed byte count + mov es:[di],bl ; store byte to be repeated + inc di + +@@NotFilled: + cmp al,bl ; hase there been a byte transition ? + je @@RepeatByte ; No! + + cmp cl,1 ; do we have a unique byte ? + jne @@NotUnique ; No + + test bl,80h ; Can this byte be mistaken for repeat count + jz @@Unambiguous ; No ! Dont bother with repeat count + +@@NotUnique: + or cl,80h ; Set bit to indicate value is repeat count + mov es:[di],cl ; store it + inc di +@@Unambiguous: + xor cx,cx ; clear compressed byte count + mov es:[di],bl ; store byte to be repeated + inc di + mov bl,al ; move latest byte into bl + jmp short @@RepeatByte + +@@LastByte: + cmp cl,1 ; Is this a unique byte + jne @@FinalCount ; No + + test bl,80h ; Can this byte be mistaken for repeat count + jz @@FinalByte ; No, so dont bother with the repeat count + +@@FinalCount: ; Output the repeat count + or cl,80h + mov al,cl + stosb + +@@FinalByte: + mov al,bl + stosb + + mov al,80h ; store terminating null length + stosb + + ; Calculate encoded length of buffer + + mov ax,di + pop di + sub ax,di + + pop di + pop si + pop ds + pop bp + ret +_x_buff_RLEncode endp + + + +;**************************************************************** +;* +;* NAME: x_buff_RLE_size +;* +;* +;* Returns the size the input data would compress to. +;* +;* C PROTOTYPE: +;* +;* extern unsigned int x_buff_RLE_size(char far * source_buff, +;* unsigned int count); +;* +;* source_buff - The uncompressed data buffer +;* count - The size of the source data in bytes +;* +;* +proc _x_buff_RLE_size +ARG src:dword,count:word + push bp + mov bp,sp + push ds + push si + push di + + lds si,[src] + mov dx,[count] + + xor di,di + + lodsb ; Load first byte into BL + mov bl,al + xor cx,cx ; Set number characters packed to zero + cld ; All moves are forward + +@@RepeatByte: + lodsb ; Get byte into AL + inc cx ; Increment compressed byte count + sub dx,1 ; Decrement bytes left + je @@LastByte ; Finished when dx = 1 + cmp cx,7fh ; Filled block yet + jne @@NotFilled ; Nope! + + add di,2 ; RL/BYTE pair stub + +@@NotFilled: + cmp al,bl ; hase there been a byte transition ? + je @@RepeatByte ; No! + + cmp cl,1 ; do we have a unique byte ? + jne @@NotUnique ; No + + test bl,80h ; Can this byte be mistaken for repeat count + jz @@Unambiguous ; No ! Dont bother with repeat count + +@@NotUnique: + inc di ; RL stub + +@@Unambiguous: + xor cx,cx ; clear compressed byte count + inc di ; BYTE stub + mov bl,al ; move latest byte into bl + jmp short @@RepeatByte + +@@LastByte: + cmp cl,1 ; Is this a unique byte + jne @@FinalCount ; No + + test bl,80h ; Can this byte be mistaken for repeat count + jz @@FinalByte ; No, so dont bother with the repeat count + +@@FinalCount: ; Output the repeat count + inc di ; RL stub + +@@FinalByte: + inc di ; BYTE stub + inc di ; RL stub - Account for termiating null + mov ax,di + + pop di + pop si + pop ds + pop bp + ret +_x_buff_RLE_size endp + +;**************************************************************** +;* +;* NAME: x_buff_RLDecode +;* +;* +;* Expands an RLE compresses source buffer to a destination buffer. +;* returns the size of the resultant uncompressed data. +;* +;* C PROTOTYPE: +;* +;* extern unsigned int x_buff_RLDecode(char far * source_buff, +;* char far * dest_buff); +;* +;* source_buff - The buffer to compress +;* dest_buff - The destination buffer +;* +;* WARNING: buffers must be pre allocated. +;* +proc _x_buff_RLDecode +ARG src:dword,dest:dword +LOCAL si_ini:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk + push ds + push si + push di + + mov dx,-1 ; zero output data buffer size - 1 (compensate for + ; terminating null RL) + xor cx,cx ; clear CX + cld ; Move forward + + lds si,[src] ; point ds:si -> RLE source + les di,[dest] ; point es:di -> uncompressed buffer + mov [si_ini],si + +@@UnpackLoop: + lodsb ; load a byte into AL + cmp al,80h ; is it terminating null RL code + je @@done ; if so jump + + test al,80h ; is AL a RL code (is high bit set ?) + jz @@NoRepeats ; if not the no RL encoding for this byte, jump + + mov cl,al ; set CL to RL (run length) taking care + xor cl,80h ; to remove the bit identifying it as a RL + add dx,cx ; increment buffer size + + lodsb ; get the next byte which should be a data byte + + shr cx,1 ; divide RL by 2 to use word stos + jcxz @@NoRepeats ; result is zero, jump + + mov ah,al ; copy data byte to AH since going to use stosw + rep stosw ; copy AX to outbut buffer RL times + jnb @@UnpackLoop ; when we shifted the RL if we had a carry => + ; we had an odd number of repeats so store the + ; last BYTE if carry was set otherwise jump + stosb ; store AL in destination buffer + jmp short @@UnpackLoop + +@@NoRepeats: + inc dx ; increment buffer size + stosb ; store AL in destination buffer + jmp short @@UnpackLoop + +@@done: + + mov bx,si + sub bx,[si_ini] + mov ax,dx + pop di + pop si + pop ds + mov [_RLE_last_buff_offs],bx + mov sp,bp + pop bp + ret +_x_buff_RLDecode endp + +;========================================================================== +;========================================================================== +; RLEncode to file / RLDecode from file +; WARNING the following functions are *MUCH* slower than the above +; Its best to use the above functions with intermediate buffers where +; disk i/o is concearned... See demo 4 +;========================================================================== +;========================================================================== + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; put_cx +; +; Local utility proc for x_file_RLEncode - write cx to file +; +; Entry: +; es:dx -> output buffer +; cx = word to write +; +; +put_cx proc near + push ds ; preserve critical registers + push ax + push bx + mov ax,ds ; set up DS to output buffers segment + mov ds,ax + mov word ptr [RLEbuff],cx ; copy CX to output buffer + mov ah,40h ; select "write to file or device" DOS service + mov bx,[handle] ; select handle of file to write + mov cx,2 ; sending 2 bytes + int 21h ; call DOS service + pop bx ; recover registers + pop ax + pop ds + ret +put_cx endp + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; put_cx +; +; Local utility proc for x_file_RLEncode - write cx to file +; +; Entry: +; es:dx -> output buffer +; cx = word to write +; +; +put_cl proc near + push ds ; preserve critical registers + push ax + push bx + mov ax,ds ; set up DS to output buffers segment + mov ds,ax + mov byte ptr [RLEbuff],cl + mov ah,40h ; select "write to file or device" DOS service + mov bx,[handle] ; select handle of file to write + mov cx,1 ; sending 1 byte + int 21h ; call DOS service + pop bx ; recover registers + pop ax + pop ds + ret +put_cl endp + + +;**************************************************************** +;* +;* NAME: x_file_RLEncode +;* +;* +;* RLE Compresses a source buffer to an output file returning +;* the size of the resultant compressed data or 0 if it fails. +;* +;* C PROTOTYPE: +;* +;* extern unsigned int x_file_RLEncode(int handle, +;* char far * source_buff,unsigned int count); +;* +;* source_buff - The buffer to compress +;* handle - The file handler +;* count - The size of the source data in bytes +;* +;* +proc _x_file_RLEncode +ARG handle:word,src:dword,count:word +LOCAL filesize:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk + push ds + push si + push di + + mov [filesize],0 + mov dx,offset [RLEbuff] + mov ax,ds + mov es,ax + lds si,[src] + mov di,[count] + + lodsb ; Load first byte into BL + mov bl,al + xor cx,cx ; Set number characters packed to zero + cld ; All moves are forward + +@@RepeatByte: + lodsb ; Get byte into AL + inc cx ; Increment compressed byte count + sub di,1 ; Decrement bytes left + je @@LastByte ; Finished when di = 1 + cmp cx,7fh ; Filled block yet + jne @@NotFilled ; Nope! + + or cl,80h ; Set bit to indicate value is repeat count + mov ch,bl + add [filesize],2 + call put_cx + jb @@FileError ; if carry set then file I/O error + xor cx,cx ; clear compressed byte count + +@@NotFilled: + cmp al,bl ; hase there been a byte transition ? + je @@RepeatByte ; No! + + cmp cl,1 ; do we have a unique byte ? + jne @@NotUnique ; No + + test bl,80h ; Can this byte be mistaken for repeat count + jz @@Unambiguous ; No ! Dont bother with repeat count + +@@NotUnique: + or cl,80h ; Set bit to indicate value is repeat count + inc [filesize] + call put_cl ; store it + jb @@FileError ; if carry set then file I/O error +@@Unambiguous: + + mov cl,bl ; store byte to be repeated + inc [filesize] + call put_cl + jb @@FileError ; if carry set then file I/O error + mov bl,al ; move latest byte into bl + xor cx,cx ; clear compressed byte count + jmp short @@RepeatByte + +@@FileError: + mov ax,0 + jmp short @@exit + +@@LastByte: + cmp cl,1 ; Is this a unique byte + jne @@FinalCount ; No + + test bl,80h ; Can this byte be mistaken for repeat count + jz @@FinalByte ; No, so dont bother with the repeat count + +@@FinalCount: ; Output the repeat count + or cl,80h + inc [filesize] + call put_cl + jb @@FileError ; if carry set then file I/O error + +@@FinalByte: + mov cl,bl + mov ch,80h + add [filesize],2 + call put_cx ; store terminating null length + jb @@FileError ; if carry set then file I/O error + + mov ax,[filesize] + jmp short @@exit + +@@exit: + pop di + pop si + pop ds + mov sp,bp + pop bp + ret +_x_file_RLEncode endp + + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; GET_BYTE +; +; macro to read a byte from the input file into al +; +GET_BYTE macro + push bx + mov ah,3fh ; select "read from file or device" DOS service + mov bx,[handle] ; Select handle of file to close + mov cx,1 ; Want to read 1 byte + int 21h ; call DOS service + pop bx + jb @@FileError ; failed if carry flag set + mov al,[RLEbuff] + endm + + +;**************************************************************** +;* +;* NAME: x_file_RLDecode +;* +;* +;* Expands an RLE compresses file to a destination RAM buffer. +;* returns the size of the resultant uncompressed data. +;* +;* C PROTOTYPE: +;* +;* extern unsigned int x_buff_RLDecode(int handle, +;* char far * dest_buff); +;* +;* handle - Input file handle +;* dest_buff - The destination buffer +;* +;* +proc _x_file_RLDecode +ARG handle:word,dest:dword + push bp + mov bp,sp + push si + push di + + + mov bx,-1 ; zero output data buffer size - 1 (compensate for + ; terminating null RL) + mov dx,offset [RLEbuff] ; setup DS:DX -> RLEBuffer + xor cx,cx ; clear CX + cld ; Move forward + + les di,[dest] ; point es:di -> uncompressed buffer + +@@UnpackLoop: + + GET_BYTE ; Load a byte from file into AL + + cmp al,80h ; is it terminating null RL code + je @@done ; if so jump + + test al,80h ; is AL a RL code (is high bit set ?) + jz @@NoRepeats ; if not the no RL encoding for this byte, jump + + mov cl,al ; set CL to RL (run length) taking care + xor cl,80h ; to remove the bit identifying it as a RL + add bx,cx ; increment buffer size + mov si,cx ; save the CX value + GET_BYTE ; Load a byte from file into AL + mov cx,si ; restore CX value + shr cx,1 ; divide RL by 2 to use word stos + jcxz @@NoRepeats ; result is zero, jump + + mov ah,al ; copy data byte to AH since going to use stosw + rep stosw ; copy AX to outbut buffer RL times + jnb @@UnpackLoop ; when we shifted the RL if we had a carry => + ; we had an odd number of repeats so store the + ; last BYTE if carry was set otherwise jump + stosb ; store AL in destination buffer + jmp short @@UnpackLoop + +@@NoRepeats: + inc bx + stosb ; store AL in destination buffer + jmp short @@UnpackLoop + +@@FileError: + mov ax,0 + jmp short @@exit + +@@done: + mov ax,bx +@@exit: + pop di + pop si + pop bp + ret +_x_file_RLDecode endp + + end + + \ No newline at end of file diff --git a/16/xlib/xrletool.h b/16/xlib/xrletool.h new file mode 100755 index 00000000..0ec859e6 --- /dev/null +++ b/16/xlib/xrletool.h @@ -0,0 +1,50 @@ +/*----------------------------------------------------------------------- +; +; XRLETOOL - header file +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +;-----------------------------------------------------------------------*/ + +#ifndef _XRLETOOL_H_ +#define _XRLETOOL_H_ + +extern unsigned int RLE_last_buff_offs; + +/* FUNCTIONS =========================================================== */ + +extern unsigned int x_buff_RLEncode( /* Compress data buffer */ + char far * source_buff, + char far * dest_buff, + unsigned int count); + +extern unsigned int x_buff_RLE_size( /* Calculate buffer's compressed size */ + char far * source_buff, + unsigned int count); + + +extern unsigned int x_buff_RLDecode( /* Uncompress data buffer */ + char far * source_buff, + char far * dest_buff); + +extern int x_file_RLEncode( /* Compress data buffer to file */ + int handle, + char far * src_buff, + unsigned int count); + +extern int x_file_RLDecode( /* Uncompress data file */ + int file_handle, + char far * dest_buff); + + +#endif + + + \ No newline at end of file diff --git a/16/xlib/xrletool.inc b/16/xlib/xrletool.inc new file mode 100755 index 00000000..6fda4ffb --- /dev/null +++ b/16/xlib/xrletool.inc @@ -0,0 +1,26 @@ +;----------------------------------------------------------------------- +; +; XRLETOOL - Include file +; +; XRLETOOL.ASM export functions +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + + global _x_buff_RLEncode :proc + global _x_buff_RLE_size :proc + global _x_buff_RLDecode :proc + global _x_file_RLEncode :proc + global _x_file_RLDecode :proc + + global _RLE_last_buff_offs :word + + \ No newline at end of file diff --git a/16/xlib/xtext.asm b/16/xlib/xtext.asm new file mode 100755 index 00000000..378ed265 --- /dev/null +++ b/16/xlib/xtext.asm @@ -0,0 +1,446 @@ +;----------------------------------------------------------------------- +; MODULE XTEXT +; +; Point functions all MODE X 256 Color resolutions +; +; Compile with Tasm. +; C callable. +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + +include xlib.inc +include xtext.inc + +.data + +_FontDriverActive db 0 + + +_CharHeight db 0 +_CharWidth db 0 +_FontPtr dw 2 dup (0) +_FirstChar db 0 + +_UserFontPtr dw 2 dup (0) +_UserChHeight db 0 +_UserChWidth db 0 +_UserFirstCh db 0 + + +F8x8Ptr dw 2 dup (0) +F8x14Ptr dw 2 dup (0) + +; This is a look up table for the mirror image of a byte eg +; a byte with the value 11001010 has a corresponding byte in the table +; 01010011. This is necessary as the VGA rom font bits are the reverse +; order of what we need for the Mode X. If you know a better-faster way +; TELL ME! + +MirrorTable label byte + db 0,128, 64,192, 32,160, 96,224, 16,144, 80,208, 48,176,112,240 + db 8,136, 72,200, 40,168,104,232, 24,152, 88,216, 56,184,120,248 + db 4,132, 68,196, 36,164,100,228, 20,148, 84,212, 52,180,116,244 + db 12,140, 76,204, 44,172,108,236, 28,156, 92,220, 60,188,124,252 + db 2,130, 66,194, 34,162, 98,226, 18,146, 82,210, 50,178,114,242 + db 10,138, 74,202, 42,170,106,234, 26,154, 90,218, 58,186,122,250 + db 6,134, 70,198, 38,166,102,230, 22,150, 86,214, 54,182,118,246 + db 14,142, 78,206, 46,174,110,238, 30,158, 94,222, 62,190,126,254 + db 1,129, 65,193, 33,161, 97,225, 17,145, 81,209, 49,177,113,241 + db 9,137, 73,201, 41,169,105,233, 25,153, 89,217, 57,185,121,249 + db 5,133, 69,197, 37,165,101,229, 21,149, 85,213, 53,181,117,245 + db 13,141, 77,205, 45,173,109,237, 29,157, 93,221, 61,189,125,253 + db 3,131, 67,195, 35,163, 99,227, 19,147, 83,211, 51,179,115,243 + db 11,139, 75,203, 43,171,107,235, 27,155, 91,219, 59,187,123,251 + db 7,135, 71,199, 39,167,103,231, 23,151, 87,215, 55,183,119,247 + db 15,143, 79,207, 47,175,111,239, 31,159, 95,223, 63,191,127,255 + +MirrorTableOffs dw ? +.code + +;---------------------------------------------------------------------- +; x_text_init - Initializes the Mode X text driver and sets the +; default font (VGA ROM 8x8) +; +; C caller: +; +; x_text_init() +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_text_init proc + push bp + + mov [_FontDriverActive],TRUE + mov ax,1130h ; AH = BIOS generator function + ; AL = BIOS get font pointer subfunction + push ax ; Save Video interrupt function parameters + mov bh,3 ; Select 8x8 VGA ROM font + int 10h ; Call BIOS video interrupt + mov word ptr [F8x8Ptr],bp ; Save 8x8 Font address in FontPtr table + mov word ptr [F8x8Ptr+2],es + + mov word ptr [_FontPtr],bp ; Default font = 8x8 ROM font + mov word ptr [_FontPtr+2],es + + pop ax ; Recall Video interrupt function parameters + mov bh,2 ; Select 8x14 VGA ROM font + int 10h ; Call BIOS video interrupt + mov word ptr [F8x14Ptr],bp ; Save 8x14 Font address in FontPtr table + mov word ptr [F8x14Ptr+2],es + + + mov al,8 + mov [_CharHeight],al ; Set the font character heights + mov [_CharWidth] ,al ; Set the font character widths + + mov dx,offset MirrorTable ; Initialize mirror table offset + mov [MirrorTableOffs],dx + + pop bp + ret +_x_text_init endp + + +;---------------------------------------------------------------------- +; x_set_font - Mode X Set current font for text drawing +; +; C caller: +; +; x_set_font(int FontID) +; +; PARAMETERS FontID 0 = VGA ROM 8x8 +; 1 = VGA ROM 8x14 +; 2 = User defined bitmapped font +; +; +; WARNING: A user font must be registered before setting FontID 2 +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- + +_x_set_font proc + ARG FontID:word + push bp + mov bp,sp + + xor dx,dx ; Clear DX - Mirror table offset (0 for non ROM fonts) + mov cx,FontID + cmp cx,2 + + jne @@not_userfont ; Do we have a user font + mov ax,[_UserFontPtr] ; Yes - Activate it + mov [_FontPtr],ax + + mov ax,[_UserFontPtr+2] + mov [_FontPtr+2],ax + + mov al,[_UserChHeight] + mov [_CharHeight],al ; Set the font character heights + + mov al,[_UserChWidth] + mov [_CharWidth],al ; Set the font character heights + + mov al,[_UserFirstCh] + mov [_FirstChar],al + jmp short @@done + +@@not_userfont: ; We have a ROM font + + mov dx,offset MirrorTable + mov [_CharWidth],8 ; Set the font character widths + mov [_FirstChar],0 ; Character sets start at ascii 0 + cmp cx,1 ; Do we have an 8x14 ROM font + jne @@not_8x14font ; No, we have 8x8 - jump + + mov ax,[F8x14Ptr] ; Yes Activate it + mov [_FontPtr],ax + + mov ax,[F8x14Ptr+2] + mov [_FontPtr+2],ax + + mov [_CharHeight],14 ; Set the font character heights + jmp short @@done + +@@not_8x14font: + mov ax,[F8x8Ptr] ; Activate the 8x8 ROM Font + mov [_FontPtr],ax + + mov ax,[F8x8Ptr+2] + mov [_FontPtr+2],ax + + mov [_CharHeight],8 ; Set the font character heights + +@@done: + mov [MirrorTableOffs],dx + + pop bp + ret +_x_set_font endp + + +;---------------------------------------------------------------------- +; x_register_userfont - Mode X register user font +; +; C caller: +; +; x_register_userfont(void far *user_font) +; +; +; NOTES registering a user font deregisters the previous user font +; User fonts may be at most 8 pixels wide +; +; +; USER FONT STRUCTURE +; +; Word: ascii code of first char in font +; Byte: Height of chars in font +; Byte: Width of chars in font +; n*h*Byte: the font data where n = number of chars and h = height +; of chars +; +; WARNING: The onus is on the program to ensure that all characters +; drawn whilst this font is active, are within the range of +; characters defined. +; +; +; UPDATE: Variable width fonts are now available (up to 8 pixels max) +; If the Width byte in the font header is 0 then it is assumed that +; the font is variable width. For variable width fonts each characters +; data is followed by one byte representing the characters pixel width. +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_register_userfont proc + ARG FontToRegister:dword + push bp + mov bp,sp + push si + + mov ax,word ptr [FontToRegister] + mov bx,word ptr [FontToRegister+2] + add ax,4 + mov [_UserFontPtr],ax + mov [_UserFontPtr+2],bx + + push ds + lds si,[FontToRegister] + lodsw + mov bx,ax + lodsw + pop ds + + mov [_UserChHeight],al + mov [_UserChWidth],ah + mov [_UserFirstCh],bl + pop si + pop bp + ret +_x_register_userfont endp + + +_x_get_char_width proc + ARG Chr:byte + push bp + mov bp,sp + + xor ah,ah + mov al,[_CharWidth] + or al,al + jz @@NotFixed + pop bp + ret + +@@NotFixed: + push si + mov al,[_CharHeight] + mov bx,ax + inc al + mov dl,[Chr] ; User fonts may have incomplete charsets + sub dl,[_FirstChar] ; this compensates for fonts not starting at + ; ascii value 0 + mul dl ; Mult AX by character to draw giving offset + ; of first character byte in font table + add ax,bx + les si,dword ptr [_FontPtr] + add si,ax + xor ah,ah + mov al,es:[si] + pop si + pop bp + ret +_x_get_char_width endp + + +;---------------------------------------------------------------------- +; x_char_put - Mode X Draw a text character at the specified location +; +; +; C caller: +; +; x_char_put(char ch, int x, int y, unsigned ScrnOffs, unsigned Color) +; +; PARAMETERS ch char to draw +; x,y screen coords at which to draw ch +; ScrnOffs Starting offset of page on whih to draw +; Color Color of the text +; +; NOTES: Uses the current font settings. See SetFont, InitTextDriver, +; RegisterUserFont +; +; WARNING: InitTextDriver must be called before using this function +; +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_char_put proc + ARG Chr:byte,X:word,Y:word,ScrnOffs:word,Color:word + LOCAL ScreenInc:word,Hold:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk + push si + push di + push ds + + cld + mov ax,[_ScrnLogicalByteWidth] ; AX = Virtual screen width + mov bx,ax ; copy Virt screen width and decrement + sub bx,3 ; by the max number of bytes (whole or part) + ; that a character row may occupy on the screen + mov [ScreenInc],bx ; Save it to the local stack var. SceenInc + mul [Y] ; Find the starting dest. screen address of + mov di,[X] ; the character to draw + mov cx,di + shr di,2 + add di,ax + add di,[ScrnOffs] ; Dont forget to compensate for page + + mov ax,SCREEN_SEG ; ES:DI -> first screen dest. byte of char + mov es,ax + + and cx,3 ; CH = 0, CL = Plane of first pixel + + mov bx,[MirrorTableOffs] ; set BX to offset of mirror table for XLAT + mov al,[_CharHeight] ; AL = Character height, AH = 0 + xor ah,ah + mov ch,al ; CH = Character height + + cmp [_CharWidth],0 + jne @@NoWidthByte + inc al +@@NoWidthByte: + + mov dl,[Chr] ; User fonts may have incomplete charsets + sub dl,[_FirstChar] ; this compensates for fonts not starting at + ; ascii value 0 + mul dl ; Mult AX by character to draw giving offset + ; of first character byte in font table + + lds si,dword ptr [_FontPtr] ; DS:SI -> beggining of required font + add si,ax ; DS:SI -> first byte of req. char + + mov dx,SC_INDEX ; Prepare for VGA out's + +@@MainLoop: + + lodsb ; load character byte into AL + or al,al + jz @@NoCharPixels ; Dont bother if no pixels to draw + + or bx,bx ; if BX=0 -> User font, so no need to mirror data + jz @@DontMirror + push ds + mov dx,@data ; Set DS to the Mirror lookup table's segment + mov ds,dx ; - BX should already contain the offset addr of table + xlatb ; AL is now replaced by the corresponding table entry + pop ds ; Restore previous data segment + mov dx,SC_INDEX ; Restore DX + +@@DontMirror: + xor ah,ah ; shift the byte for the dest plane and save it + shl ax,cl + mov [Hold],ax + + mov ah,al ; output high nibble of first byte of shifted char + and ah,0fh ; 4 pixels at a time ! + jnz @@p1 ; if nibble has pixels, draw them + inc di ; otherwise go to next nibble + jmp @@SecondNibble + +@@p1: + mov al,MAP_MASK + out dx,ax + mov al,byte ptr [Color] + stosb + +@@SecondNibble: + ; output low nibble of first byte of shifted char + mov ax,[Hold] + shl ax,4 + and ah,0fh + jnz @@p2 + inc di + jmp @@ThirdNibble + +@@p2: + mov al,MAP_MASK + out dx,ax + mov al,byte ptr [Color] + stosb + +@@ThirdNibble: + mov ax,[Hold] ; output high nibble of last byte of shifted char + and ah,0fh + jnz @@p3 + inc di + jmp short @@NextCharRow + +@@p3: + mov al,MAP_MASK ; completing the drawing of one character row + out dx,ax + mov al,byte ptr [Color] + stosb + +@@NextCharRow: + add di,[ScreenInc] ; Now move to the next screen row and do the same + dec ch ; any remaining character bytes + jnz @@MainLoop + +@@done: + pop es + mov ah,0 + mov al,es:[_CharWidth] ; return the character width (for string fuctions + or al,al + jnz @@FixedSpacing ; using this character drawing function). + lodsb +@@FixedSpacing: + + mov bx,es + mov ds,bx + + pop di + pop si + mov sp,bp + pop bp + ret + +@@NoCharPixels: + add di,3 + add di,[ScreenInc] ; Now move to the next screen row and do the same + dec ch ; any remaining character bytes + jnz @@MainLoop + jmp short @@done + +_x_char_put endp + + +end + diff --git a/16/xlib/xtext.h b/16/xlib/xtext.h new file mode 100755 index 00000000..d4dbd923 --- /dev/null +++ b/16/xlib/xtext.h @@ -0,0 +1,91 @@ +/*----------------------------------------------------------------------- +; +; XTEXT - header file +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;-----------------------------------------------------------------------*/ + +#ifndef _XTEXT_H_ +#define _XTEXT_H_ + + +#define FONT_8x8 0 +#define FONT_8x15 1 +#define FONT_USER 2 + +/* FUNCTIONS =========================================================== */ + +#ifdef __cplusplus +extern "C" { +#endif + +WORD x_text_init(void); /* Initialize text functionns */ + +void x_set_font( + WORD FontId); /* Set the font style */ + +void x_register_userfont( /* register a user defined font */ + char far *UserFontPtr); + +unsigned int x_char_put( /* Draw a text character using */ + char ch, /* the currently active font */ + WORD X, + WORD Y, + WORD PgOffs, + WORD Color); + + +unsigned int x_get_char_width( /* Get the character width */ + char ch); + + +/* the folowing function is from xprintf.c but is included due to its */ +/* close relationship with this module */ + +void x_printf( /* formatted text output */ + WORD x, + WORD y, + WORD ScrnOffs, + WORD color, + char *ln,...); + +void x_bgprintf( /* formatted text output */ + WORD x, + WORD y, + WORD ScrnOffs, + WORD fgcolor, + WORD bgcolor, + char *ln,...); + +#ifdef __cplusplus +} +#endif + + +/* VARIABLES =========================================================== */ + +extern BYTE CharHeight; /* Char height of currently active font */ +extern BYTE CharWidth; /* Char width of currently active font */ +extern BYTE FirstChar; /* First char in the curr. active font */ + +extern BYTE UserCharHeight; /* Char height of currentle regist'd user font */ +extern BYTE UserCharWidth; /* Char height of currentle regist'd user font */ +extern BYTE UserFirstChar; /* First char of the curr. regist'd usera font */ + + +#endif + + diff --git a/16/xlib/xtext.inc b/16/xlib/xtext.inc new file mode 100755 index 00000000..37a21977 --- /dev/null +++ b/16/xlib/xtext.inc @@ -0,0 +1,31 @@ +;----------------------------------------------------------------------- +; +; XPOINT - Include file +; +; XPOINT.ASM export functions +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + + global _x_text_init :proc + global _x_set_font :proc + global _x_char_put :proc + global _x_register_userfont :proc + global _x_get_char_width :proc + + global _CharHeight :byte + global _CharWidth :byte + global _FontPtr :word:2 + global _FirstChar :byte + global _UserFontPtr :word:2 + global _UserChHeight :byte + global _UserChWidth :byte + global _UserFirstCh :byte diff --git a/16/xlib/xvbitmap.asm b/16/xlib/xvbitmap.asm new file mode 100755 index 00000000..b57220c8 --- /dev/null +++ b/16/xlib/xvbitmap.asm @@ -0,0 +1,681 @@ +;----------------------------------------------------------------------- +; MODULE XVBITMAP +; +; Video Bitmap functions - Video Ram <-> Video Ram +; +; Compile with Tasm. +; C callable. +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- +COMMENT $ + +The XVBITMAP module implements yet another type of bitmap to complement +planar and compiled bitmaps, VRAM based bitmaps. If a 4 cylinder car is +analagous to planar bitmaps, that is thrifty on memory consumption but low +performance and and a V8 is analagous to Compiled bitmaps, memory guzzlers +that really fly, then VRAM based bitmaps are the 6 cylinder modest performers +with acceptable memory consumption. + +To summarise their selling points, VBM's are moderately fast with fair memory +consumption, and unlike compiled bitmaps, can be clipped. The disadvantages +are that they are limited by the amount of free video ram and have a complex +structure. + +The VRAM bitmap format is rather complex consisting of components stored in +video ram and components in system ram working together. This complexity +necessitates the existence of a creation function "x_make_vbm" which takes +an input linear bitmap and generates the equivalent VBM (VRAM Bit Map). + +VBM structure: + + WORD 0 Size Total size of this VBM structure in bytes + WORD 1 ImageWidth Width in bytes of the image (for all alignments) + WORD 2 ImageHeight Height in scan lines of the image + + WORD 3 Alignment 0 ImagePtr Offset in VidRAM of this aligned image + +--WORD 4 MaskPtr Offset (within this structure's DS) of + | . alignment masks + | . + | . + | WORD 9 Alignment 3 ImagePtr Offset in VidRAM of this aligned image + +|--WORD 10 MaskPtr Offset (within this structure's DS) of + || alignment masks + || + |+->BYTE 21 (WORD 11) -------+-- Image masks for alignment 0 + | . | + | . | + | BYTE 21 + ImageWidth*ImageHeight -----+ + | + | . + | . (similaly for alignments 1 - 2 ) + | . + | + +-->BYTE 21 + 3*ImageWidth*ImageHeight + 1-+-- Image masks for alignment 3 + . | + . | + BYTE 21 + 4*(ImageWidth*ImageHeight) --+ + + . + . + << Similarly for alignments 2 and 3 >> + . + . + BYTE 21 + 4*(ImageWidth*ImageHeight) + ------------- + + (And dont forget the corresponding data in video ram) + +$ + + +include xlib.inc +include xvbitmap.inc + +VBM_info_struc struc + Size dw ? + ImageWidth dw ? + ImageHeight dw ? +; AlignData dw ? +VBM_info_struc ends + +AlignData equ 6 + +VBM_alignment_struc struc + ImagePtr dw ? + MaskPtr dw ? +VBM_alignment_struc ends + + + .code + + +;---------------------------------------------------------------------- +; x_store_vbm_image +; +; Store the linear bitmap in video RAM using the specified alignment and +; start address. Returns number video ram bytes used. +; +; THIS FUNCTION IS FOR USE BY x_make_masked_vbm +; +; Prototype: +; +; x_store_vbm_image(unsigned int vramoffs, unsigned int Align, +; char far *lbm); +; +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_store_vbm_image proc + ARG VramOffs:word,Align:word,LBitmap:dword + LOCAL BMWidth:byte=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + + mov ax,SCREEN_SEG ; Point ES to screen segment + mov es,ax + mov di,[VramOffs] ; Point ES:DI to VRAM dest start + mov bx,[Align] ; Set BL to first pixel plane align + and bl,03h + + lds si,[LBitmap] ; DS:SI -> source linear Bitmap + lodsw ; Al = B.M. width (bytes) AH = B.M. + mov bh,ah ; Save source bitmap dimensions + mov [BMWidth],al ; + + mov dx,SC_INDEX ; Initialize Map Mask for plane + mov al,MAP_MASK ; selection + out dx,al + inc dx + xor ch,ch ; clear CH +@@RowLoop: + mov cl,bl ; Set initial plane for current + mov ah,11h ; allignment + shl ah,cl + + mov cl,[BMWidth] ; Initialize column counter +@@ColLoop: + mov al,ah + out dx,al ; set vga write plane + lodsb ; load next LBM pixel + mov es:[di],al ; store it in Video Ram + shl ah,1 ; rotate plane mask + jnb @@NoAddrIncr ; Time to increment dest address ? + inc di ; Yes: increment addr and reset + mov ah,11h ; plane mask to plane 0 +@@NoAddrIncr: + loop @@ColLoop ; Loop to next pixel column + cmp ah,11h +; je @@skip + inc di ; Increment dest addr +;@@skip: + dec bh ; Decrement row counter + jnz @@RowLoop ; Jump if more rows to go + mov ax,di ; calculate video RAM consumed and + sub ax,[VramOffs] ; return value + + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_store_vbm_image endp + + +_x_put_masked_vbm proc + ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword + LOCAL VBMWidth:word,VBMHeight:word,NextLineIncr:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + + mov ax,SCREEN_SEG ; Point es to VGA segment + mov es,ax + mov ax,[Y] ; Calculate dest screen row + mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen + mul cx ; width then adding screen offset + + mov di,[ScrnOffs] ; store result in DI + add di,ax + mov si,[X] ; Load X coord into CX and make a + mov bx,si ; copy in DX + shr bx,2 ; Find starting byte in dest row + add di,bx ; add to DI giving screen offset of + ; first pixel's byte + + and si,3 ; get pixel alignment in si + + lds bx,[SrcVBM] ; DS:BX -> VBM data structure + shl si,2 ; si = offset of data for curr + ; alignment + + mov ax,word ptr [bx+ImageHeight] ; Get image height + mov [VBMHeight],ax + mov ax,word ptr [bx+ImageWidth] ; Get image width + mov [VBMWidth],ax + + sub cx,ax ; NextLineIncr = bytes to the begin. + mov [NextLineIncr],cx ; of bitmaps next row on screen + mov dx,[bx+MaskPtr+AlignData+si] ; DS:SI -> mask data + mov bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap + mov si,dx + + mov dx,GC_INDEX ; Set bit mask for all bits from + mov ax,BIT_MASK ; VGA latches and none from CPU + out dx,ax + + mov dx,SC_INDEX ; Point SC register to map mask + mov al,MAP_MASK ; in preperation for masking data + out dx,al + inc dx ; Point dx to SC data register + mov ah,byte ptr [VBMHeight] ; AH = Scanline loop counter + +@@RowLoop: + mov cx,[VBMWidth] ; Width in bytes across + +@@ColumnLoop: + lodsb + out dx,al + mov al,es:[bx] ; load latches from source bitmap + stosb ; store latches to dest. bitmap + inc bx + loop @@ColumnLoop + + add di,[NextLineIncr] ; point to start of next dest row + dec ah ; decrement scan line counter + jnz @@RowLoop ; jump if more scanlines left + + mov dx,GC_INDEX+1 ; Restore bitmask to the default - + mov al,0ffh ; all data from cpu + out dx,al + + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_put_masked_vbm endp + + +_x_put_masked_vbm_clipx proc +ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword +LOCAL DataInc,LeftSkip,VBMWidth,VBMHeight,NextLineIncr:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + + mov di,[X] ; load X coord int DI and make a + mov si,di ; copy in SI + sar di,2 ; Find Byte offset of X coord + + and si,3 ; Calculate pixels plane alignment + shl si,2 ; Prepare to lookup mask & data + les bx,[SrcVBM] ; ES:BX -> begining of VBM data + + mov cx,es:[bx+ImageWidth] ; Get image width and save in CX + + + + ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;; + + mov dx,[_LeftClip] + sub dx,di + jle @@NotLeftClip + cmp dx,cx + jnl @@NotVisible + add di,dx + mov [LeftSkip],dx + mov [DataInc],dx + sub cx,dx + jmp short @@HorizClipDone + + ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;; + +@@NotVisible: + mov ax,1 + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret + + ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;; + +@@NotLeftClip: + mov dx,[_RightClip] + sub dx,di + js @@NotVisible + mov [LeftSkip],0 + mov [DataInc],0 + cmp dx,cx + jge @@HorizClipDone + inc dx + sub cx,dx + mov [DataInc],cx + mov cx,dx + +@@HorizClipDone: + + + add di,[ScrnOffs] ; Add the current page offset + mov [VBMWidth],cx + mov ax,es:[bx+ImageHeight] ; Get image height and save in AX + mov [VBMHeight],ax + + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + mov ax,[Y] ; Calculate dest screen row + mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen + mul cx ; width then adding screen offset + add di,ax ; Add Dest Screen Row to di + sub cx,[VBMWidth] + mov [NextLineIncr],cx + + mov ax,es ; copy ES to DS + mov ds,ax + mov ax,SCREEN_SEG ; Point es to VGA segment + mov es,ax + + mov ax,[bx+MaskPtr+AlignData+si] ; DS:SI -> mask data + mov bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap + mov si,ax + + mov ax,[LeftSkip] ; Skip data/mask bytes in + add bx,ax ; each row that have been clipped + add si,ax ; by the L.H.S border + + + mov dx,GC_INDEX ; Set bit mask for all bits from + mov ax,BIT_MASK ; VGA latches and none from CPU + out dx,ax + mov dx,SC_INDEX ; Point SC register to map mask + mov al,MAP_MASK ; in preperation for masking data + out dx,al + inc dx ; Point dx to SC data register + mov ah,byte ptr [VBMHeight] ; AH = Scanline loop counter + +@@RowLoop: + mov cx,[VBMWidth] ; Width in bytes across + +@@ColumnLoop: + lodsb + out dx,al + mov al,es:[bx] ; load latches from source bitmap + stosb ; store latches to dest. bitmap + inc bx + loop @@ColumnLoop + add bx,[DataInc] + add si,[DataInc] + add di,[NextLineIncr] ; point to start of next dest row + dec byte ptr ah ; decrement scan line counter + jnz @@RowLoop ; jump if more scanlines left + + mov dx,GC_INDEX+1 ; Restore bitmask to the default - + mov al,0ffh ; all data from cpu + out dx,al + xor ax,ax + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_put_masked_vbm_clipx endp + + +_x_put_masked_vbm_clipy proc +ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword +LOCAL VBMWidth,VBMHeight,TopRow,NextLineIncr:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + + mov di,[X] ; load X coord int DI and make a + mov si,di ; copy in SI + + + and si,3 ; Calculate pixels plane alignment + shl si,2 ; Prepare to lookup mask & data + les bx,[SrcVBM] ; ES:BX -> begining of VBM data + + + mov ax,es:[bx+ImageHeight] ; Get image height and save in AX + + + + ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;; + + mov dx,[_TopClip] ; Compare u.l. Y coord with Top + sub dx,[Y] ; clipping border + jle @@NotTopClip ; jump if VBM not clipped from above + cmp dx,ax + jnl @@NotVisible ; jump if VBM is completely obscured + mov [TopRow],dx + sub ax,dx + add [Y],dx + jmp short @@VertClipDone + + ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;; + +@@NotVisible: + mov ax,1 + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret + + ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;; + +@@NotTopClip: + mov dx,[_BottomClip] + sub dx,[Y] + js @@NotVisible + mov [TopRow],0 + cmp dx,ax + jg @@VertClipDone + inc dx + mov ax,dx + +@@VertClipDone: + + + shr di,2 ; Find Byte offset of X coord + add di,[ScrnOffs] ; Add the current page offset + mov cx,es:[bx+ImageWidth] ; Get image width and save in CX + mov [VBMWidth],cx + mov [VBMHeight],ax + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + mov ax,[Y] ; Calculate dest screen row + mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen + mul cx ; width then adding screen offset + add di,ax ; Add Dest Screen Row to di + sub cx,[VBMWidth] + mov [NextLineIncr],cx + + mov ax,es ; copy ES to DS + mov ds,ax + mov ax,SCREEN_SEG ; Point es to VGA segment + mov es,ax + + mov ax,[bx+MaskPtr+AlignData+si] ; DS:SI -> mask data + mov bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap + mov si,ax + + + + mov ax,[VBMWidth] ; Increment DS:BX and DS:SI to + mul [TopRow] ; skip image/mask data that has + add bx,ax ; been clipped by the top border + add si,ax + + + mov dx,GC_INDEX ; Set bit mask for all bits from + mov ax,BIT_MASK ; VGA latches and none from CPU + out dx,ax + mov dx,SC_INDEX ; Point SC register to map mask + mov al,MAP_MASK ; in preperation for masking data + out dx,al + inc dx ; Point dx to SC data register + mov ah,byte ptr [VBMHeight] ; AH = Scanline loop counter + +@@RowLoop: + mov cx,[VBMWidth] ; Width in bytes across + +@@ColumnLoop: + lodsb + out dx,al + mov al,es:[bx] ; load latches from source bitmap + stosb ; store latches to dest. bitmap + inc bx + loop @@ColumnLoop + add di,[NextLineIncr] ; point to start of next dest row + dec byte ptr ah ; decrement scan line counter + jnz @@RowLoop ; jump if more scanlines left + + mov dx,GC_INDEX+1 ; Restore bitmask to the default - + mov al,0ffh ; all data from cpu + out dx,al + + xor ax,ax + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_put_masked_vbm_clipy endp + +_x_put_masked_vbm_clipxy proc +ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword +LOCAL DataInc,LeftSkip,VBMWidth,VBMHeight,TopRow,NextLineIncr:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + + mov di,[X] ; load X coord int DI and make a + mov si,di ; copy in SI + sar di,2 ; Find Byte offset of X coord + and si,3 ; Calculate pixels plane alignment + shl si,2 ; Prepare to lookup mask & data + les bx,[SrcVBM] ; ES:BX -> begining of VBM data + + mov cx,es:[bx+ImageWidth] ; Get image width and save in CX + mov ax,es:[bx+ImageHeight] ; Get image height and save in AX + + + + ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;; + + mov dx,[_TopClip] ; Compare u.l. Y coord with Top + sub dx,[Y] ; clipping border + jle @@NotTopClip ; jump if VBM not clipped from above + cmp dx,ax + jnl @@NotVisible ; jump if VBM is completely obscured + mov [TopRow],dx + sub ax,dx + add [Y],dx + jmp short @@VertClipDone + + ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;; + +@@NotVisible: + mov ax,1 + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret + + ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;; + +@@NotTopClip: + mov dx,[_BottomClip] + sub dx,[Y] + js @@NotVisible + mov [TopRow],0 + cmp dx,ax + jg @@VertClipDone + inc dx + mov ax,dx + +@@VertClipDone: + + ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;; + + + mov dx,[_LeftClip] + sub dx,di + jle @@NotLeftClip + cmp dx,cx + jnl @@NotVisible + add di,dx + mov [LeftSkip],dx + mov [DataInc],dx + sub cx,dx + jmp short @@HorizClipDone + + ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;; + +@@NotLeftClip: + mov dx,[_RightClip] + sub dx,di + js @@NotVisible + mov [LeftSkip],0 + mov [DataInc],0 + cmp dx,cx + jge @@HorizClipDone + inc dx + sub cx,dx + mov [DataInc],cx + mov cx,dx + +@@HorizClipDone: + + add di,[ScrnOffs] ; Add the current page offset + mov [VBMWidth],cx + mov [VBMHeight],ax + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + mov ax,[Y] ; Calculate dest screen row + mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen + mul cx ; width then adding screen offset + add di,ax ; Add Dest Screen Row to di + sub cx,[VBMWidth] + mov [NextLineIncr],cx + + mov ax,es ; copy ES to DS + mov ds,ax + mov ax,SCREEN_SEG ; Point es to VGA segment + mov es,ax + + mov ax,[bx+MaskPtr+AlignData+si] ; DS:SI -> mask data + mov bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap + mov si,ax + + + + mov ax,[VBMWidth] ; Increment DS:BX and DS:SI to + add ax,[DataInc] ; skip image/mask data that has + mul [TopRow] ; been clipped by the top border + add ax,[LeftSkip] ; Skip also data/mask bytes in + add bx,ax ; each row that have been clipped + add si,ax ; by the L.H.S border + + + mov dx,GC_INDEX ; Set bit mask for all bits from + mov ax,BIT_MASK ; VGA latches and none from CPU + out dx,ax + mov dx,SC_INDEX ; Point SC register to map mask + mov al,MAP_MASK ; in preperation for masking data + out dx,al + inc dx ; Point dx to SC data register + mov ah,byte ptr [VBMHeight] ; AH = Scanline loop counter + +@@RowLoop: + mov cx,[VBMWidth] ; Width in bytes across + +@@ColumnLoop: + lodsb + out dx,al + mov al,es:[bx] ; load latches from source bitmap + stosb ; store latches to dest. bitmap + inc bx + loop @@ColumnLoop + add bx,[DataInc] + add si,[DataInc] + add di,[NextLineIncr] ; point to start of next dest row + dec byte ptr ah ; decrement scan line counter + jnz @@RowLoop ; jump if more scanlines left + + mov dx,GC_INDEX+1 ; Restore bitmask to the default - + mov al,0ffh ; all data from cpu + out dx,al + xor ax,ax + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_put_masked_vbm_clipxy endp + + + end + + \ No newline at end of file diff --git a/16/xlib/xvbitmap.h b/16/xlib/xvbitmap.h new file mode 100755 index 00000000..856dbabe --- /dev/null +++ b/16/xlib/xvbitmap.h @@ -0,0 +1,69 @@ +/*----------------------------------------------------------------------- +; +; XVBITMAP - header file +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +; +; Terminology & notes: +; VRAM == Video RAM +; SRAM == System RAM +; X coordinates are in pixels unless explicitly stated +; +;-----------------------------------------------------------------------*/ + +#ifndef _XVBITMAP_H_ +#define _XVBITMAP_H_ + + +/* FUNCTIONS =========================================================== */ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +void x_put_masked_vbm( /* Copy a planar bitmap from SRAM masking */ + int X, /* only non zero pixels to VRAM */ + int Y, + WORD ScrnOffs, + BYTE far * VBitmap); + +int x_put_masked_vbm_clipx(/* Copy a planar bitmap from SRAM masking */ + int X, /* only non zero pixels to VRAM. Clip X */ + int Y, + WORD ScrnOffs, + BYTE far * VBitmap); + +int x_put_masked_vbm_clipy(/* Copy a planar bitmap from SRAM masking */ + int X, /* only non zero pixels to VRAM. Clip Y */ + int Y, + WORD ScrnOffs, + BYTE far * VBitmap); + +int x_put_masked_vbm_clipxy(/* Copy a planar bitmap from SRAM masking */ + int X, /* only non zero pixels to VRAM. Clip X & Y */ + int Y, + WORD ScrnOffs, + BYTE far * VBitmap); + +char far * x_make_vbm( + char far *lbm, + WORD *VramStart); + +#ifdef __cplusplus +} +#endif + + +#endif + + diff --git a/16/xlib/xvbitmap.inc b/16/xlib/xvbitmap.inc new file mode 100755 index 00000000..38caa4dc --- /dev/null +++ b/16/xlib/xvbitmap.inc @@ -0,0 +1,22 @@ +;----------------------------------------------------------------------- +; +; XVBITMAP - Include file +; +; XVBITMAP.ASM export functions +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + global _x_store_vbm_image :proc + global _x_put_masked_vbm :proc + global _x_put_masked_vbm_clipx :proc + global _x_put_masked_vbm_clipy :proc + global _x_put_masked_vbm_clipxy :proc + \ No newline at end of file diff --git a/16/xlib/xvbmtool.inc b/16/xlib/xvbmtool.inc new file mode 100755 index 00000000..6fbc8717 --- /dev/null +++ b/16/xlib/xvbmtool.inc @@ -0,0 +1,22 @@ +;----------------------------------------------------------------------- +; +; XVBMTOOL - Include file +; +; XVBMTOOL.ASM export functions +; +; +; +; ****** XLIB - Mode X graphics library **************** +; ****** **************** +; ****** Written By Themie Gouthas **************** +; ****** Aeronautical Research Laboratory **************** +; ****** Defence Science and Technology Organisation **************** +; ****** Australia **************** +; +; egg@dstos3.dsto.gov.au +; teg@bart.dsto.gov.au +;----------------------------------------------------------------------- + + + global _x_store_vbm_image :proc + \ No newline at end of file diff --git a/16/xlib/xvsync.asm b/16/xlib/xvsync.asm new file mode 100755 index 00000000..452ec654 --- /dev/null +++ b/16/xlib/xvsync.asm @@ -0,0 +1,311 @@ +; MODULE XVSYNC +; Xlib comptible vsync handler +; Written by Tore Bastiansen +; based on REND386 by Dave Stampe and Bernie Roehl + +include xlib.inc +include xmain.inc +include xvsync.inc + + +TIMER_VECT equ 08h + +PIC_CMD equ 20h +NONSPEC_EOI equ 20h +TIMER_MODE equ 34h +TIMER_CONTROL equ 43h +TIMER_0 equ 40h + +LATCH_COUNT equ 00h + +INT_IN_ADVANCE equ 100 + +DOS_GETVECT equ 3500h +DOS_SETVECT equ 2500h + + +.data +_TicksPerSecond dw 0 +_VsyncIntTicks label dword +VsyncIntTicksLo dw 0 +VsyncIntTicksHi dw 0 +_VsyncPeriod dw 0 ;Time (in clicks) between each vsync + ;1 click = 1.193 microseconds + +ClockRate dw 0 ;Clock rate (in clicks) for timer 0 +ClockCounter dw 0 ;Counts total clicks modulo 65536 +UserVsyncHandler label dword ;Pointer to user routine called +UserVsyncOffs dw 0 ;called once each vsync period. +UserVsyncSeg dw 0 +InUserHandler dw 0 + db 100h dup(?) +LocalStack label byte ;Local stack for user handler +StackSeg dw 0 +StackPtr dw 0 + + +ElapsedVrts dw 0 +VrtsToSkip dw 1 + +.code +get_vsync_period proc near + mov al,TIMER_MODE ;Start timer + out TIMER_CONTROL,al + mov al,0 + out TIMER_0,al + out TIMER_0,al + + WaitVsyncStart + + mov al,LATCH_COUNT + out TIMER_CONTROL,al + in al,TIMER_0 + mov cl,al + in al,TIMER_0 + mov ch,al ;cx=65536-clicks + + WaitVsyncStart + + mov al,LATCH_COUNT + out TIMER_CONTROL,al + in al,TIMER_0 + mov dl,al + in al,TIMER_0 + mov dh,al ;dx=65536-clicks + + sub cx,dx ;cx=clicks between two vsyncs + mov ax,cx ;return in ax + ret +get_vsync_period endp + +vsync_int proc far + pusha ;Save regs + push ds + push es + + mov ax,@data ;Set the right datasegment + mov ds,ax + add [VsyncIntTicksLo],1 ;Increment _VsyncIntTicks + adc [VsyncIntTicksHi],0 + + inc [ElapsedVrts] + mov cx,[ElapsedVrts] + cmp cx,[VrtsToSkip] + jl @@StopClock + + cmp [_StartAddressFlag],1 ;Change in start address + jne @@StopClock + + mov dx,CRTC_INDEX ;Yes, set start address + mov ax,[_WaitingStartLow] + mov bx,[_WaitingStartHigh] + out dx,ax + mov ax,bx + out dx,ax + +@@StopClock: + cli + mov al,TIMER_MODE ;Stop the timer + out TIMER_CONTROL,al ;Dont want any interrupts + mov al,255 + out TIMER_0,al + out TIMER_0,al + sti + + cli + mov dx,INPUT_STATUS_0 ;Wait for vsync +@@WaitVS: + in al,dx + test al,08h + jz @@WaitVS + + mov al,TIMER_MODE ;Start timer again + out TIMER_CONTROL,al + mov ax,[ClockRate] + out TIMER_0,al + mov al,ah + out TIMER_0,al + + cmp cx,[VrtsToSkip] + jl @@PaletteInt + + cmp [_StartAddressFlag],1 ;Any change in start address ? + jne @@PaletteInt + + xor cx,cx + mov [ElapsedVrts],cx + + mov ax,[_WaitingPelPan] ;Yes, set pel pan register + mov dx,AC_INDEX + out dx,al + mov al,ah + out dx,al + mov [_StartAddressFlag],0 + +@@PaletteInt: + cmp [_VsyncPaletteCount],0 ;Any changes in the palette + je @@MouseInt + mov si, offset _VsyncPaletteBuffer ;Yes + mov cx, [_VsyncPaletteCount] + mov ax, [_VsyncPaletteStart] + mov dx, DAC_WRITE_INDEX + out dx, al + mov dx, DAC_DATA + +@@DacOutLoop: + outsb + outsb + outsb + loop @@DacOutLoop + mov [_VsyncPaletteCount],0 + +@@MouseInt: + cmp [_MouseRefreshFlag],1 ; Does the mouse need refresh + jne @@UserInt + call dword ptr [_MouseVsyncHandler] ; Yes + ;(this is not yet implemented) + +@@UserInt: + cmp [UserVsyncSeg], 0 ;Is the a user interrupt routine? + je short @@Sim182 + cmp [InUserHandler],0 ;Yes, but is it already active? + jne short @@Sim182 + mov [InUserHandler],1 ;No, mark it as active + mov [StackSeg],ss ;make a local stack + mov [StackPtr],sp + push ds + pop ss + mov sp, offset LocalStack + sti + call dword ptr [UserVsyncHandler] + cli + mov sp, [StackPtr] ;Restore old stack + mov ss, [StackSeg] + mov [InUserHandler],0 ;Mark as not active + +; SIM 18.2 Hz +@@Sim182: + mov ax,[_VsyncPeriod] ;Count number of clicks + add [ClockCounter],ax ;If it is bigger than 65536 + jnc short @@DontChainOld + pop es ;more than 1/18.2 secs has gone + pop ds + popa + sti + db 0eah ; jmp instruction + OldTimerInt dd 0 ; Pointer to old int8 routine + ; Selfmodyfiing code + ;jmp dword ptr [OldTimerInt] Chain to old +@@DontChainOld: + +; CLEAN UP AND RETURN + mov al,NONSPEC_EOI + out PIC_CMD,al + + + pop es + pop ds + popa + sti + iret +vsync_int endp + + +_x_install_vsync_handler proc +ARG VrtSkipCount:word + push bp + mov bp,sp + mov ax,[VrtSkipCount] + or ax,ax + jnz @@NonZeroCount + mov ax,1 +@@NonZeroCount: + mov [VrtsToSkip],ax + mov [ElapsedVrts],0 + cmp [_VsyncHandlerActive],TRUE ;Is it already active + je short @@Return + call get_vsync_period ;no, get the vsync period + + mov [_VsyncPeriod],ax + sub ax,INT_IN_ADVANCE ;We need a little extra + mov [ClockRate],ax ;time + + mov dx,18 ;dx:ax=1193000 + mov ax,13352 + idiv [_VsyncPeriod] + mov [_TicksPerSecond],ax ;1193/_VsyncPeriod + + mov word ptr [_VsyncIntTicks],0 + mov word ptr [_VsyncIntTicks+2],0 + + cli + mov ax, DOS_GETVECT+TIMER_VECT ;Get address of old timer int + int 21h + mov ax,es + mov word ptr cs:[OldTimerInt],bx ;Store in OldTimerInt + mov word ptr cs:[OldTimerInt+2],ax + + mov [_VsyncHandlerActive],TRUE ;Mark handler as active + mov ax,DOS_SETVECT+TIMER_VECT ;Set the new timer int + push ds + mov dx,seg vsync_int + mov ds,dx + mov dx,offset vsync_int + int 21h + pop ds + + mov al,TIMER_MODE ;Reprogram timer 0 + out TIMER_CONTROL,al + mov ax,ClockRate + out TIMER_0,al + mov al,ah + out TIMER_0,al + sti +@@Return: + pop bp + ret +_x_install_vsync_handler endp + +_x_remove_vsync_handler proc + cmp [_VsyncHandlerActive],FALSE + je short @@Return + mov dx, word ptr cs:[OldTimerInt] + mov ax, word ptr cs:[OldTimerInt+2] + push ds + mov ds,ax + mov ax,DOS_SETVECT+TIMER_VECT ;Restore the old timer int + cli + int 21h + pop ds + mov al,TIMER_MODE ;Restore timer 0 + out TIMER_CONTROL,al + mov al,0 + out TIMER_0,al + out TIMER_0,al + sti +@@Return: + ret +_x_remove_vsync_handler endp + + +; WARNING: The user vsync handler cannot use the 386 specific registers +; (EAX,EBX,ECX,EDX,ESI,EDI,ESP,EBP,FS,GS) +; whithout saving them first. +; It must not do any drawing. +; Only 256 butes of stack is provided. + +_x_set_user_vsync_handler proc +ARG handler_proc:dword + push bp + mov bp,sp + mov ax, word ptr [handler_proc] + mov dx, word ptr [handler_proc+2] + cli + mov word ptr [UserVsyncHandler],ax + mov word ptr [UserVsyncHandler+2],dx + sti + pop bp + ret +_x_set_user_vsync_handler endp + +end diff --git a/16/xlib/xvsync.h b/16/xlib/xvsync.h new file mode 100755 index 00000000..be2be0cc --- /dev/null +++ b/16/xlib/xvsync.h @@ -0,0 +1,22 @@ +#ifndef _XVSYNC_H_ +#define _XVSYNC_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + + void x_install_vsync_handler(int skipcount); + void x_remove_vsync_handler(void); + void x_set_user_vsync_handler(void far (*)()); + +#ifdef __cplusplus +} +#endif + + +extern WORD TicksPerSecond; +extern volatile long VsyncIntTicks; +extern WORD VsyncPeriod; + +#endif diff --git a/16/xlib/xvsync.inc b/16/xlib/xvsync.inc new file mode 100755 index 00000000..d93ddade --- /dev/null +++ b/16/xlib/xvsync.inc @@ -0,0 +1,6 @@ +global _x_install_vsync_handler :proc +global _x_remove_vsync_handler :proc +global _x_set_user_vsync_handler :proc +global _TicksPerSecond :word +global _VsyncIntTicks :dword +global _VsyncPeriod :word diff --git a/16/xlib/zip.bat b/16/xlib/zip.bat new file mode 100755 index 00000000..00ecf626 --- /dev/null +++ b/16/xlib/zip.bat @@ -0,0 +1,118 @@ +pkzip -a xlib06.zip MAKEFILE + +pkzip -a xlib06.zip XBEZIER.ASM +pkzip -a xlib06.zip XBMTOOLS.ASM +pkzip -a xlib06.zip XCBITMAP.ASM +pkzip -a xlib06.zip XCOMPPBM.ASM +pkzip -a xlib06.zip XDETECT.ASM +pkzip -a xlib06.zip XFILEIO.ASM +pkzip -a xlib06.zip XLINE.ASM +pkzip -a xlib06.zip XMAIN.ASM +pkzip -a xlib06.zip XMOUSE.ASM +pkzip -a xlib06.zip XPAL.ASM +pkzip -a xlib06.zip XPBITMAP.ASM +pkzip -a xlib06.zip XPBMCLIP.ASM +pkzip -a xlib06.zip XPOINT.ASM +pkzip -a xlib06.zip XRECT.ASM +pkzip -a xlib06.zip XRLETOOL.ASM +pkzip -a xlib06.zip XTEXT.ASM +pkzip -a xlib06.zip XVBITMAP.ASM +pkzip -a xlib06.zip XCIRCLE.ASM +pkzip -a xlib06.zip XCLIPPBM.ASM +pkzip -a xlib06.zip XPOLYGON.ASM +pkzip -a xlib06.zip XFILL.ASM +pkzip -a xlib06.zip XVSYNC.ASM + +pkzip -a xlib06.zip XCBITM32.C +pkzip -a xlib06.zip DEMO1.C +pkzip -a xlib06.zip DEMO2.C +pkzip -a xlib06.zip DEMO3.C +pkzip -a xlib06.zip DEMO4.C +pkzip -a xlib06.zip DEMO5.C +pkzip -a xlib06.zip DEMO6.C +pkzip -a xlib06.zip DEMO7.C +pkzip -a xlib06.zip DEMO8.C +pkzip -a xlib06.zip DEMO9.C +pkzip -a xlib06.zip DEMO10.CPP + +pkzip -a xlib06.zip XMAKEVBM.C +pkzip -a xlib06.zip XPRINTF.C +pkzip -a xlib06.zip UPDATES.DOC +pkzip -a xlib06.zip XLIBREF1.DOC +pkzip -a xlib06.zip XLIBREF2.DOC +pkzip -a xlib06.zip DEMO7.EXE +pkzip -a xlib06.zip DEMO1.EXE +pkzip -a xlib06.zip DEMO2.EXE +pkzip -a xlib06.zip DEMO3.EXE +pkzip -a xlib06.zip DEMO4.EXE +pkzip -a xlib06.zip DEMO5.EXE +pkzip -a xlib06.zip DEMO6.EXE +pkzip -a xlib06.zip DEMO8.EXE +pkzip -a xlib06.zip DEMO9.EXE +pkzip -a xlib06.zip DEMO10.EXE + +pkzip -a xlib06.zip FIXED6X8.FNT +pkzip -a xlib06.zip VAR6X8.FNT +pkzip -a xlib06.zip VARSWISL.FNT +pkzip -a xlib06.zip VARSWISB.FNT +pkzip -a xlib06.zip TIMPANI.FNT +pkzip -a xlib06.zip MODERNB.FNT +pkzip -a xlib06.zip CRISP6X9.FNT +pkzip -a xlib06.zip TINY4.FNT +pkzip -a xlib06.zip SMALTHIN.FNT + +pkzip -a xlib06.zip XBEZIER.H +pkzip -a xlib06.zip XBMTOOLS.H +pkzip -a xlib06.zip XCBITMAP.H +pkzip -a xlib06.zip XCOMPPBM.H +pkzip -a xlib06.zip XDETECT.H +pkzip -a xlib06.zip XFILEIO.H +pkzip -a xlib06.zip XLIB.H +pkzip -a xlib06.zip XLIB_ALL.H +pkzip -a xlib06.zip XLINE.H +pkzip -a xlib06.zip XMOUSE.H +pkzip -a xlib06.zip XPAL.H +pkzip -a xlib06.zip XPBITMAP.H +pkzip -a xlib06.zip XPBMCLIP.H +pkzip -a xlib06.zip XPOINT.H +pkzip -a xlib06.zip XRECT.H +pkzip -a xlib06.zip XRLETOOL.H +pkzip -a xlib06.zip XTEXT.H +pkzip -a xlib06.zip XVBITMAP.H +pkzip -a xlib06.zip XCIRCLE.H +pkzip -a xlib06.zip XCLIPPBM.H +pkzip -a xlib06.zip XPOLYGON.H +pkzip -a xlib06.zip XFILL.H +pkzip -a xlib06.zip XVSYNC.H +pkzip -a xlib06.zip XCBITM32.H + +pkzip -a xlib06.zip MODEL.INC +pkzip -a xlib06.zip XBEZIER.INC +pkzip -a xlib06.zip XBMTOOLS.INC +pkzip -a xlib06.zip XCBITMAP.INC +pkzip -a xlib06.zip XCOMPPBM.INC +pkzip -a xlib06.zip XDETECT.INC +pkzip -a xlib06.zip XFILEIO.INC +pkzip -a xlib06.zip XLIB.INC +pkzip -a xlib06.zip XLINE.INC +pkzip -a xlib06.zip XMAIN.INC +pkzip -a xlib06.zip XPAL.INC +pkzip -a xlib06.zip XPBITMAP.INC +pkzip -a xlib06.zip XPBMCLIP.INC +pkzip -a xlib06.zip XPOINT.INC +pkzip -a xlib06.zip XRECT.INC +pkzip -a xlib06.zip XRLETOOL.INC +pkzip -a xlib06.zip XTEXT.INC +pkzip -a xlib06.zip XVBITMAP.INC +pkzip -a xlib06.zip XVBMTOOL.INC +pkzip -a xlib06.zip XCIRCLE.INC +pkzip -a xlib06.zip XCLIPPBM.INC +pkzip -a xlib06.zip XPOLYGON.INC +pkzip -a xlib06.zip XFILL.INC +pkzip -a xlib06.zip XVSYNC.INC + +pkzip -a xlib06.zip XLIB04S.LIB +pkzip -a xlib06.zip XLIB04C.LIB +pkzip -a xlib06.zip XLIB04L.LIB +pkzip -a xlib06.zip ZIP.BAT + -- 2.39.5