Itsa me, quake3io!
This commit is contained in:
parent
dbe4ddb103
commit
5b755058f5
1409 changed files with 798983 additions and 798983 deletions
1678
code/qcommon/cm_load.c
Normal file → Executable file
1678
code/qcommon/cm_load.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
388
code/qcommon/cm_local.h
Normal file → Executable file
388
code/qcommon/cm_local.h
Normal file → Executable file
|
@ -1,194 +1,194 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "qcommon.h"
|
||||
#include "cm_polylib.h"
|
||||
|
||||
#define MAX_SUBMODELS 256
|
||||
#define BOX_MODEL_HANDLE 255
|
||||
#define CAPSULE_MODEL_HANDLE 254
|
||||
|
||||
|
||||
typedef struct {
|
||||
cplane_t *plane;
|
||||
int children[2]; // negative numbers are leafs
|
||||
} cNode_t;
|
||||
|
||||
typedef struct {
|
||||
int cluster;
|
||||
int area;
|
||||
|
||||
int firstLeafBrush;
|
||||
int numLeafBrushes;
|
||||
|
||||
int firstLeafSurface;
|
||||
int numLeafSurfaces;
|
||||
} cLeaf_t;
|
||||
|
||||
typedef struct cmodel_s {
|
||||
vec3_t mins, maxs;
|
||||
cLeaf_t leaf; // submodels don't reference the main tree
|
||||
} cmodel_t;
|
||||
|
||||
typedef struct {
|
||||
cplane_t *plane;
|
||||
int surfaceFlags;
|
||||
int shaderNum;
|
||||
} cbrushside_t;
|
||||
|
||||
typedef struct {
|
||||
int shaderNum; // the shader that determined the contents
|
||||
int contents;
|
||||
vec3_t bounds[2];
|
||||
int numsides;
|
||||
cbrushside_t *sides;
|
||||
int checkcount; // to avoid repeated testings
|
||||
} cbrush_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int checkcount; // to avoid repeated testings
|
||||
int surfaceFlags;
|
||||
int contents;
|
||||
struct patchCollide_s *pc;
|
||||
} cPatch_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int floodnum;
|
||||
int floodvalid;
|
||||
} cArea_t;
|
||||
|
||||
typedef struct {
|
||||
char name[MAX_QPATH];
|
||||
|
||||
int numShaders;
|
||||
dshader_t *shaders;
|
||||
|
||||
int numBrushSides;
|
||||
cbrushside_t *brushsides;
|
||||
|
||||
int numPlanes;
|
||||
cplane_t *planes;
|
||||
|
||||
int numNodes;
|
||||
cNode_t *nodes;
|
||||
|
||||
int numLeafs;
|
||||
cLeaf_t *leafs;
|
||||
|
||||
int numLeafBrushes;
|
||||
int *leafbrushes;
|
||||
|
||||
int numLeafSurfaces;
|
||||
int *leafsurfaces;
|
||||
|
||||
int numSubModels;
|
||||
cmodel_t *cmodels;
|
||||
|
||||
int numBrushes;
|
||||
cbrush_t *brushes;
|
||||
|
||||
int numClusters;
|
||||
int clusterBytes;
|
||||
byte *visibility;
|
||||
qboolean vised; // if false, visibility is just a single cluster of ffs
|
||||
|
||||
int numEntityChars;
|
||||
char *entityString;
|
||||
|
||||
int numAreas;
|
||||
cArea_t *areas;
|
||||
int *areaPortals; // [ numAreas*numAreas ] reference counts
|
||||
|
||||
int numSurfaces;
|
||||
cPatch_t **surfaces; // non-patches will be NULL
|
||||
|
||||
int floodvalid;
|
||||
int checkcount; // incremented on each trace
|
||||
} clipMap_t;
|
||||
|
||||
|
||||
// keep 1/8 unit away to keep the position valid before network snapping
|
||||
// and to avoid various numeric issues
|
||||
#define SURFACE_CLIP_EPSILON (0.125)
|
||||
|
||||
extern clipMap_t cm;
|
||||
extern int c_pointcontents;
|
||||
extern int c_traces, c_brush_traces, c_patch_traces;
|
||||
extern cvar_t *cm_noAreas;
|
||||
extern cvar_t *cm_noCurves;
|
||||
extern cvar_t *cm_playerCurveClip;
|
||||
|
||||
// cm_test.c
|
||||
|
||||
// Used for oriented capsule collision detection
|
||||
typedef struct
|
||||
{
|
||||
qboolean use;
|
||||
float radius;
|
||||
float halfheight;
|
||||
vec3_t offset;
|
||||
} sphere_t;
|
||||
|
||||
typedef struct {
|
||||
vec3_t start;
|
||||
vec3_t end;
|
||||
vec3_t size[2]; // size of the box being swept through the model
|
||||
vec3_t offsets[8]; // [signbits][x] = either size[0][x] or size[1][x]
|
||||
float maxOffset; // longest corner length from origin
|
||||
vec3_t extents; // greatest of abs(size[0]) and abs(size[1])
|
||||
vec3_t bounds[2]; // enclosing box of start and end surrounding by size
|
||||
vec3_t modelOrigin;// origin of the model tracing through
|
||||
int contents; // ored contents of the model tracing through
|
||||
qboolean isPoint; // optimized case
|
||||
trace_t trace; // returned from trace call
|
||||
sphere_t sphere; // sphere for oriendted capsule collision
|
||||
} traceWork_t;
|
||||
|
||||
typedef struct leafList_s {
|
||||
int count;
|
||||
int maxcount;
|
||||
qboolean overflowed;
|
||||
int *list;
|
||||
vec3_t bounds[2];
|
||||
int lastLeaf; // for overflows where each leaf can't be stored individually
|
||||
void (*storeLeafs)( struct leafList_s *ll, int nodenum );
|
||||
} leafList_t;
|
||||
|
||||
|
||||
int CM_BoxBrushes( const vec3_t mins, const vec3_t maxs, cbrush_t **list, int listsize );
|
||||
|
||||
void CM_StoreLeafs( leafList_t *ll, int nodenum );
|
||||
void CM_StoreBrushes( leafList_t *ll, int nodenum );
|
||||
|
||||
void CM_BoxLeafnums_r( leafList_t *ll, int nodenum );
|
||||
|
||||
cmodel_t *CM_ClipHandleToModel( clipHandle_t handle );
|
||||
|
||||
// cm_patch.c
|
||||
|
||||
struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, vec3_t *points );
|
||||
void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc );
|
||||
qboolean CM_PositionTestInPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc );
|
||||
void CM_ClearLevelPatches( void );
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "qcommon.h"
|
||||
#include "cm_polylib.h"
|
||||
|
||||
#define MAX_SUBMODELS 256
|
||||
#define BOX_MODEL_HANDLE 255
|
||||
#define CAPSULE_MODEL_HANDLE 254
|
||||
|
||||
|
||||
typedef struct {
|
||||
cplane_t *plane;
|
||||
int children[2]; // negative numbers are leafs
|
||||
} cNode_t;
|
||||
|
||||
typedef struct {
|
||||
int cluster;
|
||||
int area;
|
||||
|
||||
int firstLeafBrush;
|
||||
int numLeafBrushes;
|
||||
|
||||
int firstLeafSurface;
|
||||
int numLeafSurfaces;
|
||||
} cLeaf_t;
|
||||
|
||||
typedef struct cmodel_s {
|
||||
vec3_t mins, maxs;
|
||||
cLeaf_t leaf; // submodels don't reference the main tree
|
||||
} cmodel_t;
|
||||
|
||||
typedef struct {
|
||||
cplane_t *plane;
|
||||
int surfaceFlags;
|
||||
int shaderNum;
|
||||
} cbrushside_t;
|
||||
|
||||
typedef struct {
|
||||
int shaderNum; // the shader that determined the contents
|
||||
int contents;
|
||||
vec3_t bounds[2];
|
||||
int numsides;
|
||||
cbrushside_t *sides;
|
||||
int checkcount; // to avoid repeated testings
|
||||
} cbrush_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int checkcount; // to avoid repeated testings
|
||||
int surfaceFlags;
|
||||
int contents;
|
||||
struct patchCollide_s *pc;
|
||||
} cPatch_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int floodnum;
|
||||
int floodvalid;
|
||||
} cArea_t;
|
||||
|
||||
typedef struct {
|
||||
char name[MAX_QPATH];
|
||||
|
||||
int numShaders;
|
||||
dshader_t *shaders;
|
||||
|
||||
int numBrushSides;
|
||||
cbrushside_t *brushsides;
|
||||
|
||||
int numPlanes;
|
||||
cplane_t *planes;
|
||||
|
||||
int numNodes;
|
||||
cNode_t *nodes;
|
||||
|
||||
int numLeafs;
|
||||
cLeaf_t *leafs;
|
||||
|
||||
int numLeafBrushes;
|
||||
int *leafbrushes;
|
||||
|
||||
int numLeafSurfaces;
|
||||
int *leafsurfaces;
|
||||
|
||||
int numSubModels;
|
||||
cmodel_t *cmodels;
|
||||
|
||||
int numBrushes;
|
||||
cbrush_t *brushes;
|
||||
|
||||
int numClusters;
|
||||
int clusterBytes;
|
||||
byte *visibility;
|
||||
qboolean vised; // if false, visibility is just a single cluster of ffs
|
||||
|
||||
int numEntityChars;
|
||||
char *entityString;
|
||||
|
||||
int numAreas;
|
||||
cArea_t *areas;
|
||||
int *areaPortals; // [ numAreas*numAreas ] reference counts
|
||||
|
||||
int numSurfaces;
|
||||
cPatch_t **surfaces; // non-patches will be NULL
|
||||
|
||||
int floodvalid;
|
||||
int checkcount; // incremented on each trace
|
||||
} clipMap_t;
|
||||
|
||||
|
||||
// keep 1/8 unit away to keep the position valid before network snapping
|
||||
// and to avoid various numeric issues
|
||||
#define SURFACE_CLIP_EPSILON (0.125)
|
||||
|
||||
extern clipMap_t cm;
|
||||
extern int c_pointcontents;
|
||||
extern int c_traces, c_brush_traces, c_patch_traces;
|
||||
extern cvar_t *cm_noAreas;
|
||||
extern cvar_t *cm_noCurves;
|
||||
extern cvar_t *cm_playerCurveClip;
|
||||
|
||||
// cm_test.c
|
||||
|
||||
// Used for oriented capsule collision detection
|
||||
typedef struct
|
||||
{
|
||||
qboolean use;
|
||||
float radius;
|
||||
float halfheight;
|
||||
vec3_t offset;
|
||||
} sphere_t;
|
||||
|
||||
typedef struct {
|
||||
vec3_t start;
|
||||
vec3_t end;
|
||||
vec3_t size[2]; // size of the box being swept through the model
|
||||
vec3_t offsets[8]; // [signbits][x] = either size[0][x] or size[1][x]
|
||||
float maxOffset; // longest corner length from origin
|
||||
vec3_t extents; // greatest of abs(size[0]) and abs(size[1])
|
||||
vec3_t bounds[2]; // enclosing box of start and end surrounding by size
|
||||
vec3_t modelOrigin;// origin of the model tracing through
|
||||
int contents; // ored contents of the model tracing through
|
||||
qboolean isPoint; // optimized case
|
||||
trace_t trace; // returned from trace call
|
||||
sphere_t sphere; // sphere for oriendted capsule collision
|
||||
} traceWork_t;
|
||||
|
||||
typedef struct leafList_s {
|
||||
int count;
|
||||
int maxcount;
|
||||
qboolean overflowed;
|
||||
int *list;
|
||||
vec3_t bounds[2];
|
||||
int lastLeaf; // for overflows where each leaf can't be stored individually
|
||||
void (*storeLeafs)( struct leafList_s *ll, int nodenum );
|
||||
} leafList_t;
|
||||
|
||||
|
||||
int CM_BoxBrushes( const vec3_t mins, const vec3_t maxs, cbrush_t **list, int listsize );
|
||||
|
||||
void CM_StoreLeafs( leafList_t *ll, int nodenum );
|
||||
void CM_StoreBrushes( leafList_t *ll, int nodenum );
|
||||
|
||||
void CM_BoxLeafnums_r( leafList_t *ll, int nodenum );
|
||||
|
||||
cmodel_t *CM_ClipHandleToModel( clipHandle_t handle );
|
||||
|
||||
// cm_patch.c
|
||||
|
||||
struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, vec3_t *points );
|
||||
void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc );
|
||||
qboolean CM_PositionTestInPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc );
|
||||
void CM_ClearLevelPatches( void );
|
||||
|
|
3542
code/qcommon/cm_patch.c
Normal file → Executable file
3542
code/qcommon/cm_patch.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
206
code/qcommon/cm_patch.h
Normal file → Executable file
206
code/qcommon/cm_patch.h
Normal file → Executable file
|
@ -1,103 +1,103 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//#define CULL_BBOX
|
||||
|
||||
/*
|
||||
|
||||
This file does not reference any globals, and has these entry points:
|
||||
|
||||
void CM_ClearLevelPatches( void );
|
||||
struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, const vec3_t *points );
|
||||
void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc );
|
||||
qboolean CM_PositionTestInPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc );
|
||||
void CM_DrawDebugSurface( void (*drawPoly)(int color, int numPoints, flaot *points) );
|
||||
|
||||
|
||||
Issues for collision against curved surfaces:
|
||||
|
||||
Surface edges need to be handled differently than surface planes
|
||||
|
||||
Plane expansion causes raw surfaces to expand past expanded bounding box
|
||||
|
||||
Position test of a volume against a surface is tricky.
|
||||
|
||||
Position test of a point against a surface is not well defined, because the surface has no volume.
|
||||
|
||||
|
||||
Tracing leading edge points instead of volumes?
|
||||
Position test by tracing corner to corner? (8*7 traces -- ouch)
|
||||
|
||||
coplanar edges
|
||||
triangulated patches
|
||||
degenerate patches
|
||||
|
||||
endcaps
|
||||
degenerate
|
||||
|
||||
WARNING: this may misbehave with meshes that have rows or columns that only
|
||||
degenerate a few triangles. Completely degenerate rows and columns are handled
|
||||
properly.
|
||||
*/
|
||||
|
||||
|
||||
#define MAX_FACETS 1024
|
||||
#define MAX_PATCH_PLANES 2048
|
||||
|
||||
typedef struct {
|
||||
float plane[4];
|
||||
int signbits; // signx + (signy<<1) + (signz<<2), used as lookup during collision
|
||||
} patchPlane_t;
|
||||
|
||||
typedef struct {
|
||||
int surfacePlane;
|
||||
int numBorders; // 3 or four + 6 axial bevels + 4 or 3 * 4 edge bevels
|
||||
int borderPlanes[4+6+16];
|
||||
int borderInward[4+6+16];
|
||||
qboolean borderNoAdjust[4+6+16];
|
||||
} facet_t;
|
||||
|
||||
typedef struct patchCollide_s {
|
||||
vec3_t bounds[2];
|
||||
int numPlanes; // surface planes plus edge planes
|
||||
patchPlane_t *planes;
|
||||
int numFacets;
|
||||
facet_t *facets;
|
||||
} patchCollide_t;
|
||||
|
||||
|
||||
#define MAX_GRID_SIZE 129
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
qboolean wrapWidth;
|
||||
qboolean wrapHeight;
|
||||
vec3_t points[MAX_GRID_SIZE][MAX_GRID_SIZE]; // [width][height]
|
||||
} cGrid_t;
|
||||
|
||||
#define SUBDIVIDE_DISTANCE 16 //4 // never more than this units away from curve
|
||||
#define PLANE_TRI_EPSILON 0.1
|
||||
#define WRAP_POINT_EPSILON 0.1
|
||||
|
||||
|
||||
struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, vec3_t *points );
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
//#define CULL_BBOX
|
||||
|
||||
/*
|
||||
|
||||
This file does not reference any globals, and has these entry points:
|
||||
|
||||
void CM_ClearLevelPatches( void );
|
||||
struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, const vec3_t *points );
|
||||
void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc );
|
||||
qboolean CM_PositionTestInPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc );
|
||||
void CM_DrawDebugSurface( void (*drawPoly)(int color, int numPoints, flaot *points) );
|
||||
|
||||
|
||||
Issues for collision against curved surfaces:
|
||||
|
||||
Surface edges need to be handled differently than surface planes
|
||||
|
||||
Plane expansion causes raw surfaces to expand past expanded bounding box
|
||||
|
||||
Position test of a volume against a surface is tricky.
|
||||
|
||||
Position test of a point against a surface is not well defined, because the surface has no volume.
|
||||
|
||||
|
||||
Tracing leading edge points instead of volumes?
|
||||
Position test by tracing corner to corner? (8*7 traces -- ouch)
|
||||
|
||||
coplanar edges
|
||||
triangulated patches
|
||||
degenerate patches
|
||||
|
||||
endcaps
|
||||
degenerate
|
||||
|
||||
WARNING: this may misbehave with meshes that have rows or columns that only
|
||||
degenerate a few triangles. Completely degenerate rows and columns are handled
|
||||
properly.
|
||||
*/
|
||||
|
||||
|
||||
#define MAX_FACETS 1024
|
||||
#define MAX_PATCH_PLANES 2048
|
||||
|
||||
typedef struct {
|
||||
float plane[4];
|
||||
int signbits; // signx + (signy<<1) + (signz<<2), used as lookup during collision
|
||||
} patchPlane_t;
|
||||
|
||||
typedef struct {
|
||||
int surfacePlane;
|
||||
int numBorders; // 3 or four + 6 axial bevels + 4 or 3 * 4 edge bevels
|
||||
int borderPlanes[4+6+16];
|
||||
int borderInward[4+6+16];
|
||||
qboolean borderNoAdjust[4+6+16];
|
||||
} facet_t;
|
||||
|
||||
typedef struct patchCollide_s {
|
||||
vec3_t bounds[2];
|
||||
int numPlanes; // surface planes plus edge planes
|
||||
patchPlane_t *planes;
|
||||
int numFacets;
|
||||
facet_t *facets;
|
||||
} patchCollide_t;
|
||||
|
||||
|
||||
#define MAX_GRID_SIZE 129
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
qboolean wrapWidth;
|
||||
qboolean wrapHeight;
|
||||
vec3_t points[MAX_GRID_SIZE][MAX_GRID_SIZE]; // [width][height]
|
||||
} cGrid_t;
|
||||
|
||||
#define SUBDIVIDE_DISTANCE 16 //4 // never more than this units away from curve
|
||||
#define PLANE_TRI_EPSILON 0.1
|
||||
#define WRAP_POINT_EPSILON 0.1
|
||||
|
||||
|
||||
struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, vec3_t *points );
|
||||
|
|
1474
code/qcommon/cm_polylib.c
Normal file → Executable file
1474
code/qcommon/cm_polylib.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
136
code/qcommon/cm_polylib.h
Normal file → Executable file
136
code/qcommon/cm_polylib.h
Normal file → Executable file
|
@ -1,68 +1,68 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// this is only used for visualization tools in cm_ debug functions
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numpoints;
|
||||
vec3_t p[4]; // variable sized
|
||||
} winding_t;
|
||||
|
||||
#define MAX_POINTS_ON_WINDING 64
|
||||
|
||||
#define SIDE_FRONT 0
|
||||
#define SIDE_BACK 1
|
||||
#define SIDE_ON 2
|
||||
#define SIDE_CROSS 3
|
||||
|
||||
#define CLIP_EPSILON 0.1f
|
||||
|
||||
#define MAX_MAP_BOUNDS 65535
|
||||
|
||||
// you can define on_epsilon in the makefile as tighter
|
||||
#ifndef ON_EPSILON
|
||||
#define ON_EPSILON 0.1f
|
||||
#endif
|
||||
|
||||
winding_t *AllocWinding (int points);
|
||||
vec_t WindingArea (winding_t *w);
|
||||
void WindingCenter (winding_t *w, vec3_t center);
|
||||
void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist,
|
||||
vec_t epsilon, winding_t **front, winding_t **back);
|
||||
winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist);
|
||||
winding_t *CopyWinding (winding_t *w);
|
||||
winding_t *ReverseWinding (winding_t *w);
|
||||
winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist);
|
||||
void CheckWinding (winding_t *w);
|
||||
void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist);
|
||||
void RemoveColinearPoints (winding_t *w);
|
||||
int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist);
|
||||
void FreeWinding (winding_t *w);
|
||||
void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs);
|
||||
|
||||
void AddWindingToConvexHull( winding_t *w, winding_t **hull, vec3_t normal );
|
||||
|
||||
void ChopWindingInPlace (winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon);
|
||||
// frees the original if clipped
|
||||
|
||||
void pw(winding_t *w);
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// this is only used for visualization tools in cm_ debug functions
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numpoints;
|
||||
vec3_t p[4]; // variable sized
|
||||
} winding_t;
|
||||
|
||||
#define MAX_POINTS_ON_WINDING 64
|
||||
|
||||
#define SIDE_FRONT 0
|
||||
#define SIDE_BACK 1
|
||||
#define SIDE_ON 2
|
||||
#define SIDE_CROSS 3
|
||||
|
||||
#define CLIP_EPSILON 0.1f
|
||||
|
||||
#define MAX_MAP_BOUNDS 65535
|
||||
|
||||
// you can define on_epsilon in the makefile as tighter
|
||||
#ifndef ON_EPSILON
|
||||
#define ON_EPSILON 0.1f
|
||||
#endif
|
||||
|
||||
winding_t *AllocWinding (int points);
|
||||
vec_t WindingArea (winding_t *w);
|
||||
void WindingCenter (winding_t *w, vec3_t center);
|
||||
void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist,
|
||||
vec_t epsilon, winding_t **front, winding_t **back);
|
||||
winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist);
|
||||
winding_t *CopyWinding (winding_t *w);
|
||||
winding_t *ReverseWinding (winding_t *w);
|
||||
winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist);
|
||||
void CheckWinding (winding_t *w);
|
||||
void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist);
|
||||
void RemoveColinearPoints (winding_t *w);
|
||||
int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist);
|
||||
void FreeWinding (winding_t *w);
|
||||
void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs);
|
||||
|
||||
void AddWindingToConvexHull( winding_t *w, winding_t **hull, vec3_t normal );
|
||||
|
||||
void ChopWindingInPlace (winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon);
|
||||
// frees the original if clipped
|
||||
|
||||
void pw(winding_t *w);
|
||||
|
|
152
code/qcommon/cm_public.h
Normal file → Executable file
152
code/qcommon/cm_public.h
Normal file → Executable file
|
@ -1,76 +1,76 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "qfiles.h"
|
||||
|
||||
|
||||
void CM_LoadMap( const char *name, qboolean clientload, int *checksum);
|
||||
void CM_ClearMap( void );
|
||||
clipHandle_t CM_InlineModel( int index ); // 0 = world, 1 + are bmodels
|
||||
clipHandle_t CM_TempBoxModel( const vec3_t mins, const vec3_t maxs, int capsule );
|
||||
|
||||
void CM_ModelBounds( clipHandle_t model, vec3_t mins, vec3_t maxs );
|
||||
|
||||
int CM_NumClusters (void);
|
||||
int CM_NumInlineModels( void );
|
||||
char *CM_EntityString (void);
|
||||
|
||||
// returns an ORed contents mask
|
||||
int CM_PointContents( const vec3_t p, clipHandle_t model );
|
||||
int CM_TransformedPointContents( const vec3_t p, clipHandle_t model, const vec3_t origin, const vec3_t angles );
|
||||
|
||||
void CM_BoxTrace ( trace_t *results, const vec3_t start, const vec3_t end,
|
||||
vec3_t mins, vec3_t maxs,
|
||||
clipHandle_t model, int brushmask, int capsule );
|
||||
void CM_TransformedBoxTrace( trace_t *results, const vec3_t start, const vec3_t end,
|
||||
vec3_t mins, vec3_t maxs,
|
||||
clipHandle_t model, int brushmask,
|
||||
const vec3_t origin, const vec3_t angles, int capsule );
|
||||
|
||||
byte *CM_ClusterPVS (int cluster);
|
||||
|
||||
int CM_PointLeafnum( const vec3_t p );
|
||||
|
||||
// only returns non-solid leafs
|
||||
// overflow if return listsize and if *lastLeaf != list[listsize-1]
|
||||
int CM_BoxLeafnums( const vec3_t mins, const vec3_t maxs, int *list,
|
||||
int listsize, int *lastLeaf );
|
||||
|
||||
int CM_LeafCluster (int leafnum);
|
||||
int CM_LeafArea (int leafnum);
|
||||
|
||||
void CM_AdjustAreaPortalState( int area1, int area2, qboolean open );
|
||||
qboolean CM_AreasConnected( int area1, int area2 );
|
||||
|
||||
int CM_WriteAreaBits( byte *buffer, int area );
|
||||
|
||||
// cm_tag.c
|
||||
int CM_LerpTag( orientation_t *tag, clipHandle_t model, int startFrame, int endFrame,
|
||||
float frac, const char *tagName );
|
||||
|
||||
|
||||
// cm_marks.c
|
||||
int CM_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection,
|
||||
int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer );
|
||||
|
||||
// cm_patch.c
|
||||
void CM_DrawDebugSurface( void (*drawPoly)(int color, int numPoints, float *points) );
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "qfiles.h"
|
||||
|
||||
|
||||
void CM_LoadMap( const char *name, qboolean clientload, int *checksum);
|
||||
void CM_ClearMap( void );
|
||||
clipHandle_t CM_InlineModel( int index ); // 0 = world, 1 + are bmodels
|
||||
clipHandle_t CM_TempBoxModel( const vec3_t mins, const vec3_t maxs, int capsule );
|
||||
|
||||
void CM_ModelBounds( clipHandle_t model, vec3_t mins, vec3_t maxs );
|
||||
|
||||
int CM_NumClusters (void);
|
||||
int CM_NumInlineModels( void );
|
||||
char *CM_EntityString (void);
|
||||
|
||||
// returns an ORed contents mask
|
||||
int CM_PointContents( const vec3_t p, clipHandle_t model );
|
||||
int CM_TransformedPointContents( const vec3_t p, clipHandle_t model, const vec3_t origin, const vec3_t angles );
|
||||
|
||||
void CM_BoxTrace ( trace_t *results, const vec3_t start, const vec3_t end,
|
||||
vec3_t mins, vec3_t maxs,
|
||||
clipHandle_t model, int brushmask, int capsule );
|
||||
void CM_TransformedBoxTrace( trace_t *results, const vec3_t start, const vec3_t end,
|
||||
vec3_t mins, vec3_t maxs,
|
||||
clipHandle_t model, int brushmask,
|
||||
const vec3_t origin, const vec3_t angles, int capsule );
|
||||
|
||||
byte *CM_ClusterPVS (int cluster);
|
||||
|
||||
int CM_PointLeafnum( const vec3_t p );
|
||||
|
||||
// only returns non-solid leafs
|
||||
// overflow if return listsize and if *lastLeaf != list[listsize-1]
|
||||
int CM_BoxLeafnums( const vec3_t mins, const vec3_t maxs, int *list,
|
||||
int listsize, int *lastLeaf );
|
||||
|
||||
int CM_LeafCluster (int leafnum);
|
||||
int CM_LeafArea (int leafnum);
|
||||
|
||||
void CM_AdjustAreaPortalState( int area1, int area2, qboolean open );
|
||||
qboolean CM_AreasConnected( int area1, int area2 );
|
||||
|
||||
int CM_WriteAreaBits( byte *buffer, int area );
|
||||
|
||||
// cm_tag.c
|
||||
int CM_LerpTag( orientation_t *tag, clipHandle_t model, int startFrame, int endFrame,
|
||||
float frac, const char *tagName );
|
||||
|
||||
|
||||
// cm_marks.c
|
||||
int CM_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection,
|
||||
int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer );
|
||||
|
||||
// cm_patch.c
|
||||
void CM_DrawDebugSurface( void (*drawPoly)(int color, int numPoints, float *points) );
|
||||
|
|
956
code/qcommon/cm_test.c
Normal file → Executable file
956
code/qcommon/cm_test.c
Normal file → Executable file
|
@ -1,478 +1,478 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
#include "cm_local.h"
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_PointLeafnum_r
|
||||
|
||||
==================
|
||||
*/
|
||||
int CM_PointLeafnum_r( const vec3_t p, int num ) {
|
||||
float d;
|
||||
cNode_t *node;
|
||||
cplane_t *plane;
|
||||
|
||||
while (num >= 0)
|
||||
{
|
||||
node = cm.nodes + num;
|
||||
plane = node->plane;
|
||||
|
||||
if (plane->type < 3)
|
||||
d = p[plane->type] - plane->dist;
|
||||
else
|
||||
d = DotProduct (plane->normal, p) - plane->dist;
|
||||
if (d < 0)
|
||||
num = node->children[1];
|
||||
else
|
||||
num = node->children[0];
|
||||
}
|
||||
|
||||
c_pointcontents++; // optimize counter
|
||||
|
||||
return -1 - num;
|
||||
}
|
||||
|
||||
int CM_PointLeafnum( const vec3_t p ) {
|
||||
if ( !cm.numNodes ) { // map not loaded
|
||||
return 0;
|
||||
}
|
||||
return CM_PointLeafnum_r (p, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
======================================================================
|
||||
|
||||
LEAF LISTING
|
||||
|
||||
======================================================================
|
||||
*/
|
||||
|
||||
|
||||
void CM_StoreLeafs( leafList_t *ll, int nodenum ) {
|
||||
int leafNum;
|
||||
|
||||
leafNum = -1 - nodenum;
|
||||
|
||||
// store the lastLeaf even if the list is overflowed
|
||||
if ( cm.leafs[ leafNum ].cluster != -1 ) {
|
||||
ll->lastLeaf = leafNum;
|
||||
}
|
||||
|
||||
if ( ll->count >= ll->maxcount) {
|
||||
ll->overflowed = qtrue;
|
||||
return;
|
||||
}
|
||||
ll->list[ ll->count++ ] = leafNum;
|
||||
}
|
||||
|
||||
void CM_StoreBrushes( leafList_t *ll, int nodenum ) {
|
||||
int i, k;
|
||||
int leafnum;
|
||||
int brushnum;
|
||||
cLeaf_t *leaf;
|
||||
cbrush_t *b;
|
||||
|
||||
leafnum = -1 - nodenum;
|
||||
|
||||
leaf = &cm.leafs[leafnum];
|
||||
|
||||
for ( k = 0 ; k < leaf->numLeafBrushes ; k++ ) {
|
||||
brushnum = cm.leafbrushes[leaf->firstLeafBrush+k];
|
||||
b = &cm.brushes[brushnum];
|
||||
if ( b->checkcount == cm.checkcount ) {
|
||||
continue; // already checked this brush in another leaf
|
||||
}
|
||||
b->checkcount = cm.checkcount;
|
||||
for ( i = 0 ; i < 3 ; i++ ) {
|
||||
if ( b->bounds[0][i] >= ll->bounds[1][i] || b->bounds[1][i] <= ll->bounds[0][i] ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( i != 3 ) {
|
||||
continue;
|
||||
}
|
||||
if ( ll->count >= ll->maxcount) {
|
||||
ll->overflowed = qtrue;
|
||||
return;
|
||||
}
|
||||
((cbrush_t **)ll->list)[ ll->count++ ] = b;
|
||||
}
|
||||
#if 0
|
||||
// store patches?
|
||||
for ( k = 0 ; k < leaf->numLeafSurfaces ; k++ ) {
|
||||
patch = cm.surfaces[ cm.leafsurfaces[ leaf->firstleafsurface + k ] ];
|
||||
if ( !patch ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CM_BoxLeafnums
|
||||
|
||||
Fills in a list of all the leafs touched
|
||||
=============
|
||||
*/
|
||||
void CM_BoxLeafnums_r( leafList_t *ll, int nodenum ) {
|
||||
cplane_t *plane;
|
||||
cNode_t *node;
|
||||
int s;
|
||||
|
||||
while (1) {
|
||||
if (nodenum < 0) {
|
||||
ll->storeLeafs( ll, nodenum );
|
||||
return;
|
||||
}
|
||||
|
||||
node = &cm.nodes[nodenum];
|
||||
plane = node->plane;
|
||||
s = BoxOnPlaneSide( ll->bounds[0], ll->bounds[1], plane );
|
||||
if (s == 1) {
|
||||
nodenum = node->children[0];
|
||||
} else if (s == 2) {
|
||||
nodenum = node->children[1];
|
||||
} else {
|
||||
// go down both
|
||||
CM_BoxLeafnums_r( ll, node->children[0] );
|
||||
nodenum = node->children[1];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_BoxLeafnums
|
||||
==================
|
||||
*/
|
||||
int CM_BoxLeafnums( const vec3_t mins, const vec3_t maxs, int *list, int listsize, int *lastLeaf) {
|
||||
leafList_t ll;
|
||||
|
||||
cm.checkcount++;
|
||||
|
||||
VectorCopy( mins, ll.bounds[0] );
|
||||
VectorCopy( maxs, ll.bounds[1] );
|
||||
ll.count = 0;
|
||||
ll.maxcount = listsize;
|
||||
ll.list = list;
|
||||
ll.storeLeafs = CM_StoreLeafs;
|
||||
ll.lastLeaf = 0;
|
||||
ll.overflowed = qfalse;
|
||||
|
||||
CM_BoxLeafnums_r( &ll, 0 );
|
||||
|
||||
*lastLeaf = ll.lastLeaf;
|
||||
return ll.count;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_BoxBrushes
|
||||
==================
|
||||
*/
|
||||
int CM_BoxBrushes( const vec3_t mins, const vec3_t maxs, cbrush_t **list, int listsize ) {
|
||||
leafList_t ll;
|
||||
|
||||
cm.checkcount++;
|
||||
|
||||
VectorCopy( mins, ll.bounds[0] );
|
||||
VectorCopy( maxs, ll.bounds[1] );
|
||||
ll.count = 0;
|
||||
ll.maxcount = listsize;
|
||||
ll.list = (void *)list;
|
||||
ll.storeLeafs = CM_StoreBrushes;
|
||||
ll.lastLeaf = 0;
|
||||
ll.overflowed = qfalse;
|
||||
|
||||
CM_BoxLeafnums_r( &ll, 0 );
|
||||
|
||||
return ll.count;
|
||||
}
|
||||
|
||||
|
||||
//====================================================================
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_PointContents
|
||||
|
||||
==================
|
||||
*/
|
||||
int CM_PointContents( const vec3_t p, clipHandle_t model ) {
|
||||
int leafnum;
|
||||
int i, k;
|
||||
int brushnum;
|
||||
cLeaf_t *leaf;
|
||||
cbrush_t *b;
|
||||
int contents;
|
||||
float d;
|
||||
cmodel_t *clipm;
|
||||
|
||||
if (!cm.numNodes) { // map not loaded
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( model ) {
|
||||
clipm = CM_ClipHandleToModel( model );
|
||||
leaf = &clipm->leaf;
|
||||
} else {
|
||||
leafnum = CM_PointLeafnum_r (p, 0);
|
||||
leaf = &cm.leafs[leafnum];
|
||||
}
|
||||
|
||||
contents = 0;
|
||||
for (k=0 ; k<leaf->numLeafBrushes ; k++) {
|
||||
brushnum = cm.leafbrushes[leaf->firstLeafBrush+k];
|
||||
b = &cm.brushes[brushnum];
|
||||
|
||||
// see if the point is in the brush
|
||||
for ( i = 0 ; i < b->numsides ; i++ ) {
|
||||
d = DotProduct( p, b->sides[i].plane->normal );
|
||||
// FIXME test for Cash
|
||||
// if ( d >= b->sides[i].plane->dist ) {
|
||||
if ( d > b->sides[i].plane->dist ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( i == b->numsides ) {
|
||||
contents |= b->contents;
|
||||
}
|
||||
}
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_TransformedPointContents
|
||||
|
||||
Handles offseting and rotation of the end points for moving and
|
||||
rotating entities
|
||||
==================
|
||||
*/
|
||||
int CM_TransformedPointContents( const vec3_t p, clipHandle_t model, const vec3_t origin, const vec3_t angles) {
|
||||
vec3_t p_l;
|
||||
vec3_t temp;
|
||||
vec3_t forward, right, up;
|
||||
|
||||
// subtract origin offset
|
||||
VectorSubtract (p, origin, p_l);
|
||||
|
||||
// rotate start and end into the models frame of reference
|
||||
if ( model != BOX_MODEL_HANDLE &&
|
||||
(angles[0] || angles[1] || angles[2]) )
|
||||
{
|
||||
AngleVectors (angles, forward, right, up);
|
||||
|
||||
VectorCopy (p_l, temp);
|
||||
p_l[0] = DotProduct (temp, forward);
|
||||
p_l[1] = -DotProduct (temp, right);
|
||||
p_l[2] = DotProduct (temp, up);
|
||||
}
|
||||
|
||||
return CM_PointContents( p_l, model );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
PVS
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
byte *CM_ClusterPVS (int cluster) {
|
||||
if (cluster < 0 || cluster >= cm.numClusters || !cm.vised ) {
|
||||
return cm.visibility;
|
||||
}
|
||||
|
||||
return cm.visibility + cluster * cm.clusterBytes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
AREAPORTALS
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
void CM_FloodArea_r( int areaNum, int floodnum) {
|
||||
int i;
|
||||
cArea_t *area;
|
||||
int *con;
|
||||
|
||||
area = &cm.areas[ areaNum ];
|
||||
|
||||
if ( area->floodvalid == cm.floodvalid ) {
|
||||
if (area->floodnum == floodnum)
|
||||
return;
|
||||
Com_Error (ERR_DROP, "FloodArea_r: reflooded");
|
||||
}
|
||||
|
||||
area->floodnum = floodnum;
|
||||
area->floodvalid = cm.floodvalid;
|
||||
con = cm.areaPortals + areaNum * cm.numAreas;
|
||||
for ( i=0 ; i < cm.numAreas ; i++ ) {
|
||||
if ( con[i] > 0 ) {
|
||||
CM_FloodArea_r( i, floodnum );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CM_FloodAreaConnections
|
||||
|
||||
====================
|
||||
*/
|
||||
void CM_FloodAreaConnections( void ) {
|
||||
int i;
|
||||
cArea_t *area;
|
||||
int floodnum;
|
||||
|
||||
// all current floods are now invalid
|
||||
cm.floodvalid++;
|
||||
floodnum = 0;
|
||||
|
||||
for (i = 0 ; i < cm.numAreas ; i++) {
|
||||
area = &cm.areas[i];
|
||||
if (area->floodvalid == cm.floodvalid) {
|
||||
continue; // already flooded into
|
||||
}
|
||||
floodnum++;
|
||||
CM_FloodArea_r (i, floodnum);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CM_AdjustAreaPortalState
|
||||
|
||||
====================
|
||||
*/
|
||||
void CM_AdjustAreaPortalState( int area1, int area2, qboolean open ) {
|
||||
if ( area1 < 0 || area2 < 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( area1 >= cm.numAreas || area2 >= cm.numAreas ) {
|
||||
Com_Error (ERR_DROP, "CM_ChangeAreaPortalState: bad area number");
|
||||
}
|
||||
|
||||
if ( open ) {
|
||||
cm.areaPortals[ area1 * cm.numAreas + area2 ]++;
|
||||
cm.areaPortals[ area2 * cm.numAreas + area1 ]++;
|
||||
} else {
|
||||
cm.areaPortals[ area1 * cm.numAreas + area2 ]--;
|
||||
cm.areaPortals[ area2 * cm.numAreas + area1 ]--;
|
||||
if ( cm.areaPortals[ area2 * cm.numAreas + area1 ] < 0 ) {
|
||||
Com_Error (ERR_DROP, "CM_AdjustAreaPortalState: negative reference count");
|
||||
}
|
||||
}
|
||||
|
||||
CM_FloodAreaConnections ();
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CM_AreasConnected
|
||||
|
||||
====================
|
||||
*/
|
||||
qboolean CM_AreasConnected( int area1, int area2 ) {
|
||||
#ifndef BSPC
|
||||
if ( cm_noAreas->integer ) {
|
||||
return qtrue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( area1 < 0 || area2 < 0 ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
if (area1 >= cm.numAreas || area2 >= cm.numAreas) {
|
||||
Com_Error (ERR_DROP, "area >= cm.numAreas");
|
||||
}
|
||||
|
||||
if (cm.areas[area1].floodnum == cm.areas[area2].floodnum) {
|
||||
return qtrue;
|
||||
}
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CM_WriteAreaBits
|
||||
|
||||
Writes a bit vector of all the areas
|
||||
that are in the same flood as the area parameter
|
||||
Returns the number of bytes needed to hold all the bits.
|
||||
|
||||
The bits are OR'd in, so you can CM_WriteAreaBits from multiple
|
||||
viewpoints and get the union of all visible areas.
|
||||
|
||||
This is used to cull non-visible entities from snapshots
|
||||
=================
|
||||
*/
|
||||
int CM_WriteAreaBits (byte *buffer, int area)
|
||||
{
|
||||
int i;
|
||||
int floodnum;
|
||||
int bytes;
|
||||
|
||||
bytes = (cm.numAreas+7)>>3;
|
||||
|
||||
#ifndef BSPC
|
||||
if (cm_noAreas->integer || area == -1)
|
||||
#else
|
||||
if ( area == -1)
|
||||
#endif
|
||||
{ // for debugging, send everything
|
||||
Com_Memset (buffer, 255, bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
floodnum = cm.areas[area].floodnum;
|
||||
for (i=0 ; i<cm.numAreas ; i++)
|
||||
{
|
||||
if (cm.areas[i].floodnum == floodnum || area == -1)
|
||||
buffer[i>>3] |= 1<<(i&7);
|
||||
}
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
#include "cm_local.h"
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_PointLeafnum_r
|
||||
|
||||
==================
|
||||
*/
|
||||
int CM_PointLeafnum_r( const vec3_t p, int num ) {
|
||||
float d;
|
||||
cNode_t *node;
|
||||
cplane_t *plane;
|
||||
|
||||
while (num >= 0)
|
||||
{
|
||||
node = cm.nodes + num;
|
||||
plane = node->plane;
|
||||
|
||||
if (plane->type < 3)
|
||||
d = p[plane->type] - plane->dist;
|
||||
else
|
||||
d = DotProduct (plane->normal, p) - plane->dist;
|
||||
if (d < 0)
|
||||
num = node->children[1];
|
||||
else
|
||||
num = node->children[0];
|
||||
}
|
||||
|
||||
c_pointcontents++; // optimize counter
|
||||
|
||||
return -1 - num;
|
||||
}
|
||||
|
||||
int CM_PointLeafnum( const vec3_t p ) {
|
||||
if ( !cm.numNodes ) { // map not loaded
|
||||
return 0;
|
||||
}
|
||||
return CM_PointLeafnum_r (p, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
======================================================================
|
||||
|
||||
LEAF LISTING
|
||||
|
||||
======================================================================
|
||||
*/
|
||||
|
||||
|
||||
void CM_StoreLeafs( leafList_t *ll, int nodenum ) {
|
||||
int leafNum;
|
||||
|
||||
leafNum = -1 - nodenum;
|
||||
|
||||
// store the lastLeaf even if the list is overflowed
|
||||
if ( cm.leafs[ leafNum ].cluster != -1 ) {
|
||||
ll->lastLeaf = leafNum;
|
||||
}
|
||||
|
||||
if ( ll->count >= ll->maxcount) {
|
||||
ll->overflowed = qtrue;
|
||||
return;
|
||||
}
|
||||
ll->list[ ll->count++ ] = leafNum;
|
||||
}
|
||||
|
||||
void CM_StoreBrushes( leafList_t *ll, int nodenum ) {
|
||||
int i, k;
|
||||
int leafnum;
|
||||
int brushnum;
|
||||
cLeaf_t *leaf;
|
||||
cbrush_t *b;
|
||||
|
||||
leafnum = -1 - nodenum;
|
||||
|
||||
leaf = &cm.leafs[leafnum];
|
||||
|
||||
for ( k = 0 ; k < leaf->numLeafBrushes ; k++ ) {
|
||||
brushnum = cm.leafbrushes[leaf->firstLeafBrush+k];
|
||||
b = &cm.brushes[brushnum];
|
||||
if ( b->checkcount == cm.checkcount ) {
|
||||
continue; // already checked this brush in another leaf
|
||||
}
|
||||
b->checkcount = cm.checkcount;
|
||||
for ( i = 0 ; i < 3 ; i++ ) {
|
||||
if ( b->bounds[0][i] >= ll->bounds[1][i] || b->bounds[1][i] <= ll->bounds[0][i] ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( i != 3 ) {
|
||||
continue;
|
||||
}
|
||||
if ( ll->count >= ll->maxcount) {
|
||||
ll->overflowed = qtrue;
|
||||
return;
|
||||
}
|
||||
((cbrush_t **)ll->list)[ ll->count++ ] = b;
|
||||
}
|
||||
#if 0
|
||||
// store patches?
|
||||
for ( k = 0 ; k < leaf->numLeafSurfaces ; k++ ) {
|
||||
patch = cm.surfaces[ cm.leafsurfaces[ leaf->firstleafsurface + k ] ];
|
||||
if ( !patch ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CM_BoxLeafnums
|
||||
|
||||
Fills in a list of all the leafs touched
|
||||
=============
|
||||
*/
|
||||
void CM_BoxLeafnums_r( leafList_t *ll, int nodenum ) {
|
||||
cplane_t *plane;
|
||||
cNode_t *node;
|
||||
int s;
|
||||
|
||||
while (1) {
|
||||
if (nodenum < 0) {
|
||||
ll->storeLeafs( ll, nodenum );
|
||||
return;
|
||||
}
|
||||
|
||||
node = &cm.nodes[nodenum];
|
||||
plane = node->plane;
|
||||
s = BoxOnPlaneSide( ll->bounds[0], ll->bounds[1], plane );
|
||||
if (s == 1) {
|
||||
nodenum = node->children[0];
|
||||
} else if (s == 2) {
|
||||
nodenum = node->children[1];
|
||||
} else {
|
||||
// go down both
|
||||
CM_BoxLeafnums_r( ll, node->children[0] );
|
||||
nodenum = node->children[1];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_BoxLeafnums
|
||||
==================
|
||||
*/
|
||||
int CM_BoxLeafnums( const vec3_t mins, const vec3_t maxs, int *list, int listsize, int *lastLeaf) {
|
||||
leafList_t ll;
|
||||
|
||||
cm.checkcount++;
|
||||
|
||||
VectorCopy( mins, ll.bounds[0] );
|
||||
VectorCopy( maxs, ll.bounds[1] );
|
||||
ll.count = 0;
|
||||
ll.maxcount = listsize;
|
||||
ll.list = list;
|
||||
ll.storeLeafs = CM_StoreLeafs;
|
||||
ll.lastLeaf = 0;
|
||||
ll.overflowed = qfalse;
|
||||
|
||||
CM_BoxLeafnums_r( &ll, 0 );
|
||||
|
||||
*lastLeaf = ll.lastLeaf;
|
||||
return ll.count;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_BoxBrushes
|
||||
==================
|
||||
*/
|
||||
int CM_BoxBrushes( const vec3_t mins, const vec3_t maxs, cbrush_t **list, int listsize ) {
|
||||
leafList_t ll;
|
||||
|
||||
cm.checkcount++;
|
||||
|
||||
VectorCopy( mins, ll.bounds[0] );
|
||||
VectorCopy( maxs, ll.bounds[1] );
|
||||
ll.count = 0;
|
||||
ll.maxcount = listsize;
|
||||
ll.list = (void *)list;
|
||||
ll.storeLeafs = CM_StoreBrushes;
|
||||
ll.lastLeaf = 0;
|
||||
ll.overflowed = qfalse;
|
||||
|
||||
CM_BoxLeafnums_r( &ll, 0 );
|
||||
|
||||
return ll.count;
|
||||
}
|
||||
|
||||
|
||||
//====================================================================
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_PointContents
|
||||
|
||||
==================
|
||||
*/
|
||||
int CM_PointContents( const vec3_t p, clipHandle_t model ) {
|
||||
int leafnum;
|
||||
int i, k;
|
||||
int brushnum;
|
||||
cLeaf_t *leaf;
|
||||
cbrush_t *b;
|
||||
int contents;
|
||||
float d;
|
||||
cmodel_t *clipm;
|
||||
|
||||
if (!cm.numNodes) { // map not loaded
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( model ) {
|
||||
clipm = CM_ClipHandleToModel( model );
|
||||
leaf = &clipm->leaf;
|
||||
} else {
|
||||
leafnum = CM_PointLeafnum_r (p, 0);
|
||||
leaf = &cm.leafs[leafnum];
|
||||
}
|
||||
|
||||
contents = 0;
|
||||
for (k=0 ; k<leaf->numLeafBrushes ; k++) {
|
||||
brushnum = cm.leafbrushes[leaf->firstLeafBrush+k];
|
||||
b = &cm.brushes[brushnum];
|
||||
|
||||
// see if the point is in the brush
|
||||
for ( i = 0 ; i < b->numsides ; i++ ) {
|
||||
d = DotProduct( p, b->sides[i].plane->normal );
|
||||
// FIXME test for Cash
|
||||
// if ( d >= b->sides[i].plane->dist ) {
|
||||
if ( d > b->sides[i].plane->dist ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( i == b->numsides ) {
|
||||
contents |= b->contents;
|
||||
}
|
||||
}
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_TransformedPointContents
|
||||
|
||||
Handles offseting and rotation of the end points for moving and
|
||||
rotating entities
|
||||
==================
|
||||
*/
|
||||
int CM_TransformedPointContents( const vec3_t p, clipHandle_t model, const vec3_t origin, const vec3_t angles) {
|
||||
vec3_t p_l;
|
||||
vec3_t temp;
|
||||
vec3_t forward, right, up;
|
||||
|
||||
// subtract origin offset
|
||||
VectorSubtract (p, origin, p_l);
|
||||
|
||||
// rotate start and end into the models frame of reference
|
||||
if ( model != BOX_MODEL_HANDLE &&
|
||||
(angles[0] || angles[1] || angles[2]) )
|
||||
{
|
||||
AngleVectors (angles, forward, right, up);
|
||||
|
||||
VectorCopy (p_l, temp);
|
||||
p_l[0] = DotProduct (temp, forward);
|
||||
p_l[1] = -DotProduct (temp, right);
|
||||
p_l[2] = DotProduct (temp, up);
|
||||
}
|
||||
|
||||
return CM_PointContents( p_l, model );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
PVS
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
byte *CM_ClusterPVS (int cluster) {
|
||||
if (cluster < 0 || cluster >= cm.numClusters || !cm.vised ) {
|
||||
return cm.visibility;
|
||||
}
|
||||
|
||||
return cm.visibility + cluster * cm.clusterBytes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
AREAPORTALS
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
void CM_FloodArea_r( int areaNum, int floodnum) {
|
||||
int i;
|
||||
cArea_t *area;
|
||||
int *con;
|
||||
|
||||
area = &cm.areas[ areaNum ];
|
||||
|
||||
if ( area->floodvalid == cm.floodvalid ) {
|
||||
if (area->floodnum == floodnum)
|
||||
return;
|
||||
Com_Error (ERR_DROP, "FloodArea_r: reflooded");
|
||||
}
|
||||
|
||||
area->floodnum = floodnum;
|
||||
area->floodvalid = cm.floodvalid;
|
||||
con = cm.areaPortals + areaNum * cm.numAreas;
|
||||
for ( i=0 ; i < cm.numAreas ; i++ ) {
|
||||
if ( con[i] > 0 ) {
|
||||
CM_FloodArea_r( i, floodnum );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CM_FloodAreaConnections
|
||||
|
||||
====================
|
||||
*/
|
||||
void CM_FloodAreaConnections( void ) {
|
||||
int i;
|
||||
cArea_t *area;
|
||||
int floodnum;
|
||||
|
||||
// all current floods are now invalid
|
||||
cm.floodvalid++;
|
||||
floodnum = 0;
|
||||
|
||||
for (i = 0 ; i < cm.numAreas ; i++) {
|
||||
area = &cm.areas[i];
|
||||
if (area->floodvalid == cm.floodvalid) {
|
||||
continue; // already flooded into
|
||||
}
|
||||
floodnum++;
|
||||
CM_FloodArea_r (i, floodnum);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CM_AdjustAreaPortalState
|
||||
|
||||
====================
|
||||
*/
|
||||
void CM_AdjustAreaPortalState( int area1, int area2, qboolean open ) {
|
||||
if ( area1 < 0 || area2 < 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( area1 >= cm.numAreas || area2 >= cm.numAreas ) {
|
||||
Com_Error (ERR_DROP, "CM_ChangeAreaPortalState: bad area number");
|
||||
}
|
||||
|
||||
if ( open ) {
|
||||
cm.areaPortals[ area1 * cm.numAreas + area2 ]++;
|
||||
cm.areaPortals[ area2 * cm.numAreas + area1 ]++;
|
||||
} else {
|
||||
cm.areaPortals[ area1 * cm.numAreas + area2 ]--;
|
||||
cm.areaPortals[ area2 * cm.numAreas + area1 ]--;
|
||||
if ( cm.areaPortals[ area2 * cm.numAreas + area1 ] < 0 ) {
|
||||
Com_Error (ERR_DROP, "CM_AdjustAreaPortalState: negative reference count");
|
||||
}
|
||||
}
|
||||
|
||||
CM_FloodAreaConnections ();
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CM_AreasConnected
|
||||
|
||||
====================
|
||||
*/
|
||||
qboolean CM_AreasConnected( int area1, int area2 ) {
|
||||
#ifndef BSPC
|
||||
if ( cm_noAreas->integer ) {
|
||||
return qtrue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( area1 < 0 || area2 < 0 ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
if (area1 >= cm.numAreas || area2 >= cm.numAreas) {
|
||||
Com_Error (ERR_DROP, "area >= cm.numAreas");
|
||||
}
|
||||
|
||||
if (cm.areas[area1].floodnum == cm.areas[area2].floodnum) {
|
||||
return qtrue;
|
||||
}
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CM_WriteAreaBits
|
||||
|
||||
Writes a bit vector of all the areas
|
||||
that are in the same flood as the area parameter
|
||||
Returns the number of bytes needed to hold all the bits.
|
||||
|
||||
The bits are OR'd in, so you can CM_WriteAreaBits from multiple
|
||||
viewpoints and get the union of all visible areas.
|
||||
|
||||
This is used to cull non-visible entities from snapshots
|
||||
=================
|
||||
*/
|
||||
int CM_WriteAreaBits (byte *buffer, int area)
|
||||
{
|
||||
int i;
|
||||
int floodnum;
|
||||
int bytes;
|
||||
|
||||
bytes = (cm.numAreas+7)>>3;
|
||||
|
||||
#ifndef BSPC
|
||||
if (cm_noAreas->integer || area == -1)
|
||||
#else
|
||||
if ( area == -1)
|
||||
#endif
|
||||
{ // for debugging, send everything
|
||||
Com_Memset (buffer, 255, bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
floodnum = cm.areas[area].floodnum;
|
||||
for (i=0 ; i<cm.numAreas ; i++)
|
||||
{
|
||||
if (cm.areas[i].floodnum == floodnum || area == -1)
|
||||
buffer[i>>3] |= 1<<(i&7);
|
||||
}
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
|
2942
code/qcommon/cm_trace.c
Normal file → Executable file
2942
code/qcommon/cm_trace.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
1430
code/qcommon/cmd.c
Normal file → Executable file
1430
code/qcommon/cmd.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
1272
code/qcommon/cmd.c.save
Normal file → Executable file
1272
code/qcommon/cmd.c.save
Normal file → Executable file
File diff suppressed because it is too large
Load diff
6634
code/qcommon/common.c
Normal file → Executable file
6634
code/qcommon/common.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
1812
code/qcommon/cvar.c
Normal file → Executable file
1812
code/qcommon/cvar.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
6838
code/qcommon/files.c
Normal file → Executable file
6838
code/qcommon/files.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
874
code/qcommon/huffman.c
Normal file → Executable file
874
code/qcommon/huffman.c
Normal file → Executable file
|
@ -1,437 +1,437 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
/* This is based on the Adaptive Huffman algorithm described in Sayood's Data
|
||||
* Compression book. The ranks are not actually stored, but implicitly defined
|
||||
* by the location of a node within a doubly-linked list */
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "qcommon.h"
|
||||
|
||||
static int bloc = 0;
|
||||
|
||||
void Huff_putBit( int bit, byte *fout, int *offset) {
|
||||
bloc = *offset;
|
||||
if ((bloc&7) == 0) {
|
||||
fout[(bloc>>3)] = 0;
|
||||
}
|
||||
fout[(bloc>>3)] |= bit << (bloc&7);
|
||||
bloc++;
|
||||
*offset = bloc;
|
||||
}
|
||||
|
||||
int Huff_getBit( byte *fin, int *offset) {
|
||||
int t;
|
||||
bloc = *offset;
|
||||
t = (fin[(bloc>>3)] >> (bloc&7)) & 0x1;
|
||||
bloc++;
|
||||
*offset = bloc;
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Add a bit to the output file (buffered) */
|
||||
static void add_bit (char bit, byte *fout) {
|
||||
if ((bloc&7) == 0) {
|
||||
fout[(bloc>>3)] = 0;
|
||||
}
|
||||
fout[(bloc>>3)] |= bit << (bloc&7);
|
||||
bloc++;
|
||||
}
|
||||
|
||||
/* Receive one bit from the input file (buffered) */
|
||||
static int get_bit (byte *fin) {
|
||||
int t;
|
||||
t = (fin[(bloc>>3)] >> (bloc&7)) & 0x1;
|
||||
bloc++;
|
||||
return t;
|
||||
}
|
||||
|
||||
static node_t **get_ppnode(huff_t* huff) {
|
||||
node_t **tppnode;
|
||||
if (!huff->freelist) {
|
||||
return &(huff->nodePtrs[huff->blocPtrs++]);
|
||||
} else {
|
||||
tppnode = huff->freelist;
|
||||
huff->freelist = (node_t **)*tppnode;
|
||||
return tppnode;
|
||||
}
|
||||
}
|
||||
|
||||
static void free_ppnode(huff_t* huff, node_t **ppnode) {
|
||||
*ppnode = (node_t *)huff->freelist;
|
||||
huff->freelist = ppnode;
|
||||
}
|
||||
|
||||
/* Swap the location of these two nodes in the tree */
|
||||
static void swap (huff_t* huff, node_t *node1, node_t *node2) {
|
||||
node_t *par1, *par2;
|
||||
|
||||
par1 = node1->parent;
|
||||
par2 = node2->parent;
|
||||
|
||||
if (par1) {
|
||||
if (par1->left == node1) {
|
||||
par1->left = node2;
|
||||
} else {
|
||||
par1->right = node2;
|
||||
}
|
||||
} else {
|
||||
huff->tree = node2;
|
||||
}
|
||||
|
||||
if (par2) {
|
||||
if (par2->left == node2) {
|
||||
par2->left = node1;
|
||||
} else {
|
||||
par2->right = node1;
|
||||
}
|
||||
} else {
|
||||
huff->tree = node1;
|
||||
}
|
||||
|
||||
node1->parent = par2;
|
||||
node2->parent = par1;
|
||||
}
|
||||
|
||||
/* Swap these two nodes in the linked list (update ranks) */
|
||||
static void swaplist(node_t *node1, node_t *node2) {
|
||||
node_t *par1;
|
||||
|
||||
par1 = node1->next;
|
||||
node1->next = node2->next;
|
||||
node2->next = par1;
|
||||
|
||||
par1 = node1->prev;
|
||||
node1->prev = node2->prev;
|
||||
node2->prev = par1;
|
||||
|
||||
if (node1->next == node1) {
|
||||
node1->next = node2;
|
||||
}
|
||||
if (node2->next == node2) {
|
||||
node2->next = node1;
|
||||
}
|
||||
if (node1->next) {
|
||||
node1->next->prev = node1;
|
||||
}
|
||||
if (node2->next) {
|
||||
node2->next->prev = node2;
|
||||
}
|
||||
if (node1->prev) {
|
||||
node1->prev->next = node1;
|
||||
}
|
||||
if (node2->prev) {
|
||||
node2->prev->next = node2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do the increments */
|
||||
static void increment(huff_t* huff, node_t *node) {
|
||||
node_t *lnode;
|
||||
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->next != NULL && node->next->weight == node->weight) {
|
||||
lnode = *node->head;
|
||||
if (lnode != node->parent) {
|
||||
swap(huff, lnode, node);
|
||||
}
|
||||
swaplist(lnode, node);
|
||||
}
|
||||
if (node->prev && node->prev->weight == node->weight) {
|
||||
*node->head = node->prev;
|
||||
} else {
|
||||
*node->head = NULL;
|
||||
free_ppnode(huff, node->head);
|
||||
}
|
||||
node->weight++;
|
||||
if (node->next && node->next->weight == node->weight) {
|
||||
node->head = node->next->head;
|
||||
} else {
|
||||
node->head = get_ppnode(huff);
|
||||
*node->head = node;
|
||||
}
|
||||
if (node->parent) {
|
||||
increment(huff, node->parent);
|
||||
if (node->prev == node->parent) {
|
||||
swaplist(node, node->parent);
|
||||
if (*node->head == node) {
|
||||
*node->head = node->parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Huff_addRef(huff_t* huff, byte ch) {
|
||||
node_t *tnode, *tnode2;
|
||||
if (huff->loc[ch] == NULL) { /* if this is the first transmission of this node */
|
||||
tnode = &(huff->nodeList[huff->blocNode++]);
|
||||
tnode2 = &(huff->nodeList[huff->blocNode++]);
|
||||
|
||||
tnode2->symbol = INTERNAL_NODE;
|
||||
tnode2->weight = 1;
|
||||
tnode2->next = huff->lhead->next;
|
||||
if (huff->lhead->next) {
|
||||
huff->lhead->next->prev = tnode2;
|
||||
if (huff->lhead->next->weight == 1) {
|
||||
tnode2->head = huff->lhead->next->head;
|
||||
} else {
|
||||
tnode2->head = get_ppnode(huff);
|
||||
*tnode2->head = tnode2;
|
||||
}
|
||||
} else {
|
||||
tnode2->head = get_ppnode(huff);
|
||||
*tnode2->head = tnode2;
|
||||
}
|
||||
huff->lhead->next = tnode2;
|
||||
tnode2->prev = huff->lhead;
|
||||
|
||||
tnode->symbol = ch;
|
||||
tnode->weight = 1;
|
||||
tnode->next = huff->lhead->next;
|
||||
if (huff->lhead->next) {
|
||||
huff->lhead->next->prev = tnode;
|
||||
if (huff->lhead->next->weight == 1) {
|
||||
tnode->head = huff->lhead->next->head;
|
||||
} else {
|
||||
/* this should never happen */
|
||||
tnode->head = get_ppnode(huff);
|
||||
*tnode->head = tnode2;
|
||||
}
|
||||
} else {
|
||||
/* this should never happen */
|
||||
tnode->head = get_ppnode(huff);
|
||||
*tnode->head = tnode;
|
||||
}
|
||||
huff->lhead->next = tnode;
|
||||
tnode->prev = huff->lhead;
|
||||
tnode->left = tnode->right = NULL;
|
||||
|
||||
if (huff->lhead->parent) {
|
||||
if (huff->lhead->parent->left == huff->lhead) { /* lhead is guaranteed to by the NYT */
|
||||
huff->lhead->parent->left = tnode2;
|
||||
} else {
|
||||
huff->lhead->parent->right = tnode2;
|
||||
}
|
||||
} else {
|
||||
huff->tree = tnode2;
|
||||
}
|
||||
|
||||
tnode2->right = tnode;
|
||||
tnode2->left = huff->lhead;
|
||||
|
||||
tnode2->parent = huff->lhead->parent;
|
||||
huff->lhead->parent = tnode->parent = tnode2;
|
||||
|
||||
huff->loc[ch] = tnode;
|
||||
|
||||
increment(huff, tnode2->parent);
|
||||
} else {
|
||||
increment(huff, huff->loc[ch]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get a symbol */
|
||||
int Huff_Receive (node_t *node, int *ch, byte *fin) {
|
||||
while (node && node->symbol == INTERNAL_NODE) {
|
||||
if (get_bit(fin)) {
|
||||
node = node->right;
|
||||
} else {
|
||||
node = node->left;
|
||||
}
|
||||
}
|
||||
if (!node) {
|
||||
return 0;
|
||||
// Com_Error(ERR_DROP, "Illegal tree!\n");
|
||||
}
|
||||
return (*ch = node->symbol);
|
||||
}
|
||||
|
||||
/* Get a symbol */
|
||||
void Huff_offsetReceive (node_t *node, int *ch, byte *fin, int *offset) {
|
||||
bloc = *offset;
|
||||
while (node && node->symbol == INTERNAL_NODE) {
|
||||
if (get_bit(fin)) {
|
||||
node = node->right;
|
||||
} else {
|
||||
node = node->left;
|
||||
}
|
||||
}
|
||||
if (!node) {
|
||||
*ch = 0;
|
||||
return;
|
||||
// Com_Error(ERR_DROP, "Illegal tree!\n");
|
||||
}
|
||||
*ch = node->symbol;
|
||||
*offset = bloc;
|
||||
}
|
||||
|
||||
/* Send the prefix code for this node */
|
||||
static void send(node_t *node, node_t *child, byte *fout) {
|
||||
if (node->parent) {
|
||||
send(node->parent, node, fout);
|
||||
}
|
||||
if (child) {
|
||||
if (node->right == child) {
|
||||
add_bit(1, fout);
|
||||
} else {
|
||||
add_bit(0, fout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Send a symbol */
|
||||
void Huff_transmit (huff_t *huff, int ch, byte *fout) {
|
||||
int i;
|
||||
if (huff->loc[ch] == NULL) {
|
||||
/* node_t hasn't been transmitted, send a NYT, then the symbol */
|
||||
Huff_transmit(huff, NYT, fout);
|
||||
for (i = 7; i >= 0; i--) {
|
||||
add_bit((char)((ch >> i) & 0x1), fout);
|
||||
}
|
||||
} else {
|
||||
send(huff->loc[ch], NULL, fout);
|
||||
}
|
||||
}
|
||||
|
||||
void Huff_offsetTransmit (huff_t *huff, int ch, byte *fout, int *offset) {
|
||||
bloc = *offset;
|
||||
send(huff->loc[ch], NULL, fout);
|
||||
*offset = bloc;
|
||||
}
|
||||
|
||||
void Huff_Decompress(msg_t *mbuf, int offset) {
|
||||
int ch, cch, i, j, size;
|
||||
byte seq[65536];
|
||||
byte* buffer;
|
||||
huff_t huff;
|
||||
|
||||
size = mbuf->cursize - offset;
|
||||
buffer = mbuf->data + offset;
|
||||
|
||||
if ( size <= 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Com_Memset(&huff, 0, sizeof(huff_t));
|
||||
// Initialize the tree & list with the NYT node
|
||||
huff.tree = huff.lhead = huff.ltail = huff.loc[NYT] = &(huff.nodeList[huff.blocNode++]);
|
||||
huff.tree->symbol = NYT;
|
||||
huff.tree->weight = 0;
|
||||
huff.lhead->next = huff.lhead->prev = NULL;
|
||||
huff.tree->parent = huff.tree->left = huff.tree->right = NULL;
|
||||
|
||||
cch = buffer[0]*256 + buffer[1];
|
||||
// don't overflow with bad messages
|
||||
if ( cch > mbuf->maxsize - offset ) {
|
||||
cch = mbuf->maxsize - offset;
|
||||
}
|
||||
bloc = 16;
|
||||
|
||||
for ( j = 0; j < cch; j++ ) {
|
||||
ch = 0;
|
||||
// don't overflow reading from the messages
|
||||
// FIXME: would it be better to have a overflow check in get_bit ?
|
||||
if ( (bloc >> 3) > size ) {
|
||||
seq[j] = 0;
|
||||
break;
|
||||
}
|
||||
Huff_Receive(huff.tree, &ch, buffer); /* Get a character */
|
||||
if ( ch == NYT ) { /* We got a NYT, get the symbol associated with it */
|
||||
ch = 0;
|
||||
for ( i = 0; i < 8; i++ ) {
|
||||
ch = (ch<<1) + get_bit(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
seq[j] = ch; /* Write symbol */
|
||||
|
||||
Huff_addRef(&huff, (byte)ch); /* Increment node */
|
||||
}
|
||||
mbuf->cursize = cch + offset;
|
||||
Com_Memcpy(mbuf->data + offset, seq, cch);
|
||||
}
|
||||
|
||||
extern int oldsize;
|
||||
|
||||
void Huff_Compress(msg_t *mbuf, int offset) {
|
||||
int i, ch, size;
|
||||
byte seq[65536];
|
||||
byte* buffer;
|
||||
huff_t huff;
|
||||
|
||||
size = mbuf->cursize - offset;
|
||||
buffer = mbuf->data+ + offset;
|
||||
|
||||
if (size<=0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Com_Memset(&huff, 0, sizeof(huff_t));
|
||||
// Add the NYT (not yet transmitted) node into the tree/list */
|
||||
huff.tree = huff.lhead = huff.loc[NYT] = &(huff.nodeList[huff.blocNode++]);
|
||||
huff.tree->symbol = NYT;
|
||||
huff.tree->weight = 0;
|
||||
huff.lhead->next = huff.lhead->prev = NULL;
|
||||
huff.tree->parent = huff.tree->left = huff.tree->right = NULL;
|
||||
huff.loc[NYT] = huff.tree;
|
||||
|
||||
seq[0] = (size>>8);
|
||||
seq[1] = size&0xff;
|
||||
|
||||
bloc = 16;
|
||||
|
||||
for (i=0; i<size; i++ ) {
|
||||
ch = buffer[i];
|
||||
Huff_transmit(&huff, ch, seq); /* Transmit symbol */
|
||||
Huff_addRef(&huff, (byte)ch); /* Do update */
|
||||
}
|
||||
|
||||
bloc += 8; // next byte
|
||||
|
||||
mbuf->cursize = (bloc>>3) + offset;
|
||||
Com_Memcpy(mbuf->data+offset, seq, (bloc>>3));
|
||||
}
|
||||
|
||||
void Huff_Init(huffman_t *huff) {
|
||||
|
||||
Com_Memset(&huff->compressor, 0, sizeof(huff_t));
|
||||
Com_Memset(&huff->decompressor, 0, sizeof(huff_t));
|
||||
|
||||
// Initialize the tree & list with the NYT node
|
||||
huff->decompressor.tree = huff->decompressor.lhead = huff->decompressor.ltail = huff->decompressor.loc[NYT] = &(huff->decompressor.nodeList[huff->decompressor.blocNode++]);
|
||||
huff->decompressor.tree->symbol = NYT;
|
||||
huff->decompressor.tree->weight = 0;
|
||||
huff->decompressor.lhead->next = huff->decompressor.lhead->prev = NULL;
|
||||
huff->decompressor.tree->parent = huff->decompressor.tree->left = huff->decompressor.tree->right = NULL;
|
||||
|
||||
// Add the NYT (not yet transmitted) node into the tree/list */
|
||||
huff->compressor.tree = huff->compressor.lhead = huff->compressor.loc[NYT] = &(huff->compressor.nodeList[huff->compressor.blocNode++]);
|
||||
huff->compressor.tree->symbol = NYT;
|
||||
huff->compressor.tree->weight = 0;
|
||||
huff->compressor.lhead->next = huff->compressor.lhead->prev = NULL;
|
||||
huff->compressor.tree->parent = huff->compressor.tree->left = huff->compressor.tree->right = NULL;
|
||||
huff->compressor.loc[NYT] = huff->compressor.tree;
|
||||
}
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
/* This is based on the Adaptive Huffman algorithm described in Sayood's Data
|
||||
* Compression book. The ranks are not actually stored, but implicitly defined
|
||||
* by the location of a node within a doubly-linked list */
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "qcommon.h"
|
||||
|
||||
static int bloc = 0;
|
||||
|
||||
void Huff_putBit( int bit, byte *fout, int *offset) {
|
||||
bloc = *offset;
|
||||
if ((bloc&7) == 0) {
|
||||
fout[(bloc>>3)] = 0;
|
||||
}
|
||||
fout[(bloc>>3)] |= bit << (bloc&7);
|
||||
bloc++;
|
||||
*offset = bloc;
|
||||
}
|
||||
|
||||
int Huff_getBit( byte *fin, int *offset) {
|
||||
int t;
|
||||
bloc = *offset;
|
||||
t = (fin[(bloc>>3)] >> (bloc&7)) & 0x1;
|
||||
bloc++;
|
||||
*offset = bloc;
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Add a bit to the output file (buffered) */
|
||||
static void add_bit (char bit, byte *fout) {
|
||||
if ((bloc&7) == 0) {
|
||||
fout[(bloc>>3)] = 0;
|
||||
}
|
||||
fout[(bloc>>3)] |= bit << (bloc&7);
|
||||
bloc++;
|
||||
}
|
||||
|
||||
/* Receive one bit from the input file (buffered) */
|
||||
static int get_bit (byte *fin) {
|
||||
int t;
|
||||
t = (fin[(bloc>>3)] >> (bloc&7)) & 0x1;
|
||||
bloc++;
|
||||
return t;
|
||||
}
|
||||
|
||||
static node_t **get_ppnode(huff_t* huff) {
|
||||
node_t **tppnode;
|
||||
if (!huff->freelist) {
|
||||
return &(huff->nodePtrs[huff->blocPtrs++]);
|
||||
} else {
|
||||
tppnode = huff->freelist;
|
||||
huff->freelist = (node_t **)*tppnode;
|
||||
return tppnode;
|
||||
}
|
||||
}
|
||||
|
||||
static void free_ppnode(huff_t* huff, node_t **ppnode) {
|
||||
*ppnode = (node_t *)huff->freelist;
|
||||
huff->freelist = ppnode;
|
||||
}
|
||||
|
||||
/* Swap the location of these two nodes in the tree */
|
||||
static void swap (huff_t* huff, node_t *node1, node_t *node2) {
|
||||
node_t *par1, *par2;
|
||||
|
||||
par1 = node1->parent;
|
||||
par2 = node2->parent;
|
||||
|
||||
if (par1) {
|
||||
if (par1->left == node1) {
|
||||
par1->left = node2;
|
||||
} else {
|
||||
par1->right = node2;
|
||||
}
|
||||
} else {
|
||||
huff->tree = node2;
|
||||
}
|
||||
|
||||
if (par2) {
|
||||
if (par2->left == node2) {
|
||||
par2->left = node1;
|
||||
} else {
|
||||
par2->right = node1;
|
||||
}
|
||||
} else {
|
||||
huff->tree = node1;
|
||||
}
|
||||
|
||||
node1->parent = par2;
|
||||
node2->parent = par1;
|
||||
}
|
||||
|
||||
/* Swap these two nodes in the linked list (update ranks) */
|
||||
static void swaplist(node_t *node1, node_t *node2) {
|
||||
node_t *par1;
|
||||
|
||||
par1 = node1->next;
|
||||
node1->next = node2->next;
|
||||
node2->next = par1;
|
||||
|
||||
par1 = node1->prev;
|
||||
node1->prev = node2->prev;
|
||||
node2->prev = par1;
|
||||
|
||||
if (node1->next == node1) {
|
||||
node1->next = node2;
|
||||
}
|
||||
if (node2->next == node2) {
|
||||
node2->next = node1;
|
||||
}
|
||||
if (node1->next) {
|
||||
node1->next->prev = node1;
|
||||
}
|
||||
if (node2->next) {
|
||||
node2->next->prev = node2;
|
||||
}
|
||||
if (node1->prev) {
|
||||
node1->prev->next = node1;
|
||||
}
|
||||
if (node2->prev) {
|
||||
node2->prev->next = node2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do the increments */
|
||||
static void increment(huff_t* huff, node_t *node) {
|
||||
node_t *lnode;
|
||||
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->next != NULL && node->next->weight == node->weight) {
|
||||
lnode = *node->head;
|
||||
if (lnode != node->parent) {
|
||||
swap(huff, lnode, node);
|
||||
}
|
||||
swaplist(lnode, node);
|
||||
}
|
||||
if (node->prev && node->prev->weight == node->weight) {
|
||||
*node->head = node->prev;
|
||||
} else {
|
||||
*node->head = NULL;
|
||||
free_ppnode(huff, node->head);
|
||||
}
|
||||
node->weight++;
|
||||
if (node->next && node->next->weight == node->weight) {
|
||||
node->head = node->next->head;
|
||||
} else {
|
||||
node->head = get_ppnode(huff);
|
||||
*node->head = node;
|
||||
}
|
||||
if (node->parent) {
|
||||
increment(huff, node->parent);
|
||||
if (node->prev == node->parent) {
|
||||
swaplist(node, node->parent);
|
||||
if (*node->head == node) {
|
||||
*node->head = node->parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Huff_addRef(huff_t* huff, byte ch) {
|
||||
node_t *tnode, *tnode2;
|
||||
if (huff->loc[ch] == NULL) { /* if this is the first transmission of this node */
|
||||
tnode = &(huff->nodeList[huff->blocNode++]);
|
||||
tnode2 = &(huff->nodeList[huff->blocNode++]);
|
||||
|
||||
tnode2->symbol = INTERNAL_NODE;
|
||||
tnode2->weight = 1;
|
||||
tnode2->next = huff->lhead->next;
|
||||
if (huff->lhead->next) {
|
||||
huff->lhead->next->prev = tnode2;
|
||||
if (huff->lhead->next->weight == 1) {
|
||||
tnode2->head = huff->lhead->next->head;
|
||||
} else {
|
||||
tnode2->head = get_ppnode(huff);
|
||||
*tnode2->head = tnode2;
|
||||
}
|
||||
} else {
|
||||
tnode2->head = get_ppnode(huff);
|
||||
*tnode2->head = tnode2;
|
||||
}
|
||||
huff->lhead->next = tnode2;
|
||||
tnode2->prev = huff->lhead;
|
||||
|
||||
tnode->symbol = ch;
|
||||
tnode->weight = 1;
|
||||
tnode->next = huff->lhead->next;
|
||||
if (huff->lhead->next) {
|
||||
huff->lhead->next->prev = tnode;
|
||||
if (huff->lhead->next->weight == 1) {
|
||||
tnode->head = huff->lhead->next->head;
|
||||
} else {
|
||||
/* this should never happen */
|
||||
tnode->head = get_ppnode(huff);
|
||||
*tnode->head = tnode2;
|
||||
}
|
||||
} else {
|
||||
/* this should never happen */
|
||||
tnode->head = get_ppnode(huff);
|
||||
*tnode->head = tnode;
|
||||
}
|
||||
huff->lhead->next = tnode;
|
||||
tnode->prev = huff->lhead;
|
||||
tnode->left = tnode->right = NULL;
|
||||
|
||||
if (huff->lhead->parent) {
|
||||
if (huff->lhead->parent->left == huff->lhead) { /* lhead is guaranteed to by the NYT */
|
||||
huff->lhead->parent->left = tnode2;
|
||||
} else {
|
||||
huff->lhead->parent->right = tnode2;
|
||||
}
|
||||
} else {
|
||||
huff->tree = tnode2;
|
||||
}
|
||||
|
||||
tnode2->right = tnode;
|
||||
tnode2->left = huff->lhead;
|
||||
|
||||
tnode2->parent = huff->lhead->parent;
|
||||
huff->lhead->parent = tnode->parent = tnode2;
|
||||
|
||||
huff->loc[ch] = tnode;
|
||||
|
||||
increment(huff, tnode2->parent);
|
||||
} else {
|
||||
increment(huff, huff->loc[ch]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get a symbol */
|
||||
int Huff_Receive (node_t *node, int *ch, byte *fin) {
|
||||
while (node && node->symbol == INTERNAL_NODE) {
|
||||
if (get_bit(fin)) {
|
||||
node = node->right;
|
||||
} else {
|
||||
node = node->left;
|
||||
}
|
||||
}
|
||||
if (!node) {
|
||||
return 0;
|
||||
// Com_Error(ERR_DROP, "Illegal tree!\n");
|
||||
}
|
||||
return (*ch = node->symbol);
|
||||
}
|
||||
|
||||
/* Get a symbol */
|
||||
void Huff_offsetReceive (node_t *node, int *ch, byte *fin, int *offset) {
|
||||
bloc = *offset;
|
||||
while (node && node->symbol == INTERNAL_NODE) {
|
||||
if (get_bit(fin)) {
|
||||
node = node->right;
|
||||
} else {
|
||||
node = node->left;
|
||||
}
|
||||
}
|
||||
if (!node) {
|
||||
*ch = 0;
|
||||
return;
|
||||
// Com_Error(ERR_DROP, "Illegal tree!\n");
|
||||
}
|
||||
*ch = node->symbol;
|
||||
*offset = bloc;
|
||||
}
|
||||
|
||||
/* Send the prefix code for this node */
|
||||
static void send(node_t *node, node_t *child, byte *fout) {
|
||||
if (node->parent) {
|
||||
send(node->parent, node, fout);
|
||||
}
|
||||
if (child) {
|
||||
if (node->right == child) {
|
||||
add_bit(1, fout);
|
||||
} else {
|
||||
add_bit(0, fout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Send a symbol */
|
||||
void Huff_transmit (huff_t *huff, int ch, byte *fout) {
|
||||
int i;
|
||||
if (huff->loc[ch] == NULL) {
|
||||
/* node_t hasn't been transmitted, send a NYT, then the symbol */
|
||||
Huff_transmit(huff, NYT, fout);
|
||||
for (i = 7; i >= 0; i--) {
|
||||
add_bit((char)((ch >> i) & 0x1), fout);
|
||||
}
|
||||
} else {
|
||||
send(huff->loc[ch], NULL, fout);
|
||||
}
|
||||
}
|
||||
|
||||
void Huff_offsetTransmit (huff_t *huff, int ch, byte *fout, int *offset) {
|
||||
bloc = *offset;
|
||||
send(huff->loc[ch], NULL, fout);
|
||||
*offset = bloc;
|
||||
}
|
||||
|
||||
void Huff_Decompress(msg_t *mbuf, int offset) {
|
||||
int ch, cch, i, j, size;
|
||||
byte seq[65536];
|
||||
byte* buffer;
|
||||
huff_t huff;
|
||||
|
||||
size = mbuf->cursize - offset;
|
||||
buffer = mbuf->data + offset;
|
||||
|
||||
if ( size <= 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Com_Memset(&huff, 0, sizeof(huff_t));
|
||||
// Initialize the tree & list with the NYT node
|
||||
huff.tree = huff.lhead = huff.ltail = huff.loc[NYT] = &(huff.nodeList[huff.blocNode++]);
|
||||
huff.tree->symbol = NYT;
|
||||
huff.tree->weight = 0;
|
||||
huff.lhead->next = huff.lhead->prev = NULL;
|
||||
huff.tree->parent = huff.tree->left = huff.tree->right = NULL;
|
||||
|
||||
cch = buffer[0]*256 + buffer[1];
|
||||
// don't overflow with bad messages
|
||||
if ( cch > mbuf->maxsize - offset ) {
|
||||
cch = mbuf->maxsize - offset;
|
||||
}
|
||||
bloc = 16;
|
||||
|
||||
for ( j = 0; j < cch; j++ ) {
|
||||
ch = 0;
|
||||
// don't overflow reading from the messages
|
||||
// FIXME: would it be better to have a overflow check in get_bit ?
|
||||
if ( (bloc >> 3) > size ) {
|
||||
seq[j] = 0;
|
||||
break;
|
||||
}
|
||||
Huff_Receive(huff.tree, &ch, buffer); /* Get a character */
|
||||
if ( ch == NYT ) { /* We got a NYT, get the symbol associated with it */
|
||||
ch = 0;
|
||||
for ( i = 0; i < 8; i++ ) {
|
||||
ch = (ch<<1) + get_bit(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
seq[j] = ch; /* Write symbol */
|
||||
|
||||
Huff_addRef(&huff, (byte)ch); /* Increment node */
|
||||
}
|
||||
mbuf->cursize = cch + offset;
|
||||
Com_Memcpy(mbuf->data + offset, seq, cch);
|
||||
}
|
||||
|
||||
extern int oldsize;
|
||||
|
||||
void Huff_Compress(msg_t *mbuf, int offset) {
|
||||
int i, ch, size;
|
||||
byte seq[65536];
|
||||
byte* buffer;
|
||||
huff_t huff;
|
||||
|
||||
size = mbuf->cursize - offset;
|
||||
buffer = mbuf->data+ + offset;
|
||||
|
||||
if (size<=0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Com_Memset(&huff, 0, sizeof(huff_t));
|
||||
// Add the NYT (not yet transmitted) node into the tree/list */
|
||||
huff.tree = huff.lhead = huff.loc[NYT] = &(huff.nodeList[huff.blocNode++]);
|
||||
huff.tree->symbol = NYT;
|
||||
huff.tree->weight = 0;
|
||||
huff.lhead->next = huff.lhead->prev = NULL;
|
||||
huff.tree->parent = huff.tree->left = huff.tree->right = NULL;
|
||||
huff.loc[NYT] = huff.tree;
|
||||
|
||||
seq[0] = (size>>8);
|
||||
seq[1] = size&0xff;
|
||||
|
||||
bloc = 16;
|
||||
|
||||
for (i=0; i<size; i++ ) {
|
||||
ch = buffer[i];
|
||||
Huff_transmit(&huff, ch, seq); /* Transmit symbol */
|
||||
Huff_addRef(&huff, (byte)ch); /* Do update */
|
||||
}
|
||||
|
||||
bloc += 8; // next byte
|
||||
|
||||
mbuf->cursize = (bloc>>3) + offset;
|
||||
Com_Memcpy(mbuf->data+offset, seq, (bloc>>3));
|
||||
}
|
||||
|
||||
void Huff_Init(huffman_t *huff) {
|
||||
|
||||
Com_Memset(&huff->compressor, 0, sizeof(huff_t));
|
||||
Com_Memset(&huff->decompressor, 0, sizeof(huff_t));
|
||||
|
||||
// Initialize the tree & list with the NYT node
|
||||
huff->decompressor.tree = huff->decompressor.lhead = huff->decompressor.ltail = huff->decompressor.loc[NYT] = &(huff->decompressor.nodeList[huff->decompressor.blocNode++]);
|
||||
huff->decompressor.tree->symbol = NYT;
|
||||
huff->decompressor.tree->weight = 0;
|
||||
huff->decompressor.lhead->next = huff->decompressor.lhead->prev = NULL;
|
||||
huff->decompressor.tree->parent = huff->decompressor.tree->left = huff->decompressor.tree->right = NULL;
|
||||
|
||||
// Add the NYT (not yet transmitted) node into the tree/list */
|
||||
huff->compressor.tree = huff->compressor.lhead = huff->compressor.loc[NYT] = &(huff->compressor.nodeList[huff->compressor.blocNode++]);
|
||||
huff->compressor.tree->symbol = NYT;
|
||||
huff->compressor.tree->weight = 0;
|
||||
huff->compressor.lhead->next = huff->compressor.lhead->prev = NULL;
|
||||
huff->compressor.tree->parent = huff->compressor.tree->left = huff->compressor.tree->right = NULL;
|
||||
huff->compressor.loc[NYT] = huff->compressor.tree;
|
||||
}
|
||||
|
||||
|
|
598
code/qcommon/md4.c
Normal file → Executable file
598
code/qcommon/md4.c
Normal file → Executable file
|
@ -1,299 +1,299 @@
|
|||
/* GLOBAL.H - RSAREF types and constants */
|
||||
|
||||
#include <string.h>
|
||||
#if defined(_WIN32)
|
||||
#pragma warning(disable : 4711) // selected for automatic inline expansion
|
||||
#endif
|
||||
|
||||
/* POINTER defines a generic pointer type */
|
||||
typedef unsigned char *POINTER;
|
||||
|
||||
/* UINT2 defines a two byte word */
|
||||
typedef unsigned short int UINT2;
|
||||
|
||||
/* UINT4 defines a four byte word */
|
||||
typedef unsigned long int UINT4;
|
||||
|
||||
|
||||
/* MD4.H - header file for MD4C.C */
|
||||
|
||||
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
License to copy and use this software is granted provided that it is identified as the “RSA Data Security, Inc. MD4 Message-Digest Algorithm” in all material mentioning or referencing this software or this function.
|
||||
License is also granted to make and use derivative works provided that such works are identified as “derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm” in all material mentioning or referencing the derived work.
|
||||
RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided “as is” without express or implied warranty of any kind.
|
||||
|
||||
These notices must be retained in any copies of any part of this documentation and/or software. */
|
||||
|
||||
/* MD4 context. */
|
||||
typedef struct {
|
||||
UINT4 state[4]; /* state (ABCD) */
|
||||
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
|
||||
unsigned char buffer[64]; /* input buffer */
|
||||
} MD4_CTX;
|
||||
|
||||
void MD4Init (MD4_CTX *);
|
||||
void MD4Update (MD4_CTX *, const unsigned char *, unsigned int);
|
||||
void MD4Final (unsigned char [16], MD4_CTX *);
|
||||
|
||||
#ifndef __VECTORC
|
||||
void Com_Memset (void* dest, const int val, const size_t count);
|
||||
void Com_Memcpy (void* dest, const void* src, const size_t count);
|
||||
#else
|
||||
#define Com_Memset memset
|
||||
#define Com_Memcpy memcpy
|
||||
#endif
|
||||
|
||||
/* MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm */
|
||||
/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
|
||||
|
||||
License to copy and use this software is granted provided that it is identified as the
|
||||
RSA Data Security, Inc. MD4 Message-Digest Algorithm
|
||||
in all material mentioning or referencing this software or this function.
|
||||
License is also granted to make and use derivative works provided that such works are identified as
|
||||
derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm
|
||||
in all material mentioning or referencing the derived work.
|
||||
RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided
|
||||
as is without express or implied warranty of any kind.
|
||||
|
||||
These notices must be retained in any copies of any part of this documentation and/or software. */
|
||||
|
||||
/* Constants for MD4Transform routine. */
|
||||
#define S11 3
|
||||
#define S12 7
|
||||
#define S13 11
|
||||
#define S14 19
|
||||
#define S21 3
|
||||
#define S22 5
|
||||
#define S23 9
|
||||
#define S24 13
|
||||
#define S31 3
|
||||
#define S32 9
|
||||
#define S33 11
|
||||
#define S34 15
|
||||
|
||||
static void MD4Transform (UINT4 [4], const unsigned char [64]);
|
||||
static void Encode (unsigned char *, UINT4 *, unsigned int);
|
||||
static void Decode (UINT4 *, const unsigned char *, unsigned int);
|
||||
|
||||
static unsigned char PADDING[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/* F, G and H are basic MD4 functions. */
|
||||
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||
#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
|
||||
/* ROTATE_LEFT rotates x left n bits. */
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||
|
||||
/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
|
||||
/* Rotation is separate from addition to prevent recomputation */
|
||||
#define FF(a, b, c, d, x, s) {(a) += F ((b), (c), (d)) + (x); (a) = ROTATE_LEFT ((a), (s));}
|
||||
|
||||
#define GG(a, b, c, d, x, s) {(a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; (a) = ROTATE_LEFT ((a), (s));}
|
||||
|
||||
#define HH(a, b, c, d, x, s) {(a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; (a) = ROTATE_LEFT ((a), (s));}
|
||||
|
||||
|
||||
/* MD4 initialization. Begins an MD4 operation, writing a new context. */
|
||||
void MD4Init (MD4_CTX *context)
|
||||
{
|
||||
context->count[0] = context->count[1] = 0;
|
||||
|
||||
/* Load magic initialization constants.*/
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xefcdab89;
|
||||
context->state[2] = 0x98badcfe;
|
||||
context->state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
/* MD4 block update operation. Continues an MD4 message-digest operation, processing another message block, and updating the context. */
|
||||
void MD4Update (MD4_CTX *context, const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
unsigned int i, index, partLen;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
|
||||
|
||||
/* Update number of bits */
|
||||
if ((context->count[0] += ((UINT4)inputLen << 3))< ((UINT4)inputLen << 3))
|
||||
context->count[1]++;
|
||||
|
||||
context->count[1] += ((UINT4)inputLen >> 29);
|
||||
|
||||
partLen = 64 - index;
|
||||
|
||||
/* Transform as many times as possible.*/
|
||||
if (inputLen >= partLen)
|
||||
{
|
||||
Com_Memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen);
|
||||
MD4Transform (context->state, context->buffer);
|
||||
|
||||
for (i = partLen; i + 63 < inputLen; i += 64)
|
||||
MD4Transform (context->state, &input[i]);
|
||||
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
i = 0;
|
||||
|
||||
/* Buffer remaining input */
|
||||
Com_Memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i);
|
||||
}
|
||||
|
||||
|
||||
/* MD4 finalization. Ends an MD4 message-digest operation, writing the the message digest and zeroizing the context. */
|
||||
void MD4Final (unsigned char digest[16], MD4_CTX *context)
|
||||
{
|
||||
unsigned char bits[8];
|
||||
unsigned int index, padLen;
|
||||
|
||||
/* Save number of bits */
|
||||
Encode (bits, context->count, 8);
|
||||
|
||||
/* Pad out to 56 mod 64.*/
|
||||
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
|
||||
padLen = (index < 56) ? (56 - index) : (120 - index);
|
||||
MD4Update (context, PADDING, padLen);
|
||||
|
||||
/* Append length (before padding) */
|
||||
MD4Update (context, bits, 8);
|
||||
|
||||
/* Store state in digest */
|
||||
Encode (digest, context->state, 16);
|
||||
|
||||
/* Zeroize sensitive information.*/
|
||||
Com_Memset ((POINTER)context, 0, sizeof (*context));
|
||||
}
|
||||
|
||||
|
||||
/* MD4 basic transformation. Transforms state based on block. */
|
||||
static void MD4Transform (UINT4 state[4], const unsigned char block[64])
|
||||
{
|
||||
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||
|
||||
Decode (x, block, 64);
|
||||
|
||||
/* Round 1 */
|
||||
FF (a, b, c, d, x[ 0], S11); /* 1 */
|
||||
FF (d, a, b, c, x[ 1], S12); /* 2 */
|
||||
FF (c, d, a, b, x[ 2], S13); /* 3 */
|
||||
FF (b, c, d, a, x[ 3], S14); /* 4 */
|
||||
FF (a, b, c, d, x[ 4], S11); /* 5 */
|
||||
FF (d, a, b, c, x[ 5], S12); /* 6 */
|
||||
FF (c, d, a, b, x[ 6], S13); /* 7 */
|
||||
FF (b, c, d, a, x[ 7], S14); /* 8 */
|
||||
FF (a, b, c, d, x[ 8], S11); /* 9 */
|
||||
FF (d, a, b, c, x[ 9], S12); /* 10 */
|
||||
FF (c, d, a, b, x[10], S13); /* 11 */
|
||||
FF (b, c, d, a, x[11], S14); /* 12 */
|
||||
FF (a, b, c, d, x[12], S11); /* 13 */
|
||||
FF (d, a, b, c, x[13], S12); /* 14 */
|
||||
FF (c, d, a, b, x[14], S13); /* 15 */
|
||||
FF (b, c, d, a, x[15], S14); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
GG (a, b, c, d, x[ 0], S21); /* 17 */
|
||||
GG (d, a, b, c, x[ 4], S22); /* 18 */
|
||||
GG (c, d, a, b, x[ 8], S23); /* 19 */
|
||||
GG (b, c, d, a, x[12], S24); /* 20 */
|
||||
GG (a, b, c, d, x[ 1], S21); /* 21 */
|
||||
GG (d, a, b, c, x[ 5], S22); /* 22 */
|
||||
GG (c, d, a, b, x[ 9], S23); /* 23 */
|
||||
GG (b, c, d, a, x[13], S24); /* 24 */
|
||||
GG (a, b, c, d, x[ 2], S21); /* 25 */
|
||||
GG (d, a, b, c, x[ 6], S22); /* 26 */
|
||||
GG (c, d, a, b, x[10], S23); /* 27 */
|
||||
GG (b, c, d, a, x[14], S24); /* 28 */
|
||||
GG (a, b, c, d, x[ 3], S21); /* 29 */
|
||||
GG (d, a, b, c, x[ 7], S22); /* 30 */
|
||||
GG (c, d, a, b, x[11], S23); /* 31 */
|
||||
GG (b, c, d, a, x[15], S24); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
HH (a, b, c, d, x[ 0], S31); /* 33 */
|
||||
HH (d, a, b, c, x[ 8], S32); /* 34 */
|
||||
HH (c, d, a, b, x[ 4], S33); /* 35 */
|
||||
HH (b, c, d, a, x[12], S34); /* 36 */
|
||||
HH (a, b, c, d, x[ 2], S31); /* 37 */
|
||||
HH (d, a, b, c, x[10], S32); /* 38 */
|
||||
HH (c, d, a, b, x[ 6], S33); /* 39 */
|
||||
HH (b, c, d, a, x[14], S34); /* 40 */
|
||||
HH (a, b, c, d, x[ 1], S31); /* 41 */
|
||||
HH (d, a, b, c, x[ 9], S32); /* 42 */
|
||||
HH (c, d, a, b, x[ 5], S33); /* 43 */
|
||||
HH (b, c, d, a, x[13], S34); /* 44 */
|
||||
HH (a, b, c, d, x[ 3], S31); /* 45 */
|
||||
HH (d, a, b, c, x[11], S32); /* 46 */
|
||||
HH (c, d, a, b, x[ 7], S33); /* 47 */
|
||||
HH (b, c, d, a, x[15], S34); /* 48 */
|
||||
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
|
||||
/* Zeroize sensitive information.*/
|
||||
Com_Memset ((POINTER)x, 0, sizeof (x));
|
||||
}
|
||||
|
||||
|
||||
/* Encodes input (UINT4) into output (unsigned char). Assumes len is a multiple of 4. */
|
||||
static void Encode (unsigned char *output, UINT4 *input, unsigned int len)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4) {
|
||||
output[j] = (unsigned char)(input[i] & 0xff);
|
||||
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
|
||||
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
|
||||
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Decodes input (unsigned char) into output (UINT4). Assumes len is a multiple of 4. */
|
||||
static void Decode (UINT4 *output, const unsigned char *input, unsigned int len)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
|
||||
unsigned Com_BlockChecksum (void *buffer, int length)
|
||||
{
|
||||
int digest[4];
|
||||
unsigned val;
|
||||
MD4_CTX ctx;
|
||||
|
||||
MD4Init (&ctx);
|
||||
MD4Update (&ctx, (unsigned char *)buffer, length);
|
||||
MD4Final ( (unsigned char *)digest, &ctx);
|
||||
|
||||
val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
unsigned Com_BlockChecksumKey (void *buffer, int length, int key)
|
||||
{
|
||||
int digest[4];
|
||||
unsigned val;
|
||||
MD4_CTX ctx;
|
||||
|
||||
MD4Init (&ctx);
|
||||
MD4Update (&ctx, (unsigned char *)&key, 4);
|
||||
MD4Update (&ctx, (unsigned char *)buffer, length);
|
||||
MD4Final ( (unsigned char *)digest, &ctx);
|
||||
|
||||
val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
|
||||
|
||||
return val;
|
||||
}
|
||||
/* GLOBAL.H - RSAREF types and constants */
|
||||
|
||||
#include <string.h>
|
||||
#if defined(_WIN32)
|
||||
#pragma warning(disable : 4711) // selected for automatic inline expansion
|
||||
#endif
|
||||
|
||||
/* POINTER defines a generic pointer type */
|
||||
typedef unsigned char *POINTER;
|
||||
|
||||
/* UINT2 defines a two byte word */
|
||||
typedef unsigned short int UINT2;
|
||||
|
||||
/* UINT4 defines a four byte word */
|
||||
typedef unsigned long int UINT4;
|
||||
|
||||
|
||||
/* MD4.H - header file for MD4C.C */
|
||||
|
||||
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
License to copy and use this software is granted provided that it is identified as the “RSA Data Security, Inc. MD4 Message-Digest Algorithm” in all material mentioning or referencing this software or this function.
|
||||
License is also granted to make and use derivative works provided that such works are identified as “derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm” in all material mentioning or referencing the derived work.
|
||||
RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided “as is” without express or implied warranty of any kind.
|
||||
|
||||
These notices must be retained in any copies of any part of this documentation and/or software. */
|
||||
|
||||
/* MD4 context. */
|
||||
typedef struct {
|
||||
UINT4 state[4]; /* state (ABCD) */
|
||||
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
|
||||
unsigned char buffer[64]; /* input buffer */
|
||||
} MD4_CTX;
|
||||
|
||||
void MD4Init (MD4_CTX *);
|
||||
void MD4Update (MD4_CTX *, const unsigned char *, unsigned int);
|
||||
void MD4Final (unsigned char [16], MD4_CTX *);
|
||||
|
||||
#ifndef __VECTORC
|
||||
void Com_Memset (void* dest, const int val, const size_t count);
|
||||
void Com_Memcpy (void* dest, const void* src, const size_t count);
|
||||
#else
|
||||
#define Com_Memset memset
|
||||
#define Com_Memcpy memcpy
|
||||
#endif
|
||||
|
||||
/* MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm */
|
||||
/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
|
||||
|
||||
License to copy and use this software is granted provided that it is identified as the
|
||||
RSA Data Security, Inc. MD4 Message-Digest Algorithm
|
||||
in all material mentioning or referencing this software or this function.
|
||||
License is also granted to make and use derivative works provided that such works are identified as
|
||||
derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm
|
||||
in all material mentioning or referencing the derived work.
|
||||
RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided
|
||||
as is without express or implied warranty of any kind.
|
||||
|
||||
These notices must be retained in any copies of any part of this documentation and/or software. */
|
||||
|
||||
/* Constants for MD4Transform routine. */
|
||||
#define S11 3
|
||||
#define S12 7
|
||||
#define S13 11
|
||||
#define S14 19
|
||||
#define S21 3
|
||||
#define S22 5
|
||||
#define S23 9
|
||||
#define S24 13
|
||||
#define S31 3
|
||||
#define S32 9
|
||||
#define S33 11
|
||||
#define S34 15
|
||||
|
||||
static void MD4Transform (UINT4 [4], const unsigned char [64]);
|
||||
static void Encode (unsigned char *, UINT4 *, unsigned int);
|
||||
static void Decode (UINT4 *, const unsigned char *, unsigned int);
|
||||
|
||||
static unsigned char PADDING[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/* F, G and H are basic MD4 functions. */
|
||||
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||
#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
|
||||
/* ROTATE_LEFT rotates x left n bits. */
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||
|
||||
/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
|
||||
/* Rotation is separate from addition to prevent recomputation */
|
||||
#define FF(a, b, c, d, x, s) {(a) += F ((b), (c), (d)) + (x); (a) = ROTATE_LEFT ((a), (s));}
|
||||
|
||||
#define GG(a, b, c, d, x, s) {(a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; (a) = ROTATE_LEFT ((a), (s));}
|
||||
|
||||
#define HH(a, b, c, d, x, s) {(a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; (a) = ROTATE_LEFT ((a), (s));}
|
||||
|
||||
|
||||
/* MD4 initialization. Begins an MD4 operation, writing a new context. */
|
||||
void MD4Init (MD4_CTX *context)
|
||||
{
|
||||
context->count[0] = context->count[1] = 0;
|
||||
|
||||
/* Load magic initialization constants.*/
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xefcdab89;
|
||||
context->state[2] = 0x98badcfe;
|
||||
context->state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
/* MD4 block update operation. Continues an MD4 message-digest operation, processing another message block, and updating the context. */
|
||||
void MD4Update (MD4_CTX *context, const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
unsigned int i, index, partLen;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
|
||||
|
||||
/* Update number of bits */
|
||||
if ((context->count[0] += ((UINT4)inputLen << 3))< ((UINT4)inputLen << 3))
|
||||
context->count[1]++;
|
||||
|
||||
context->count[1] += ((UINT4)inputLen >> 29);
|
||||
|
||||
partLen = 64 - index;
|
||||
|
||||
/* Transform as many times as possible.*/
|
||||
if (inputLen >= partLen)
|
||||
{
|
||||
Com_Memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen);
|
||||
MD4Transform (context->state, context->buffer);
|
||||
|
||||
for (i = partLen; i + 63 < inputLen; i += 64)
|
||||
MD4Transform (context->state, &input[i]);
|
||||
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
i = 0;
|
||||
|
||||
/* Buffer remaining input */
|
||||
Com_Memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i);
|
||||
}
|
||||
|
||||
|
||||
/* MD4 finalization. Ends an MD4 message-digest operation, writing the the message digest and zeroizing the context. */
|
||||
void MD4Final (unsigned char digest[16], MD4_CTX *context)
|
||||
{
|
||||
unsigned char bits[8];
|
||||
unsigned int index, padLen;
|
||||
|
||||
/* Save number of bits */
|
||||
Encode (bits, context->count, 8);
|
||||
|
||||
/* Pad out to 56 mod 64.*/
|
||||
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
|
||||
padLen = (index < 56) ? (56 - index) : (120 - index);
|
||||
MD4Update (context, PADDING, padLen);
|
||||
|
||||
/* Append length (before padding) */
|
||||
MD4Update (context, bits, 8);
|
||||
|
||||
/* Store state in digest */
|
||||
Encode (digest, context->state, 16);
|
||||
|
||||
/* Zeroize sensitive information.*/
|
||||
Com_Memset ((POINTER)context, 0, sizeof (*context));
|
||||
}
|
||||
|
||||
|
||||
/* MD4 basic transformation. Transforms state based on block. */
|
||||
static void MD4Transform (UINT4 state[4], const unsigned char block[64])
|
||||
{
|
||||
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||
|
||||
Decode (x, block, 64);
|
||||
|
||||
/* Round 1 */
|
||||
FF (a, b, c, d, x[ 0], S11); /* 1 */
|
||||
FF (d, a, b, c, x[ 1], S12); /* 2 */
|
||||
FF (c, d, a, b, x[ 2], S13); /* 3 */
|
||||
FF (b, c, d, a, x[ 3], S14); /* 4 */
|
||||
FF (a, b, c, d, x[ 4], S11); /* 5 */
|
||||
FF (d, a, b, c, x[ 5], S12); /* 6 */
|
||||
FF (c, d, a, b, x[ 6], S13); /* 7 */
|
||||
FF (b, c, d, a, x[ 7], S14); /* 8 */
|
||||
FF (a, b, c, d, x[ 8], S11); /* 9 */
|
||||
FF (d, a, b, c, x[ 9], S12); /* 10 */
|
||||
FF (c, d, a, b, x[10], S13); /* 11 */
|
||||
FF (b, c, d, a, x[11], S14); /* 12 */
|
||||
FF (a, b, c, d, x[12], S11); /* 13 */
|
||||
FF (d, a, b, c, x[13], S12); /* 14 */
|
||||
FF (c, d, a, b, x[14], S13); /* 15 */
|
||||
FF (b, c, d, a, x[15], S14); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
GG (a, b, c, d, x[ 0], S21); /* 17 */
|
||||
GG (d, a, b, c, x[ 4], S22); /* 18 */
|
||||
GG (c, d, a, b, x[ 8], S23); /* 19 */
|
||||
GG (b, c, d, a, x[12], S24); /* 20 */
|
||||
GG (a, b, c, d, x[ 1], S21); /* 21 */
|
||||
GG (d, a, b, c, x[ 5], S22); /* 22 */
|
||||
GG (c, d, a, b, x[ 9], S23); /* 23 */
|
||||
GG (b, c, d, a, x[13], S24); /* 24 */
|
||||
GG (a, b, c, d, x[ 2], S21); /* 25 */
|
||||
GG (d, a, b, c, x[ 6], S22); /* 26 */
|
||||
GG (c, d, a, b, x[10], S23); /* 27 */
|
||||
GG (b, c, d, a, x[14], S24); /* 28 */
|
||||
GG (a, b, c, d, x[ 3], S21); /* 29 */
|
||||
GG (d, a, b, c, x[ 7], S22); /* 30 */
|
||||
GG (c, d, a, b, x[11], S23); /* 31 */
|
||||
GG (b, c, d, a, x[15], S24); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
HH (a, b, c, d, x[ 0], S31); /* 33 */
|
||||
HH (d, a, b, c, x[ 8], S32); /* 34 */
|
||||
HH (c, d, a, b, x[ 4], S33); /* 35 */
|
||||
HH (b, c, d, a, x[12], S34); /* 36 */
|
||||
HH (a, b, c, d, x[ 2], S31); /* 37 */
|
||||
HH (d, a, b, c, x[10], S32); /* 38 */
|
||||
HH (c, d, a, b, x[ 6], S33); /* 39 */
|
||||
HH (b, c, d, a, x[14], S34); /* 40 */
|
||||
HH (a, b, c, d, x[ 1], S31); /* 41 */
|
||||
HH (d, a, b, c, x[ 9], S32); /* 42 */
|
||||
HH (c, d, a, b, x[ 5], S33); /* 43 */
|
||||
HH (b, c, d, a, x[13], S34); /* 44 */
|
||||
HH (a, b, c, d, x[ 3], S31); /* 45 */
|
||||
HH (d, a, b, c, x[11], S32); /* 46 */
|
||||
HH (c, d, a, b, x[ 7], S33); /* 47 */
|
||||
HH (b, c, d, a, x[15], S34); /* 48 */
|
||||
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
|
||||
/* Zeroize sensitive information.*/
|
||||
Com_Memset ((POINTER)x, 0, sizeof (x));
|
||||
}
|
||||
|
||||
|
||||
/* Encodes input (UINT4) into output (unsigned char). Assumes len is a multiple of 4. */
|
||||
static void Encode (unsigned char *output, UINT4 *input, unsigned int len)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4) {
|
||||
output[j] = (unsigned char)(input[i] & 0xff);
|
||||
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
|
||||
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
|
||||
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Decodes input (unsigned char) into output (UINT4). Assumes len is a multiple of 4. */
|
||||
static void Decode (UINT4 *output, const unsigned char *input, unsigned int len)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
|
||||
unsigned Com_BlockChecksum (void *buffer, int length)
|
||||
{
|
||||
int digest[4];
|
||||
unsigned val;
|
||||
MD4_CTX ctx;
|
||||
|
||||
MD4Init (&ctx);
|
||||
MD4Update (&ctx, (unsigned char *)buffer, length);
|
||||
MD4Final ( (unsigned char *)digest, &ctx);
|
||||
|
||||
val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
unsigned Com_BlockChecksumKey (void *buffer, int length, int key)
|
||||
{
|
||||
int digest[4];
|
||||
unsigned val;
|
||||
MD4_CTX ctx;
|
||||
|
||||
MD4Init (&ctx);
|
||||
MD4Update (&ctx, (unsigned char *)&key, 4);
|
||||
MD4Update (&ctx, (unsigned char *)buffer, length);
|
||||
MD4Final ( (unsigned char *)digest, &ctx);
|
||||
|
||||
val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
|
||||
|
||||
return val;
|
||||
}
|
||||
|
|
3514
code/qcommon/msg.c
Normal file → Executable file
3514
code/qcommon/msg.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
1484
code/qcommon/net_chan.c
Normal file → Executable file
1484
code/qcommon/net_chan.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
2134
code/qcommon/qcommon.h
Normal file → Executable file
2134
code/qcommon/qcommon.h
Normal file → Executable file
File diff suppressed because it is too large
Load diff
976
code/qcommon/qfiles.h
Normal file → Executable file
976
code/qcommon/qfiles.h
Normal file → Executable file
|
@ -1,488 +1,488 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef __QFILES_H__
|
||||
#define __QFILES_H__
|
||||
|
||||
//
|
||||
// qfiles.h: quake file formats
|
||||
// This file must be identical in the quake and utils directories
|
||||
//
|
||||
|
||||
// surface geometry should not exceed these limits
|
||||
#define SHADER_MAX_VERTEXES 1000
|
||||
#define SHADER_MAX_INDEXES (6*SHADER_MAX_VERTEXES)
|
||||
|
||||
|
||||
// the maximum size of game relative pathnames
|
||||
#define MAX_QPATH 64
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
QVM files
|
||||
|
||||
========================================================================
|
||||
*/
|
||||
|
||||
#define VM_MAGIC 0x12721444
|
||||
typedef struct {
|
||||
int vmMagic;
|
||||
|
||||
int instructionCount;
|
||||
|
||||
int codeOffset;
|
||||
int codeLength;
|
||||
|
||||
int dataOffset;
|
||||
int dataLength;
|
||||
int litLength; // ( dataLength - litLength ) should be byteswapped on load
|
||||
int bssLength; // zero filled memory appended to datalength
|
||||
} vmHeader_t;
|
||||
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
PCX files are used for 8 bit images
|
||||
|
||||
========================================================================
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char manufacturer;
|
||||
char version;
|
||||
char encoding;
|
||||
char bits_per_pixel;
|
||||
unsigned short xmin,ymin,xmax,ymax;
|
||||
unsigned short hres,vres;
|
||||
unsigned char palette[48];
|
||||
char reserved;
|
||||
char color_planes;
|
||||
unsigned short bytes_per_line;
|
||||
unsigned short palette_type;
|
||||
char filler[58];
|
||||
unsigned char data; // unbounded
|
||||
} pcx_t;
|
||||
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
TGA files are used for 24/32 bit images
|
||||
|
||||
========================================================================
|
||||
*/
|
||||
|
||||
typedef struct _TargaHeader {
|
||||
unsigned char id_length, colormap_type, image_type;
|
||||
unsigned short colormap_index, colormap_length;
|
||||
unsigned char colormap_size;
|
||||
unsigned short x_origin, y_origin, width, height;
|
||||
unsigned char pixel_size, attributes;
|
||||
} TargaHeader;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
.MD3 triangle model file format
|
||||
|
||||
========================================================================
|
||||
*/
|
||||
|
||||
#define MD3_IDENT (('3'<<24)+('P'<<16)+('D'<<8)+'I')
|
||||
#define MD3_VERSION 15
|
||||
|
||||
// limits
|
||||
#define MD3_MAX_LODS 3
|
||||
#define MD3_MAX_TRIANGLES 8192 // per surface
|
||||
#define MD3_MAX_VERTS 4096 // per surface
|
||||
#define MD3_MAX_SHADERS 256 // per surface
|
||||
#define MD3_MAX_FRAMES 1024 // per model
|
||||
#define MD3_MAX_SURFACES 32 // per model
|
||||
#define MD3_MAX_TAGS 16 // per frame
|
||||
|
||||
// vertex scales
|
||||
#define MD3_XYZ_SCALE (1.0/64)
|
||||
|
||||
typedef struct md3Frame_s {
|
||||
vec3_t bounds[2];
|
||||
vec3_t localOrigin;
|
||||
float radius;
|
||||
char name[16];
|
||||
} md3Frame_t;
|
||||
|
||||
typedef struct md3Tag_s {
|
||||
char name[MAX_QPATH]; // tag name
|
||||
vec3_t origin;
|
||||
vec3_t axis[3];
|
||||
} md3Tag_t;
|
||||
|
||||
/*
|
||||
** md3Surface_t
|
||||
**
|
||||
** CHUNK SIZE
|
||||
** header sizeof( md3Surface_t )
|
||||
** shaders sizeof( md3Shader_t ) * numShaders
|
||||
** triangles[0] sizeof( md3Triangle_t ) * numTriangles
|
||||
** st sizeof( md3St_t ) * numVerts
|
||||
** XyzNormals sizeof( md3XyzNormal_t ) * numVerts * numFrames
|
||||
*/
|
||||
typedef struct {
|
||||
int ident; //
|
||||
|
||||
char name[MAX_QPATH]; // polyset name
|
||||
|
||||
int flags;
|
||||
int numFrames; // all surfaces in a model should have the same
|
||||
|
||||
int numShaders; // all surfaces in a model should have the same
|
||||
int numVerts;
|
||||
|
||||
int numTriangles;
|
||||
int ofsTriangles;
|
||||
|
||||
int ofsShaders; // offset from start of md3Surface_t
|
||||
int ofsSt; // texture coords are common for all frames
|
||||
int ofsXyzNormals; // numVerts * numFrames
|
||||
|
||||
int ofsEnd; // next surface follows
|
||||
} md3Surface_t;
|
||||
|
||||
typedef struct {
|
||||
char name[MAX_QPATH];
|
||||
int shaderIndex; // for in-game use
|
||||
} md3Shader_t;
|
||||
|
||||
typedef struct {
|
||||
int indexes[3];
|
||||
} md3Triangle_t;
|
||||
|
||||
typedef struct {
|
||||
float st[2];
|
||||
} md3St_t;
|
||||
|
||||
typedef struct {
|
||||
short xyz[3];
|
||||
short normal;
|
||||
} md3XyzNormal_t;
|
||||
|
||||
typedef struct {
|
||||
int ident;
|
||||
int version;
|
||||
|
||||
char name[MAX_QPATH]; // model name
|
||||
|
||||
int flags;
|
||||
|
||||
int numFrames;
|
||||
int numTags;
|
||||
int numSurfaces;
|
||||
|
||||
int numSkins;
|
||||
|
||||
int ofsFrames; // offset for first frame
|
||||
int ofsTags; // numFrames * numTags
|
||||
int ofsSurfaces; // first surface, others follow
|
||||
|
||||
int ofsEnd; // end of file
|
||||
} md3Header_t;
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
MD4 file format
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define MD4_IDENT (('4'<<24)+('P'<<16)+('D'<<8)+'I')
|
||||
#define MD4_VERSION 1
|
||||
#define MD4_MAX_BONES 128
|
||||
|
||||
typedef struct {
|
||||
int boneIndex; // these are indexes into the boneReferences,
|
||||
float boneWeight; // not the global per-frame bone list
|
||||
vec3_t offset;
|
||||
} md4Weight_t;
|
||||
|
||||
typedef struct {
|
||||
vec3_t normal;
|
||||
vec2_t texCoords;
|
||||
int numWeights;
|
||||
md4Weight_t weights[1]; // variable sized
|
||||
} md4Vertex_t;
|
||||
|
||||
typedef struct {
|
||||
int indexes[3];
|
||||
} md4Triangle_t;
|
||||
|
||||
typedef struct {
|
||||
int ident;
|
||||
|
||||
char name[MAX_QPATH]; // polyset name
|
||||
char shader[MAX_QPATH];
|
||||
int shaderIndex; // for in-game use
|
||||
|
||||
int ofsHeader; // this will be a negative number
|
||||
|
||||
int numVerts;
|
||||
int ofsVerts;
|
||||
|
||||
int numTriangles;
|
||||
int ofsTriangles;
|
||||
|
||||
// Bone references are a set of ints representing all the bones
|
||||
// present in any vertex weights for this surface. This is
|
||||
// needed because a model may have surfaces that need to be
|
||||
// drawn at different sort times, and we don't want to have
|
||||
// to re-interpolate all the bones for each surface.
|
||||
int numBoneReferences;
|
||||
int ofsBoneReferences;
|
||||
|
||||
int ofsEnd; // next surface follows
|
||||
} md4Surface_t;
|
||||
|
||||
typedef struct {
|
||||
float matrix[3][4];
|
||||
} md4Bone_t;
|
||||
|
||||
typedef struct {
|
||||
vec3_t bounds[2]; // bounds of all surfaces of all LOD's for this frame
|
||||
vec3_t localOrigin; // midpoint of bounds, used for sphere cull
|
||||
float radius; // dist from localOrigin to corner
|
||||
md4Bone_t bones[1]; // [numBones]
|
||||
} md4Frame_t;
|
||||
|
||||
typedef struct {
|
||||
int numSurfaces;
|
||||
int ofsSurfaces; // first surface, others follow
|
||||
int ofsEnd; // next lod follows
|
||||
} md4LOD_t;
|
||||
|
||||
typedef struct {
|
||||
int ident;
|
||||
int version;
|
||||
|
||||
char name[MAX_QPATH]; // model name
|
||||
|
||||
// frames and bones are shared by all levels of detail
|
||||
int numFrames;
|
||||
int numBones;
|
||||
int ofsBoneNames; // char name[ MAX_QPATH ]
|
||||
int ofsFrames; // md4Frame_t[numFrames]
|
||||
|
||||
// each level of detail has completely separate sets of surfaces
|
||||
int numLODs;
|
||||
int ofsLODs;
|
||||
|
||||
int ofsEnd; // end of file
|
||||
} md4Header_t;
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
.BSP file format
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
#define BSP_IDENT (('P'<<24)+('S'<<16)+('B'<<8)+'I')
|
||||
// little-endian "IBSP"
|
||||
|
||||
#define BSP_VERSION 46
|
||||
|
||||
|
||||
// there shouldn't be any problem with increasing these values at the
|
||||
// expense of more memory allocation in the utilities
|
||||
#define MAX_MAP_MODELS 0x400
|
||||
#define MAX_MAP_BRUSHES 0x8000
|
||||
#define MAX_MAP_ENTITIES 0x800
|
||||
#define MAX_MAP_ENTSTRING 0x40000
|
||||
#define MAX_MAP_SHADERS 0x400
|
||||
|
||||
#define MAX_MAP_AREAS 0x100 // MAX_MAP_AREA_BYTES in q_shared must match!
|
||||
#define MAX_MAP_FOGS 0x100
|
||||
#define MAX_MAP_PLANES 0x20000
|
||||
#define MAX_MAP_NODES 0x20000
|
||||
#define MAX_MAP_BRUSHSIDES 0x20000
|
||||
#define MAX_MAP_LEAFS 0x20000
|
||||
#define MAX_MAP_LEAFFACES 0x20000
|
||||
#define MAX_MAP_LEAFBRUSHES 0x40000
|
||||
#define MAX_MAP_PORTALS 0x20000
|
||||
#define MAX_MAP_LIGHTING 0x800000
|
||||
#define MAX_MAP_LIGHTGRID 0x800000
|
||||
#define MAX_MAP_VISIBILITY 0x200000
|
||||
|
||||
#define MAX_MAP_DRAW_SURFS 0x20000
|
||||
#define MAX_MAP_DRAW_VERTS 0x80000
|
||||
#define MAX_MAP_DRAW_INDEXES 0x80000
|
||||
|
||||
|
||||
// key / value pair sizes in the entities lump
|
||||
#define MAX_KEY 32
|
||||
#define MAX_VALUE 1024
|
||||
|
||||
// the editor uses these predefined yaw angles to orient entities up or down
|
||||
#define ANGLE_UP -1
|
||||
#define ANGLE_DOWN -2
|
||||
|
||||
#define LIGHTMAP_WIDTH 128
|
||||
#define LIGHTMAP_HEIGHT 128
|
||||
|
||||
#define MAX_WORLD_COORD ( 128*1024 )
|
||||
#define MIN_WORLD_COORD ( -128*1024 )
|
||||
#define WORLD_SIZE ( MAX_WORLD_COORD - MIN_WORLD_COORD )
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
typedef struct {
|
||||
int fileofs, filelen;
|
||||
} lump_t;
|
||||
|
||||
#define LUMP_ENTITIES 0
|
||||
#define LUMP_SHADERS 1
|
||||
#define LUMP_PLANES 2
|
||||
#define LUMP_NODES 3
|
||||
#define LUMP_LEAFS 4
|
||||
#define LUMP_LEAFSURFACES 5
|
||||
#define LUMP_LEAFBRUSHES 6
|
||||
#define LUMP_MODELS 7
|
||||
#define LUMP_BRUSHES 8
|
||||
#define LUMP_BRUSHSIDES 9
|
||||
#define LUMP_DRAWVERTS 10
|
||||
#define LUMP_DRAWINDEXES 11
|
||||
#define LUMP_FOGS 12
|
||||
#define LUMP_SURFACES 13
|
||||
#define LUMP_LIGHTMAPS 14
|
||||
#define LUMP_LIGHTGRID 15
|
||||
#define LUMP_VISIBILITY 16
|
||||
#define HEADER_LUMPS 17
|
||||
|
||||
typedef struct {
|
||||
int ident;
|
||||
int version;
|
||||
|
||||
lump_t lumps[HEADER_LUMPS];
|
||||
} dheader_t;
|
||||
|
||||
typedef struct {
|
||||
float mins[3], maxs[3];
|
||||
int firstSurface, numSurfaces;
|
||||
int firstBrush, numBrushes;
|
||||
} dmodel_t;
|
||||
|
||||
typedef struct {
|
||||
char shader[MAX_QPATH];
|
||||
int surfaceFlags;
|
||||
int contentFlags;
|
||||
} dshader_t;
|
||||
|
||||
// planes x^1 is allways the opposite of plane x
|
||||
|
||||
typedef struct {
|
||||
float normal[3];
|
||||
float dist;
|
||||
} dplane_t;
|
||||
|
||||
typedef struct {
|
||||
int planeNum;
|
||||
int children[2]; // negative numbers are -(leafs+1), not nodes
|
||||
int mins[3]; // for frustom culling
|
||||
int maxs[3];
|
||||
} dnode_t;
|
||||
|
||||
typedef struct {
|
||||
int cluster; // -1 = opaque cluster (do I still store these?)
|
||||
int area;
|
||||
|
||||
int mins[3]; // for frustum culling
|
||||
int maxs[3];
|
||||
|
||||
int firstLeafSurface;
|
||||
int numLeafSurfaces;
|
||||
|
||||
int firstLeafBrush;
|
||||
int numLeafBrushes;
|
||||
} dleaf_t;
|
||||
|
||||
typedef struct {
|
||||
int planeNum; // positive plane side faces out of the leaf
|
||||
int shaderNum;
|
||||
} dbrushside_t;
|
||||
|
||||
typedef struct {
|
||||
int firstSide;
|
||||
int numSides;
|
||||
int shaderNum; // the shader that determines the contents flags
|
||||
} dbrush_t;
|
||||
|
||||
typedef struct {
|
||||
char shader[MAX_QPATH];
|
||||
int brushNum;
|
||||
int visibleSide; // the brush side that ray tests need to clip against (-1 == none)
|
||||
} dfog_t;
|
||||
|
||||
typedef struct {
|
||||
vec3_t xyz;
|
||||
float st[2];
|
||||
float lightmap[2];
|
||||
vec3_t normal;
|
||||
byte color[4];
|
||||
} drawVert_t;
|
||||
|
||||
typedef enum {
|
||||
MST_BAD,
|
||||
MST_PLANAR,
|
||||
MST_PATCH,
|
||||
MST_TRIANGLE_SOUP,
|
||||
MST_FLARE
|
||||
} mapSurfaceType_t;
|
||||
|
||||
typedef struct {
|
||||
int shaderNum;
|
||||
int fogNum;
|
||||
int surfaceType;
|
||||
|
||||
int firstVert;
|
||||
int numVerts;
|
||||
|
||||
int firstIndex;
|
||||
int numIndexes;
|
||||
|
||||
int lightmapNum;
|
||||
int lightmapX, lightmapY;
|
||||
int lightmapWidth, lightmapHeight;
|
||||
|
||||
vec3_t lightmapOrigin;
|
||||
vec3_t lightmapVecs[3]; // for patches, [0] and [1] are lodbounds
|
||||
|
||||
int patchWidth;
|
||||
int patchHeight;
|
||||
} dsurface_t;
|
||||
|
||||
|
||||
#endif
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
#ifndef __QFILES_H__
|
||||
#define __QFILES_H__
|
||||
|
||||
//
|
||||
// qfiles.h: quake file formats
|
||||
// This file must be identical in the quake and utils directories
|
||||
//
|
||||
|
||||
// surface geometry should not exceed these limits
|
||||
#define SHADER_MAX_VERTEXES 1000
|
||||
#define SHADER_MAX_INDEXES (6*SHADER_MAX_VERTEXES)
|
||||
|
||||
|
||||
// the maximum size of game relative pathnames
|
||||
#define MAX_QPATH 64
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
QVM files
|
||||
|
||||
========================================================================
|
||||
*/
|
||||
|
||||
#define VM_MAGIC 0x12721444
|
||||
typedef struct {
|
||||
int vmMagic;
|
||||
|
||||
int instructionCount;
|
||||
|
||||
int codeOffset;
|
||||
int codeLength;
|
||||
|
||||
int dataOffset;
|
||||
int dataLength;
|
||||
int litLength; // ( dataLength - litLength ) should be byteswapped on load
|
||||
int bssLength; // zero filled memory appended to datalength
|
||||
} vmHeader_t;
|
||||
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
PCX files are used for 8 bit images
|
||||
|
||||
========================================================================
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char manufacturer;
|
||||
char version;
|
||||
char encoding;
|
||||
char bits_per_pixel;
|
||||
unsigned short xmin,ymin,xmax,ymax;
|
||||
unsigned short hres,vres;
|
||||
unsigned char palette[48];
|
||||
char reserved;
|
||||
char color_planes;
|
||||
unsigned short bytes_per_line;
|
||||
unsigned short palette_type;
|
||||
char filler[58];
|
||||
unsigned char data; // unbounded
|
||||
} pcx_t;
|
||||
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
TGA files are used for 24/32 bit images
|
||||
|
||||
========================================================================
|
||||
*/
|
||||
|
||||
typedef struct _TargaHeader {
|
||||
unsigned char id_length, colormap_type, image_type;
|
||||
unsigned short colormap_index, colormap_length;
|
||||
unsigned char colormap_size;
|
||||
unsigned short x_origin, y_origin, width, height;
|
||||
unsigned char pixel_size, attributes;
|
||||
} TargaHeader;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
.MD3 triangle model file format
|
||||
|
||||
========================================================================
|
||||
*/
|
||||
|
||||
#define MD3_IDENT (('3'<<24)+('P'<<16)+('D'<<8)+'I')
|
||||
#define MD3_VERSION 15
|
||||
|
||||
// limits
|
||||
#define MD3_MAX_LODS 3
|
||||
#define MD3_MAX_TRIANGLES 8192 // per surface
|
||||
#define MD3_MAX_VERTS 4096 // per surface
|
||||
#define MD3_MAX_SHADERS 256 // per surface
|
||||
#define MD3_MAX_FRAMES 1024 // per model
|
||||
#define MD3_MAX_SURFACES 32 // per model
|
||||
#define MD3_MAX_TAGS 16 // per frame
|
||||
|
||||
// vertex scales
|
||||
#define MD3_XYZ_SCALE (1.0/64)
|
||||
|
||||
typedef struct md3Frame_s {
|
||||
vec3_t bounds[2];
|
||||
vec3_t localOrigin;
|
||||
float radius;
|
||||
char name[16];
|
||||
} md3Frame_t;
|
||||
|
||||
typedef struct md3Tag_s {
|
||||
char name[MAX_QPATH]; // tag name
|
||||
vec3_t origin;
|
||||
vec3_t axis[3];
|
||||
} md3Tag_t;
|
||||
|
||||
/*
|
||||
** md3Surface_t
|
||||
**
|
||||
** CHUNK SIZE
|
||||
** header sizeof( md3Surface_t )
|
||||
** shaders sizeof( md3Shader_t ) * numShaders
|
||||
** triangles[0] sizeof( md3Triangle_t ) * numTriangles
|
||||
** st sizeof( md3St_t ) * numVerts
|
||||
** XyzNormals sizeof( md3XyzNormal_t ) * numVerts * numFrames
|
||||
*/
|
||||
typedef struct {
|
||||
int ident; //
|
||||
|
||||
char name[MAX_QPATH]; // polyset name
|
||||
|
||||
int flags;
|
||||
int numFrames; // all surfaces in a model should have the same
|
||||
|
||||
int numShaders; // all surfaces in a model should have the same
|
||||
int numVerts;
|
||||
|
||||
int numTriangles;
|
||||
int ofsTriangles;
|
||||
|
||||
int ofsShaders; // offset from start of md3Surface_t
|
||||
int ofsSt; // texture coords are common for all frames
|
||||
int ofsXyzNormals; // numVerts * numFrames
|
||||
|
||||
int ofsEnd; // next surface follows
|
||||
} md3Surface_t;
|
||||
|
||||
typedef struct {
|
||||
char name[MAX_QPATH];
|
||||
int shaderIndex; // for in-game use
|
||||
} md3Shader_t;
|
||||
|
||||
typedef struct {
|
||||
int indexes[3];
|
||||
} md3Triangle_t;
|
||||
|
||||
typedef struct {
|
||||
float st[2];
|
||||
} md3St_t;
|
||||
|
||||
typedef struct {
|
||||
short xyz[3];
|
||||
short normal;
|
||||
} md3XyzNormal_t;
|
||||
|
||||
typedef struct {
|
||||
int ident;
|
||||
int version;
|
||||
|
||||
char name[MAX_QPATH]; // model name
|
||||
|
||||
int flags;
|
||||
|
||||
int numFrames;
|
||||
int numTags;
|
||||
int numSurfaces;
|
||||
|
||||
int numSkins;
|
||||
|
||||
int ofsFrames; // offset for first frame
|
||||
int ofsTags; // numFrames * numTags
|
||||
int ofsSurfaces; // first surface, others follow
|
||||
|
||||
int ofsEnd; // end of file
|
||||
} md3Header_t;
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
MD4 file format
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define MD4_IDENT (('4'<<24)+('P'<<16)+('D'<<8)+'I')
|
||||
#define MD4_VERSION 1
|
||||
#define MD4_MAX_BONES 128
|
||||
|
||||
typedef struct {
|
||||
int boneIndex; // these are indexes into the boneReferences,
|
||||
float boneWeight; // not the global per-frame bone list
|
||||
vec3_t offset;
|
||||
} md4Weight_t;
|
||||
|
||||
typedef struct {
|
||||
vec3_t normal;
|
||||
vec2_t texCoords;
|
||||
int numWeights;
|
||||
md4Weight_t weights[1]; // variable sized
|
||||
} md4Vertex_t;
|
||||
|
||||
typedef struct {
|
||||
int indexes[3];
|
||||
} md4Triangle_t;
|
||||
|
||||
typedef struct {
|
||||
int ident;
|
||||
|
||||
char name[MAX_QPATH]; // polyset name
|
||||
char shader[MAX_QPATH];
|
||||
int shaderIndex; // for in-game use
|
||||
|
||||
int ofsHeader; // this will be a negative number
|
||||
|
||||
int numVerts;
|
||||
int ofsVerts;
|
||||
|
||||
int numTriangles;
|
||||
int ofsTriangles;
|
||||
|
||||
// Bone references are a set of ints representing all the bones
|
||||
// present in any vertex weights for this surface. This is
|
||||
// needed because a model may have surfaces that need to be
|
||||
// drawn at different sort times, and we don't want to have
|
||||
// to re-interpolate all the bones for each surface.
|
||||
int numBoneReferences;
|
||||
int ofsBoneReferences;
|
||||
|
||||
int ofsEnd; // next surface follows
|
||||
} md4Surface_t;
|
||||
|
||||
typedef struct {
|
||||
float matrix[3][4];
|
||||
} md4Bone_t;
|
||||
|
||||
typedef struct {
|
||||
vec3_t bounds[2]; // bounds of all surfaces of all LOD's for this frame
|
||||
vec3_t localOrigin; // midpoint of bounds, used for sphere cull
|
||||
float radius; // dist from localOrigin to corner
|
||||
md4Bone_t bones[1]; // [numBones]
|
||||
} md4Frame_t;
|
||||
|
||||
typedef struct {
|
||||
int numSurfaces;
|
||||
int ofsSurfaces; // first surface, others follow
|
||||
int ofsEnd; // next lod follows
|
||||
} md4LOD_t;
|
||||
|
||||
typedef struct {
|
||||
int ident;
|
||||
int version;
|
||||
|
||||
char name[MAX_QPATH]; // model name
|
||||
|
||||
// frames and bones are shared by all levels of detail
|
||||
int numFrames;
|
||||
int numBones;
|
||||
int ofsBoneNames; // char name[ MAX_QPATH ]
|
||||
int ofsFrames; // md4Frame_t[numFrames]
|
||||
|
||||
// each level of detail has completely separate sets of surfaces
|
||||
int numLODs;
|
||||
int ofsLODs;
|
||||
|
||||
int ofsEnd; // end of file
|
||||
} md4Header_t;
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
.BSP file format
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
#define BSP_IDENT (('P'<<24)+('S'<<16)+('B'<<8)+'I')
|
||||
// little-endian "IBSP"
|
||||
|
||||
#define BSP_VERSION 46
|
||||
|
||||
|
||||
// there shouldn't be any problem with increasing these values at the
|
||||
// expense of more memory allocation in the utilities
|
||||
#define MAX_MAP_MODELS 0x400
|
||||
#define MAX_MAP_BRUSHES 0x8000
|
||||
#define MAX_MAP_ENTITIES 0x800
|
||||
#define MAX_MAP_ENTSTRING 0x40000
|
||||
#define MAX_MAP_SHADERS 0x400
|
||||
|
||||
#define MAX_MAP_AREAS 0x100 // MAX_MAP_AREA_BYTES in q_shared must match!
|
||||
#define MAX_MAP_FOGS 0x100
|
||||
#define MAX_MAP_PLANES 0x20000
|
||||
#define MAX_MAP_NODES 0x20000
|
||||
#define MAX_MAP_BRUSHSIDES 0x20000
|
||||
#define MAX_MAP_LEAFS 0x20000
|
||||
#define MAX_MAP_LEAFFACES 0x20000
|
||||
#define MAX_MAP_LEAFBRUSHES 0x40000
|
||||
#define MAX_MAP_PORTALS 0x20000
|
||||
#define MAX_MAP_LIGHTING 0x800000
|
||||
#define MAX_MAP_LIGHTGRID 0x800000
|
||||
#define MAX_MAP_VISIBILITY 0x200000
|
||||
|
||||
#define MAX_MAP_DRAW_SURFS 0x20000
|
||||
#define MAX_MAP_DRAW_VERTS 0x80000
|
||||
#define MAX_MAP_DRAW_INDEXES 0x80000
|
||||
|
||||
|
||||
// key / value pair sizes in the entities lump
|
||||
#define MAX_KEY 32
|
||||
#define MAX_VALUE 1024
|
||||
|
||||
// the editor uses these predefined yaw angles to orient entities up or down
|
||||
#define ANGLE_UP -1
|
||||
#define ANGLE_DOWN -2
|
||||
|
||||
#define LIGHTMAP_WIDTH 128
|
||||
#define LIGHTMAP_HEIGHT 128
|
||||
|
||||
#define MAX_WORLD_COORD ( 128*1024 )
|
||||
#define MIN_WORLD_COORD ( -128*1024 )
|
||||
#define WORLD_SIZE ( MAX_WORLD_COORD - MIN_WORLD_COORD )
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
typedef struct {
|
||||
int fileofs, filelen;
|
||||
} lump_t;
|
||||
|
||||
#define LUMP_ENTITIES 0
|
||||
#define LUMP_SHADERS 1
|
||||
#define LUMP_PLANES 2
|
||||
#define LUMP_NODES 3
|
||||
#define LUMP_LEAFS 4
|
||||
#define LUMP_LEAFSURFACES 5
|
||||
#define LUMP_LEAFBRUSHES 6
|
||||
#define LUMP_MODELS 7
|
||||
#define LUMP_BRUSHES 8
|
||||
#define LUMP_BRUSHSIDES 9
|
||||
#define LUMP_DRAWVERTS 10
|
||||
#define LUMP_DRAWINDEXES 11
|
||||
#define LUMP_FOGS 12
|
||||
#define LUMP_SURFACES 13
|
||||
#define LUMP_LIGHTMAPS 14
|
||||
#define LUMP_LIGHTGRID 15
|
||||
#define LUMP_VISIBILITY 16
|
||||
#define HEADER_LUMPS 17
|
||||
|
||||
typedef struct {
|
||||
int ident;
|
||||
int version;
|
||||
|
||||
lump_t lumps[HEADER_LUMPS];
|
||||
} dheader_t;
|
||||
|
||||
typedef struct {
|
||||
float mins[3], maxs[3];
|
||||
int firstSurface, numSurfaces;
|
||||
int firstBrush, numBrushes;
|
||||
} dmodel_t;
|
||||
|
||||
typedef struct {
|
||||
char shader[MAX_QPATH];
|
||||
int surfaceFlags;
|
||||
int contentFlags;
|
||||
} dshader_t;
|
||||
|
||||
// planes x^1 is allways the opposite of plane x
|
||||
|
||||
typedef struct {
|
||||
float normal[3];
|
||||
float dist;
|
||||
} dplane_t;
|
||||
|
||||
typedef struct {
|
||||
int planeNum;
|
||||
int children[2]; // negative numbers are -(leafs+1), not nodes
|
||||
int mins[3]; // for frustom culling
|
||||
int maxs[3];
|
||||
} dnode_t;
|
||||
|
||||
typedef struct {
|
||||
int cluster; // -1 = opaque cluster (do I still store these?)
|
||||
int area;
|
||||
|
||||
int mins[3]; // for frustum culling
|
||||
int maxs[3];
|
||||
|
||||
int firstLeafSurface;
|
||||
int numLeafSurfaces;
|
||||
|
||||
int firstLeafBrush;
|
||||
int numLeafBrushes;
|
||||
} dleaf_t;
|
||||
|
||||
typedef struct {
|
||||
int planeNum; // positive plane side faces out of the leaf
|
||||
int shaderNum;
|
||||
} dbrushside_t;
|
||||
|
||||
typedef struct {
|
||||
int firstSide;
|
||||
int numSides;
|
||||
int shaderNum; // the shader that determines the contents flags
|
||||
} dbrush_t;
|
||||
|
||||
typedef struct {
|
||||
char shader[MAX_QPATH];
|
||||
int brushNum;
|
||||
int visibleSide; // the brush side that ray tests need to clip against (-1 == none)
|
||||
} dfog_t;
|
||||
|
||||
typedef struct {
|
||||
vec3_t xyz;
|
||||
float st[2];
|
||||
float lightmap[2];
|
||||
vec3_t normal;
|
||||
byte color[4];
|
||||
} drawVert_t;
|
||||
|
||||
typedef enum {
|
||||
MST_BAD,
|
||||
MST_PLANAR,
|
||||
MST_PATCH,
|
||||
MST_TRIANGLE_SOUP,
|
||||
MST_FLARE
|
||||
} mapSurfaceType_t;
|
||||
|
||||
typedef struct {
|
||||
int shaderNum;
|
||||
int fogNum;
|
||||
int surfaceType;
|
||||
|
||||
int firstVert;
|
||||
int numVerts;
|
||||
|
||||
int firstIndex;
|
||||
int numIndexes;
|
||||
|
||||
int lightmapNum;
|
||||
int lightmapX, lightmapY;
|
||||
int lightmapWidth, lightmapHeight;
|
||||
|
||||
vec3_t lightmapOrigin;
|
||||
vec3_t lightmapVecs[3]; // for patches, [0] and [1] are lodbounds
|
||||
|
||||
int patchWidth;
|
||||
int patchHeight;
|
||||
} dsurface_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
|
8598
code/qcommon/unzip.c
Normal file → Executable file
8598
code/qcommon/unzip.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
672
code/qcommon/unzip.h
Normal file → Executable file
672
code/qcommon/unzip.h
Normal file → Executable file
|
@ -1,336 +1,336 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
|
||||
/* like the STRICT of WIN32, we define a pointer that cannot be converted
|
||||
from (void*) without cast */
|
||||
typedef struct TagunzFile__ { int unused; } unzFile__;
|
||||
typedef unzFile__ *unzFile;
|
||||
#else
|
||||
typedef void* unzFile;
|
||||
#endif
|
||||
|
||||
/* tm_unz contain date/time info */
|
||||
typedef struct tm_unz_s
|
||||
{
|
||||
unsigned int tm_sec; /* seconds after the minute - [0,59] */
|
||||
unsigned int tm_min; /* minutes after the hour - [0,59] */
|
||||
unsigned int tm_hour; /* hours since midnight - [0,23] */
|
||||
unsigned int tm_mday; /* day of the month - [1,31] */
|
||||
unsigned int tm_mon; /* months since January - [0,11] */
|
||||
unsigned int tm_year; /* years - [1980..2044] */
|
||||
} tm_unz;
|
||||
|
||||
/* unz_global_info structure contain global data about the ZIPfile
|
||||
These data comes from the end of central dir */
|
||||
typedef struct unz_global_info_s
|
||||
{
|
||||
unsigned long number_entry; /* total number of entries in the central dir on this disk */
|
||||
unsigned long size_comment; /* size of the global comment of the zipfile */
|
||||
} unz_global_info;
|
||||
|
||||
|
||||
/* unz_file_info contain information about a file in the zipfile */
|
||||
typedef struct unz_file_info_s
|
||||
{
|
||||
unsigned long version; /* version made by 2 unsigned chars */
|
||||
unsigned long version_needed; /* version needed to extract 2 unsigned chars */
|
||||
unsigned long flag; /* general purpose bit flag 2 unsigned chars */
|
||||
unsigned long compression_method; /* compression method 2 unsigned chars */
|
||||
unsigned long dosDate; /* last mod file date in Dos fmt 4 unsigned chars */
|
||||
unsigned long crc; /* crc-32 4 unsigned chars */
|
||||
unsigned long compressed_size; /* compressed size 4 unsigned chars */
|
||||
unsigned long uncompressed_size; /* uncompressed size 4 unsigned chars */
|
||||
unsigned long size_filename; /* filename length 2 unsigned chars */
|
||||
unsigned long size_file_extra; /* extra field length 2 unsigned chars */
|
||||
unsigned long size_file_comment; /* file comment length 2 unsigned chars */
|
||||
|
||||
unsigned long disk_num_start; /* disk number start 2 unsigned chars */
|
||||
unsigned long internal_fa; /* internal file attributes 2 unsigned chars */
|
||||
unsigned long external_fa; /* external file attributes 4 unsigned chars */
|
||||
|
||||
tm_unz tmu_date;
|
||||
} unz_file_info;
|
||||
|
||||
/* unz_file_info_interntal contain internal info about a file in zipfile*/
|
||||
typedef struct unz_file_info_internal_s
|
||||
{
|
||||
unsigned long offset_curfile;/* relative offset of static header 4 unsigned chars */
|
||||
} unz_file_info_internal;
|
||||
|
||||
typedef void* (*alloc_func) (void* opaque, unsigned int items, unsigned int size);
|
||||
typedef void (*free_func) (void* opaque, void* address);
|
||||
|
||||
struct internal_state;
|
||||
|
||||
typedef struct z_stream_s {
|
||||
unsigned char *next_in; /* next input unsigned char */
|
||||
unsigned int avail_in; /* number of unsigned chars available at next_in */
|
||||
unsigned long total_in; /* total nb of input unsigned chars read so */
|
||||
|
||||
unsigned char *next_out; /* next output unsigned char should be put there */
|
||||
unsigned int avail_out; /* remaining free space at next_out */
|
||||
unsigned long total_out; /* total nb of unsigned chars output so */
|
||||
|
||||
char *msg; /* last error message, NULL if no error */
|
||||
struct internal_state *state; /* not visible by applications */
|
||||
|
||||
alloc_func zalloc; /* used to allocate the internal state */
|
||||
free_func zfree; /* used to free the internal state */
|
||||
unsigned char* opaque; /* private data object passed to zalloc and zfree */
|
||||
|
||||
int data_type; /* best guess about the data type: ascii or binary */
|
||||
unsigned long adler; /* adler32 value of the uncompressed data */
|
||||
unsigned long reserved; /* reserved for future use */
|
||||
} z_stream;
|
||||
|
||||
typedef z_stream *z_streamp;
|
||||
|
||||
|
||||
/* file_in_zip_read_info_s contain internal information about a file in zipfile,
|
||||
when reading and decompress it */
|
||||
typedef struct
|
||||
{
|
||||
char *read_buffer; /* internal buffer for compressed data */
|
||||
z_stream stream; /* zLib stream structure for inflate */
|
||||
|
||||
unsigned long pos_in_zipfile; /* position in unsigned char on the zipfile, for fseek*/
|
||||
unsigned long stream_initialised; /* flag set if stream structure is initialised*/
|
||||
|
||||
unsigned long offset_local_extrafield;/* offset of the static extra field */
|
||||
unsigned int size_local_extrafield;/* size of the static extra field */
|
||||
unsigned long pos_local_extrafield; /* position in the static extra field in read*/
|
||||
|
||||
unsigned long crc32; /* crc32 of all data uncompressed */
|
||||
unsigned long crc32_wait; /* crc32 we must obtain after decompress all */
|
||||
unsigned long rest_read_compressed; /* number of unsigned char to be decompressed */
|
||||
unsigned long rest_read_uncompressed;/*number of unsigned char to be obtained after decomp*/
|
||||
FILE* file; /* io structore of the zipfile */
|
||||
unsigned long compression_method; /* compression method (0==store) */
|
||||
unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
|
||||
} file_in_zip_read_info_s;
|
||||
|
||||
|
||||
/* unz_s contain internal information about the zipfile
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
FILE* file; /* io structore of the zipfile */
|
||||
unz_global_info gi; /* public global information */
|
||||
unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
|
||||
unsigned long num_file; /* number of the current file in the zipfile*/
|
||||
unsigned long pos_in_central_dir; /* pos of the current file in the central dir*/
|
||||
unsigned long current_file_ok; /* flag about the usability of the current file*/
|
||||
unsigned long central_pos; /* position of the beginning of the central dir*/
|
||||
|
||||
unsigned long size_central_dir; /* size of the central directory */
|
||||
unsigned long offset_central_dir; /* offset of start of central directory with
|
||||
respect to the starting disk number */
|
||||
|
||||
unz_file_info cur_file_info; /* public info about the current file in zip*/
|
||||
unz_file_info_internal cur_file_info_internal; /* private info about it*/
|
||||
file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
|
||||
file if we are decompressing it */
|
||||
unsigned char* tmpFile;
|
||||
int tmpPos,tmpSize;
|
||||
} unz_s;
|
||||
|
||||
#define UNZ_OK (0)
|
||||
#define UNZ_END_OF_LIST_OF_FILE (-100)
|
||||
#define UNZ_ERRNO (Z_ERRNO)
|
||||
#define UNZ_EOF (0)
|
||||
#define UNZ_PARAMERROR (-102)
|
||||
#define UNZ_BADZIPFILE (-103)
|
||||
#define UNZ_INTERNALERROR (-104)
|
||||
#define UNZ_CRCERROR (-105)
|
||||
|
||||
#define UNZ_CASESENSITIVE 1
|
||||
#define UNZ_NOTCASESENSITIVE 2
|
||||
#define UNZ_OSDEFAULTCASE 0
|
||||
|
||||
extern int unzStringFileNameCompare (const char* fileName1, const char* fileName2, int iCaseSensitivity);
|
||||
|
||||
/*
|
||||
Compare two filename (fileName1,fileName2).
|
||||
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
|
||||
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
|
||||
or strcasecmp)
|
||||
If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
|
||||
(like 1 on Unix, 2 on Windows)
|
||||
*/
|
||||
|
||||
extern unzFile unzOpen (const char *path);
|
||||
extern unzFile unzReOpen (const char* path, unzFile file);
|
||||
|
||||
/*
|
||||
Open a Zip file. path contain the full pathname (by example,
|
||||
on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
|
||||
"zlib/zlib111.zip".
|
||||
If the zipfile cannot be opened (file don't exist or in not valid), the
|
||||
return value is NULL.
|
||||
Else, the return value is a unzFile Handle, usable with other function
|
||||
of this unzip package.
|
||||
*/
|
||||
|
||||
extern int unzClose (unzFile file);
|
||||
|
||||
/*
|
||||
Close a ZipFile opened with unzipOpen.
|
||||
If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
|
||||
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
|
||||
return UNZ_OK if there is no problem. */
|
||||
|
||||
extern int unzGetGlobalInfo (unzFile file, unz_global_info *pglobal_info);
|
||||
|
||||
/*
|
||||
Write info about the ZipFile in the *pglobal_info structure.
|
||||
No preparation of the structure is needed
|
||||
return UNZ_OK if there is no problem. */
|
||||
|
||||
|
||||
extern int unzGetGlobalComment (unzFile file, char *szComment, unsigned long uSizeBuf);
|
||||
|
||||
/*
|
||||
Get the global comment string of the ZipFile, in the szComment buffer.
|
||||
uSizeBuf is the size of the szComment buffer.
|
||||
return the number of unsigned char copied or an error code <0
|
||||
*/
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* Unzip package allow you browse the directory of the zipfile */
|
||||
|
||||
extern int unzGoToFirstFile (unzFile file);
|
||||
|
||||
/*
|
||||
Set the current file of the zipfile to the first file.
|
||||
return UNZ_OK if there is no problem
|
||||
*/
|
||||
|
||||
extern int unzGoToNextFile (unzFile file);
|
||||
|
||||
/*
|
||||
Set the current file of the zipfile to the next file.
|
||||
return UNZ_OK if there is no problem
|
||||
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
|
||||
*/
|
||||
|
||||
extern int unzGetCurrentFileInfoPosition (unzFile file, unsigned long *pos );
|
||||
|
||||
/*
|
||||
Get the position of the info of the current file in the zip.
|
||||
return UNZ_OK if there is no problem
|
||||
*/
|
||||
|
||||
extern int unzSetCurrentFileInfoPosition (unzFile file, unsigned long pos );
|
||||
|
||||
/*
|
||||
Set the position of the info of the current file in the zip.
|
||||
return UNZ_OK if there is no problem
|
||||
*/
|
||||
|
||||
extern int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity);
|
||||
|
||||
/*
|
||||
Try locate the file szFileName in the zipfile.
|
||||
For the iCaseSensitivity signification, see unzStringFileNameCompare
|
||||
|
||||
return value :
|
||||
UNZ_OK if the file is found. It becomes the current file.
|
||||
UNZ_END_OF_LIST_OF_FILE if the file is not found
|
||||
*/
|
||||
|
||||
|
||||
extern int unzGetCurrentFileInfo (unzFile file, unz_file_info *pfile_info, char *szFileName, unsigned long fileNameBufferSize, void *extraField, unsigned long extraFieldBufferSize, char *szComment, unsigned long commentBufferSize);
|
||||
|
||||
/*
|
||||
Get Info about the current file
|
||||
if pfile_info!=NULL, the *pfile_info structure will contain somes info about
|
||||
the current file
|
||||
if szFileName!=NULL, the filemane string will be copied in szFileName
|
||||
(fileNameBufferSize is the size of the buffer)
|
||||
if extraField!=NULL, the extra field information will be copied in extraField
|
||||
(extraFieldBufferSize is the size of the buffer).
|
||||
This is the Central-header version of the extra field
|
||||
if szComment!=NULL, the comment string of the file will be copied in szComment
|
||||
(commentBufferSize is the size of the buffer)
|
||||
*/
|
||||
|
||||
/***************************************************************************/
|
||||
/* for reading the content of the current zipfile, you can open it, read data
|
||||
from it, and close it (you can close it before reading all the file)
|
||||
*/
|
||||
|
||||
extern int unzOpenCurrentFile (unzFile file);
|
||||
|
||||
/*
|
||||
Open for reading data the current file in the zipfile.
|
||||
If there is no error, the return value is UNZ_OK.
|
||||
*/
|
||||
|
||||
extern int unzCloseCurrentFile (unzFile file);
|
||||
|
||||
/*
|
||||
Close the file in zip opened with unzOpenCurrentFile
|
||||
Return UNZ_CRCERROR if all the file was read but the CRC is not good
|
||||
*/
|
||||
|
||||
|
||||
extern int unzReadCurrentFile (unzFile file, void* buf, unsigned len);
|
||||
|
||||
/*
|
||||
Read unsigned chars from the current file (opened by unzOpenCurrentFile)
|
||||
buf contain buffer where data must be copied
|
||||
len the size of buf.
|
||||
|
||||
return the number of unsigned char copied if somes unsigned chars are copied
|
||||
return 0 if the end of file was reached
|
||||
return <0 with error code if there is an error
|
||||
(UNZ_ERRNO for IO error, or zLib error for uncompress error)
|
||||
*/
|
||||
|
||||
extern long unztell(unzFile file);
|
||||
|
||||
/*
|
||||
Give the current position in uncompressed data
|
||||
*/
|
||||
|
||||
extern int unzeof (unzFile file);
|
||||
|
||||
/*
|
||||
return 1 if the end of file was reached, 0 elsewhere
|
||||
*/
|
||||
|
||||
extern int unzGetLocalExtrafield (unzFile file, void* buf, unsigned len);
|
||||
|
||||
/*
|
||||
Read extra field from the current file (opened by unzOpenCurrentFile)
|
||||
This is the local-header version of the extra field (sometimes, there is
|
||||
more info in the local-header version than in the central-header)
|
||||
|
||||
if buf==NULL, it return the size of the local extra field
|
||||
|
||||
if buf!=NULL, len is the size of the buffer, the extra header is copied in
|
||||
buf.
|
||||
the return value is the number of unsigned chars copied in buf, or (if <0)
|
||||
the error code
|
||||
*/
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
|
||||
/* like the STRICT of WIN32, we define a pointer that cannot be converted
|
||||
from (void*) without cast */
|
||||
typedef struct TagunzFile__ { int unused; } unzFile__;
|
||||
typedef unzFile__ *unzFile;
|
||||
#else
|
||||
typedef void* unzFile;
|
||||
#endif
|
||||
|
||||
/* tm_unz contain date/time info */
|
||||
typedef struct tm_unz_s
|
||||
{
|
||||
unsigned int tm_sec; /* seconds after the minute - [0,59] */
|
||||
unsigned int tm_min; /* minutes after the hour - [0,59] */
|
||||
unsigned int tm_hour; /* hours since midnight - [0,23] */
|
||||
unsigned int tm_mday; /* day of the month - [1,31] */
|
||||
unsigned int tm_mon; /* months since January - [0,11] */
|
||||
unsigned int tm_year; /* years - [1980..2044] */
|
||||
} tm_unz;
|
||||
|
||||
/* unz_global_info structure contain global data about the ZIPfile
|
||||
These data comes from the end of central dir */
|
||||
typedef struct unz_global_info_s
|
||||
{
|
||||
unsigned long number_entry; /* total number of entries in the central dir on this disk */
|
||||
unsigned long size_comment; /* size of the global comment of the zipfile */
|
||||
} unz_global_info;
|
||||
|
||||
|
||||
/* unz_file_info contain information about a file in the zipfile */
|
||||
typedef struct unz_file_info_s
|
||||
{
|
||||
unsigned long version; /* version made by 2 unsigned chars */
|
||||
unsigned long version_needed; /* version needed to extract 2 unsigned chars */
|
||||
unsigned long flag; /* general purpose bit flag 2 unsigned chars */
|
||||
unsigned long compression_method; /* compression method 2 unsigned chars */
|
||||
unsigned long dosDate; /* last mod file date in Dos fmt 4 unsigned chars */
|
||||
unsigned long crc; /* crc-32 4 unsigned chars */
|
||||
unsigned long compressed_size; /* compressed size 4 unsigned chars */
|
||||
unsigned long uncompressed_size; /* uncompressed size 4 unsigned chars */
|
||||
unsigned long size_filename; /* filename length 2 unsigned chars */
|
||||
unsigned long size_file_extra; /* extra field length 2 unsigned chars */
|
||||
unsigned long size_file_comment; /* file comment length 2 unsigned chars */
|
||||
|
||||
unsigned long disk_num_start; /* disk number start 2 unsigned chars */
|
||||
unsigned long internal_fa; /* internal file attributes 2 unsigned chars */
|
||||
unsigned long external_fa; /* external file attributes 4 unsigned chars */
|
||||
|
||||
tm_unz tmu_date;
|
||||
} unz_file_info;
|
||||
|
||||
/* unz_file_info_interntal contain internal info about a file in zipfile*/
|
||||
typedef struct unz_file_info_internal_s
|
||||
{
|
||||
unsigned long offset_curfile;/* relative offset of static header 4 unsigned chars */
|
||||
} unz_file_info_internal;
|
||||
|
||||
typedef void* (*alloc_func) (void* opaque, unsigned int items, unsigned int size);
|
||||
typedef void (*free_func) (void* opaque, void* address);
|
||||
|
||||
struct internal_state;
|
||||
|
||||
typedef struct z_stream_s {
|
||||
unsigned char *next_in; /* next input unsigned char */
|
||||
unsigned int avail_in; /* number of unsigned chars available at next_in */
|
||||
unsigned long total_in; /* total nb of input unsigned chars read so */
|
||||
|
||||
unsigned char *next_out; /* next output unsigned char should be put there */
|
||||
unsigned int avail_out; /* remaining free space at next_out */
|
||||
unsigned long total_out; /* total nb of unsigned chars output so */
|
||||
|
||||
char *msg; /* last error message, NULL if no error */
|
||||
struct internal_state *state; /* not visible by applications */
|
||||
|
||||
alloc_func zalloc; /* used to allocate the internal state */
|
||||
free_func zfree; /* used to free the internal state */
|
||||
unsigned char* opaque; /* private data object passed to zalloc and zfree */
|
||||
|
||||
int data_type; /* best guess about the data type: ascii or binary */
|
||||
unsigned long adler; /* adler32 value of the uncompressed data */
|
||||
unsigned long reserved; /* reserved for future use */
|
||||
} z_stream;
|
||||
|
||||
typedef z_stream *z_streamp;
|
||||
|
||||
|
||||
/* file_in_zip_read_info_s contain internal information about a file in zipfile,
|
||||
when reading and decompress it */
|
||||
typedef struct
|
||||
{
|
||||
char *read_buffer; /* internal buffer for compressed data */
|
||||
z_stream stream; /* zLib stream structure for inflate */
|
||||
|
||||
unsigned long pos_in_zipfile; /* position in unsigned char on the zipfile, for fseek*/
|
||||
unsigned long stream_initialised; /* flag set if stream structure is initialised*/
|
||||
|
||||
unsigned long offset_local_extrafield;/* offset of the static extra field */
|
||||
unsigned int size_local_extrafield;/* size of the static extra field */
|
||||
unsigned long pos_local_extrafield; /* position in the static extra field in read*/
|
||||
|
||||
unsigned long crc32; /* crc32 of all data uncompressed */
|
||||
unsigned long crc32_wait; /* crc32 we must obtain after decompress all */
|
||||
unsigned long rest_read_compressed; /* number of unsigned char to be decompressed */
|
||||
unsigned long rest_read_uncompressed;/*number of unsigned char to be obtained after decomp*/
|
||||
FILE* file; /* io structore of the zipfile */
|
||||
unsigned long compression_method; /* compression method (0==store) */
|
||||
unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
|
||||
} file_in_zip_read_info_s;
|
||||
|
||||
|
||||
/* unz_s contain internal information about the zipfile
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
FILE* file; /* io structore of the zipfile */
|
||||
unz_global_info gi; /* public global information */
|
||||
unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
|
||||
unsigned long num_file; /* number of the current file in the zipfile*/
|
||||
unsigned long pos_in_central_dir; /* pos of the current file in the central dir*/
|
||||
unsigned long current_file_ok; /* flag about the usability of the current file*/
|
||||
unsigned long central_pos; /* position of the beginning of the central dir*/
|
||||
|
||||
unsigned long size_central_dir; /* size of the central directory */
|
||||
unsigned long offset_central_dir; /* offset of start of central directory with
|
||||
respect to the starting disk number */
|
||||
|
||||
unz_file_info cur_file_info; /* public info about the current file in zip*/
|
||||
unz_file_info_internal cur_file_info_internal; /* private info about it*/
|
||||
file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
|
||||
file if we are decompressing it */
|
||||
unsigned char* tmpFile;
|
||||
int tmpPos,tmpSize;
|
||||
} unz_s;
|
||||
|
||||
#define UNZ_OK (0)
|
||||
#define UNZ_END_OF_LIST_OF_FILE (-100)
|
||||
#define UNZ_ERRNO (Z_ERRNO)
|
||||
#define UNZ_EOF (0)
|
||||
#define UNZ_PARAMERROR (-102)
|
||||
#define UNZ_BADZIPFILE (-103)
|
||||
#define UNZ_INTERNALERROR (-104)
|
||||
#define UNZ_CRCERROR (-105)
|
||||
|
||||
#define UNZ_CASESENSITIVE 1
|
||||
#define UNZ_NOTCASESENSITIVE 2
|
||||
#define UNZ_OSDEFAULTCASE 0
|
||||
|
||||
extern int unzStringFileNameCompare (const char* fileName1, const char* fileName2, int iCaseSensitivity);
|
||||
|
||||
/*
|
||||
Compare two filename (fileName1,fileName2).
|
||||
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
|
||||
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
|
||||
or strcasecmp)
|
||||
If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
|
||||
(like 1 on Unix, 2 on Windows)
|
||||
*/
|
||||
|
||||
extern unzFile unzOpen (const char *path);
|
||||
extern unzFile unzReOpen (const char* path, unzFile file);
|
||||
|
||||
/*
|
||||
Open a Zip file. path contain the full pathname (by example,
|
||||
on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
|
||||
"zlib/zlib111.zip".
|
||||
If the zipfile cannot be opened (file don't exist or in not valid), the
|
||||
return value is NULL.
|
||||
Else, the return value is a unzFile Handle, usable with other function
|
||||
of this unzip package.
|
||||
*/
|
||||
|
||||
extern int unzClose (unzFile file);
|
||||
|
||||
/*
|
||||
Close a ZipFile opened with unzipOpen.
|
||||
If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
|
||||
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
|
||||
return UNZ_OK if there is no problem. */
|
||||
|
||||
extern int unzGetGlobalInfo (unzFile file, unz_global_info *pglobal_info);
|
||||
|
||||
/*
|
||||
Write info about the ZipFile in the *pglobal_info structure.
|
||||
No preparation of the structure is needed
|
||||
return UNZ_OK if there is no problem. */
|
||||
|
||||
|
||||
extern int unzGetGlobalComment (unzFile file, char *szComment, unsigned long uSizeBuf);
|
||||
|
||||
/*
|
||||
Get the global comment string of the ZipFile, in the szComment buffer.
|
||||
uSizeBuf is the size of the szComment buffer.
|
||||
return the number of unsigned char copied or an error code <0
|
||||
*/
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* Unzip package allow you browse the directory of the zipfile */
|
||||
|
||||
extern int unzGoToFirstFile (unzFile file);
|
||||
|
||||
/*
|
||||
Set the current file of the zipfile to the first file.
|
||||
return UNZ_OK if there is no problem
|
||||
*/
|
||||
|
||||
extern int unzGoToNextFile (unzFile file);
|
||||
|
||||
/*
|
||||
Set the current file of the zipfile to the next file.
|
||||
return UNZ_OK if there is no problem
|
||||
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
|
||||
*/
|
||||
|
||||
extern int unzGetCurrentFileInfoPosition (unzFile file, unsigned long *pos );
|
||||
|
||||
/*
|
||||
Get the position of the info of the current file in the zip.
|
||||
return UNZ_OK if there is no problem
|
||||
*/
|
||||
|
||||
extern int unzSetCurrentFileInfoPosition (unzFile file, unsigned long pos );
|
||||
|
||||
/*
|
||||
Set the position of the info of the current file in the zip.
|
||||
return UNZ_OK if there is no problem
|
||||
*/
|
||||
|
||||
extern int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity);
|
||||
|
||||
/*
|
||||
Try locate the file szFileName in the zipfile.
|
||||
For the iCaseSensitivity signification, see unzStringFileNameCompare
|
||||
|
||||
return value :
|
||||
UNZ_OK if the file is found. It becomes the current file.
|
||||
UNZ_END_OF_LIST_OF_FILE if the file is not found
|
||||
*/
|
||||
|
||||
|
||||
extern int unzGetCurrentFileInfo (unzFile file, unz_file_info *pfile_info, char *szFileName, unsigned long fileNameBufferSize, void *extraField, unsigned long extraFieldBufferSize, char *szComment, unsigned long commentBufferSize);
|
||||
|
||||
/*
|
||||
Get Info about the current file
|
||||
if pfile_info!=NULL, the *pfile_info structure will contain somes info about
|
||||
the current file
|
||||
if szFileName!=NULL, the filemane string will be copied in szFileName
|
||||
(fileNameBufferSize is the size of the buffer)
|
||||
if extraField!=NULL, the extra field information will be copied in extraField
|
||||
(extraFieldBufferSize is the size of the buffer).
|
||||
This is the Central-header version of the extra field
|
||||
if szComment!=NULL, the comment string of the file will be copied in szComment
|
||||
(commentBufferSize is the size of the buffer)
|
||||
*/
|
||||
|
||||
/***************************************************************************/
|
||||
/* for reading the content of the current zipfile, you can open it, read data
|
||||
from it, and close it (you can close it before reading all the file)
|
||||
*/
|
||||
|
||||
extern int unzOpenCurrentFile (unzFile file);
|
||||
|
||||
/*
|
||||
Open for reading data the current file in the zipfile.
|
||||
If there is no error, the return value is UNZ_OK.
|
||||
*/
|
||||
|
||||
extern int unzCloseCurrentFile (unzFile file);
|
||||
|
||||
/*
|
||||
Close the file in zip opened with unzOpenCurrentFile
|
||||
Return UNZ_CRCERROR if all the file was read but the CRC is not good
|
||||
*/
|
||||
|
||||
|
||||
extern int unzReadCurrentFile (unzFile file, void* buf, unsigned len);
|
||||
|
||||
/*
|
||||
Read unsigned chars from the current file (opened by unzOpenCurrentFile)
|
||||
buf contain buffer where data must be copied
|
||||
len the size of buf.
|
||||
|
||||
return the number of unsigned char copied if somes unsigned chars are copied
|
||||
return 0 if the end of file was reached
|
||||
return <0 with error code if there is an error
|
||||
(UNZ_ERRNO for IO error, or zLib error for uncompress error)
|
||||
*/
|
||||
|
||||
extern long unztell(unzFile file);
|
||||
|
||||
/*
|
||||
Give the current position in uncompressed data
|
||||
*/
|
||||
|
||||
extern int unzeof (unzFile file);
|
||||
|
||||
/*
|
||||
return 1 if the end of file was reached, 0 elsewhere
|
||||
*/
|
||||
|
||||
extern int unzGetLocalExtrafield (unzFile file, void* buf, unsigned len);
|
||||
|
||||
/*
|
||||
Read extra field from the current file (opened by unzOpenCurrentFile)
|
||||
This is the local-header version of the extra field (sometimes, there is
|
||||
more info in the local-header version than in the central-header)
|
||||
|
||||
if buf==NULL, it return the size of the local extra field
|
||||
|
||||
if buf!=NULL, len is the size of the buffer, the extra header is copied in
|
||||
buf.
|
||||
the return value is the number of unsigned chars copied in buf, or (if <0)
|
||||
the error code
|
||||
*/
|
||||
|
|
1670
code/qcommon/vm.c
Normal file → Executable file
1670
code/qcommon/vm.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
1778
code/qcommon/vm_interpreted.c
Normal file → Executable file
1778
code/qcommon/vm_interpreted.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
360
code/qcommon/vm_local.h
Normal file → Executable file
360
code/qcommon/vm_local.h
Normal file → Executable file
|
@ -1,180 +1,180 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
#include "../game/q_shared.h"
|
||||
#include "qcommon.h"
|
||||
|
||||
typedef enum {
|
||||
OP_UNDEF,
|
||||
|
||||
OP_IGNORE,
|
||||
|
||||
OP_BREAK,
|
||||
|
||||
OP_ENTER,
|
||||
OP_LEAVE,
|
||||
OP_CALL,
|
||||
OP_PUSH,
|
||||
OP_POP,
|
||||
|
||||
OP_CONST,
|
||||
OP_LOCAL,
|
||||
|
||||
OP_JUMP,
|
||||
|
||||
//-------------------
|
||||
|
||||
OP_EQ,
|
||||
OP_NE,
|
||||
|
||||
OP_LTI,
|
||||
OP_LEI,
|
||||
OP_GTI,
|
||||
OP_GEI,
|
||||
|
||||
OP_LTU,
|
||||
OP_LEU,
|
||||
OP_GTU,
|
||||
OP_GEU,
|
||||
|
||||
OP_EQF,
|
||||
OP_NEF,
|
||||
|
||||
OP_LTF,
|
||||
OP_LEF,
|
||||
OP_GTF,
|
||||
OP_GEF,
|
||||
|
||||
//-------------------
|
||||
|
||||
OP_LOAD1,
|
||||
OP_LOAD2,
|
||||
OP_LOAD4,
|
||||
OP_STORE1,
|
||||
OP_STORE2,
|
||||
OP_STORE4, // *(stack[top-1]) = stack[top]
|
||||
OP_ARG,
|
||||
|
||||
OP_BLOCK_COPY,
|
||||
|
||||
//-------------------
|
||||
|
||||
OP_SEX8,
|
||||
OP_SEX16,
|
||||
|
||||
OP_NEGI,
|
||||
OP_ADD,
|
||||
OP_SUB,
|
||||
OP_DIVI,
|
||||
OP_DIVU,
|
||||
OP_MODI,
|
||||
OP_MODU,
|
||||
OP_MULI,
|
||||
OP_MULU,
|
||||
|
||||
OP_BAND,
|
||||
OP_BOR,
|
||||
OP_BXOR,
|
||||
OP_BCOM,
|
||||
|
||||
OP_LSH,
|
||||
OP_RSHI,
|
||||
OP_RSHU,
|
||||
|
||||
OP_NEGF,
|
||||
OP_ADDF,
|
||||
OP_SUBF,
|
||||
OP_DIVF,
|
||||
OP_MULF,
|
||||
|
||||
OP_CVIF,
|
||||
OP_CVFI
|
||||
} opcode_t;
|
||||
|
||||
|
||||
|
||||
typedef int vmptr_t;
|
||||
|
||||
typedef struct vmSymbol_s {
|
||||
struct vmSymbol_s *next;
|
||||
int symValue;
|
||||
int profileCount;
|
||||
char symName[1]; // variable sized
|
||||
} vmSymbol_t;
|
||||
|
||||
#define VM_OFFSET_PROGRAM_STACK 0
|
||||
#define VM_OFFSET_SYSTEM_CALL 4
|
||||
|
||||
struct vm_s {
|
||||
// DO NOT MOVE OR CHANGE THESE WITHOUT CHANGING THE VM_OFFSET_* DEFINES
|
||||
// USED BY THE ASM CODE
|
||||
int programStack; // the vm may be recursively entered
|
||||
int (*systemCall)( int *parms );
|
||||
|
||||
//------------------------------------
|
||||
|
||||
char name[MAX_QPATH];
|
||||
|
||||
// for dynamic linked modules
|
||||
void *dllHandle;
|
||||
int (QDECL *entryPoint)( int callNum, ... );
|
||||
|
||||
// for interpreted modules
|
||||
qboolean currentlyInterpreting;
|
||||
|
||||
qboolean compiled;
|
||||
byte *codeBase;
|
||||
int codeLength;
|
||||
|
||||
int *instructionPointers;
|
||||
int instructionPointersLength;
|
||||
|
||||
byte *dataBase;
|
||||
int dataMask;
|
||||
|
||||
int stackBottom; // if programStack < stackBottom, error
|
||||
|
||||
int numSymbols;
|
||||
struct vmSymbol_s *symbols;
|
||||
|
||||
int callLevel; // for debug indenting
|
||||
int breakFunction; // increment breakCount on function entry to this
|
||||
int breakCount;
|
||||
|
||||
// fqpath member added 7/20/02 by T.Ray
|
||||
char fqpath[MAX_QPATH+1] ;
|
||||
};
|
||||
|
||||
|
||||
extern vm_t *currentVM;
|
||||
extern int vm_debugLevel;
|
||||
|
||||
void VM_Compile( vm_t *vm, vmHeader_t *header );
|
||||
int VM_CallCompiled( vm_t *vm, int *args );
|
||||
|
||||
void VM_PrepareInterpreter( vm_t *vm, vmHeader_t *header );
|
||||
int VM_CallInterpreted( vm_t *vm, int *args );
|
||||
|
||||
vmSymbol_t *VM_ValueToFunctionSymbol( vm_t *vm, int value );
|
||||
int VM_SymbolToValue( vm_t *vm, const char *symbol );
|
||||
const char *VM_ValueToSymbol( vm_t *vm, int value );
|
||||
void VM_LogSyscalls( int *args );
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 1999-2005 Id Software, Inc.
|
||||
|
||||
This file is part of Quake III Arena source code.
|
||||
|
||||
Quake III Arena source code 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.
|
||||
|
||||
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
#include "../game/q_shared.h"
|
||||
#include "qcommon.h"
|
||||
|
||||
typedef enum {
|
||||
OP_UNDEF,
|
||||
|
||||
OP_IGNORE,
|
||||
|
||||
OP_BREAK,
|
||||
|
||||
OP_ENTER,
|
||||
OP_LEAVE,
|
||||
OP_CALL,
|
||||
OP_PUSH,
|
||||
OP_POP,
|
||||
|
||||
OP_CONST,
|
||||
OP_LOCAL,
|
||||
|
||||
OP_JUMP,
|
||||
|
||||
//-------------------
|
||||
|
||||
OP_EQ,
|
||||
OP_NE,
|
||||
|
||||
OP_LTI,
|
||||
OP_LEI,
|
||||
OP_GTI,
|
||||
OP_GEI,
|
||||
|
||||
OP_LTU,
|
||||
OP_LEU,
|
||||
OP_GTU,
|
||||
OP_GEU,
|
||||
|
||||
OP_EQF,
|
||||
OP_NEF,
|
||||
|
||||
OP_LTF,
|
||||
OP_LEF,
|
||||
OP_GTF,
|
||||
OP_GEF,
|
||||
|
||||
//-------------------
|
||||
|
||||
OP_LOAD1,
|
||||
OP_LOAD2,
|
||||
OP_LOAD4,
|
||||
OP_STORE1,
|
||||
OP_STORE2,
|
||||
OP_STORE4, // *(stack[top-1]) = stack[top]
|
||||
OP_ARG,
|
||||
|
||||
OP_BLOCK_COPY,
|
||||
|
||||
//-------------------
|
||||
|
||||
OP_SEX8,
|
||||
OP_SEX16,
|
||||
|
||||
OP_NEGI,
|
||||
OP_ADD,
|
||||
OP_SUB,
|
||||
OP_DIVI,
|
||||
OP_DIVU,
|
||||
OP_MODI,
|
||||
OP_MODU,
|
||||
OP_MULI,
|
||||
OP_MULU,
|
||||
|
||||
OP_BAND,
|
||||
OP_BOR,
|
||||
OP_BXOR,
|
||||
OP_BCOM,
|
||||
|
||||
OP_LSH,
|
||||
OP_RSHI,
|
||||
OP_RSHU,
|
||||
|
||||
OP_NEGF,
|
||||
OP_ADDF,
|
||||
OP_SUBF,
|
||||
OP_DIVF,
|
||||
OP_MULF,
|
||||
|
||||
OP_CVIF,
|
||||
OP_CVFI
|
||||
} opcode_t;
|
||||
|
||||
|
||||
|
||||
typedef int vmptr_t;
|
||||
|
||||
typedef struct vmSymbol_s {
|
||||
struct vmSymbol_s *next;
|
||||
int symValue;
|
||||
int profileCount;
|
||||
char symName[1]; // variable sized
|
||||
} vmSymbol_t;
|
||||
|
||||
#define VM_OFFSET_PROGRAM_STACK 0
|
||||
#define VM_OFFSET_SYSTEM_CALL 4
|
||||
|
||||
struct vm_s {
|
||||
// DO NOT MOVE OR CHANGE THESE WITHOUT CHANGING THE VM_OFFSET_* DEFINES
|
||||
// USED BY THE ASM CODE
|
||||
int programStack; // the vm may be recursively entered
|
||||
int (*systemCall)( int *parms );
|
||||
|
||||
//------------------------------------
|
||||
|
||||
char name[MAX_QPATH];
|
||||
|
||||
// for dynamic linked modules
|
||||
void *dllHandle;
|
||||
int (QDECL *entryPoint)( int callNum, ... );
|
||||
|
||||
// for interpreted modules
|
||||
qboolean currentlyInterpreting;
|
||||
|
||||
qboolean compiled;
|
||||
byte *codeBase;
|
||||
int codeLength;
|
||||
|
||||
int *instructionPointers;
|
||||
int instructionPointersLength;
|
||||
|
||||
byte *dataBase;
|
||||
int dataMask;
|
||||
|
||||
int stackBottom; // if programStack < stackBottom, error
|
||||
|
||||
int numSymbols;
|
||||
struct vmSymbol_s *symbols;
|
||||
|
||||
int callLevel; // for debug indenting
|
||||
int breakFunction; // increment breakCount on function entry to this
|
||||
int breakCount;
|
||||
|
||||
// fqpath member added 7/20/02 by T.Ray
|
||||
char fqpath[MAX_QPATH+1] ;
|
||||
};
|
||||
|
||||
|
||||
extern vm_t *currentVM;
|
||||
extern int vm_debugLevel;
|
||||
|
||||
void VM_Compile( vm_t *vm, vmHeader_t *header );
|
||||
int VM_CallCompiled( vm_t *vm, int *args );
|
||||
|
||||
void VM_PrepareInterpreter( vm_t *vm, vmHeader_t *header );
|
||||
int VM_CallInterpreted( vm_t *vm, int *args );
|
||||
|
||||
vmSymbol_t *VM_ValueToFunctionSymbol( vm_t *vm, int value );
|
||||
int VM_SymbolToValue( vm_t *vm, const char *symbol );
|
||||
const char *VM_ValueToSymbol( vm_t *vm, int value );
|
||||
void VM_LogSyscalls( int *args );
|
||||
|
||||
|
|
2958
code/qcommon/vm_ppc.c
Normal file → Executable file
2958
code/qcommon/vm_ppc.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
4238
code/qcommon/vm_ppc_new.c
Normal file → Executable file
4238
code/qcommon/vm_ppc_new.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
2392
code/qcommon/vm_x86.c
Normal file → Executable file
2392
code/qcommon/vm_x86.c
Normal file → Executable file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue