[PATCH] Move model.c to common directory

diff -urN -X exclude a/NQ/model.c head/NQ/model.c
--- a/NQ/model.c	2006-06-10 20:33:47.000000000 +0930
+++ head/NQ/model.c	1970-01-01 09:30:00.000000000 +0930
@@ -1,1847 +0,0 @@
-/*
-Copyright (C) 1996-1997 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-*/
-// models.c -- model loading and caching
-
-// models are the only shared resource between a client and server running
-// on the same machine.
-
-#include <stdint.h>
-
-#include "console.h"
-#include "quakedef.h"
-#include "r_local.h"
-#include "sys.h"
-
-#ifdef QW_HACK
-#include "crc.h"
-#endif
-
-model_t *loadmodel;
-char loadname[32];		// for hunk tags
-
-void Mod_LoadSpriteModel(model_t *mod, void *buffer);
-void Mod_LoadBrushModel(model_t *mod, void *buffer);
-void Mod_LoadAliasModel(model_t *mod, void *buffer);
-model_t *Mod_LoadModel(model_t *mod, qboolean crash);
-
-byte mod_novis[MAX_MAP_LEAFS / 8];
-
-#define	MAX_MOD_KNOWN	256
-model_t mod_known[MAX_MOD_KNOWN];
-int mod_numknown;
-
-/*
-===============
-Mod_Init
-===============
-*/
-void
-Mod_Init(void)
-{
-    memset(mod_novis, 0xff, sizeof(mod_novis));
-}
-
-/*
-===============
-Mod_Extradata
-
-Caches the data if needed
-===============
-*/
-void *
-Mod_Extradata(model_t *mod)
-{
-    void *r;
-
-    r = Cache_Check(&mod->cache);
-    if (r)
-	return r;
-
-    Mod_LoadModel(mod, true);
-
-    if (!mod->cache.data)
-	Sys_Error("%s: caching failed", __func__);
-    return mod->cache.data;
-}
-
-/*
-===============
-Mod_PointInLeaf
-===============
-*/
-mleaf_t *
-Mod_PointInLeaf(vec3_t p, model_t *model)
-{
-    mnode_t *node;
-    float d;
-    mplane_t *plane;
-
-    if (!model || !model->nodes)
-	Sys_Error("%s: bad model", __func__);
-
-    node = model->nodes;
-    while (1) {
-	if (node->contents < 0)
-	    return (mleaf_t *)node;
-	plane = node->plane;
-	d = DotProduct(p, plane->normal) - plane->dist;
-	if (d > 0)
-	    node = node->children[0];
-	else
-	    node = node->children[1];
-    }
-
-    return NULL;		// never reached
-}
-
-
-/*
-===================
-Mod_DecompressVis
-===================
-*/
-byte *
-Mod_DecompressVis(byte *in, model_t *model)
-{
-    static byte decompressed[MAX_MAP_LEAFS / 8];
-    int c;
-    byte *out;
-    int row;
-
-    row = (model->numleafs + 7) >> 3;
-    out = decompressed;
-
-    if (!in) {			// no vis info, so make all visible
-	while (row) {
-	    *out++ = 0xff;
-	    row--;
-	}
-	return decompressed;
-    }
-
-    do {
-	if (*in) {
-	    *out++ = *in++;
-	    continue;
-	}
-
-	c = in[1];
-	in += 2;
-	while (c) {
-	    *out++ = 0;
-	    c--;
-	}
-    } while (out - decompressed < row);
-
-    return decompressed;
-}
-
-byte *
-Mod_LeafPVS(mleaf_t *leaf, model_t *model)
-{
-    if (leaf == model->leafs)
-	return mod_novis;
-    return Mod_DecompressVis(leaf->compressed_vis, model);
-}
-
-/*
-===================
-Mod_ClearAll
-===================
-*/
-void
-Mod_ClearAll(void)
-{
-    int i;
-    model_t *mod;
-
-    for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++)
-	if (mod->type != mod_alias)
-	    mod->needload = true;
-}
-
-/*
-==================
-Mod_FindName
-
-==================
-*/
-model_t *
-Mod_FindName(char *name)
-{
-    int i;
-    model_t *mod;
-
-    if (!name[0])
-	Sys_Error("%s: NULL name", __func__);
-
-//
-// search the currently loaded models
-//
-    for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++)
-	if (!strcmp(mod->name, name))
-	    break;
-
-    if (i == mod_numknown) {
-	if (mod_numknown == MAX_MOD_KNOWN)
-	    Sys_Error("mod_numknown == MAX_MOD_KNOWN");
-	strcpy(mod->name, name);
-	mod->needload = true;
-	mod_numknown++;
-    }
-
-    return mod;
-}
-
-/*
-==================
-Mod_TouchModel
-
-==================
-*/
-void
-Mod_TouchModel(char *name)
-{
-    model_t *mod;
-
-    mod = Mod_FindName(name);
-
-    if (!mod->needload) {
-	if (mod->type == mod_alias)
-	    Cache_Check(&mod->cache);
-    }
-}
-
-/*
-==================
-Mod_LoadModel
-
-Loads a model into the cache
-==================
-*/
-model_t *
-Mod_LoadModel(model_t *mod, qboolean crash)
-{
-    unsigned *buf;
-    byte stackbuf[1024];	// avoid dirtying the cache heap
-
-    if (!mod->needload) {
-	if (mod->type == mod_alias) {
-	    if (Cache_Check(&mod->cache))
-		return mod;
-	} else
-	    return mod;		// not cached at all
-    }
-
-//
-// because the world is so huge, load it one piece at a time
-//
-
-//
-// load the file
-//
-    buf = (unsigned *)COM_LoadStackFile(mod->name, stackbuf, sizeof(stackbuf),
-					NULL);
-    if (!buf) {
-	if (crash)
-	    Sys_Error("%s: %s not found", __func__, mod->name);
-	return NULL;
-    }
-//
-// allocate a new model
-//
-    COM_FileBase(mod->name, loadname);
-
-    loadmodel = mod;
-
-//
-// fill it in
-//
-
-// call the apropriate loader
-    mod->needload = false;
-
-    switch (LittleLong(*(unsigned *)buf)) {
-    case IDPOLYHEADER:
-	Mod_LoadAliasModel(mod, buf);
-	break;
-
-    case IDSPRITEHEADER:
-	Mod_LoadSpriteModel(mod, buf);
-	break;
-
-    default:
-	Mod_LoadBrushModel(mod, buf);
-	break;
-    }
-
-    return mod;
-}
-
-/*
-==================
-Mod_ForName
-
-Loads in a model for the given name
-==================
-*/
-model_t *
-Mod_ForName(char *name, qboolean crash)
-{
-    model_t *mod;
-
-    mod = Mod_FindName(name);
-
-    return Mod_LoadModel(mod, crash);
-}
-
-
-/*
-===============================================================================
-
-					BRUSHMODEL LOADING
-
-===============================================================================
-*/
-
-byte *mod_base;
-
-
-/*
-=================
-Mod_LoadTextures
-=================
-*/
-void
-Mod_LoadTextures(lump_t *l)
-{
-    int i, j, pixels, num, max, altmax;
-    miptex_t *mt;
-    texture_t *tx, *tx2;
-    texture_t *anims[10];
-    texture_t *altanims[10];
-    dmiptexlump_t *m;
-
-    if (!l->filelen) {
-	loadmodel->textures = NULL;
-	return;
-    }
-    m = (dmiptexlump_t *)(mod_base + l->fileofs);
-
-    m->nummiptex = LittleLong(m->nummiptex);
-
-    loadmodel->numtextures = m->nummiptex;
-    loadmodel->textures =
-	Hunk_AllocName(m->nummiptex * sizeof(*loadmodel->textures), loadname);
-
-    for (i = 0; i < m->nummiptex; i++) {
-	m->dataofs[i] = LittleLong(m->dataofs[i]);
-	if (m->dataofs[i] == -1)
-	    continue;
-	mt = (miptex_t *)((byte *)m + m->dataofs[i]);
-	mt->width = (uint32_t)LittleLong(mt->width);
-	mt->height = (uint32_t)LittleLong(mt->height);
-	for (j = 0; j < MIPLEVELS; j++)
-	    mt->offsets[j] = (uint32_t)LittleLong(mt->offsets[j]);
-
-	if ((mt->width & 15) || (mt->height & 15))
-	    Sys_Error("Texture %s is not 16 aligned", mt->name);
-	pixels = mt->width * mt->height / 64 * 85;
-	tx = Hunk_AllocName(sizeof(texture_t) + pixels, loadname);
-	loadmodel->textures[i] = tx;
-
-	memcpy(tx->name, mt->name, sizeof(tx->name));
-	tx->width = mt->width;
-	tx->height = mt->height;
-	for (j = 0; j < MIPLEVELS; j++)
-	    tx->offsets[j] =
-		mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
-	// the pixels immediately follow the structures
-	memcpy(tx + 1, mt + 1, pixels);
-
-	if (!strncmp(mt->name, "sky", 3))
-	    R_InitSky(tx);
-    }
-
-//
-// sequence the animations
-//
-    for (i = 0; i < m->nummiptex; i++) {
-	tx = loadmodel->textures[i];
-	if (!tx || tx->name[0] != '+')
-	    continue;
-	if (tx->anim_next)
-	    continue;		// allready sequenced
-
-	// find the number of frames in the animation
-	memset(anims, 0, sizeof(anims));
-	memset(altanims, 0, sizeof(altanims));
-
-	max = tx->name[1];
-	altmax = 0;
-	if (max >= 'a' && max <= 'z')
-	    max -= 'a' - 'A';
-	if (max >= '0' && max <= '9') {
-	    max -= '0';
-	    altmax = 0;
-	    anims[max] = tx;
-	    max++;
-	} else if (max >= 'A' && max <= 'J') {
-	    altmax = max - 'A';
-	    max = 0;
-	    altanims[altmax] = tx;
-	    altmax++;
-	} else
-	    Sys_Error("Bad animating texture %s", tx->name);
-
-	for (j = i + 1; j < m->nummiptex; j++) {
-	    tx2 = loadmodel->textures[j];
-	    if (!tx2 || tx2->name[0] != '+')
-		continue;
-	    if (strcmp(tx2->name + 2, tx->name + 2))
-		continue;
-
-	    num = tx2->name[1];
-	    if (num >= 'a' && num <= 'z')
-		num -= 'a' - 'A';
-	    if (num >= '0' && num <= '9') {
-		num -= '0';
-		anims[num] = tx2;
-		if (num + 1 > max)
-		    max = num + 1;
-	    } else if (num >= 'A' && num <= 'J') {
-		num = num - 'A';
-		altanims[num] = tx2;
-		if (num + 1 > altmax)
-		    altmax = num + 1;
-	    } else
-		Sys_Error("Bad animating texture %s", tx->name);
-	}
-
-#define	ANIM_CYCLE	2
-	// link them all together
-	for (j = 0; j < max; j++) {
-	    tx2 = anims[j];
-	    if (!tx2)
-		Sys_Error("Missing frame %i of %s", j, tx->name);
-	    tx2->anim_total = max * ANIM_CYCLE;
-	    tx2->anim_min = j * ANIM_CYCLE;
-	    tx2->anim_max = (j + 1) * ANIM_CYCLE;
-	    tx2->anim_next = anims[(j + 1) % max];
-	    if (altmax)
-		tx2->alternate_anims = altanims[0];
-	}
-	for (j = 0; j < altmax; j++) {
-	    tx2 = altanims[j];
-	    if (!tx2)
-		Sys_Error("Missing frame %i of %s", j, tx->name);
-	    tx2->anim_total = altmax * ANIM_CYCLE;
-	    tx2->anim_min = j * ANIM_CYCLE;
-	    tx2->anim_max = (j + 1) * ANIM_CYCLE;
-	    tx2->anim_next = altanims[(j + 1) % altmax];
-	    if (max)
-		tx2->alternate_anims = anims[0];
-	}
-    }
-}
-
-/*
-=================
-Mod_LoadLighting
-=================
-*/
-void
-Mod_LoadLighting(lump_t *l)
-{
-    if (!l->filelen) {
-	loadmodel->lightdata = NULL;
-	return;
-    }
-    loadmodel->lightdata = Hunk_AllocName(l->filelen, loadname);
-    memcpy(loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
-}
-
-
-/*
-=================
-Mod_LoadVisibility
-=================
-*/
-void
-Mod_LoadVisibility(lump_t *l)
-{
-    if (!l->filelen) {
-	loadmodel->visdata = NULL;
-	return;
-    }
-    loadmodel->visdata = Hunk_AllocName(l->filelen, loadname);
-    memcpy(loadmodel->visdata, mod_base + l->fileofs, l->filelen);
-}
-
-
-/*
-=================
-Mod_LoadEntities
-=================
-*/
-void
-Mod_LoadEntities(lump_t *l)
-{
-    if (!l->filelen) {
-	loadmodel->entities = NULL;
-	return;
-    }
-    loadmodel->entities = Hunk_AllocName(l->filelen, loadname);
-    memcpy(loadmodel->entities, mod_base + l->fileofs, l->filelen);
-}
-
-
-/*
-=================
-Mod_LoadVertexes
-=================
-*/
-void
-Mod_LoadVertexes(lump_t *l)
-{
-    dvertex_t *in;
-    mvertex_t *out;
-    int i, count;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->vertexes = out;
-    loadmodel->numvertexes = count;
-
-    for (i = 0; i < count; i++, in++, out++) {
-	out->position[0] = LittleFloat(in->point[0]);
-	out->position[1] = LittleFloat(in->point[1]);
-	out->position[2] = LittleFloat(in->point[2]);
-    }
-}
-
-/*
-=================
-Mod_LoadSubmodels
-=================
-*/
-void
-Mod_LoadSubmodels(lump_t *l)
-{
-    dmodel_t *in;
-    dmodel_t *out;
-    int i, j, count;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->submodels = out;
-    loadmodel->numsubmodels = count;
-
-    for (i = 0; i < count; i++, in++, out++) {
-	for (j = 0; j < 3; j++) {	// spread the mins / maxs by a pixel
-	    out->mins[j] = LittleFloat(in->mins[j]) - 1;
-	    out->maxs[j] = LittleFloat(in->maxs[j]) + 1;
-	    out->origin[j] = LittleFloat(in->origin[j]);
-	}
-	for (j = 0; j < MAX_MAP_HULLS; j++)
-	    out->headnode[j] = LittleLong(in->headnode[j]);
-	out->visleafs = LittleLong(in->visleafs);
-	out->firstface = LittleLong(in->firstface);
-	out->numfaces = LittleLong(in->numfaces);
-    }
-}
-
-/*
-=================
-Mod_LoadEdges
-=================
-*/
-void
-Mod_LoadEdges(lump_t *l)
-{
-    dedge_t *in;
-    medge_t *out;
-    int i, count;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName((count + 1) * sizeof(*out), loadname);
-
-    loadmodel->edges = out;
-    loadmodel->numedges = count;
-
-    for (i = 0; i < count; i++, in++, out++) {
-	out->v[0] = (uint16_t)LittleShort(in->v[0]);
-	out->v[1] = (uint16_t)LittleShort(in->v[1]);
-    }
-}
-
-/*
-=================
-Mod_LoadTexinfo
-=================
-*/
-void
-Mod_LoadTexinfo(lump_t *l)
-{
-    texinfo_t *in;
-    mtexinfo_t *out;
-    int i, j, count;
-    int miptex;
-    float len1, len2;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->texinfo = out;
-    loadmodel->numtexinfo = count;
-
-    for (i = 0; i < count; i++, in++, out++) {
-	for (j = 0; j < 8; j++)
-	    out->vecs[0][j] = LittleFloat(in->vecs[0][j]);
-	len1 = Length(out->vecs[0]);
-	len2 = Length(out->vecs[1]);
-	len1 = (len1 + len2) / 2;
-	if (len1 < 0.32)
-	    out->mipadjust = 4;
-	else if (len1 < 0.49)
-	    out->mipadjust = 3;
-	else if (len1 < 0.99)
-	    out->mipadjust = 2;
-	else
-	    out->mipadjust = 1;
-#if 0
-	if (len1 + len2 < 0.001)
-	    out->mipadjust = 1;	// don't crash
-	else
-	    out->mipadjust = 1 / floor((len1 + len2) / 2 + 0.1);
-#endif
-
-	miptex = LittleLong(in->miptex);
-	out->flags = LittleLong(in->flags);
-
-	if (!loadmodel->textures) {
-	    out->texture = r_notexture_mip;	// checkerboard texture
-	    out->flags = 0;
-	} else {
-	    if (miptex >= loadmodel->numtextures)
-		Sys_Error("miptex >= loadmodel->numtextures");
-	    out->texture = loadmodel->textures[miptex];
-	    if (!out->texture) {
-		out->texture = r_notexture_mip;	// texture not found
-		out->flags = 0;
-	    }
-	}
-    }
-}
-
-/*
-================
-CalcSurfaceExtents
-
-Fills in s->texturemins[] and s->extents[]
-================
-*/
-void
-CalcSurfaceExtents(msurface_t *s)
-{
-    float mins[2], maxs[2], val;
-    int i, j, e;
-    mvertex_t *v;
-    mtexinfo_t *tex;
-    int bmins[2], bmaxs[2];
-
-    mins[0] = mins[1] = 999999;
-    maxs[0] = maxs[1] = -99999;
-
-    tex = s->texinfo;
-
-    for (i = 0; i < s->numedges; i++) {
-	e = loadmodel->surfedges[s->firstedge + i];
-	if (e >= 0)
-	    v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
-	else
-	    v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
-
-	for (j = 0; j < 2; j++) {
-	    val = v->position[0] * tex->vecs[j][0] +
-		v->position[1] * tex->vecs[j][1] +
-		v->position[2] * tex->vecs[j][2] + tex->vecs[j][3];
-	    if (val < mins[j])
-		mins[j] = val;
-	    if (val > maxs[j])
-		maxs[j] = val;
-	}
-    }
-
-    for (i = 0; i < 2; i++) {
-	bmins[i] = floor(mins[i] / 16);
-	bmaxs[i] = ceil(maxs[i] / 16);
-
-	s->texturemins[i] = bmins[i] * 16;
-	s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
-	if (!(tex->flags & TEX_SPECIAL) && s->extents[i] > 256)
-	    Sys_Error("Bad surface extents");
-    }
-}
-
-
-/*
-=================
-Mod_LoadFaces
-=================
-*/
-void
-Mod_LoadFaces(lump_t *l)
-{
-    dface_t *in;
-    msurface_t *out;
-    int i, count, surfnum;
-    int planenum, side;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->surfaces = out;
-    loadmodel->numsurfaces = count;
-
-    for (surfnum = 0; surfnum < count; surfnum++, in++, out++) {
-	out->firstedge = LittleLong(in->firstedge);
-	out->numedges = LittleShort(in->numedges);
-	out->flags = 0;
-
-	planenum = LittleShort(in->planenum);
-	side = LittleShort(in->side);
-	if (side)
-	    out->flags |= SURF_PLANEBACK;
-
-	out->plane = loadmodel->planes + planenum;
-
-	out->texinfo = loadmodel->texinfo + LittleShort(in->texinfo);
-
-	CalcSurfaceExtents(out);
-
-	// lighting info
-
-	for (i = 0; i < MAXLIGHTMAPS; i++)
-	    out->styles[i] = in->styles[i];
-	i = LittleLong(in->lightofs);
-	if (i == -1)
-	    out->samples = NULL;
-	else
-	    out->samples = loadmodel->lightdata + i;
-
-	// set the drawing flags flag
-
-	if (!strncmp(out->texinfo->texture->name, "sky", 3))	// sky
-	{
-	    out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
-	    continue;
-	}
-
-	if (!strncmp(out->texinfo->texture->name, "*", 1))	// turbulent
-	{
-	    out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
-	    for (i = 0; i < 2; i++) {
-		out->extents[i] = 16384;
-		out->texturemins[i] = -8192;
-	    }
-	    continue;
-	}
-    }
-}
-
-
-/*
-=================
-Mod_SetParent
-=================
-*/
-void
-Mod_SetParent(mnode_t *node, mnode_t *parent)
-{
-    node->parent = parent;
-    if (node->contents < 0)
-	return;
-    Mod_SetParent(node->children[0], node);
-    Mod_SetParent(node->children[1], node);
-}
-
-/*
-=================
-Mod_LoadNodes
-=================
-*/
-void
-Mod_LoadNodes(lump_t *l)
-{
-    int i, j, count, p;
-    dnode_t *in;
-    mnode_t *out;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->nodes = out;
-    loadmodel->numnodes = count;
-
-    for (i = 0; i < count; i++, in++, out++) {
-	for (j = 0; j < 3; j++) {
-	    out->minmaxs[j] = LittleShort(in->mins[j]);
-	    out->minmaxs[3 + j] = LittleShort(in->maxs[j]);
-	}
-
-	p = LittleLong(in->planenum);
-	out->plane = loadmodel->planes + p;
-
-	out->firstsurface = (uint16_t)LittleShort(in->firstface);
-	out->numsurfaces = (uint16_t)LittleShort(in->numfaces);
-
-	for (j = 0; j < 2; j++) {
-	    p = LittleShort(in->children[j]);
-	    if (p >= 0)
-		out->children[j] = loadmodel->nodes + p;
-	    else
-		out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
-	}
-    }
-
-    Mod_SetParent(loadmodel->nodes, NULL);	// sets nodes and leafs
-}
-
-/*
-=================
-Mod_LoadLeafs
-=================
-*/
-void
-Mod_LoadLeafs(lump_t *l)
-{
-    dleaf_t *in;
-    mleaf_t *out;
-    int i, j, count, p;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-
-    /* FIXME - fail gracefully */
-    if (count > MAX_MAP_LEAFS)
-	Sys_Error("%s: model->numleafs > MAX_MAP_LEAFS\n", __func__);
-
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->leafs = out;
-    loadmodel->numleafs = count;
-
-    for (i = 0; i < count; i++, in++, out++) {
-	for (j = 0; j < 3; j++) {
-	    out->minmaxs[j] = LittleShort(in->mins[j]);
-	    out->minmaxs[3 + j] = LittleShort(in->maxs[j]);
-	}
-
-	p = LittleLong(in->contents);
-	out->contents = p;
-
-	out->firstmarksurface = loadmodel->marksurfaces +
-	    (uint16_t)LittleShort(in->firstmarksurface);
-	out->nummarksurfaces =
-	    (uint16_t)LittleShort(in->nummarksurfaces);
-
-	p = LittleLong(in->visofs);
-	if (p == -1)
-	    out->compressed_vis = NULL;
-	else
-	    out->compressed_vis = loadmodel->visdata + p;
-	out->efrags = NULL;
-
-	for (j = 0; j < 4; j++)
-	    out->ambient_sound_level[j] = in->ambient_level[j];
-    }
-}
-
-/*
-=================
-Mod_LoadClipnodes
-=================
-*/
-void
-Mod_LoadClipnodes(lump_t *l)
-{
-    dclipnode_t *in, *out;
-    int i, count;
-    hull_t *hull;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->clipnodes = out;
-    loadmodel->numclipnodes = count;
-
-    hull = &loadmodel->hulls[1];
-    hull->clipnodes = out;
-    hull->firstclipnode = 0;
-    hull->lastclipnode = count - 1;
-    hull->planes = loadmodel->planes;
-    hull->clip_mins[0] = -16;
-    hull->clip_mins[1] = -16;
-    hull->clip_mins[2] = -24;
-    hull->clip_maxs[0] = 16;
-    hull->clip_maxs[1] = 16;
-    hull->clip_maxs[2] = 32;
-
-    hull = &loadmodel->hulls[2];
-    hull->clipnodes = out;
-    hull->firstclipnode = 0;
-    hull->lastclipnode = count - 1;
-    hull->planes = loadmodel->planes;
-    hull->clip_mins[0] = -32;
-    hull->clip_mins[1] = -32;
-    hull->clip_mins[2] = -24;
-    hull->clip_maxs[0] = 32;
-    hull->clip_maxs[1] = 32;
-    hull->clip_maxs[2] = 64;
-
-    for (i = 0; i < count; i++, out++, in++) {
-	out->planenum = LittleLong(in->planenum);
-	out->children[0] = LittleShort(in->children[0]);
-	out->children[1] = LittleShort(in->children[1]);
-    }
-}
-
-/*
-=================
-Mod_MakeHull0
-
-Duplicate the drawing hull structure as a clipping hull
-=================
-*/
-void
-Mod_MakeHull0(void)
-{
-    mnode_t *in, *child;
-    dclipnode_t *out;
-    int i, j, count;
-    hull_t *hull;
-
-    hull = &loadmodel->hulls[0];
-
-    in = loadmodel->nodes;
-    count = loadmodel->numnodes;
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    hull->clipnodes = out;
-    hull->firstclipnode = 0;
-    hull->lastclipnode = count - 1;
-    hull->planes = loadmodel->planes;
-
-    for (i = 0; i < count; i++, out++, in++) {
-	out->planenum = in->plane - loadmodel->planes;
-	for (j = 0; j < 2; j++) {
-	    child = in->children[j];
-	    if (child->contents < 0)
-		out->children[j] = child->contents;
-	    else
-		out->children[j] = child - loadmodel->nodes;
-	}
-    }
-}
-
-/*
-=================
-Mod_LoadMarksurfaces
-=================
-*/
-void
-Mod_LoadMarksurfaces(lump_t *l)
-{
-    int i, j, count;
-    unsigned short *in;
-    msurface_t **out;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->marksurfaces = out;
-    loadmodel->nummarksurfaces = count;
-
-    for (i = 0; i < count; i++) {
-	j = (uint16_t)LittleShort(in[i]);
-	if (j >= loadmodel->numsurfaces)
-	    Sys_Error("%s: bad surface number", __func__);
-	out[i] = loadmodel->surfaces + j;
-    }
-}
-
-/*
-=================
-Mod_LoadSurfedges
-=================
-*/
-void
-Mod_LoadSurfedges(lump_t *l)
-{
-    int i, count;
-    int *in, *out;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->surfedges = out;
-    loadmodel->numsurfedges = count;
-
-    for (i = 0; i < count; i++)
-	out[i] = LittleLong(in[i]);
-}
-
-/*
-=================
-Mod_LoadPlanes
-=================
-*/
-void
-Mod_LoadPlanes(lump_t *l)
-{
-    int i, j;
-    mplane_t *out;
-    dplane_t *in;
-    int count;
-    int bits;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * 2 * sizeof(*out), loadname);
-
-    loadmodel->planes = out;
-    loadmodel->numplanes = count;
-
-    for (i = 0; i < count; i++, in++, out++) {
-	bits = 0;
-	for (j = 0; j < 3; j++) {
-	    out->normal[j] = LittleFloat(in->normal[j]);
-	    if (out->normal[j] < 0)
-		bits |= 1 << j;
-	}
-
-	out->dist = LittleFloat(in->dist);
-	out->type = LittleLong(in->type);
-	out->signbits = bits;
-    }
-}
-
-/*
-=================
-RadiusFromBounds
-=================
-*/
-float
-RadiusFromBounds(vec3_t mins, vec3_t maxs)
-{
-    int i;
-    vec3_t corner;
-
-    for (i = 0; i < 3; i++) {
-	corner[i] =
-	    fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
-    }
-
-    return Length(corner);
-}
-
-/*
-=================
-Mod_LoadBrushModel
-=================
-*/
-void
-Mod_LoadBrushModel(model_t *mod, void *buffer)
-{
-    int i, j;
-    dheader_t *header;
-    dmodel_t *bm;
-
-    loadmodel->type = mod_brush;
-
-    header = (dheader_t *)buffer;
-
-    i = LittleLong(header->version);
-    if (i != BSPVERSION)
-	Sys_Error("%s: %s has wrong version number (%i should be %i)",
-		  __func__, mod->name, i, BSPVERSION);
-
-// swap all the lumps
-    mod_base = (byte *)header;
-
-    for (i = 0; i < sizeof(dheader_t) / 4; i++)
-	((int *)header)[i] = LittleLong(((int *)header)[i]);
-
-#ifdef QW_HACK
-    mod->checksum = 0;
-    mod->checksum2 = 0;
-
-// checksum all of the map, except for entities
-    for (i = 0; i < HEADER_LUMPS; i++) {
-	if (i == LUMP_ENTITIES)
-	    continue;
-	mod->checksum ^=
-	    Com_BlockChecksum(mod_base + header->lumps[i].fileofs,
-			      header->lumps[i].filelen);
-
-	if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES)
-	    continue;
-	mod->checksum2 ^=
-	    Com_BlockChecksum(mod_base + header->lumps[i].fileofs,
-			      header->lumps[i].filelen);
-    }
-#endif
-
-// load into heap
-
-    Mod_LoadVertexes(&header->lumps[LUMP_VERTEXES]);
-    Mod_LoadEdges(&header->lumps[LUMP_EDGES]);
-    Mod_LoadSurfedges(&header->lumps[LUMP_SURFEDGES]);
-    Mod_LoadTextures(&header->lumps[LUMP_TEXTURES]);
-    Mod_LoadLighting(&header->lumps[LUMP_LIGHTING]);
-    Mod_LoadPlanes(&header->lumps[LUMP_PLANES]);
-    Mod_LoadTexinfo(&header->lumps[LUMP_TEXINFO]);
-    Mod_LoadFaces(&header->lumps[LUMP_FACES]);
-    Mod_LoadMarksurfaces(&header->lumps[LUMP_MARKSURFACES]);
-    Mod_LoadVisibility(&header->lumps[LUMP_VISIBILITY]);
-    Mod_LoadLeafs(&header->lumps[LUMP_LEAFS]);
-    Mod_LoadNodes(&header->lumps[LUMP_NODES]);
-    Mod_LoadClipnodes(&header->lumps[LUMP_CLIPNODES]);
-    Mod_LoadEntities(&header->lumps[LUMP_ENTITIES]);
-    Mod_LoadSubmodels(&header->lumps[LUMP_MODELS]);
-
-    Mod_MakeHull0();
-
-    mod->numframes = 2;		// regular and alternate animation
-    mod->flags = 0;
-
-//
-// set up the submodels (FIXME: this is confusing)
-//
-    for (i = 0; i < mod->numsubmodels; i++) {
-	bm = &mod->submodels[i];
-
-	mod->hulls[0].firstclipnode = bm->headnode[0];
-	for (j = 1; j < MAX_MAP_HULLS; j++) {
-	    mod->hulls[j].firstclipnode = bm->headnode[j];
-	    mod->hulls[j].lastclipnode = mod->numclipnodes - 1;
-	}
-
-	mod->firstmodelsurface = bm->firstface;
-	mod->nummodelsurfaces = bm->numfaces;
-	mod->radius = RadiusFromBounds(mod->mins, mod->maxs);
-
-	VectorCopy(bm->maxs, mod->maxs);
-	VectorCopy(bm->mins, mod->mins);
-
-	mod->numleafs = bm->visleafs;
-
-	/* duplicate the basic information */
-	if (i < mod->numsubmodels - 1) {
-	    char name[10];
-
-	    sprintf(name, "*%i", i + 1);
-	    loadmodel = Mod_FindName(name);
-	    *loadmodel = *mod;
-	    strcpy(loadmodel->name, name);
-	    mod = loadmodel;
-	}
-    }
-}
-
-/*
-==============================================================================
-
-ALIAS MODELS
-
-==============================================================================
-*/
-
-/*
-=================
-Mod_LoadAliasFrame
-=================
-*/
-void *
-Mod_LoadAliasFrame(void *pin, int *pframeindex, int numv,
-		   trivertx_t *pbboxmin, trivertx_t *pbboxmax,
-		   aliashdr_t *pheader, char *name)
-{
-    trivertx_t *pframe, *pinframe;
-    int i, j;
-    daliasframe_t *pdaliasframe;
-
-    pdaliasframe = (daliasframe_t *)pin;
-
-    strcpy(name, pdaliasframe->name);
-
-    for (i = 0; i < 3; i++) {
-	// these are byte values, so we don't have to worry about
-	// endianness
-	pbboxmin->v[i] = pdaliasframe->bboxmin.v[i];
-	pbboxmax->v[i] = pdaliasframe->bboxmax.v[i];
-    }
-
-    pinframe = (trivertx_t *)(pdaliasframe + 1);
-    pframe = Hunk_AllocName(numv * sizeof(*pframe), loadname);
-
-    *pframeindex = (byte *)pframe - (byte *)pheader;
-
-    for (j = 0; j < numv; j++) {
-	int k;
-
-	// these are all byte values, so no need to deal with endianness
-	pframe[j].lightnormalindex = pinframe[j].lightnormalindex;
-
-	for (k = 0; k < 3; k++) {
-	    pframe[j].v[k] = pinframe[j].v[k];
-	}
-    }
-
-    pinframe += numv;
-
-    return (void *)pinframe;
-}
-
-
-/*
-=================
-Mod_LoadAliasGroup
-=================
-*/
-void *
-Mod_LoadAliasGroup(void *pin, int *pframeindex, int numv,
-		   trivertx_t *pbboxmin, trivertx_t *pbboxmax,
-		   aliashdr_t *pheader, char *name)
-{
-    daliasgroup_t *pingroup;
-    maliasgroup_t *paliasgroup;
-    int i, numframes;
-    daliasinterval_t *pin_intervals;
-    float *poutintervals;
-    void *ptemp;
-
-    pingroup = (daliasgroup_t *)pin;
-
-    numframes = LittleLong(pingroup->numframes);
-
-    paliasgroup = Hunk_AllocName(sizeof(maliasgroup_t) +
-				 (numframes -
-				  1) * sizeof(paliasgroup->frames[0]),
-				 loadname);
-
-    paliasgroup->numframes = numframes;
-
-    for (i = 0; i < 3; i++) {
-	// these are byte values, so we don't have to worry about endianness
-	pbboxmin->v[i] = pingroup->bboxmin.v[i];
-	pbboxmax->v[i] = pingroup->bboxmax.v[i];
-    }
-
-    *pframeindex = (byte *)paliasgroup - (byte *)pheader;
-
-    pin_intervals = (daliasinterval_t *)(pingroup + 1);
-
-    poutintervals = Hunk_AllocName(numframes * sizeof(float), loadname);
-
-    paliasgroup->intervals = (byte *)poutintervals - (byte *)pheader;
-
-    for (i = 0; i < numframes; i++) {
-	*poutintervals = LittleFloat(pin_intervals->interval);
-	if (*poutintervals <= 0.0)
-	    Sys_Error("%s: interval <= 0", __func__);
-
-	poutintervals++;
-	pin_intervals++;
-    }
-
-    ptemp = (void *)pin_intervals;
-
-    for (i = 0; i < numframes; i++) {
-	ptemp = Mod_LoadAliasFrame(ptemp,
-				   &paliasgroup->frames[i].frame,
-				   numv,
-				   &paliasgroup->frames[i].bboxmin,
-				   &paliasgroup->frames[i].bboxmax,
-				   pheader, name);
-    }
-
-    return ptemp;
-}
-
-
-/*
-=================
-Mod_LoadAliasSkin
-=================
-*/
-void *
-Mod_LoadAliasSkin(void *pin, int *pskinindex, int skinsize,
-		  aliashdr_t *pheader)
-{
-    int i;
-    byte *pskin, *pinskin;
-    unsigned short *pusskin;
-
-    pskin = Hunk_AllocName(skinsize * r_pixbytes, loadname);
-    pinskin = (byte *)pin;
-    *pskinindex = (byte *)pskin - (byte *)pheader;
-
-    if (r_pixbytes == 1) {
-	memcpy(pskin, pinskin, skinsize);
-    } else if (r_pixbytes == 2) {
-	pusskin = (unsigned short *)pskin;
-
-	for (i = 0; i < skinsize; i++)
-	    pusskin[i] = d_8to16table[pinskin[i]];
-    } else {
-	Sys_Error("%s: driver set invalid r_pixbytes: %d", __func__,
-		  r_pixbytes);
-    }
-
-    pinskin += skinsize;
-
-    return ((void *)pinskin);
-}
-
-
-/*
-=================
-Mod_LoadAliasSkinGroup
-=================
-*/
-void *
-Mod_LoadAliasSkinGroup(void *pin, int *pskinindex, int skinsize,
-		       aliashdr_t *pheader)
-{
-    daliasskingroup_t *pinskingroup;
-    maliasskingroup_t *paliasskingroup;
-    int i, numskins;
-    daliasskininterval_t *pinskinintervals;
-    float *poutskinintervals;
-    void *ptemp;
-
-    pinskingroup = (daliasskingroup_t *)pin;
-
-    numskins = LittleLong(pinskingroup->numskins);
-
-    paliasskingroup = Hunk_AllocName(sizeof(maliasskingroup_t) +
-				     (numskins -
-				      1) *
-				     sizeof(paliasskingroup->skindescs[0]),
-				     loadname);
-
-    paliasskingroup->numskins = numskins;
-
-    *pskinindex = (byte *)paliasskingroup - (byte *)pheader;
-    pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
-    poutskinintervals = Hunk_AllocName(numskins * sizeof(float), loadname);
-
-    paliasskingroup->intervals = (byte *)poutskinintervals - (byte *)pheader;
-
-    for (i = 0; i < numskins; i++) {
-	*poutskinintervals = LittleFloat(pinskinintervals->interval);
-	if (*poutskinintervals <= 0)
-	    Sys_Error("%s: interval <= 0", __func__);
-
-	poutskinintervals++;
-	pinskinintervals++;
-    }
-
-    ptemp = (void *)pinskinintervals;
-
-    for (i = 0; i < numskins; i++) {
-	ptemp = Mod_LoadAliasSkin(ptemp,
-				  &paliasskingroup->skindescs[i].skin,
-				  skinsize, pheader);
-    }
-
-    return ptemp;
-}
-
-
-/*
-=================
-Mod_LoadAliasModel
-=================
-*/
-void
-Mod_LoadAliasModel(model_t *mod, void *buffer)
-{
-    int i;
-    mdl_t *pmodel, *pinmodel;
-    stvert_t *pstverts, *pinstverts;
-    aliashdr_t *pheader;
-    mtriangle_t *ptri;
-    dtriangle_t *pintriangles;
-    int version, numframes, numskins;
-    int size;
-    daliasframetype_t *pframetype;
-    daliasskintype_t *pskintype;
-    maliasskindesc_t *pskindesc;
-    int skinsize;
-    int start, end, total;
-
-#ifdef QW_HACK
-    if (!strcmp(loadmodel->name, "progs/player.mdl") ||
-	!strcmp(loadmodel->name, "progs/eyes.mdl")) {
-	unsigned short crc;
-	byte *p;
-	int len;
-	char st[40];
-
-	CRC_Init(&crc);
-	for (len = com_filesize, p = buffer; len; len--, p++)
-	    CRC_ProcessByte(&crc, *p);
-
-	sprintf(st, "%d", (int)crc);
-	Info_SetValueForKey(cls.userinfo,
-			    !strcmp(loadmodel->name,
-				    "progs/player.mdl") ? pmodel_name :
-			    emodel_name, st, MAX_INFO_STRING);
-
-	if (cls.state >= ca_connected) {
-	    MSG_WriteByte(&cls.netchan.message, clc_stringcmd);
-	    sprintf(st, "setinfo %s %d",
-		    !strcmp(loadmodel->name,
-			    "progs/player.mdl") ? pmodel_name : emodel_name,
-		    (int)crc);
-	    SZ_Print(&cls.netchan.message, st);
-	}
-    }
-#endif
-
-    start = Hunk_LowMark();
-
-    pinmodel = (mdl_t *)buffer;
-
-    version = LittleLong(pinmodel->version);
-    if (version != ALIAS_VERSION)
-	Sys_Error("%s has wrong version number (%i should be %i)",
-		  mod->name, version, ALIAS_VERSION);
-
-//
-// allocate space for a working header, plus all the data except the frames,
-// skin and group info
-//
-    size = sizeof(aliashdr_t) + LittleLong(pinmodel->numframes) *
-	sizeof(pheader->frames[0]) +
-	sizeof(mdl_t) +
-	LittleLong(pinmodel->numverts) * sizeof(stvert_t) +
-	LittleLong(pinmodel->numtris) * sizeof(mtriangle_t);
-
-    pheader = Hunk_AllocName(size, loadname);
-    pmodel = (mdl_t *)((byte *)&pheader[1] +
-		       (LittleLong(pinmodel->numframes) - 1) *
-		       sizeof(pheader->frames[0]));
-
-    mod->flags = LittleLong(pinmodel->flags);
-
-//
-// endian-adjust and copy the data, starting with the alias model header
-//
-    pmodel->boundingradius = LittleFloat(pinmodel->boundingradius);
-    pmodel->numskins = LittleLong(pinmodel->numskins);
-    pmodel->skinwidth = LittleLong(pinmodel->skinwidth);
-    pmodel->skinheight = LittleLong(pinmodel->skinheight);
-
-    if (pmodel->skinheight > MAX_LBM_HEIGHT)
-	Sys_Error("model %s has a skin taller than %d", mod->name,
-		  MAX_LBM_HEIGHT);
-
-    pmodel->numverts = LittleLong(pinmodel->numverts);
-
-    if (pmodel->numverts <= 0)
-	Sys_Error("model %s has no vertices", mod->name);
-
-    if (pmodel->numverts > MAXALIASVERTS)
-	Sys_Error("model %s has too many vertices", mod->name);
-
-    pmodel->numtris = LittleLong(pinmodel->numtris);
-
-    if (pmodel->numtris <= 0)
-	Sys_Error("model %s has no triangles", mod->name);
-
-    pmodel->numframes = LittleLong(pinmodel->numframes);
-    pmodel->size = LittleFloat(pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
-    mod->synctype = LittleLong(pinmodel->synctype);
-    mod->numframes = pmodel->numframes;
-
-    for (i = 0; i < 3; i++) {
-	pmodel->scale[i] = LittleFloat(pinmodel->scale[i]);
-	pmodel->scale_origin[i] = LittleFloat(pinmodel->scale_origin[i]);
-	pmodel->eyeposition[i] = LittleFloat(pinmodel->eyeposition[i]);
-    }
-
-    numskins = pmodel->numskins;
-    numframes = pmodel->numframes;
-
-    if (pmodel->skinwidth & 0x03)
-	Sys_Error("%s: skinwidth not multiple of 4", __func__);
-
-    pheader->model = (byte *)pmodel - (byte *)pheader;
-
-//
-// load the skins
-//
-    skinsize = pmodel->skinheight * pmodel->skinwidth;
-
-    if (numskins < 1)
-	Sys_Error("%s: Invalid # of skins: %d", __func__, numskins);
-
-    pskintype = (daliasskintype_t *)&pinmodel[1];
-
-    pskindesc = Hunk_AllocName(numskins * sizeof(maliasskindesc_t), loadname);
-
-    pheader->skindesc = (byte *)pskindesc - (byte *)pheader;
-
-    for (i = 0; i < numskins; i++) {
-	aliasskintype_t skintype;
-
-	skintype = LittleLong(pskintype->type);
-	pskindesc[i].type = skintype;
-
-	if (skintype == ALIAS_SKIN_SINGLE) {
-	    pskintype = (daliasskintype_t *)
-		Mod_LoadAliasSkin(pskintype + 1,
-				  &pskindesc[i].skin, skinsize, pheader);
-	} else {
-	    pskintype = (daliasskintype_t *)
-		Mod_LoadAliasSkinGroup(pskintype + 1,
-				       &pskindesc[i].skin, skinsize, pheader);
-	}
-    }
-
-//
-// set base s and t vertices
-//
-    pstverts = (stvert_t *)&pmodel[1];
-    pinstverts = (stvert_t *)pskintype;
-
-    pheader->stverts = (byte *)pstverts - (byte *)pheader;
-
-    for (i = 0; i < pmodel->numverts; i++) {
-	pstverts[i].onseam = LittleLong(pinstverts[i].onseam);
-	// put s and t in 16.16 format
-	pstverts[i].s = LittleLong(pinstverts[i].s) << 16;
-	pstverts[i].t = LittleLong(pinstverts[i].t) << 16;
-    }
-
-//
-// set up the triangles
-//
-    ptri = (mtriangle_t *)&pstverts[pmodel->numverts];
-    pintriangles = (dtriangle_t *)&pinstverts[pmodel->numverts];
-
-    pheader->triangles = (byte *)ptri - (byte *)pheader;
-
-    for (i = 0; i < pmodel->numtris; i++) {
-	int j;
-
-	ptri[i].facesfront = LittleLong(pintriangles[i].facesfront);
-
-	for (j = 0; j < 3; j++) {
-	    ptri[i].vertindex[j] = LittleLong(pintriangles[i].vertindex[j]);
-	}
-    }
-
-//
-// load the frames
-//
-    if (numframes < 1)
-	Sys_Error("%s: Invalid # of frames: %d", __func__, numframes);
-
-    pframetype = (daliasframetype_t *)&pintriangles[pmodel->numtris];
-
-    for (i = 0; i < numframes; i++) {
-	aliasframetype_t frametype;
-
-	frametype = LittleLong(pframetype->type);
-	pheader->frames[i].type = frametype;
-
-	if (frametype == ALIAS_SINGLE) {
-	    pframetype = (daliasframetype_t *)
-		Mod_LoadAliasFrame(pframetype + 1,
-				   &pheader->frames[i].frame,
-				   pmodel->numverts,
-				   &pheader->frames[i].bboxmin,
-				   &pheader->frames[i].bboxmax,
-				   pheader, pheader->frames[i].name);
-	} else {
-	    pframetype = (daliasframetype_t *)
-		Mod_LoadAliasGroup(pframetype + 1,
-				   &pheader->frames[i].frame,
-				   pmodel->numverts,
-				   &pheader->frames[i].bboxmin,
-				   &pheader->frames[i].bboxmax,
-				   pheader, pheader->frames[i].name);
-	}
-    }
-
-    mod->type = mod_alias;
-
-// FIXME: do this right
-    mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
-    mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
-
-//
-// move the complete, relocatable alias model to the cache
-//
-    end = Hunk_LowMark();
-    total = end - start;
-
-    Cache_Alloc(&mod->cache, total, loadname);
-    if (!mod->cache.data)
-	return;
-    memcpy(mod->cache.data, pheader, total);
-
-    Hunk_FreeToLowMark(start);
-}
-
-//=============================================================================
-
-/*
-=================
-Mod_LoadSpriteFrame
-=================
-*/
-void *
-Mod_LoadSpriteFrame(void *pin, mspriteframe_t **ppframe)
-{
-    dspriteframe_t *pinframe;
-    mspriteframe_t *pspriteframe;
-    int i, width, height, size, origin[2];
-    unsigned short *ppixout;
-    byte *ppixin;
-
-    pinframe = (dspriteframe_t *)pin;
-
-    width = LittleLong(pinframe->width);
-    height = LittleLong(pinframe->height);
-    size = width * height;
-
-    pspriteframe =
-	Hunk_AllocName(sizeof(mspriteframe_t) + size * r_pixbytes, loadname);
-
-    memset(pspriteframe, 0, sizeof(mspriteframe_t) + size);
-    *ppframe = pspriteframe;
-
-    pspriteframe->width = width;
-    pspriteframe->height = height;
-    origin[0] = LittleLong(pinframe->origin[0]);
-    origin[1] = LittleLong(pinframe->origin[1]);
-
-    pspriteframe->up = origin[1];
-    pspriteframe->down = origin[1] - height;
-    pspriteframe->left = origin[0];
-    pspriteframe->right = width + origin[0];
-
-    if (r_pixbytes == 1) {
-	memcpy(&pspriteframe->pixels[0], (byte *)(pinframe + 1), size);
-    } else if (r_pixbytes == 2) {
-	ppixin = (byte *)(pinframe + 1);
-	ppixout = (unsigned short *)&pspriteframe->pixels[0];
-
-	for (i = 0; i < size; i++)
-	    ppixout[i] = d_8to16table[ppixin[i]];
-    } else {
-	Sys_Error("%s: driver set invalid r_pixbytes: %d", __func__,
-		  r_pixbytes);
-    }
-
-    return (void *)((byte *)pinframe + sizeof(dspriteframe_t) + size);
-}
-
-
-/*
-=================
-Mod_LoadSpriteGroup
-=================
-*/
-void *
-Mod_LoadSpriteGroup(void *pin, mspriteframe_t **ppframe)
-{
-    dspritegroup_t *pingroup;
-    mspritegroup_t *pspritegroup;
-    int i, numframes;
-    dspriteinterval_t *pin_intervals;
-    float *poutintervals;
-    void *ptemp;
-
-    pingroup = (dspritegroup_t *)pin;
-
-    numframes = LittleLong(pingroup->numframes);
-
-    pspritegroup = Hunk_AllocName(sizeof(mspritegroup_t) +
-				  (numframes -
-				   1) * sizeof(pspritegroup->frames[0]),
-				  loadname);
-
-    pspritegroup->numframes = numframes;
-
-    *ppframe = (mspriteframe_t *)pspritegroup;
-
-    pin_intervals = (dspriteinterval_t *)(pingroup + 1);
-
-    poutintervals = Hunk_AllocName(numframes * sizeof(float), loadname);
-
-    pspritegroup->intervals = poutintervals;
-
-    for (i = 0; i < numframes; i++) {
-	*poutintervals = LittleFloat(pin_intervals->interval);
-	if (*poutintervals <= 0.0)
-	    Sys_Error("%s: interval <= 0", __func__);
-
-	poutintervals++;
-	pin_intervals++;
-    }
-
-    ptemp = (void *)pin_intervals;
-
-    for (i = 0; i < numframes; i++) {
-	ptemp = Mod_LoadSpriteFrame(ptemp, &pspritegroup->frames[i]);
-    }
-
-    return ptemp;
-}
-
-
-/*
-=================
-Mod_LoadSpriteModel
-=================
-*/
-void
-Mod_LoadSpriteModel(model_t *mod, void *buffer)
-{
-    int i;
-    int version;
-    dsprite_t *pin;
-    msprite_t *psprite;
-    int numframes;
-    int size;
-    dspriteframetype_t *pframetype;
-
-    pin = (dsprite_t *) buffer;
-
-    version = LittleLong(pin->version);
-    if (version != SPRITE_VERSION)
-	Sys_Error("%s has wrong version number "
-		  "(%i should be %i)", mod->name, version, SPRITE_VERSION);
-
-    numframes = LittleLong(pin->numframes);
-
-    size = sizeof(msprite_t) + (numframes - 1) * sizeof(psprite->frames);
-
-    psprite = Hunk_AllocName(size, loadname);
-    psprite->type = LittleLong(pin->type);
-    psprite->maxwidth = LittleLong(pin->width);
-    psprite->maxheight = LittleLong(pin->height);
-    psprite->beamlength = LittleFloat(pin->beamlength);
-    mod->synctype = LittleLong(pin->synctype);
-    psprite->numframes = numframes;
-
-    mod->mins[0] = mod->mins[1] = -psprite->maxwidth / 2;
-    mod->maxs[0] = mod->maxs[1] = psprite->maxwidth / 2;
-    mod->mins[2] = -psprite->maxheight / 2;
-    mod->maxs[2] = psprite->maxheight / 2;
-
-//
-// load the frames
-//
-    if (numframes < 1)
-	Sys_Error("%s: Invalid # of frames: %d", __func__, numframes);
-
-    mod->numframes = numframes;
-    mod->flags = 0;
-
-    pframetype = (dspriteframetype_t *) (pin + 1);
-
-    for (i = 0; i < numframes; i++) {
-	spriteframetype_t frametype;
-
-	frametype = LittleLong(pframetype->type);
-	psprite->frames[i].type = frametype;
-
-	if (frametype == SPR_SINGLE) {
-	    pframetype = (dspriteframetype_t *)
-		Mod_LoadSpriteFrame(pframetype + 1,
-				    &psprite->frames[i].frameptr);
-	} else {
-	    pframetype = (dspriteframetype_t *)
-		Mod_LoadSpriteGroup(pframetype + 1,
-				    &psprite->frames[i].frameptr);
-	}
-    }
-
-    mod->type = mod_sprite;
-}
-
-//=============================================================================
-
-/*
-================
-Mod_Print
-================
-*/
-void
-Mod_Print(void)
-{
-    int i;
-    model_t *mod;
-
-    Con_Printf("Cached models:\n");
-    for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++)
-	Con_Printf("%8p : %s\n", mod->cache.data, mod->name);
-}
diff -urN -X exclude a/QW/client/model.c head/QW/client/model.c
--- a/QW/client/model.c	2006-06-10 20:33:48.000000000 +0930
+++ head/QW/client/model.c	1970-01-01 09:30:00.000000000 +0930
@@ -1,1847 +0,0 @@
-/*
-Copyright (C) 1996-1997 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-*/
-// models.c -- model loading and caching
-
-// models are the only shared resource between a client and server running
-// on the same machine.
-
-#include <stdint.h>
-
-#include "console.h"
-#include "quakedef.h"
-#include "r_local.h"
-#include "sys.h"
-
-#ifdef QW_HACK
-#include "crc.h"
-#endif
-
-model_t *loadmodel;
-char loadname[32];		// for hunk tags
-
-void Mod_LoadSpriteModel(model_t *mod, void *buffer);
-void Mod_LoadBrushModel(model_t *mod, void *buffer);
-void Mod_LoadAliasModel(model_t *mod, void *buffer);
-model_t *Mod_LoadModel(model_t *mod, qboolean crash);
-
-byte mod_novis[MAX_MAP_LEAFS / 8];
-
-#define	MAX_MOD_KNOWN	256
-model_t mod_known[MAX_MOD_KNOWN];
-int mod_numknown;
-
-/*
-===============
-Mod_Init
-===============
-*/
-void
-Mod_Init(void)
-{
-    memset(mod_novis, 0xff, sizeof(mod_novis));
-}
-
-/*
-===============
-Mod_Extradata
-
-Caches the data if needed
-===============
-*/
-void *
-Mod_Extradata(model_t *mod)
-{
-    void *r;
-
-    r = Cache_Check(&mod->cache);
-    if (r)
-	return r;
-
-    Mod_LoadModel(mod, true);
-
-    if (!mod->cache.data)
-	Sys_Error("%s: caching failed", __func__);
-    return mod->cache.data;
-}
-
-/*
-===============
-Mod_PointInLeaf
-===============
-*/
-mleaf_t *
-Mod_PointInLeaf(vec3_t p, model_t *model)
-{
-    mnode_t *node;
-    float d;
-    mplane_t *plane;
-
-    if (!model || !model->nodes)
-	Sys_Error("%s: bad model", __func__);
-
-    node = model->nodes;
-    while (1) {
-	if (node->contents < 0)
-	    return (mleaf_t *)node;
-	plane = node->plane;
-	d = DotProduct(p, plane->normal) - plane->dist;
-	if (d > 0)
-	    node = node->children[0];
-	else
-	    node = node->children[1];
-    }
-
-    return NULL;		// never reached
-}
-
-
-/*
-===================
-Mod_DecompressVis
-===================
-*/
-byte *
-Mod_DecompressVis(byte *in, model_t *model)
-{
-    static byte decompressed[MAX_MAP_LEAFS / 8];
-    int c;
-    byte *out;
-    int row;
-
-    row = (model->numleafs + 7) >> 3;
-    out = decompressed;
-
-    if (!in) {			// no vis info, so make all visible
-	while (row) {
-	    *out++ = 0xff;
-	    row--;
-	}
-	return decompressed;
-    }
-
-    do {
-	if (*in) {
-	    *out++ = *in++;
-	    continue;
-	}
-
-	c = in[1];
-	in += 2;
-	while (c) {
-	    *out++ = 0;
-	    c--;
-	}
-    } while (out - decompressed < row);
-
-    return decompressed;
-}
-
-byte *
-Mod_LeafPVS(mleaf_t *leaf, model_t *model)
-{
-    if (leaf == model->leafs)
-	return mod_novis;
-    return Mod_DecompressVis(leaf->compressed_vis, model);
-}
-
-/*
-===================
-Mod_ClearAll
-===================
-*/
-void
-Mod_ClearAll(void)
-{
-    int i;
-    model_t *mod;
-
-    for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++)
-	if (mod->type != mod_alias)
-	    mod->needload = true;
-}
-
-/*
-==================
-Mod_FindName
-
-==================
-*/
-model_t *
-Mod_FindName(char *name)
-{
-    int i;
-    model_t *mod;
-
-    if (!name[0])
-	Sys_Error("%s: NULL name", __func__);
-
-//
-// search the currently loaded models
-//
-    for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++)
-	if (!strcmp(mod->name, name))
-	    break;
-
-    if (i == mod_numknown) {
-	if (mod_numknown == MAX_MOD_KNOWN)
-	    Sys_Error("mod_numknown == MAX_MOD_KNOWN");
-	strcpy(mod->name, name);
-	mod->needload = true;
-	mod_numknown++;
-    }
-
-    return mod;
-}
-
-/*
-==================
-Mod_TouchModel
-
-==================
-*/
-void
-Mod_TouchModel(char *name)
-{
-    model_t *mod;
-
-    mod = Mod_FindName(name);
-
-    if (!mod->needload) {
-	if (mod->type == mod_alias)
-	    Cache_Check(&mod->cache);
-    }
-}
-
-/*
-==================
-Mod_LoadModel
-
-Loads a model into the cache
-==================
-*/
-model_t *
-Mod_LoadModel(model_t *mod, qboolean crash)
-{
-    unsigned *buf;
-    byte stackbuf[1024];	// avoid dirtying the cache heap
-
-    if (!mod->needload) {
-	if (mod->type == mod_alias) {
-	    if (Cache_Check(&mod->cache))
-		return mod;
-	} else
-	    return mod;		// not cached at all
-    }
-
-//
-// because the world is so huge, load it one piece at a time
-//
-
-//
-// load the file
-//
-    buf = (unsigned *)COM_LoadStackFile(mod->name, stackbuf, sizeof(stackbuf),
-					NULL);
-    if (!buf) {
-	if (crash)
-	    Sys_Error("%s: %s not found", __func__, mod->name);
-	return NULL;
-    }
-//
-// allocate a new model
-//
-    COM_FileBase(mod->name, loadname);
-
-    loadmodel = mod;
-
-//
-// fill it in
-//
-
-// call the apropriate loader
-    mod->needload = false;
-
-    switch (LittleLong(*(unsigned *)buf)) {
-    case IDPOLYHEADER:
-	Mod_LoadAliasModel(mod, buf);
-	break;
-
-    case IDSPRITEHEADER:
-	Mod_LoadSpriteModel(mod, buf);
-	break;
-
-    default:
-	Mod_LoadBrushModel(mod, buf);
-	break;
-    }
-
-    return mod;
-}
-
-/*
-==================
-Mod_ForName
-
-Loads in a model for the given name
-==================
-*/
-model_t *
-Mod_ForName(char *name, qboolean crash)
-{
-    model_t *mod;
-
-    mod = Mod_FindName(name);
-
-    return Mod_LoadModel(mod, crash);
-}
-
-
-/*
-===============================================================================
-
-					BRUSHMODEL LOADING
-
-===============================================================================
-*/
-
-byte *mod_base;
-
-
-/*
-=================
-Mod_LoadTextures
-=================
-*/
-void
-Mod_LoadTextures(lump_t *l)
-{
-    int i, j, pixels, num, max, altmax;
-    miptex_t *mt;
-    texture_t *tx, *tx2;
-    texture_t *anims[10];
-    texture_t *altanims[10];
-    dmiptexlump_t *m;
-
-    if (!l->filelen) {
-	loadmodel->textures = NULL;
-	return;
-    }
-    m = (dmiptexlump_t *)(mod_base + l->fileofs);
-
-    m->nummiptex = LittleLong(m->nummiptex);
-
-    loadmodel->numtextures = m->nummiptex;
-    loadmodel->textures =
-	Hunk_AllocName(m->nummiptex * sizeof(*loadmodel->textures), loadname);
-
-    for (i = 0; i < m->nummiptex; i++) {
-	m->dataofs[i] = LittleLong(m->dataofs[i]);
-	if (m->dataofs[i] == -1)
-	    continue;
-	mt = (miptex_t *)((byte *)m + m->dataofs[i]);
-	mt->width = (uint32_t)LittleLong(mt->width);
-	mt->height = (uint32_t)LittleLong(mt->height);
-	for (j = 0; j < MIPLEVELS; j++)
-	    mt->offsets[j] = (uint32_t)LittleLong(mt->offsets[j]);
-
-	if ((mt->width & 15) || (mt->height & 15))
-	    Sys_Error("Texture %s is not 16 aligned", mt->name);
-	pixels = mt->width * mt->height / 64 * 85;
-	tx = Hunk_AllocName(sizeof(texture_t) + pixels, loadname);
-	loadmodel->textures[i] = tx;
-
-	memcpy(tx->name, mt->name, sizeof(tx->name));
-	tx->width = mt->width;
-	tx->height = mt->height;
-	for (j = 0; j < MIPLEVELS; j++)
-	    tx->offsets[j] =
-		mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
-	// the pixels immediately follow the structures
-	memcpy(tx + 1, mt + 1, pixels);
-
-	if (!strncmp(mt->name, "sky", 3))
-	    R_InitSky(tx);
-    }
-
-//
-// sequence the animations
-//
-    for (i = 0; i < m->nummiptex; i++) {
-	tx = loadmodel->textures[i];
-	if (!tx || tx->name[0] != '+')
-	    continue;
-	if (tx->anim_next)
-	    continue;		// allready sequenced
-
-	// find the number of frames in the animation
-	memset(anims, 0, sizeof(anims));
-	memset(altanims, 0, sizeof(altanims));
-
-	max = tx->name[1];
-	altmax = 0;
-	if (max >= 'a' && max <= 'z')
-	    max -= 'a' - 'A';
-	if (max >= '0' && max <= '9') {
-	    max -= '0';
-	    altmax = 0;
-	    anims[max] = tx;
-	    max++;
-	} else if (max >= 'A' && max <= 'J') {
-	    altmax = max - 'A';
-	    max = 0;
-	    altanims[altmax] = tx;
-	    altmax++;
-	} else
-	    Sys_Error("Bad animating texture %s", tx->name);
-
-	for (j = i + 1; j < m->nummiptex; j++) {
-	    tx2 = loadmodel->textures[j];
-	    if (!tx2 || tx2->name[0] != '+')
-		continue;
-	    if (strcmp(tx2->name + 2, tx->name + 2))
-		continue;
-
-	    num = tx2->name[1];
-	    if (num >= 'a' && num <= 'z')
-		num -= 'a' - 'A';
-	    if (num >= '0' && num <= '9') {
-		num -= '0';
-		anims[num] = tx2;
-		if (num + 1 > max)
-		    max = num + 1;
-	    } else if (num >= 'A' && num <= 'J') {
-		num = num - 'A';
-		altanims[num] = tx2;
-		if (num + 1 > altmax)
-		    altmax = num + 1;
-	    } else
-		Sys_Error("Bad animating texture %s", tx->name);
-	}
-
-#define	ANIM_CYCLE	2
-	// link them all together
-	for (j = 0; j < max; j++) {
-	    tx2 = anims[j];
-	    if (!tx2)
-		Sys_Error("Missing frame %i of %s", j, tx->name);
-	    tx2->anim_total = max * ANIM_CYCLE;
-	    tx2->anim_min = j * ANIM_CYCLE;
-	    tx2->anim_max = (j + 1) * ANIM_CYCLE;
-	    tx2->anim_next = anims[(j + 1) % max];
-	    if (altmax)
-		tx2->alternate_anims = altanims[0];
-	}
-	for (j = 0; j < altmax; j++) {
-	    tx2 = altanims[j];
-	    if (!tx2)
-		Sys_Error("Missing frame %i of %s", j, tx->name);
-	    tx2->anim_total = altmax * ANIM_CYCLE;
-	    tx2->anim_min = j * ANIM_CYCLE;
-	    tx2->anim_max = (j + 1) * ANIM_CYCLE;
-	    tx2->anim_next = altanims[(j + 1) % altmax];
-	    if (max)
-		tx2->alternate_anims = anims[0];
-	}
-    }
-}
-
-/*
-=================
-Mod_LoadLighting
-=================
-*/
-void
-Mod_LoadLighting(lump_t *l)
-{
-    if (!l->filelen) {
-	loadmodel->lightdata = NULL;
-	return;
-    }
-    loadmodel->lightdata = Hunk_AllocName(l->filelen, loadname);
-    memcpy(loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
-}
-
-
-/*
-=================
-Mod_LoadVisibility
-=================
-*/
-void
-Mod_LoadVisibility(lump_t *l)
-{
-    if (!l->filelen) {
-	loadmodel->visdata = NULL;
-	return;
-    }
-    loadmodel->visdata = Hunk_AllocName(l->filelen, loadname);
-    memcpy(loadmodel->visdata, mod_base + l->fileofs, l->filelen);
-}
-
-
-/*
-=================
-Mod_LoadEntities
-=================
-*/
-void
-Mod_LoadEntities(lump_t *l)
-{
-    if (!l->filelen) {
-	loadmodel->entities = NULL;
-	return;
-    }
-    loadmodel->entities = Hunk_AllocName(l->filelen, loadname);
-    memcpy(loadmodel->entities, mod_base + l->fileofs, l->filelen);
-}
-
-
-/*
-=================
-Mod_LoadVertexes
-=================
-*/
-void
-Mod_LoadVertexes(lump_t *l)
-{
-    dvertex_t *in;
-    mvertex_t *out;
-    int i, count;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->vertexes = out;
-    loadmodel->numvertexes = count;
-
-    for (i = 0; i < count; i++, in++, out++) {
-	out->position[0] = LittleFloat(in->point[0]);
-	out->position[1] = LittleFloat(in->point[1]);
-	out->position[2] = LittleFloat(in->point[2]);
-    }
-}
-
-/*
-=================
-Mod_LoadSubmodels
-=================
-*/
-void
-Mod_LoadSubmodels(lump_t *l)
-{
-    dmodel_t *in;
-    dmodel_t *out;
-    int i, j, count;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->submodels = out;
-    loadmodel->numsubmodels = count;
-
-    for (i = 0; i < count; i++, in++, out++) {
-	for (j = 0; j < 3; j++) {	// spread the mins / maxs by a pixel
-	    out->mins[j] = LittleFloat(in->mins[j]) - 1;
-	    out->maxs[j] = LittleFloat(in->maxs[j]) + 1;
-	    out->origin[j] = LittleFloat(in->origin[j]);
-	}
-	for (j = 0; j < MAX_MAP_HULLS; j++)
-	    out->headnode[j] = LittleLong(in->headnode[j]);
-	out->visleafs = LittleLong(in->visleafs);
-	out->firstface = LittleLong(in->firstface);
-	out->numfaces = LittleLong(in->numfaces);
-    }
-}
-
-/*
-=================
-Mod_LoadEdges
-=================
-*/
-void
-Mod_LoadEdges(lump_t *l)
-{
-    dedge_t *in;
-    medge_t *out;
-    int i, count;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName((count + 1) * sizeof(*out), loadname);
-
-    loadmodel->edges = out;
-    loadmodel->numedges = count;
-
-    for (i = 0; i < count; i++, in++, out++) {
-	out->v[0] = (uint16_t)LittleShort(in->v[0]);
-	out->v[1] = (uint16_t)LittleShort(in->v[1]);
-    }
-}
-
-/*
-=================
-Mod_LoadTexinfo
-=================
-*/
-void
-Mod_LoadTexinfo(lump_t *l)
-{
-    texinfo_t *in;
-    mtexinfo_t *out;
-    int i, j, count;
-    int miptex;
-    float len1, len2;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->texinfo = out;
-    loadmodel->numtexinfo = count;
-
-    for (i = 0; i < count; i++, in++, out++) {
-	for (j = 0; j < 8; j++)
-	    out->vecs[0][j] = LittleFloat(in->vecs[0][j]);
-	len1 = Length(out->vecs[0]);
-	len2 = Length(out->vecs[1]);
-	len1 = (len1 + len2) / 2;
-	if (len1 < 0.32)
-	    out->mipadjust = 4;
-	else if (len1 < 0.49)
-	    out->mipadjust = 3;
-	else if (len1 < 0.99)
-	    out->mipadjust = 2;
-	else
-	    out->mipadjust = 1;
-#if 0
-	if (len1 + len2 < 0.001)
-	    out->mipadjust = 1;	// don't crash
-	else
-	    out->mipadjust = 1 / floor((len1 + len2) / 2 + 0.1);
-#endif
-
-	miptex = LittleLong(in->miptex);
-	out->flags = LittleLong(in->flags);
-
-	if (!loadmodel->textures) {
-	    out->texture = r_notexture_mip;	// checkerboard texture
-	    out->flags = 0;
-	} else {
-	    if (miptex >= loadmodel->numtextures)
-		Sys_Error("miptex >= loadmodel->numtextures");
-	    out->texture = loadmodel->textures[miptex];
-	    if (!out->texture) {
-		out->texture = r_notexture_mip;	// texture not found
-		out->flags = 0;
-	    }
-	}
-    }
-}
-
-/*
-================
-CalcSurfaceExtents
-
-Fills in s->texturemins[] and s->extents[]
-================
-*/
-void
-CalcSurfaceExtents(msurface_t *s)
-{
-    float mins[2], maxs[2], val;
-    int i, j, e;
-    mvertex_t *v;
-    mtexinfo_t *tex;
-    int bmins[2], bmaxs[2];
-
-    mins[0] = mins[1] = 999999;
-    maxs[0] = maxs[1] = -99999;
-
-    tex = s->texinfo;
-
-    for (i = 0; i < s->numedges; i++) {
-	e = loadmodel->surfedges[s->firstedge + i];
-	if (e >= 0)
-	    v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
-	else
-	    v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
-
-	for (j = 0; j < 2; j++) {
-	    val = v->position[0] * tex->vecs[j][0] +
-		v->position[1] * tex->vecs[j][1] +
-		v->position[2] * tex->vecs[j][2] + tex->vecs[j][3];
-	    if (val < mins[j])
-		mins[j] = val;
-	    if (val > maxs[j])
-		maxs[j] = val;
-	}
-    }
-
-    for (i = 0; i < 2; i++) {
-	bmins[i] = floor(mins[i] / 16);
-	bmaxs[i] = ceil(maxs[i] / 16);
-
-	s->texturemins[i] = bmins[i] * 16;
-	s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
-	if (!(tex->flags & TEX_SPECIAL) && s->extents[i] > 256)
-	    Sys_Error("Bad surface extents");
-    }
-}
-
-
-/*
-=================
-Mod_LoadFaces
-=================
-*/
-void
-Mod_LoadFaces(lump_t *l)
-{
-    dface_t *in;
-    msurface_t *out;
-    int i, count, surfnum;
-    int planenum, side;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->surfaces = out;
-    loadmodel->numsurfaces = count;
-
-    for (surfnum = 0; surfnum < count; surfnum++, in++, out++) {
-	out->firstedge = LittleLong(in->firstedge);
-	out->numedges = LittleShort(in->numedges);
-	out->flags = 0;
-
-	planenum = LittleShort(in->planenum);
-	side = LittleShort(in->side);
-	if (side)
-	    out->flags |= SURF_PLANEBACK;
-
-	out->plane = loadmodel->planes + planenum;
-
-	out->texinfo = loadmodel->texinfo + LittleShort(in->texinfo);
-
-	CalcSurfaceExtents(out);
-
-	// lighting info
-
-	for (i = 0; i < MAXLIGHTMAPS; i++)
-	    out->styles[i] = in->styles[i];
-	i = LittleLong(in->lightofs);
-	if (i == -1)
-	    out->samples = NULL;
-	else
-	    out->samples = loadmodel->lightdata + i;
-
-	// set the drawing flags flag
-
-	if (!strncmp(out->texinfo->texture->name, "sky", 3))	// sky
-	{
-	    out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
-	    continue;
-	}
-
-	if (!strncmp(out->texinfo->texture->name, "*", 1))	// turbulent
-	{
-	    out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
-	    for (i = 0; i < 2; i++) {
-		out->extents[i] = 16384;
-		out->texturemins[i] = -8192;
-	    }
-	    continue;
-	}
-    }
-}
-
-
-/*
-=================
-Mod_SetParent
-=================
-*/
-void
-Mod_SetParent(mnode_t *node, mnode_t *parent)
-{
-    node->parent = parent;
-    if (node->contents < 0)
-	return;
-    Mod_SetParent(node->children[0], node);
-    Mod_SetParent(node->children[1], node);
-}
-
-/*
-=================
-Mod_LoadNodes
-=================
-*/
-void
-Mod_LoadNodes(lump_t *l)
-{
-    int i, j, count, p;
-    dnode_t *in;
-    mnode_t *out;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->nodes = out;
-    loadmodel->numnodes = count;
-
-    for (i = 0; i < count; i++, in++, out++) {
-	for (j = 0; j < 3; j++) {
-	    out->minmaxs[j] = LittleShort(in->mins[j]);
-	    out->minmaxs[3 + j] = LittleShort(in->maxs[j]);
-	}
-
-	p = LittleLong(in->planenum);
-	out->plane = loadmodel->planes + p;
-
-	out->firstsurface = (uint16_t)LittleShort(in->firstface);
-	out->numsurfaces = (uint16_t)LittleShort(in->numfaces);
-
-	for (j = 0; j < 2; j++) {
-	    p = LittleShort(in->children[j]);
-	    if (p >= 0)
-		out->children[j] = loadmodel->nodes + p;
-	    else
-		out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
-	}
-    }
-
-    Mod_SetParent(loadmodel->nodes, NULL);	// sets nodes and leafs
-}
-
-/*
-=================
-Mod_LoadLeafs
-=================
-*/
-void
-Mod_LoadLeafs(lump_t *l)
-{
-    dleaf_t *in;
-    mleaf_t *out;
-    int i, j, count, p;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-
-    /* FIXME - fail gracefully */
-    if (count > MAX_MAP_LEAFS)
-	Sys_Error("%s: model->numleafs > MAX_MAP_LEAFS\n", __func__);
-
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->leafs = out;
-    loadmodel->numleafs = count;
-
-    for (i = 0; i < count; i++, in++, out++) {
-	for (j = 0; j < 3; j++) {
-	    out->minmaxs[j] = LittleShort(in->mins[j]);
-	    out->minmaxs[3 + j] = LittleShort(in->maxs[j]);
-	}
-
-	p = LittleLong(in->contents);
-	out->contents = p;
-
-	out->firstmarksurface = loadmodel->marksurfaces +
-	    (uint16_t)LittleShort(in->firstmarksurface);
-	out->nummarksurfaces =
-	    (uint16_t)LittleShort(in->nummarksurfaces);
-
-	p = LittleLong(in->visofs);
-	if (p == -1)
-	    out->compressed_vis = NULL;
-	else
-	    out->compressed_vis = loadmodel->visdata + p;
-	out->efrags = NULL;
-
-	for (j = 0; j < 4; j++)
-	    out->ambient_sound_level[j] = in->ambient_level[j];
-    }
-}
-
-/*
-=================
-Mod_LoadClipnodes
-=================
-*/
-void
-Mod_LoadClipnodes(lump_t *l)
-{
-    dclipnode_t *in, *out;
-    int i, count;
-    hull_t *hull;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->clipnodes = out;
-    loadmodel->numclipnodes = count;
-
-    hull = &loadmodel->hulls[1];
-    hull->clipnodes = out;
-    hull->firstclipnode = 0;
-    hull->lastclipnode = count - 1;
-    hull->planes = loadmodel->planes;
-    hull->clip_mins[0] = -16;
-    hull->clip_mins[1] = -16;
-    hull->clip_mins[2] = -24;
-    hull->clip_maxs[0] = 16;
-    hull->clip_maxs[1] = 16;
-    hull->clip_maxs[2] = 32;
-
-    hull = &loadmodel->hulls[2];
-    hull->clipnodes = out;
-    hull->firstclipnode = 0;
-    hull->lastclipnode = count - 1;
-    hull->planes = loadmodel->planes;
-    hull->clip_mins[0] = -32;
-    hull->clip_mins[1] = -32;
-    hull->clip_mins[2] = -24;
-    hull->clip_maxs[0] = 32;
-    hull->clip_maxs[1] = 32;
-    hull->clip_maxs[2] = 64;
-
-    for (i = 0; i < count; i++, out++, in++) {
-	out->planenum = LittleLong(in->planenum);
-	out->children[0] = LittleShort(in->children[0]);
-	out->children[1] = LittleShort(in->children[1]);
-    }
-}
-
-/*
-=================
-Mod_MakeHull0
-
-Duplicate the drawing hull structure as a clipping hull
-=================
-*/
-void
-Mod_MakeHull0(void)
-{
-    mnode_t *in, *child;
-    dclipnode_t *out;
-    int i, j, count;
-    hull_t *hull;
-
-    hull = &loadmodel->hulls[0];
-
-    in = loadmodel->nodes;
-    count = loadmodel->numnodes;
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    hull->clipnodes = out;
-    hull->firstclipnode = 0;
-    hull->lastclipnode = count - 1;
-    hull->planes = loadmodel->planes;
-
-    for (i = 0; i < count; i++, out++, in++) {
-	out->planenum = in->plane - loadmodel->planes;
-	for (j = 0; j < 2; j++) {
-	    child = in->children[j];
-	    if (child->contents < 0)
-		out->children[j] = child->contents;
-	    else
-		out->children[j] = child - loadmodel->nodes;
-	}
-    }
-}
-
-/*
-=================
-Mod_LoadMarksurfaces
-=================
-*/
-void
-Mod_LoadMarksurfaces(lump_t *l)
-{
-    int i, j, count;
-    unsigned short *in;
-    msurface_t **out;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->marksurfaces = out;
-    loadmodel->nummarksurfaces = count;
-
-    for (i = 0; i < count; i++) {
-	j = (uint16_t)LittleShort(in[i]);
-	if (j >= loadmodel->numsurfaces)
-	    Sys_Error("%s: bad surface number", __func__);
-	out[i] = loadmodel->surfaces + j;
-    }
-}
-
-/*
-=================
-Mod_LoadSurfedges
-=================
-*/
-void
-Mod_LoadSurfedges(lump_t *l)
-{
-    int i, count;
-    int *in, *out;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * sizeof(*out), loadname);
-
-    loadmodel->surfedges = out;
-    loadmodel->numsurfedges = count;
-
-    for (i = 0; i < count; i++)
-	out[i] = LittleLong(in[i]);
-}
-
-/*
-=================
-Mod_LoadPlanes
-=================
-*/
-void
-Mod_LoadPlanes(lump_t *l)
-{
-    int i, j;
-    mplane_t *out;
-    dplane_t *in;
-    int count;
-    int bits;
-
-    in = (void *)(mod_base + l->fileofs);
-    if (l->filelen % sizeof(*in))
-	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
-    count = l->filelen / sizeof(*in);
-    out = Hunk_AllocName(count * 2 * sizeof(*out), loadname);
-
-    loadmodel->planes = out;
-    loadmodel->numplanes = count;
-
-    for (i = 0; i < count; i++, in++, out++) {
-	bits = 0;
-	for (j = 0; j < 3; j++) {
-	    out->normal[j] = LittleFloat(in->normal[j]);
-	    if (out->normal[j] < 0)
-		bits |= 1 << j;
-	}
-
-	out->dist = LittleFloat(in->dist);
-	out->type = LittleLong(in->type);
-	out->signbits = bits;
-    }
-}
-
-/*
-=================
-RadiusFromBounds
-=================
-*/
-float
-RadiusFromBounds(vec3_t mins, vec3_t maxs)
-{
-    int i;
-    vec3_t corner;
-
-    for (i = 0; i < 3; i++) {
-	corner[i] =
-	    fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
-    }
-
-    return Length(corner);
-}
-
-/*
-=================
-Mod_LoadBrushModel
-=================
-*/
-void
-Mod_LoadBrushModel(model_t *mod, void *buffer)
-{
-    int i, j;
-    dheader_t *header;
-    dmodel_t *bm;
-
-    loadmodel->type = mod_brush;
-
-    header = (dheader_t *)buffer;
-
-    i = LittleLong(header->version);
-    if (i != BSPVERSION)
-	Sys_Error("%s: %s has wrong version number (%i should be %i)",
-		  __func__, mod->name, i, BSPVERSION);
-
-// swap all the lumps
-    mod_base = (byte *)header;
-
-    for (i = 0; i < sizeof(dheader_t) / 4; i++)
-	((int *)header)[i] = LittleLong(((int *)header)[i]);
-
-#ifdef QW_HACK
-    mod->checksum = 0;
-    mod->checksum2 = 0;
-
-// checksum all of the map, except for entities
-    for (i = 0; i < HEADER_LUMPS; i++) {
-	if (i == LUMP_ENTITIES)
-	    continue;
-	mod->checksum ^=
-	    Com_BlockChecksum(mod_base + header->lumps[i].fileofs,
-			      header->lumps[i].filelen);
-
-	if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES)
-	    continue;
-	mod->checksum2 ^=
-	    Com_BlockChecksum(mod_base + header->lumps[i].fileofs,
-			      header->lumps[i].filelen);
-    }
-#endif
-
-// load into heap
-
-    Mod_LoadVertexes(&header->lumps[LUMP_VERTEXES]);
-    Mod_LoadEdges(&header->lumps[LUMP_EDGES]);
-    Mod_LoadSurfedges(&header->lumps[LUMP_SURFEDGES]);
-    Mod_LoadTextures(&header->lumps[LUMP_TEXTURES]);
-    Mod_LoadLighting(&header->lumps[LUMP_LIGHTING]);
-    Mod_LoadPlanes(&header->lumps[LUMP_PLANES]);
-    Mod_LoadTexinfo(&header->lumps[LUMP_TEXINFO]);
-    Mod_LoadFaces(&header->lumps[LUMP_FACES]);
-    Mod_LoadMarksurfaces(&header->lumps[LUMP_MARKSURFACES]);
-    Mod_LoadVisibility(&header->lumps[LUMP_VISIBILITY]);
-    Mod_LoadLeafs(&header->lumps[LUMP_LEAFS]);
-    Mod_LoadNodes(&header->lumps[LUMP_NODES]);
-    Mod_LoadClipnodes(&header->lumps[LUMP_CLIPNODES]);
-    Mod_LoadEntities(&header->lumps[LUMP_ENTITIES]);
-    Mod_LoadSubmodels(&header->lumps[LUMP_MODELS]);
-
-    Mod_MakeHull0();
-
-    mod->numframes = 2;		// regular and alternate animation
-    mod->flags = 0;
-
-//
-// set up the submodels (FIXME: this is confusing)
-//
-    for (i = 0; i < mod->numsubmodels; i++) {
-	bm = &mod->submodels[i];
-
-	mod->hulls[0].firstclipnode = bm->headnode[0];
-	for (j = 1; j < MAX_MAP_HULLS; j++) {
-	    mod->hulls[j].firstclipnode = bm->headnode[j];
-	    mod->hulls[j].lastclipnode = mod->numclipnodes - 1;
-	}
-
-	mod->firstmodelsurface = bm->firstface;
-	mod->nummodelsurfaces = bm->numfaces;
-	mod->radius = RadiusFromBounds(mod->mins, mod->maxs);
-
-	VectorCopy(bm->maxs, mod->maxs);
-	VectorCopy(bm->mins, mod->mins);
-
-	mod->numleafs = bm->visleafs;
-
-	/* duplicate the basic information */
-	if (i < mod->numsubmodels - 1) {
-	    char name[10];
-
-	    sprintf(name, "*%i", i + 1);
-	    loadmodel = Mod_FindName(name);
-	    *loadmodel = *mod;
-	    strcpy(loadmodel->name, name);
-	    mod = loadmodel;
-	}
-    }
-}
-
-/*
-==============================================================================
-
-ALIAS MODELS
-
-==============================================================================
-*/
-
-/*
-=================
-Mod_LoadAliasFrame
-=================
-*/
-void *
-Mod_LoadAliasFrame(void *pin, int *pframeindex, int numv,
-		   trivertx_t *pbboxmin, trivertx_t *pbboxmax,
-		   aliashdr_t *pheader, char *name)
-{
-    trivertx_t *pframe, *pinframe;
-    int i, j;
-    daliasframe_t *pdaliasframe;
-
-    pdaliasframe = (daliasframe_t *)pin;
-
-    strcpy(name, pdaliasframe->name);
-
-    for (i = 0; i < 3; i++) {
-	// these are byte values, so we don't have to worry about
-	// endianness
-	pbboxmin->v[i] = pdaliasframe->bboxmin.v[i];
-	pbboxmax->v[i] = pdaliasframe->bboxmax.v[i];
-    }
-
-    pinframe = (trivertx_t *)(pdaliasframe + 1);
-    pframe = Hunk_AllocName(numv * sizeof(*pframe), loadname);
-
-    *pframeindex = (byte *)pframe - (byte *)pheader;
-
-    for (j = 0; j < numv; j++) {
-	int k;
-
-	// these are all byte values, so no need to deal with endianness
-	pframe[j].lightnormalindex = pinframe[j].lightnormalindex;
-
-	for (k = 0; k < 3; k++) {
-	    pframe[j].v[k] = pinframe[j].v[k];
-	}
-    }
-
-    pinframe += numv;
-
-    return (void *)pinframe;
-}
-
-
-/*
-=================
-Mod_LoadAliasGroup
-=================
-*/
-void *
-Mod_LoadAliasGroup(void *pin, int *pframeindex, int numv,
-		   trivertx_t *pbboxmin, trivertx_t *pbboxmax,
-		   aliashdr_t *pheader, char *name)
-{
-    daliasgroup_t *pingroup;
-    maliasgroup_t *paliasgroup;
-    int i, numframes;
-    daliasinterval_t *pin_intervals;
-    float *poutintervals;
-    void *ptemp;
-
-    pingroup = (daliasgroup_t *)pin;
-
-    numframes = LittleLong(pingroup->numframes);
-
-    paliasgroup = Hunk_AllocName(sizeof(maliasgroup_t) +
-				 (numframes -
-				  1) * sizeof(paliasgroup->frames[0]),
-				 loadname);
-
-    paliasgroup->numframes = numframes;
-
-    for (i = 0; i < 3; i++) {
-	// these are byte values, so we don't have to worry about endianness
-	pbboxmin->v[i] = pingroup->bboxmin.v[i];
-	pbboxmax->v[i] = pingroup->bboxmax.v[i];
-    }
-
-    *pframeindex = (byte *)paliasgroup - (byte *)pheader;
-
-    pin_intervals = (daliasinterval_t *)(pingroup + 1);
-
-    poutintervals = Hunk_AllocName(numframes * sizeof(float), loadname);
-
-    paliasgroup->intervals = (byte *)poutintervals - (byte *)pheader;
-
-    for (i = 0; i < numframes; i++) {
-	*poutintervals = LittleFloat(pin_intervals->interval);
-	if (*poutintervals <= 0.0)
-	    Sys_Error("%s: interval <= 0", __func__);
-
-	poutintervals++;
-	pin_intervals++;
-    }
-
-    ptemp = (void *)pin_intervals;
-
-    for (i = 0; i < numframes; i++) {
-	ptemp = Mod_LoadAliasFrame(ptemp,
-				   &paliasgroup->frames[i].frame,
-				   numv,
-				   &paliasgroup->frames[i].bboxmin,
-				   &paliasgroup->frames[i].bboxmax,
-				   pheader, name);
-    }
-
-    return ptemp;
-}
-
-
-/*
-=================
-Mod_LoadAliasSkin
-=================
-*/
-void *
-Mod_LoadAliasSkin(void *pin, int *pskinindex, int skinsize,
-		  aliashdr_t *pheader)
-{
-    int i;
-    byte *pskin, *pinskin;
-    unsigned short *pusskin;
-
-    pskin = Hunk_AllocName(skinsize * r_pixbytes, loadname);
-    pinskin = (byte *)pin;
-    *pskinindex = (byte *)pskin - (byte *)pheader;
-
-    if (r_pixbytes == 1) {
-	memcpy(pskin, pinskin, skinsize);
-    } else if (r_pixbytes == 2) {
-	pusskin = (unsigned short *)pskin;
-
-	for (i = 0; i < skinsize; i++)
-	    pusskin[i] = d_8to16table[pinskin[i]];
-    } else {
-	Sys_Error("%s: driver set invalid r_pixbytes: %d", __func__,
-		  r_pixbytes);
-    }
-
-    pinskin += skinsize;
-
-    return ((void *)pinskin);
-}
-
-
-/*
-=================
-Mod_LoadAliasSkinGroup
-=================
-*/
-void *
-Mod_LoadAliasSkinGroup(void *pin, int *pskinindex, int skinsize,
-		       aliashdr_t *pheader)
-{
-    daliasskingroup_t *pinskingroup;
-    maliasskingroup_t *paliasskingroup;
-    int i, numskins;
-    daliasskininterval_t *pinskinintervals;
-    float *poutskinintervals;
-    void *ptemp;
-
-    pinskingroup = (daliasskingroup_t *)pin;
-
-    numskins = LittleLong(pinskingroup->numskins);
-
-    paliasskingroup = Hunk_AllocName(sizeof(maliasskingroup_t) +
-				     (numskins -
-				      1) *
-				     sizeof(paliasskingroup->skindescs[0]),
-				     loadname);
-
-    paliasskingroup->numskins = numskins;
-
-    *pskinindex = (byte *)paliasskingroup - (byte *)pheader;
-    pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
-    poutskinintervals = Hunk_AllocName(numskins * sizeof(float), loadname);
-
-    paliasskingroup->intervals = (byte *)poutskinintervals - (byte *)pheader;
-
-    for (i = 0; i < numskins; i++) {
-	*poutskinintervals = LittleFloat(pinskinintervals->interval);
-	if (*poutskinintervals <= 0)
-	    Sys_Error("%s: interval <= 0", __func__);
-
-	poutskinintervals++;
-	pinskinintervals++;
-    }
-
-    ptemp = (void *)pinskinintervals;
-
-    for (i = 0; i < numskins; i++) {
-	ptemp = Mod_LoadAliasSkin(ptemp,
-				  &paliasskingroup->skindescs[i].skin,
-				  skinsize, pheader);
-    }
-
-    return ptemp;
-}
-
-
-/*
-=================
-Mod_LoadAliasModel
-=================
-*/
-void
-Mod_LoadAliasModel(model_t *mod, void *buffer)
-{
-    int i;
-    mdl_t *pmodel, *pinmodel;
-    stvert_t *pstverts, *pinstverts;
-    aliashdr_t *pheader;
-    mtriangle_t *ptri;
-    dtriangle_t *pintriangles;
-    int version, numframes, numskins;
-    int size;
-    daliasframetype_t *pframetype;
-    daliasskintype_t *pskintype;
-    maliasskindesc_t *pskindesc;
-    int skinsize;
-    int start, end, total;
-
-#ifdef QW_HACK
-    if (!strcmp(loadmodel->name, "progs/player.mdl") ||
-	!strcmp(loadmodel->name, "progs/eyes.mdl")) {
-	unsigned short crc;
-	byte *p;
-	int len;
-	char st[40];
-
-	CRC_Init(&crc);
-	for (len = com_filesize, p = buffer; len; len--, p++)
-	    CRC_ProcessByte(&crc, *p);
-
-	sprintf(st, "%d", (int)crc);
-	Info_SetValueForKey(cls.userinfo,
-			    !strcmp(loadmodel->name,
-				    "progs/player.mdl") ? pmodel_name :
-			    emodel_name, st, MAX_INFO_STRING);
-
-	if (cls.state >= ca_connected) {
-	    MSG_WriteByte(&cls.netchan.message, clc_stringcmd);
-	    sprintf(st, "setinfo %s %d",
-		    !strcmp(loadmodel->name,
-			    "progs/player.mdl") ? pmodel_name : emodel_name,
-		    (int)crc);
-	    SZ_Print(&cls.netchan.message, st);
-	}
-    }
-#endif
-
-    start = Hunk_LowMark();
-
-    pinmodel = (mdl_t *)buffer;
-
-    version = LittleLong(pinmodel->version);
-    if (version != ALIAS_VERSION)
-	Sys_Error("%s has wrong version number (%i should be %i)",
-		  mod->name, version, ALIAS_VERSION);
-
-//
-// allocate space for a working header, plus all the data except the frames,
-// skin and group info
-//
-    size = sizeof(aliashdr_t) + LittleLong(pinmodel->numframes) *
-	sizeof(pheader->frames[0]) +
-	sizeof(mdl_t) +
-	LittleLong(pinmodel->numverts) * sizeof(stvert_t) +
-	LittleLong(pinmodel->numtris) * sizeof(mtriangle_t);
-
-    pheader = Hunk_AllocName(size, loadname);
-    pmodel = (mdl_t *)((byte *)&pheader[1] +
-		       (LittleLong(pinmodel->numframes) - 1) *
-		       sizeof(pheader->frames[0]));
-
-    mod->flags = LittleLong(pinmodel->flags);
-
-//
-// endian-adjust and copy the data, starting with the alias model header
-//
-    pmodel->boundingradius = LittleFloat(pinmodel->boundingradius);
-    pmodel->numskins = LittleLong(pinmodel->numskins);
-    pmodel->skinwidth = LittleLong(pinmodel->skinwidth);
-    pmodel->skinheight = LittleLong(pinmodel->skinheight);
-
-    if (pmodel->skinheight > MAX_LBM_HEIGHT)
-	Sys_Error("model %s has a skin taller than %d", mod->name,
-		  MAX_LBM_HEIGHT);
-
-    pmodel->numverts = LittleLong(pinmodel->numverts);
-
-    if (pmodel->numverts <= 0)
-	Sys_Error("model %s has no vertices", mod->name);
-
-    if (pmodel->numverts > MAXALIASVERTS)
-	Sys_Error("model %s has too many vertices", mod->name);
-
-    pmodel->numtris = LittleLong(pinmodel->numtris);
-
-    if (pmodel->numtris <= 0)
-	Sys_Error("model %s has no triangles", mod->name);
-
-    pmodel->numframes = LittleLong(pinmodel->numframes);
-    pmodel->size = LittleFloat(pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
-    mod->synctype = LittleLong(pinmodel->synctype);
-    mod->numframes = pmodel->numframes;
-
-    for (i = 0; i < 3; i++) {
-	pmodel->scale[i] = LittleFloat(pinmodel->scale[i]);
-	pmodel->scale_origin[i] = LittleFloat(pinmodel->scale_origin[i]);
-	pmodel->eyeposition[i] = LittleFloat(pinmodel->eyeposition[i]);
-    }
-
-    numskins = pmodel->numskins;
-    numframes = pmodel->numframes;
-
-    if (pmodel->skinwidth & 0x03)
-	Sys_Error("%s: skinwidth not multiple of 4", __func__);
-
-    pheader->model = (byte *)pmodel - (byte *)pheader;
-
-//
-// load the skins
-//
-    skinsize = pmodel->skinheight * pmodel->skinwidth;
-
-    if (numskins < 1)
-	Sys_Error("%s: Invalid # of skins: %d", __func__, numskins);
-
-    pskintype = (daliasskintype_t *)&pinmodel[1];
-
-    pskindesc = Hunk_AllocName(numskins * sizeof(maliasskindesc_t), loadname);
-
-    pheader->skindesc = (byte *)pskindesc - (byte *)pheader;
-
-    for (i = 0; i < numskins; i++) {
-	aliasskintype_t skintype;
-
-	skintype = LittleLong(pskintype->type);
-	pskindesc[i].type = skintype;
-
-	if (skintype == ALIAS_SKIN_SINGLE) {
-	    pskintype = (daliasskintype_t *)
-		Mod_LoadAliasSkin(pskintype + 1,
-				  &pskindesc[i].skin, skinsize, pheader);
-	} else {
-	    pskintype = (daliasskintype_t *)
-		Mod_LoadAliasSkinGroup(pskintype + 1,
-				       &pskindesc[i].skin, skinsize, pheader);
-	}
-    }
-
-//
-// set base s and t vertices
-//
-    pstverts = (stvert_t *)&pmodel[1];
-    pinstverts = (stvert_t *)pskintype;
-
-    pheader->stverts = (byte *)pstverts - (byte *)pheader;
-
-    for (i = 0; i < pmodel->numverts; i++) {
-	pstverts[i].onseam = LittleLong(pinstverts[i].onseam);
-	// put s and t in 16.16 format
-	pstverts[i].s = LittleLong(pinstverts[i].s) << 16;
-	pstverts[i].t = LittleLong(pinstverts[i].t) << 16;
-    }
-
-//
-// set up the triangles
-//
-    ptri = (mtriangle_t *)&pstverts[pmodel->numverts];
-    pintriangles = (dtriangle_t *)&pinstverts[pmodel->numverts];
-
-    pheader->triangles = (byte *)ptri - (byte *)pheader;
-
-    for (i = 0; i < pmodel->numtris; i++) {
-	int j;
-
-	ptri[i].facesfront = LittleLong(pintriangles[i].facesfront);
-
-	for (j = 0; j < 3; j++) {
-	    ptri[i].vertindex[j] = LittleLong(pintriangles[i].vertindex[j]);
-	}
-    }
-
-//
-// load the frames
-//
-    if (numframes < 1)
-	Sys_Error("%s: Invalid # of frames: %d", __func__, numframes);
-
-    pframetype = (daliasframetype_t *)&pintriangles[pmodel->numtris];
-
-    for (i = 0; i < numframes; i++) {
-	aliasframetype_t frametype;
-
-	frametype = LittleLong(pframetype->type);
-	pheader->frames[i].type = frametype;
-
-	if (frametype == ALIAS_SINGLE) {
-	    pframetype = (daliasframetype_t *)
-		Mod_LoadAliasFrame(pframetype + 1,
-				   &pheader->frames[i].frame,
-				   pmodel->numverts,
-				   &pheader->frames[i].bboxmin,
-				   &pheader->frames[i].bboxmax,
-				   pheader, pheader->frames[i].name);
-	} else {
-	    pframetype = (daliasframetype_t *)
-		Mod_LoadAliasGroup(pframetype + 1,
-				   &pheader->frames[i].frame,
-				   pmodel->numverts,
-				   &pheader->frames[i].bboxmin,
-				   &pheader->frames[i].bboxmax,
-				   pheader, pheader->frames[i].name);
-	}
-    }
-
-    mod->type = mod_alias;
-
-// FIXME: do this right
-    mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
-    mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
-
-//
-// move the complete, relocatable alias model to the cache
-//
-    end = Hunk_LowMark();
-    total = end - start;
-
-    Cache_Alloc(&mod->cache, total, loadname);
-    if (!mod->cache.data)
-	return;
-    memcpy(mod->cache.data, pheader, total);
-
-    Hunk_FreeToLowMark(start);
-}
-
-//=============================================================================
-
-/*
-=================
-Mod_LoadSpriteFrame
-=================
-*/
-void *
-Mod_LoadSpriteFrame(void *pin, mspriteframe_t **ppframe)
-{
-    dspriteframe_t *pinframe;
-    mspriteframe_t *pspriteframe;
-    int i, width, height, size, origin[2];
-    unsigned short *ppixout;
-    byte *ppixin;
-
-    pinframe = (dspriteframe_t *)pin;
-
-    width = LittleLong(pinframe->width);
-    height = LittleLong(pinframe->height);
-    size = width * height;
-
-    pspriteframe =
-	Hunk_AllocName(sizeof(mspriteframe_t) + size * r_pixbytes, loadname);
-
-    memset(pspriteframe, 0, sizeof(mspriteframe_t) + size);
-    *ppframe = pspriteframe;
-
-    pspriteframe->width = width;
-    pspriteframe->height = height;
-    origin[0] = LittleLong(pinframe->origin[0]);
-    origin[1] = LittleLong(pinframe->origin[1]);
-
-    pspriteframe->up = origin[1];
-    pspriteframe->down = origin[1] - height;
-    pspriteframe->left = origin[0];
-    pspriteframe->right = width + origin[0];
-
-    if (r_pixbytes == 1) {
-	memcpy(&pspriteframe->pixels[0], (byte *)(pinframe + 1), size);
-    } else if (r_pixbytes == 2) {
-	ppixin = (byte *)(pinframe + 1);
-	ppixout = (unsigned short *)&pspriteframe->pixels[0];
-
-	for (i = 0; i < size; i++)
-	    ppixout[i] = d_8to16table[ppixin[i]];
-    } else {
-	Sys_Error("%s: driver set invalid r_pixbytes: %d", __func__,
-		  r_pixbytes);
-    }
-
-    return (void *)((byte *)pinframe + sizeof(dspriteframe_t) + size);
-}
-
-
-/*
-=================
-Mod_LoadSpriteGroup
-=================
-*/
-void *
-Mod_LoadSpriteGroup(void *pin, mspriteframe_t **ppframe)
-{
-    dspritegroup_t *pingroup;
-    mspritegroup_t *pspritegroup;
-    int i, numframes;
-    dspriteinterval_t *pin_intervals;
-    float *poutintervals;
-    void *ptemp;
-
-    pingroup = (dspritegroup_t *)pin;
-
-    numframes = LittleLong(pingroup->numframes);
-
-    pspritegroup = Hunk_AllocName(sizeof(mspritegroup_t) +
-				  (numframes -
-				   1) * sizeof(pspritegroup->frames[0]),
-				  loadname);
-
-    pspritegroup->numframes = numframes;
-
-    *ppframe = (mspriteframe_t *)pspritegroup;
-
-    pin_intervals = (dspriteinterval_t *)(pingroup + 1);
-
-    poutintervals = Hunk_AllocName(numframes * sizeof(float), loadname);
-
-    pspritegroup->intervals = poutintervals;
-
-    for (i = 0; i < numframes; i++) {
-	*poutintervals = LittleFloat(pin_intervals->interval);
-	if (*poutintervals <= 0.0)
-	    Sys_Error("%s: interval <= 0", __func__);
-
-	poutintervals++;
-	pin_intervals++;
-    }
-
-    ptemp = (void *)pin_intervals;
-
-    for (i = 0; i < numframes; i++) {
-	ptemp = Mod_LoadSpriteFrame(ptemp, &pspritegroup->frames[i]);
-    }
-
-    return ptemp;
-}
-
-
-/*
-=================
-Mod_LoadSpriteModel
-=================
-*/
-void
-Mod_LoadSpriteModel(model_t *mod, void *buffer)
-{
-    int i;
-    int version;
-    dsprite_t *pin;
-    msprite_t *psprite;
-    int numframes;
-    int size;
-    dspriteframetype_t *pframetype;
-
-    pin = (dsprite_t *) buffer;
-
-    version = LittleLong(pin->version);
-    if (version != SPRITE_VERSION)
-	Sys_Error("%s has wrong version number "
-		  "(%i should be %i)", mod->name, version, SPRITE_VERSION);
-
-    numframes = LittleLong(pin->numframes);
-
-    size = sizeof(msprite_t) + (numframes - 1) * sizeof(psprite->frames);
-
-    psprite = Hunk_AllocName(size, loadname);
-    psprite->type = LittleLong(pin->type);
-    psprite->maxwidth = LittleLong(pin->width);
-    psprite->maxheight = LittleLong(pin->height);
-    psprite->beamlength = LittleFloat(pin->beamlength);
-    mod->synctype = LittleLong(pin->synctype);
-    psprite->numframes = numframes;
-
-    mod->mins[0] = mod->mins[1] = -psprite->maxwidth / 2;
-    mod->maxs[0] = mod->maxs[1] = psprite->maxwidth / 2;
-    mod->mins[2] = -psprite->maxheight / 2;
-    mod->maxs[2] = psprite->maxheight / 2;
-
-//
-// load the frames
-//
-    if (numframes < 1)
-	Sys_Error("%s: Invalid # of frames: %d", __func__, numframes);
-
-    mod->numframes = numframes;
-    mod->flags = 0;
-
-    pframetype = (dspriteframetype_t *) (pin + 1);
-
-    for (i = 0; i < numframes; i++) {
-	spriteframetype_t frametype;
-
-	frametype = LittleLong(pframetype->type);
-	psprite->frames[i].type = frametype;
-
-	if (frametype == SPR_SINGLE) {
-	    pframetype = (dspriteframetype_t *)
-		Mod_LoadSpriteFrame(pframetype + 1,
-				    &psprite->frames[i].frameptr);
-	} else {
-	    pframetype = (dspriteframetype_t *)
-		Mod_LoadSpriteGroup(pframetype + 1,
-				    &psprite->frames[i].frameptr);
-	}
-    }
-
-    mod->type = mod_sprite;
-}
-
-//=============================================================================
-
-/*
-================
-Mod_Print
-================
-*/
-void
-Mod_Print(void)
-{
-    int i;
-    model_t *mod;
-
-    Con_Printf("Cached models:\n");
-    for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++)
-	Con_Printf("%8p : %s\n", mod->cache.data, mod->name);
-}
diff -urN -X exclude a/common/model.c head/common/model.c
--- a/common/model.c	1970-01-01 09:30:00.000000000 +0930
+++ head/common/model.c	2006-06-10 20:31:40.000000000 +0930
@@ -0,0 +1,1847 @@
+/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+*/
+// models.c -- model loading and caching
+
+// models are the only shared resource between a client and server running
+// on the same machine.
+
+#include <stdint.h>
+
+#include "console.h"
+#include "quakedef.h"
+#include "r_local.h"
+#include "sys.h"
+
+#ifdef QW_HACK
+#include "crc.h"
+#endif
+
+model_t *loadmodel;
+char loadname[32];		// for hunk tags
+
+void Mod_LoadSpriteModel(model_t *mod, void *buffer);
+void Mod_LoadBrushModel(model_t *mod, void *buffer);
+void Mod_LoadAliasModel(model_t *mod, void *buffer);
+model_t *Mod_LoadModel(model_t *mod, qboolean crash);
+
+byte mod_novis[MAX_MAP_LEAFS / 8];
+
+#define	MAX_MOD_KNOWN	256
+model_t mod_known[MAX_MOD_KNOWN];
+int mod_numknown;
+
+/*
+===============
+Mod_Init
+===============
+*/
+void
+Mod_Init(void)
+{
+    memset(mod_novis, 0xff, sizeof(mod_novis));
+}
+
+/*
+===============
+Mod_Extradata
+
+Caches the data if needed
+===============
+*/
+void *
+Mod_Extradata(model_t *mod)
+{
+    void *r;
+
+    r = Cache_Check(&mod->cache);
+    if (r)
+	return r;
+
+    Mod_LoadModel(mod, true);
+
+    if (!mod->cache.data)
+	Sys_Error("%s: caching failed", __func__);
+    return mod->cache.data;
+}
+
+/*
+===============
+Mod_PointInLeaf
+===============
+*/
+mleaf_t *
+Mod_PointInLeaf(vec3_t p, model_t *model)
+{
+    mnode_t *node;
+    float d;
+    mplane_t *plane;
+
+    if (!model || !model->nodes)
+	Sys_Error("%s: bad model", __func__);
+
+    node = model->nodes;
+    while (1) {
+	if (node->contents < 0)
+	    return (mleaf_t *)node;
+	plane = node->plane;
+	d = DotProduct(p, plane->normal) - plane->dist;
+	if (d > 0)
+	    node = node->children[0];
+	else
+	    node = node->children[1];
+    }
+
+    return NULL;		// never reached
+}
+
+
+/*
+===================
+Mod_DecompressVis
+===================
+*/
+byte *
+Mod_DecompressVis(byte *in, model_t *model)
+{
+    static byte decompressed[MAX_MAP_LEAFS / 8];
+    int c;
+    byte *out;
+    int row;
+
+    row = (model->numleafs + 7) >> 3;
+    out = decompressed;
+
+    if (!in) {			// no vis info, so make all visible
+	while (row) {
+	    *out++ = 0xff;
+	    row--;
+	}
+	return decompressed;
+    }
+
+    do {
+	if (*in) {
+	    *out++ = *in++;
+	    continue;
+	}
+
+	c = in[1];
+	in += 2;
+	while (c) {
+	    *out++ = 0;
+	    c--;
+	}
+    } while (out - decompressed < row);
+
+    return decompressed;
+}
+
+byte *
+Mod_LeafPVS(mleaf_t *leaf, model_t *model)
+{
+    if (leaf == model->leafs)
+	return mod_novis;
+    return Mod_DecompressVis(leaf->compressed_vis, model);
+}
+
+/*
+===================
+Mod_ClearAll
+===================
+*/
+void
+Mod_ClearAll(void)
+{
+    int i;
+    model_t *mod;
+
+    for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++)
+	if (mod->type != mod_alias)
+	    mod->needload = true;
+}
+
+/*
+==================
+Mod_FindName
+
+==================
+*/
+model_t *
+Mod_FindName(char *name)
+{
+    int i;
+    model_t *mod;
+
+    if (!name[0])
+	Sys_Error("%s: NULL name", __func__);
+
+//
+// search the currently loaded models
+//
+    for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++)
+	if (!strcmp(mod->name, name))
+	    break;
+
+    if (i == mod_numknown) {
+	if (mod_numknown == MAX_MOD_KNOWN)
+	    Sys_Error("mod_numknown == MAX_MOD_KNOWN");
+	strcpy(mod->name, name);
+	mod->needload = true;
+	mod_numknown++;
+    }
+
+    return mod;
+}
+
+/*
+==================
+Mod_TouchModel
+
+==================
+*/
+void
+Mod_TouchModel(char *name)
+{
+    model_t *mod;
+
+    mod = Mod_FindName(name);
+
+    if (!mod->needload) {
+	if (mod->type == mod_alias)
+	    Cache_Check(&mod->cache);
+    }
+}
+
+/*
+==================
+Mod_LoadModel
+
+Loads a model into the cache
+==================
+*/
+model_t *
+Mod_LoadModel(model_t *mod, qboolean crash)
+{
+    unsigned *buf;
+    byte stackbuf[1024];	// avoid dirtying the cache heap
+
+    if (!mod->needload) {
+	if (mod->type == mod_alias) {
+	    if (Cache_Check(&mod->cache))
+		return mod;
+	} else
+	    return mod;		// not cached at all
+    }
+
+//
+// because the world is so huge, load it one piece at a time
+//
+
+//
+// load the file
+//
+    buf = (unsigned *)COM_LoadStackFile(mod->name, stackbuf, sizeof(stackbuf),
+					NULL);
+    if (!buf) {
+	if (crash)
+	    Sys_Error("%s: %s not found", __func__, mod->name);
+	return NULL;
+    }
+//
+// allocate a new model
+//
+    COM_FileBase(mod->name, loadname);
+
+    loadmodel = mod;
+
+//
+// fill it in
+//
+
+// call the apropriate loader
+    mod->needload = false;
+
+    switch (LittleLong(*(unsigned *)buf)) {
+    case IDPOLYHEADER:
+	Mod_LoadAliasModel(mod, buf);
+	break;
+
+    case IDSPRITEHEADER:
+	Mod_LoadSpriteModel(mod, buf);
+	break;
+
+    default:
+	Mod_LoadBrushModel(mod, buf);
+	break;
+    }
+
+    return mod;
+}
+
+/*
+==================
+Mod_ForName
+
+Loads in a model for the given name
+==================
+*/
+model_t *
+Mod_ForName(char *name, qboolean crash)
+{
+    model_t *mod;
+
+    mod = Mod_FindName(name);
+
+    return Mod_LoadModel(mod, crash);
+}
+
+
+/*
+===============================================================================
+
+					BRUSHMODEL LOADING
+
+===============================================================================
+*/
+
+byte *mod_base;
+
+
+/*
+=================
+Mod_LoadTextures
+=================
+*/
+void
+Mod_LoadTextures(lump_t *l)
+{
+    int i, j, pixels, num, max, altmax;
+    miptex_t *mt;
+    texture_t *tx, *tx2;
+    texture_t *anims[10];
+    texture_t *altanims[10];
+    dmiptexlump_t *m;
+
+    if (!l->filelen) {
+	loadmodel->textures = NULL;
+	return;
+    }
+    m = (dmiptexlump_t *)(mod_base + l->fileofs);
+
+    m->nummiptex = LittleLong(m->nummiptex);
+
+    loadmodel->numtextures = m->nummiptex;
+    loadmodel->textures =
+	Hunk_AllocName(m->nummiptex * sizeof(*loadmodel->textures), loadname);
+
+    for (i = 0; i < m->nummiptex; i++) {
+	m->dataofs[i] = LittleLong(m->dataofs[i]);
+	if (m->dataofs[i] == -1)
+	    continue;
+	mt = (miptex_t *)((byte *)m + m->dataofs[i]);
+	mt->width = (uint32_t)LittleLong(mt->width);
+	mt->height = (uint32_t)LittleLong(mt->height);
+	for (j = 0; j < MIPLEVELS; j++)
+	    mt->offsets[j] = (uint32_t)LittleLong(mt->offsets[j]);
+
+	if ((mt->width & 15) || (mt->height & 15))
+	    Sys_Error("Texture %s is not 16 aligned", mt->name);
+	pixels = mt->width * mt->height / 64 * 85;
+	tx = Hunk_AllocName(sizeof(texture_t) + pixels, loadname);
+	loadmodel->textures[i] = tx;
+
+	memcpy(tx->name, mt->name, sizeof(tx->name));
+	tx->width = mt->width;
+	tx->height = mt->height;
+	for (j = 0; j < MIPLEVELS; j++)
+	    tx->offsets[j] =
+		mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
+	// the pixels immediately follow the structures
+	memcpy(tx + 1, mt + 1, pixels);
+
+	if (!strncmp(mt->name, "sky", 3))
+	    R_InitSky(tx);
+    }
+
+//
+// sequence the animations
+//
+    for (i = 0; i < m->nummiptex; i++) {
+	tx = loadmodel->textures[i];
+	if (!tx || tx->name[0] != '+')
+	    continue;
+	if (tx->anim_next)
+	    continue;		// allready sequenced
+
+	// find the number of frames in the animation
+	memset(anims, 0, sizeof(anims));
+	memset(altanims, 0, sizeof(altanims));
+
+	max = tx->name[1];
+	altmax = 0;
+	if (max >= 'a' && max <= 'z')
+	    max -= 'a' - 'A';
+	if (max >= '0' && max <= '9') {
+	    max -= '0';
+	    altmax = 0;
+	    anims[max] = tx;
+	    max++;
+	} else if (max >= 'A' && max <= 'J') {
+	    altmax = max - 'A';
+	    max = 0;
+	    altanims[altmax] = tx;
+	    altmax++;
+	} else
+	    Sys_Error("Bad animating texture %s", tx->name);
+
+	for (j = i + 1; j < m->nummiptex; j++) {
+	    tx2 = loadmodel->textures[j];
+	    if (!tx2 || tx2->name[0] != '+')
+		continue;
+	    if (strcmp(tx2->name + 2, tx->name + 2))
+		continue;
+
+	    num = tx2->name[1];
+	    if (num >= 'a' && num <= 'z')
+		num -= 'a' - 'A';
+	    if (num >= '0' && num <= '9') {
+		num -= '0';
+		anims[num] = tx2;
+		if (num + 1 > max)
+		    max = num + 1;
+	    } else if (num >= 'A' && num <= 'J') {
+		num = num - 'A';
+		altanims[num] = tx2;
+		if (num + 1 > altmax)
+		    altmax = num + 1;
+	    } else
+		Sys_Error("Bad animating texture %s", tx->name);
+	}
+
+#define	ANIM_CYCLE	2
+	// link them all together
+	for (j = 0; j < max; j++) {
+	    tx2 = anims[j];
+	    if (!tx2)
+		Sys_Error("Missing frame %i of %s", j, tx->name);
+	    tx2->anim_total = max * ANIM_CYCLE;
+	    tx2->anim_min = j * ANIM_CYCLE;
+	    tx2->anim_max = (j + 1) * ANIM_CYCLE;
+	    tx2->anim_next = anims[(j + 1) % max];
+	    if (altmax)
+		tx2->alternate_anims = altanims[0];
+	}
+	for (j = 0; j < altmax; j++) {
+	    tx2 = altanims[j];
+	    if (!tx2)
+		Sys_Error("Missing frame %i of %s", j, tx->name);
+	    tx2->anim_total = altmax * ANIM_CYCLE;
+	    tx2->anim_min = j * ANIM_CYCLE;
+	    tx2->anim_max = (j + 1) * ANIM_CYCLE;
+	    tx2->anim_next = altanims[(j + 1) % altmax];
+	    if (max)
+		tx2->alternate_anims = anims[0];
+	}
+    }
+}
+
+/*
+=================
+Mod_LoadLighting
+=================
+*/
+void
+Mod_LoadLighting(lump_t *l)
+{
+    if (!l->filelen) {
+	loadmodel->lightdata = NULL;
+	return;
+    }
+    loadmodel->lightdata = Hunk_AllocName(l->filelen, loadname);
+    memcpy(loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
+}
+
+
+/*
+=================
+Mod_LoadVisibility
+=================
+*/
+void
+Mod_LoadVisibility(lump_t *l)
+{
+    if (!l->filelen) {
+	loadmodel->visdata = NULL;
+	return;
+    }
+    loadmodel->visdata = Hunk_AllocName(l->filelen, loadname);
+    memcpy(loadmodel->visdata, mod_base + l->fileofs, l->filelen);
+}
+
+
+/*
+=================
+Mod_LoadEntities
+=================
+*/
+void
+Mod_LoadEntities(lump_t *l)
+{
+    if (!l->filelen) {
+	loadmodel->entities = NULL;
+	return;
+    }
+    loadmodel->entities = Hunk_AllocName(l->filelen, loadname);
+    memcpy(loadmodel->entities, mod_base + l->fileofs, l->filelen);
+}
+
+
+/*
+=================
+Mod_LoadVertexes
+=================
+*/
+void
+Mod_LoadVertexes(lump_t *l)
+{
+    dvertex_t *in;
+    mvertex_t *out;
+    int i, count;
+
+    in = (void *)(mod_base + l->fileofs);
+    if (l->filelen % sizeof(*in))
+	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
+    count = l->filelen / sizeof(*in);
+    out = Hunk_AllocName(count * sizeof(*out), loadname);
+
+    loadmodel->vertexes = out;
+    loadmodel->numvertexes = count;
+
+    for (i = 0; i < count; i++, in++, out++) {
+	out->position[0] = LittleFloat(in->point[0]);
+	out->position[1] = LittleFloat(in->point[1]);
+	out->position[2] = LittleFloat(in->point[2]);
+    }
+}
+
+/*
+=================
+Mod_LoadSubmodels
+=================
+*/
+void
+Mod_LoadSubmodels(lump_t *l)
+{
+    dmodel_t *in;
+    dmodel_t *out;
+    int i, j, count;
+
+    in = (void *)(mod_base + l->fileofs);
+    if (l->filelen % sizeof(*in))
+	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
+    count = l->filelen / sizeof(*in);
+    out = Hunk_AllocName(count * sizeof(*out), loadname);
+
+    loadmodel->submodels = out;
+    loadmodel->numsubmodels = count;
+
+    for (i = 0; i < count; i++, in++, out++) {
+	for (j = 0; j < 3; j++) {	// spread the mins / maxs by a pixel
+	    out->mins[j] = LittleFloat(in->mins[j]) - 1;
+	    out->maxs[j] = LittleFloat(in->maxs[j]) + 1;
+	    out->origin[j] = LittleFloat(in->origin[j]);
+	}
+	for (j = 0; j < MAX_MAP_HULLS; j++)
+	    out->headnode[j] = LittleLong(in->headnode[j]);
+	out->visleafs = LittleLong(in->visleafs);
+	out->firstface = LittleLong(in->firstface);
+	out->numfaces = LittleLong(in->numfaces);
+    }
+}
+
+/*
+=================
+Mod_LoadEdges
+=================
+*/
+void
+Mod_LoadEdges(lump_t *l)
+{
+    dedge_t *in;
+    medge_t *out;
+    int i, count;
+
+    in = (void *)(mod_base + l->fileofs);
+    if (l->filelen % sizeof(*in))
+	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
+    count = l->filelen / sizeof(*in);
+    out = Hunk_AllocName((count + 1) * sizeof(*out), loadname);
+
+    loadmodel->edges = out;
+    loadmodel->numedges = count;
+
+    for (i = 0; i < count; i++, in++, out++) {
+	out->v[0] = (uint16_t)LittleShort(in->v[0]);
+	out->v[1] = (uint16_t)LittleShort(in->v[1]);
+    }
+}
+
+/*
+=================
+Mod_LoadTexinfo
+=================
+*/
+void
+Mod_LoadTexinfo(lump_t *l)
+{
+    texinfo_t *in;
+    mtexinfo_t *out;
+    int i, j, count;
+    int miptex;
+    float len1, len2;
+
+    in = (void *)(mod_base + l->fileofs);
+    if (l->filelen % sizeof(*in))
+	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
+    count = l->filelen / sizeof(*in);
+    out = Hunk_AllocName(count * sizeof(*out), loadname);
+
+    loadmodel->texinfo = out;
+    loadmodel->numtexinfo = count;
+
+    for (i = 0; i < count; i++, in++, out++) {
+	for (j = 0; j < 8; j++)
+	    out->vecs[0][j] = LittleFloat(in->vecs[0][j]);
+	len1 = Length(out->vecs[0]);
+	len2 = Length(out->vecs[1]);
+	len1 = (len1 + len2) / 2;
+	if (len1 < 0.32)
+	    out->mipadjust = 4;
+	else if (len1 < 0.49)
+	    out->mipadjust = 3;
+	else if (len1 < 0.99)
+	    out->mipadjust = 2;
+	else
+	    out->mipadjust = 1;
+#if 0
+	if (len1 + len2 < 0.001)
+	    out->mipadjust = 1;	// don't crash
+	else
+	    out->mipadjust = 1 / floor((len1 + len2) / 2 + 0.1);
+#endif
+
+	miptex = LittleLong(in->miptex);
+	out->flags = LittleLong(in->flags);
+
+	if (!loadmodel->textures) {
+	    out->texture = r_notexture_mip;	// checkerboard texture
+	    out->flags = 0;
+	} else {
+	    if (miptex >= loadmodel->numtextures)
+		Sys_Error("miptex >= loadmodel->numtextures");
+	    out->texture = loadmodel->textures[miptex];
+	    if (!out->texture) {
+		out->texture = r_notexture_mip;	// texture not found
+		out->flags = 0;
+	    }
+	}
+    }
+}
+
+/*
+================
+CalcSurfaceExtents
+
+Fills in s->texturemins[] and s->extents[]
+================
+*/
+void
+CalcSurfaceExtents(msurface_t *s)
+{
+    float mins[2], maxs[2], val;
+    int i, j, e;
+    mvertex_t *v;
+    mtexinfo_t *tex;
+    int bmins[2], bmaxs[2];
+
+    mins[0] = mins[1] = 999999;
+    maxs[0] = maxs[1] = -99999;
+
+    tex = s->texinfo;
+
+    for (i = 0; i < s->numedges; i++) {
+	e = loadmodel->surfedges[s->firstedge + i];
+	if (e >= 0)
+	    v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
+	else
+	    v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
+
+	for (j = 0; j < 2; j++) {
+	    val = v->position[0] * tex->vecs[j][0] +
+		v->position[1] * tex->vecs[j][1] +
+		v->position[2] * tex->vecs[j][2] + tex->vecs[j][3];
+	    if (val < mins[j])
+		mins[j] = val;
+	    if (val > maxs[j])
+		maxs[j] = val;
+	}
+    }
+
+    for (i = 0; i < 2; i++) {
+	bmins[i] = floor(mins[i] / 16);
+	bmaxs[i] = ceil(maxs[i] / 16);
+
+	s->texturemins[i] = bmins[i] * 16;
+	s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
+	if (!(tex->flags & TEX_SPECIAL) && s->extents[i] > 256)
+	    Sys_Error("Bad surface extents");
+    }
+}
+
+
+/*
+=================
+Mod_LoadFaces
+=================
+*/
+void
+Mod_LoadFaces(lump_t *l)
+{
+    dface_t *in;
+    msurface_t *out;
+    int i, count, surfnum;
+    int planenum, side;
+
+    in = (void *)(mod_base + l->fileofs);
+    if (l->filelen % sizeof(*in))
+	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
+    count = l->filelen / sizeof(*in);
+    out = Hunk_AllocName(count * sizeof(*out), loadname);
+
+    loadmodel->surfaces = out;
+    loadmodel->numsurfaces = count;
+
+    for (surfnum = 0; surfnum < count; surfnum++, in++, out++) {
+	out->firstedge = LittleLong(in->firstedge);
+	out->numedges = LittleShort(in->numedges);
+	out->flags = 0;
+
+	planenum = LittleShort(in->planenum);
+	side = LittleShort(in->side);
+	if (side)
+	    out->flags |= SURF_PLANEBACK;
+
+	out->plane = loadmodel->planes + planenum;
+
+	out->texinfo = loadmodel->texinfo + LittleShort(in->texinfo);
+
+	CalcSurfaceExtents(out);
+
+	// lighting info
+
+	for (i = 0; i < MAXLIGHTMAPS; i++)
+	    out->styles[i] = in->styles[i];
+	i = LittleLong(in->lightofs);
+	if (i == -1)
+	    out->samples = NULL;
+	else
+	    out->samples = loadmodel->lightdata + i;
+
+	// set the drawing flags flag
+
+	if (!strncmp(out->texinfo->texture->name, "sky", 3))	// sky
+	{
+	    out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
+	    continue;
+	}
+
+	if (!strncmp(out->texinfo->texture->name, "*", 1))	// turbulent
+	{
+	    out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
+	    for (i = 0; i < 2; i++) {
+		out->extents[i] = 16384;
+		out->texturemins[i] = -8192;
+	    }
+	    continue;
+	}
+    }
+}
+
+
+/*
+=================
+Mod_SetParent
+=================
+*/
+void
+Mod_SetParent(mnode_t *node, mnode_t *parent)
+{
+    node->parent = parent;
+    if (node->contents < 0)
+	return;
+    Mod_SetParent(node->children[0], node);
+    Mod_SetParent(node->children[1], node);
+}
+
+/*
+=================
+Mod_LoadNodes
+=================
+*/
+void
+Mod_LoadNodes(lump_t *l)
+{
+    int i, j, count, p;
+    dnode_t *in;
+    mnode_t *out;
+
+    in = (void *)(mod_base + l->fileofs);
+    if (l->filelen % sizeof(*in))
+	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
+    count = l->filelen / sizeof(*in);
+    out = Hunk_AllocName(count * sizeof(*out), loadname);
+
+    loadmodel->nodes = out;
+    loadmodel->numnodes = count;
+
+    for (i = 0; i < count; i++, in++, out++) {
+	for (j = 0; j < 3; j++) {
+	    out->minmaxs[j] = LittleShort(in->mins[j]);
+	    out->minmaxs[3 + j] = LittleShort(in->maxs[j]);
+	}
+
+	p = LittleLong(in->planenum);
+	out->plane = loadmodel->planes + p;
+
+	out->firstsurface = (uint16_t)LittleShort(in->firstface);
+	out->numsurfaces = (uint16_t)LittleShort(in->numfaces);
+
+	for (j = 0; j < 2; j++) {
+	    p = LittleShort(in->children[j]);
+	    if (p >= 0)
+		out->children[j] = loadmodel->nodes + p;
+	    else
+		out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
+	}
+    }
+
+    Mod_SetParent(loadmodel->nodes, NULL);	// sets nodes and leafs
+}
+
+/*
+=================
+Mod_LoadLeafs
+=================
+*/
+void
+Mod_LoadLeafs(lump_t *l)
+{
+    dleaf_t *in;
+    mleaf_t *out;
+    int i, j, count, p;
+
+    in = (void *)(mod_base + l->fileofs);
+    if (l->filelen % sizeof(*in))
+	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
+    count = l->filelen / sizeof(*in);
+
+    /* FIXME - fail gracefully */
+    if (count > MAX_MAP_LEAFS)
+	Sys_Error("%s: model->numleafs > MAX_MAP_LEAFS\n", __func__);
+
+    out = Hunk_AllocName(count * sizeof(*out), loadname);
+
+    loadmodel->leafs = out;
+    loadmodel->numleafs = count;
+
+    for (i = 0; i < count; i++, in++, out++) {
+	for (j = 0; j < 3; j++) {
+	    out->minmaxs[j] = LittleShort(in->mins[j]);
+	    out->minmaxs[3 + j] = LittleShort(in->maxs[j]);
+	}
+
+	p = LittleLong(in->contents);
+	out->contents = p;
+
+	out->firstmarksurface = loadmodel->marksurfaces +
+	    (uint16_t)LittleShort(in->firstmarksurface);
+	out->nummarksurfaces =
+	    (uint16_t)LittleShort(in->nummarksurfaces);
+
+	p = LittleLong(in->visofs);
+	if (p == -1)
+	    out->compressed_vis = NULL;
+	else
+	    out->compressed_vis = loadmodel->visdata + p;
+	out->efrags = NULL;
+
+	for (j = 0; j < 4; j++)
+	    out->ambient_sound_level[j] = in->ambient_level[j];
+    }
+}
+
+/*
+=================
+Mod_LoadClipnodes
+=================
+*/
+void
+Mod_LoadClipnodes(lump_t *l)
+{
+    dclipnode_t *in, *out;
+    int i, count;
+    hull_t *hull;
+
+    in = (void *)(mod_base + l->fileofs);
+    if (l->filelen % sizeof(*in))
+	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
+    count = l->filelen / sizeof(*in);
+    out = Hunk_AllocName(count * sizeof(*out), loadname);
+
+    loadmodel->clipnodes = out;
+    loadmodel->numclipnodes = count;
+
+    hull = &loadmodel->hulls[1];
+    hull->clipnodes = out;
+    hull->firstclipnode = 0;
+    hull->lastclipnode = count - 1;
+    hull->planes = loadmodel->planes;
+    hull->clip_mins[0] = -16;
+    hull->clip_mins[1] = -16;
+    hull->clip_mins[2] = -24;
+    hull->clip_maxs[0] = 16;
+    hull->clip_maxs[1] = 16;
+    hull->clip_maxs[2] = 32;
+
+    hull = &loadmodel->hulls[2];
+    hull->clipnodes = out;
+    hull->firstclipnode = 0;
+    hull->lastclipnode = count - 1;
+    hull->planes = loadmodel->planes;
+    hull->clip_mins[0] = -32;
+    hull->clip_mins[1] = -32;
+    hull->clip_mins[2] = -24;
+    hull->clip_maxs[0] = 32;
+    hull->clip_maxs[1] = 32;
+    hull->clip_maxs[2] = 64;
+
+    for (i = 0; i < count; i++, out++, in++) {
+	out->planenum = LittleLong(in->planenum);
+	out->children[0] = LittleShort(in->children[0]);
+	out->children[1] = LittleShort(in->children[1]);
+    }
+}
+
+/*
+=================
+Mod_MakeHull0
+
+Duplicate the drawing hull structure as a clipping hull
+=================
+*/
+void
+Mod_MakeHull0(void)
+{
+    mnode_t *in, *child;
+    dclipnode_t *out;
+    int i, j, count;
+    hull_t *hull;
+
+    hull = &loadmodel->hulls[0];
+
+    in = loadmodel->nodes;
+    count = loadmodel->numnodes;
+    out = Hunk_AllocName(count * sizeof(*out), loadname);
+
+    hull->clipnodes = out;
+    hull->firstclipnode = 0;
+    hull->lastclipnode = count - 1;
+    hull->planes = loadmodel->planes;
+
+    for (i = 0; i < count; i++, out++, in++) {
+	out->planenum = in->plane - loadmodel->planes;
+	for (j = 0; j < 2; j++) {
+	    child = in->children[j];
+	    if (child->contents < 0)
+		out->children[j] = child->contents;
+	    else
+		out->children[j] = child - loadmodel->nodes;
+	}
+    }
+}
+
+/*
+=================
+Mod_LoadMarksurfaces
+=================
+*/
+void
+Mod_LoadMarksurfaces(lump_t *l)
+{
+    int i, j, count;
+    unsigned short *in;
+    msurface_t **out;
+
+    in = (void *)(mod_base + l->fileofs);
+    if (l->filelen % sizeof(*in))
+	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
+    count = l->filelen / sizeof(*in);
+    out = Hunk_AllocName(count * sizeof(*out), loadname);
+
+    loadmodel->marksurfaces = out;
+    loadmodel->nummarksurfaces = count;
+
+    for (i = 0; i < count; i++) {
+	j = (uint16_t)LittleShort(in[i]);
+	if (j >= loadmodel->numsurfaces)
+	    Sys_Error("%s: bad surface number", __func__);
+	out[i] = loadmodel->surfaces + j;
+    }
+}
+
+/*
+=================
+Mod_LoadSurfedges
+=================
+*/
+void
+Mod_LoadSurfedges(lump_t *l)
+{
+    int i, count;
+    int *in, *out;
+
+    in = (void *)(mod_base + l->fileofs);
+    if (l->filelen % sizeof(*in))
+	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
+    count = l->filelen / sizeof(*in);
+    out = Hunk_AllocName(count * sizeof(*out), loadname);
+
+    loadmodel->surfedges = out;
+    loadmodel->numsurfedges = count;
+
+    for (i = 0; i < count; i++)
+	out[i] = LittleLong(in[i]);
+}
+
+/*
+=================
+Mod_LoadPlanes
+=================
+*/
+void
+Mod_LoadPlanes(lump_t *l)
+{
+    int i, j;
+    mplane_t *out;
+    dplane_t *in;
+    int count;
+    int bits;
+
+    in = (void *)(mod_base + l->fileofs);
+    if (l->filelen % sizeof(*in))
+	Sys_Error("%s: funny lump size in %s", __func__, loadmodel->name);
+    count = l->filelen / sizeof(*in);
+    out = Hunk_AllocName(count * 2 * sizeof(*out), loadname);
+
+    loadmodel->planes = out;
+    loadmodel->numplanes = count;
+
+    for (i = 0; i < count; i++, in++, out++) {
+	bits = 0;
+	for (j = 0; j < 3; j++) {
+	    out->normal[j] = LittleFloat(in->normal[j]);
+	    if (out->normal[j] < 0)
+		bits |= 1 << j;
+	}
+
+	out->dist = LittleFloat(in->dist);
+	out->type = LittleLong(in->type);
+	out->signbits = bits;
+    }
+}
+
+/*
+=================
+RadiusFromBounds
+=================
+*/
+float
+RadiusFromBounds(vec3_t mins, vec3_t maxs)
+{
+    int i;
+    vec3_t corner;
+
+    for (i = 0; i < 3; i++) {
+	corner[i] =
+	    fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
+    }
+
+    return Length(corner);
+}
+
+/*
+=================
+Mod_LoadBrushModel
+=================
+*/
+void
+Mod_LoadBrushModel(model_t *mod, void *buffer)
+{
+    int i, j;
+    dheader_t *header;
+    dmodel_t *bm;
+
+    loadmodel->type = mod_brush;
+
+    header = (dheader_t *)buffer;
+
+    i = LittleLong(header->version);
+    if (i != BSPVERSION)
+	Sys_Error("%s: %s has wrong version number (%i should be %i)",
+		  __func__, mod->name, i, BSPVERSION);
+
+// swap all the lumps
+    mod_base = (byte *)header;
+
+    for (i = 0; i < sizeof(dheader_t) / 4; i++)
+	((int *)header)[i] = LittleLong(((int *)header)[i]);
+
+#ifdef QW_HACK
+    mod->checksum = 0;
+    mod->checksum2 = 0;
+
+// checksum all of the map, except for entities
+    for (i = 0; i < HEADER_LUMPS; i++) {
+	if (i == LUMP_ENTITIES)
+	    continue;
+	mod->checksum ^=
+	    Com_BlockChecksum(mod_base + header->lumps[i].fileofs,
+			      header->lumps[i].filelen);
+
+	if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES)
+	    continue;
+	mod->checksum2 ^=
+	    Com_BlockChecksum(mod_base + header->lumps[i].fileofs,
+			      header->lumps[i].filelen);
+    }
+#endif
+
+// load into heap
+
+    Mod_LoadVertexes(&header->lumps[LUMP_VERTEXES]);
+    Mod_LoadEdges(&header->lumps[LUMP_EDGES]);
+    Mod_LoadSurfedges(&header->lumps[LUMP_SURFEDGES]);
+    Mod_LoadTextures(&header->lumps[LUMP_TEXTURES]);
+    Mod_LoadLighting(&header->lumps[LUMP_LIGHTING]);
+    Mod_LoadPlanes(&header->lumps[LUMP_PLANES]);
+    Mod_LoadTexinfo(&header->lumps[LUMP_TEXINFO]);
+    Mod_LoadFaces(&header->lumps[LUMP_FACES]);
+    Mod_LoadMarksurfaces(&header->lumps[LUMP_MARKSURFACES]);
+    Mod_LoadVisibility(&header->lumps[LUMP_VISIBILITY]);
+    Mod_LoadLeafs(&header->lumps[LUMP_LEAFS]);
+    Mod_LoadNodes(&header->lumps[LUMP_NODES]);
+    Mod_LoadClipnodes(&header->lumps[LUMP_CLIPNODES]);
+    Mod_LoadEntities(&header->lumps[LUMP_ENTITIES]);
+    Mod_LoadSubmodels(&header->lumps[LUMP_MODELS]);
+
+    Mod_MakeHull0();
+
+    mod->numframes = 2;		// regular and alternate animation
+    mod->flags = 0;
+
+//
+// set up the submodels (FIXME: this is confusing)
+//
+    for (i = 0; i < mod->numsubmodels; i++) {
+	bm = &mod->submodels[i];
+
+	mod->hulls[0].firstclipnode = bm->headnode[0];
+	for (j = 1; j < MAX_MAP_HULLS; j++) {
+	    mod->hulls[j].firstclipnode = bm->headnode[j];
+	    mod->hulls[j].lastclipnode = mod->numclipnodes - 1;
+	}
+
+	mod->firstmodelsurface = bm->firstface;
+	mod->nummodelsurfaces = bm->numfaces;
+	mod->radius = RadiusFromBounds(mod->mins, mod->maxs);
+
+	VectorCopy(bm->maxs, mod->maxs);
+	VectorCopy(bm->mins, mod->mins);
+
+	mod->numleafs = bm->visleafs;
+
+	/* duplicate the basic information */
+	if (i < mod->numsubmodels - 1) {
+	    char name[10];
+
+	    sprintf(name, "*%i", i + 1);
+	    loadmodel = Mod_FindName(name);
+	    *loadmodel = *mod;
+	    strcpy(loadmodel->name, name);
+	    mod = loadmodel;
+	}
+    }
+}
+
+/*
+==============================================================================
+
+ALIAS MODELS
+
+==============================================================================
+*/
+
+/*
+=================
+Mod_LoadAliasFrame
+=================
+*/
+void *
+Mod_LoadAliasFrame(void *pin, int *pframeindex, int numv,
+		   trivertx_t *pbboxmin, trivertx_t *pbboxmax,
+		   aliashdr_t *pheader, char *name)
+{
+    trivertx_t *pframe, *pinframe;
+    int i, j;
+    daliasframe_t *pdaliasframe;
+
+    pdaliasframe = (daliasframe_t *)pin;
+
+    strcpy(name, pdaliasframe->name);
+
+    for (i = 0; i < 3; i++) {
+	// these are byte values, so we don't have to worry about
+	// endianness
+	pbboxmin->v[i] = pdaliasframe->bboxmin.v[i];
+	pbboxmax->v[i] = pdaliasframe->bboxmax.v[i];
+    }
+
+    pinframe = (trivertx_t *)(pdaliasframe + 1);
+    pframe = Hunk_AllocName(numv * sizeof(*pframe), loadname);
+
+    *pframeindex = (byte *)pframe - (byte *)pheader;
+
+    for (j = 0; j < numv; j++) {
+	int k;
+
+	// these are all byte values, so no need to deal with endianness
+	pframe[j].lightnormalindex = pinframe[j].lightnormalindex;
+
+	for (k = 0; k < 3; k++) {
+	    pframe[j].v[k] = pinframe[j].v[k];
+	}
+    }
+
+    pinframe += numv;
+
+    return (void *)pinframe;
+}
+
+
+/*
+=================
+Mod_LoadAliasGroup
+=================
+*/
+void *
+Mod_LoadAliasGroup(void *pin, int *pframeindex, int numv,
+		   trivertx_t *pbboxmin, trivertx_t *pbboxmax,
+		   aliashdr_t *pheader, char *name)
+{
+    daliasgroup_t *pingroup;
+    maliasgroup_t *paliasgroup;
+    int i, numframes;
+    daliasinterval_t *pin_intervals;
+    float *poutintervals;
+    void *ptemp;
+
+    pingroup = (daliasgroup_t *)pin;
+
+    numframes = LittleLong(pingroup->numframes);
+
+    paliasgroup = Hunk_AllocName(sizeof(maliasgroup_t) +
+				 (numframes -
+				  1) * sizeof(paliasgroup->frames[0]),
+				 loadname);
+
+    paliasgroup->numframes = numframes;
+
+    for (i = 0; i < 3; i++) {
+	// these are byte values, so we don't have to worry about endianness
+	pbboxmin->v[i] = pingroup->bboxmin.v[i];
+	pbboxmax->v[i] = pingroup->bboxmax.v[i];
+    }
+
+    *pframeindex = (byte *)paliasgroup - (byte *)pheader;
+
+    pin_intervals = (daliasinterval_t *)(pingroup + 1);
+
+    poutintervals = Hunk_AllocName(numframes * sizeof(float), loadname);
+
+    paliasgroup->intervals = (byte *)poutintervals - (byte *)pheader;
+
+    for (i = 0; i < numframes; i++) {
+	*poutintervals = LittleFloat(pin_intervals->interval);
+	if (*poutintervals <= 0.0)
+	    Sys_Error("%s: interval <= 0", __func__);
+
+	poutintervals++;
+	pin_intervals++;
+    }
+
+    ptemp = (void *)pin_intervals;
+
+    for (i = 0; i < numframes; i++) {
+	ptemp = Mod_LoadAliasFrame(ptemp,
+				   &paliasgroup->frames[i].frame,
+				   numv,
+				   &paliasgroup->frames[i].bboxmin,
+				   &paliasgroup->frames[i].bboxmax,
+				   pheader, name);
+    }
+
+    return ptemp;
+}
+
+
+/*
+=================
+Mod_LoadAliasSkin
+=================
+*/
+void *
+Mod_LoadAliasSkin(void *pin, int *pskinindex, int skinsize,
+		  aliashdr_t *pheader)
+{
+    int i;
+    byte *pskin, *pinskin;
+    unsigned short *pusskin;
+
+    pskin = Hunk_AllocName(skinsize * r_pixbytes, loadname);
+    pinskin = (byte *)pin;
+    *pskinindex = (byte *)pskin - (byte *)pheader;
+
+    if (r_pixbytes == 1) {
+	memcpy(pskin, pinskin, skinsize);
+    } else if (r_pixbytes == 2) {
+	pusskin = (unsigned short *)pskin;
+
+	for (i = 0; i < skinsize; i++)
+	    pusskin[i] = d_8to16table[pinskin[i]];
+    } else {
+	Sys_Error("%s: driver set invalid r_pixbytes: %d", __func__,
+		  r_pixbytes);
+    }
+
+    pinskin += skinsize;
+
+    return ((void *)pinskin);
+}
+
+
+/*
+=================
+Mod_LoadAliasSkinGroup
+=================
+*/
+void *
+Mod_LoadAliasSkinGroup(void *pin, int *pskinindex, int skinsize,
+		       aliashdr_t *pheader)
+{
+    daliasskingroup_t *pinskingroup;
+    maliasskingroup_t *paliasskingroup;
+    int i, numskins;
+    daliasskininterval_t *pinskinintervals;
+    float *poutskinintervals;
+    void *ptemp;
+
+    pinskingroup = (daliasskingroup_t *)pin;
+
+    numskins = LittleLong(pinskingroup->numskins);
+
+    paliasskingroup = Hunk_AllocName(sizeof(maliasskingroup_t) +
+				     (numskins -
+				      1) *
+				     sizeof(paliasskingroup->skindescs[0]),
+				     loadname);
+
+    paliasskingroup->numskins = numskins;
+
+    *pskinindex = (byte *)paliasskingroup - (byte *)pheader;
+    pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
+    poutskinintervals = Hunk_AllocName(numskins * sizeof(float), loadname);
+
+    paliasskingroup->intervals = (byte *)poutskinintervals - (byte *)pheader;
+
+    for (i = 0; i < numskins; i++) {
+	*poutskinintervals = LittleFloat(pinskinintervals->interval);
+	if (*poutskinintervals <= 0)
+	    Sys_Error("%s: interval <= 0", __func__);
+
+	poutskinintervals++;
+	pinskinintervals++;
+    }
+
+    ptemp = (void *)pinskinintervals;
+
+    for (i = 0; i < numskins; i++) {
+	ptemp = Mod_LoadAliasSkin(ptemp,
+				  &paliasskingroup->skindescs[i].skin,
+				  skinsize, pheader);
+    }
+
+    return ptemp;
+}
+
+
+/*
+=================
+Mod_LoadAliasModel
+=================
+*/
+void
+Mod_LoadAliasModel(model_t *mod, void *buffer)
+{
+    int i;
+    mdl_t *pmodel, *pinmodel;
+    stvert_t *pstverts, *pinstverts;
+    aliashdr_t *pheader;
+    mtriangle_t *ptri;
+    dtriangle_t *pintriangles;
+    int version, numframes, numskins;
+    int size;
+    daliasframetype_t *pframetype;
+    daliasskintype_t *pskintype;
+    maliasskindesc_t *pskindesc;
+    int skinsize;
+    int start, end, total;
+
+#ifdef QW_HACK
+    if (!strcmp(loadmodel->name, "progs/player.mdl") ||
+	!strcmp(loadmodel->name, "progs/eyes.mdl")) {
+	unsigned short crc;
+	byte *p;
+	int len;
+	char st[40];
+
+	CRC_Init(&crc);
+	for (len = com_filesize, p = buffer; len; len--, p++)
+	    CRC_ProcessByte(&crc, *p);
+
+	sprintf(st, "%d", (int)crc);
+	Info_SetValueForKey(cls.userinfo,
+			    !strcmp(loadmodel->name,
+				    "progs/player.mdl") ? pmodel_name :
+			    emodel_name, st, MAX_INFO_STRING);
+
+	if (cls.state >= ca_connected) {
+	    MSG_WriteByte(&cls.netchan.message, clc_stringcmd);
+	    sprintf(st, "setinfo %s %d",
+		    !strcmp(loadmodel->name,
+			    "progs/player.mdl") ? pmodel_name : emodel_name,
+		    (int)crc);
+	    SZ_Print(&cls.netchan.message, st);
+	}
+    }
+#endif
+
+    start = Hunk_LowMark();
+
+    pinmodel = (mdl_t *)buffer;
+
+    version = LittleLong(pinmodel->version);
+    if (version != ALIAS_VERSION)
+	Sys_Error("%s has wrong version number (%i should be %i)",
+		  mod->name, version, ALIAS_VERSION);
+
+//
+// allocate space for a working header, plus all the data except the frames,
+// skin and group info
+//
+    size = sizeof(aliashdr_t) + LittleLong(pinmodel->numframes) *
+	sizeof(pheader->frames[0]) +
+	sizeof(mdl_t) +
+	LittleLong(pinmodel->numverts) * sizeof(stvert_t) +
+	LittleLong(pinmodel->numtris) * sizeof(mtriangle_t);
+
+    pheader = Hunk_AllocName(size, loadname);
+    pmodel = (mdl_t *)((byte *)&pheader[1] +
+		       (LittleLong(pinmodel->numframes) - 1) *
+		       sizeof(pheader->frames[0]));
+
+    mod->flags = LittleLong(pinmodel->flags);
+
+//
+// endian-adjust and copy the data, starting with the alias model header
+//
+    pmodel->boundingradius = LittleFloat(pinmodel->boundingradius);
+    pmodel->numskins = LittleLong(pinmodel->numskins);
+    pmodel->skinwidth = LittleLong(pinmodel->skinwidth);
+    pmodel->skinheight = LittleLong(pinmodel->skinheight);
+
+    if (pmodel->skinheight > MAX_LBM_HEIGHT)
+	Sys_Error("model %s has a skin taller than %d", mod->name,
+		  MAX_LBM_HEIGHT);
+
+    pmodel->numverts = LittleLong(pinmodel->numverts);
+
+    if (pmodel->numverts <= 0)
+	Sys_Error("model %s has no vertices", mod->name);
+
+    if (pmodel->numverts > MAXALIASVERTS)
+	Sys_Error("model %s has too many vertices", mod->name);
+
+    pmodel->numtris = LittleLong(pinmodel->numtris);
+
+    if (pmodel->numtris <= 0)
+	Sys_Error("model %s has no triangles", mod->name);
+
+    pmodel->numframes = LittleLong(pinmodel->numframes);
+    pmodel->size = LittleFloat(pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
+    mod->synctype = LittleLong(pinmodel->synctype);
+    mod->numframes = pmodel->numframes;
+
+    for (i = 0; i < 3; i++) {
+	pmodel->scale[i] = LittleFloat(pinmodel->scale[i]);
+	pmodel->scale_origin[i] = LittleFloat(pinmodel->scale_origin[i]);
+	pmodel->eyeposition[i] = LittleFloat(pinmodel->eyeposition[i]);
+    }
+
+    numskins = pmodel->numskins;
+    numframes = pmodel->numframes;
+
+    if (pmodel->skinwidth & 0x03)
+	Sys_Error("%s: skinwidth not multiple of 4", __func__);
+
+    pheader->model = (byte *)pmodel - (byte *)pheader;
+
+//
+// load the skins
+//
+    skinsize = pmodel->skinheight * pmodel->skinwidth;
+
+    if (numskins < 1)
+	Sys_Error("%s: Invalid # of skins: %d", __func__, numskins);
+
+    pskintype = (daliasskintype_t *)&pinmodel[1];
+
+    pskindesc = Hunk_AllocName(numskins * sizeof(maliasskindesc_t), loadname);
+
+    pheader->skindesc = (byte *)pskindesc - (byte *)pheader;
+
+    for (i = 0; i < numskins; i++) {
+	aliasskintype_t skintype;
+
+	skintype = LittleLong(pskintype->type);
+	pskindesc[i].type = skintype;
+
+	if (skintype == ALIAS_SKIN_SINGLE) {
+	    pskintype = (daliasskintype_t *)
+		Mod_LoadAliasSkin(pskintype + 1,
+				  &pskindesc[i].skin, skinsize, pheader);
+	} else {
+	    pskintype = (daliasskintype_t *)
+		Mod_LoadAliasSkinGroup(pskintype + 1,
+				       &pskindesc[i].skin, skinsize, pheader);
+	}
+    }
+
+//
+// set base s and t vertices
+//
+    pstverts = (stvert_t *)&pmodel[1];
+    pinstverts = (stvert_t *)pskintype;
+
+    pheader->stverts = (byte *)pstverts - (byte *)pheader;
+
+    for (i = 0; i < pmodel->numverts; i++) {
+	pstverts[i].onseam = LittleLong(pinstverts[i].onseam);
+	// put s and t in 16.16 format
+	pstverts[i].s = LittleLong(pinstverts[i].s) << 16;
+	pstverts[i].t = LittleLong(pinstverts[i].t) << 16;
+    }
+
+//
+// set up the triangles
+//
+    ptri = (mtriangle_t *)&pstverts[pmodel->numverts];
+    pintriangles = (dtriangle_t *)&pinstverts[pmodel->numverts];
+
+    pheader->triangles = (byte *)ptri - (byte *)pheader;
+
+    for (i = 0; i < pmodel->numtris; i++) {
+	int j;
+
+	ptri[i].facesfront = LittleLong(pintriangles[i].facesfront);
+
+	for (j = 0; j < 3; j++) {
+	    ptri[i].vertindex[j] = LittleLong(pintriangles[i].vertindex[j]);
+	}
+    }
+
+//
+// load the frames
+//
+    if (numframes < 1)
+	Sys_Error("%s: Invalid # of frames: %d", __func__, numframes);
+
+    pframetype = (daliasframetype_t *)&pintriangles[pmodel->numtris];
+
+    for (i = 0; i < numframes; i++) {
+	aliasframetype_t frametype;
+
+	frametype = LittleLong(pframetype->type);
+	pheader->frames[i].type = frametype;
+
+	if (frametype == ALIAS_SINGLE) {
+	    pframetype = (daliasframetype_t *)
+		Mod_LoadAliasFrame(pframetype + 1,
+				   &pheader->frames[i].frame,
+				   pmodel->numverts,
+				   &pheader->frames[i].bboxmin,
+				   &pheader->frames[i].bboxmax,
+				   pheader, pheader->frames[i].name);
+	} else {
+	    pframetype = (daliasframetype_t *)
+		Mod_LoadAliasGroup(pframetype + 1,
+				   &pheader->frames[i].frame,
+				   pmodel->numverts,
+				   &pheader->frames[i].bboxmin,
+				   &pheader->frames[i].bboxmax,
+				   pheader, pheader->frames[i].name);
+	}
+    }
+
+    mod->type = mod_alias;
+
+// FIXME: do this right
+    mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
+    mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
+
+//
+// move the complete, relocatable alias model to the cache
+//
+    end = Hunk_LowMark();
+    total = end - start;
+
+    Cache_Alloc(&mod->cache, total, loadname);
+    if (!mod->cache.data)
+	return;
+    memcpy(mod->cache.data, pheader, total);
+
+    Hunk_FreeToLowMark(start);
+}
+
+//=============================================================================
+
+/*
+=================
+Mod_LoadSpriteFrame
+=================
+*/
+void *
+Mod_LoadSpriteFrame(void *pin, mspriteframe_t **ppframe)
+{
+    dspriteframe_t *pinframe;
+    mspriteframe_t *pspriteframe;
+    int i, width, height, size, origin[2];
+    unsigned short *ppixout;
+    byte *ppixin;
+
+    pinframe = (dspriteframe_t *)pin;
+
+    width = LittleLong(pinframe->width);
+    height = LittleLong(pinframe->height);
+    size = width * height;
+
+    pspriteframe =
+	Hunk_AllocName(sizeof(mspriteframe_t) + size * r_pixbytes, loadname);
+
+    memset(pspriteframe, 0, sizeof(mspriteframe_t) + size);
+    *ppframe = pspriteframe;
+
+    pspriteframe->width = width;
+    pspriteframe->height = height;
+    origin[0] = LittleLong(pinframe->origin[0]);
+    origin[1] = LittleLong(pinframe->origin[1]);
+
+    pspriteframe->up = origin[1];
+    pspriteframe->down = origin[1] - height;
+    pspriteframe->left = origin[0];
+    pspriteframe->right = width + origin[0];
+
+    if (r_pixbytes == 1) {
+	memcpy(&pspriteframe->pixels[0], (byte *)(pinframe + 1), size);
+    } else if (r_pixbytes == 2) {
+	ppixin = (byte *)(pinframe + 1);
+	ppixout = (unsigned short *)&pspriteframe->pixels[0];
+
+	for (i = 0; i < size; i++)
+	    ppixout[i] = d_8to16table[ppixin[i]];
+    } else {
+	Sys_Error("%s: driver set invalid r_pixbytes: %d", __func__,
+		  r_pixbytes);
+    }
+
+    return (void *)((byte *)pinframe + sizeof(dspriteframe_t) + size);
+}
+
+
+/*
+=================
+Mod_LoadSpriteGroup
+=================
+*/
+void *
+Mod_LoadSpriteGroup(void *pin, mspriteframe_t **ppframe)
+{
+    dspritegroup_t *pingroup;
+    mspritegroup_t *pspritegroup;
+    int i, numframes;
+    dspriteinterval_t *pin_intervals;
+    float *poutintervals;
+    void *ptemp;
+
+    pingroup = (dspritegroup_t *)pin;
+
+    numframes = LittleLong(pingroup->numframes);
+
+    pspritegroup = Hunk_AllocName(sizeof(mspritegroup_t) +
+				  (numframes -
+				   1) * sizeof(pspritegroup->frames[0]),
+				  loadname);
+
+    pspritegroup->numframes = numframes;
+
+    *ppframe = (mspriteframe_t *)pspritegroup;
+
+    pin_intervals = (dspriteinterval_t *)(pingroup + 1);
+
+    poutintervals = Hunk_AllocName(numframes * sizeof(float), loadname);
+
+    pspritegroup->intervals = poutintervals;
+
+    for (i = 0; i < numframes; i++) {
+	*poutintervals = LittleFloat(pin_intervals->interval);
+	if (*poutintervals <= 0.0)
+	    Sys_Error("%s: interval <= 0", __func__);
+
+	poutintervals++;
+	pin_intervals++;
+    }
+
+    ptemp = (void *)pin_intervals;
+
+    for (i = 0; i < numframes; i++) {
+	ptemp = Mod_LoadSpriteFrame(ptemp, &pspritegroup->frames[i]);
+    }
+
+    return ptemp;
+}
+
+
+/*
+=================
+Mod_LoadSpriteModel
+=================
+*/
+void
+Mod_LoadSpriteModel(model_t *mod, void *buffer)
+{
+    int i;
+    int version;
+    dsprite_t *pin;
+    msprite_t *psprite;
+    int numframes;
+    int size;
+    dspriteframetype_t *pframetype;
+
+    pin = (dsprite_t *) buffer;
+
+    version = LittleLong(pin->version);
+    if (version != SPRITE_VERSION)
+	Sys_Error("%s has wrong version number "
+		  "(%i should be %i)", mod->name, version, SPRITE_VERSION);
+
+    numframes = LittleLong(pin->numframes);
+
+    size = sizeof(msprite_t) + (numframes - 1) * sizeof(psprite->frames);
+
+    psprite = Hunk_AllocName(size, loadname);
+    psprite->type = LittleLong(pin->type);
+    psprite->maxwidth = LittleLong(pin->width);
+    psprite->maxheight = LittleLong(pin->height);
+    psprite->beamlength = LittleFloat(pin->beamlength);
+    mod->synctype = LittleLong(pin->synctype);
+    psprite->numframes = numframes;
+
+    mod->mins[0] = mod->mins[1] = -psprite->maxwidth / 2;
+    mod->maxs[0] = mod->maxs[1] = psprite->maxwidth / 2;
+    mod->mins[2] = -psprite->maxheight / 2;
+    mod->maxs[2] = psprite->maxheight / 2;
+
+//
+// load the frames
+//
+    if (numframes < 1)
+	Sys_Error("%s: Invalid # of frames: %d", __func__, numframes);
+
+    mod->numframes = numframes;
+    mod->flags = 0;
+
+    pframetype = (dspriteframetype_t *) (pin + 1);
+
+    for (i = 0; i < numframes; i++) {
+	spriteframetype_t frametype;
+
+	frametype = LittleLong(pframetype->type);
+	psprite->frames[i].type = frametype;
+
+	if (frametype == SPR_SINGLE) {
+	    pframetype = (dspriteframetype_t *)
+		Mod_LoadSpriteFrame(pframetype + 1,
+				    &psprite->frames[i].frameptr);
+	} else {
+	    pframetype = (dspriteframetype_t *)
+		Mod_LoadSpriteGroup(pframetype + 1,
+				    &psprite->frames[i].frameptr);
+	}
+    }
+
+    mod->type = mod_sprite;
+}
+
+//=============================================================================
+
+/*
+================
+Mod_Print
+================
+*/
+void
+Mod_Print(void)
+{
+    int i;
+    model_t *mod;
+
+    Con_Printf("Cached models:\n");
+    for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++)
+	Con_Printf("%8p : %s\n", mod->cache.data, mod->name);
+}
