예제 #1
0
파일: rts.c 프로젝트: SilkyPantsDan/eduke32
/*
= 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;
}
예제 #2
0
파일: animlib.c 프로젝트: dahlor/Duke3DS
// <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;
}
예제 #3
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);
      }
   }
예제 #4
0
파일: sound.c 프로젝트: wosigh/duke3d
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);
}
예제 #5
0
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;
}
예제 #6
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;
}
예제 #7
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;
}
예제 #8
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);
}
예제 #9
0
파일: texcache.c 프로젝트: clobber/eduke32
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;
}
예제 #10
0
파일: texcache.c 프로젝트: clobber/eduke32
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();
}
예제 #11
0
파일: texcache.c 프로젝트: clobber/eduke32
// 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;
}