// This is trigon.cc CVS version: $Id: trigon.cc,v 1.3 2000/02/28 21:11:42 andreaha Exp $
#include "eng.h"

/************************************************************************/
/* World::Trigon                                                        */
/************************************************************************/

/* trigon printout */
void World::Trigon::printOut() {
  dpush1("World::Trigon::printOut()");
  
  print2("Trigon [%#010x] printout:\n", (int)this);
  print2("  Filltype: %s\n", myworld->util.fillstr(filltype));
  print2("  Visible : %s\n", visible ? myworld->util.charptr("Yes") : myworld->util.charptr("No"));
  print2("  Twosided: %s\n", twosided ? myworld->util.charptr("Yes") : myworld->util.charptr("No"));
  print2("  Material: %s\n", txt ? txt->name : myworld->util.charptr("No"));
  print2("  Shademap: %s\n", shademap ? shademap->name : myworld->util.charptr("No"));

  dpop();
}

/* set draw function */
void World::Trigon::setDraw(int i) {

  dpush2("World::Trigon::setDraw(%i)", i);

  switch (i) {
  case TEXTURE:
    draw = &fillTexture;
    noclip = &fillTextureNoClip;
    break;
  case TEXTURE|MIP:
    draw = &fillTextureMip;
    noclip = &fillTextureMipNoClip;
    break;
  case TEXTURE|GOURAUD:
    draw = &fillGTexture;
    noclip = &fillGTextureNoClip;
    break;
  case TEXTURE|GOURAUD|MIP:
    draw = &fillGTextureMip;
    noclip = &fillGTextureMipNoClip;
    break;
  case TEXTURE|GOURAUD|TRANSPARENT:
    draw = &fillGTextureTrans;
    noclip = &fillGTextureTransNoClip;
    break;
  case PHONG:   
    draw = &fillPhong;
    noclip = &fillPhongNoClip;
    break; 
  case PLAIN:   
    draw = &fillPlain; 
    noclip = &fillPlainNoClip;
    break; 
  case GOURAUD: 
    draw = &fillGouraud;
    noclip = &fillGouraudNoClip;
    break;
  case GOURAUD|TRANSPARENT: 
    draw = &fillGouraudTransparent;
    noclip = &fillGouraudTransparentNoClip;
    break;
  default:    
    debug("Illegal filltype, using TEXTURE.");
    draw = &fillTexture;
    noclip = &fillTextureNoClip;
    break;
  }

  dpop();
}

/* draw function */
void World::Trigon::drawIt(int *dst) {

  dpush2("World::Trigon::drawIt(%#010x)",(int)dst);

  switch (clipped) {
  case TRUE: 
    (this->*draw)(dst);
    break;
  case FALSE:
    (this->*noclip)(dst);
    break;
  }

  dpop();
}

/* scan one left, texture, no perspective */
void World::Trigon::texScanLeft(World::Vertex *v1, World::Vertex *v2) {

  dpush3("World::Trigon::texScanLeft(%#010x, %#010x)",(int)v1,(int)v2);

  Yvalc  *yvalptr;
  float  divheight;
  float  prestep;
  float  xslope,  uslope,  vslope;
  int    ixslope, iuslope, ivslope;
  int    i, x, skip;
  int    u, v;

  int y1, y2;

  y1 = v1->cyr;
  y2 = v2->cyr;

  if (y1 == y2) { dpop(); return; }

  prestep   = y1 - v1->posr->y;
  divheight = (float )1.0 / (v2->posr->y - v1->posr->y);

  xslope = (v2->posr->x - v1->posr->x) * divheight;
  uslope = (v2->u  - v1->u) * divheight;
  vslope = (v2->v  - v1->v) * divheight;

  ixslope= float2fixed(xslope);
  iuslope= float2fixed(uslope);
  ivslope= float2fixed(vslope);

  x = float2fixed(v1->posr->x + (xslope * prestep)) + (1<<15);
  u = float2fixed(v1->u  + (uslope * prestep)) + (1<<15);
  v = float2fixed(v1->v  + (vslope * prestep)) + (1<<15);

  if (y1 > myworld->maxy) { dpop(); return; }
  if (y2 < 0) { dpop(); return; }
  if (y1 < 0) {
    skip = (0 - y1);
    x   += (ixslope * skip);
    u   += (iuslope * skip);
    v   += (ivslope * skip);
    y1   = 0;
  }

  if (y2 > myworld->maxy) y2 = myworld->maxy;

  yvalptr = &(myworld->yval[y1]);

  for (i = y1; i < y2; i++) {
    yvalptr->xl = x >> 16;
    yvalptr->u  = u;
    yvalptr->v  = v;
    x += ixslope;
    u += iuslope;
    v += ivslope;
    yvalptr++;
  }

  dpop();
}

/* scan one left, gouraud + texture, no perspective */
void World::Trigon::gTexScanLeft(World::Vertex *v1, World::Vertex *v2) {

  dpush3("World::Trigon::gTexScanLeft(%#010x, %#010x)",(int)v1,(int)v2);

  Yvalc  *yvalptr;
  float  divheight;
  float  prestep;
  float  xslope,  uslope,  vslope, rslope, gslope, bslope;
  int    ixslope, iuslope, ivslope, irslope, igslope, ibslope;
  int    i, x, skip;
  int    u, v, r, g, b;

  int y1, y2;

  y1 = v1->cyr;
  y2 = v2->cyr;

  if (y1 == y2) { dpop(); return; }

  prestep   = y1 - v1->posr->y;
  divheight = (float )1.0 / (v2->posr->y - v1->posr->y);

  xslope = (v2->posr->x - v1->posr->x) * divheight;
  uslope = (v2->u  - v1->u) * divheight;
  vslope = (v2->v  - v1->v) * divheight;
  rslope = (v2->gouraud.r  - v1->gouraud.r) * divheight;
  gslope = (v2->gouraud.g  - v1->gouraud.g) * divheight;
  bslope = (v2->gouraud.b  - v1->gouraud.b) * divheight;

  ixslope= float2fixed(xslope);
  iuslope= float2fixed(uslope);
  ivslope= float2fixed(vslope);
  irslope= float2fixed(rslope);
  igslope= float2fixed(gslope);
  ibslope= float2fixed(bslope);

  x = float2fixed(v1->posr->x + (xslope * prestep)) + (1<<15);
  u = float2fixed(v1->u  + (uslope * prestep)) + (1<<15);
  v = float2fixed(v1->v  + (vslope * prestep)) + (1<<15);
  r = float2fixed(v1->gouraud.r  + (rslope * prestep)) + (1<<15);
  g = float2fixed(v1->gouraud.g  + (gslope * prestep)) + (1<<15);
  b = float2fixed(v1->gouraud.b  + (bslope * prestep)) + (1<<15);

  if (y1 > myworld->maxy) { dpop(); return; }
  if (y2 < 0) { dpop(); return; }
  if (y1 < 0) {
    skip = (0 - y1);
    x   += (ixslope * skip);
    u   += (iuslope * skip);
    v   += (ivslope * skip);
    r   += (irslope * skip);
    g   += (igslope * skip);
    b   += (ibslope * skip);
    y1   = 0;
  }

  if (y2 > myworld->maxy) y2 = myworld->maxy;

  yvalptr = &(myworld->yval[y1]);

  for (i = y1; i < y2; i++) {
    yvalptr->xl = x >> 16;
    yvalptr->u  = u;
    yvalptr->v  = v;
    yvalptr->r  = r;
    yvalptr->g  = g;
    yvalptr->b  = b;
    x += ixslope;
    u += iuslope;
    v += ivslope;
    r += irslope;
    g += igslope;
    b += ibslope;
    yvalptr++;
  }

  dpop();
}


/* scan one left, plain */
void World::Trigon::plainScanLeft(World::Vertex *v1, World::Vertex *v2) {

  dpush3("World::Trigon::plainScanLeft(%#010x, %#010x)",(int)v1,(int)v2);

  Yvalc  *yvalptr;
  float  divheight;
  float  prestep;
  float  xslope;
  int    ixslope;
  int    i, x, skip;

  int y1, y2;

  y1 = v1->cyr;
  y2 = v2->cyr;

  if (y1 == y2) { dpop(); return; }

  prestep   = y1 - v1->posr->y;
  divheight = (float )1.0 / (v2->posr->y - v1->posr->y);

  xslope = (v2->posr->x - v1->posr->x) * divheight;

  ixslope= float2fixed(xslope);

  x = float2fixed(v1->posr->x + (xslope * prestep)) + (1<<15);

  if (y1 > myworld->maxy) { dpop(); return; }
  if (y2 < 0) { dpop(); return; }
  if (y1 < 0) {
    skip = (0 - y1);
    x   += (ixslope * skip);
    y1   = 0;
  }

  if (y2 > myworld->maxy) y2 = myworld->maxy;

  yvalptr = &(myworld->yval[y1]);

  for (i = y1; i < y2; i++) {
    yvalptr->xl = x >> 16;
    x += ixslope;
    yvalptr++;
  }

  dpop();
}

/* scan one left, gouraud */
void World::Trigon::gouraudScanLeft(World::Vertex *v1, World::Vertex *v2) {

  dpush3("World::Trigon::gouraudScanLeft(%#010x, %#010x)",(int)v1,(int)v2);

  Yvalc  *yvalptr;
  float  divheight;
  float  prestep;
  float  xslope,  rslope, gslope, bslope;
  int    ixslope, irslope, igslope, ibslope;
  int    i, x, skip;
  int    r, g, b;
  int y1, y2;

  y1 = v1->cyr;
  y2 = v2->cyr;

  if (y1 == y2) { dpop(); return; }

  prestep   = y1 - v1->posr->y;
  divheight = (float )1.0 / (v2->posr->y - v1->posr->y);

  xslope = (v2->posr->x - v1->posr->x) * divheight;
  rslope = (v2->gouraud.r - v1->gouraud.r) * divheight;
  gslope = (v2->gouraud.g - v1->gouraud.g) * divheight;
  bslope = (v2->gouraud.b - v1->gouraud.b) * divheight;

  ixslope= float2fixed(xslope);
  irslope= float2fixed(rslope);
  igslope= float2fixed(gslope);
  ibslope= float2fixed(bslope);

  x = float2fixed(v1->posr->x + (xslope * prestep)) + (1<<15);
  r = float2fixed(v1->gouraud.r + (rslope * prestep)) + (1<<15);
  g = float2fixed(v1->gouraud.g + (gslope * prestep)) + (1<<15);
  b = float2fixed(v1->gouraud.b + (bslope * prestep)) + (1<<15);

  if (y1 > myworld->maxy) { dpop(); return; }
  if (y2 < 0) { dpop(); return; }
  if (y1 < 0) {
    skip = (0 - y1);
    x   += (ixslope * skip);
    r   += (irslope * skip);
    g   += (igslope * skip);
    b   += (ibslope * skip);
    y1   = 0;
  }

  if (y2 > myworld->maxy) y2 = myworld->maxy;

  yvalptr = &(myworld->yval[y1]);

  for (i = y1; i < y2; i++) {
    yvalptr->xl = x >> 16;
    yvalptr->r  = r;                             // gour
    yvalptr->g  = g;                             // gour
    yvalptr->b  = b;                             // gour
    x += ixslope;
    r += irslope;
    g += igslope;
    b += ibslope;
    yvalptr++;
  }

  dpop();
}

/* scan one right */
void World::Trigon::scanRight(Vertex *v1, Vertex *v2) {

  dpush3("World::Trigon::scanRight(%#010x, %#010x)",(int)v1,(int)v2);

  Yvalc *yvalptr;
  float deltax, deltay;
  float xslope;
  float prestep;
  int   ixslope;
  int   i,x,skip;

  int y1, y2;

  y1 = v1->cyr;
  y2 = v2->cyr;

  if (y1 == y2) { dpop(); return; }

  deltax = v2->posr->x - v1->posr->x;
  deltay = v2->posr->y - v1->posr->y;
  xslope = deltax / deltay;
  ixslope= float2fixed(xslope);

  prestep = y1 - v1->posr->y;
  x = float2fixed(v1->posr->x + (xslope * prestep)) + (1<<15);

  if (y1 > myworld->maxy) { dpop(); return; }
  if (y2 < 0) { dpop(); return; }
 
  if (y1 < 0) {
    skip = (0 - y1);
    x   += (ixslope * skip);
    y1   = 0;
  }

  if (y2 > myworld->maxy) y2 = myworld->maxy;
  if (y1 < _y1) _y1 = y1;
  if (y2 > _y2) _y2 = y2;

  yvalptr = &(myworld->yval[y1]);

  for (i = y1; i < y2; i++) {
    yvalptr->xr = x >> 16;
    x += ixslope;
    yvalptr++;
  }

  dpop();
}

/* fill trigon using texture algorithm, no perspective correction */
void World::Trigon::fillTexture(int *dst) {
  
  dpush2("World::Trigon::fillTexture(%#010x)", (int )dst);

  Vertex *vct[3];                               // vertices
  int    pa,pb,pc;
  int    i, y;                                  // y temp value
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  float  uadd,vadd;
  int    iuadd, ivadd;
  int    xl, xr;
  int    u, v;
  int    length;
  int    skip;
  int    *iptr;
  int    *t = (int *)txt->txt;
  Yvalc  *yvalp;

  vct[0] = cp;                                       /* simplify offset calc */
  vct[1] = bp;
  vct[2] = ap;

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1;        /* sort a as highest node */
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;                    /* b,c clockwize */
  pc = pa - 1; if (pc < 0) pc = 2;

  /*|  a  |   a  | a b | c a |     |*/
  /*|   b |  c   |  c  |  b  |  a  |*/
  /*| c   |    b |     |     | c b |*/
  /*
  ap->u = ua; ap->v = va;
  bp->u = ub; bp->v = vb;
  cp->u = uc; cp->v = vc;
  */
  _y1 =  9999;
  _y2 = -9999;
  texScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y)
    scanRight(vct[pb],vct[pc]);
  else
    texScanLeft(vct[pc],vct[pb]); 

  if (_y1 == _y2) { dpop(); return; }                        // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;

  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  uadd = ( (vct[1]->u - vct[0]->u) * deltay2
          -(vct[2]->u - vct[0]->u) * deltay1 ) * divdelta;
  vadd = ( (vct[1]->v - vct[0]->v) * deltay2
          -(vct[2]->v - vct[0]->v) * deltay1 ) * divdelta;

  iuadd = float2fixed(uadd);
  ivadd = float2fixed(vadd);

  yvalp = &(myworld->yval[_y1]);

  for (y = _y1; y < _y2; y++) {
    xl = yvalp->xl;
    xr = yvalp->xr;
    u  = yvalp->u;
    v  = yvalp->v;
    yvalp++;

    if ((xr >= 0) && (xl < myworld->rendx)) {
      if (xr > (myworld->maxx)) xr = myworld->maxx;
      if (xl < 0) {
        skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        xl   = 0;
      }
      length = xr - xl;
      if (length > 0) {
        iptr = dst + xl + myworld->precy[y];

        for (i = 0; i < length; i++) {
          *iptr++ = t[((v>>8)&0xff00) + ((u>>16)&0xff)];
          u += iuadd;
          v += ivadd;
        }
      }
    }
  }

  dpop();
}
void World::Trigon::fillTextureNoClip(int *dst) {
  
  dpush2("World::Trigon::fillTexture(%#010x)", (int )dst);

  Vertex *vct[3];                               // vertices
  int    pa,pb,pc;
  int    i, y;                                  // y temp value
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  float  uadd,vadd;
  int    iuadd, ivadd;
  int    xl, xr;
  int    u, v;
  int    length;
  int    *iptr;
  int    *t = (int *)txt->txt;
  Yvalc  *yvalp;

  vct[0] = cp;                                       /* simplify offset calc */
  vct[1] = bp;
  vct[2] = ap;

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1;        /* sort a as highest node */
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;                    /* b,c clockwize */
  pc = pa - 1; if (pc < 0) pc = 2;

  /*|  a  |   a  | a b | c a |     |*/
  /*|   b |  c   |  c  |  b  |  a  |*/
  /*| c   |    b |     |     | c b |*/
  /*
  ap->u = ua; ap->v = va;
  bp->u = ub; bp->v = vb;
  cp->u = uc; cp->v = vc;
  */
  _y1 =  9999;
  _y2 = -9999;
  texScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y)
    scanRight(vct[pb],vct[pc]);
  else
    texScanLeft(vct[pc],vct[pb]); 

  if (_y1 == _y2) { dpop(); return; }                        // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;


  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  uadd = ( (vct[1]->u - vct[0]->u) * deltay2
          -(vct[2]->u - vct[0]->u) * deltay1 ) * divdelta;
  vadd = ( (vct[1]->v - vct[0]->v) * deltay2
          -(vct[2]->v - vct[0]->v) * deltay1 ) * divdelta;

  iuadd = float2fixed(uadd);
  ivadd = float2fixed(vadd);

  yvalp = &(myworld->yval[_y1]);


  for (y = _y1; y < _y2; y++) {
    xl = yvalp->xl;
    xr = yvalp->xr;
    u  = yvalp->u;
    v  = yvalp->v;
    yvalp++;

    length = xr - xl;
    if (length > 0) {
      iptr = dst + xl + myworld->precy[y];

      for (i = 0; i < length; i++) {
	*iptr++ = t[((v>>8)&0xff00) + ((u>>16)&0xff)];
	u += iuadd;
	v += ivadd;
      }
    }
  }
  
  dpop();
}

/* fill trigon using texture algorithm, no perspective correction */
void World::Trigon::fillTextureMip(int *dst) {
  
  dpush2("World::Trigon::fillTextureMip(%#010x)", (int )dst);

  Vertex *vct[3];                               // vertices
  int    pa,pb,pc;
  int    i, y;                                  // y temp value
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  float  uadd,vadd;
  int    iuadd, ivadd;
  int    xl, xr;
  int    u, v;
  int    length;
  int    skip;
  int    *iptr;
  int    maxadd;
  int    *t;
  Yvalc  *yvalp;

  vct[0] = cp;                                       /* simplify offset calc */
  vct[1] = bp;
  vct[2] = ap;

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1;        /* sort a as highest node */
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;                    /* b,c clockwize */
  pc = pa - 1; if (pc < 0) pc = 2;

  /*|  a  |   a  | a b | c a |     |*/
  /*|   b |  c   |  c  |  b  |  a  |*/
  /*| c   |    b |     |     | c b |*/
  /*
  ap->u = ua; ap->v = va;
  bp->u = ub; bp->v = vb;
  cp->u = uc; cp->v = vc;
  */
  _y1 =  9999;
  _y2 = -9999;
  texScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y)
    scanRight(vct[pb],vct[pc]);
  else
    texScanLeft(vct[pc],vct[pb]); 

  if (_y1 == _y2) { dpop(); return; }                        // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;

  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  uadd = ( (vct[1]->u - vct[0]->u) * deltay2
          -(vct[2]->u - vct[0]->u) * deltay1 ) * divdelta;
  vadd = ( (vct[1]->v - vct[0]->v) * deltay2
          -(vct[2]->v - vct[0]->v) * deltay1 ) * divdelta;

  iuadd = float2fixed(uadd);
  ivadd = float2fixed(vadd);

  yvalp = &(myworld->yval[_y1]);

  if (fabs(uadd) > fabs(vadd))
    maxadd = CEIL(fabs(uadd));
  else
    maxadd = CEIL(fabs(vadd));

  if (!(maxadd >> 1)) {

    t = txt->txt;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      if ((xr >= 0) && (xl < myworld->rendx)) {
	if (xr > (myworld->maxx)) xr = myworld->maxx;
	if (xl < 0) {
	  skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        xl   = 0;
	}
	length = xr - xl;
	if (length > 0) {
	  iptr = dst + xl + myworld->precy[y];
	  
	  for (i = 0; i < length; i++) {
	    *iptr++ = t[((v>>8)&0xff00) + ((u>>16)&0xff)];
	    u += iuadd;
	    v += ivadd;
	  }
	}
      }
    }
  } else 
  if (!(maxadd >> 2)) {

    t = txt->txtm1;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      if ((xr >= 0) && (xl < myworld->rendx)) {
	if (xr > (myworld->maxx)) xr = myworld->maxx;
	if (xl < 0) {
	  skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        xl   = 0;
	}
	length = xr - xl;
	if (length > 0) {
	  iptr = dst + xl + myworld->precy[y];
	  
	  for (i = 0; i < length; i++) {
	    *iptr++ = t[((v>>10)&0x3f80) + ((u>>17)&0x007f)];
	    u += iuadd;
	    v += ivadd;
	  }
	}
      }
    }
  } else
  if (!(maxadd >> 3)) {

    t = txt->txtm2;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      if ((xr >= 0) && (xl < myworld->rendx)) {
	if (xr > (myworld->maxx)) xr = myworld->maxx;
	if (xl < 0) {
	  skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        xl   = 0;
	}
	length = xr - xl;
	if (length > 0) {
	  iptr = dst + xl + myworld->precy[y];
	  
	  for (i = 0; i < length; i++) {
	    *iptr++ = t[((v>>12)&0x0fc0) + ((u>>18)&0x3f)];
	    u += iuadd;
	    v += ivadd;
	  }
	}
      }
    }
  } else
  if (!(maxadd >> 4)) {

    t = txt->txtm3;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      if ((xr >= 0) && (xl < myworld->rendx)) {
	if (xr > (myworld->maxx)) xr = myworld->maxx;
	if (xl < 0) {
	  skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        xl   = 0;
	}
	length = xr - xl;
	if (length > 0) {
	  iptr = dst + xl + myworld->precy[y];
	  
	  for (i = 0; i < length; i++) {
	    *iptr++ = t[((v>>14)&0x3e0) + ((u>>19)&0x1f)];
	    u += iuadd;
	    v += ivadd;
	  }
	}
      }
    }
  } else 
  if (!(maxadd >> 5)) {

    t = txt->txtm4;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      if ((xr >= 0) && (xl < myworld->rendx)) {
	if (xr > (myworld->maxx)) xr = myworld->maxx;
	if (xl < 0) {
	  skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        xl   = 0;
	}
	length = xr - xl;
	if (length > 0) {
	  iptr = dst + xl + myworld->precy[y];
	  
	  for (i = 0; i < length; i++) {
	    *iptr++ = t[((v>>16)&0xf0) + ((u>>20)&0xf)];
	    u += iuadd;
	    v += ivadd;
	  }
	}
      }
    }
  } else
  if (!(maxadd >> 6)) {
    
    t = txt->txtm5;
    
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      if ((xr >= 0) && (xl < myworld->rendx)) {
	if (xr > (myworld->maxx)) xr = myworld->maxx;
	if (xl < 0) {
	  skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        xl   = 0;
	}
	length = xr - xl;
	if (length > 0) {
	  iptr = dst + xl + myworld->precy[y];
	  
	  for (i = 0; i < length; i++) {
	    *iptr++ = t[((v>>20)&0xc) + ((u>>22)&0x3)];
	    u += iuadd;
	    v += ivadd;
	  }
	}
      }
    }
  } else {
    //    if (!(maxadd >> 7))
    t = txt->txtm6;
    
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      if ((xr >= 0) && (xl < myworld->rendx)) {
	if (xr > (myworld->maxx)) xr = myworld->maxx;
	if (xl < 0) {
	  skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        xl   = 0;
	}
	length = xr - xl;
	if (length > 0) {
	  iptr = dst + xl + myworld->precy[y];
	  
	  for (i = 0; i < length; i++) {
	    *iptr++ = t[((v>>22)&0x2) + ((u>>23)&0x1)];
	    u += iuadd;
	    v += ivadd;
	  }
	}
      }
    }
  }

  dpop();
}
/* fill trigon using texture algorithm, no perspective correction */
void World::Trigon::fillTextureMipNoClip(int *dst) {
  
  dpush2("World::Trigon::fillTextureMipNoClip(%#010x)", (int )dst);

  Vertex *vct[3];                               // vertices
  int    pa,pb,pc;
  int    i, y;                                  // y temp value
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  float  uadd,vadd;
  int    iuadd, ivadd;
  int    xl, xr;
  int    u, v;
  int    length;
  int    *iptr;
  int    maxadd;
  int    *t;
  Yvalc  *yvalp;

  vct[0] = cp;                                       /* simplify offset calc */
  vct[1] = bp;
  vct[2] = ap;

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1;        /* sort a as highest node */
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;                    /* b,c clockwize */
  pc = pa - 1; if (pc < 0) pc = 2;

  /*|  a  |   a  | a b | c a |     |*/
  /*|   b |  c   |  c  |  b  |  a  |*/
  /*| c   |    b |     |     | c b |*/
  /*
  ap->u = ua; ap->v = va;
  bp->u = ub; bp->v = vb;
  cp->u = uc; cp->v = vc;
  */
  _y1 =  9999;
  _y2 = -9999;
  texScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y)
    scanRight(vct[pb],vct[pc]);
  else
    texScanLeft(vct[pc],vct[pb]); 

  if (_y1 == _y2) { dpop(); return; }                        // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;

  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  uadd = ( (vct[1]->u - vct[0]->u) * deltay2
          -(vct[2]->u - vct[0]->u) * deltay1 ) * divdelta;
  vadd = ( (vct[1]->v - vct[0]->v) * deltay2
          -(vct[2]->v - vct[0]->v) * deltay1 ) * divdelta;

  iuadd = float2fixed(uadd);
  ivadd = float2fixed(vadd);

  yvalp = &(myworld->yval[_y1]);

  if (fabs(uadd) > fabs(vadd))
    maxadd = CEIL(fabs(uadd));
  else
    maxadd = CEIL(fabs(vadd));

  if (!(maxadd >> 1)) {
    t = txt->txt;
    
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      length = xr - xl;
      if (length > 0) {
	iptr = dst + xl + myworld->precy[y];
	
	for (i = 0; i < length; i++) {
	  *iptr++ = t[((v>>8)&0xff00) + ((u>>16)&0xff)];
	  u += iuadd;
	  v += ivadd;
	}
      }
    }
  } else 
  if (!(maxadd >> 2)) {
    t = txt->txtm1;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      length = xr - xl;
      if (length > 0) {
	iptr = dst + xl + myworld->precy[y];
	  
	for (i = 0; i < length; i++) {
	  *iptr++ = t[((v>>10)&0x3F80) + ((u>>17)&0x007f)];
	  u += iuadd;
	  v += ivadd;
	}
      }
    }
  } else
  if (!(maxadd >> 3)) {
    t = txt->txtm2;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      length = xr - xl;
      if (length > 0) {
	iptr = dst + xl + myworld->precy[y];
	  
	for (i = 0; i < length; i++) {
	  *iptr++ = t[((v>>12)&0x0fc0) + ((u>>18)&0x3f)];
	  u += iuadd;
	  v += ivadd;
	}
      }
    }
  } else
  if (!(maxadd >> 4)) {
    t = txt->txtm3;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      length = xr - xl;
      if (length > 0) {
	iptr = dst + xl + myworld->precy[y];
	
	for (i = 0; i < length; i++) {
	  *iptr++ = t[((v>>14)&0x3e0) + ((u>>19)&0x1f)];
	  u += iuadd;
	  v += ivadd;
	}
      }
    }
  } else 
  if (!(maxadd >> 5)) {
    t = txt->txtm4;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      length = xr - xl;
      if (length > 0) {
	iptr = dst + xl + myworld->precy[y];
	  
	for (i = 0; i < length; i++) {
	  *iptr++ = t[((v>>16)&0xf0) + ((u>>20)&0xf)];
	  u += iuadd;
	  v += ivadd;
	}
      }
    }
  } else
  if (!(maxadd >> 6)) {

    t = txt->txtm5;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      length = xr - xl;
      if (length > 0) {
	iptr = dst + xl + myworld->precy[y];
	  
	for (i = 0; i < length; i++) {
	  *iptr++ = t[((v>>20)&0xc) + ((u>>22)&0x3)];
	  u += iuadd;
	  v += ivadd;
	}
      }
    }
  } else
//  if (!(maxadd >> 7))
  {
    t = txt->txtm6;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      length = xr - xl;
      if (length > 0) {
	iptr = dst + xl + myworld->precy[y];
	
	for (i = 0; i < length; i++) {
	  *iptr++ = t[((v>>22)&0x2) + ((u>>23)&0x1)];
	  u += iuadd;
	  v += ivadd;
	}
      }
    }
  }
  dpop();
}


/* fill trigon using texture algorithm, no perspective correction */
void World::Trigon::fillGTextureMip(int *dst) {
  
  dpush2("World::Trigon::fillTextureMip(%#010x)", (int )dst);

  Vertex *vct[3];                               // vertices
  int    pa,pb,pc;
  int    i, y;                                  // y temp value
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  float  uadd,vadd;
  int    iuadd, ivadd;
  int    xl, xr;
  int    u, v;
  int    length;
  int    skip;
  int    *iptr;
  int    maxadd;
  int    *t;
  Yvalc  *yvalp;

  vct[0] = cp;                                       /* simplify offset calc */
  vct[1] = bp;
  vct[2] = ap;

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1;        /* sort a as highest node */
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;                    /* b,c clockwize */
  pc = pa - 1; if (pc < 0) pc = 2;

  /*|  a  |   a  | a b | c a |     |*/
  /*|   b |  c   |  c  |  b  |  a  |*/
  /*| c   |    b |     |     | c b |*/
  /*
  ap->u = ua; ap->v = va;
  bp->u = ub; bp->v = vb;
  cp->u = uc; cp->v = vc;
  */
  _y1 =  9999;
  _y2 = -9999;
  texScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y)
    scanRight(vct[pb],vct[pc]);
  else
    texScanLeft(vct[pc],vct[pb]); 

  if (_y1 == _y2) { dpop(); return; }                        // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;

  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  uadd = ( (vct[1]->u - vct[0]->u) * deltay2
          -(vct[2]->u - vct[0]->u) * deltay1 ) * divdelta;
  vadd = ( (vct[1]->v - vct[0]->v) * deltay2
          -(vct[2]->v - vct[0]->v) * deltay1 ) * divdelta;

  iuadd = float2fixed(uadd);
  ivadd = float2fixed(vadd);

  yvalp = &(myworld->yval[_y1]);

  if (fabs(uadd) > fabs(vadd))
    maxadd = CEIL(fabs(uadd));
  else
    maxadd = CEIL(fabs(vadd));

  if (!(maxadd >> 1)) {

    t = txt->txt;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      if ((xr >= 0) && (xl < myworld->rendx)) {
	if (xr > (myworld->maxx)) xr = myworld->maxx;
	if (xl < 0) {
	  skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        xl   = 0;
	}
	length = xr - xl;
	if (length > 0) {
	  iptr = dst + xl + myworld->precy[y];
	  
	  for (i = 0; i < length; i++) {
	    *iptr++ = t[((v>>8)&0xff00) + ((u>>16)&0xff)];
	    u += iuadd;
	    v += ivadd;
	  }
	}
      }
    }
  } else 
  if (!(maxadd >> 2)) {

    t = txt->txtm1;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      if ((xr >= 0) && (xl < myworld->rendx)) {
	if (xr > (myworld->maxx)) xr = myworld->maxx;
	if (xl < 0) {
	  skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        xl   = 0;
	}
	length = xr - xl;
	if (length > 0) {
	  iptr = dst + xl + myworld->precy[y];
	  
	  for (i = 0; i < length; i++) {
	    *iptr++ = t[((v>>10)&0x3f80) + ((u>>17)&0x007f)];
	    u += iuadd;
	    v += ivadd;
	  }
	}
      }
    }
  } else
  if (!(maxadd >> 3)) {

    t = txt->txtm2;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      if ((xr >= 0) && (xl < myworld->rendx)) {
	if (xr > (myworld->maxx)) xr = myworld->maxx;
	if (xl < 0) {
	  skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        xl   = 0;
	}
	length = xr - xl;
	if (length > 0) {
	  iptr = dst + xl + myworld->precy[y];
	  
	  for (i = 0; i < length; i++) {
	    *iptr++ = t[((v>>12)&0x0fc0) + ((u>>18)&0x3f)];
	    u += iuadd;
	    v += ivadd;
	  }
	}
      }
    }
  } else
  if (!(maxadd >> 4)) {

    t = txt->txtm3;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      if ((xr >= 0) && (xl < myworld->rendx)) {
	if (xr > (myworld->maxx)) xr = myworld->maxx;
	if (xl < 0) {
	  skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        xl   = 0;
	}
	length = xr - xl;
	if (length > 0) {
	  iptr = dst + xl + myworld->precy[y];
	  
	  for (i = 0; i < length; i++) {
	    *iptr++ = t[((v>>14)&0x3e0) + ((u>>19)&0x1f)];
	    u += iuadd;
	    v += ivadd;
	  }
	}
      }
    }
  } else 
  if (!(maxadd >> 5)) {

    t = txt->txtm4;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      if ((xr >= 0) && (xl < myworld->rendx)) {
	if (xr > (myworld->maxx)) xr = myworld->maxx;
	if (xl < 0) {
	  skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        xl   = 0;
	}
	length = xr - xl;
	if (length > 0) {
	  iptr = dst + xl + myworld->precy[y];
	  
	  for (i = 0; i < length; i++) {
	    *iptr++ = t[((v>>16)&0xf0) + ((u>>20)&0xf)];
	    u += iuadd;
	    v += ivadd;
	  }
	}
      }
    }
  } else
  if (!(maxadd >> 6)) {
    
    t = txt->txtm5;
    
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      if ((xr >= 0) && (xl < myworld->rendx)) {
	if (xr > (myworld->maxx)) xr = myworld->maxx;
	if (xl < 0) {
	  skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        xl   = 0;
	}
	length = xr - xl;
	if (length > 0) {
	  iptr = dst + xl + myworld->precy[y];
	  
	  for (i = 0; i < length; i++) {
	    *iptr++ = t[((v>>20)&0xc) + ((u>>22)&0x3)];
	    u += iuadd;
	    v += ivadd;
	  }
	}
      }
    }
  } else {
    //    if (!(maxadd >> 7))
    t = txt->txtm6;
    
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      if ((xr >= 0) && (xl < myworld->rendx)) {
	if (xr > (myworld->maxx)) xr = myworld->maxx;
	if (xl < 0) {
	  skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        xl   = 0;
	}
	length = xr - xl;
	if (length > 0) {
	  iptr = dst + xl + myworld->precy[y];
	  
	  for (i = 0; i < length; i++) {
	    *iptr++ = t[((v>>22)&0x2) + ((u>>23)&0x1)];
	    u += iuadd;
	    v += ivadd;
	  }
	}
      }
    }
  }

  dpop();
}
/* fill trigon using texture algorithm, no perspective correction */
void World::Trigon::fillGTextureMipNoClip(int *dst) {
  
  dpush2("World::Trigon::fillTextureMipNoClip(%#010x)", (int )dst);

  Vertex *vct[3];                               // vertices
  int    pa,pb,pc;
  int    i, y;                                  // y temp value
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  float  uadd,vadd;
  int    iuadd, ivadd;
  int    xl, xr;
  int    u, v;
  int    length;
  int    *iptr;
  int    maxadd;
  int    *t;
  Yvalc  *yvalp;

  vct[0] = cp;                                       /* simplify offset calc */
  vct[1] = bp;
  vct[2] = ap;

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1;        /* sort a as highest node */
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;                    /* b,c clockwize */
  pc = pa - 1; if (pc < 0) pc = 2;

  /*|  a  |   a  | a b | c a |     |*/
  /*|   b |  c   |  c  |  b  |  a  |*/
  /*| c   |    b |     |     | c b |*/
  /*
  ap->u = ua; ap->v = va;
  bp->u = ub; bp->v = vb;
  cp->u = uc; cp->v = vc;
  */
  _y1 =  9999;
  _y2 = -9999;
  texScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y)
    scanRight(vct[pb],vct[pc]);
  else
    texScanLeft(vct[pc],vct[pb]); 

  if (_y1 == _y2) { dpop(); return; }                        // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;

  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  uadd = ( (vct[1]->u - vct[0]->u) * deltay2
          -(vct[2]->u - vct[0]->u) * deltay1 ) * divdelta;
  vadd = ( (vct[1]->v - vct[0]->v) * deltay2
          -(vct[2]->v - vct[0]->v) * deltay1 ) * divdelta;

  iuadd = float2fixed(uadd);
  ivadd = float2fixed(vadd);

  yvalp = &(myworld->yval[_y1]);

  if (fabs(uadd) > fabs(vadd))
    maxadd = CEIL(fabs(uadd));
  else
    maxadd = CEIL(fabs(vadd));

  if (!(maxadd >> 1)) {
    t = txt->txt;
    
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      length = xr - xl;
      if (length > 0) {
	iptr = dst + xl + myworld->precy[y];
	
	for (i = 0; i < length; i++) {
	  *iptr++ = t[((v>>8)&0xff00) + ((u>>16)&0xff)];
	  u += iuadd;
	  v += ivadd;
	}
      }
    }
  } else 
  if (!(maxadd >> 2)) {
    t = txt->txtm1;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      length = xr - xl;
      if (length > 0) {
	iptr = dst + xl + myworld->precy[y];
	  
	for (i = 0; i < length; i++) {
	  *iptr++ = t[((v>>10)&0x3F80) + ((u>>17)&0x007f)];
	  u += iuadd;
	  v += ivadd;
	}
      }
    }
  } else
  if (!(maxadd >> 3)) {
    t = txt->txtm2;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      length = xr - xl;
      if (length > 0) {
	iptr = dst + xl + myworld->precy[y];
	  
	for (i = 0; i < length; i++) {
	  *iptr++ = t[((v>>12)&0x0fc0) + ((u>>18)&0x3f)];
	  u += iuadd;
	  v += ivadd;
	}
      }
    }
  } else
  if (!(maxadd >> 4)) {
    t = txt->txtm3;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      length = xr - xl;
      if (length > 0) {
	iptr = dst + xl + myworld->precy[y];
	
	for (i = 0; i < length; i++) {
	  *iptr++ = t[((v>>14)&0x3e0) + ((u>>19)&0x1f)];
	  u += iuadd;
	  v += ivadd;
	}
      }
    }
  } else 
  if (!(maxadd >> 5)) {
    t = txt->txtm4;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      length = xr - xl;
      if (length > 0) {
	iptr = dst + xl + myworld->precy[y];
	  
	for (i = 0; i < length; i++) {
	  *iptr++ = t[((v>>16)&0xf0) + ((u>>20)&0xf)];
	  u += iuadd;
	  v += ivadd;
	}
      }
    }
  } else
  if (!(maxadd >> 6)) {

    t = txt->txtm5;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      length = xr - xl;
      if (length > 0) {
	iptr = dst + xl + myworld->precy[y];
	  
	for (i = 0; i < length; i++) {
	  *iptr++ = t[((v>>20)&0xc) + ((u>>22)&0x3)];
	  u += iuadd;
	  v += ivadd;
	}
      }
    }
  } else
//  if (!(maxadd >> 7))
  {
    t = txt->txtm6;
  
    for (y = _y1; y < _y2; y++) {
      xl = yvalp->xl;
      xr = yvalp->xr;
      u  = yvalp->u;
      v  = yvalp->v;
      yvalp++;
      
      length = xr - xl;
      if (length > 0) {
	iptr = dst + xl + myworld->precy[y];
	
	for (i = 0; i < length; i++) {
	  *iptr++ = t[((v>>22)&0x2) + ((u>>23)&0x1)];
	  u += iuadd;
	  v += ivadd;
	}
      }
    }
  }
  dpop();
}

/* fill trigon using plain algorithm */
void World::Trigon::fillPlain(int *dst) {
  
  dpush2("World::Trigon::fillPlain(%#010x)", (int )dst);

  Vertex *vct[3];                               // vertices
  int    pa,pb,pc;
  int    i, y;                                  // y temp value
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  int    xl, xr;
  int    length;
  int    skip;
  int    *iptr;
  Yvalc  *yvalp;
  int    c, r, g, b;

  vct[0] = cp;                                       /* simplify offset calc */
  vct[1] = bp;
  vct[2] = ap;

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1;        /* sort a as highest node */
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;                    /* b,c clockwize */
  pc = pa - 1; if (pc < 0) pc = 2;

  /*|  a  |   a  | a b | c a |     |*/
  /*|   b |  c   |  c  |  b  |  a  |*/
  /*| c   |    b |     |     | c b |*/

  ap->u = ua; ap->v = va;
  bp->u = ub; bp->v = vb;
  cp->u = uc; cp->v = vc;

  _y1 =  9999;
  _y2 = -9999;
  plainScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y)
    scanRight(vct[pb],vct[pc]);
  else
    plainScanLeft(vct[pc],vct[pb]); 

  if (_y1 == _y2) { dpop(); return; }                        // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;


  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  yvalp = &(myworld->yval[_y1]);

  r = CEIL((vct[0]->gouraud.r
          + vct[1]->gouraud.r
          + vct[2]->gouraud.r) * ((float )1.0 / (float )3.0));
  g = CEIL((vct[0]->gouraud.g
          + vct[1]->gouraud.g
          + vct[2]->gouraud.g) * ((float )1.0 / (float )3.0));
  b = CEIL((vct[0]->gouraud.b
          + vct[1]->gouraud.b
          + vct[2]->gouraud.b) * ((float )1.0 / (float )3.0));

  unsigned int ALPHAMASK = 0x000000ff;
  c = (r << 24) | (g << 16) | (b << 8) | ALPHAMASK;

  for (y = _y1; y < _y2; y++) {
    xl = yvalp->xl;
    xr = yvalp->xr;
    yvalp++;

    if ((xr >= 0) && (xl < myworld->rendx)) {
      if (xr > (myworld->maxx)) xr = myworld->maxx;
      if (xl < 0) {
        skip = (0 - xl);
        xl   = 0;
      }
      length = xr - xl;
      if (length > 0) {
        iptr = dst + xl + myworld->precy[y];

        for (i = 0; i < length; i++)
          *iptr++ = c;
      }
    }
  }

  dpop();
}
void World::Trigon::fillPlainNoClip(int *dst) {
  
  dpush2("World::Trigon::fillPlainNoClip(%#010x)", (int )dst);

  Vertex *vct[3];                               // vertices
  int    pa,pb,pc;
  int    i, y;                                  // y temp value
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  int    xl, xr;
  int    length;
  int    *iptr;
  Yvalc  *yvalp;
  int    c, r, g, b;

  vct[0] = cp;                                       /* simplify offset calc */
  vct[1] = bp;
  vct[2] = ap;

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1;        /* sort a as highest node */
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;                    /* b,c clockwize */
  pc = pa - 1; if (pc < 0) pc = 2;

  /*|  a  |   a  | a b | c a |     |*/
  /*|   b |  c   |  c  |  b  |  a  |*/
  /*| c   |    b |     |     | c b |*/

  ap->u = ua; ap->v = va;
  bp->u = ub; bp->v = vb;
  cp->u = uc; cp->v = vc;

  _y1 =  9999;
  _y2 = -9999;
  plainScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y)
    scanRight(vct[pb],vct[pc]);
  else
    plainScanLeft(vct[pc],vct[pb]); 

  if (_y1 == _y2) { dpop(); return; }                        // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;


  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  yvalp = &(myworld->yval[_y1]);

  r = CEIL((vct[0]->gouraud.r
          + vct[1]->gouraud.r
          + vct[2]->gouraud.r) * ((float )1.0 / (float )3.0));
  g = CEIL((vct[0]->gouraud.g
          + vct[1]->gouraud.g
          + vct[2]->gouraud.g) * ((float )1.0 / (float )3.0));
  b = CEIL((vct[0]->gouraud.b
          + vct[1]->gouraud.b
          + vct[2]->gouraud.b) * ((float )1.0 / (float )3.0));

  unsigned int ALPHAMASK = 0x000000ff;
  c = (r << 24) | (g << 16) | (b << 8) | ALPHAMASK;

  for (y = _y1; y < _y2; y++) {
    xl = yvalp->xl;
    xr = yvalp->xr;
    yvalp++;

    length = xr - xl;
    if (length > 0) {
      iptr = dst + xl + myworld->precy[y];      
      for (i = 0; i < length; i++)
	*iptr++ = c;
    }
  }

  dpop();
}

/* fill trigon using plain algorithm */
void World::Trigon::fillGouraud(int *dst) {

  dpush2("World::Trigon::fillGouraud(%#010x)", (int )dst);

  Vertex *vct[3]; 
  int    pa,pb,pc;
  int    i, y;    
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  float  radd, gadd, badd;
  int    iradd, igadd, ibadd;
  int    xl, xr;
  int    r, g, b;
  int    length;
  int    skip;
  int    *ptr;
  Yvalc  *yvalp;

  vct[0] = cp;                                 
  vct[1] = bp;
  vct[2] = ap;

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1;
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;
  pc = pa - 1; if (pc < 0) pc = 2;

  /* |  a  |   a  | a b | c a |     | */
  /* |   b |  c   |  c  |  b  |  a  | */
  /* | c   |    b |     |     | c b | */

  _y1 =  9999;
  _y2 = -9999;
  gouraudScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y) {
    scanRight(vct[pb],vct[pc]);
  } else {
    gouraudScanLeft(vct[pc],vct[pb]);
  }

  if (_y1 == _y2) return;                         // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;


  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  radd = ( (vct[1]->gouraud.r - vct[0]->gouraud.r) * deltay2
          -(vct[2]->gouraud.r - vct[0]->gouraud.r) * deltay1 ) * divdelta;
  gadd = ( (vct[1]->gouraud.g - vct[0]->gouraud.g) * deltay2
          -(vct[2]->gouraud.g - vct[0]->gouraud.g) * deltay1 ) * divdelta;
  badd = ( (vct[1]->gouraud.b - vct[0]->gouraud.b) * deltay2
          -(vct[2]->gouraud.b - vct[0]->gouraud.b) * deltay1 ) * divdelta;

  unsigned int ALPHAMASK  = 0x000000ff;
  unsigned int REDMASK    = 0xff000000;
  unsigned int GREENMASK  = 0x00ff0000;
  unsigned int BLUEMASK   = 0x0000ff00;

  iradd = float2fixed(radd);
  igadd = float2fixed(gadd);
  ibadd = float2fixed(badd);

  yvalp = &(myworld->yval[_y1]);

  for (y = _y1; y < _y2; y++) {
    xl = yvalp->xl;
    xr = yvalp->xr;
    r  = yvalp->r;
    g  = yvalp->g;
    b  = yvalp->b;
    yvalp++;

    if ((xr >= 0) && (xl < (myworld->maxx))) {
      if (xr > (myworld->maxx)) xr = (myworld->maxx);
      if (xl < 0) {
        skip = (0 - xl);
        r   += (iradd * skip);
        g   += (igadd * skip);
        b   += (ibadd * skip);
        xl   = 0;
      }

      length = xr - xl;

      if (length > 0) {
        ptr = dst + myworld->precy[y] + xl;

        for (i = 0; i < length; i++) {
	  *ptr++ = ((r<<8)&REDMASK)|(g&GREENMASK)|((b>>8)&BLUEMASK)|ALPHAMASK;
          r += iradd;
          g += igadd;
          b += ibadd;
        }
      }
    }
  }

  dpop();
}
void World::Trigon::fillGouraudNoClip(int *dst) {

  dpush2("World::Trigon::fillGouraud(%#010x)", (int )dst);

  Vertex *vct[3]; 
  int    pa,pb,pc;
  int    i, y;    
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  float  radd, gadd, badd;
  int    iradd, igadd, ibadd;
  int    xl, xr;
  int    r, g, b;
  int    length;
  int    *ptr;
  Yvalc  *yvalp;

  vct[0] = cp;                                 
  vct[1] = bp;
  vct[2] = ap;

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1;
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;
  pc = pa - 1; if (pc < 0) pc = 2;

  /* |  a  |   a  | a b | c a |     | */
  /* |   b |  c   |  c  |  b  |  a  | */
  /* | c   |    b |     |     | c b | */

  _y1 =  9999;
  _y2 = -9999;
  gouraudScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y) {
    scanRight(vct[pb],vct[pc]);
  } else {
    gouraudScanLeft(vct[pc],vct[pb]);
  }

  if (_y1 == _y2) return;                         // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;


  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  radd = ( (vct[1]->gouraud.r - vct[0]->gouraud.r) * deltay2
          -(vct[2]->gouraud.r - vct[0]->gouraud.r) * deltay1 ) * divdelta;
  gadd = ( (vct[1]->gouraud.g - vct[0]->gouraud.g) * deltay2
          -(vct[2]->gouraud.g - vct[0]->gouraud.g) * deltay1 ) * divdelta;
  badd = ( (vct[1]->gouraud.b - vct[0]->gouraud.b) * deltay2
          -(vct[2]->gouraud.b - vct[0]->gouraud.b) * deltay1 ) * divdelta;

  unsigned int ALPHAMASK  = 0x000000ff;
  unsigned int REDMASK    = 0xff000000;
  unsigned int GREENMASK  = 0x00ff0000;
  unsigned int BLUEMASK   = 0x0000ff00;

  iradd = float2fixed(radd);
  igadd = float2fixed(gadd);
  ibadd = float2fixed(badd);

  yvalp = &(myworld->yval[_y1]);

  for (y = _y1; y < _y2; y++) {
    xl = yvalp->xl;
    xr = yvalp->xr;
    r  = yvalp->r;
    g  = yvalp->g;
    b  = yvalp->b;
    yvalp++;

    length = xr - xl;

    if (length > 0) {
      ptr = dst + myworld->precy[y] + xl;

      for (i = 0; i < length; i++) {
	*ptr++ = ((r<<8)&REDMASK)|(g&GREENMASK)|((b>>8)&BLUEMASK)|ALPHAMASK;
	r += iradd;
	g += igadd;
	b += ibadd;
      }
    }
  }

  dpop();
}

/* fill trigon using gouraud + texture algorithm, no perspective correction */
void World::Trigon::fillGTexture(int *dst) {
  
  dpush2("World::Trigon::fillGTexture(%#010x)", (int )dst);

  Vertex *vct[3];                               // vertices
  int    pa,pb,pc;
  int    i, y;                                  // y temp value
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  float  uadd,vadd,radd,gadd,badd;
  int    iuadd, ivadd, iradd, igadd, ibadd;
  int    xl, xr;
  int    u, v, r, g, b;
  int    rs, gs, bs;
  int    read;
  int    length;
  int    skip;
  int    *iptr;
  int    *t = (int *)txt->txt;
  Yvalc  *yvalp;

  vct[0] = cp;                                       /* simplify offset calc */
  vct[1] = bp;
  vct[2] = ap;

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1;        /* sort a as highest node */
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;                    /* b,c clockwize */
  pc = pa - 1; if (pc < 0) pc = 2;

  /*|  a  |   a  | a b | c a |     |*/
  /*|   b |  c   |  c  |  b  |  a  |*/
  /*| c   |    b |     |     | c b |*/
  /*
  ap->u = ua; ap->v = va;
  bp->u = ub; bp->v = vb;
  cp->u = uc; cp->v = vc;
  */
  _y1 =  9999;
  _y2 = -9999;
  gTexScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y)
    scanRight(vct[pb],vct[pc]);
  else
    gTexScanLeft(vct[pc],vct[pb]); 

  if (_y1 == _y2) { dpop(); return; }                        // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;

  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  uadd = ( (vct[1]->u - vct[0]->u) * deltay2
          -(vct[2]->u - vct[0]->u) * deltay1 ) * divdelta;
  vadd = ( (vct[1]->v - vct[0]->v) * deltay2
          -(vct[2]->v - vct[0]->v) * deltay1 ) * divdelta;
  radd = ( (vct[1]->gouraud.r - vct[0]->gouraud.r) * deltay2
          -(vct[2]->gouraud.r - vct[0]->gouraud.r) * deltay1 ) * divdelta;
  gadd = ( (vct[1]->gouraud.g - vct[0]->gouraud.g) * deltay2
          -(vct[2]->gouraud.g - vct[0]->gouraud.g) * deltay1 ) * divdelta;
  badd = ( (vct[1]->gouraud.b - vct[0]->gouraud.b) * deltay2
          -(vct[2]->gouraud.b - vct[0]->gouraud.b) * deltay1 ) * divdelta;

  unsigned int ALPHAMASK  = 0x000000ff;
  unsigned int REDMASK    = 0xff000000;
  unsigned int GREENMASK  = 0x00ff0000;
  unsigned int BLUEMASK   = 0x0000ff00;

  iuadd = float2fixed(uadd);
  ivadd = float2fixed(vadd);
  iradd = float2fixed(radd);
  igadd = float2fixed(gadd);
  ibadd = float2fixed(badd);
  
  yvalp = &(myworld->yval[_y1]);

  for (y = _y1; y < _y2; y++) {
    xl = yvalp->xl;
    xr = yvalp->xr;
    u  = yvalp->u;
    v  = yvalp->v;
    r  = yvalp->r;
    g  = yvalp->g;
    b  = yvalp->b;
    yvalp++;

    if ((xr >= 0) && (xl < myworld->rendx)) {
      if (xr > (myworld->maxx)) xr = myworld->maxx;
      if (xl < 0) {
        skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        r   += (iradd * skip);
        g   += (igadd * skip);
        b   += (ibadd * skip);
        xl   = 0;
      }
      length = xr - xl;
      if (length > 0) {
        iptr = dst + xl + myworld->precy[y];

        for (i = 0; i < length; i++) {

	  read = t[((v>>8)&0xff00) + ((u>>16)&0xff)];

	  rs = myworld->lookup[(r>>16)+((read & REDMASK)>>16)]<<24;
	  gs = myworld->lookup[(g>>16)+((read & GREENMASK)>>8)]<<16;
	  bs = myworld->lookup[(b>>16)+((read & BLUEMASK))]<<8;

          *iptr++ = rs | gs | bs | ALPHAMASK;

          u += iuadd;
          v += ivadd;
          r += iradd;
          g += igadd;
          b += ibadd;
        }
      }
    }
  }

  dpop();
}
/* fill trigon using gouraud + texture algorithm, no perspective correction */
void World::Trigon::fillGTextureNoClip(int *dst) {
  
  dpush2("World::Trigon::fillGTextureNoClip(%#010x)", (int )dst);

  Vertex *vct[3];                               // vertices
  int    pa,pb,pc;
  int    i, y;                                  // y temp value
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  float  uadd,vadd,radd,gadd,badd;
  int    iuadd, ivadd, iradd, igadd, ibadd;
  int    xl, xr;
  int    u, v, r, g, b;
  int    rs, gs, bs;
  int    read;
  int    length;
  int    *iptr;
  int    *t = (int *)txt->txt;
  Yvalc  *yvalp;

  vct[0] = cp;                                       /* simplify offset calc */
  vct[1] = bp;
  vct[2] = ap;

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1;        /* sort a as highest node */
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;                    /* b,c clockwize */
  pc = pa - 1; if (pc < 0) pc = 2;

  /*|  a  |   a  | a b | c a |     |*/
  /*|   b |  c   |  c  |  b  |  a  |*/
  /*| c   |    b |     |     | c b |*/
  /*
  ap->u = ua; ap->v = va;
  bp->u = ub; bp->v = vb;
  cp->u = uc; cp->v = vc;
  */
  _y1 =  9999;
  _y2 = -9999;
  gTexScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y)
    scanRight(vct[pb],vct[pc]);
  else
    gTexScanLeft(vct[pc],vct[pb]); 

  if (_y1 == _y2) { dpop(); return; }                        // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;

  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  uadd = ( (vct[1]->u - vct[0]->u) * deltay2
          -(vct[2]->u - vct[0]->u) * deltay1 ) * divdelta;
  vadd = ( (vct[1]->v - vct[0]->v) * deltay2
          -(vct[2]->v - vct[0]->v) * deltay1 ) * divdelta;
  radd = ( (vct[1]->gouraud.r - vct[0]->gouraud.r) * deltay2
          -(vct[2]->gouraud.r - vct[0]->gouraud.r) * deltay1 ) * divdelta;
  gadd = ( (vct[1]->gouraud.g - vct[0]->gouraud.g) * deltay2
          -(vct[2]->gouraud.g - vct[0]->gouraud.g) * deltay1 ) * divdelta;
  badd = ( (vct[1]->gouraud.b - vct[0]->gouraud.b) * deltay2
          -(vct[2]->gouraud.b - vct[0]->gouraud.b) * deltay1 ) * divdelta;

  unsigned int ALPHAMASK  = 0x000000ff;
  unsigned int REDMASK    = 0xff000000;
  unsigned int GREENMASK  = 0x00ff0000;
  unsigned int BLUEMASK   = 0x0000ff00;

  iuadd = float2fixed(uadd);
  ivadd = float2fixed(vadd);
  iradd = float2fixed(radd);
  igadd = float2fixed(gadd);
  ibadd = float2fixed(badd);

  yvalp = &(myworld->yval[_y1]);

  for (y = _y1; y < _y2; y++) {
    xl = yvalp->xl;
    xr = yvalp->xr;
    u  = yvalp->u;
    v  = yvalp->v;
    r  = yvalp->r;
    g  = yvalp->g;
    b  = yvalp->b;
    yvalp++;

    length = xr - xl;
    if (length > 0) {
      iptr = dst + xl + myworld->precy[y];

      for (i = 0; i < length; i++) {
	
	read = t[((v>>8)&0xff00) + ((u>>16)&0xff)];
	
	rs = myworld->lookup[(r>>16)+((read & REDMASK)>>16)]<<24;
	gs = myworld->lookup[(g>>16)+((read & GREENMASK)>>8)]<<16;
	bs = myworld->lookup[(b>>16)+((read & BLUEMASK))]<<8;

	*iptr++ = rs | gs | bs | ALPHAMASK;
	
	u += iuadd;
	v += ivadd;
	r += iradd;
	g += igadd;
	b += ibadd;
      }
    }
  }

  dpop();
}

/* fill trigon using gouraud + texture algorithm, no perspective correction */
void World::Trigon::fillGTextureTrans(int *dst) {
  
  dpush2("World::Trigon::fillGTextureTrans(%#010x)", (int )dst);

  Vertex *vct[3];                               // vertices
  int    pa,pb,pc;
  int    i, y;                                  // y temp value
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  float  uadd,vadd,radd,gadd,badd;
  int    iuadd, ivadd, iradd, igadd, ibadd;
  int    xl, xr;
  int    u, v, r, g, b;
  int    rs, gs, bs;
  int    read;
  int    length;
  int    skip;
  int    *iptr;
  int    *t = (int *)txt->txt;
  Yvalc  *yvalp;

  vct[0] = cp;                                       /* simplify offset calc */
  vct[1] = bp;
  vct[2] = ap;

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1;        /* sort a as highest node */
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;                    /* b,c clockwize */
  pc = pa - 1; if (pc < 0) pc = 2;

  /*|  a  |   a  | a b | c a |     |*/
  /*|   b |  c   |  c  |  b  |  a  |*/
  /*| c   |    b |     |     | c b |*/
  /*
  ap->u = ua; ap->v = va;
  bp->u = ub; bp->v = vb;
  cp->u = uc; cp->v = vc;
  */
  _y1 =  9999;
  _y2 = -9999;
  gTexScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y)
    scanRight(vct[pb],vct[pc]);
  else
    gTexScanLeft(vct[pc],vct[pb]); 

  if (_y1 == _y2) { dpop(); return; }                        // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;

  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  uadd = ( (vct[1]->u - vct[0]->u) * deltay2
          -(vct[2]->u - vct[0]->u) * deltay1 ) * divdelta;
  vadd = ( (vct[1]->v - vct[0]->v) * deltay2
          -(vct[2]->v - vct[0]->v) * deltay1 ) * divdelta;
  radd = ( (vct[1]->gouraud.r - vct[0]->gouraud.r) * deltay2
          -(vct[2]->gouraud.r - vct[0]->gouraud.r) * deltay1 ) * divdelta;
  gadd = ( (vct[1]->gouraud.g - vct[0]->gouraud.g) * deltay2
          -(vct[2]->gouraud.g - vct[0]->gouraud.g) * deltay1 ) * divdelta;
  badd = ( (vct[1]->gouraud.b - vct[0]->gouraud.b) * deltay2
          -(vct[2]->gouraud.b - vct[0]->gouraud.b) * deltay1 ) * divdelta;

  unsigned int ALPHAMASK  = 0x000000ff;
  unsigned int REDMASK    = 0xff000000;
  unsigned int GREENMASK  = 0x00ff0000;
  unsigned int BLUEMASK   = 0x0000ff00;

  iuadd = float2fixed(uadd);
  ivadd = float2fixed(vadd);
  iradd = float2fixed(radd);
  igadd = float2fixed(gadd);
  ibadd = float2fixed(badd);
  
  yvalp = &(myworld->yval[_y1]);

  for (y = _y1; y < _y2; y++) {
    xl = yvalp->xl;
    xr = yvalp->xr;
    u  = yvalp->u;
    v  = yvalp->v;
    r  = yvalp->r;
    g  = yvalp->g;
    b  = yvalp->b;
    yvalp++;

    if ((xr >= 0) && (xl < myworld->rendx)) {
      if (xr > (myworld->maxx)) xr = myworld->maxx;
      if (xl < 0) {
        skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        r   += (iradd * skip);
        g   += (igadd * skip);
        b   += (ibadd * skip);
        xl   = 0;
      }
      length = xr - xl;
      if (length > 0) {
        iptr = dst + xl + myworld->precy[y];

        for (i = 0; i < length; i++) {

	  read = t[((v>>8)&0xff00) + ((u>>16)&0xff)];
	  
	  rs = myworld->lookup[(r>>16)+((read & REDMASK)>>16)]<<16;
	  gs = myworld->lookup[(g>>16)+((read & GREENMASK)>>8)]<<16;
	  bs = myworld->lookup[(b>>16)+((read & BLUEMASK))]<<16;

	  read = *iptr;

	  *iptr++ = ((((read&REDMASK)>>1)   + (rs<<7)) & REDMASK)|
	            ((((read&GREENMASK)>>1) + (gs>>1))&GREENMASK)|
	            ((((read&BLUEMASK )>>1) + (bs>>9))&BLUEMASK)|
                    ALPHAMASK;

          u += iuadd;
          v += ivadd;
          r += iradd;
          g += igadd;
          b += ibadd;
        }
      }
    }
  }

  dpop();
}
/* fill trigon using gouraud + texture algorithm, no perspective correction */
void World::Trigon::fillGTextureTransNoClip(int *dst) {
  
  dpush2("World::Trigon::fillGTextureTransNoClip(%#010x)", (int )dst);

  Vertex *vct[3];                               // vertices
  int    pa,pb,pc;
  int    i, y;                                  // y temp value
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  float  uadd,vadd,radd,gadd,badd;
  int    iuadd, ivadd, iradd, igadd, ibadd;
  int    xl, xr;
  int    u, v, r, g, b;
  int    rs, gs, bs;
  int    read;
  int    length;
  int    *iptr;
  int    *t = (int *)txt->txt;
  Yvalc  *yvalp;

  vct[0] = cp;                                       /* simplify offset calc */
  vct[1] = bp;
  vct[2] = ap;

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1;        /* sort a as highest node */
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;                    /* b,c clockwize */
  pc = pa - 1; if (pc < 0) pc = 2;

  /*|  a  |   a  | a b | c a |     |*/
  /*|   b |  c   |  c  |  b  |  a  |*/
  /*| c   |    b |     |     | c b |*/
  /*
  ap->u = ua; ap->v = va;
  bp->u = ub; bp->v = vb;
  cp->u = uc; cp->v = vc;
  */
  _y1 =  9999;
  _y2 = -9999;
  gTexScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y)
    scanRight(vct[pb],vct[pc]);
  else
    gTexScanLeft(vct[pc],vct[pb]); 

  if (_y1 == _y2) { dpop(); return; }                        // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;

  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  uadd = ( (vct[1]->u - vct[0]->u) * deltay2
          -(vct[2]->u - vct[0]->u) * deltay1 ) * divdelta;
  vadd = ( (vct[1]->v - vct[0]->v) * deltay2
          -(vct[2]->v - vct[0]->v) * deltay1 ) * divdelta;
  radd = ( (vct[1]->gouraud.r - vct[0]->gouraud.r) * deltay2
          -(vct[2]->gouraud.r - vct[0]->gouraud.r) * deltay1 ) * divdelta;
  gadd = ( (vct[1]->gouraud.g - vct[0]->gouraud.g) * deltay2
          -(vct[2]->gouraud.g - vct[0]->gouraud.g) * deltay1 ) * divdelta;
  badd = ( (vct[1]->gouraud.b - vct[0]->gouraud.b) * deltay2
          -(vct[2]->gouraud.b - vct[0]->gouraud.b) * deltay1 ) * divdelta;

  unsigned int ALPHAMASK  = 0x000000ff;
  unsigned int REDMASK    = 0xff000000;
  unsigned int GREENMASK  = 0x00ff0000;
  unsigned int BLUEMASK   = 0x0000ff00;

  iuadd = float2fixed(uadd);
  ivadd = float2fixed(vadd);
  iradd = float2fixed(radd);
  igadd = float2fixed(gadd);
  ibadd = float2fixed(badd);
  
  yvalp = &(myworld->yval[_y1]);

  for (y = _y1; y < _y2; y++) {
    xl = yvalp->xl;
    xr = yvalp->xr;
    u  = yvalp->u;
    v  = yvalp->v;
    r  = yvalp->r;
    g  = yvalp->g;
    b  = yvalp->b;
    yvalp++;

    length = xr - xl;
    if (length > 0) {
      iptr = dst + xl + myworld->precy[y];
      
      for (i = 0; i < length; i++) {
	
	read = t[((v>>8)&0xff00) + ((u>>16)&0xff)];
	
	rs = myworld->lookup[(r>>16)+((read & REDMASK)>>16)]<<16;
	gs = myworld->lookup[(g>>16)+((read & GREENMASK)>>8)]<<16;
	bs = myworld->lookup[(b>>16)+((read & BLUEMASK))]<<16;
	
	read = *iptr;
	
	*iptr++ = ((((read&REDMASK)>>1)   + (rs<<7)) & REDMASK)|
	          ((((read&GREENMASK)>>1) + (gs>>1))&GREENMASK)|
	          ((((read&BLUEMASK )>>1) + (bs>>9))&BLUEMASK)|
	          ALPHAMASK;

	u += iuadd;
	v += ivadd;
	r += iradd;
	g += igadd;
	b += ibadd;
      }
    }
  }

  dpop();
}

/* polyfiller, fake Phong (env mapping) */
void World::Trigon::fillPhong(int *dst) {

  dpush2("World::Trigon::fillPhong(%#010x)", (int )dst);

  Vertex *vct[3];                               // vertices
  int    pa,pb,pc;
  int    i, y;                                  // y temp value
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  float  uadd,vadd;
  int    iuadd, ivadd;
  int    xl, xr;
  int    u, v;
  int    length;
  int    skip;
  int    *iptr;
  int    *t = (int *)txt->txt;
  Yvalc  *yvalp;

  vct[0] = cp;                                  // simplify offset calc
  vct[1] = bp;
  vct[2] = ap;

  vct[0]->u = 128 + (vct[0]->normal.posr->x * 127);
  vct[0]->v = 128 + (vct[0]->normal.posr->y * 127);
  vct[1]->u = 128 + (vct[1]->normal.posr->x * 127);
  vct[1]->v = 128 + (vct[1]->normal.posr->y * 127);
  vct[2]->u = 128 + (vct[2]->normal.posr->x * 127);
  vct[2]->v = 128 + (vct[2]->normal.posr->y * 127);

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1; // sort a as highest node
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;                    // b,c clockwize
  pc = pa - 1; if (pc < 0) pc = 2;

  /* |  a  |   a  | a b | c a |     | */
  /* |   b |  c   |  c  |  b  |  a  | */
  /* | c   |    b |     |     | c b | */

  _y1 =  9999;
  _y2 = -9999;
  texScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y) {
    scanRight(vct[pb],vct[pc]);
  } else {
    texScanLeft(vct[pc],vct[pb]);
  }

  if (_y1 == _y2) { dpop(); return; }                        // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;


  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  uadd = ( (vct[1]->u - vct[0]->u) * deltay2
          -(vct[2]->u - vct[0]->u) * deltay1 ) * divdelta;
  vadd = ( (vct[1]->v - vct[0]->v) * deltay2
          -(vct[2]->v - vct[0]->v) * deltay1 ) * divdelta;

  iuadd = float2fixed(uadd);
  ivadd = float2fixed(vadd);

  yvalp = &(myworld->yval[_y1]);

  for (y = _y1; y < _y2; y++) {
    xl = yvalp->xl;
    xr = yvalp->xr;
    u  = yvalp->u;
    v  = yvalp->v;
    yvalp++;

    if ((xr >= 0) && (xl < (myworld->maxx))) {
      if (xr > (myworld->maxx)) xr = (myworld->maxx);
      if (xl < 0) {
        skip = (0 - xl);
        u   += (iuadd * skip);
        v   += (ivadd * skip);
        xl   = 0;
      }

      length = xr - xl;

      if (length > 0) {
        iptr = dst + myworld->precy[y] + xl;

        for (i = 0; i < length; i++) {
          *iptr++ = t[((v>>8)&0xff00) + ((u>>16)&0xff)];
          u += iuadd;
          v += ivadd;
        }
      }
    }
  }
  dpop();
}
void World::Trigon::fillPhongNoClip(int *dst) {

  dpush2("World::Trigon::fillPhongNoClip(%#010x)", (int )dst);


  Vertex *vct[3];                               // vertices
  int    pa,pb,pc;
  int    i, y;                                  // y temp value
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  float  uadd,vadd;
  int    iuadd, ivadd;
  int    xl, xr;
  int    u, v;
  int    length;
  int    *iptr;
  int    *t = (int *)txt->txt;
  Yvalc  *yvalp;

  vct[0] = cp;                                  // simplify offset calc
  vct[1] = bp;
  vct[2] = ap;

  vct[0]->u = 128 + (vct[0]->normal.posr->x * 127);
  vct[0]->v = 128 + (vct[0]->normal.posr->y * 127);
  vct[1]->u = 128 + (vct[1]->normal.posr->x * 127);
  vct[1]->v = 128 + (vct[1]->normal.posr->y * 127);
  vct[2]->u = 128 + (vct[2]->normal.posr->x * 127);
  vct[2]->v = 128 + (vct[2]->normal.posr->y * 127);

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1; // sort a as highest node
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;                    // b,c clockwize
  pc = pa - 1; if (pc < 0) pc = 2;

  /* |  a  |   a  | a b | c a |     | */
  /* |   b |  c   |  c  |  b  |  a  | */
  /* | c   |    b |     |     | c b | */

  _y1 =  9999;
  _y2 = -9999;
  texScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y) {
    scanRight(vct[pb],vct[pc]);
  } else {
    texScanLeft(vct[pc],vct[pb]);
  }

  if (_y1 == _y2) { dpop(); return; }                         // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;


  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  uadd = ( (vct[1]->u - vct[0]->u) * deltay2
          -(vct[2]->u - vct[0]->u) * deltay1 ) * divdelta;
  vadd = ( (vct[1]->v - vct[0]->v) * deltay2
          -(vct[2]->v - vct[0]->v) * deltay1 ) * divdelta;

  iuadd = float2fixed(uadd);
  ivadd = float2fixed(vadd);

  yvalp = &(myworld->yval[_y1]);

  for (y = _y1; y < _y2; y++) {
    xl = yvalp->xl;
    xr = yvalp->xr;
    u  = yvalp->u;
    v  = yvalp->v;
    yvalp++;

    length = xr - xl;

    if (length > 0) {
      iptr = dst + myworld->precy[y] + xl;

      for (i = 0; i < length; i++) {
	*iptr++ = t[((v>>8)&0xff00) + ((u>>16)&0xff)];
	u += iuadd;
	v += ivadd;
      }
    }
  }
  
  dpop();
}

/* fill trigon using gouraud transparent algorithm */
void World::Trigon::fillGouraudTransparent(int *dst) {

  dpush2("World::Trigon::fillGouraudTransparent(%#010x)", (int )dst);

  Vertex *vct[3]; 
  int    pa,pb,pc;
  int    i, y;    
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  float  radd, gadd, badd;
  int    iradd, igadd, ibadd;
  int    xl, xr;
  int    r, g, b;
  int    length;
  int    skip;
  int    read;

  int    *ptr;
  Yvalc  *yvalp;

  vct[0] = cp;                                 
  vct[1] = bp;
  vct[2] = ap;

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1;
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;
  pc = pa - 1; if (pc < 0) pc = 2;

  /* |  a  |   a  | a b | c a |     | */
  /* |   b |  c   |  c  |  b  |  a  | */
  /* | c   |    b |     |     | c b | */

  _y1 =  9999;
  _y2 = -9999;
  gouraudScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y) {
    scanRight(vct[pb],vct[pc]);
  } else {
    gouraudScanLeft(vct[pc],vct[pb]);
  }

  if (_y1 == _y2) { dpop(); return; }                         // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;


  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  radd = ( (vct[1]->gouraud.r - vct[0]->gouraud.r) * deltay2
          -(vct[2]->gouraud.r - vct[0]->gouraud.r) * deltay1 ) * divdelta;
  gadd = ( (vct[1]->gouraud.g - vct[0]->gouraud.g) * deltay2
          -(vct[2]->gouraud.g - vct[0]->gouraud.g) * deltay1 ) * divdelta;
  badd = ( (vct[1]->gouraud.b - vct[0]->gouraud.b) * deltay2
          -(vct[2]->gouraud.b - vct[0]->gouraud.b) * deltay1 ) * divdelta;

  unsigned int ALPHAMASK  = 0x000000ff;
  unsigned int REDMASK    = 0xff000000;
  unsigned int GREENMASK  = 0x00ff0000;
  unsigned int BLUEMASK   = 0x0000ff00;

  iradd = float2fixed(radd);
  igadd = float2fixed(gadd);
  ibadd = float2fixed(badd);

  yvalp = &(myworld->yval[_y1]);

  for (y = _y1; y < _y2; y++) {
    xl = yvalp->xl;
    xr = yvalp->xr;
    r  = yvalp->r;
    g  = yvalp->g;
    b  = yvalp->b;
    yvalp++;

    if ((xr >= 0) && (xl < myworld->maxx)) {
      if (xr > myworld->maxx) xr = myworld->maxx;
      if (xl < 0) {
        skip = (0 - xl);
        r   += (iradd * skip);
        g   += (igadd * skip);
        b   += (ibadd * skip);
        xl   = 0;
      }

      length = xr - xl;

      if (length > 0) {
        ptr = dst + myworld->precy[y] + xl;

        for (i = 0; i < length; i++) {
	  read = *ptr;

	  *ptr++ = ((((read & REDMASK)>>1)   + (r<<7)) & REDMASK)|
	           ((((read & GREENMASK)>>1) + (g>>1)) & GREENMASK)|
	           ((((read & BLUEMASK )>>1) + (b>>9)) & BLUEMASK)|
                   ALPHAMASK;

          r += iradd;
          g += igadd;
          b += ibadd;
        }
      }
    }
  }

  dpop();
}
void World::Trigon::fillGouraudTransparentNoClip(int *dst) {

  dpush2("World::Trigon::fillGouraudTransparentNoClip(%#010x)", (int )dst);

  Vertex *vct[3]; 
  int    pa,pb,pc;
  int    i, y;    
  float  deltay1, deltay2;
  float  delta;
  float  divdelta;
  float  radd, gadd, badd;
  int    iradd, igadd, ibadd;
  int    xl, xr;
  int    r, g, b;
  int    length;
  int    read;

  int    *ptr;
  Yvalc  *yvalp;

  vct[0] = cp;                                 
  vct[1] = bp;
  vct[2] = ap;

  pa = 0;
  if (vct[1]->posr->y < vct[pa]->posr->y) pa = 1;
  if (vct[2]->posr->y < vct[pa]->posr->y) pa = 2;
  pb = pa + 1; if (pb > 2) pb = 0;
  pc = pa - 1; if (pc < 0) pc = 2;

  /* |  a  |   a  | a b | c a |     | */
  /* |   b |  c   |  c  |  b  |  a  | */
  /* | c   |    b |     |     | c b | */

  _y1 =  9999;
  _y2 = -9999;
  gouraudScanLeft(vct[pa], vct[pc]);
  scanRight(vct[pa], vct[pb]);

  if (vct[pb]->posr->y < vct[pc]->posr->y) {
    scanRight(vct[pb],vct[pc]);
  } else {
    gouraudScanLeft(vct[pc],vct[pb]);
  }

  if (_y1 == _y2) {return; dpop(); }                         // reject flat polys

  if (myworld->upperscanline > _y1)
     myworld->upperscanline = _y1;

  if (myworld->lowerscanline < _y2)
     myworld->lowerscanline = _y2;


  deltay1 = vct[1]->posr->y - vct[0]->posr->y;
  deltay2 = vct[2]->posr->y - vct[0]->posr->y;

  delta = ((vct[1]->posr->x - vct[0]->posr->x) * deltay2)
         -((vct[2]->posr->x - vct[0]->posr->x) * deltay1);
  divdelta = 1 / delta;

  radd = ( (vct[1]->gouraud.r - vct[0]->gouraud.r) * deltay2
          -(vct[2]->gouraud.r - vct[0]->gouraud.r) * deltay1 ) * divdelta;
  gadd = ( (vct[1]->gouraud.g - vct[0]->gouraud.g) * deltay2
          -(vct[2]->gouraud.g - vct[0]->gouraud.g) * deltay1 ) * divdelta;
  badd = ( (vct[1]->gouraud.b - vct[0]->gouraud.b) * deltay2
          -(vct[2]->gouraud.b - vct[0]->gouraud.b) * deltay1 ) * divdelta;

  unsigned int ALPHAMASK  = 0x000000ff;
  unsigned int REDMASK    = 0xff000000;
  unsigned int GREENMASK  = 0x00ff0000;
  unsigned int BLUEMASK   = 0x0000ff00;

  iradd = float2fixed(radd);
  igadd = float2fixed(gadd);
  ibadd = float2fixed(badd);

  yvalp = &(myworld->yval[_y1]);

  for (y = _y1; y < _y2; y++) {
    xl = yvalp->xl;
    xr = yvalp->xr;
    r  = yvalp->r;
    g  = yvalp->g;
    b  = yvalp->b;
    yvalp++;

    length = xr - xl;

    if (length > 0) {
      ptr = dst + myworld->precy[y] + xl;

      for (i = 0; i < length; i++) {
	read = *ptr;

	*ptr++ = ((((read&REDMASK)>>1)   + (r<<7)) & REDMASK)|
	         ((((read&GREENMASK)>>1) + (g>>1))&GREENMASK)|
	         ((((read&BLUEMASK )>>1) + (b>>9))&BLUEMASK)|
                 ALPHAMASK;
	
	r += iradd;
	g += igadd;
	b += ibadd;
      }
    }
  }

  dpop();
}

/* check if poly is lost */
int World::Trigon::lostPoly() {

  dpush1("World::Trigon::lostPoly()");

  dpop();
  return 0;
}














