www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1993/10/09/18:31:53

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 <stdio.h>
#include <assert.h>

#include <stdlib.h>
#include <memory.h>
#include <grx.h>
#include <mousex.h>

#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) grx.fg = grx.palette[i]; /* for now */
  else grx.fg = GrBlack();

  grx.lopt.lno_color = grx.fg;

  return (0);
};

/*
 * grx_mapcolor
 *
 *  change index i in the color map to the appropriate r, g, b, value.
 */
static int
grx_mapcolor(int c, int r, int g, int b)
{
    int j;

    if (c >= 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<sides; i++)
   {
      points[i][0] = x[i];
      points[i][1] = grx.height - y[i];
    }

  GrFilledPolygon( sides, points, grx.fg );

  return (0);
};

static int
grx_checkkey()
{
    char c;

    if (kbhit()) {
        if ((c = getkey()) == 3) {  /* control-c */
            grx_exit();
            /* don't call vexit(), avoid back-refs */
            exit(0);
        } else
            return c;
    } else  return 0;
}

static int
grx_locator(int *x, int *y)
{
  MouseEvent mEv;
  static ox = 0, oy = 0, obuttons = 0;

  if (!grx.has_mouse) 
    {
      *x = *y = 0;
      return (-1);
    }

  MouseGetEvent( M_MOTION | M_BUTTON_CHANGE | M_POLL, &mEv );

    if (mEv.flags & M_MOTION) {
      ox = mEv.x;
      oy = vdevice.sizeSy - mEv.y;
    }
    if (mEv.flags & M_BUTTON_CHANGE) {
        obuttons = ((mEv.buttons & M_LEFT) ? 1 : 0) |
            ((mEv.buttons & M_MIDDLE) ? 2 : 0) |
            ((mEv.buttons & M_RIGHT) ? 4 : 0);
    }
  *x = ox;
  *y = oy;

  return (obuttons);
}

static
int grx_lwidth( int w )
{
  grx.lopt.lno_width = w;
}

static DevEntry grxdev = {
    "grx",
    "@:pc8x8.fnt",
    "@:pc8x16.fnt",
    grx_backbuffer, /* backbuffer */
    grx_char, /* hardware char */
    grx_checkkey, /* keyhit */
    grx_vclear, /* clear viewport to current colour */
    grx_colour, /* set current colour */
    grx_draw, /* draw line */
    grx_exit, /* close graphics & exit */
    grx_fill, /* fill polygon */
    grx_font, /* set hardware font */
    grx_frontbuffer, /* front buffer */
    getkey, /* wait for and get key */
    grx_init, /* begin graphics */
    grx_locator, /* get mouse position */
    grx_mapcolor, /* map colour (set indices) */
    noop, /* set linestyle */
    grx_lwidth, /* set line width */
    grx_string, /* draw string of chars */
    grx_swapbuffers, /* swap buffers */
    grx_sync  /* sync display */
};

/*
 * _grx_devcpy
 *
 *  copy the pc device into vdevice.dev. (as listed in drivers.c)
 */
_grx_devcpy()
{
    vdevice.dev = grxdev;
    return(0);
}

/*
 * Gary Lawrence Murphy ----------------- garym AT virtual DOT rose DOT utoronto DOT ca
 * University of Toronto ---------- 4 Taddle Creek, Toronto, Ont M5S 1A4
 * Human Factors, Ind Engineering ------------ fax/voice: (416) 978-3776
 * ----------------------- The true destination is always just here, now
*/


- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019