static void I_UploadNewPalette(int pal) { // This is used to replace the current 256 colour cmap with a new one // Used by 256 colour PseudoColor modes // Array of SDL_Color structs used for setting the 256-colour palette static SDL_Color* colours; static int cachedgamma; static size_t num_pals; if ((colours == NULL) || (cachedgamma != usegamma)) { int pplump = W_GetNumForName("PLAYPAL"); int gtlump = (W_CheckNumForName)("GAMMATBL",ns_prboom); register const byte * palette = W_CacheLumpNum(pplump); register const byte * const gtable = (const byte *)W_CacheLumpNum(gtlump) + 256*(cachedgamma = usegamma); register int i; num_pals = W_LumpLength(pplump) / (3*256); num_pals *= 256; if (!colours) { // First call - allocate and prepare colour array colours = malloc(sizeof(SDL_Color)*num_pals); } // set the colormap entries for (i=0 ; (size_t)i<num_pals ; i++) { colours[i].r = gtable[palette[0]]; colours[i].g = gtable[palette[1]]; colours[i].b = gtable[palette[2]]; palette += 3; } W_UnlockLumpNum(pplump); W_UnlockLumpNum(gtlump); num_pals/=256; } #ifdef RANGECHECK if ((size_t)pal >= num_pals) I_Error("I_UploadNewPalette: Palette number out of range (%d>=%d)", pal, num_pals); #endif u32 i; for(i = 0; i < 256; i++) { u8 r, g, b; r = (u8)colours[i+256*pal].r; g = (u8)colours[i+256*pal].g; b = (u8)colours[i+256*pal].b; BG_PALETTE[i]=RGB8(r,g,b); } }
static void setpalette(int pal) { if (colours == NULL) { int pplump = W_GetNumForName("PLAYPAL"); register const byte * palette = W_CacheLumpNum(pplump); register int i; num_pals = W_LumpLength(pplump) / (3*256); num_pals *= 256; if (!colours) colours = malloc(sizeof(*colours) * num_pals); for (i = 0; (size_t)i < num_pals; i++) { colours[i].r = palette[0]; colours[i].g = palette[1]; colours[i].b = palette[2]; palette += 3; } W_UnlockLumpNum(pplump); num_pals /= 256; } SDL_SetPalette(surface, SDL_LOGPAL | SDL_PHYSPAL, colours + 256 * pal, 0, 256); }
static int R_DemoEx_GetVersion(void) { int result = -1; int lump, ver; unsigned int size; const char *data; char str_ver[32]; lump = W_CheckNumForName(DEMOEX_VERSION_LUMPNAME); if (lump != -1) { size = W_LumpLength(lump); if (size > 0) { data = W_CacheLumpNum(lump); strncpy(str_ver, data, MIN(size, sizeof(str_ver))); if (sscanf(str_ver, "%d", &ver) == 1) { result = ver; } } W_UnlockLumpNum(lump); } return result; }
// // 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, index = 0; int episode = (gamemode == registered || gamemode==retail) ? 2 : gamemode == commercial ? 3 : 1; const switchlist_t *alphSwitchList; //jff 3/23/98 pointer to switch table int lump = W_GetNumForName("SWITCHES"); // cph - new wad lump handling //jff 3/23/98 read the switch table from a predefined lump alphSwitchList = (const switchlist_t *)W_CacheLumpNum(lump); for (i=0;;i++) { if (index+1 >= max_numswitches) switchlist = realloc(switchlist, sizeof *switchlist * (max_numswitches = max_numswitches ? max_numswitches*2 : 8)); if (SHORT(alphSwitchList[i].episode) <= episode) //jff 5/11/98 endianess { if (!SHORT(alphSwitchList[i].episode)) break; switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name1); switchlist[index++] = R_TextureNumForName(alphSwitchList[i].name2); } } numswitches = index/2; switchlist[index] = -1; W_UnlockLumpNum(lump); }
/////////////////////////////////////////////////////////// // Palette stuff. // static void I_UploadNewPalette(int pal) { // This is used to replace the current 256 colour cmap with a new one // Used by 256 colour PseudoColor modes // Array of XColor structs used for setting the 256-colour palette static XColor* colours; static int cachedgamma; static size_t num_pals; if ((colours == NULL) || (cachedgamma != usegamma)) { int lump = W_GetNumForName("PLAYPAL"); const byte *palette = W_CacheLumpNum(lump); register const byte *const gtable = gammatable[cachedgamma = usegamma]; register int i; num_pals = W_LumpLength(lump) / (3*256); num_pals *= 256; if (!colours) { // First call - allocate and prepare colour array colours = malloc(sizeof(*colours)*num_pals); for (i=0 ; i<num_pals ; i++) { colours[i].pixel = i & 0xff; colours[i].flags = DoRed|DoGreen|DoBlue; } } // set the X colormap entries for (i=0 ; i<num_pals ; i++) { register int c; c = gtable[palette[0]]; colours[i].red = (c<<8) + c; c = gtable[palette[1]]; colours[i].green = (c<<8) + c; c = gtable[palette[2]]; colours[i].blue = (c<<8) + c; palette += 3; } W_UnlockLumpNum(lump); num_pals/=256; } #ifdef RANGECHECK if (pal >= num_pals) I_Error("I_UploadNewPalette: Palette number out of range (%d>=%d)", pal, num_pals); #endif // store the colors to the current colormap XStoreColors(X_display, X_cmap, colours + 256*pal, 256); #ifdef HAVE_LIBXXF86DGA /* install DGA colormap */ if(doDga) XF86DGAInstallColormap(X_display, X_screen, X_cmap); #endif }
static void I_UploadNewPalette(int pal) { // This is used to replace the current 256 colour cmap with a new one // Used by 256 colour PseudoColor modes static int cachedgamma; static size_t num_pals; if (V_GetMode() == VID_MODEGL) return; if ((palettes == NULL) || (cachedgamma != usegamma)) { int pplump = W_GetNumForName("PLAYPAL"); int gtlump = (W_CheckNumForName)("GAMMATBL",ns_prboom); register const byte * palette = W_CacheLumpNum(pplump); register const byte * const gtable = (const byte *)W_CacheLumpNum(gtlump) + 256*(cachedgamma = usegamma); register int i; num_pals = W_LumpLength(pplump) / (3*256); num_pals *= 256; if (!palettes) { // First call - allocate and prepare colour array palettes = malloc(sizeof(*palettes)*num_pals); } // set the colormap entries for (i=0 ; (size_t)i<num_pals ; i++) { palettes[i] = (gtable[palette[0]] << 24) + (gtable[palette[1]] << 16) + (gtable[palette[2]] << 8) + 0xff; palette += 3; } W_UnlockLumpNum(pplump); W_UnlockLumpNum(gtlump); num_pals/=256; } #ifdef RANGECHECK if ((size_t)pal >= num_pals) I_Error("I_UploadNewPalette: Palette number out of range (%d>=%d)", pal, num_pals); #endif // store the colors to the current display currentPalette = 256 * pal; }
void gld_BindFlat(GLTexture *gltexture, unsigned int flags) { const unsigned char *flat; unsigned char *buffer; int w, h; if (!gltexture || gltexture->textype != GLDT_FLAT) { qglBindTexture(GL_TEXTURE_2D, 0); last_glTexID = NULL; return; } #ifdef HAVE_LIBSDL_IMAGE if (gld_LoadHiresTex(gltexture, CR_DEFAULT)) { gld_SetTexClamp(gltexture, flags); last_glTexID = gltexture->texid_p; return; } #endif gld_GetTextureTexID(gltexture, CR_DEFAULT); if (last_glTexID == gltexture->texid_p) { gld_SetTexClamp(gltexture, flags); return; } last_glTexID = gltexture->texid_p; if (*gltexture->texid_p != 0) { qglBindTexture(GL_TEXTURE_2D, *gltexture->texid_p); gld_SetTexClamp(gltexture, flags); return; } flat=W_CacheLumpNum(gltexture->index); buffer=(unsigned char*)Z_Malloc(gltexture->buffer_size,PU_STATIC,0); if (!(gltexture->flags & GLTEXTURE_MIPMAP) && gl_paletted_texture) memset(buffer,transparent_pal_index,gltexture->buffer_size); else memset(buffer,0,gltexture->buffer_size); gld_AddFlatToTexture(gltexture, buffer, flat, !(gltexture->flags & GLTEXTURE_MIPMAP) && gl_paletted_texture); if (*gltexture->texid_p == 0) qglGenTextures(1, gltexture->texid_p); qglBindTexture(GL_TEXTURE_2D, *gltexture->texid_p); buffer = gld_HQResize(gltexture, buffer, gltexture->buffer_width, gltexture->buffer_height, &w, &h); gld_BuildTexture(gltexture, buffer, false, w, h); gld_SetTexClamp(gltexture, flags); W_UnlockLumpNum(gltexture->index); }
void F_TextWrite (void) { { // erase the entire screen to a tiled background const byte *src; // cph - const int x,y; int lump; // killough 4/17/98: src = W_CacheLumpNum(lump = firstflat + R_FlatNumForName(finaleflat)); V_DrawBlock(0, 0, 0, 64, 64, src, 0); for (y=0 ; y<SCREENHEIGHT ; y+=64) for (x=y ? 0 : 64; x<SCREENWIDTH ; x+=64) V_CopyRect(0, 0, 0, ((SCREENWIDTH-x) < 64) ? (SCREENWIDTH-x) : 64, ((SCREENHEIGHT-y) < 64) ? (SCREENHEIGHT-y) : 64, x, y, 0); W_UnlockLumpNum(lump); } V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT); { // draw some of the text onto the screen int cx = 10; int cy = 10; const char* ch = finaletext; // CPhipps - const int count = (finalecount - 10)/Get_TextSpeed(); // phares int w; if (count < 0) count = 0; for ( ; count ; count-- ) { int c = *ch++; if (!c) break; if (c == '\n') { cx = 10; cy += 11; continue; } c = toupper(c) - HU_FONTSTART; if (c < 0 || c> HU_FONTSIZE) { cx += 4; continue; } w = SHORT (hu_font[c]->width); if (cx+w > SCREENWIDTH) break; // CPhipps - patch drawing updated V_DrawMemPatch(cx, cy, 0, hu_font[c], NULL, VPT_STRETCH); cx+=w; } } }
void R_DemoEx_ShowComment(void) { extern patchnum_t hu_font[]; int lump; int cx = 10; int cy = 10; const char* ch; int count; int w; if (!use_demoex_info) return; lump = W_CheckNumForName(DEMOEX_COMMENT_LUMPNAME); if (lump == -1) return; count = W_LumpLength(lump); if (count <= 0) return; ch = W_CacheLumpNum(lump); for ( ; count ; count-- ) { int c = *ch++; if (!c) break; if (c == '\n') { cx = 10; cy += 11; continue; } c = toupper(c) - HU_FONTSTART; if (c < 0 || c> HU_FONTSIZE) { cx += 4; continue; } w = hu_font[c].width; if (cx + w > SCREENWIDTH) break; V_DrawNumPatch(cx, cy, 0, hu_font[c].lumpnum, CR_DEFAULT, VPT_STRETCH); cx += w; } W_UnlockLumpNum(lump); }
// // I_SetPalette // void I_SetPalette (int pal) { if (!INITIALISED) return; if (true_color) { int lump = W_GetNumForName("PLAYPAL"); const byte *palette = W_CacheLumpNum(lump); I_SetPaletteTranslation(palette + (3*256)*pal); W_UnlockLumpNum(lump); } else I_UploadNewPalette(pal); }
static int ReadLump(const char *filename, const char *lumpname, unsigned char **buffer) { FILE *file = NULL; int size = 0; const unsigned char *data; int lump; file = fopen(filename, "r"); if (file) { fseek(file, 0, SEEK_END); size = ftell(file); fseek(file, 0, SEEK_SET); *buffer = malloc(size + 1); size = fread(*buffer, 1, size, file); if (size > 0) { (*buffer)[size] = 0; } fclose(file); } else { char name[9]; char* p; strncpy(name, lumpname, 9); name[8] = 0; for(p = name; *p; p++) *p = toupper(*p); lump = (W_CheckNumForName)(name, ns_prboom); if (lump != -1) { size = W_LumpLength(lump); data = W_CacheLumpNum(lump); *buffer = calloc(1, size + 1); memcpy (*buffer, data, size); (*buffer)[size] = 0; W_UnlockLumpNum(lump); } } return size; }
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); width = LittleShort(patch->width); height = LittleShort(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 = LittleLong(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_UnlockLumpNum(lump); return result; }
// // 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, index = 0; int episode = (gamemode == registered || gamemode==retail) ? 2 : gamemode == commercial ? 3 : 1; const switchlist_t *alphSwitchList; //jff 3/23/98 pointer to switch table int lump = W_GetNumForName("SWITCHES"); // cph - new wad lump handling //jff 3/23/98 read the switch table from a predefined lump alphSwitchList = (const switchlist_t *)W_CacheLumpNum(lump); for (i=0;;i++) { if (index+1 >= max_numswitches) switchlist = 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, 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) lprintf(LO_WARN, "P_InitSwitchList: unknown texture %s\n", alphSwitchList[i].name1); texture2 = R_CheckTextureNumForName(alphSwitchList[i].name2); if (texture2 == -1) lprintf(LO_WARN, "P_InitSwitchList: unknown texture %s\n", alphSwitchList[i].name2); if (texture1 != -1 && texture2 != -1) { switchlist[index++] = texture1; switchlist[index++] = texture2; } } } numswitches = index/2; switchlist[index] = -1; W_UnlockLumpNum(lump); }
void S_StopMusic(void) { //jff 1/22/98 return if music is not enabled if (!mus_card || nomusicparm) return; if (mus_playing) { //if (mus_paused) // I_ResumeSong(mus_playing->handle); mus_stop_music(); if (mus_playing->lumpnum >= 0) W_UnlockLumpNum(mus_playing->lumpnum); // cph - release the music data mus_playing->data = 0; mus_playing = 0; } }
static uint_64_t G_UpdateSignature(uint_64_t s, const char *name) { int i; int lump = W_CheckNumForName(name); if (lump != -1 && (i = lump + 10) < numlumps) { do { int size = W_LumpLength(i); const byte *p = W_CacheLumpNum(i); while (size--) { s <<= 1; s += *p++; } W_UnlockLumpNum(i); } while (--i > lump); } return s; }
//--------------------------------------------------------------------------- static void createTextureCompositePatch(int id) { rpatch_t *composite_patch; texture_t *texture; texpatch_t *texpatch; int patchNum; const patch_t *oldPatch; const column_t *oldColumn, *oldPrevColumn, *oldNextColumn; int i, x, y; int oy, count; int pixelDataSize; int columnsDataSize; int postsDataSize; int dataSize; int numPostsTotal; const unsigned char *oldColumnPixelData; int numPostsUsedSoFar; int edgeSlope; count_t *countsInColumn; #ifdef RANGECHECK if (id >= numtextures) I_Error("createTextureCompositePatch: %i >= numtextures", id); #endif composite_patch = &texture_composites[id]; texture = textures[id]; 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->isNotTileable = 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); 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_UnlockLumpNum(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); for (x=0; x<SHORT(oldPatch->width); x++) { 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])); { // tiling int prevColumnIndex = x-1; int nextColumnIndex = x+1; while (prevColumnIndex < 0) prevColumnIndex += SHORT(oldPatch->width); while (nextColumnIndex >= SHORT(oldPatch->width)) nextColumnIndex -= SHORT(oldPatch->width); oldPrevColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[prevColumnIndex])); oldNextColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[nextColumnIndex])); } while (oldColumn->topdelta != 0xff) { rpost_t *post = &composite_patch->columns[tx].posts[countsInColumn[tx].posts_used]; 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 == 0) { // draw first patch at original position, it will be partly // overdrawn below for (y=0; y<count; y++) { int ty = oy + oldColumn->topdelta + 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 + oldColumn->topdelta) < 0) { count += oy; oy = 0; } } else { // with a single patch only negative y origins are wrong oy = 0; } // set up the post's data post->topdelta = oldColumn->topdelta + 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; } post->slope = 0; edgeSlope = getColumnEdgeSlope(oldPrevColumn, oldNextColumn, oldColumn->topdelta); if (edgeSlope == 1) post->slope |= RDRAW_EDGESLOPE_TOP_UP; else if (edgeSlope == -1) post->slope |= RDRAW_EDGESLOPE_TOP_DOWN; edgeSlope = getColumnEdgeSlope(oldPrevColumn, oldNextColumn, oldColumn->topdelta+count); if (edgeSlope == 1) post->slope |= RDRAW_EDGESLOPE_BOT_UP; else if (edgeSlope == -1) post->slope |= RDRAW_EDGESLOPE_BOT_DOWN; // fill in the post's pixels for (y=0; y<count; y++) { int ty = oy + oldColumn->topdelta + 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_UnlockLumpNum(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]; int length; if ((post2->topdelta - post1->topdelta) < 0) switchPosts(post1, post2); if ((post1->topdelta + post1->length) >= post2->topdelta) { length = (post1->length + post2->length) - ((post1->topdelta + post1->length) - post2->topdelta); if (post1->length < length) { post1->slope = post2->slope; post1->length = length; } removePostFromColumn(column, i+1); i = 0; continue; } i++; } } if (1 || composite_patch->isNotTileable) { const rcolumn_t *column, *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++) { //oldColumn = (const column_t *)((const byte *)oldPatch + oldPatch->columnofs[x]); column = R_GetPatchColumnClamped(composite_patch, x); prevColumn = R_GetPatchColumnClamped(composite_patch, x-1); if (column->pixels[0] == 0xff) { // 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 (getIsSolidAtSpot(oldColumn, y)) continue; if (column->pixels[y] != 0xff) continue; // this pixel is a hole if (x && prevColumn->pixels[y-1] != 0xff) { // copy the color from the left column->pixels[y] = prevColumn->pixels[y]; } else { // copy the color from above column->pixels[y] = column->pixels[y-1]; } } } // verify that the patch truly is non-rectangular since // this determines tiling later on } free(countsInColumn); }
//--------------------------------------------------------------------------- static void createPatch(int id) { rpatch_t *patch; const int patchNum = id; const patch_t *oldPatch = (const patch_t*)W_CacheLumpNum(patchNum); const column_t *oldColumn, *oldPrevColumn, *oldNextColumn; int x, y; int pixelDataSize; int columnsDataSize; int postsDataSize; int dataSize; int *numPostsInColumn; int numPostsTotal; const unsigned char *oldColumnPixelData; int numPostsUsedSoFar; int edgeSlope; #ifdef RANGECHECK if (id >= numlumps) I_Error("createPatch: %i >= numlumps", id); #endif patch = &patches[id]; // proff - 2003-02-16 What about endianess? patch->width = SHORT(oldPatch->width); patch->widthmask = 0; patch->height = SHORT(oldPatch->height); patch->leftoffset = SHORT(oldPatch->leftoffset); patch->topoffset = SHORT(oldPatch->topoffset); patch->isNotTileable = getPatchIsNotTileable(oldPatch); // 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 = (int*)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++) { oldColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[x])); if (patch->isNotTileable) { // non-tiling if (x == 0) oldPrevColumn = 0; else oldPrevColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[x-1])); if (x == patch->width-1) oldNextColumn = 0; else oldNextColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[x+1])); } else { // tiling int prevColumnIndex = x-1; int nextColumnIndex = x+1; while (prevColumnIndex < 0) prevColumnIndex += patch->width; while (nextColumnIndex >= patch->width) nextColumnIndex -= patch->width; oldPrevColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[prevColumnIndex])); oldNextColumn = (const column_t *)((const byte *)oldPatch + LONG(oldPatch->columnofs[nextColumnIndex])); } // setup the column's data patch->columns[x].pixels = patch->pixels + (x*patch->height) + 0; patch->columns[x].numPosts = numPostsInColumn[x]; patch->columns[x].posts = patch->posts + numPostsUsedSoFar; while (oldColumn->topdelta != 0xff) { // set up the post's data patch->posts[numPostsUsedSoFar].topdelta = oldColumn->topdelta; patch->posts[numPostsUsedSoFar].length = oldColumn->length; patch->posts[numPostsUsedSoFar].slope = 0; edgeSlope = getColumnEdgeSlope(oldPrevColumn, oldNextColumn, oldColumn->topdelta); if (edgeSlope == 1) patch->posts[numPostsUsedSoFar].slope |= RDRAW_EDGESLOPE_TOP_UP; else if (edgeSlope == -1) patch->posts[numPostsUsedSoFar].slope |= RDRAW_EDGESLOPE_TOP_DOWN; edgeSlope = getColumnEdgeSlope(oldPrevColumn, oldNextColumn, oldColumn->topdelta+oldColumn->length); if (edgeSlope == 1) patch->posts[numPostsUsedSoFar].slope |= RDRAW_EDGESLOPE_BOT_UP; else if (edgeSlope == -1) patch->posts[numPostsUsedSoFar].slope |= RDRAW_EDGESLOPE_BOT_DOWN; // fill in the post's pixels oldColumnPixelData = (const byte *)oldColumn + 3; for (y=0; y<oldColumn->length; y++) { patch->pixels[x * patch->height + oldColumn->topdelta + y] = oldColumnPixelData[y]; } oldColumn = (const column_t *)((const byte *)oldColumn + oldColumn->length + 4); numPostsUsedSoFar++; } } if (1 || patch->isNotTileable) { const rcolumn_t *column, *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++) { //oldColumn = (const column_t *)((const byte *)oldPatch + oldPatch->columnofs[x]); column = R_GetPatchColumnClamped(patch, x); prevColumn = R_GetPatchColumnClamped(patch, x-1); if (column->pixels[0] == 0xff) { // 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 if (x && prevColumn->pixels[y-1] != 0xff) { // copy the color from the left column->pixels[y] = prevColumn->pixels[y]; } else { // copy the color from above column->pixels[y] = column->pixels[y-1]; } } } // verify that the patch truly is non-rectangular since // this determines tiling later on } W_UnlockLumpNum(patchNum); free(numPostsInColumn); }
void D_Display (void) { static boolean isborderstate IDATA_ATTR= false; static boolean borderwillneedredraw IDATA_ATTR= false; static gamestate_t oldgamestate IDATA_ATTR= -1; boolean wipe; boolean viewactive = false, isborder = false; if (nodrawers) // for comparative timing / profiling return; // save the current screen if about to wipe if ((wipe = gamestate != wipegamestate)) wipe_StartScreen(0, 0, SCREENWIDTH, SCREENHEIGHT); if (gamestate != GS_LEVEL) { // Not a level switch (oldgamestate) { case (gamestate_t)-1: case GS_LEVEL: V_SetPalette(0); // cph - use default (basic) palette default: break; } switch (gamestate) { case GS_INTERMISSION: WI_Drawer(); break; case GS_FINALE: F_Drawer(); break; case GS_DEMOSCREEN: D_PageDrawer(); break; default: break; } } else if (gametic != basetic) { // In a level boolean redrawborderstuff; HU_Erase(); if (setsizeneeded) { // change the view size if needed R_ExecuteSetViewSize(); oldgamestate = -1; // force background redraw } // Work out if the player view is visible, and if there is a border viewactive = (!(automapmode & am_active) || (automapmode & am_overlay)) && !inhelpscreens; isborder = viewactive ? (viewheight != SCREENHEIGHT) : (!inhelpscreens && (automapmode & am_active)); if (oldgamestate != GS_LEVEL) { R_FillBackScreen (); // draw the pattern into the back screen redrawborderstuff = isborder; } else { // CPhipps - // If there is a border, and either there was no border last time, // or the border might need refreshing, then redraw it. redrawborderstuff = isborder && (!isborderstate || borderwillneedredraw); // The border may need redrawing next time if the border surrounds the screen, // and there is a menu being displayed borderwillneedredraw = menuactive && isborder && viewactive && (viewwidth != SCREENWIDTH); } if (redrawborderstuff) R_DrawViewBorder(); // Now do the drawing if (viewactive) R_RenderPlayerView (&players[displayplayer]); if (automapmode & am_active) AM_Drawer(); ST_Drawer((viewheight != SCREENHEIGHT) || ((automapmode & am_active) && !(automapmode & am_overlay)), redrawborderstuff); R_DrawViewBorder(); HU_Drawer(); } isborderstate = isborder; oldgamestate = wipegamestate = gamestate; // draw pause pic if (paused) { static int x; if (!x) { // Cache results of x pos calc int lump = W_GetNumForName("M_PAUSE"); const patch_t* p = W_CacheLumpNum(lump); x = (320 - SHORT(p->width))/2; W_UnlockLumpNum(lump); } // CPhipps - updated for new patch drawing V_DrawNamePatch(x, (!(automapmode & am_active) || (automapmode & am_overlay)) ? 4+(viewwindowy*200/SCREENHEIGHT) : 4, // cph - Must un-stretch viewwindowy 0, "M_PAUSE", CR_DEFAULT, VPT_STRETCH); } // menus go directly to the screen M_Drawer(); // menu is drawn even on top of everything D_BuildNewTiccmds(); // normal update if (!wipe) I_FinishUpdate (); // page flip or blit buffer else { // wipe update wipe_EndScreen(0, 0, SCREENWIDTH, SCREENHEIGHT); D_Wipe(); } }
void gld_BindFlat(GLTexture *gltexture) { const unsigned char *flat; int i; unsigned char *buffer; if (gltexture==last_gltexture) return; last_gltexture=gltexture; if (!gltexture) return; if (gltexture->textype!=GLDT_FLAT) { glBindTexture(GL_TEXTURE_2D, 0); last_gltexture = NULL; last_cm = -1; return; } if (gltexture->glTexID[CR_DEFAULT]!=0) { glBindTexture(GL_TEXTURE_2D, gltexture->glTexID[CR_DEFAULT]); glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_RESIDENT,&i); #ifdef _DEBUG if (i!=GL_TRUE) lprintf(LO_INFO, "glGetTexParam: %i\n", i); #endif if (i==GL_TRUE) return; } flat=W_CacheLumpNum(gltexture->index); buffer=(unsigned char*)Z_Malloc(gltexture->buffer_size,PU_STATIC,0); if (!(gltexture->mipmap & use_mipmapping) & gl_paletted_texture) memset(buffer,transparent_pal_index,gltexture->buffer_size); else memset(buffer,0,gltexture->buffer_size); gld_AddFlatToTexture(gltexture, buffer, flat, !(gltexture->mipmap & use_mipmapping) & gl_paletted_texture); if (gltexture->glTexID[CR_DEFAULT]==0) glGenTextures(1,&gltexture->glTexID[CR_DEFAULT]); glBindTexture(GL_TEXTURE_2D, gltexture->glTexID[CR_DEFAULT]); #ifdef USE_GLU_MIPMAP if (gltexture->mipmap & use_mipmapping) { gluBuild2DMipmaps(GL_TEXTURE_2D, gl_tex_format, gltexture->buffer_width, gltexture->buffer_height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_mipmap_filter); if (gl_texture_filter_anisotropic) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0); } else #endif /* USE_GLU_MIPMAP */ { #ifdef USE_GLU_IMAGESCALE if ((gltexture->buffer_width!=gltexture->tex_width) || (gltexture->buffer_height!=gltexture->tex_height) ) { unsigned char *scaledbuffer; scaledbuffer=(unsigned char*)Z_Malloc(gltexture->tex_width*gltexture->tex_height*4,PU_STATIC,0); if (scaledbuffer) { gluScaleImage(GL_RGBA, gltexture->buffer_width, gltexture->buffer_height, GL_UNSIGNED_BYTE,buffer, gltexture->tex_width, gltexture->tex_height, GL_UNSIGNED_BYTE,scaledbuffer); Z_Free(buffer); buffer=scaledbuffer; glTexImage2D( GL_TEXTURE_2D, 0, gl_tex_format, gltexture->tex_width, gltexture->tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); } } else #endif /* USE_GLU_IMAGESCALE */ { if (gl_paletted_texture) { I_Error("Paletted textures not supported"); /* gld_SetTexturePalette(GL_TEXTURE_2D); glTexImage2D( GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, gltexture->buffer_width, gltexture->buffer_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, buffer); */ } else { glTexImage2D( GL_TEXTURE_2D, 0, gl_tex_format, gltexture->buffer_width, gltexture->buffer_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); } } // Vladimir i -> x glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_filter); } Z_Free(buffer); W_UnlockLumpNum(gltexture->index); }
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; } }
static inline void precache_lump(int l) { W_CacheLumpNum(l); W_UnlockLumpNum(l); }
/////////////////////////////////////////////////////////// // Palette stuff. // static void I_UploadNewPalette(int pal, int force) { // This is used to replace the current 256 colour cmap with a new one // Used by 256 colour PseudoColor modes // Array of SDL_Color structs used for setting the 256-colour palette static SDL_Color* colours; static int cachedgamma; static size_t num_pals; if (V_GetMode() == VID_MODEGL) return; if ((colours == NULL) || (cachedgamma != usegamma) || force) { int pplump = W_GetNumForName("PLAYPAL"); int gtlump = (W_CheckNumForName)("GAMMATBL",ns_prboom); register const byte * palette = W_CacheLumpNum(pplump); register const byte * const gtable = (const byte *)W_CacheLumpNum(gtlump) + 256*(cachedgamma = usegamma); register int i; num_pals = W_LumpLength(pplump) / (3*256); num_pals *= 256; if (!colours) { // First call - allocate and prepare colour array colours = malloc(sizeof(*colours)*num_pals); #ifdef GL_DOOM vid_8ingl.colours = malloc(sizeof(vid_8ingl.colours[0]) * 4 * num_pals); #endif } // set the colormap entries for (i=0 ; (size_t)i<num_pals ; i++) { #ifdef GL_DOOM if (vid_8ingl.enabled) { if (V_GetMode() == VID_MODE8) { vid_8ingl.colours[i * 4 + 0] = gtable[palette[2]]; vid_8ingl.colours[i * 4 + 1] = gtable[palette[1]]; vid_8ingl.colours[i * 4 + 2] = gtable[palette[0]]; vid_8ingl.colours[i * 4 + 3] = 255; } } else #endif { colours[i].r = gtable[palette[0]]; colours[i].g = gtable[palette[1]]; colours[i].b = gtable[palette[2]]; } palette += 3; } W_UnlockLumpNum(pplump); W_UnlockLumpNum(gtlump); num_pals/=256; } #ifdef RANGECHECK if ((size_t)pal >= num_pals) I_Error("I_UploadNewPalette: Palette number out of range (%d>=%d)", pal, num_pals); #endif // store the colors to the current display // SDL_SetColors(SDL_GetVideoSurface(), colours+256*pal, 0, 256); #ifdef GL_DOOM if (vid_8ingl.enabled) { vid_8ingl.palette = pal; } else #endif { SDL_SetPalette(SDL_GetVideoSurface(),SDL_LOGPAL|SDL_PHYSPAL,colours+256*pal, 0, 256); } }
static void R_DemoEx_GetParams(const byte *pwad_p, waddata_t *waddata) { int lump; size_t size; char *str; const char *data; char **params; int i, p, paramscount; lump = W_CheckNumForName(DEMOEX_PARAMS_LUMPNAME); if (lump == -1) return; size = W_LumpLength(lump); if (size <= 0) return; str = calloc(size + 1, 1); if (!str) return; data = W_CacheLumpNum(lump); strncpy(str, data, size); M_ParseCmdLine(str, NULL, NULL, ¶mscount, &i); params = malloc(paramscount * sizeof(char*) + i * sizeof(char) + 1); if (params) { struct { const char *param; wad_source_t source; } files[] = { {"-iwad" , source_iwad}, {"-file" , source_pwad}, {"-deh" , source_deh}, {NULL} }; M_ParseCmdLine(str, params, ((char*)params) + sizeof(char*) * paramscount, ¶mscount, &i); if (!M_CheckParm("-iwad") && !M_CheckParm("-file")) { i = 0; while (files[i].param) { p = M_CheckParmEx(files[i].param, params, paramscount); if (p >= 0) { while (++p != paramscount && *params[p] != '-') { char *filename; //something is wrong here filename = I_FindFile(params[p], ".wad"); if (!filename) { filename = strdup(params[p]); } WadDataAddItem(waddata, filename, files[i].source, 0); free(filename); } } i++; } } if (!M_CheckParm("-complevel")) { p = M_CheckParmEx("-complevel", params, paramscount); if (p >= 0 && p < (int)paramscount - 1) { M_AddParam("-complevel"); M_AddParam(strdup(params[p + 1])); } } //for recording or playback using "single-player coop" mode if (!M_CheckParm("-solo-net")) { p = M_CheckParmEx("-solo-net", params, paramscount); if (p >= 0) { M_AddParam("-solo-net"); } } if (!M_CheckParm("-emulate")) { p = M_CheckParmEx("-emulate", params, paramscount); if (p >= 0 && p < (int)paramscount - 1) { M_AddParam("-emulate"); M_AddParam(strdup(params[p + 1])); } } // for doom 1.2 if (!M_CheckParm("-respawn")) { p = M_CheckParmEx("-respawn", params, paramscount); if (p >= 0) { M_AddParam("-respawn"); } } // for doom 1.2 if (!M_CheckParm("-fast")) { p = M_CheckParmEx("-fast", params, paramscount); if (p >= 0) { M_AddParam("-fast"); } } // for doom 1.2 if (!M_CheckParm("-nomonsters")) { p = M_CheckParmEx("-nomonsters", params, paramscount); if (p >= 0) { M_AddParam("-nomonsters"); } } p = M_CheckParmEx("-spechit", params, paramscount); if (p >= 0 && p < (int)paramscount - 1) { spechit_baseaddr = atoi(params[p + 1]); } //overflows { overrun_list_t overflow; for (overflow = 0; overflow < OVERFLOW_MAX; overflow++) { int value; char *pstr, *mask; mask = malloc(strlen(overflow_cfgname[overflow]) + 16); if (mask) { sprintf(mask, "-set %s", overflow_cfgname[overflow]); pstr = strstr(str, mask); if (pstr) { strcat(mask, " = %d"); if (sscanf(pstr, mask, &value) == 1) { overflows[overflow].tmp_emulate = value; } } free(mask); } } } free(params); } W_UnlockLumpNum(lump); free(str); }
//--------------------------------------------------------------------------- static void createPatch(int id) { rpatch_t *patch; const int patchNum = id; const patch_t *oldPatch; const column_t *oldColumn, *oldPrevColumn, *oldNextColumn; int x, y; int pixelDataSize; int columnsDataSize; int postsDataSize; int dataSize; int *numPostsInColumn; int numPostsTotal; const unsigned char *oldColumnPixelData; int numPostsUsedSoFar; int edgeSlope; #ifdef RANGECHECK if (id >= numlumps) I_Error("createPatch: %i >= numlumps", id); #endif if (!CheckIfPatch(patchNum)) { I_Error("createPatch: Unknown patch format %s.", (patchNum < numlumps ? lumpinfo[patchNum].name : NULL)); } oldPatch = (const patch_t*)W_CacheLumpNum(patchNum); patch = &patches[id]; // proff - 2003-02-16 What about endianess? patch->width = LittleShort(oldPatch->width); patch->widthmask = 0; patch->height = LittleShort(oldPatch->height); patch->leftoffset = LittleShort(oldPatch->leftoffset); patch->topoffset = LittleShort(oldPatch->topoffset); patch->flags = 0; if (getPatchIsNotTileable(oldPatch)) patch->flags |= PATCH_ISNOTTILEABLE; #ifdef GL_DOOM // Width of M_THERMM patch is 9, but Doom interprets it as 8-columns lump // during drawing. It is not a problem for software mode and GL_NEAREST, // but looks wrong with filtering. So I need to patch it during loading. if (V_GetMode() == VID_MODEGL) { if (!strncasecmp(lumpinfo[id].name, "M_THERMM", 8) && patch->width > 8) { patch->width--; } } #endif // 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 + LittleLong(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 + LittleLong(oldPatch->columnofs[x])); if (patch->flags&PATCH_ISNOTTILEABLE) { // non-tiling if (x == 0) oldPrevColumn = 0; else oldPrevColumn = (const column_t *)((const byte *)oldPatch + LittleLong(oldPatch->columnofs[x-1])); if (x == patch->width-1) oldNextColumn = 0; else oldNextColumn = (const column_t *)((const byte *)oldPatch + LittleLong(oldPatch->columnofs[x+1])); } else { // tiling int prevColumnIndex = x-1; int nextColumnIndex = x+1; while (prevColumnIndex < 0) prevColumnIndex += patch->width; while (nextColumnIndex >= patch->width) nextColumnIndex -= patch->width; oldPrevColumn = (const column_t *)((const byte *)oldPatch + LittleLong(oldPatch->columnofs[prevColumnIndex])); oldNextColumn = (const column_t *)((const byte *)oldPatch + LittleLong(oldPatch->columnofs[nextColumnIndex])); } // setup the column's data patch->columns[x].pixels = patch->pixels + (x*patch->height) + 0; 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; patch->posts[numPostsUsedSoFar].slope = 0; edgeSlope = getColumnEdgeSlope(oldPrevColumn, oldNextColumn, top); if (edgeSlope == 1) patch->posts[numPostsUsedSoFar].slope |= RDRAW_EDGESLOPE_TOP_UP; else if (edgeSlope == -1) patch->posts[numPostsUsedSoFar].slope |= RDRAW_EDGESLOPE_TOP_DOWN; edgeSlope = getColumnEdgeSlope(oldPrevColumn, oldNextColumn, top+len); if (edgeSlope == 1) patch->posts[numPostsUsedSoFar].slope |= RDRAW_EDGESLOPE_BOT_UP; else if (edgeSlope == -1) patch->posts[numPostsUsedSoFar].slope |= RDRAW_EDGESLOPE_BOT_DOWN; // 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++; } } if (1 || (patch->flags&PATCH_ISNOTTILEABLE)) { const rcolumn_t *column, *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++) { //oldColumn = (const column_t *)((const byte *)oldPatch + oldPatch->columnofs[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) { // copy the color from the left column->pixels[y] = prevColumn->pixels[y]; } else { // copy the color from above column->pixels[y] = column->pixels[y-1]; } } } // verify that the patch truly is non-rectangular since // this determines tiling later on } W_UnlockLumpNum(patchNum); free(numPostsInColumn); }