#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_spans16(int y, int ey)
{
  float prew = tmap[6] + y * tmap[8];
  float prev = tmap[3] + y * tmap[5];
  float preu = tmap[0] + y * tmap[2];

  for (; y < ey; y++) {
    int sx = scan[y][0];
    int len = scan[y][1] - sx;

    if (len > 0) {
      float w0;
      float v0;
      float u0;

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

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

#ifdef	USE_ZBUFFER
      unsigned short int *zBuffer = localDim.zBuffer + multRows[y] + sx;
#endif

      /* 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;

#ifdef	USE_ZBUFFER
      w = FLOAT_TO_FIX(w0);					/* 1/zbuffer */
#endif
      v = FLOAT_TO_FIX(v0);
      u = FLOAT_TO_FIX(u0);

      for (slen = len >> SUBDIV_SHIFT; slen > 0; slen--) {
	sx += SUBDIV;
	w0 = 1 / (prew + sx * tmap[7]);
	v0 = (prev + sx * tmap[4]) * w0;
	u0 = (preu + sx * tmap[1]) * w0;

#ifdef	USE_ZBUFFER
	dw = (FLOAT_TO_FIX(w0) - w) >> SUBDIV_SHIFT;		/* 1/zbuffer */
#endif
	dv = (FLOAT_TO_FIX(v0) - v) >> SUBDIV_SHIFT;
	du = (FLOAT_TO_FIX(u0) - 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

#ifdef	USE_ZBUFFER
	w = FLOAT_TO_FIX(w0);					/* 1/zbuffer */
#endif
	v = FLOAT_TO_FIX(v0);
	u = FLOAT_TO_FIX(u0);
      }

      if ((slen = (len & SUBDIV_MASK) - 1)) {			/* a) do not calc if only draw 1 pixel */
	float w1;
	float v1;
	float u1;

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

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

    prew += tmap[8];
    prev += tmap[5];
    preu += tmap[2];
  }
}
