#if defined(NOASM) || \
    defined(USE_ZBUFFER) || \
    !( \
       ((defined(__mc68020__) || defined(__mc68030__)) && defined(__HAVE_68881__)) || \
        defined(__mc68040__) || \
        defined(__mc68060__) \
     )
# undef	 NOASM
# define NOASM
# undef  staticvar
# define staticvar
#endif

/* clipping */
static point_3d defaultPoints[32], *defaultVList[32];
staticvar fix scan[768][2];

void setup_default_point_list(void)
{
  int i;

  for (i = 32 - 1; i >= 0; --i)
    defaultVList[i] = &defaultPoints[i];
}

/* calculation */
static short int compute_mip_level(__memBase, int face)
{
  /*
   * dumb algorithm: grab 3d coordinate of some vertex,
   * compute dist from viewer
   */
  double dist;
  int se = bspMem->shared.quake1.dfaces[face].firstedge;
  int e = bspMem->shared.quake1.dsurfedges[se];

  if (e < 0)
    e = -e;
  dist = scalw(dist2_from_viewer((vec_t *) & bspMem->shared.quake1.dvertexes[bspMem->shared.quake1.dedges[e].v[0]].point), -16);	/* / 65536; */
  if (dist < 1)
    return 0;
  if (dist < 4)
    return 1;
  if (dist < 16)
    return 2;
  return 3;
}

staticvar float tmap[9];

static void compute_texture_gradients(__memBase, struct texture *Text, short int mip)
{
  float uu, vv;
  float tmp0, tmp1, tmp2;
  vec3_t P, M, N;

  /* project vectors onto face's plane, and transform */
  transform_vector(M, Text->textGradient.uv0);
  transform_vector(N, Text->textGradient.uv1);
  transform_point_raw(P, Text->textGradient.scaled);

  uu = Text->textGradient.u;
  vv = Text->textGradient.v;

  /*
   * we could just subtract (u,v) every time we compute a new (u,v);
   * instead we fold it into P:
   */
  P[0] += uu * M[0] + vv * N[0];
  P[1] += uu * M[1] + vv * N[1];
  P[2] += uu * M[2] + vv * N[2];

  /*
   * offset by Center of screen--if this were folded into
   * transform translation we could avoid it
   */
  tmp2 = N[0] * M[2] - N[2] * M[0];
  tmp1 = N[1] * M[2] - N[2] * M[1];
  tmp0 = N[0] * M[1] - N[1] * M[0];
  tmp0 -= tmp1 * xCenter + tmp2 * yCenter;
  tmap[8] = tmp2;
  tmap[7] = tmp1;
  tmap[6] = tmp0;

  tmp2 = P[2] * M[0] - P[0] * M[2];
  tmp1 = P[2] * M[1] - P[1] * M[2];
  tmp0 = P[1] * M[0] - P[0] * M[1];
  tmp0 -= tmp1 * xCenter + tmp2 * yCenter;
  tmap[5] = scalw(tmp2, -mip);
  tmap[4] = scalw(tmp1, -mip);
  tmap[3] = scalw(tmp0, -mip);

  tmp2 = P[0] * N[2] - P[2] * N[0];
  tmp1 = P[1] * N[2] - P[2] * N[1];
  tmp0 = P[0] * N[1] - P[1] * N[0];
  tmp0 -= tmp1 * xCenter + tmp2 * yCenter;
  tmap[2] = scalw(tmp2, -mip);
  tmap[1] = scalw(tmp1, -mip);
  tmap[0] = scalw(tmp0, -mip);
}

/*
 * NOTE: subdivision of 16 is a really hard thig, it works most, but you can see sometimes curved textures
 *       if you have some processorpower use 8 instead!
 */
#define SUBDIV_SHIFT	4
#define SUBDIV		(1 << SUBDIV_SHIFT)
#define	SUBDIV_MASK	(SUBDIV - 1)

/* draw an affine (linear) span starting at dest, n pixels long, */
/* starting at (u,v) in the texture and stepping by (du,dv) each pixel */
/*
 * if we are in liquid, we can calculate the average pixelcolor
 * of the liquid texture (eg. *lava1) and do a transp with this color
 * so we don't need to change the palette, and the accuracity
 * is better
 *
 * we can make the liquid with a falloff if we use the zbuffer,
 * we have the current z-value, and the z-value at that position
 * we sub them and calculate the transparency-level from that
 * (better use every 10th or like that transparency-level: first,
 *  the transparency is not so accurate, that every percent makes
 *  a change, second, all 100% transparency uses 6,5MB cached
 *  tables, both in memory and on disk (horror!))
 * the falloff is calculated from the brightness of the liquid texture
 * and the type, so brighter texture are more transparent than darker
 *
 * the liquid looks more real if the textures after it also warps
 * so we must determine, which textures lies in liquid, probably
 * we can use the same procedure as the liquid itself, maybe
 * we must project the liquids behaviour to the texture (uff)
 *
 * how to determine if a texture lies in liquid? as I know qbsp
 * splits the plaes at every intersection of two polygons, that
 * means we do not need to split the polygon at the liquid-line
 * the disadvatage of the mark-texture-in-liquid is, that while
 * we are in liquid, the textures outside the liquid doesn't warp
 *
 * probably we can do real wave in liquid, for that we do not change
 * the du or dv, but the z-value (upwards) of the polygon in a
 * reproducable caustics manner, the difficulty is, to calculate this
 * values in the very inner loop (draw_affine), thats slow
 *
 * how to avoid this mipmap shiftig and masking in liquid textures:
 * after building the waterblock convert the scanlines from this:
 *
 * +----+ example: memory-block-size is 64*64
 * |****|          mipmap-size is 32*32
 * |    |          memory is linear
 * |    |
 * |    |
 * +----+
 *
 * interally handled as this:   to this:
 *                              
 * +--+                         +----+ we need no shiftig, on masking
 * |**|                         |**  | and it is faster, 'cause the 
 * |**|                         |**  | conversion could be cached and is
 * +--+                         |    | out of the span-draw-inner-loop
 *                              |    |
 *                              +----+
 *
 * we can even remove all the shifting, if we put the warp-textures
 * in a 256*64 block, so the offset is 0x0000xxyy (0b000000000000000000xxxxxx00yyyyyy)
 * that is a 16k-block per watertexture, not too much
 *
 * probably it could be faster, if we call a hook defined in the TextureCache
 */

#ifndef NOASM
#ifdef DRIVER_8BIT
#include "drawSpans8-m68k2.S"
#include "drawSpans8flat-m68k2.S"
#include "drawSpans8wire-m68k2.S"
#endif
#ifdef DRIVER_16BIT
#include "drawSpans16-m68k2.S"
#endif
#ifdef DRIVER_24BIT
#include "drawSpans24-m68k2.S"
#endif
#ifdef DRIVER_32BIT
#include "drawSpans32-m68k2.S"
#endif
#else
#ifdef DRIVER_8BIT
#include "draw-opti8.c"
#include "draw-opti8flat.c"
#include "draw-opti8wire.c"
#endif
#ifdef DRIVER_16BIT
#include "draw-opti16.c"
#endif
#ifdef DRIVER_24BIT
#include "draw-opti24.c"
#endif
#ifdef DRIVER_32BIT
#endif
#endif

/* preparing */
static inline void scan_convert(point_3d * a, point_3d * b)
{
  int right;
  fix x, dx;
  int y, ey;

  if (a->sy == b->sy)
    return;

  if (a->sy < b->sy)
    right = 0;
  else {
    void *temp = a;

    a = b;
    b = temp;
    right = 1;
  }

  /* compute dxdy */
  dx = FLOAT_TO_INT(scalw((b->sx - a->sx), 16) / (b->sy - a->sy));	/* * 65536.0 */
  x = a->sx;
  y = FIX_INT(a->sy);
  ey = FIX_INT(b->sy);
  x += FLOAT_TO_INT(((double)dx * ((y << 16) - a->sy)) * (1 / 65534.0));

  while (y < ey) {
    scan[y][right] = FIX_INT(x);
    x += dx;
    ++y;
  }
}
