From: sparky4 Date: Wed, 11 Nov 2015 09:34:29 +0000 (-0600) Subject: added xlib to the project and i gotta convert the damn makefile -.- X-Git-Url: http://4ch.mooo.com/gitweb/?a=commitdiff_plain;h=cdb90d6b06eec485931782872a2550afea961050;p=16.git added xlib to the project and i gotta convert the damn makefile -.- --- diff --git a/16/xlib/CRISP6X9.FNT b/16/xlib/CRISP6X9.FNT new file mode 100755 index 00000000..0b8a209b Binary files /dev/null and b/16/xlib/CRISP6X9.FNT differ diff --git a/16/xlib/DEMO1.C b/16/xlib/DEMO1.C new file mode 100755 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;j +#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 00000000..d6dfd068 Binary files /dev/null and b/16/xlib/DEMO2.EXE differ diff --git a/16/xlib/DEMO3.C b/16/xlib/DEMO3.C new file mode 100755 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 00000000..ef3a06a2 Binary files /dev/null and b/16/xlib/DEMO3.EXE differ diff --git a/16/xlib/DEMO4.C b/16/xlib/DEMO4.C new file mode 100755 index 00000000..b91a576a --- /dev/null +++ b/16/xlib/DEMO4.C @@ -0,0 +1,170 @@ +/************************************************************************* + +DEMO 4 + +Demonstrates RLE encoding to file QUICK and DIRTY +**************************************************************************/ + + + +#include +#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 00000000..54c567da Binary files /dev/null and b/16/xlib/DEMO4.EXE differ diff --git a/16/xlib/DEMO5.C b/16/xlib/DEMO5.C new file mode 100755 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;j + +#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 00000000..7e26f1f6 Binary files /dev/null and b/16/xlib/DEMO6.EXE differ diff --git a/16/xlib/DEMO7.C b/16/xlib/DEMO7.C new file mode 100755 index 00000000..e5cce457 --- /dev/null +++ b/16/xlib/DEMO7.C @@ -0,0 +1,38 @@ +/* Program to demonstrate Bezier curves */ + +#include + +#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 00000000..3762184b Binary files /dev/null and b/16/xlib/DEMO7.EXE differ diff --git a/16/xlib/DEMO8.C b/16/xlib/DEMO8.C new file mode 100755 index 00000000..5241eed3 --- /dev/null +++ b/16/xlib/DEMO8.C @@ -0,0 +1,154 @@ +/************************************************************************* + +DEMO 2 + +Demonstrates the speed difference between compiled bitmap, conventional +masked planar bitmap, and video bitmap blits. + +**************************************************************************/ + + + +#include +#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 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 00000000..6cd3b0d6 Binary files /dev/null and b/16/xlib/VAR6X8.FNT differ diff --git a/16/xlib/VARSWISB.FNT b/16/xlib/VARSWISB.FNT new file mode 100755 index 00000000..a4a357b9 Binary files /dev/null and b/16/xlib/VARSWISB.FNT differ diff --git a/16/xlib/VARSWISL.FNT b/16/xlib/VARSWISL.FNT new file mode 100755 index 00000000..d1b2e565 Binary files /dev/null and b/16/xlib/VARSWISL.FNT differ diff --git a/16/xlib/XBEZIER.ASM b/16/xlib/XBEZIER.ASM new file mode 100755 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/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/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/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 + diff --git a/16/xlib/makefile b/16/xlib/makefile new file mode 100755 index 00000000..7bc7d04d --- /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) + + +%.c.obj: + $(CC) -c $(CFLAGS) $< + +%.asm.obj: + wasm $(AFLAGS) $* \ + + +XLIBOBJS= xprintf.obj xpoint.obj xline.obj xmain.obj xpal.obj xpbitmap.obj \ + xrect.obj xtext.obj xcbitmap.obj xdetect.obj xbmtools.obj \ + xfileio.obj xrletool.obj xbezier.obj xpbmclip.obj xvbitmap.obj \ + xmakevbm.obj xmouse.obj xcircle.obj xclippbm.obj xcomppbm.obj \ + xpolygon.obj xvsync.obj xfill.obj xcbitm32.obj + + +all: demo1.exe demo2.exe demo3.exe demo4.exe demo5.exe demo6.exe demo7.exe \ + demo8.exe demo9.exe demo10.exe + +demo1.exe : demo1.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo1.obj xlib$(XLIB_VERSION)$(MODEL).lib + +demo2.exe : demo2.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo2.obj xlib$(XLIB_VERSION)$(MODEL).lib + +demo3.exe : demo3.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo3.obj xlib$(XLIB_VERSION)$(MODEL).lib + +demo4.exe : demo4.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo4.obj xlib$(XLIB_VERSION)$(MODEL).lib + +demo5.exe : demo5.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo5.obj xlib$(XLIB_VERSION)$(MODEL).lib + +demo6.exe : demo6.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo6.obj xlib$(XLIB_VERSION)$(MODEL).lib + +demo7.exe : demo7.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo7.obj xlib$(XLIB_VERSION)$(MODEL).lib + +demo8.exe : demo8.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo8.obj xlib$(XLIB_VERSION)$(MODEL).lib + +demo9.exe : demo9.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo9.obj xlib$(XLIB_VERSION)$(MODEL).lib + +demo10.exe : demo10.obj $(XLIBOBJS) xlib$(XLIB_VERSION)$(MODEL).lib + $(CC) $(CFLAGS) demo10.obj 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.obj : xprintf.c +xpoint.obj : xpoint.asm xpoint.inc xlib.inc model.inc +xline.obj : xline.asm xline.inc xlib.inc model.inc +xmain.obj : xmain.asm xmain.inc xlib.inc model.inc +xpal.obj : xpal.asm xpal.inc xlib.inc model.inc +xpbitmap.obj: xpbitmap.asm xpbitmap.inc xlib.inc model.inc +xpbmclip.obj: xpbmclip.asm xpbmclip.inc xlib.inc model.inc +xclippbm.obj: xclippbm.asm xclippbm.inc xlib.inc model.inc +xrect.obj : xpal.asm xpal.inc xlib.inc model.inc +xtext.obj : xtext.asm xtext.inc xlib.inc model.inc +xcbitmap.obj: xcbitmap.asm xcbitmap.inc xlib.inc model.inc +xcomppbm.obj: xcomppbm.asm xcomppbm.inc xlib.inc model.inc +xcbitm32.obj: xcbitm32.c +xdetect.obj : xdetect.asm xdetect.inc model.inc +xbmtools.obj: xbmtools.asm xbmtools.inc model.inc +xfileio.obj : xfileio.asm xfileio.inc model.inc +xrletool.obj: xrletool.asm xrletool.inc model.inc +xvbitmap.obj: xvbitmap.asm xvbitmap.inc xlib.inc model.inc +xmakevbm.obj: xmakevbm.c xvbitmap.h +xmouse.obj : xmouse.asm xlib.inc model.inc +xcircle.obj : xcircle.asm xcircle.inc xlib.inc model.inc +xpolygon.obj: xpolygon.asm xpolygon.inc xlib.inc model.inc +xvsync.obj : xvsync.asm xvsync.inc xlib.inc model.inc +xfill.obj : xfill.asm xfill.inc xlib.inc model.inc