#ifdef	USE_ZBUFFER
#define	inc()        { u += du; v += dv; w += dw; }
#define	fill(pel, z) { *pBuffer++ = (pel); *zBuffer++ = (unsigned short int)(z); }
#else
#define	inc()        { u += du; v += dv; }
#define	fill(pel, z) { *pBuffer++ = (pel); }
#endif

#ifdef	USE_ZBUFFER
unsigned short int *draw_affine16(int n, unsigned short int *pBuffer, unsigned short int *zBuffer, int u, int v, int w, int du, int dv, int dw)
#else
unsigned short int *draw_affine16(int n, unsigned short int *pBuffer, int u, int v, int du, int dv)
#endif
{
  if (textureType == WALL_TYPE) {
    while (n--) {
      int iu = u >> 16;
      int iv = ((v >> (16 - MAX_LOGY)) & MAX_MASKX) + textureRow;

#ifdef CALCULATE_PIXELDRAW
      pixelDraw++;
      if (*pBuffer)
	pixelOverdraw++;
#endif

      fill(texture.hicolor[multMuls[iv] + iu], w);
      inc();
    }
  }
  else if (textureType == SKY_TYPE) {
    /* TODO: skies */
    while (n--) {
      int iu;
      int iv;
      unsigned short int pel, sum;

#ifdef CALCULATE_PIXELDRAW
      pixelDraw++;
      if (*pBuffer)
	pixelOverdraw++;
#endif

      iu = ((u >> 8) + skyMovementX1) & 0x00007F00;
      iv = ((v >> 16) + skyMovementY1) & 0x0000007F;
      sum = texture.hicolor[iu + iv + 0x80];
      iu = ((u >> 8) + skyMovementX2) & 0x00007F00;
      iv = ((v >> 16) + skyMovementY2) & 0x0000007F;
      if ((pel = texture.hicolor[iu + iv]))
	sum = pel;

      fill(sum, 0xFFFF);
      inc();
    }
  }
  else {
    while (n--) {
#ifndef	FAST_WARP
      int iv = ((v + (swim_v[((u >> textureShift2) & 0xff)] >> textureMip)) >> 16) & textureMask2;
      int iu = ((u + (swim_u[((v >> textureShift2) & 0xff)] >> textureMip)) >> textureShift1) & textureMask1;
#else
      int iv = ((v + swim_v[(u >> 16)]) >> 16) & textureMask2;
      int iu = ((u + swim_u[(v >> 16)]) >> textureShift1) & textureMask1;
#endif

      fill(pretransp(texture.hicolor[iu + iv], *pBuffer), w);
      inc();
    }
  }
  return pBuffer;
}

/* given a span (x0,y)..(x1,y), draw a perspective-correct span for it */
/*
 * the zbuffer is interesting for dynamic model-draw etc.
 * the buffers values (1/z) are all under 0, we can try to
 * store them as 16bit-wide-fraction
 *
 * while(n--) {
 *   *zbuf++ = (unsigned short int)(w); / we need only the lower part /
 *   w += dw;
 * }
 *
 */
void draw_span16(int y, int sx, int ex)
{
  float w0, w1;
  float v0, v1;
  float u0, u1;

#ifdef	USE_ZBUFFER
  int w, dw;							/* 1/zbuffer */
#endif
  int v, dv;
  int u, du;
  int slen, rlen, len, end;

  unsigned short int *pBuffer = localDim.frameBuffer + multRows[y] + sx;

#ifdef	USE_ZBUFFER
  unsigned short int *zBuffer = localDim.zBuffer + multRows[y] + sx;
#endif
  float prew = tmap[6] + y * tmap[8];
  float prev = tmap[3] + y * tmap[5];
  float preu = tmap[0] + y * tmap[2];

  /* compute (u,v) at left end */
  w0 = 1 / (prew + sx * tmap[7]);				/* 1/zbuffer */
  v0 = (prev + sx * tmap[4]) * w0;
  u0 = (preu + sx * tmap[1]) * w0;

  len = ex - sx;
  for (slen = len >> SUBDIV_SHIFT; slen > 0; slen--) {
#ifdef	USE_ZBUFFER
    w = FLOAT_TO_FIX(w0);					/* 1/zbuffer */
#endif
    v = FLOAT_TO_FIX(v0);
    u = FLOAT_TO_FIX(u0);

    end = sx + SUBDIV;
    w1 = 1 / (prew + end * tmap[7]);
    v1 = (prev + end * tmap[4]) * w1;
    u1 = (preu + end * tmap[1]) * w1;

#ifdef	USE_ZBUFFER
    dw = (FLOAT_TO_FIX(v1) - w) >> SUBDIV_SHIFT;		/* 1/zbuffer */
#endif
    dv = (FLOAT_TO_FIX(v1) - v) >> SUBDIV_SHIFT;
    du = (FLOAT_TO_FIX(u1) - u) >> SUBDIV_SHIFT;

#ifdef	USE_ZBUFFER
    pBuffer = draw_affine16(SUBDIV, pBuffer, zBuffer, u, v, w, du, dv, dw);
    zBuffer += SUBDIV;
#else
    pBuffer = draw_affine16(SUBDIV, pBuffer, u, v, du, dv);
#endif
    sx = end;

#ifdef	USE_ZBUFFER
    w0 = w1;							/* 1/zbuffer */
#endif
    v0 = v1;
    u0 = u1;
  }

#ifdef	USE_ZBUFFER
  w = FLOAT_TO_FIX(w0);						/* 1/zbuffer */
#endif
  v = FLOAT_TO_FIX(v0);
  u = FLOAT_TO_FIX(u0);
  if ((rlen = (len & SUBDIV_MASK) - 1)) {			/* a) do not calc if only draw 1 pixel */
    end = sx + rlen;
    w1 = 1 / (prew + end * tmap[7]);
    v1 = (prev + end * tmap[4]) * w1;
    u1 = (preu + end * tmap[1]) * w1;

#ifdef	USE_ZBUFFER
    dw = FLOAT_TO_FIX((w1 - w0) / rlen);			/* 1/zbuffer */
#endif
    dv = FLOAT_TO_FIX((v1 - v0) / rlen);
    du = FLOAT_TO_FIX((u1 - u0) / rlen);
  }
  /* a) but draw that pixel surely */
#ifdef	USE_ZBUFFER
  draw_affine16(rlen + 1, pBuffer, zBuffer, u, v, w, du, dv, dw);	/* for the last pixel the du and dv are thrown away */
#else
  draw_affine16(rlen + 1, pBuffer, u, v, du, dv);		/* for the last pixel the du and dv are thrown away */
#endif
}
