Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

be_aas_file.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 
00023 /*****************************************************************************
00024  * name:        be_aas_file.c
00025  *
00026  * desc:        AAS file loading/writing
00027  *
00028  * $Archive: /MissionPack/code/botlib/be_aas_file.c $
00029  *
00030  *****************************************************************************/
00031 
00032 #include "../game/q_shared.h"
00033 #include "l_memory.h"
00034 #include "l_script.h"
00035 #include "l_precomp.h"
00036 #include "l_struct.h"
00037 #include "l_libvar.h"
00038 #include "l_utils.h"
00039 #include "aasfile.h"
00040 #include "../game/botlib.h"
00041 #include "../game/be_aas.h"
00042 #include "be_aas_funcs.h"
00043 #include "be_interface.h"
00044 #include "be_aas_def.h"
00045 
00046 //#define AASFILEDEBUG
00047 
00048 //===========================================================================
00049 //
00050 // Parameter:               -
00051 // Returns:                 -
00052 // Changes Globals:     -
00053 //===========================================================================
00054 void AAS_SwapAASData(void)
00055 {
00056     int i, j;
00057     //bounding boxes
00058     for (i = 0; i < aasworld.numbboxes; i++)
00059     {
00060         aasworld.bboxes[i].presencetype = LittleLong(aasworld.bboxes[i].presencetype);
00061         aasworld.bboxes[i].flags = LittleLong(aasworld.bboxes[i].flags);
00062         for (j = 0; j < 3; j++)
00063         {
00064             aasworld.bboxes[i].mins[j] = LittleLong(aasworld.bboxes[i].mins[j]);
00065             aasworld.bboxes[i].maxs[j] = LittleLong(aasworld.bboxes[i].maxs[j]);
00066         } //end for
00067     } //end for
00068     //vertexes
00069     for (i = 0; i < aasworld.numvertexes; i++)
00070     {
00071         for (j = 0; j < 3; j++)
00072             aasworld.vertexes[i][j] = LittleFloat(aasworld.vertexes[i][j]);
00073     } //end for
00074     //planes
00075     for (i = 0; i < aasworld.numplanes; i++)
00076     {
00077         for (j = 0; j < 3; j++)
00078             aasworld.planes[i].normal[j] = LittleFloat(aasworld.planes[i].normal[j]);
00079         aasworld.planes[i].dist = LittleFloat(aasworld.planes[i].dist);
00080         aasworld.planes[i].type = LittleLong(aasworld.planes[i].type);
00081     } //end for
00082     //edges
00083     for (i = 0; i < aasworld.numedges; i++)
00084     {
00085         aasworld.edges[i].v[0] = LittleLong(aasworld.edges[i].v[0]);
00086         aasworld.edges[i].v[1] = LittleLong(aasworld.edges[i].v[1]);
00087     } //end for
00088     //edgeindex
00089     for (i = 0; i < aasworld.edgeindexsize; i++)
00090     {
00091         aasworld.edgeindex[i] = LittleLong(aasworld.edgeindex[i]);
00092     } //end for
00093     //faces
00094     for (i = 0; i < aasworld.numfaces; i++)
00095     {
00096         aasworld.faces[i].planenum = LittleLong(aasworld.faces[i].planenum);
00097         aasworld.faces[i].faceflags = LittleLong(aasworld.faces[i].faceflags);
00098         aasworld.faces[i].numedges = LittleLong(aasworld.faces[i].numedges);
00099         aasworld.faces[i].firstedge = LittleLong(aasworld.faces[i].firstedge);
00100         aasworld.faces[i].frontarea = LittleLong(aasworld.faces[i].frontarea);
00101         aasworld.faces[i].backarea = LittleLong(aasworld.faces[i].backarea);
00102     } //end for
00103     //face index
00104     for (i = 0; i < aasworld.faceindexsize; i++)
00105     {
00106         aasworld.faceindex[i] = LittleLong(aasworld.faceindex[i]);
00107     } //end for
00108     //convex areas
00109     for (i = 0; i < aasworld.numareas; i++)
00110     {
00111         aasworld.areas[i].areanum = LittleLong(aasworld.areas[i].areanum);
00112         aasworld.areas[i].numfaces = LittleLong(aasworld.areas[i].numfaces);
00113         aasworld.areas[i].firstface = LittleLong(aasworld.areas[i].firstface);
00114         for (j = 0; j < 3; j++)
00115         {
00116             aasworld.areas[i].mins[j] = LittleFloat(aasworld.areas[i].mins[j]);
00117             aasworld.areas[i].maxs[j] = LittleFloat(aasworld.areas[i].maxs[j]);
00118             aasworld.areas[i].center[j] = LittleFloat(aasworld.areas[i].center[j]);
00119         } //end for
00120     } //end for
00121     //area settings
00122     for (i = 0; i < aasworld.numareasettings; i++)
00123     {
00124         aasworld.areasettings[i].contents = LittleLong(aasworld.areasettings[i].contents);
00125         aasworld.areasettings[i].areaflags = LittleLong(aasworld.areasettings[i].areaflags);
00126         aasworld.areasettings[i].presencetype = LittleLong(aasworld.areasettings[i].presencetype);
00127         aasworld.areasettings[i].cluster = LittleLong(aasworld.areasettings[i].cluster);
00128         aasworld.areasettings[i].clusterareanum = LittleLong(aasworld.areasettings[i].clusterareanum);
00129         aasworld.areasettings[i].numreachableareas = LittleLong(aasworld.areasettings[i].numreachableareas);
00130         aasworld.areasettings[i].firstreachablearea = LittleLong(aasworld.areasettings[i].firstreachablearea);
00131     } //end for
00132     //area reachability
00133     for (i = 0; i < aasworld.reachabilitysize; i++)
00134     {
00135         aasworld.reachability[i].areanum = LittleLong(aasworld.reachability[i].areanum);
00136         aasworld.reachability[i].facenum = LittleLong(aasworld.reachability[i].facenum);
00137         aasworld.reachability[i].edgenum = LittleLong(aasworld.reachability[i].edgenum);
00138         for (j = 0; j < 3; j++)
00139         {
00140             aasworld.reachability[i].start[j] = LittleFloat(aasworld.reachability[i].start[j]);
00141             aasworld.reachability[i].end[j] = LittleFloat(aasworld.reachability[i].end[j]);
00142         } //end for
00143         aasworld.reachability[i].traveltype = LittleLong(aasworld.reachability[i].traveltype);
00144         aasworld.reachability[i].traveltime = LittleShort(aasworld.reachability[i].traveltime);
00145     } //end for
00146     //nodes
00147     for (i = 0; i < aasworld.numnodes; i++)
00148     {
00149         aasworld.nodes[i].planenum = LittleLong(aasworld.nodes[i].planenum);
00150         aasworld.nodes[i].children[0] = LittleLong(aasworld.nodes[i].children[0]);
00151         aasworld.nodes[i].children[1] = LittleLong(aasworld.nodes[i].children[1]);
00152     } //end for
00153     //cluster portals
00154     for (i = 0; i < aasworld.numportals; i++)
00155     {
00156         aasworld.portals[i].areanum = LittleLong(aasworld.portals[i].areanum);
00157         aasworld.portals[i].frontcluster = LittleLong(aasworld.portals[i].frontcluster);
00158         aasworld.portals[i].backcluster = LittleLong(aasworld.portals[i].backcluster);
00159         aasworld.portals[i].clusterareanum[0] = LittleLong(aasworld.portals[i].clusterareanum[0]);
00160         aasworld.portals[i].clusterareanum[1] = LittleLong(aasworld.portals[i].clusterareanum[1]);
00161     } //end for
00162     //cluster portal index
00163     for (i = 0; i < aasworld.portalindexsize; i++)
00164     {
00165         aasworld.portalindex[i] = LittleLong(aasworld.portalindex[i]);
00166     } //end for
00167     //cluster
00168     for (i = 0; i < aasworld.numclusters; i++)
00169     {
00170         aasworld.clusters[i].numareas = LittleLong(aasworld.clusters[i].numareas);
00171         aasworld.clusters[i].numreachabilityareas = LittleLong(aasworld.clusters[i].numreachabilityareas);
00172         aasworld.clusters[i].numportals = LittleLong(aasworld.clusters[i].numportals);
00173         aasworld.clusters[i].firstportal = LittleLong(aasworld.clusters[i].firstportal);
00174     } //end for
00175 } //end of the function AAS_SwapAASData
00176 //===========================================================================
00177 // dump the current loaded aas file
00178 //
00179 // Parameter:               -
00180 // Returns:                 -
00181 // Changes Globals:     -
00182 //===========================================================================
00183 void AAS_DumpAASData(void)
00184 {
00185     aasworld.numbboxes = 0;
00186     if (aasworld.bboxes) FreeMemory(aasworld.bboxes);
00187     aasworld.bboxes = NULL;
00188     aasworld.numvertexes = 0;
00189     if (aasworld.vertexes) FreeMemory(aasworld.vertexes);
00190     aasworld.vertexes = NULL;
00191     aasworld.numplanes = 0;
00192     if (aasworld.planes) FreeMemory(aasworld.planes);
00193     aasworld.planes = NULL;
00194     aasworld.numedges = 0;
00195     if (aasworld.edges) FreeMemory(aasworld.edges);
00196     aasworld.edges = NULL;
00197     aasworld.edgeindexsize = 0;
00198     if (aasworld.edgeindex) FreeMemory(aasworld.edgeindex);
00199     aasworld.edgeindex = NULL;
00200     aasworld.numfaces = 0;
00201     if (aasworld.faces) FreeMemory(aasworld.faces);
00202     aasworld.faces = NULL;
00203     aasworld.faceindexsize = 0;
00204     if (aasworld.faceindex) FreeMemory(aasworld.faceindex);
00205     aasworld.faceindex = NULL;
00206     aasworld.numareas = 0;
00207     if (aasworld.areas) FreeMemory(aasworld.areas);
00208     aasworld.areas = NULL;
00209     aasworld.numareasettings = 0;
00210     if (aasworld.areasettings) FreeMemory(aasworld.areasettings);
00211     aasworld.areasettings = NULL;
00212     aasworld.reachabilitysize = 0;
00213     if (aasworld.reachability) FreeMemory(aasworld.reachability);
00214     aasworld.reachability = NULL;
00215     aasworld.numnodes = 0;
00216     if (aasworld.nodes) FreeMemory(aasworld.nodes);
00217     aasworld.nodes = NULL;
00218     aasworld.numportals = 0;
00219     if (aasworld.portals) FreeMemory(aasworld.portals);
00220     aasworld.portals = NULL;
00221     aasworld.numportals = 0;
00222     if (aasworld.portalindex) FreeMemory(aasworld.portalindex);
00223     aasworld.portalindex = NULL;
00224     aasworld.portalindexsize = 0;
00225     if (aasworld.clusters) FreeMemory(aasworld.clusters);
00226     aasworld.clusters = NULL;
00227     aasworld.numclusters = 0;
00228     //
00229     aasworld.loaded = qfalse;
00230     aasworld.initialized = qfalse;
00231     aasworld.savefile = qfalse;
00232 } //end of the function AAS_DumpAASData
00233 //===========================================================================
00234 //
00235 // Parameter:               -
00236 // Returns:                 -
00237 // Changes Globals:     -
00238 //===========================================================================
00239 #ifdef AASFILEDEBUG
00240 void AAS_FileInfo(void)
00241 {
00242     int i, n, optimized;
00243 
00244     botimport.Print(PRT_MESSAGE, "version = %d\n", AASVERSION);
00245     botimport.Print(PRT_MESSAGE, "numvertexes = %d\n", aasworld.numvertexes);
00246     botimport.Print(PRT_MESSAGE, "numplanes = %d\n", aasworld.numplanes);
00247     botimport.Print(PRT_MESSAGE, "numedges = %d\n", aasworld.numedges);
00248     botimport.Print(PRT_MESSAGE, "edgeindexsize = %d\n", aasworld.edgeindexsize);
00249     botimport.Print(PRT_MESSAGE, "numfaces = %d\n", aasworld.numfaces);
00250     botimport.Print(PRT_MESSAGE, "faceindexsize = %d\n", aasworld.faceindexsize);
00251     botimport.Print(PRT_MESSAGE, "numareas = %d\n", aasworld.numareas);
00252     botimport.Print(PRT_MESSAGE, "numareasettings = %d\n", aasworld.numareasettings);
00253     botimport.Print(PRT_MESSAGE, "reachabilitysize = %d\n", aasworld.reachabilitysize);
00254     botimport.Print(PRT_MESSAGE, "numnodes = %d\n", aasworld.numnodes);
00255     botimport.Print(PRT_MESSAGE, "numportals = %d\n", aasworld.numportals);
00256     botimport.Print(PRT_MESSAGE, "portalindexsize = %d\n", aasworld.portalindexsize);
00257     botimport.Print(PRT_MESSAGE, "numclusters = %d\n", aasworld.numclusters);
00258     //
00259     for (n = 0, i = 0; i < aasworld.numareasettings; i++)
00260     {
00261         if (aasworld.areasettings[i].areaflags & AREA_GROUNDED) n++;
00262     } //end for
00263     botimport.Print(PRT_MESSAGE, "num grounded areas = %d\n", n);
00264     //
00265     botimport.Print(PRT_MESSAGE, "planes size %d bytes\n", aasworld.numplanes * sizeof(aas_plane_t));
00266     botimport.Print(PRT_MESSAGE, "areas size %d bytes\n", aasworld.numareas * sizeof(aas_area_t));
00267     botimport.Print(PRT_MESSAGE, "areasettings size %d bytes\n", aasworld.numareasettings * sizeof(aas_areasettings_t));
00268     botimport.Print(PRT_MESSAGE, "nodes size %d bytes\n", aasworld.numnodes * sizeof(aas_node_t));
00269     botimport.Print(PRT_MESSAGE, "reachability size %d bytes\n", aasworld.reachabilitysize * sizeof(aas_reachability_t));
00270     botimport.Print(PRT_MESSAGE, "portals size %d bytes\n", aasworld.numportals * sizeof(aas_portal_t));
00271     botimport.Print(PRT_MESSAGE, "clusters size %d bytes\n", aasworld.numclusters * sizeof(aas_cluster_t));
00272 
00273     optimized = aasworld.numplanes * sizeof(aas_plane_t) +
00274                     aasworld.numareas * sizeof(aas_area_t) +
00275                     aasworld.numareasettings * sizeof(aas_areasettings_t) +
00276                     aasworld.numnodes * sizeof(aas_node_t) +
00277                     aasworld.reachabilitysize * sizeof(aas_reachability_t) +
00278                     aasworld.numportals * sizeof(aas_portal_t) +
00279                     aasworld.numclusters * sizeof(aas_cluster_t);
00280     botimport.Print(PRT_MESSAGE, "optimzed size %d KB\n", optimized >> 10);
00281 } //end of the function AAS_FileInfo
00282 #endif //AASFILEDEBUG
00283 //===========================================================================
00284 // allocate memory and read a lump of a AAS file
00285 //
00286 // Parameter:               -
00287 // Returns:                 -
00288 // Changes Globals:     -
00289 //===========================================================================
00290 char *AAS_LoadAASLump(fileHandle_t fp, int offset, int length, int *lastoffset, int size)
00291 {
00292     char *buf;
00293     //
00294     if (!length)
00295     {
00296         //just alloc a dummy
00297         return (char *) GetClearedHunkMemory(size+1);
00298     } //end if
00299     //seek to the data
00300     if (offset != *lastoffset)
00301     {
00302         botimport.Print(PRT_WARNING, "AAS file not sequentially read\n");
00303         if (botimport.FS_Seek(fp, offset, FS_SEEK_SET))
00304         {
00305             AAS_Error("can't seek to aas lump\n");
00306             AAS_DumpAASData();
00307             botimport.FS_FCloseFile(fp);
00308             return 0;
00309         } //end if
00310     } //end if
00311     //allocate memory
00312     buf = (char *) GetClearedHunkMemory(length+1);
00313     //read the data
00314     if (length)
00315     {
00316         botimport.FS_Read(buf, length, fp );
00317         *lastoffset += length;
00318     } //end if
00319     return buf;
00320 } //end of the function AAS_LoadAASLump
00321 //===========================================================================
00322 //
00323 // Parameter:           -
00324 // Returns:             -
00325 // Changes Globals:     -
00326 //===========================================================================
00327 void AAS_DData(unsigned char *data, int size)
00328 {
00329     int i;
00330 
00331     for (i = 0; i < size; i++)
00332     {
00333         data[i] ^= (unsigned char) i * 119;
00334     } //end for
00335 } //end of the function AAS_DData
00336 //===========================================================================
00337 // load an aas file
00338 //
00339 // Parameter:           -
00340 // Returns:             -
00341 // Changes Globals:     -
00342 //===========================================================================
00343 int AAS_LoadAASFile(char *filename)
00344 {
00345     fileHandle_t fp;
00346     aas_header_t header;
00347     int offset, length, lastoffset;
00348 
00349     botimport.Print(PRT_MESSAGE, "trying to load %s\n", filename);
00350     //dump current loaded aas file
00351     AAS_DumpAASData();
00352     //open the file
00353     botimport.FS_FOpenFile( filename, &fp, FS_READ );
00354     if (!fp)
00355     {
00356         AAS_Error("can't open %s\n", filename);
00357         return BLERR_CANNOTOPENAASFILE;
00358     } //end if
00359     //read the header
00360     botimport.FS_Read(&header, sizeof(aas_header_t), fp );
00361     lastoffset = sizeof(aas_header_t);
00362     //check header identification
00363     header.ident = LittleLong(header.ident);
00364     if (header.ident != AASID)
00365     {
00366         AAS_Error("%s is not an AAS file\n", filename);
00367         botimport.FS_FCloseFile(fp);
00368         return BLERR_WRONGAASFILEID;
00369     } //end if
00370     //check the version
00371     header.version = LittleLong(header.version);
00372     //
00373     if (header.version != AASVERSION_OLD && header.version != AASVERSION)
00374     {
00375         AAS_Error("aas file %s is version %i, not %i\n", filename, header.version, AASVERSION);
00376         botimport.FS_FCloseFile(fp);
00377         return BLERR_WRONGAASFILEVERSION;
00378     } //end if
00379     //
00380     if (header.version == AASVERSION)
00381     {
00382         AAS_DData((unsigned char *) &header + 8, sizeof(aas_header_t) - 8);
00383     } //end if
00384     //
00385     aasworld.bspchecksum = atoi(LibVarGetString( "sv_mapChecksum"));
00386     if (LittleLong(header.bspchecksum) != aasworld.bspchecksum)
00387     {
00388         AAS_Error("aas file %s is out of date\n", filename);
00389         botimport.FS_FCloseFile(fp);
00390         return BLERR_WRONGAASFILEVERSION;
00391     } //end if
00392     //load the lumps:
00393     //bounding boxes
00394     offset = LittleLong(header.lumps[AASLUMP_BBOXES].fileofs);
00395     length = LittleLong(header.lumps[AASLUMP_BBOXES].filelen);
00396     aasworld.bboxes = (aas_bbox_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_bbox_t));
00397     aasworld.numbboxes = length / sizeof(aas_bbox_t);
00398     if (aasworld.numbboxes && !aasworld.bboxes) return BLERR_CANNOTREADAASLUMP;
00399     //vertexes
00400     offset = LittleLong(header.lumps[AASLUMP_VERTEXES].fileofs);
00401     length = LittleLong(header.lumps[AASLUMP_VERTEXES].filelen);
00402     aasworld.vertexes = (aas_vertex_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_vertex_t));
00403     aasworld.numvertexes = length / sizeof(aas_vertex_t);
00404     if (aasworld.numvertexes && !aasworld.vertexes) return BLERR_CANNOTREADAASLUMP;
00405     //planes
00406     offset = LittleLong(header.lumps[AASLUMP_PLANES].fileofs);
00407     length = LittleLong(header.lumps[AASLUMP_PLANES].filelen);
00408     aasworld.planes = (aas_plane_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_plane_t));
00409     aasworld.numplanes = length / sizeof(aas_plane_t);
00410     if (aasworld.numplanes && !aasworld.planes) return BLERR_CANNOTREADAASLUMP;
00411     //edges
00412     offset = LittleLong(header.lumps[AASLUMP_EDGES].fileofs);
00413     length = LittleLong(header.lumps[AASLUMP_EDGES].filelen);
00414     aasworld.edges = (aas_edge_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_edge_t));
00415     aasworld.numedges = length / sizeof(aas_edge_t);
00416     if (aasworld.numedges && !aasworld.edges) return BLERR_CANNOTREADAASLUMP;
00417     //edgeindex
00418     offset = LittleLong(header.lumps[AASLUMP_EDGEINDEX].fileofs);
00419     length = LittleLong(header.lumps[AASLUMP_EDGEINDEX].filelen);
00420     aasworld.edgeindex = (aas_edgeindex_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_edgeindex_t));
00421     aasworld.edgeindexsize = length / sizeof(aas_edgeindex_t);
00422     if (aasworld.edgeindexsize && !aasworld.edgeindex) return BLERR_CANNOTREADAASLUMP;
00423     //faces
00424     offset = LittleLong(header.lumps[AASLUMP_FACES].fileofs);
00425     length = LittleLong(header.lumps[AASLUMP_FACES].filelen);
00426     aasworld.faces = (aas_face_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_face_t));
00427     aasworld.numfaces = length / sizeof(aas_face_t);
00428     if (aasworld.numfaces && !aasworld.faces) return BLERR_CANNOTREADAASLUMP;
00429     //faceindex
00430     offset = LittleLong(header.lumps[AASLUMP_FACEINDEX].fileofs);
00431     length = LittleLong(header.lumps[AASLUMP_FACEINDEX].filelen);
00432     aasworld.faceindex = (aas_faceindex_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_faceindex_t));
00433     aasworld.faceindexsize = length / sizeof(aas_faceindex_t);
00434     if (aasworld.faceindexsize && !aasworld.faceindex) return BLERR_CANNOTREADAASLUMP;
00435     //convex areas
00436     offset = LittleLong(header.lumps[AASLUMP_AREAS].fileofs);
00437     length = LittleLong(header.lumps[AASLUMP_AREAS].filelen);
00438     aasworld.areas = (aas_area_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_area_t));
00439     aasworld.numareas = length / sizeof(aas_area_t);
00440     if (aasworld.numareas && !aasworld.areas) return BLERR_CANNOTREADAASLUMP;
00441     //area settings
00442     offset = LittleLong(header.lumps[AASLUMP_AREASETTINGS].fileofs);
00443     length = LittleLong(header.lumps[AASLUMP_AREASETTINGS].filelen);
00444     aasworld.areasettings = (aas_areasettings_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_areasettings_t));
00445     aasworld.numareasettings = length / sizeof(aas_areasettings_t);
00446     if (aasworld.numareasettings && !aasworld.areasettings) return BLERR_CANNOTREADAASLUMP;
00447     //reachability list
00448     offset = LittleLong(header.lumps[AASLUMP_REACHABILITY].fileofs);
00449     length = LittleLong(header.lumps[AASLUMP_REACHABILITY].filelen);
00450     aasworld.reachability = (aas_reachability_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_reachability_t));
00451     aasworld.reachabilitysize = length / sizeof(aas_reachability_t);
00452     if (aasworld.reachabilitysize && !aasworld.reachability) return BLERR_CANNOTREADAASLUMP;
00453     //nodes
00454     offset = LittleLong(header.lumps[AASLUMP_NODES].fileofs);
00455     length = LittleLong(header.lumps[AASLUMP_NODES].filelen);
00456     aasworld.nodes = (aas_node_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_node_t));
00457     aasworld.numnodes = length / sizeof(aas_node_t);
00458     if (aasworld.numnodes && !aasworld.nodes) return BLERR_CANNOTREADAASLUMP;
00459     //cluster portals
00460     offset = LittleLong(header.lumps[AASLUMP_PORTALS].fileofs);
00461     length = LittleLong(header.lumps[AASLUMP_PORTALS].filelen);
00462     aasworld.portals = (aas_portal_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_portal_t));
00463     aasworld.numportals = length / sizeof(aas_portal_t);
00464     if (aasworld.numportals && !aasworld.portals) return BLERR_CANNOTREADAASLUMP;
00465     //cluster portal index
00466     offset = LittleLong(header.lumps[AASLUMP_PORTALINDEX].fileofs);
00467     length = LittleLong(header.lumps[AASLUMP_PORTALINDEX].filelen);
00468     aasworld.portalindex = (aas_portalindex_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_portalindex_t));
00469     aasworld.portalindexsize = length / sizeof(aas_portalindex_t);
00470     if (aasworld.portalindexsize && !aasworld.portalindex) return BLERR_CANNOTREADAASLUMP;
00471     //clusters
00472     offset = LittleLong(header.lumps[AASLUMP_CLUSTERS].fileofs);
00473     length = LittleLong(header.lumps[AASLUMP_CLUSTERS].filelen);
00474     aasworld.clusters = (aas_cluster_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_cluster_t));
00475     aasworld.numclusters = length / sizeof(aas_cluster_t);
00476     if (aasworld.numclusters && !aasworld.clusters) return BLERR_CANNOTREADAASLUMP;
00477     //swap everything
00478     AAS_SwapAASData();
00479     //aas file is loaded
00480     aasworld.loaded = qtrue;
00481     //close the file
00482     botimport.FS_FCloseFile(fp);
00483     //
00484 #ifdef AASFILEDEBUG
00485     AAS_FileInfo();
00486 #endif //AASFILEDEBUG
00487     //
00488     return BLERR_NOERROR;
00489 } //end of the function AAS_LoadAASFile
00490 //===========================================================================
00491 //
00492 // Parameter:               -
00493 // Returns:                 -
00494 // Changes Globals:     -
00495 //===========================================================================
00496 static int AAS_WriteAASLump_offset;
00497 
00498 int AAS_WriteAASLump(fileHandle_t fp, aas_header_t *h, int lumpnum, void *data, int length)
00499 {
00500     aas_lump_t *lump;
00501 
00502     lump = &h->lumps[lumpnum];
00503     
00504     lump->fileofs = LittleLong(AAS_WriteAASLump_offset);    //LittleLong(ftell(fp));
00505     lump->filelen = LittleLong(length);
00506 
00507     if (length > 0)
00508     {
00509         botimport.FS_Write(data, length, fp );
00510     } //end if
00511 
00512     AAS_WriteAASLump_offset += length;
00513 
00514     return qtrue;
00515 } //end of the function AAS_WriteAASLump
00516 //===========================================================================
00517 // aas data is useless after writing to file because it is byte swapped
00518 //
00519 // Parameter:               -
00520 // Returns:                 -
00521 // Changes Globals:     -
00522 //===========================================================================
00523 qboolean AAS_WriteAASFile(char *filename)
00524 {
00525     aas_header_t header;
00526     fileHandle_t fp;
00527 
00528     botimport.Print(PRT_MESSAGE, "writing %s\n", filename);
00529     //swap the aas data
00530     AAS_SwapAASData();
00531     //initialize the file header
00532     Com_Memset(&header, 0, sizeof(aas_header_t));
00533     header.ident = LittleLong(AASID);
00534     header.version = LittleLong(AASVERSION);
00535     header.bspchecksum = LittleLong(aasworld.bspchecksum);
00536     //open a new file
00537     botimport.FS_FOpenFile( filename, &fp, FS_WRITE );
00538     if (!fp)
00539     {
00540         botimport.Print(PRT_ERROR, "error opening %s\n", filename);
00541         return qfalse;
00542     } //end if
00543     //write the header
00544     botimport.FS_Write(&header, sizeof(aas_header_t), fp);
00545     AAS_WriteAASLump_offset = sizeof(aas_header_t);
00546     //add the data lumps to the file
00547     if (!AAS_WriteAASLump(fp, &header, AASLUMP_BBOXES, aasworld.bboxes,
00548         aasworld.numbboxes * sizeof(aas_bbox_t))) return qfalse;
00549     if (!AAS_WriteAASLump(fp, &header, AASLUMP_VERTEXES, aasworld.vertexes,
00550         aasworld.numvertexes * sizeof(aas_vertex_t))) return qfalse;
00551     if (!AAS_WriteAASLump(fp, &header, AASLUMP_PLANES, aasworld.planes,
00552         aasworld.numplanes * sizeof(aas_plane_t))) return qfalse;
00553     if (!AAS_WriteAASLump(fp, &header, AASLUMP_EDGES, aasworld.edges,
00554         aasworld.numedges * sizeof(aas_edge_t))) return qfalse;
00555     if (!AAS_WriteAASLump(fp, &header, AASLUMP_EDGEINDEX, aasworld.edgeindex,
00556         aasworld.edgeindexsize * sizeof(aas_edgeindex_t))) return qfalse;
00557     if (!AAS_WriteAASLump(fp, &header, AASLUMP_FACES, aasworld.faces,
00558         aasworld.numfaces * sizeof(aas_face_t))) return qfalse;
00559     if (!AAS_WriteAASLump(fp, &header, AASLUMP_FACEINDEX, aasworld.faceindex,
00560         aasworld.faceindexsize * sizeof(aas_faceindex_t))) return qfalse;
00561     if (!AAS_WriteAASLump(fp, &header, AASLUMP_AREAS, aasworld.areas,
00562         aasworld.numareas * sizeof(aas_area_t))) return qfalse;
00563     if (!AAS_WriteAASLump(fp, &header, AASLUMP_AREASETTINGS, aasworld.areasettings,
00564         aasworld.numareasettings * sizeof(aas_areasettings_t))) return qfalse;
00565     if (!AAS_WriteAASLump(fp, &header, AASLUMP_REACHABILITY, aasworld.reachability,
00566         aasworld.reachabilitysize * sizeof(aas_reachability_t))) return qfalse;
00567     if (!AAS_WriteAASLump(fp, &header, AASLUMP_NODES, aasworld.nodes,
00568         aasworld.numnodes * sizeof(aas_node_t))) return qfalse;
00569     if (!AAS_WriteAASLump(fp, &header, AASLUMP_PORTALS, aasworld.portals,
00570         aasworld.numportals * sizeof(aas_portal_t))) return qfalse;
00571     if (!AAS_WriteAASLump(fp, &header, AASLUMP_PORTALINDEX, aasworld.portalindex,
00572         aasworld.portalindexsize * sizeof(aas_portalindex_t))) return qfalse;
00573     if (!AAS_WriteAASLump(fp, &header, AASLUMP_CLUSTERS, aasworld.clusters,
00574         aasworld.numclusters * sizeof(aas_cluster_t))) return qfalse;
00575     //rewrite the header with the added lumps
00576     botimport.FS_Seek(fp, 0, FS_SEEK_SET);
00577     AAS_DData((unsigned char *) &header + 8, sizeof(aas_header_t) - 8);
00578     botimport.FS_Write(&header, sizeof(aas_header_t), fp);
00579     //close the file
00580     botimport.FS_FCloseFile(fp);
00581     return qtrue;
00582 } //end of the function AAS_WriteAASFile

Generated on Thu Aug 25 12:37:09 2005 for Quake III Arena by  doxygen 1.3.9.1