// // TextureManger::cachePatch // void TextureManager::cachePatch(texhandle_t handle) { unsigned int lumpnum = handle & ~(PATCH_HANDLE_MASK | SPRITE_HANDLE_MASK); unsigned int lumplen = W_LumpLength(lumpnum); byte* lumpdata = new byte[lumplen]; W_ReadLump(lumpnum, lumpdata); int width = LESHORT(*(short*)(lumpdata + 0)); int height = LESHORT(*(short*)(lumpdata + 2)); int offsetx = LESHORT(*(short*)(lumpdata + 4)); int offsety = LESHORT(*(short*)(lumpdata + 6)); Texture* texture = createTexture(handle, width, height); texture->mOffsetX = offsetx; texture->mOffsetY = offsety; if (clientside) { // TODO: remove this once proper masking is in place memset(texture->mData, 0, width * height); // initialize the mask to entirely transparent memset(texture->mMask, 0, width * height); R_DrawPatchIntoTexture(texture, lumpdata, 0, 0); texture->mHasMask = (memchr(texture->mMask, 0, width * height) != NULL); } delete [] lumpdata; }
bool NetDemo::writeHeader() { strncpy(header.identifier, "ODAD", 4); header.version = NETDEMOVER; header.compression = 0; header.snapshot_spacing = NetDemo::SNAPSHOT_SPACING; netdemo_header_t tmpheader; memcpy(&tmpheader, &header, sizeof(header)); // convert from native byte ordering to little-endian tmpheader.snapshot_index_size = LESHORT(tmpheader.snapshot_index_size); tmpheader.snapshot_index_offset = LELONG(tmpheader.snapshot_index_offset); tmpheader.map_index_size = LESHORT(tmpheader.map_index_size); tmpheader.map_index_offset = LELONG(tmpheader.map_index_offset); tmpheader.snapshot_spacing = LESHORT(tmpheader.snapshot_spacing); tmpheader.starting_gametic = LELONG(tmpheader.starting_gametic); tmpheader.ending_gametic = LELONG(tmpheader.ending_gametic); fseek(demofp, 0, SEEK_SET); size_t cnt = 0; cnt += sizeof(tmpheader.identifier) * fwrite(&tmpheader.identifier, sizeof(tmpheader.identifier), 1, demofp); cnt += sizeof(tmpheader.version) * fwrite(&tmpheader.version, sizeof(tmpheader.version), 1, demofp); cnt += sizeof(tmpheader.compression) * fwrite(&tmpheader.compression, sizeof(tmpheader.compression), 1, demofp); cnt += sizeof(tmpheader.snapshot_index_size) * fwrite(&tmpheader.snapshot_index_size, sizeof(tmpheader.snapshot_index_size), 1, demofp); cnt += sizeof(tmpheader.snapshot_index_offset)* fwrite(&tmpheader.snapshot_index_offset, sizeof(tmpheader.snapshot_index_offset), 1, demofp); cnt += sizeof(tmpheader.map_index_size) * fwrite(&tmpheader.map_index_size, sizeof(tmpheader.map_index_size), 1, demofp); cnt += sizeof(tmpheader.map_index_offset)* fwrite(&tmpheader.map_index_offset, sizeof(tmpheader.map_index_offset), 1, demofp); cnt += sizeof(tmpheader.snapshot_spacing) * fwrite(&tmpheader.snapshot_spacing, sizeof(tmpheader.snapshot_spacing), 1, demofp); cnt += sizeof(tmpheader.starting_gametic) * fwrite(&tmpheader.starting_gametic, sizeof(tmpheader.starting_gametic), 1, demofp); cnt += sizeof(tmpheader.ending_gametic) * fwrite(&tmpheader.ending_gametic, sizeof(tmpheader.ending_gametic), 1, demofp); cnt += sizeof(tmpheader.reserved) * fwrite(&tmpheader.reserved, sizeof(tmpheader.reserved), 1, demofp); if (cnt < NetDemo::HEADER_SIZE) return false; return true; }
// Find a string by name int FStringTable::FindString (const char *name) const { if (Names == NULL) { LoadNames (); } const WORD *nameOfs = (WORD *)Names; const char *nameBase = (char *)Names + NumStrings*4; int min = 0; int max = NumStrings-1; while (min <= max) { const int mid = (min + max) / 2; const char *const tablename = LESHORT(nameOfs[mid*2]) + nameBase; const int lex = stricmp (name, tablename); if (lex == 0) return nameOfs[mid*2+1]; else if (lex < 0) max = mid - 1; else min = mid + 1; } return -1; }
void FStringTable::LoadNames () const { BYTE *lump = (BYTE *)W_CacheLumpNum (LumpNum, PU_CACHE); int nameLen = LESHORT(((Header *)lump)->NameLen); FlushNames (); Names = new BYTE[nameLen + 4*NumStrings]; memcpy (Names, lump + sizeof(Header), nameLen + 4*NumStrings); }
bool NetDemo::readHeader() { fseek(demofp, 0, SEEK_SET); size_t cnt = 0; cnt += sizeof(header.identifier) * fread(&header.identifier, sizeof(header.identifier), 1, demofp); cnt += sizeof(header.version) * fread(&header.version, sizeof(header.version), 1, demofp); cnt += sizeof(header.compression) * fread(&header.compression, sizeof(header.compression), 1, demofp); cnt += sizeof(header.snapshot_index_size) * fread(&header.snapshot_index_size, sizeof(header.snapshot_index_size), 1, demofp); cnt += sizeof(header.snapshot_index_offset)* fread(&header.snapshot_index_offset, sizeof(header.snapshot_index_offset), 1, demofp); cnt += sizeof(header.map_index_size) * fread(&header.map_index_size, sizeof(header.map_index_size), 1, demofp); cnt += sizeof(header.map_index_offset)* fread(&header.map_index_offset, sizeof(header.map_index_offset), 1, demofp); cnt += sizeof(header.snapshot_spacing) * fread(&header.snapshot_spacing, sizeof(header.snapshot_spacing), 1, demofp); cnt += sizeof(header.starting_gametic) * fread(&header.starting_gametic, sizeof(header.starting_gametic), 1, demofp); cnt += sizeof(header.ending_gametic) * fread(&header.ending_gametic, sizeof(header.ending_gametic), 1, demofp); cnt += sizeof(header.reserved) * fread(&header.reserved, sizeof(header.reserved), 1, demofp); if (cnt < NetDemo::HEADER_SIZE) return false; // convert from little-endian to native byte ordering header.snapshot_index_size = LESHORT(header.snapshot_index_size); header.snapshot_index_offset = LELONG(header.snapshot_index_offset); header.map_index_size = LESHORT(header.map_index_size); header.map_index_offset = LELONG(header.map_index_offset); header.snapshot_spacing = LESHORT(header.snapshot_spacing); header.starting_gametic = LELONG(header.starting_gametic); header.ending_gametic = LELONG(header.ending_gametic); return true; }
// // R_DrawPatchIntoTexture // // Draws a lump in patch_t format into a Texture at the given offset. // static void R_DrawPatchIntoTexture(Texture* texture, const byte* lumpdata, int xoffs, int yoffs) { int texwidth = texture->getWidth(); int texheight = texture->getHeight(); int patchwidth = LESHORT(*(short*)(lumpdata + 0)); const int* colofs = (int*)(lumpdata + 8); int x1 = MAX(xoffs, 0); int x2 = MIN(xoffs + patchwidth - 1, texwidth - 1); for (int x = x1; x <= x2; x++) { int abstopdelta = 0; const byte* post = lumpdata + LELONG(colofs[x - xoffs]); while (*post != 0xFF) { int posttopdelta = *(post + 0); int postlength = *(post + 1); // handle DeePsea tall patches where topdelta is treated as a relative // offset instead of an absolute offset if (posttopdelta <= abstopdelta) abstopdelta += posttopdelta; else abstopdelta = posttopdelta; int topoffset = yoffs + abstopdelta; int y1 = MAX(topoffset, 0); int y2 = MIN(topoffset + postlength - 1, texheight - 1); if (y1 <= y2) { byte* dest = texture->getData() + texheight * x + y1; const byte* source = post + 3; memcpy(dest, source, y2 - y1 + 1); // set up the mask byte* mask = texture->getMaskData() + texheight * x + y1; memset(mask, 1, y2 - y1 + 1); } post += postlength + 4; } } }
// // R_InitTextures // Initializes the texture list // with the textures from the world map. // void R_InitTextures (void) { maptexture_t* mtexture; texture_t* texture; mappatch_t* mpatch; texpatch_t* patch; int i; int j; int* maptex; int* maptex2; int* maptex1; int* patchlookup; int totalwidth; int nummappatches; int offset; int maxoff; int maxoff2; int numtextures1; int numtextures2; int* directory; int errors = 0; // Load the patch names from pnames.lmp. { char *names = (char *)W_CacheLumpName ("PNAMES", PU_STATIC); char *name_p = names+4; nummappatches = LELONG ( *((int *)names) ); patchlookup = new int[nummappatches]; for (i = 0; i < nummappatches; i++) { patchlookup[i] = W_CheckNumForName (name_p + i*8); 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_p + i*8, ns_sprites); } } Z_Free (names); } // 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 = (int *)W_CacheLumpName ("TEXTURE1", PU_STATIC); numtextures1 = LELONG(*maptex); maxoff = W_LumpLength (W_GetNumForName ("TEXTURE1")); directory = maptex+1; if (W_CheckNumForName ("TEXTURE2") != -1) { maptex2 = (int *)W_CacheLumpName ("TEXTURE2", PU_STATIC); numtextures2 = LELONG(*maptex2); maxoff2 = W_LumpLength (W_GetNumForName ("TEXTURE2")); } else { maptex2 = NULL; numtextures2 = 0; maxoff2 = 0; } // denis - fix memory leaks for (i = 0; i < numtextures; i++) { delete[] texturecolumnlump[i]; delete[] texturecolumnofs[i]; } // denis - fix memory leaks delete[] textures; delete[] texturecolumnlump; delete[] texturecolumnofs; delete[] texturecomposite; delete[] texturecompositesize; delete[] texturewidthmask; delete[] textureheight; delete[] texturescalex; delete[] texturescaley; numtextures = numtextures1 + numtextures2; textures = new texture_t *[numtextures]; texturecolumnlump = new short *[numtextures]; texturecolumnofs = new unsigned int *[numtextures]; texturecomposite = new byte *[numtextures]; texturecompositesize = new int[numtextures]; texturewidthmask = new int[numtextures]; textureheight = new fixed_t[numtextures]; texturescalex = new fixed_t[numtextures]; texturescaley = new fixed_t[numtextures]; totalwidth = 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 = LELONG(*directory); if (offset > maxoff) I_FatalError ("R_InitTextures: bad texture directory"); mtexture = (maptexture_t *) ( (byte *)maptex + offset); texture = textures[i] = (texture_t *) Z_Malloc (sizeof(texture_t) + sizeof(texpatch_t)*(SAFESHORT(mtexture->patchcount)-1), PU_STATIC, 0); texture->width = SAFESHORT(mtexture->width); texture->height = SAFESHORT(mtexture->height); texture->patchcount = SAFESHORT(mtexture->patchcount); strncpy (texture->name, mtexture->name, 9); // denis - todo string limit? std::transform(texture->name, texture->name + strlen(texture->name), texture->name, toupper); mpatch = &mtexture->patches[0]; patch = &texture->patches[0]; for (j=0 ; j<texture->patchcount ; j++, mpatch++, patch++) { patch->originx = LESHORT(mpatch->originx); patch->originy = LESHORT(mpatch->originy); patch->patch = patchlookup[LESHORT(mpatch->patch)]; if (patch->patch == -1) { Printf (PRINT_HIGH, "R_InitTextures: Missing patch in texture %s\n", texture->name); errors++; } } texturecolumnlump[i] = new short[texture->width]; texturecolumnofs[i] = new unsigned int[texture->width]; for (j = 1; j*2 <= texture->width; j <<= 1) ; texturewidthmask[i] = j-1; textureheight[i] = texture->height << FRACBITS; // [RH] Special for beta 29: Values of 0 will use the tx/ty cvars // to determine scaling instead of defaulting to 8. I will likely // remove this once I finish the betas, because by then, users // should be able to actually create scaled textures. texturescalex[i] = mtexture->scalex ? mtexture->scalex << (FRACBITS - 3) : FRACUNIT; texturescaley[i] = mtexture->scaley ? mtexture->scaley << (FRACBITS - 3) : FRACUNIT; totalwidth += texture->width; } delete[] patchlookup; Z_Free (maptex1); if (maptex2) Z_Free (maptex2); if (errors) I_FatalError ("%d errors in R_InitTextures.", errors); // [RH] Setup hash chains. Go from back to front so that if // duplicates are found, the first one gets used instead // of the last (thus mimicing the original behavior // of R_CheckTextureNumForName(). for (i = 0; i < numtextures; i++) textures[i]->index = -1; for (i = numtextures - 1; i >= 0; i--) { j = 0; //W_LumpNameHash (textures[i]->name) % (unsigned) numtextures; textures[i]->next = textures[j]->index; textures[j]->index = i; } if (clientside) // server doesn't need to load patches ever { // Precalculate whatever possible. for (i = 0; i < numtextures; i++) R_GenerateLookup (i, &errors); } // if (errors) // I_FatalError ("%d errors encountered during texture generation.", errors); // Create translation table for global animation. delete[] texturetranslation; texturetranslation = new int[numtextures+1]; for (i = 0; i < numtextures; i++) texturetranslation[i] = i; }
void FStringTable::LoadStrings (int lump, int expectedSize, bool enuOnly) { BYTE *strData = (BYTE *)W_CacheLumpNum (lump, PU_CACHE); int lumpLen = LELONG(((Header *)strData)->FileSize); int nameCount = LESHORT(((Header *)strData)->NameCount); int nameLen = LESHORT(((Header *)strData)->NameLen); int languageStart = sizeof(Header) + nameCount*4 + nameLen; languageStart += (4 - languageStart) & 3; if (expectedSize >= 0 && nameCount != expectedSize) { char name[9]; W_GetLumpName (name, lump); name[8] = 0; I_FatalError ("%s had %d strings.\nThis version of ZDoom expects it to have %d.", name, nameCount, expectedSize); } FreeStandardStrings (); NumStrings = nameCount; LumpNum = lump; if (Strings == NULL) { Strings = new char *[nameCount]; StringStatus = new BYTE[(nameCount+7)/8]; memset (StringStatus, 0, (nameCount+7)/8); // 0 means: from wad (standard) memset (Strings, 0, sizeof(char *)*nameCount); } BYTE *const start = strData + languageStart; BYTE *const end = strData + lumpLen; int loadedCount, i; for (loadedCount = i = 0; i < NumStrings; ++i) { if (Strings[i] != NULL) { ++loadedCount; } } if (!enuOnly) { for (i = 0; i < 4 && loadedCount != nameCount; ++i) { loadedCount += LoadLanguage (LanguageIDs[i], true, start, end); loadedCount += LoadLanguage (LanguageIDs[i] & MAKE_ID(0xff,0xff,0,0), true, start, end); loadedCount += LoadLanguage (LanguageIDs[i], false, start, end); } } // Fill in any missing strings with the default language (enu) if (loadedCount != nameCount) { loadedCount += LoadLanguage (MAKE_ID('e','n','u',0), true, start, end); } DoneLoading (start, end); if (loadedCount != nameCount) { I_FatalError ("Loaded %d strings (expected %d)", loadedCount, nameCount); } }
void P_TranslateLineDef (line_t *ld, maplinedef_t *mld) { short special = LESHORT(mld->special); short tag = LESHORT(mld->tag); short flags = LESHORT(mld->flags); bool passthrough = (flags & ML_PASSUSE_BOOM); int i; flags &= 0x01ff; // Ignore flags unknown to DOOM if (special <= NUM_SPECIALS) { // This is a regular special; translate thru LUT flags = flags | (SpecialTranslation[special].flags << 8); if (passthrough) { if (GET_SPAC(flags) == SPAC_USE) { flags &= ~ML_SPAC_MASK; flags |= SPAC_USETHROUGH << ML_SPAC_SHIFT; } if (GET_SPAC(flags) == SPAC_CROSS) { flags &= ~ML_SPAC_MASK; flags |= SPAC_CROSSTHROUGH << ML_SPAC_SHIFT; } // TODO: what to do with gun-activated lines with passthrough? } ld->special = SpecialTranslation[special].newspecial; for (i = 0; i < 5; i++) ld->args[i] = SpecialTranslation[special].args[i] == TAG ? tag : SpecialTranslation[special].args[i]; } else if (special == 337) { ld->special = Line_Horizon; ld->flags = flags; ld->id = tag; memset(ld->args, 0, sizeof(ld->args)); } else if (special >= 340 && special <= 347) { // [SL] 2012-01-30 - convert to ZDoom Plane_Align special for // sloping sectors ld->special = Plane_Align; ld->flags = flags; ld->id = tag; memset(ld->args, 0, sizeof(ld->args)); switch (special) { case 340: // Slope the Floor in front of the line ld->args[0] = 1; break; case 341: // Slope the Ceiling in front of the line ld->args[1] = 1; break; case 342: // Slope the Floor+Ceiling in front of the line ld->args[0] = ld->args[1] = 1; break; case 343: // Slope the Floor behind the line ld->args[0] = 2; break; case 344: // Slope the Ceiling behind the line ld->args[1] = 2; break; case 345: // Slope the Floor+Ceiling behind the line ld->args[0] = ld->args[1] = 2; break; case 346: // Slope the Floor behind+Ceiling in front of the line ld->args[0] = 2; ld->args[1] = 1; break; case 347: // Slope the Floor in front+Ceiling behind the line ld->args[0] = 1; ld->args[1] = 2; } } else if (special <= GenCrusherBase) { if (special >= OdamexStaticInits && special < OdamexStaticInits + NUM_STATIC_INITS) { // An Odamex Static_Init special ld->special = Static_Init; ld->args[0] = tag; ld->args[1] = special - OdamexStaticInits; } else { // This is an unknown special. Just zero it. ld->special = 0; memset (ld->args, 0, sizeof(ld->args)); } } else { // Anything else is a BOOM generalized linedef type switch (special & 0x0007) { case WalkMany: flags |= ML_REPEAT_SPECIAL; case WalkOnce: if (passthrough) flags |= SPAC_CROSSTHROUGH << ML_SPAC_SHIFT; else flags |= SPAC_CROSS << ML_SPAC_SHIFT; break; case SwitchMany: case PushMany: flags |= ML_REPEAT_SPECIAL; case SwitchOnce: case PushOnce: if (passthrough) flags |= SPAC_USETHROUGH << ML_SPAC_SHIFT; else flags |= SPAC_USE << ML_SPAC_SHIFT; break; case GunMany: flags |= ML_REPEAT_SPECIAL; case GunOnce: flags |= SPAC_IMPACT << ML_SPAC_SHIFT; break; } // We treat push triggers like switch triggers with zero tags. if ((special & 0x0007) == PushMany || (special & 0x0007) == PushOnce) ld->args[0] = 0; else ld->args[0] = tag; if (special <= GenStairsBase) { // Generalized crusher (tag, dnspeed, upspeed, silent, damage) ld->special = Generic_Crusher; if (special & 0x0020) flags |= ML_MONSTERSCANACTIVATE; switch (special & 0x0018) { case 0x0000: ld->args[1] = C_SLOW; break; case 0x0008: ld->args[1] = C_NORMAL; break; case 0x0010: ld->args[1] = C_FAST; break; case 0x0018: ld->args[1] = C_TURBO; break; } ld->args[2] = ld->args[1]; ld->args[3] = (special & 0x0040) >> 6; ld->args[4] = 10; } else if (special <= GenLiftBase)
// // TextureManager::addTextureDirectory // // Requires that the PNAMES lump has been read and processed. // void TextureManager::addTextureDirectory(const char* lumpname) { // // Texture definition. // Each texture is composed of one or more patches, // with patches being lumps stored in the WAD. // The lumps are referenced by number, and patched // into the rectangular texture space using origin // and possibly other attributes. // struct mappatch_t { short originx; short originy; short patch; short stepdir; short colormap; }; // // Texture definition. // A DOOM wall texture is a list of patches // which are to be combined in a predefined order. // struct maptexture_t { char name[8]; WORD masked; // [RH] Unused BYTE scalex; // [RH] Scaling (8 is normal) BYTE scaley; // [RH] Same as above short width; short height; byte columndirectory[4]; // OBSOLETE short patchcount; mappatch_t patches[1]; }; int lumpnum = W_CheckNumForName(lumpname); if (lumpnum == -1) { if (iequals("TEXTURE1", lumpname)) I_Error("R_InitTextures: TEXTURE1 lump not found"); return; } size_t lumplen = W_LumpLength(lumpnum); if (lumplen == 0) return; byte* lumpdata = new byte[lumplen]; W_ReadLump(lumpnum, lumpdata); int* texoffs = (int*)(lumpdata + 4); // keep track of the number of texture errors int errors = 0; int count = LELONG(*((int*)(lumpdata + 0))); for (int i = 0; i < count; i++) { maptexture_t* mtexdef = (maptexture_t*)((byte*)lumpdata + LELONG(texoffs[i])); size_t texdefsize = sizeof(texdef_t) + sizeof(texdefpatch_t) * (SAFESHORT(mtexdef->patchcount) - 1); texdef_t* texdef = (texdef_t*)(new byte[texdefsize]); texdef->width = SAFESHORT(mtexdef->width); texdef->height = SAFESHORT(mtexdef->height); texdef->patchcount = SAFESHORT(mtexdef->patchcount); texdef->scalex = mtexdef->scalex; texdef->scaley = mtexdef->scaley; char uname[9]; for (int c = 0; c < 8; c++) uname[c] = toupper(mtexdef->name[c]); uname[8] = 0; mappatch_t* mpatch = &mtexdef->patches[0]; texdefpatch_t* patch = &texdef->patches[0]; for (int j = 0; j < texdef->patchcount; j++, mpatch++, patch++) { patch->originx = LESHORT(mpatch->originx); patch->originy = LESHORT(mpatch->originy); patch->patch = mPNameLookup[LESHORT(mpatch->patch)]; if (patch->patch == -1) { Printf(PRINT_HIGH, "R_InitTextures: Missing patch in texture %s\n", uname); errors++; } } mTextureDefinitions.push_back(texdef); mTextureNameTranslationMap[uname] = mTextureDefinitions.size() - 1; } delete [] lumpdata; }