void W_GenerateHashTable(void) { lumpindex_t i; // Free the old hash table, if there is one: if (lumphash != NULL) { Z_Free(lumphash); } // Generate hash table if (numlumps > 0) { lumphash = Z_Malloc(sizeof(lumpindex_t) * numlumps, PU_STATIC, NULL); for (i = 0; i < numlumps; ++i) { lumphash[i] = -1; } for (i = 0; i < numlumps; ++i) { unsigned int hash; hash = W_LumpNameHash(lumpinfo[i]->name) % numlumps; // Hook into the hash table lumpinfo[i]->next = lumphash[hash]; lumphash[hash] = i; } } // All done! }
// // W_CheckNumForName // Returns -1 if name not found. // lumpindex_t W_CheckNumForName(char *name) { lumpindex_t i; // Do we have a hash table yet? if (lumphash) { int hash; // We do! Excellent. hash = W_LumpNameHash(name) % numlumps; for (i = lumphash[hash]; i != -1; i = lumpinfo[i]->next) if (!strncasecmp(lumpinfo[i]->name, name, 8)) return i; } else { // We don't have a hash table generate yet. Linear search :-( // scan backwards so patch lump files take precedence for (i = numlumps - 1; i >= 0; --i) if (!strncasecmp(lumpinfo[i]->name, name, 8)) return i; } // TFB. Not found. return -1; }
void W_GenerateHashTable(void) { unsigned int i; // Free the old hash table, if there is one if (lumphash != NULL) { Z_Free(lumphash); } // Generate hash table if (numlumps > 0) { lumphash = Z_Malloc(sizeof(lumpinfo_t *) * numlumps, PU_STATIC, NULL); memset(lumphash, 0, sizeof(lumpinfo_t *) * numlumps); for (i=0; i<numlumps; ++i) { unsigned int hash; hash = W_LumpNameHash(lumpinfo[i].name) % numlumps; // Hook into the hash table lumpinfo[i].next = lumphash[hash]; lumphash[hash] = &lumpinfo[i]; } } // All done! }
// W_FindNumFromName, an iterative version of W_CheckNumForName // returns list of lump numbers for a given name (latest first) // int (W_FindNumFromName)(const char *name, int li_namespace, int i) { // Hash function maps the name to one of possibly numlump chains. // It has been tuned so that the average chain length never exceeds 2. // proff 2001/09/07 - check numlumps==0, this happens when called before WAD loaded if (numlumps == 0) i = -1; else { if (i < 0) i = lumpinfo[W_LumpNameHash(name) % (unsigned) numlumps].index; else i = lumpinfo[i].next; // We search along the chain until end, looking for case-insensitive // matches which also match a namespace tag. Separate hash tables are // not used for each namespace, because the performance benefit is not // worth the overhead, considering namespace collisions are rare in // Doom wads. while (i >= 0 && (strncasecmp(lumpinfo[i].name, name, 8) || lumpinfo[i].li_namespace != li_namespace)) i = lumpinfo[i].next; } // Return the matching lump, or -1 if none found. return i; }
static void GenerateTextureHashTable(void) { texture_t **rover; int i; int key; textures_hashtable = (texture_t **)Z_Malloc(sizeof(texture_t *) * numtextures, PU_STATIC, 0); memset(textures_hashtable, 0, sizeof(texture_t *) * numtextures); // Add all textures to hash table for (i = 0; i < numtextures; ++i) { // Store index textures[i]->index = i; // Vanilla Doom does a linear search of the texures array // and stops at the first entry it finds. If there are two // entries with the same name, the first one in the array // wins. The new entry must therefore be added at the end // of the hash chain, so that earlier entries win. key = W_LumpNameHash(textures[i]->name) % numtextures; rover = &textures_hashtable[key]; while (*rover != NULL) rover = &(*rover)->next; // Hook into hash table textures[i]->next = NULL; *rover = textures[i]; } }
static void GenerateTextureHashTable(void) { int i; int key; textures_hashtable = Z_Malloc(sizeof(texture_t *) * numtextures, PU_STATIC, 0); memset(textures_hashtable, 0, sizeof(texture_t *) * numtextures); // Add all textures to hash table for (i=0; i<numtextures; ++i) { // Store index textures[i]->index = i; // Hook into hash table key = W_LumpNameHash(textures[i]->name) % numtextures; textures[i]->next = textures_hashtable[key]; textures_hashtable[key] = textures[i]; } }
int R_CheckFlatNumForName (const char* name) { int i; i = flatinfo[W_LumpNameHash(name) % (unsigned int)numflats].index; while (i >= 0 && strncasecmp(flatinfo[i].name, name, 8)) i = flatinfo[i].next; return i; }
// // W_CheckNumForName // Returns -1 if name not found. // // Rewritten by Lee Killough for Boom, to use hash table for performance. // int W_CheckNumForName(char *name) { register int i; i = lumpinfo[W_LumpNameHash(name) % (unsigned)numlumps].index; while (i >= 0 && strncasecmp(lumpinfo[i].name, name, 8)) i = lumpinfo[i].next; return i; }
int PUREFUNC R_CheckTextureNumForName(const char *name) { int i = NO_TEXTURE; if (*name != '-') // "NoTexture" marker. { i = textures[W_LumpNameHash(name) % (unsigned) numtextures]->index; while (i >= 0 && strncasecmp(textures[i]->name,name,8)) i = textures[i]->next; } return i; }
// // R_CheckTextureNumForName // Check whether texture is available. // Filter out NoTexture indicator. // int R_CheckTextureNumForName (const char *name) { int i = 0; //NO_TEXTURE; if (*name != '-') { i = textures[W_LumpNameHash(name) % (unsigned int)numtextures]->index; while (i >= 0 && strncasecmp(textures[i]->name, name, 8)) i = textures[i]->next; } return i; }
// // R_InitTextures // Initializes the texture list // with the textures from the world map. // static void R_InitTextures (void) { int i; textures = NULL; textureheight = NULL; numtextures = 0; R_MergeTextures (); textures = Z_Realloc (textures, numtextures * sizeof(*textures), PU_STATIC, 0); textureheight = Z_Realloc (textureheight, numtextures * sizeof(*textureheight), PU_STATIC, 0); // Create translation table for global animation. // killough 4/9/98: make column offsets 32-bit; // clean up malloc-ing to use sizeof texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, 0); for (i = 0; i < numtextures; ++i) texturetranslation[i] = i; while (--i >= 0) { int j; j = W_LumpNameHash(textures[i]->name) % (unsigned int)numtextures; textures[i]->next = textures[j]->index; // Prepend to chain textures[j]->index = i; } #if 0 // [BH] Initialize partially fullbright textures. texturefullbright = Z_Malloc(numtextures * sizeof(*texturefullbright), PU_STATIC, 0); memset(texturefullbright, 0, numtextures * sizeof(*texturefullbright)); if (r_brightmaps) { i = 0; while (fullbright[i].colormask) { if (fullbright[i].texture) { int num = R_CheckTextureNumForName(fullbright[i].texture); if (num != -1) texturefullbright[num] = fullbright[i].colormask; i++; } } } #endif }
// // Initialize the lump hash chains // void W_InitLumpHash(void) { int i; for (i = 0; i < numlumps; i++) lumpinfo[i].index = -1; for (i = 0; i < numlumps; i++) { int j = W_LumpNameHash(lumpinfo[i].name) % (unsigned)numlumps; lumpinfo[i].next = lumpinfo[j].index; lumpinfo[j].index = i; } }
// // W_HashLumps // // killough 1/31/98: Initialize lump hash table // [SL] taken from prboom-plus // void W_HashLumps(void) { for (unsigned int i = 0; i < numlumps; i++) lumpinfo[i].index = -1; // mark slots empty // Insert nodes to the beginning of each chain, in first-to-last // lump order, so that the last lump of a given name appears first // in any chain, observing pwad ordering rules. killough for (unsigned int i = 0; i < numlumps; i++) { unsigned int j = W_LumpNameHash(lumpinfo[i].name) % (unsigned int)numlumps; lumpinfo[i].next = lumpinfo[j].index; // Prepend to list lumpinfo[j].index = i; } }
int W_CheckNumForName (char* name) { lumpinfo_t *lump_p; int i; // Do we have a hash table yet? if (lumphash != NULL) { int hash; // We do! Excellent. hash = W_LumpNameHash(name) % numlumps; for (lump_p = lumphash[hash]; lump_p != NULL; lump_p = lump_p->next) { if (!strncasecmp(lump_p->name, name, 8)) { return lump_p - lumpinfo; } } } else { // We don't have a hash table generate yet. Linear search :-( // // scan backwards so patch lump files take precedence for (i=numlumps-1; i >= 0; --i) { if (!strncasecmp(lumpinfo[i].name, name, 8)) { return i; } } } // TFB. Not found. return -1; }
// // W_CheckNumForName // Returns -1 if name not found. // // Rewritten by Lee Killough to use hash table for performance. Significantly // cuts down on time -- increases Doom performance over 300%. This is the // single most important optimization of the original Doom sources, because // lump name lookup is used so often, and the original Doom used a sequential // search. For large wads with > 1000 lumps this meant an average of over // 500 were probed during every search. Now the average is under 2 probes per // search. There is no significant benefit to packing the names into longwords // with this new hashing algorithm, because the work to do the packing is // just as much work as simply doing the string comparisons with the new // algorithm, which minimizes the expected number of comparisons to under 2. // // [SL] taken from prboom-plus // int W_CheckNumForName(const char *name, int namespc) { // Hash function maps the name to one of possibly numlump chains. // It has been tuned so that the average chain length never exceeds 2. // proff 2001/09/07 - check numlumps==0, this happens when called before WAD loaded register int i = (numlumps==0)?(-1):(lumpinfo[W_LumpNameHash(name) % numlumps].index); // We search along the chain until end, looking for case-insensitive // matches which also match a namespace tag. Separate hash tables are // not used for each namespace, because the performance benefit is not // worth the overhead, considering namespace collisions are rare in // Doom wads. while (i >= 0 && (strnicmp(lumpinfo[i].name, name, 8) || lumpinfo[i].namespc != namespc)) i = lumpinfo[i].next; // Return the matching lump, or -1 if none found. return i; }
// // R_CheckTextureNumForName // Check whether texture is available. // Filter out NoTexture indicator. // int R_CheckTextureNumForName (char *name) { texture_t *texture; int key; // "NoTexture" marker. if (name[0] == '-') return 0; key = W_LumpNameHash(name) % numtextures; texture=textures_hashtable[key]; while (texture != NULL) { if (!strncasecmp (texture->name, name, 8) ) return texture->index; texture = texture->next; } return -1; }
// // R_InitFlats // static void R_InitFlats (void) { int i; unsigned int lump; unsigned int loading; lumpinfo_t* lump_ptr; flatinfo_t* flatinfo_ptr; numflats = R_CountEntities ("F_START", "F_END", 0); // Create translation table for global animation. flatinfo = Z_Calloc ((numflats+1)*sizeof(*flatinfo), PU_STATIC, 0); i = 0; lump = 0; loading = 0; lump_ptr = lumpinfo; flatinfo_ptr = flatinfo; do { if (loading == 0) { if (strncasecmp (lump_ptr->name, "F_START", 8) == 0) loading = 1; } else if ((strncasecmp (lump_ptr->name, "F_END", 8) == 0) || (lump_ptr->handle != (lump_ptr-1)->handle)) { loading = 0; } else if ((lump_ptr->name[0])) #ifdef MIN_SIZE_LUMP && (lump_ptr->size >= MIN_SIZE_LUMP) #endif { if (!(i&63)) putchar ('.'); if (i < numflats) { memcpy (flatinfo_ptr->name, lump_ptr->name, sizeof (flatinfo_ptr->name)); flatinfo_ptr->lump = lump; flatinfo_ptr->translation = i; flatinfo_ptr->index = -1; memset (lump_ptr -> name, 0, sizeof (lump_ptr -> name)); flatinfo_ptr++; } i++; } lump_ptr++; } while (++lump < numlumps); if (numflats != i) { printf ("\nnumflats = %u, found = %u\n", numflats, i); if (i < numflats) numflats = i; } while (--i >= 0) { int j; j = W_LumpNameHash(flatinfo[i].name) % (unsigned int)numflats; flatinfo[i].next = flatinfo[j].index; // Prepend to chain flatinfo[j].index = i; } }
static void R_InitTextures (void) { const maptexture_t *mtexture; texture_t *texture; const mappatch_t *mpatch; texpatch_t *patch; int i, j; int maptex_lump[2] = {-1, -1}; const int *maptex; const int *maptex1, *maptex2; char name[9]; int names_lump; // cph - new wad lump handling const char *names; // cph - const char *name_p;// const*'s int *patchlookup; int nummappatches; int offset; int maxoff, maxoff2; int numtextures1, numtextures2; const int *directory; int errors = 0; // Load the patch names from pnames.lmp. name[8] = 0; names = W_CacheLumpNum(names_lump = W_GetNumForName("PNAMES")); nummappatches = LittleLong(*((const int *)names)); name_p = names+4; patchlookup = malloc(nummappatches*sizeof(*patchlookup)); // killough for (i=0 ; i<nummappatches ; i++) { strncpy (name,name_p+i*8, 8); patchlookup[i] = W_CheckNumForName(name); if (patchlookup[i] == -1) { // killough 4/17/98: // Some wads use sprites as wall patches, so repeat check and // look for sprites this time, but only if there were no wall // patches found. This is the same as allowing for both, except // that wall patches always win over sprites, even when they // appear first in a wad. This is a kludgy solution to the wad // lump namespace problem. patchlookup[i] = (W_CheckNumForName)(name, ns_sprites); if (patchlookup[i] == -1 && devparm) //jff 8/3/98 use logical output routine lprintf(LO_WARN,"\nWarning: patch %.8s, index %d does not exist",name,i); } } W_UnlockLumpNum(names_lump); // cph - release the lump // Load the map texture definitions from textures.lmp. // The data is contained in one or two lumps, // TEXTURE1 for shareware, plus TEXTURE2 for commercial. maptex = maptex1 = W_CacheLumpNum(maptex_lump[0] = W_GetNumForName("TEXTURE1")); numtextures1 = LittleLong(*maptex); maxoff = W_LumpLength(maptex_lump[0]); directory = maptex+1; if (W_CheckNumForName("TEXTURE2") != -1) { maptex2 = W_CacheLumpNum(maptex_lump[1] = W_GetNumForName("TEXTURE2")); numtextures2 = LittleLong(*maptex2); maxoff2 = W_LumpLength(maptex_lump[1]); } else { maptex2 = NULL; numtextures2 = 0; maxoff2 = 0; } numtextures = numtextures1 + numtextures2; // killough 4/9/98: make column offsets 32-bit; // clean up malloc-ing to use sizeof textures = Z_Malloc(numtextures*sizeof*textures, PU_STATIC, 0); textureheight = Z_Malloc(numtextures*sizeof*textureheight, PU_STATIC, 0); for (i=0 ; i<numtextures ; i++, directory++) { if (i == numtextures1) { // Start looking in second texture file. maptex = maptex2; maxoff = maxoff2; directory = maptex+1; } offset = LittleLong(*directory); if (offset > maxoff) I_Error("R_InitTextures: Bad texture directory"); mtexture = (const maptexture_t *) ( (const byte *)maptex + offset); texture = textures[i] = Z_Malloc(sizeof(texture_t) + sizeof(texpatch_t)*(LittleShort(mtexture->patchcount)-1), PU_STATIC, 0); texture->width = LittleShort(mtexture->width); texture->height = LittleShort(mtexture->height); texture->patchcount = LittleShort(mtexture->patchcount); /* Mattias Engdegård emailed me of the following explenation of * why memcpy doesnt work on some systems: * "I suppose it is the mad unaligned allocation * going on (and which gcc in some way manages to cope with * through the __attribute__ ((packed))), and which it forgets * when optimizing memcpy (to a single word move) since it appears * to be aligned. Technically a gcc bug, but I can't blame it when * it's stressed with that amount of * non-standard nonsense." * So in short the unaligned struct confuses gcc's optimizer so * i took the memcpy out alltogether to avoid future problems-Jess */ /* The above was #ifndef SPARC, but i got a mail from * Putera Joseph F NPRI <*****@*****.**> containing: * I had to use the memcpy function on a sparc machine. The * other one would give me a core dump. * cph - I find it hard to believe that sparc memcpy is broken, * but I don't believe the pointers to memcpy have to be aligned * either. Use fast memcpy on other machines anyway. */ /* proff - I took this out, because Oli Kraus ([email protected]) told me the memcpy produced a buserror. Since this function isn't time- critical I'm using the for loop now. */ /* #ifndef GCC memcpy(texture->name, mtexture->name, sizeof(texture->name)); #else */ { size_t j; for(j=0;j<sizeof(texture->name);j++) texture->name[j]=mtexture->name[j]; } /* #endif */ mpatch = mtexture->patches; patch = texture->patches; for (j=0 ; j<texture->patchcount ; j++, mpatch++, patch++) { patch->originx = LittleShort(mpatch->originx); patch->originy = LittleShort(mpatch->originy); patch->patch = patchlookup[LittleShort(mpatch->patch)]; if (patch->patch == -1) { //jff 8/3/98 use logical output routine lprintf(LO_ERROR,"\nR_InitTextures: Missing patch %d in texture %.8s", LittleShort(mpatch->patch), texture->name); // killough 4/17/98 ++errors; } } for (j=1; j*2 <= texture->width; j<<=1) ; texture->widthmask = j-1; textureheight[i] = texture->height<<FRACBITS; } free(patchlookup); // killough for (i=0; i<2; i++) // cph - release the TEXTUREx lumps if (maptex_lump[i] != -1) W_UnlockLumpNum(maptex_lump[i]); if (errors) { const lumpinfo_t* info = W_GetLumpInfoByNum(names_lump); wadfile_info_t *wf = M_CBufGet(&resource_files_buf, info->wadfile); if (wf == NULL) { I_Error( "R_InitTextures: Bad wadfile for %s (%d)\n", info->name, info->wadfile ); } lprintf(LO_INFO, "\nR_InitTextures: The file %s seems to be incompatible with \"%s\".\n", wf->name, (doomverstr ? doomverstr : "DOOM")); I_Error("R_InitTextures: %d errors", errors); } // Precalculate whatever possible. if (devparm) // cph - If in development mode, generate now so all errors are found at once { R_InitPatches(); //e6y for (i=0 ; i<numtextures ; i++) { // proff - This is for the new renderer now R_CacheTextureCompositePatchNum(i); R_UnlockTextureCompositePatchNum(i); } } if (errors) I_Error("R_InitTextures: %d errors", errors); // Create translation table for global animation. // killough 4/9/98: make column offsets 32-bit; // clean up malloc-ing to use sizeof texturetranslation = Z_Malloc((numtextures+1)*sizeof*texturetranslation, PU_STATIC, 0); for (i=0 ; i<numtextures ; i++) texturetranslation[i] = i; // killough 1/31/98: Initialize texture hash table for (i = 0; i<numtextures; i++) textures[i]->index = -1; while (--i >= 0) { int j = W_LumpNameHash(textures[i]->name) % (unsigned) numtextures; textures[i]->next = textures[j]->index; // Prepend to chain textures[j]->index = i; } }
// // R_InitTextures // Initializes the texture list // with the textures from the world map. // void R_InitTextures(void) { const maptexture_t *mtexture; texture_t *texture; int i, j; int maptex_lump[2] = { -1, -1 }; const int *maptex1; const int *maptex2; char name[9]; int names_lump; // cph - new wad lump handling const char *names; // cph - const char *name_p;// const*'s int *patchlookup; int nummappatches; int maxoff, maxoff2; int numtextures1, numtextures2; const int *directory; // Load the patch names from pnames.lmp. name[8] = '\0'; names = W_CacheLumpNum(names_lump = W_GetNumForName("PNAMES"), PU_STATIC); nummappatches = LONG(*((const int *)names)); name_p = names + 4; patchlookup = malloc(nummappatches * sizeof(*patchlookup)); // killough for (i = 0; i < nummappatches; i++) { strncpy(name, name_p + i * 8, 8); patchlookup[i] = W_CheckNumForName(name); } W_ReleaseLumpNum(names_lump); // cph - release the lump // Load the map texture definitions from textures.lmp. // The data is contained in one or two lumps, // TEXTURE1 for shareware, plus TEXTURE2 for commercial. maptex_lump[0] = W_GetNumForName("TEXTURE1"); maptex1 = W_CacheLumpNum(maptex_lump[0], PU_STATIC); numtextures1 = LONG(*maptex1); maxoff = W_LumpLength(maptex_lump[0]); directory = maptex1 + 1; if (W_CheckNumForName("TEXTURE2") != -1) { maptex_lump[1] = W_GetNumForName("TEXTURE2"); maptex2 = W_CacheLumpNum(maptex_lump[1], PU_STATIC); numtextures2 = LONG(*maptex2); maxoff2 = W_LumpLength(maptex_lump[1]); } else { maptex2 = NULL; numtextures2 = 0; maxoff2 = 0; } numtextures = numtextures1 + numtextures2; // killough 4/9/98: make column offsets 32-bit; // clean up malloc-ing to use sizeof textures = Z_Malloc(numtextures * sizeof(*textures), PU_STATIC, 0); textureheight = Z_Malloc(numtextures * sizeof(*textureheight), PU_STATIC, 0); for (i = 0; i < numtextures; ++i, ++directory) { const mappatch_t *mpatch; texpatch_t *patch; int offset; if (i == numtextures1) { // Start looking in second texture file. maptex1 = maptex2; maxoff = maxoff2; directory = maptex1 + 1; } offset = LONG(*directory); if (offset > maxoff) I_Error("R_InitTextures: Bad texture directory"); mtexture = (const maptexture_t *)((const byte *)maptex1 + offset); texture = textures[i] = Z_Malloc(sizeof(texture_t) + sizeof(texpatch_t) * (SHORT(mtexture->patchcount) - 1), PU_STATIC, 0); texture->width = SHORT(mtexture->width); texture->height = SHORT(mtexture->height); texture->patchcount = SHORT(mtexture->patchcount); { size_t j; for (j = 0; j < sizeof(texture->name); ++j) texture->name[j] = mtexture->name[j]; } mpatch = mtexture->patches; patch = texture->patches; for (j = 0; j < texture->patchcount; ++j, ++mpatch, ++patch) { patch->originx = SHORT(mpatch->originx); patch->originy = SHORT(mpatch->originy); patch->patch = patchlookup[SHORT(mpatch->patch)]; if (patch->patch == -1) C_Warning("Patch %d is missing in the %.8s texture.", SHORT(mpatch->patch), texture->name); // killough 4/17/98 } for (j = 1; j * 2 <= texture->width; j <<= 1); texture->widthmask = j - 1; textureheight[i] = texture->height << FRACBITS; } free(patchlookup); // killough for (i = 0; i < 2; ++i) // cph - release the TEXTUREx lumps if (maptex_lump[i] != -1) W_ReleaseLumpNum(maptex_lump[i]); // Create translation table for global animation. // killough 4/9/98: make column offsets 32-bit; // clean up malloc-ing to use sizeof texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, 0); for (i = 0; i < numtextures; ++i) texturetranslation[i] = i; // killough 1/31/98: Initialize texture hash table for (i = 0; i < numtextures; ++i) textures[i]->index = -1; while (--i >= 0) { int j = W_LumpNameHash(textures[i]->name) % (unsigned int)numtextures; textures[i]->next = textures[j]->index; // Prepend to chain textures[j]->index = i; } // [BH] Initialize partially fullbright textures. texturefullbright = Z_Malloc(numtextures * sizeof(*texturefullbright), PU_STATIC, 0); memset(texturefullbright, 0, numtextures * sizeof(*texturefullbright)); if (r_brightmaps) { i = 0; while (fullbright[i].colormask) { if (fullbright[i].texture) { int num = R_CheckTextureNumForName(fullbright[i].texture); if (num != -1) texturefullbright[num] = fullbright[i].colormask; i++; } } } }