/* = RTS_AddFile = = All files are optional, but at least one file must be found = Files with a .rts extension are wadlink files with multiple lumps = Other files are single lumps with the base filename for the lump name */ static int32_t RTS_AddFile(const char *filename) { wadinfo_t header; int32_t i, handle, length, startlump; filelump_t *fileinfo, *fileinfoo; // read the entire file in // FIXME: shared opens handle = kopen4loadfrommod(filename, 0); if (handle < 0) { initprintf("RTS file \"%s\" was not found\n",filename); return -1; } startlump = rts_numlumps; // WAD file i = kread(handle, &header, sizeof(header)); if (i != sizeof(header) || Bmemcmp(header.identification, "IWAD", 4)) { initprintf("RTS file \"%s\" too short or doesn't have IWAD id\n", filename); kclose(handle); return -1; } header.numlumps = B_LITTLE32(header.numlumps); header.infotableofs = B_LITTLE32(header.infotableofs); length = header.numlumps*sizeof(filelump_t); fileinfo = fileinfoo = (filelump_t *)Xmalloc(length); klseek(handle, header.infotableofs, SEEK_SET); kread(handle, fileinfo, length); { lumpinfo_t *lump_p = (lumpinfo_t *)Xrealloc( rts_lumpinfo, (rts_numlumps + header.numlumps)*sizeof(lumpinfo_t)); rts_lumpinfo = lump_p; } rts_numlumps += header.numlumps; for (i=startlump; i<rts_numlumps; i++, fileinfo++) { lumpinfo_t *lump = &rts_lumpinfo[i]; lump->handle = handle; // NOTE: cache1d-file is not closed! lump->position = B_LITTLE32(fileinfo->filepos); lump->size = B_LITTLE32(fileinfo->size); Bstrncpy(lump->name, fileinfo->name, 8); } Bfree(fileinfoo); return 0; }
// <length> is the file size, for consistency checking. int32_t ANIM_LoadAnim(const uint8_t *buffer, int32_t length) { int32_t i; length -= sizeof(lpfileheader)+128+768; if (length < 0) return -1; anim = (anim_t *)Xrealloc(anim, sizeof(anim_t)); anim->curlpnum = 0xffff; anim->currentframe = -1; // this just modifies the data in-place instead of copying it elsewhere now anim->lpheader = (lpfileheader *)(anim->buffer = (uint8_t *)buffer); anim->lpheader->id = B_LITTLE32(anim->lpheader->id); anim->lpheader->maxLps = B_LITTLE16(anim->lpheader->maxLps); anim->lpheader->nLps = B_LITTLE16(anim->lpheader->nLps); anim->lpheader->nRecords = B_LITTLE32(anim->lpheader->nRecords); anim->lpheader->maxRecsPerLp = B_LITTLE16(anim->lpheader->maxRecsPerLp); anim->lpheader->lpfTableOffset = B_LITTLE16(anim->lpheader->lpfTableOffset); anim->lpheader->contentType = B_LITTLE32(anim->lpheader->contentType); anim->lpheader->width = B_LITTLE16(anim->lpheader->width); anim->lpheader->height = B_LITTLE16(anim->lpheader->height); anim->lpheader->nFrames = B_LITTLE32(anim->lpheader->nFrames); anim->lpheader->framesPerSecond = B_LITTLE16(anim->lpheader->framesPerSecond); length -= anim->lpheader->nLps * sizeof(lp_descriptor); if (length < 0) return -2; buffer += sizeof(lpfileheader)+128; // load the color palette for (i = 0; i < 768; i += 3) { anim->pal[i+2] = *buffer++; anim->pal[i+1] = *buffer++; anim->pal[i] = *buffer++; buffer++; } // set up large page descriptors anim->LpArray = (lp_descriptor *)buffer; // theoretically we should be able to play files with more than 256 frames now // assuming the utilities to create them can make them that way for (i = 0; i < anim->lpheader->nLps; i++) { anim->LpArray[i].baseRecord = B_LITTLE16(anim->LpArray[i].baseRecord); anim->LpArray[i].nRecords = B_LITTLE16(anim->LpArray[i].nRecords); anim->LpArray[i].nBytes = B_LITTLE16(anim->LpArray[i].nBytes); } return 0; }
void ANIM_LoadAnim (char * buffer) { uint16 i; int32 size; if (!Anim_Started) { anim = SafeMalloc(sizeof(anim_t)); Anim_Started = true; } anim->buffer = buffer; anim->curlpnum = 0xffff; anim->currentframe = -1; size = sizeof(lpfileheader); Bmemcpy(&anim->lpheader, buffer, size ); anim->lpheader.id = B_LITTLE32(anim->lpheader.id); anim->lpheader.maxLps = B_LITTLE16(anim->lpheader.maxLps); anim->lpheader.nLps = B_LITTLE16(anim->lpheader.nLps); anim->lpheader.nRecords = B_LITTLE32(anim->lpheader.nRecords); anim->lpheader.maxRecsPerLp = B_LITTLE16(anim->lpheader.maxRecsPerLp); anim->lpheader.lpfTableOffset = B_LITTLE16(anim->lpheader.lpfTableOffset); anim->lpheader.contentType = B_LITTLE32(anim->lpheader.contentType); anim->lpheader.width = B_LITTLE16(anim->lpheader.width); anim->lpheader.height = B_LITTLE16(anim->lpheader.height); anim->lpheader.nFrames = B_LITTLE32(anim->lpheader.nFrames); anim->lpheader.framesPerSecond = B_LITTLE16(anim->lpheader.framesPerSecond); buffer += size+128; // load the color palette for (i = 0; i < 768; i += 3) { anim->pal[i+2] = *buffer++; anim->pal[i+1] = *buffer++; anim->pal[i] = *buffer++; buffer++; } // read in large page descriptors size = sizeof(anim->LpArray); Bmemcpy(&anim->LpArray,buffer,size); for (i = 0; i < size/sizeof(lp_descriptor); i++) { anim->LpArray[i].baseRecord = B_LITTLE16(anim->LpArray[i].baseRecord); anim->LpArray[i].nRecords = B_LITTLE16(anim->LpArray[i].nRecords); anim->LpArray[i].nBytes = B_LITTLE16(anim->LpArray[i].nBytes); } }
void loadwaves(void) { long fil, dawaversionum, i, tmp; long wavleng[MAXWAVES], repstart[MAXWAVES], repleng[MAXWAVES], finetune[MAXWAVES]; char *p; fil = kopen4load("WAVES.KWV", 0); if (fil != -1) { kread(fil, &dawaversionum, 4); dawaversionum = B_LITTLE32(dawaversionum); if (dawaversionum != 0) { kclose(fil); return; } kread(fil, &numwaves, 4); numwaves = B_LITTLE32(numwaves); for (i=0; i<numwaves; i++) { kread(fil, &instname[i][0], 16); kread(fil, &wavleng[i], 4); wavleng[i] = B_LITTLE32(wavleng[i]); kread(fil, &repstart[i], 4); repstart[i] = B_LITTLE32(repstart[i]); kread(fil, &repleng[i], 4); repleng[i] = B_LITTLE32(repleng[i]); kread(fil, &finetune[i], 4); finetune[i] = B_LITTLE32(finetune[i]); } } else { dawaversionum = 0; numwaves = 0; } for (i=numwaves; i<MAXWAVES; i++) { memset(&instname[i][0], 0, 16); wavleng[i] = 0; repstart[i] = 0; repleng[i] = 0; finetune[i] = 0; samples[i] = NULL; } if (fil == -1) return; #if 0 for (i=0; i<numwaves; i++) { if (repleng[i]) tmp = FSOUND_LOOP_NORMAL; else tmp = FSOUND_LOOP_OFF; samples[i] = FSOUND_Sample_Alloc(FSOUND_FREE, wavleng[i], tmp, 11025, 255, 128, 1); if (!samples[i]) continue; p = (char*)Bmalloc(wavleng[i]); kread(fil,p,wavleng[i]); FSOUND_Sample_Upload(samples[i], p, FSOUND_8BITS | FSOUND_MONO | FSOUND_UNSIGNED); Bfree(p); if (repleng[i]) FSOUND_Sample_SetLoopPoints(samples[i], repstart[i], repstart[i]+repleng[i]); } #endif kclose(fil); printOSD("Loaded %d waves\n", numwaves); }
int writeicon(FILE *fp, struct icon *ico) { int i; Bfprintf(fp, "#include \"sdlayer.h\"\n" "\n" ); Bfprintf(fp,"static unsigned int sdlappicon_pixels[] = {\n"); for (i=0;i<ico->width*ico->height;i++) { if ((i%6) == 0) Bfprintf(fp,"\t"); else Bfprintf(fp," "); Bfprintf(fp, "0x%08lx,", (long)B_LITTLE32(ico->pixels[i])); if ((i%6) == 5) Bfprintf(fp,"\n"); } if ((i%16) > 0) Bfprintf(fp, "\n"); Bfprintf(fp, "};\n\n"); Bfprintf(fp,"static unsigned char sdlappicon_mask[] = {\n"); for (i=0;i<((ico->width+7)/8)*ico->height;i++) { if ((i%14) == 0) Bfprintf(fp,"\t"); else Bfprintf(fp," "); Bfprintf(fp, "%3d,", ico->mask[i]); if ((i%14) == 13) Bfprintf(fp,"\n"); } if ((i%16) > 0) Bfprintf(fp, "\n"); Bfprintf(fp, "};\n\n"); Bfprintf(fp, "struct sdlappicon sdlappicon = {\n" " %d,%d, // width,height\n" " sdlappicon_pixels,\n" " sdlappicon_mask\n" "};\n", ico->width, ico->height ); return 0; }
/** * Stores a PTCacheTile into the cache. * @param tdef a PTCacheTile entry fully completed * @return !0 on success */ int PTCacheWriteTile(PTCacheTile * tdef) { long i; PTCacheIndex * pci; FILE * fh; off_t offset; char createmode[] = "ab"; if (cachedisabled) { return 0; } if (cachereplace) { createmode[0] = 'w'; cachereplace = 0; } // 1. write the tile data to the storage file fh = fopen(CACHESTORAGEFILE, createmode); if (!fh) { cachedisabled = 1; initprintf("PolymostTexCache: error opening %s, texture cache disabled\n", CACHESTORAGEFILE); return 0; } // apparently opening in append doesn't actually put the // file pointer at the end of the file like you would // imagine, so the ftell doesn't return the length of the // file like you'd expect it should fseek(fh, 0, SEEK_END); offset = ftell(fh); if (offset == 0) { // new file const int8_t storagesig[16] = { 'P','o','l','y','m','o','s','t','T','e','x','S','t','o','r',CACHEVER }; if (fwrite(storagesig, 16, 1, fh) != 1) { goto fail; } offset = 16; } { int32_t tsizx, tsizy; int32_t format, flags, nmipmaps; tsizx = B_LITTLE32(tdef->tsizx); tsizy = B_LITTLE32(tdef->tsizy); flags = tdef->flags & (PTH_CLAMPED | PTH_HASALPHA); flags = B_LITTLE32(flags); format = B_LITTLE32(tdef->format); nmipmaps = B_LITTLE32(tdef->nummipmaps); if (fwrite(&tsizx, 4, 1, fh) != 1 || fwrite(&tsizy, 4, 1, fh) != 1 || fwrite(&flags, 4, 1, fh) != 1 || fwrite(&format, 4, 1, fh) != 1 || fwrite(&nmipmaps, 4, 1, fh) != 1) { goto fail; } } for (i = 0; i < tdef->nummipmaps; i++) { int32_t sizx, sizy; int32_t length; sizx = B_LITTLE32(tdef->mipmap[i].sizx); sizy = B_LITTLE32(tdef->mipmap[i].sizy); length = B_LITTLE32(tdef->mipmap[i].length); if (fwrite(&sizx, 4, 1, fh) != 1 || fwrite(&sizy, 4, 1, fh) != 1 || fwrite(&length, 4, 1, fh) != 1) { goto fail; } if (fwrite(tdef->mipmap[i].data, tdef->mipmap[i].length, 1, fh) != 1) { // truncated data goto fail; } } fclose(fh); // 2. append to the index fh = fopen(CACHEINDEXFILE, createmode); if (!fh) { cachedisabled = 1; initprintf("PolymostTexCache: error opening %s, texture cache disabled\n", CACHEINDEXFILE); return 0; } fseek(fh, 0, SEEK_END); if (ftell(fh) == 0) { // new file const int8_t indexsig[16] = { 'P','o','l','y','m','o','s','t','T','e','x','I','n','d','x',CACHEVER }; if (fwrite(indexsig, 16, 1, fh) != 1) { goto fail; } } { int8_t filename[BMAX_PATH]; int32_t effects, offsett, flags, mtime; memset(filename, 0, sizeof(filename)); strncpy((char *) filename, tdef->filename, sizeof(filename)); effects = B_LITTLE32(tdef->effects); flags = tdef->flags & (PTH_CLAMPED); // we don't want the informational flags in the index flags = B_LITTLE32(flags); offsett = B_LITTLE32(offset); mtime = 0; if (fwrite(filename, sizeof(filename), 1, fh) != 1 || fwrite(&effects, 4, 1, fh) != 1 || fwrite(&flags, 4, 1, fh) != 1 || fwrite(&offsett, 4, 1, fh) != 1 || fwrite(&mtime, 4, 1, fh) != 1) { goto fail; } } fclose(fh); // stow the data into the index in memory pci = ptcache_findhash(tdef->filename, tdef->effects, tdef->flags); if (pci) { // superseding an old hash entry pci->offset = offset; } else { ptcache_addhash(tdef->filename, tdef->effects, tdef->flags, offset); } return 1; fail: cachedisabled = 1; initprintf("PolymostTexCache: error writing to cache, texture cache disabled\n"); if (fh) fclose(fh); return 0; }
/** * Does the task of loading a tile from the cache * @param offset the starting offset * @return a PTCacheTile entry fully completed */ static PTCacheTile * ptcache_load(off_t offset) { int32_t tsizx, tsizy; int32_t sizx, sizy; int32_t flags; int32_t format; int32_t nmipmaps, i; int32_t length; PTCacheTile * tdef = 0; FILE * fh; if (cachereplace) { // cache is in a broken state, so don't try loading return 0; } fh = fopen(CACHESTORAGEFILE, "rb"); if (!fh) { cachedisabled = 1; initprintf("PolymostTexCache: error opening %s, texture cache disabled\n", CACHESTORAGEFILE); return 0; } fseek(fh, offset, SEEK_SET); if (fread(&tsizx, 4, 1, fh) != 1 || fread(&tsizy, 4, 1, fh) != 1 || fread(&flags, 4, 1, fh) != 1 || fread(&format, 4, 1, fh) != 1 || fread(&nmipmaps, 4, 1, fh) != 1) { // truncated entry, so throw the whole cache away goto fail; } tsizx = B_LITTLE32(tsizx); tsizy = B_LITTLE32(tsizy); flags = B_LITTLE32(flags); format = B_LITTLE32(format); nmipmaps = B_LITTLE32(nmipmaps); tdef = PTCacheAllocNewTile(nmipmaps); tdef->tsizx = tsizx; tdef->tsizy = tsizy; tdef->flags = flags; tdef->format = format; for (i = 0; i < nmipmaps; i++) { if (fread(&sizx, 4, 1, fh) != 1 || fread(&sizy, 4, 1, fh) != 1 || fread(&length, 4, 1, fh) != 1) { // truncated entry, so throw the whole cache away goto fail; } sizx = B_LITTLE32(sizx); sizy = B_LITTLE32(sizy); length = B_LITTLE32(length); tdef->mipmap[i].sizx = sizx; tdef->mipmap[i].sizy = sizy; tdef->mipmap[i].length = length; tdef->mipmap[i].data = (unsigned char *) malloc(length); if (fread(tdef->mipmap[i].data, length, 1, fh) != 1) { // truncated data goto fail; } } fclose(fh); return tdef; fail: cachereplace = 1; initprintf("PolymostTexCache: corrupt texture cache detected, cache will be replaced\n"); PTCacheUnloadIndex(); fclose(fh); if (tdef) { PTCacheFreeTile(tdef); } return 0; }
/** * Loads the cache index file into memory */ void PTCacheLoadIndex(void) { FILE * fh = 0; int8_t sig[16]; const int8_t indexsig[16] = { 'P','o','l','y','m','o','s','t','T','e','x','I','n','d','x',CACHEVER }; const int8_t storagesig[16] = { 'P','o','l','y','m','o','s','t','T','e','x','S','t','o','r',CACHEVER }; int8_t filename[BMAX_PATH+1]; int32_t effects; int32_t flags; int32_t offset; int32_t mtime; PTCacheIndex * pci; int total = 0, dups = 0; int haveindex = 0, havestore = 0; memset(filename, 0, sizeof(filename)); // first, check the cache storage file's signature. // we open for reading and writing to test permission fh = fopen(CACHESTORAGEFILE, "r+b"); if (fh) { havestore = 1; if (fread(sig, 16, 1, fh) != 1 || memcmp(sig, storagesig, 16)) { cachereplace = 1; } fclose(fh); } else { if (errno == ENOENT) { // file doesn't exist, which is fine ; } else { initprintf("PolymostTexCache: error opening %s, texture cache disabled\n", CACHESTORAGEFILE); cachedisabled = 1; return; } } // next, check the index fh = fopen(CACHEINDEXFILE, "r+b"); if (fh) { haveindex = 1; if (fread(sig, 16, 1, fh) != 1 || memcmp(sig, indexsig, 16)) { cachereplace = 1; } } else { if (errno == ENOENT) { // file doesn't exist, which is fine return; } else { initprintf("PolymostTexCache: error opening %s, texture cache disabled\n", CACHEINDEXFILE); cachedisabled = 1; return; } } // if we're missing either the index or the store, but not both at the same // time, the cache is broken and should be replaced if ((!haveindex || !havestore) && !(!haveindex && !havestore)) { cachereplace = 1; } if (cachereplace) { initprintf("PolymostTexCache: texture cache will be replaced\n"); if (fh) { fclose(fh); } return; } // now that the index is sitting at the first entry, load everything while (!feof(fh)) { if (fread(filename, BMAX_PATH, 1, fh) != 1 && feof(fh)) { break; } if (fread(&effects, 4, 1, fh) != 1 || fread(&flags, 4, 1, fh) != 1 || fread(&offset, 4, 1, fh) != 1 || fread(&mtime, 4, 1, fh) != 1) { // truncated entry, so throw the whole cache away initprintf("PolymostTexCache: corrupt texture cache index detected, cache will be replaced\n"); cachereplace = 1; PTCacheUnloadIndex(); break; } effects = B_LITTLE32(effects); flags = B_LITTLE32(flags); offset = B_LITTLE32(offset); mtime = B_LITTLE32(mtime); pci = ptcache_findhash((char *) filename, (int) effects, (int) flags); if (pci) { // superseding an old hash entry pci->offset = (off_t) offset; dups++; } else { ptcache_addhash((char *) filename, (int) effects, (int) flags, (off_t) offset); } total++; } fclose(fh); initprintf("PolymostTexCache: cache index loaded (%d entries, %d old entries skipped)\n", total, dups); }
static int32_t texcache_loadmips(const texcacheheader *head, GLenum *glerr, int32_t *xsiz, int32_t *ysiz) { int32_t level; texcachepicture pict; char *pic = NULL, *packbuf = NULL; void *midbuf = NULL; int32_t alloclen=0; for (level = 0; level==0 || (pict.xdim > 1 || pict.ydim > 1); level++) { GLint format; if (texcache_readdata(&pict, sizeof(texcachepicture))) { TEXCACHE_FREEBUFS(); return TEXCACHERR_BUFFERUNDERRUN; } // external (little endian) -> native pict.size = B_LITTLE32(pict.size); pict.format = B_LITTLE32(pict.format); pict.xdim = B_LITTLE32(pict.xdim); pict.ydim = B_LITTLE32(pict.ydim); pict.border = B_LITTLE32(pict.border); pict.depth = B_LITTLE32(pict.depth); if (level == 0) { if (xsiz) *xsiz = pict.xdim; if (ysiz) *ysiz = pict.ydim; } if (alloclen < pict.size) { pic = (char *)Xrealloc(pic, pict.size); alloclen = pict.size; packbuf = (char *)Xrealloc(packbuf, alloclen+16); midbuf = (void *)Xrealloc(midbuf, pict.size); } if (dedxtfilter(texcache.filehandle, &pict, pic, midbuf, packbuf, (head->flags & CACHEAD_COMPRESSED)!=0)) { TEXCACHE_FREEBUFS(); return TEXCACHERR_DEDXT; } bglCompressedTexImage2DARB(GL_TEXTURE_2D,level,pict.format,pict.xdim,pict.ydim,pict.border,pict.size,pic); if ((*glerr=bglGetError()) != GL_NO_ERROR) { TEXCACHE_FREEBUFS(); return TEXCACHERR_COMPTEX; } bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_INTERNAL_FORMAT, &format); if ((*glerr = bglGetError()) != GL_NO_ERROR) { TEXCACHE_FREEBUFS(); return TEXCACHERR_GETTEXLEVEL; } if (pict.format != format) { OSD_Printf("gloadtile_cached: invalid texture cache file format %d %d\n", pict.format, format); TEXCACHE_FREEBUFS(); return -1; } } TEXCACHE_FREEBUFS(); return 0; }
void texcache_writetex(const char *fn, int32_t len, int32_t dameth, char effect, texcacheheader *head) { static GLint glGetTexLevelParameterivOK = GL_TRUE; char cachefn[BMAX_PATH]; char *pic = NULL, *packbuf = NULL; void *midbuf = NULL; uint32_t alloclen=0, level; uint32_t padx=0, pady=0; GLint gi; int32_t offset = 0; if (!texcache_enabled()) return; gi = GL_FALSE; bglGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_ARB, &gi); if (gi != GL_TRUE) { if (glGetTexLevelParameterivOK == GL_TRUE) { OSD_Printf("Error: glGetTexLevelParameteriv returned GL_FALSE!\n"); glGetTexLevelParameterivOK = GL_FALSE; } return; } Blseek(texcache.filehandle, 0, BSEEK_END); offset = Blseek(texcache.filehandle, 0, BSEEK_CUR); // OSD_Printf("Caching %s, offset 0x%x\n", cachefn, offset); Bmemcpy(head->magic, TEXCACHEMAGIC, 4); // sizes are set by caller if (glusetexcache == 2) head->flags |= CACHEAD_COMPRESSED; // native -> external (little-endian) head->xdim = B_LITTLE32(head->xdim); head->ydim = B_LITTLE32(head->ydim); head->flags = B_LITTLE32(head->flags); head->quality = B_LITTLE32(head->quality); if (Bwrite(texcache.filehandle, head, sizeof(texcacheheader)) != sizeof(texcacheheader)) goto failure; CLEAR_GL_ERRORS(); for (level = 0; level==0 || (padx > 1 || pady > 1); level++) { uint32_t miplen; texcachepicture pict; bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_COMPRESSED_ARB, &gi); WRITEX_FAIL_ON_ERROR(); if (gi != GL_TRUE) goto failure; // an uncompressed mipmap bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_INTERNAL_FORMAT, &gi); WRITEX_FAIL_ON_ERROR(); #ifdef __APPLE__ if (pr_ati_textureformat_one && gi == 1) gi = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; #endif // native -> external (little endian) pict.format = B_LITTLE32(gi); bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, &gi); WRITEX_FAIL_ON_ERROR(); padx = gi; pict.xdim = B_LITTLE32(gi); bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_HEIGHT, &gi); WRITEX_FAIL_ON_ERROR(); pady = gi; pict.ydim = B_LITTLE32(gi); bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_BORDER, &gi); WRITEX_FAIL_ON_ERROR(); pict.border = B_LITTLE32(gi); bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_DEPTH, &gi); WRITEX_FAIL_ON_ERROR(); pict.depth = B_LITTLE32(gi); bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &gi); WRITEX_FAIL_ON_ERROR(); miplen = gi; pict.size = B_LITTLE32(gi); if (alloclen < miplen) { pic = (char *)Xrealloc(pic, miplen); alloclen = miplen; packbuf = (char *)Xrealloc(packbuf, alloclen); midbuf = (void *)Xrealloc(midbuf, miplen); } bglGetCompressedTexImageARB(GL_TEXTURE_2D, level, pic); WRITEX_FAIL_ON_ERROR(); if (Bwrite(texcache.filehandle, &pict, sizeof(texcachepicture)) != sizeof(texcachepicture)) goto failure; if (dxtfilter(texcache.filehandle, &pict, pic, midbuf, packbuf, miplen)) goto failure; } { texcacheindex *t; int32_t i = hash_find(&texcache.hashes, texcache_calcid(cachefn, fn, len, dameth, effect)); if (i > -1) { // update an existing entry t = texcache.iptrs[i]; t->offset = offset; t->len = Blseek(texcache.filehandle, 0, BSEEK_CUR) - t->offset; /*initprintf("%s %d got a match for %s offset %d\n",__FILE__, __LINE__, cachefn,offset);*/ } else { t = texcache.currentindex; Bstrcpy(t->name, cachefn); t->offset = offset; t->len = Blseek(texcache.filehandle, 0, BSEEK_CUR) - t->offset; t->next = (texcacheindex *)Xcalloc(1, sizeof(texcacheindex)); hash_add(&texcache.hashes, cachefn, texcache.numentries, 0); if (++texcache.numentries > texcache.iptrcnt) { texcache.iptrcnt += 512; texcache.iptrs = (texcacheindex **) Xrealloc(texcache.iptrs, sizeof(intptr_t) * texcache.iptrcnt); } texcache.iptrs[texcache.numentries-1] = t; texcache.currentindex = t->next; } if (texcache.index) { fseek(texcache.index, 0, BSEEK_END); Bfprintf(texcache.index, "%s %d %d\n", t->name, t->offset, t->len); } else OSD_Printf("wtf?\n"); } goto success; failure: initprintf("ERROR: cache failure!\n"); texcache.currentindex->offset = 0; Bmemset(texcache.currentindex->name,0,sizeof(texcache.currentindex->name)); success: TEXCACHE_FREEBUFS(); }
// returns 1 on success int32_t texcache_readtexheader(const char *fn, int32_t len, int32_t dameth, char effect, texcacheheader *head, int32_t modelp) { int32_t i, err = 0; char cachefn[BMAX_PATH]; if (!texcache_enabled()) return 0; i = hash_find(&texcache.hashes, texcache_calcid(cachefn, fn, len, dameth, effect)); if (i < 0 || !texcache.iptrs[i]) return 0; // didn't find it texcache.filepos = texcache.iptrs[i]->offset; // initprintf("%s %d got a match for %s offset %d\n",__FILE__, __LINE__, cachefn,offset); if (texcache_readdata(head, sizeof(texcacheheader))) READTEXHEADER_FAILURE(0); if (Bmemcmp(head->magic, TEXCACHEMAGIC, 4)) READTEXHEADER_FAILURE(1); // native (little-endian) -> internal head->xdim = B_LITTLE32(head->xdim); head->ydim = B_LITTLE32(head->ydim); head->flags = B_LITTLE32(head->flags); head->quality = B_LITTLE32(head->quality); if (modelp && head->quality != r_downsize) READTEXHEADER_FAILURE(2); if ((head->flags & CACHEAD_COMPRESSED) && glusetexcache != 2) READTEXHEADER_FAILURE(3); if (!(head->flags & CACHEAD_COMPRESSED) && glusetexcache == 2) READTEXHEADER_FAILURE(4); // handle nocompress if (!modelp && !(head->flags & CACHEAD_NOCOMPRESS) && head->quality != r_downsize) return 0; if (gltexmaxsize && (head->xdim > (1<<gltexmaxsize) || head->ydim > (1<<gltexmaxsize))) READTEXHEADER_FAILURE(5); if (!glinfo.texnpot && (head->flags & CACHEAD_NONPOW2)) READTEXHEADER_FAILURE(6); return 1; failure: { static const char *error_msgs[] = { "failed reading texture cache header", // 0 "header magic string doesn't match", // 1 "r_downsize doesn't match", // 2 (skins only) "compression doesn't match: cache contains compressed tex", // 3 "compression doesn't match: cache contains uncompressed tex", // 4 "texture in cache exceeds maximum supported size", // 5 "texture in cache has non-power-of-two size, unsupported", // 6 }; initprintf("%s cache miss: %s\n", modelp?"Skin":"Texture", error_msgs[err]); } return 0; }