static boolean LoadSoundLump(int sound, int *lumpnum, int *samplerate, uint32_t *length, byte **data_ref) { int lumplen; byte *data; // Load the sound *lumpnum = S_sfx[sound].lumpnum; *data_ref = (byte *)W_CacheLumpNum(*lumpnum, PU_STATIC); lumplen = W_LumpLength(*lumpnum); data = *data_ref; // Ensure this is a valid sound if (lumplen < 8 || data[0] != 0x03 || data[1] != 0x00) { // Invalid sound W_ReleaseLumpNum(*lumpnum); return false; } // 16 bit sample rate field, 32 bit length field *samplerate = (data[3] << 8) | data[2]; *length = (data[7] << 24) | (data[6] << 16) | (data[5] << 8) | data[4]; // If the header specifies that the length of the sound is // greater than the length of the lump itself, this is an invalid // sound lump. // We also discard sound lumps that are less than 49 samples long, // as this is how DMX behaves - although the actual cut-off length // seems to vary slightly depending on the sample rate. This needs // further investigation to better understand the correct // behavior. if (*length > (unsigned)lumplen - 8 || *length <= 48) { W_ReleaseLumpNum(*lumpnum); return false; } // Prune header *data_ref += 8; // The DMX sound library seems to skip the first 16 and last 16 // bytes of the lump - reason unknown. *data_ref += 16; *length -= 32; return true; }
void P_LoadSectors(int lump) { byte *data; int i; mapsector_t *ms; sector_t *ss; numsectors = W_LumpLength(lump) / sizeof(mapsector_t); sectors = Z_Malloc(numsectors * sizeof(sector_t), PU_LEVEL, 0); memset(sectors, 0, numsectors * sizeof(sector_t)); data = W_CacheLumpNum(lump, PU_STATIC); ms = (mapsector_t *) data; ss = sectors; for (i = 0; i < numsectors; i++, ss++, ms++) { ss->floorheight = SHORT(ms->floorheight) << FRACBITS; ss->ceilingheight = SHORT(ms->ceilingheight) << FRACBITS; ss->floorpic = R_FlatNumForName(ms->floorpic); ss->ceilingpic = R_FlatNumForName(ms->ceilingpic); ss->lightlevel = SHORT(ms->lightlevel); ss->special = SHORT(ms->special); ss->tag = SHORT(ms->tag); ss->thinglist = NULL; ss->seqType = SEQTYPE_STONE; // default seqType } W_ReleaseLumpNum(lump); }
void P_LoadNodes(int lump) { byte *data; int i, j, k; mapnode_t *mn; node_t *no; numnodes = W_LumpLength(lump) / sizeof(mapnode_t); nodes = Z_Malloc(numnodes * sizeof(node_t), PU_LEVEL, 0); data = W_CacheLumpNum(lump, PU_STATIC); mn = (mapnode_t *) data; no = nodes; for (i = 0; i < numnodes; i++, no++, mn++) { no->x = SHORT(mn->x) << FRACBITS; no->y = SHORT(mn->y) << FRACBITS; no->dx = SHORT(mn->dx) << FRACBITS; no->dy = SHORT(mn->dy) << FRACBITS; for (j = 0; j < 2; j++) { no->children[j] = SHORT(mn->children[j]); for (k = 0; k < 4; k++) no->bbox[j][k] = SHORT(mn->bbox[j][k]) << FRACBITS; } } W_ReleaseLumpNum(lump); }
static boolean CacheSFX_SDL(int sound) { int lumpnum; int samplerate; uint32_t length; byte *data; if (!LoadSoundLump(sound, &lumpnum, &samplerate, &length, &data)) return false; // Sample rate conversion // sound_chunks[sound].alen and abuf are determined by ExpandSoundData. sound_chunks[sound].allocated = 1; sound_chunks[sound].volume = MIX_MAX_VOLUME; ExpandSoundData_SDL(data, samplerate, length, &sound_chunks[sound]); // don't need the original lump any more W_ReleaseLumpNum(lumpnum); return true; }
void P_LoadSideDefs(int lump) { byte *data; int i; mapsidedef_t *msd; side_t *sd; numsides = W_LumpLength(lump) / sizeof(mapsidedef_t); sides = Z_Malloc(numsides * sizeof(side_t), PU_LEVEL, 0); memset(sides, 0, numsides * sizeof(side_t)); data = W_CacheLumpNum(lump, PU_STATIC); msd = (mapsidedef_t *) data; sd = sides; for (i = 0; i < numsides; i++, msd++, sd++) { sd->textureoffset = SHORT(msd->textureoffset) << FRACBITS; sd->rowoffset = SHORT(msd->rowoffset) << FRACBITS; sd->toptexture = R_TextureNumForName(msd->toptexture); sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); sd->midtexture = R_TextureNumForName(msd->midtexture); sd->sector = §ors[SHORT(msd->sector)]; } W_ReleaseLumpNum(lump); }
static void UnloadLumpCallback(const char *lumpname, int lumpnum, patch_t **ptr) { if (lumpname != NULL) { W_ReleaseLumpName(lumpname); } else { W_ReleaseLumpNum(lumpnum); } }
void SC_Close(void) { if (ScriptOpen) { if (ScriptLumpNum >= 0) W_ReleaseLumpNum(ScriptLumpNum); else Z_Free(ScriptBuffer); ScriptOpen = false; } }
void P_LoadThings(int lump) { byte *data; int i; mapthing_t spawnthing; mapthing_t *mt; int numthings; int playerCount; int deathSpotsCount; data = W_CacheLumpNum(lump, PU_STATIC); numthings = W_LumpLength(lump) / sizeof(mapthing_t); mt = (mapthing_t *) data; for (i = 0; i < numthings; i++, mt++) { spawnthing.tid = SHORT(mt->tid); spawnthing.x = SHORT(mt->x); spawnthing.y = SHORT(mt->y); spawnthing.height = SHORT(mt->height); spawnthing.angle = SHORT(mt->angle); spawnthing.type = SHORT(mt->type); spawnthing.options = SHORT(mt->options); spawnthing.special = mt->special; spawnthing.arg1 = mt->arg1; spawnthing.arg2 = mt->arg2; spawnthing.arg3 = mt->arg3; spawnthing.arg4 = mt->arg4; spawnthing.arg5 = mt->arg5; P_SpawnMapThing(&spawnthing); } P_CreateTIDList(); P_InitCreatureCorpseQueue(false); // false = do NOT scan for corpses W_ReleaseLumpNum(lump); if (!deathmatch) { // Don't need to check deathmatch spots return; } playerCount = 0; for (i = 0; i < MAXPLAYERS; i++) { playerCount += playeringame[i]; } deathSpotsCount = deathmatch_p - deathmatchstarts; if (deathSpotsCount < playerCount) { I_Error("P_LoadThings: Player count (%d) exceeds deathmatch " "spots (%d)", playerCount, deathSpotsCount); } }
void DEH_CloseFile(deh_context_t *context) { if (context->type == DEH_INPUT_FILE) { fclose(context->stream); } else if (context->type == DEH_INPUT_LUMP) { W_ReleaseLumpNum(context->lumpnum); } Z_Free(context->readbuffer); Z_Free(context); }
// Load and convert a sound effect // Returns true if successful static dboolean CacheSFX(sfxinfo_t *sfxinfo) { int lumpnum; unsigned int lumplen; int samplerate; unsigned int length; byte *data; // need to load the sound lumpnum = sfxinfo->lumpnum; data = W_CacheLumpNum(lumpnum, PU_STATIC); lumplen = W_LumpLength(lumpnum); // Check the header, and ensure this is a valid sound if (lumplen < 8 || data[0] != 0x03 || data[1] != 0x00) { // Invalid sound return false; } // 16 bit sample rate field, 32 bit length field samplerate = ((data[3] << 8) | data[2]); length = ((data[7] << 24) | (data[6] << 16) | (data[5] << 8) | data[4]); // If the header specifies that the length of the sound is greater than // the length of the lump itself, this is an invalid sound lump // We also discard sound lumps that are less than 49 samples long, // as this is how DMX behaves - although the actual cut-off length // seems to vary slightly depending on the sample rate. This needs // further investigation to better understand the correct // behavior. if (length > lumplen - 8 || length <= 48) return false; // The DMX sound library seems to skip the first 16 and last 16 // bytes of the lump - reason unknown. data += 16; length -= 32; // Sample rate conversion if (!ExpandSoundData(sfxinfo, data + 8, samplerate, length)) return false; // don't need the original lump any more W_ReleaseLumpNum(lumpnum); return true; }
// // P_InitSwitchList() // // Only called at game initialization in order to list the set of switches // and buttons known to the engine. This enables their texture to change // when activated, and in the case of buttons, change back after a timeout. // // This routine modified to read its data from a predefined lump or // PWAD lump called SWITCHES rather than a static table in this module to // allow wad designers to insert or modify switches. // // Lump format is an array of byte packed switchlist_t structures, terminated // by a structure with episode == -0. The lump can be generated from a // text source file using SWANTBLS.EXE, distributed with the BOOM utils. // The standard list of switches and animations is contained in the example // source text file DEFSWANI.DAT also in the BOOM util distribution. // // Rewritten by Lee Killough to remove limit 2/8/98 // void P_InitSwitchList(void) { int i; int index = 0; int episode = (gamemode == registered || gamemode == retail ? 2 : (gamemode == commercial ? 3 : 1)); switchlist_t *alphSwitchList; // jff 3/23/98 pointer to switch table int lump = W_GetNumForName2("SWITCHES"); // cph - new wad lump handling // jff 3/23/98 read the switch table from a predefined lump alphSwitchList = (switchlist_t *)W_CacheLumpNum(lump, PU_STATIC); for (i = 0;; ++i) { if (index + 1 >= max_numswitches) switchlist = Z_Realloc(switchlist, sizeof(*switchlist) * (max_numswitches = max_numswitches ? max_numswitches * 2 : 8)); if (SHORT(alphSwitchList[i].episode) <= episode) // jff 5/11/98 endianess { int texture1; int texture2; if (!SHORT(alphSwitchList[i].episode)) break; // Ignore switches referencing unknown texture names, instead of exiting. // Warn if either one is missing, but only add if both are valid. texture1 = R_CheckTextureNumForName(alphSwitchList[i].name1); if (texture1 == -1) C_Warning("Switch %i in SWITCHES lump has an unknown texture of %s.", i, alphSwitchList[i].name1); texture2 = R_CheckTextureNumForName(alphSwitchList[i].name2); if (texture2 == -1) C_Warning("Switch %i in SWITCHES lump has an unknown texture of %s.", i, alphSwitchList[i].name2); if (texture1 != -1 && texture2 != -1) { switchlist[index++] = texture1; switchlist[index++] = texture2; } } } numswitches = index / 2; switchlist[index] = -1; W_ReleaseLumpNum(lump); }
// Checks if the lump can be a Doom patch static dboolean CheckIfPatch(int lump) { int size; int width, height; const patch_t *patch; dboolean result; size = W_LumpLength(lump); // minimum length of a valid Doom patch if (size < 13) return false; patch = (const patch_t *)W_CacheLumpNum(lump, PU_STATIC); width = SHORT(patch->width); height = SHORT(patch->height); result = (height > 0 && height <= 16384 && width > 0 && width <= 16384 && width < size / 4); if (result) { // The dimensions seem like they might be valid for a patch, so // check the column directory for extra security. All columns // must begin after the column directory, and none of them must // point past the end of the patch. int x; for (x = 0; x < width; ++x) { unsigned int ofs = LONG(patch->columnofs[x]); // Need one byte for an empty column (but there's patches that don't know that!) if (ofs < (unsigned int)width * 4 + 8 || ofs >= (unsigned int)size) { result = false; break; } } } W_ReleaseLumpNum(lump); return result; }
static void UnloadPics(void) { int i; if (HubCount || gametype == DEATHMATCH) { W_ReleaseLumpName("INTERPIC"); patchINTERPIC = W_CacheLumpName("INTERPIC", PU_STATIC); FontBLumpBase = W_GetNumForName("FONTB16"); for (i = 0; i < 10; i++) { W_ReleaseLumpNum(FontBLumpBase + i); } W_ReleaseLumpName("FONTB13"); W_ReleaseLumpName("FONTB15"); W_ReleaseLumpName("FONTB05"); } }
void P_LoadVertexes(int lump) { byte *data; int i; mapvertex_t *ml; vertex_t *li; numvertexes = W_LumpLength(lump) / sizeof(mapvertex_t); vertexes = Z_Malloc(numvertexes * sizeof(vertex_t), PU_LEVEL, 0); data = W_CacheLumpNum(lump, PU_STATIC); ml = (mapvertex_t *) data; li = vertexes; for (i = 0; i < numvertexes; i++, li++, ml++) { li->x = SHORT(ml->x) << FRACBITS; li->y = SHORT(ml->y) << FRACBITS; } W_ReleaseLumpNum(lump); }
void P_LoadSubsectors(int lump) { byte *data; int i; mapsubsector_t *ms; subsector_t *ss; numsubsectors = W_LumpLength(lump) / sizeof(mapsubsector_t); subsectors = Z_Malloc(numsubsectors * sizeof(subsector_t), PU_LEVEL, 0); data = W_CacheLumpNum(lump, PU_STATIC); ms = (mapsubsector_t *) data; memset(subsectors, 0, numsubsectors * sizeof(subsector_t)); ss = subsectors; for (i = 0; i < numsubsectors; i++, ss++, ms++) { ss->numlines = SHORT(ms->numsegs); ss->firstline = SHORT(ms->firstseg); } W_ReleaseLumpNum(lump); }
void P_LoadSegs(int lump) { byte *data; int i; mapseg_t *ml; seg_t *li; line_t *ldef; int linedef, side; numsegs = W_LumpLength(lump) / sizeof(mapseg_t); segs = Z_Malloc(numsegs * sizeof(seg_t), PU_LEVEL, 0); memset(segs, 0, numsegs * sizeof(seg_t)); data = W_CacheLumpNum(lump, PU_STATIC); ml = (mapseg_t *) data; li = segs; for (i = 0; i < numsegs; i++, li++, ml++) { li->v1 = &vertexes[SHORT(ml->v1)]; li->v2 = &vertexes[SHORT(ml->v2)]; li->angle = (SHORT(ml->angle)) << 16; li->offset = (SHORT(ml->offset)) << 16; linedef = SHORT(ml->linedef); ldef = &lines[linedef]; li->linedef = ldef; side = SHORT(ml->side); li->sidedef = &sides[ldef->sidenum[side]]; li->frontsector = sides[ldef->sidenum[side]].sector; if (ldef->flags & ML_TWOSIDED) li->backsector = sides[ldef->sidenum[side ^ 1]].sector; else li->backsector = 0; } W_ReleaseLumpNum(lump); }
static void createPatch(int id) { rpatch_t *patch; const int patchNum = id; const patch_t *oldPatch; const column_t *oldColumn; int x, y; int pixelDataSize; int columnsDataSize; int postsDataSize; int dataSize; int *numPostsInColumn; int numPostsTotal; const unsigned char *oldColumnPixelData; int numPostsUsedSoFar; if (!CheckIfPatch(patchNum)) I_Error("createPatch: Unknown patch format %s.", (patchNum < numlumps ? lumpinfo[patchNum]->name : NULL)); oldPatch = (const patch_t*)W_CacheLumpNum(patchNum, PU_STATIC); patch = &patches[id]; patch->width = SHORT(oldPatch->width); patch->widthmask = 0; patch->height = SHORT(oldPatch->height); patch->leftoffset = SHORT(oldPatch->leftoffset); patch->topoffset = SHORT(oldPatch->topoffset); patch->flags = 0; if (getPatchIsNotTileable(oldPatch)) patch->flags |= PATCH_ISNOTTILEABLE; // work out how much memory we need to allocate for this patch's data pixelDataSize = (patch->width * patch->height + 4) & ~3; columnsDataSize = sizeof(rcolumn_t) * patch->width; // count the number of posts in each column numPostsInColumn = malloc(sizeof(int) * patch->width); numPostsTotal = 0; for (x = 0; x < patch->width; ++x) { oldColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[x])); numPostsInColumn[x] = 0; while (oldColumn->topdelta != 0xFF) { numPostsInColumn[x]++; numPostsTotal++; oldColumn = (const column_t *)((const byte *)oldColumn + oldColumn->length + 4); } } postsDataSize = numPostsTotal * sizeof(rpost_t); // allocate our data chunk dataSize = pixelDataSize + columnsDataSize + postsDataSize; patch->data = (unsigned char *)Z_Malloc(dataSize, PU_CACHE, (void **)&patch->data); memset(patch->data, 0, dataSize); // set out pixel, column, and post pointers into our data array patch->pixels = patch->data; patch->columns = (rcolumn_t *)((unsigned char *)patch->pixels + pixelDataSize); patch->posts = (rpost_t *)((unsigned char *)patch->columns + columnsDataSize); // sanity check that we've got all the memory allocated we need assert((((byte*)patch->posts + numPostsTotal * sizeof(rpost_t)) - (byte *)patch->data) == dataSize); memset(patch->pixels, 0xFF, (patch->width*patch->height)); // fill in the pixels, posts, and columns numPostsUsedSoFar = 0; for (x = 0; x < patch->width; ++x) { int top = -1; oldColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[x])); // setup the column's data patch->columns[x].pixels = patch->pixels + x * patch->height; patch->columns[x].numPosts = numPostsInColumn[x]; patch->columns[x].posts = patch->posts + numPostsUsedSoFar; while (oldColumn->topdelta != 0xFF) { int len = oldColumn->length; //e6y: support for DeePsea's true tall patches if (oldColumn->topdelta <= top) top += oldColumn->topdelta; else top = oldColumn->topdelta; // Clip posts that extend past the bottom if (top + oldColumn->length > patch->height) len = patch->height - top; if (len > 0) { // set up the post's data patch->posts[numPostsUsedSoFar].topdelta = top; patch->posts[numPostsUsedSoFar].length = len; // fill in the post's pixels oldColumnPixelData = (const byte *)oldColumn + 3; for (y = 0; y < len; y++) patch->pixels[x * patch->height + top + y] = oldColumnPixelData[y]; } oldColumn = (const column_t *)((const byte *)oldColumn + oldColumn->length + 4); numPostsUsedSoFar++; } } { const rcolumn_t *column; const rcolumn_t *prevColumn; // copy the patch image down and to the right where there are // holes to eliminate the black halo from bilinear filtering for (x = 0; x < patch->width; ++x) { column = R_GetPatchColumnClamped(patch, x); prevColumn = R_GetPatchColumnClamped(patch, x - 1); if (column->pixels[0] == 0xFF) { // e6y: marking of all patches with holes patch->flags |= PATCH_HASHOLES; // force the first pixel (which is a hole), to use // the color from the next solid spot in the column for (y = 0; y < patch->height; y++) if (column->pixels[y] != 0xFF) { column->pixels[0] = column->pixels[y]; break; } } // copy from above or to the left for (y = 1; y < patch->height; ++y) { //if (getIsSolidAtSpot(oldColumn, y)) continue; if (column->pixels[y] != 0xFF) continue; // this pixel is a hole // e6y: marking of all patches with holes patch->flags |= PATCH_HASHOLES; if (x && prevColumn->pixels[y - 1] != 0xFF) column->pixels[y] = prevColumn->pixels[y]; // copy the color from the left else column->pixels[y] = column->pixels[y - 1]; // copy the color from above } } } W_ReleaseLumpNum(patchNum); free(numPostsInColumn); }
void P_LoadLineDefs(int lump) { byte *data; int i; maplinedef_t *mld; line_t *ld; vertex_t *v1, *v2; numlines = W_LumpLength(lump) / sizeof(maplinedef_t); lines = Z_Malloc(numlines * sizeof(line_t), PU_LEVEL, 0); memset(lines, 0, numlines * sizeof(line_t)); data = W_CacheLumpNum(lump, PU_STATIC); mld = (maplinedef_t *) data; ld = lines; for (i = 0; i < numlines; i++, mld++, ld++) { ld->flags = SHORT(mld->flags); // Old line special info ... //ld->special = SHORT(mld->special); //ld->tag = SHORT(mld->tag); // New line special info ... ld->special = mld->special; ld->arg1 = mld->arg1; ld->arg2 = mld->arg2; ld->arg3 = mld->arg3; ld->arg4 = mld->arg4; ld->arg5 = mld->arg5; v1 = ld->v1 = &vertexes[SHORT(mld->v1)]; v2 = ld->v2 = &vertexes[SHORT(mld->v2)]; ld->dx = v2->x - v1->x; ld->dy = v2->y - v1->y; if (!ld->dx) ld->slopetype = ST_VERTICAL; else if (!ld->dy) ld->slopetype = ST_HORIZONTAL; else { if (FixedDiv(ld->dy, ld->dx) > 0) ld->slopetype = ST_POSITIVE; else ld->slopetype = ST_NEGATIVE; } if (v1->x < v2->x) { ld->bbox[BOXLEFT] = v1->x; ld->bbox[BOXRIGHT] = v2->x; } else { ld->bbox[BOXLEFT] = v2->x; ld->bbox[BOXRIGHT] = v1->x; } if (v1->y < v2->y) { ld->bbox[BOXBOTTOM] = v1->y; ld->bbox[BOXTOP] = v2->y; } else { ld->bbox[BOXBOTTOM] = v2->y; ld->bbox[BOXTOP] = v1->y; } ld->sidenum[0] = SHORT(mld->sidenum[0]); ld->sidenum[1] = SHORT(mld->sidenum[1]); if (ld->sidenum[0] != -1) ld->frontsector = sides[ld->sidenum[0]].sector; else ld->frontsector = 0; if (ld->sidenum[1] != -1) ld->backsector = sides[ld->sidenum[1]].sector; else ld->backsector = 0; } W_ReleaseLumpNum(lump); }
void W_ReleaseLumpName(char *name) { W_ReleaseLumpNum(W_GetNumForName(name)); }
// // 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++; } } } }
static void R_ReadTextures (int names_lump, int maptex_lump_1, int maptex_lump_2) { const maptexture_t *mtexture; texture_t *texture; int i, j; const int *maptex1; const int *maptex2; const char *names; // cph - const char *name_p;// const*'s int *patchlookup; int texbase; int numtex; int nummappatches; int maxoff, maxoff2; int numtextures1, numtextures2; const int *directory; char name[9]; // Load the patch names from pnames.lmp. name[8] = '\0'; names = W_CacheLumpNum(names_lump, 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. maptex1 = W_CacheLumpNum(maptex_lump_1, PU_STATIC); numtextures1 = LONG(*maptex1); maxoff = W_LumpLength(maptex_lump_1); directory = maptex1 + 1; if (maptex_lump_2 != -1) { maptex2 = W_CacheLumpNum(maptex_lump_2, PU_STATIC); numtextures2 = LONG(*maptex2); maxoff2 = W_LumpLength(maptex_lump_2); } else { maptex2 = NULL; numtextures2 = 0; maxoff2 = 0; } texbase = numtextures; numtex = numtextures1 + numtextures2; numtextures += numtex; // killough 4/9/98: make column offsets 32-bit; // clean up malloc-ing to use sizeof textures = Z_Realloc (textures, numtextures * sizeof(*textures), PU_STATIC, 0); textureheight = Z_Realloc (textureheight, numtextures * sizeof(*textureheight), PU_STATIC, 0); for (i = 0; i < numtex; ++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; } if ((((byte *) directory) >= ((byte *)maptex1+maxoff)) || ((offset=LONG(*directory)) >= maxoff)) { printf ("R_InitTextures: bad texture directory %X/%X %d/%d\n", (uintptr_t)directory,((uintptr_t)maptex1+maxoff), offset, maxoff); break; } mtexture = (const maptexture_t *)((const byte *)maptex1 + offset); if ((texbase) && (R_DuplicateTexture (mtexture->name, texbase))) { numtex--; numtextures--; numtextures1--; continue; } texture = textures[texbase+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); // killough 1/31/98: Initialize texture hash table texture->index = -1; { size_t j; for (j = 0; j < sizeof(texture->name); ++j) texture->name[j] = mtexture->name[j]; } #ifdef PADDED_STRUCTS mpatch = (mappatch_t *) ((char *) mtexture + 22); #else mpatch = &mtexture->patches[0]; #endif patch = texture->patches; for (j = 0; j < texture->patchcount; ++j, ++patch) { patch->originx = SHORT(mpatch->originx); patch->originy = SHORT(mpatch->originy); patch->patch = patchlookup[SHORT(mpatch->patch)]; if (patch->patch == -1) printf("Missing patch %d in texture %.8s.", SHORT(mpatch->patch), texture->name); // killough 4/17/98 #ifdef PADDED_STRUCTS mpatch = (mappatch_t *) ((unsigned char *) mpatch + 10); #else mpatch++; #endif } for (j = 1; j * 2 <= texture->width; j <<= 1); texture->widthmask = j - 1; textureheight[texbase+i] = texture->height << FRACBITS; i++; // Done here so that 'continue' misses it out... } free(patchlookup); // killough // cph - release the TEXTUREx lumps W_ReleaseLumpNum (maptex_lump_1); if (maptex_lump_2 != -1) W_ReleaseLumpNum (maptex_lump_2); }
static void createTextureCompositePatch(int id) { rpatch_t *composite_patch = &texture_composites[id]; texture_t *texture = textures[id]; texpatch_t *texpatch; int patchNum; const patch_t *oldPatch; const column_t *oldColumn; int i, x, y; int oy, count; int pixelDataSize; int columnsDataSize; int postsDataSize; int dataSize; int numPostsTotal; const unsigned char *oldColumnPixelData; int numPostsUsedSoFar; count_t *countsInColumn; composite_patch->width = texture->width; composite_patch->height = texture->height; composite_patch->widthmask = texture->widthmask; composite_patch->leftoffset = 0; composite_patch->topoffset = 0; composite_patch->flags = 0; // work out how much memory we need to allocate for this patch's data pixelDataSize = (composite_patch->width * composite_patch->height + 4) & ~3; columnsDataSize = sizeof(rcolumn_t) * composite_patch->width; // count the number of posts in each column countsInColumn = (count_t *)calloc(sizeof(count_t), composite_patch->width); numPostsTotal = 0; for (i = 0; i < texture->patchcount; ++i) { texpatch = &texture->patches[i]; patchNum = texpatch->patch; oldPatch = (const patch_t *)W_CacheLumpNum(patchNum, PU_STATIC); for (x = 0; x < SHORT(oldPatch->width); ++x) { int tx = texpatch->originx + x; if (tx < 0) continue; if (tx >= composite_patch->width) break; countsInColumn[tx].patches++; oldColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[x])); while (oldColumn->topdelta != 0xFF) { countsInColumn[tx].posts++; numPostsTotal++; oldColumn = (const column_t *)((const byte *)oldColumn + oldColumn->length + 4); } } W_ReleaseLumpNum(patchNum); } postsDataSize = numPostsTotal * sizeof(rpost_t); // allocate our data chunk dataSize = pixelDataSize + columnsDataSize + postsDataSize; composite_patch->data = (unsigned char *)Z_Malloc(dataSize, PU_STATIC, (void **)&composite_patch->data); memset(composite_patch->data, 0, dataSize); // set out pixel, column, and post pointers into our data array composite_patch->pixels = composite_patch->data; composite_patch->columns = (rcolumn_t*)((unsigned char*)composite_patch->pixels + pixelDataSize); composite_patch->posts = (rpost_t*)((unsigned char*)composite_patch->columns + columnsDataSize); // sanity check that we've got all the memory allocated we need assert((((byte *)composite_patch->posts + numPostsTotal * sizeof(rpost_t)) - (byte *)composite_patch->data) == dataSize); memset(composite_patch->pixels, 0xFF, (composite_patch->width * composite_patch->height)); numPostsUsedSoFar = 0; for (x = 0; x < texture->width; ++x) { // setup the column's data composite_patch->columns[x].pixels = composite_patch->pixels + (x * composite_patch->height); composite_patch->columns[x].numPosts = countsInColumn[x].posts; composite_patch->columns[x].posts = composite_patch->posts + numPostsUsedSoFar; numPostsUsedSoFar += countsInColumn[x].posts; } // fill in the pixels, posts, and columns for (i = 0; i < texture->patchcount; ++i) { texpatch = &texture->patches[i]; patchNum = texpatch->patch; oldPatch = (const patch_t *)W_CacheLumpNum(patchNum, PU_STATIC); for (x = 0; x < SHORT(oldPatch->width); ++x) { int top = -1; int tx = texpatch->originx + x; if (tx < 0) continue; if (tx >= composite_patch->width) break; oldColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[x])); while (oldColumn->topdelta != 0xFF) { rpost_t *post = &composite_patch->columns[tx].posts[countsInColumn[tx].posts_used]; // e6y: support for DeePsea's true tall patches if (oldColumn->topdelta <= top) top += oldColumn->topdelta; else top = oldColumn->topdelta; oldColumnPixelData = (const byte *)oldColumn + 3; oy = texpatch->originy; count = oldColumn->length; // the original renderer had several bugs which we reproduce here if (countsInColumn[tx].patches > 1) { // when there are multiple patches, then we need to handle the // column differently if (!i) { // draw first patch at original position, it will be partly // overdrawn below for (y = 0; y < count; ++y) { int ty = oy + top + y; if (ty < 0) continue; if (ty >= composite_patch->height) break; composite_patch->pixels[tx * composite_patch->height + ty] = oldColumnPixelData[y]; } } // do the buggy clipping if (oy + top < 0) { count += oy; oy = 0; } } else oy = 0; // with a single patch only negative y origins are wrong // set up the post's data post->topdelta = top + oy; post->length = count; if ((post->topdelta + post->length) > composite_patch->height) { if (post->topdelta > composite_patch->height) post->length = 0; else post->length = composite_patch->height - post->topdelta; } if (post->topdelta < 0) { if ((post->topdelta + post->length) <= 0) post->length = 0; else post->length -= post->topdelta; post->topdelta = 0; } // fill in the post's pixels for (y = 0; y < count; ++y) { int ty = oy + top + y; if (ty < 0) continue; if (ty >= composite_patch->height) break; composite_patch->pixels[tx * composite_patch->height + ty] = oldColumnPixelData[y]; } oldColumn = (const column_t *)((const byte *)oldColumn + oldColumn->length + 4); countsInColumn[tx].posts_used++; assert(countsInColumn[tx].posts_used <= countsInColumn[tx].posts); } } W_ReleaseLumpNum(patchNum); } for (x = 0; x < texture->width; ++x) { rcolumn_t *column; if (countsInColumn[x].patches <= 1) continue; // cleanup posts on multipatch columns column = &composite_patch->columns[x]; i = 0; while (i < column->numPosts - 1) { rpost_t *post1 = &column->posts[i]; rpost_t *post2 = &column->posts[i + 1]; if (post2->topdelta - post1->topdelta < 0) switchPosts(post1, post2); if (post1->topdelta + post1->length >= post2->topdelta) { int length = (post1->length + post2->length) - ((post1->topdelta + post1->length) - post2->topdelta); if (post1->length < length) post1->length = length; removePostFromColumn(column, i + 1); i = 0; continue; } i++; } } { const rcolumn_t *column; const rcolumn_t *prevColumn; // copy the patch image down and to the right where there are // holes to eliminate the black halo from bilinear filtering for (x = 0; x < composite_patch->width; ++x) { column = R_GetPatchColumnClamped(composite_patch, x); prevColumn = R_GetPatchColumnClamped(composite_patch, x - 1); if (column->pixels[0] == 0xFF) { // e6y: marking of all patches with holes composite_patch->flags |= PATCH_HASHOLES; // force the first pixel (which is a hole), to use // the color from the next solid spot in the column for (y = 0; y < composite_patch->height; ++y) { if (column->pixels[y] != 0xFF) { column->pixels[0] = column->pixels[y]; break; } } } // copy from above or to the left for (y = 1; y < composite_patch->height; ++y) { if (column->pixels[y] != 0xFF) continue; // this pixel is a hole // e6y: marking of all patches with holes composite_patch->flags |= PATCH_HASHOLES; if (x && prevColumn->pixels[y - 1] != 0xFF) column->pixels[y] = prevColumn->pixels[y]; // copy the color from the left else column->pixels[y] = column->pixels[y - 1]; // copy the color from above } } } free(countsInColumn); }
static boolean CacheSFX(sfxinfo_t *sfxinfo) { int lumpnum; unsigned int lumplen; int samplerate; unsigned int length; byte *data; // need to load the sound lumpnum = sfxinfo->lumpnum; data = W_CacheLumpNum(lumpnum, PU_STATIC); lumplen = W_LumpLength(lumpnum); // Check the header, and ensure this is a valid sound if (lumplen < 8 || data[0] != 0x03 || data[1] != 0x00) { // Invalid sound return false; } // 16 bit sample rate field, 32 bit length field samplerate = (data[3] << 8) | data[2]; length = (data[7] << 24) | (data[6] << 16) | (data[5] << 8) | data[4]; // If the header specifies that the length of the sound is greater than // the length of the lump itself, this is an invalid sound lump // We also discard sound lumps that are less than 49 samples long, // as this is how DMX behaves - although the actual cut-off length // seems to vary slightly depending on the sample rate. This needs // further investigation to better understand the correct // behavior. if (length > lumplen - 8 || length <= 48) { return false; } // The DMX sound library seems to skip the first 16 and last 16 // bytes of the lump - reason unknown. data += 16; length -= 32; // Sample rate conversion if (!ExpandSoundData(sfxinfo, data + 8, samplerate, length)) { return false; } #ifdef DEBUG_DUMP_WAVS { char filename[16]; allocated_sound_t * snd; M_snprintf(filename, sizeof(filename), "%s.wav", DEH_String(sfxinfo->name)); snd = GetAllocatedSoundBySfxInfoAndPitch(sfxinfo, NORM_PITCH); WriteWAV(filename, snd->chunk.abuf, snd->chunk.alen,mixer_freq); } #endif // don't need the original lump any more W_ReleaseLumpNum(lumpnum); return true; }