Date: Sat, 9 Oct 1993 17:51:10 -0400 From: garym AT virtual DOT rose DOT utoronto DOT ca (Gary Lawrence Murphy) To: djgpp AT sun DOT soe DOT clarkson DOT edu Subject: GRX driver for VOGL (HELP!) Well, here's the first provisional copy of my LIBGRX driver for the VOGL 'GL' emulation. Fool that I am, I started in on implementing a back-buffer for VGA (other recommendations welcome), and then, double-a-fool, I sought to optimize it a little by putting the asm code in-line (adapted from XFER.S). The linked version worked, and a first inline version that called a C function also worked, but inline I get the errors: cd c:/vogl/drivers/ make -k gcc -I../src -O2 -M > depend Incorrect DOS version gcc -c -I../src -O2 grx.c grx.c:256:operands given don't match any known 386 instruction grx.c:270:operands given don't match any known 386 instruction make.exe: *** [grx.o] Error 1 make.exe: Target `all' not remade because of errors. These errors vanish if I comment out the first "asm volatile" section in the grx_swapbuffers function! What did I do wrong? Any and all suggestions, recommendations and obtuse musing are most welcome ;-) The good news is, it works. I can compile all of the VOGL examples and while slow, I get what I should get. I'm also open to caveats about implementing Events and any other speed-ups. Here's the code: If you want to hook this into a VOGL port, you will also need to update DRIVERS.C to include a GRX driver, then hack up the makefiles to avoid spilling over the max-line-length of MsDOS :-( --------------------------------cut here-------------------------------- /* * GRX driver for VOGL c1993 by Gary Murphy garym AT virtual DOT rose DOT utoronto DOT c * */ #include #include #include #include #include #include #define MSG( m ) fprintf(stderr, "\n%s: %d: %s", __FILE__, __LINE__, (m)) #define ERROR1( m, p ) fprintf(stderr, "\n%s: %d: " m, __FILE__, __LINE__, (p)) #include "vogl.h" #define MAXCOLOR 256 static struct { GR_graphics_modes old_mode; int width, height, planes; unsigned scrsize; /* size of buffer in long words */ GrContext *cbuf; /* current context */ GrContext *fbuf; GrContext *bbuf; int palette[8]; GrLineOption lopt; /* pen drawing options */ int fg; /* foreground/background colours */ int bg; int has_mouse; GrFont *font; GrFont *lfont; GrFont *sfont; /* GrTextOption *lfont; * GrTextOption *sfont; */ int cx; int cy; } grx; /* access functions: * /* I'm going to need this to fudge in stereo graphics ... */ GrContext *setBackBuffer( GrContext *newBB ) { GrContext *oldBB = grx.bbuf; assert( newBB != NULL); grx.bbuf = newBB; return oldBB; } static int grx_init() { grx.old_mode = GrCurrentMode(); GrSetMode(GR_default_graphics); #ifndef VOGLE vdevice.devname = "Grx"; #endif /* set the VOGL device */ vdevice.sizeX = GrSizeY(); /* square max, was GrScreenX(); */ vdevice.sizeY = GrSizeY(); grx.width = vdevice.sizeSx = GrScreenX(); grx.height = vdevice.sizeSy = GrScreenY(); grx.planes = vdevice.depth = GrNumPlanes(); grx.scrsize=( GrPlaneSize(grx.width, grx.height)* grx.planes)/sizeof(long); /* setup default palette */ GrSetRGBcolorMode(); grx.lopt.lno_color = grx.fg = GrWhite(); grx.bg = GrBlack(); grx.palette[BLACK] = GrAllocColor( 0, 0, 0 ); grx.palette[RED] = GrAllocColor( 255, 0, 0 ); grx.palette[GREEN] = GrAllocColor( 0, 255, 0 ); grx.palette[YELLOW] = GrAllocColor( 255, 255, 0 ); grx.palette[BLUE] = GrAllocColor( 0, 0, 255 ); grx.palette[MAGENTA] = GrAllocColor( 255, 0, 255 ); grx.palette[CYAN] = GrAllocColor( 0, 255, 255 ); grx.palette[WHITE] = GrAllocColor( 255, 255, 255 ); /* setup back/front buffers: * frontbuffer is the current screen, back is a ram context */ grx.cbuf = grx.fbuf = GrSaveContext( NULL ); grx.bbuf = NULL; /* initialize mouse */ if ((grx.has_mouse = MouseDetect())==TRUE) { /* can I do interrupts? stay polled for now ... */ MouseEventMode(0); MouseInit(); /* no keyboard (use getch) */ MouseEventEnable(0, 1); /* cheezy mouse speed algorithm */ if (grx.width * grx.height < 100000) MouseSetSpeed(6); else if (grx.width * grx.height < 200000) MouseSetSpeed(4); else if (grx.width * grx.height < 500000) MouseSetSpeed(3); else MouseSetSpeed(2); MouseWarp(1,1); MouseDisplayCursor(); }; /* initial drawing style to thin solid lines */ grx.lopt.lno_width = 1; grx.lopt.lno_pattlen = 0; grx.lopt.lno_dashpat = NULL; /* load initial fonts */ if(getenv("GRXFONT") == NULL) GrSetFontPath("fonts"); grx.font = grx.sfont = grx.lfont = NULL; vdevice.hwidth = 8.0; vdevice.hheight = 8.0; return (1); } /* * grx_frontbuffer, grx_backbuffer, grx_swapbuffers * */ static int grx_frontbuffer() { grx.cbuf = grx.fbuf; GrSetContext( grx.fbuf ); return (0); } static int grx_backbuffer() { /* if they want a backbuffer, we'd better make one ... */ if (grx.bbuf == NULL) grx.bbuf = GrCreateContext( GrSizeX(), GrSizeY(), NULL, NULL ); assert( grx.bbuf != NULL); grx.cbuf = grx.bbuf; GrSetContext( grx.bbuf ); return (0); } static int grx_swapbuffers() { if (grx.cbuf == grx.fbuf ) grx_backbuffer(); else { unsigned long *zptr = (unsigned long *) grx.bbuf->gc_baseaddr; /* there is no inherently portable VGA backbuffer. * the following copies by long words from back to front buffer * modify this for regions by triming the first x-limit and y-limit * and upping the pointers to the start of your subcontext */ unsigned long *sptr = (unsigned long *) grx.bbuf->gc_baseaddr; unsigned long *tptr = (unsigned long *) grx.fbuf->gc_baseaddr; unsigned lc = 0; asm volatile(" \n\ yloop: \n\ movl %1,%%ecx \n\ cmpl %%ecx,%6 \n\ jae alldone \n\ cld \n\ xloop: \n\ movl %4,%%esi \n\ movl %5,%%edi \n\ movl %0,%%ecx \n\ rep \n\ movsl \n\ xdone: \n\ movl %2,%%ecx \n\ addl %%ecx,%4 \n\ movl %3,%%ecx \n\ addl %%ecx,%5 \n\ incl %6 \n\ jmp yloop \n\ alldone: " \ : /*no output*/ \ : "g" (grx.width), "g" (grx.height), \ "g" (grx.bbuf->gc_lineoffset), \ "g" (grx.fbuf->gc_lineoffset), \ "g" (sptr), "g" (tptr), "g" (lc) \ : "si", "di", "cx" ); \ asm volatile(" \n\ movl %0,%%edi \n\ movl %1,%%ecx \n\ xorl %%eax,%%eax \n\ cld \n\ rep \n\ stosl "\ : /*no output*/ \ : "g" (zptr), "g" (grx.scrsize) \ : "di", "cx" ); \ } return (0); } #ifdef VOGLE /* * grx_vclear * * Clear the screen to current colour */ grx_vclear() { GrClearScreen(grx.fg); } #else /* * grx_vclear * * Clear the viewport to current colour */ static int grx_vclear() { unsigned int vw = vdevice.maxVx - vdevice.minVx; unsigned int vh = vdevice.maxVy - vdevice.minVy; if ((vdevice.sizeSx == vw) && (vdevice.sizeSy == vh)) GrClearScreen(grx.fg); /* full screen */ else GrFilledBox( vdevice.minVx, vdevice.sizeSy - vdevice.maxVy, grx.width, grx.height, grx.fg); return (1); } #endif /* * grx_exit * * Sets the display back to text mode. */ static grx_exit() { MouseUnInit(); /* disable mouse/keyboard interrupts */ GrSetMode( grx.old_mode ); GrDestroyContext( grx.bbuf ); return (1); } static int grx_sync () {}; static int noop() { return (-1); } /* * grx_font : load either of the fonts */ static int grx_font(char *name) { GrUnloadFont( grx.font ); grx.font = GrLoadFont( name ); vdevice.hheight = 16; vdevice.hwidth = 8; return (1); } static int grx_char( int c ) { static char s[2] = "\0\0"; s[0] = c; GrTextXY(vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy + 16, s, grx.fg, 0); return (1); }; static int grx_string(char *s) { GrTextXY(vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy + 16, s, grx.fg, 0); return (1); } static int grx_draw( int x, int y ) { GrCustomLine(vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy, x, vdevice.sizeSy - y, &grx.lopt ); vdevice.cpVx = x; vdevice.cpVy = y; return(0); }; static int grx_colour(int i) { if (i= MAXCOLOR || vdevice.depth == 1) return(-1); grx.palette[c] = GrAllocColor(r, g, b); } static int grx_fill( int sides, int *x, int *y ) { int i,j; int points[sides][2]; for (i=0; i