/* ============== FinishPak ============== */ void FinishPak (void) { int dirlen; int d; int i; unsigned checksum; if (!g_pak) return; pakheader.id[0] = 'P'; pakheader.id[1] = 'A'; pakheader.id[2] = 'C'; pakheader.id[3] = 'K'; dirlen = (byte *)pf - (byte *)pfiles; pakheader.dirofs = LittleLong(ftell(pakfile)); pakheader.dirlen = LittleLong(dirlen); checksum = Com_BlockChecksum ( (void *)pfiles, dirlen ); SafeWrite (pakfile, pfiles, dirlen); i = ftell (pakfile); fseek (pakfile, 0, SEEK_SET); SafeWrite (pakfile, &pakheader, sizeof(pakheader)); fclose (pakfile); d = pf - pfiles; printf ("%i files packed in %i bytes\n",d, i); printf ("checksum: 0x%x\n", checksum); }
byte *bsp_read_miptexture_data(FILE *f, dheader_t *header, unsigned int *checksum) { // This is a special case, the lump contents is of variable // size. We can't use bsp_read_lump_data for this. lump_t *l; byte *data; assert(f); assert(header); l = &header->lumps[LUMP_TEXTURES]; data = (unsigned char *)malloc(l->filelen); fseek(f, l->fileofs, SEEK_SET); if (fread(data, 1, l->filelen, f) != l->filelen) { return NULL; } if (checksum) { *checksum = Com_BlockChecksum(data, l->filelen); } return data; }
/* ================= FS_LoadPackFile Takes an explicit (not game tree related) path to a pak file. Loads the header and directory, adding the files at the beginning of the list so they override previous pack files. ================= */ pack_t *FS_LoadPackFile (char *packfile) { dpackheader_t header; int i; packfile_t *newfiles; int numpackfiles; pack_t *pack; FILE *packhandle; dpackfile_t info[MAX_FILES_IN_PACK]; unsigned checksum; errno = 0; packhandle = fopen(packfile, "rb"); if (!packhandle) { Com_Printf("File Error: %s %d", packfile, errno); return NULL; } fread (&header, 1, sizeof(header), packhandle); if (LittleLong(header.ident) != IDPAKHEADER) Com_Error (ERR_FATAL, "%s is not a packfile", packfile); header.dirofs = LittleLong (header.dirofs); header.dirlen = LittleLong (header.dirlen); numpackfiles = header.dirlen / sizeof(dpackfile_t); if (numpackfiles > MAX_FILES_IN_PACK) Com_Error (ERR_FATAL, "%s has %i files", packfile, numpackfiles); newfiles = Z_Malloc (numpackfiles * sizeof(packfile_t)); fseek (packhandle, header.dirofs, SEEK_SET); fread (info, 1, header.dirlen, packhandle); // crc the directory to check for modifications checksum = Com_BlockChecksum ((void *)info, header.dirlen); #ifdef NO_ADDONS if (checksum != PAK0_CHECKSUM) return NULL; #endif // parse the directory for (i=0 ; i<numpackfiles ; i++) { strcpy (newfiles[i].name, info[i].name); newfiles[i].filepos = LittleLong(info[i].filepos); newfiles[i].filelen = LittleLong(info[i].filelen); } pack = Z_Malloc (sizeof (pack_t)); strcpy (pack->filename, packfile); pack->handle = packhandle; pack->numfiles = numpackfiles; pack->files = newfiles; Com_Printf ("Added packfile %s (%i files)\n", packfile, numpackfiles); return pack; }
void *bsp_read_lump_data(FILE *f, dheader_t *header, size_t *count, int lump_id, size_t type_size, unsigned int *checksum) { void *lump_data; lump_t *l; assert(f); assert(header); assert(count); assert(type_size > 0); assert(lump_id >= 0); l = &header->lumps[lump_id]; if (l->filelen % type_size) { fprintf(stderr, "Lump %s of size %d is not evenly divisible" " by its element size (%zu)\n", lump_names[lump_id], l->filelen, type_size); return NULL; } *count = l->filelen / type_size; if (!(lump_data = calloc(*count, type_size))) { fprintf(stderr, "Out of memory!\n"); return NULL; } fseek(f, l->fileofs, SEEK_SET); if (fread(lump_data, type_size, *count, f) != *count) { fprintf(stderr, "Failed to read entire lump %s!\n", lump_names[lump_id]); free(lump_data); *count = 0; return NULL; } if (checksum) { *checksum = Com_BlockChecksum(lump_data, l->filelen); } return lump_data; }
/* ================== Sys_FunctionCheckSum ================== */ int Sys_FunctionCheckSum(void *f1) { int i, j, l; unsigned shermcrap; byte func_end[32] = {0xC3, 0x90, 0x90, 0x00}; byte *ptr; byte *f1_ptr; ptr = (byte *) f1; if (*(byte *)ptr == 0xE9) { //Com_Printf("f1 %p1 jmp %d\n", (int *) f1, *(int*)(ptr+1)); f1_ptr = (byte*)(((byte*)f1) + (*(int *)(ptr+1)) + 5); } else { f1_ptr = ptr; } //Com_Printf("f1 ptr %p\n", f1_ptr); #ifdef _DEBUG sprintf((char *)func_end, "%c%c%c%c%c%c%c", 0x5F, 0x5E, 0x5B, 0x8B, 0xE5, 0x5D, 0xC3); #endif for (i = 0; i < 1024; i++) { for (j = 0; func_end[j]; j++) { if (f1_ptr[i+j] != func_end[j]) break; } if (!func_end[j]) { break; } } #ifdef _DEBUG l = i + 7; #else l = i + 2; #endif //Com_Printf("function length = %d\n", l); shermcrap = Com_BlockChecksum( f1_ptr, l ); return (int)shermcrap; }
/* ================= Mod_LoadBrushModel ================= */ void Mod_LoadBrushModel (model_t *mod, void *buffer) { int i, j; dheader_t *header; dmodel_t *bm; loadmodel->type = mod_brush; header = (dheader_t *)buffer; i = LittleLong (header->version); if (i != BSPVERSION) Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION); // swap all the lumps mod_base = (byte *)header; for (i=0 ; i<sizeof(dheader_t)/4 ; i++) ((int *)header)[i] = LittleLong ( ((int *)header)[i]); // checksum all of the map, except for entities mod->checksum = 0; mod->checksum2 = 0; for (i = 0; i < HEADER_LUMPS; i++) { if (i == LUMP_ENTITIES) continue; mod->checksum ^= Com_BlockChecksum(mod_base + header->lumps[i].fileofs, header->lumps[i].filelen); if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES) continue; mod->checksum2 ^= Com_BlockChecksum(mod_base + header->lumps[i].fileofs, header->lumps[i].filelen); } // load into heap Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]); Mod_LoadEdges (&header->lumps[LUMP_EDGES]); Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]); Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]); Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]); Mod_LoadPlanes (&header->lumps[LUMP_PLANES]); Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]); Mod_LoadFaces (&header->lumps[LUMP_FACES]); Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]); Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]); Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]); Mod_LoadNodes (&header->lumps[LUMP_NODES]); Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]); Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]); Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]); Mod_MakeHull0 (); mod->numframes = 2; // regular and alternate animation // // set up the submodels (FIXME: this is confusing) // for (i=0 ; i<mod->numsubmodels ; i++) { bm = &mod->submodels[i]; mod->hulls[0].firstclipnode = bm->headnode[0]; for (j=1 ; j<MAX_MAP_HULLS ; j++) { mod->hulls[j].firstclipnode = bm->headnode[j]; mod->hulls[j].lastclipnode = mod->numclipnodes-1; } mod->firstmodelsurface = bm->firstface; mod->nummodelsurfaces = bm->numfaces; VectorCopy (bm->maxs, mod->maxs); VectorCopy (bm->mins, mod->mins); mod->radius = RadiusFromBounds (mod->mins, mod->maxs); mod->numleafs = bm->visleafs; if (i < mod->numsubmodels-1) { // duplicate the basic information char name[10]; sprintf (name, "*%i", i+1); loadmodel = Mod_FindName (name); *loadmodel = *mod; strcpy (loadmodel->name, name); mod = loadmodel; } } }
pack_t *FS_LoadPackFile(char *packfile) { dpackheader_t header; int i; packfile_t *newfiles; int numpackfiles; pack_t *pack; FILE *packhandle; dpackfile_t info[MAX_FILES_IN_PACK]; unsigned checksum; unsigned contentFlags = 0; // Knightmare added int tmpPos, tmpLen; // Knightmare added #ifdef BINARY_PACK_SEARCH // Knightmare added int *sortIndices; long *sortHashes; #endif // BINARY_PACK_SEARCH packhandle = fopen(packfile, "rb"); if (!packhandle) return NULL; if (fread(&header, 1, sizeof(header), packhandle) != sizeof(header)) { // Knightmare- catch bad header Com_Printf("Failed to read header on %s\n", packfile); fclose(packhandle); return NULL; } if (LittleLong(header.ident) != IDPAKHEADER) { // Knightmare- made this not fatal // Com_Error (ERR_F/*ATAL, "%s is not a packfile", packfile); Com_Printf("%s is not a pak file\n", packfile); fclose(packhandle); return NULL; } header.dirofs = LittleLong(header.dirofs); header.dirlen = LittleLong(header.dirlen); if (header.dirlen > LONG_MAX) // || (header.dirlen % sizeof(packfile_t)) != 0 ) // Knightmare- catch bad dirlen { Com_Printf("%s has a bad directory length\n", packfile); fclose(packhandle); return NULL; } if (header.dirofs > (LONG_MAX - header.dirlen)) // Knightmare- catch bad dirofs { Com_Printf("%s has a bad directory offset\n", packfile); fclose(packhandle); return NULL; } numpackfiles = header.dirlen / sizeof(dpackfile_t); if (numpackfiles > MAX_FILES_IN_PACK) { // Knightmare- made this not fatal // Com_Error (ERR_FATAL, "%s has %i files", packfile, numpackfiles); Com_Printf("%s has too many files: %i > %i\n", packfile, numpackfiles, MAX_FILES_IN_PACK); fclose(packhandle); return NULL; } // newfiles = Z_Malloc (numpackfiles * sizeof(packfile_t)); if (fseek(packhandle, header.dirofs, SEEK_SET)) // Knightmare- catch seek failure { Com_Printf("Seeking to directory failed on %s\n", packfile); fclose(packhandle); return NULL; } if (fread(info, 1, header.dirlen, packhandle) != header.dirlen) // Knightmare- catch dir read failure { Com_Printf("Reading directory failed on %s\n", packfile); fclose(packhandle); return NULL; } // crc the directory to check for modifications checksum = Com_BlockChecksum((void *)info, header.dirlen); #ifdef NO_ADDONS if (checksum != PAK0_CHECKSUM) return NULL; #endif for (i = 0; i < numpackfiles; i++) // Knightmare- catch bad filelen / filepos { tmpPos = LittleLong(info[i].filepos); tmpLen = LittleLong(info[i].filelen); if (tmpLen > LONG_MAX || tmpPos > (LONG_MAX - tmpLen)) { Com_Printf("%s has a bad directory structure\n", packfile); fclose(packhandle); return NULL; } } newfiles = Z_Malloc(numpackfiles * sizeof(packfile_t)); // Knightmare- moved newfiles alloc here #ifdef BINARY_PACK_SEARCH // Knightmare- sorting of pak contents for binary search // create sort table sortIndices = Z_Malloc(numpackfiles * sizeof(int)); sortHashes = Z_Malloc(numpackfiles * sizeof(unsigned)); nameHashes = sortHashes; for (i = 0; i < numpackfiles; i++) { sortIndices[i] = i; sortHashes[i] = Com_HashFileName(info[i].name, 0, false); } qsort((void *)sortIndices, numpackfiles, sizeof(int), FS_PakFileCompare); // Parse the directory for (i = 0; i < numpackfiles; i++) { strcpy(newfiles[i].name, info[sortIndices[i]].name); newfiles[i].hash = sortHashes[sortIndices[i]]; newfiles[i].filepos = LittleLong(info[sortIndices[i]].filepos); newfiles[i].filelen = LittleLong(info[sortIndices[i]].filelen); newfiles[i].ignore = FS_FileInPakBlacklist(newfiles[i].name); // check against pak loading blacklist if (!newfiles[i].ignore) // add type flag for this file contentFlags |= FS_TypeFlagForPakItem(newfiles[i].name); } // free sort table Z_Free(sortIndices); Z_Free(sortHashes); nameHashes = NULL; #else // parse the directory for (i = 0; i<numpackfiles; i++) { strcpy(newfiles[i].name, info[i].name); newfiles[i].hash = Com_HashFileName(info[i].name, 0, false); // Knightmare- added to speed up seaching newfiles[i].filepos = LittleLong(info[i].filepos); newfiles[i].filelen = LittleLong(info[i].filelen); newfiles[i].ignore = FS_FileInPakBlacklist(info[i].name); // Knightmare- check against pak loading blacklist if (!newfiles[i].ignore) // Knightmare- add type flag for this file contentFlags |= FS_TypeFlagForPakItem(newfiles[i].name); } #endif // BINARY_PACK_SEARCH pack = Z_Malloc(sizeof (pack_t)); strcpy(pack->filename, packfile); pack->handle = packhandle; pack->numfiles = numpackfiles; pack->files = newfiles; pack->contentFlags = contentFlags; // Knightmare added Com_Printf("Added packfile %s (%i files)\n", packfile, numpackfiles); return pack; }
bspfile_t *LoadBspFile(const char *filename, bool clientload, unsigned *checksum) { guard(LoadBspFile); if (!stricmp(filename, bspfile.Name) && (clientload || !Cvar_VariableInt("flushmap"))) { if (checksum) *checksum = bspfile.checksum; bspfile.clientLoaded |= clientload; return &bspfile; } server_state_t ss = Com_ServerState(); if (clientload && (ss == ss_loading || ss == ss_game) && stricmp(filename, bspfile.Name) && bspfile.Name[0]) Com_DropError("client trying to load map \"%s\" while server running \"%s\"", filename, *bspfile.Name); if (bspfile.Name[0] && bspfile.file) delete bspfile.file; if (bspfile.extraChain) delete bspfile.extraChain; memset(&bspfile, 0, sizeof(bspfile)); strcpy(bspfile.Name, filename); if (!(bspfile.file = (byte*) GFileSystem->LoadFile(filename, &bspfile.length))) { bspfile.Name[0] = 0; Com_DropError("Couldn't load %s", filename); } bspfile.checksum = LittleLong(Com_BlockChecksum(bspfile.file, bspfile.length)); if (checksum) *checksum = bspfile.checksum; bspfile.extraChain = new CMemoryChain; bspfile.clientLoaded = clientload; unsigned *h = (unsigned*)bspfile.file; unsigned id1 = LittleLong(h[0]); unsigned id2 = LittleLong(h[1]); switch (id1) { case BSP_IDENT: switch (id2) { case BSP2_VERSION: LoadQ2BspFile(); return &bspfile; case BSP3_VERSION: LoadQ3BspFile(); return &bspfile; default: appPrintf(S_RED"Unknown bsp version %d\n", id2); }; break; case BSP1_VERSION: case BSPHL_VERSION: LoadQ1BspFile(); return &bspfile; } // error delete bspfile.file; memset(&bspfile, 0, sizeof(bspfile)); Com_DropError("%s has a wrong BSP header", filename); return NULL; // make compiler happy unguard; }
void LoadPCX(char *origname, byte **pic, byte **palette, int *width, int *height) { byte *raw; pcx_t *pcx; int x, y; int len, full_size; int pcx_width, pcx_height; qboolean image_issues = false; int dataByte, runLength; byte *out, *pix; char filename[256]; Q_strlcpy(filename, origname, sizeof(filename)); /* Add the extension */ if (strcmp(COM_FileExtension(filename), "pcx")) { Q_strlcat(filename, ".pcx", sizeof(filename)); } *pic = NULL; if (palette) { *palette = NULL; } /* load the file */ len = ri.FS_LoadFile(filename, (void **)&raw); if (!raw || len < sizeof(pcx_t)) { R_Printf(PRINT_DEVELOPER, "Bad pcx file %s\n", filename); return; } /* parse the PCX file */ pcx = (pcx_t *)raw; pcx->xmin = LittleShort(pcx->xmin); pcx->ymin = LittleShort(pcx->ymin); pcx->xmax = LittleShort(pcx->xmax); pcx->ymax = LittleShort(pcx->ymax); pcx->hres = LittleShort(pcx->hres); pcx->vres = LittleShort(pcx->vres); pcx->bytes_per_line = LittleShort(pcx->bytes_per_line); pcx->palette_type = LittleShort(pcx->palette_type); raw = &pcx->data; pcx_width = pcx->xmax - pcx->xmin; pcx_height = pcx->ymax - pcx->ymin; if ((pcx->manufacturer != 0x0a) || (pcx->version != 5) || (pcx->encoding != 1) || (pcx->bits_per_pixel != 8) || (pcx_width >= 4096) || (pcx_height >= 4096)) { R_Printf(PRINT_ALL, "Bad pcx file %s\n", filename); ri.FS_FreeFile(pcx); return; } full_size = (pcx_height + 1) * (pcx_width + 1); out = malloc(full_size); if (!out) { R_Printf(PRINT_ALL, "Can't allocate\n"); ri.FS_FreeFile(pcx); return; } *pic = out; pix = out; if (palette) { *palette = malloc(768); if (!(*palette)) { R_Printf(PRINT_ALL, "Can't allocate\n"); free(out); ri.FS_FreeFile(pcx); return; } if (len > 768) { memcpy(*palette, (byte *)pcx + len - 768, 768); } else { image_issues = true; } } if (width) { *width = pcx_width + 1; } if (height) { *height = pcx_height + 1; } for (y = 0; y <= pcx_height; y++, pix += pcx_width + 1) { for (x = 0; x <= pcx_width; ) { if (raw - (byte *)pcx > len) { // no place for read image_issues = true; x = pcx_width; break; } dataByte = *raw++; if ((dataByte & 0xC0) == 0xC0) { runLength = dataByte & 0x3F; if (raw - (byte *)pcx > len) { // no place for read image_issues = true; x = pcx_width; break; } dataByte = *raw++; } else { runLength = 1; } while (runLength-- > 0) { if ((*pic + full_size) <= (pix + x)) { // no place for write image_issues = true; x += runLength; runLength = 0; } else { pix[x++] = dataByte; } } } } if (raw - (byte *)pcx > len) { R_Printf(PRINT_DEVELOPER, "PCX file %s was malformed", filename); free(*pic); *pic = NULL; } else if(pcx_width == 319 && pcx_height == 239 && Q_strcasecmp(origname, "pics/quit.pcx") == 0 && Com_BlockChecksum(pcx, len) == 3329419434u) { // it's the quit screen, and the baseq2 one (identified by checksum) // so fix it fixQuitScreen(*pic); } if (image_issues) { R_Printf(PRINT_ALL, "PCX file %s has possible size issues.\n", filename); } ri.FS_FreeFile(pcx); }
/* * Loads in the map and all submodels */ cmodel_t *CM_LoadMap (char *name, qboolean clientload, unsigned *checksum) { unsigned *buf; int i; dheader_t header; int length; static unsigned last_checksum; map_noareas = Cvar_Get ("map_noareas", "0", 0); if ( !strcmp (map_name, name) && (clientload || !Cvar_VariableValue ("flushmap")) ) { *checksum = last_checksum; if (!clientload) { memset (portalopen, 0, sizeof(portalopen)); FloodAreaConnections (); } return &map_cmodels[0]; /* still have the right version */ } /* free old stuff */ numplanes = 0; numnodes = 0; numleafs = 0; numcmodels = 0; numvisibility = 0; numentitychars = 0; map_entitystring[0] = 0; map_name[0] = 0; if (!name || !name[0]) { numleafs = 1; numclusters = 1; numareas = 1; *checksum = 0; return &map_cmodels[0]; /* cinematic servers won't have anything at all */ } length = FS_LoadFile (name, (void **)&buf); if (!buf) Com_Error (ERR_DROP, "Couldn't load %s", name); last_checksum = LittleLong (Com_BlockChecksum (buf, length)); *checksum = last_checksum; header = *(dheader_t *)buf; for (i=0 ; i<sizeof(dheader_t)/4 ; i++) ((int *)&header)[i] = LittleLong ( ((int *)&header)[i]); if (header.version != BSPVERSION) Com_Error (ERR_DROP, "CMod_LoadBrushModel: %s has wrong version number (%i should be %i)" , name, header.version, BSPVERSION); cmod_base = (byte *)buf; /* load into heap */ CMod_LoadSurfaces (&header.lumps[LUMP_TEXINFO]); CMod_LoadLeafs (&header.lumps[LUMP_LEAFS]); CMod_LoadLeafBrushes (&header.lumps[LUMP_LEAFBRUSHES]); CMod_LoadPlanes (&header.lumps[LUMP_PLANES]); CMod_LoadBrushes (&header.lumps[LUMP_BRUSHES]); CMod_LoadBrushSides (&header.lumps[LUMP_BRUSHSIDES]); CMod_LoadSubmodels (&header.lumps[LUMP_MODELS]); CMod_LoadNodes (&header.lumps[LUMP_NODES]); CMod_LoadAreas (&header.lumps[LUMP_AREAS]); CMod_LoadAreaPortals (&header.lumps[LUMP_AREAPORTALS]); CMod_LoadVisibility (&header.lumps[LUMP_VISIBILITY]); CMod_LoadEntityString (&header.lumps[LUMP_ENTITIES]); FS_FreeFile (buf); CM_InitBoxHull (); memset (portalopen, 0, sizeof(portalopen)); FloodAreaConnections (); strcpy (map_name, name); return &map_cmodels[0]; }