fteqw/plugins/cod/codiwi.c

120 lines
3.5 KiB
C

#include "../plugin.h"
static plugimagefuncs_t *imagefuncs;
static struct pendingtextureinfo *Image_ReadIWIFile(unsigned int imgflags, const char *fname, qbyte *filedata, size_t filesize)
{
if (filesize >= 12 && filedata[0]=='I'&&filedata[1]=='W'&&filedata[2]=='i' && (filedata[3]==5/*cod2*/||filedata[3]==6/*cod4*/))
{
static const enum uploadfmt fmts[] = {PTI_INVALID/*0*/, PTI_RGBA8/*1*/, PTI_RGB8/*2*/, PTI_L8A8/*3, VALIDATE!*/, PTI_INVALID/*4,PTI_A8*/, PTI_INVALID/*5*/,PTI_INVALID/*6*/,PTI_INVALID/*7*/,PTI_INVALID/*8*/,PTI_INVALID/*9*/,PTI_INVALID/*10*/,PTI_BC1_RGBA/*11*/, PTI_BC2_RGBA/*12*/, PTI_BC3_RGBA/*13*/};
enum uploadfmt fmt = PTI_INVALID;
unsigned int bb,bw,bh,bd;
unsigned int iw,ih,id, l;
struct pendingtextureinfo *mips;
unsigned int offsets[4];
qbyte *end = filedata+filesize;
enum {
IWI_STANDARD=0,
IWI_MIPLESS=3,
IWI_CUBEMAP=6,
// IWI_NORMALMAP=0x20,
// IWI_UNKNOWN=0x40,
// IWI_UNKNOWN=0x80,
} usage = filedata[5];
if (filedata[4] < countof(fmts))
fmt = fmts[filedata[4]];
if (fmt == PTI_INVALID)
{ //bail. with warning
Con_Printf(CON_WARNING"Image_ReadIWIFile(%s): unsupported iwi pixelformat %x\n", fname, filedata[4]);
return NULL;
}
iw = filedata[6] | (filedata[7]<<8);
ih = filedata[8] | (filedata[9]<<8);
id = filedata[10] | (filedata[11]<<8);
imagefuncs->BlockSizeForEncoding(fmt, &bb, &bw, &bh, &bd);
if (!bb)
{
Con_Printf(CON_WARNING"Image_ReadIWIFile(%s): unsupported fte pixelformat %x(%i)\n", fname, filedata[4], fmt);
return NULL;
}
mips = plugfuncs->Malloc(sizeof(*mips));
mips->encoding = fmt;
if ((filedata[5]&0xf) == IWI_CUBEMAP && id==1)
{
mips->type = PTI_CUBE;
id *= 6;
}
else
mips->type = (id>1)?PTI_3D:PTI_2D;
mips->extrafree = filedata;
filedata += 12;
for (l = 0; l < countof(offsets); l++, filedata+=4)
offsets[l] = filedata[0] | (filedata[1]<<8) | (filedata[2]<<16) | (filedata[3]<<24); //dunno what this 4 values are for. looks like descending ends?
if (mips->type != PTI_2D || (usage&0xf)==IWI_MIPLESS)
mips->mipcount = l = 1;
else for (l = 0; l < countof(mips->mip); l++)
{
if ((iw >> l) || (ih >> l) || (id >> l))
mips->mipcount++;
else
break;
}
//these are smallest to biggest.
while (l --> 0)
{
unsigned int w = iw>>l;
unsigned int h = ih>>l;
unsigned int d = (mips->type==PTI_3D)?id>>l:id;
size_t datasize;
if (!w && !h && ((mips->type==PTI_3D)?!d:true))
break;
if (!w)
w = 1;
if (!h)
h = 1;
if (!d)
d = 1;
datasize = ((w+bw-1)/bw) * ((h+bh-1)/bh) * ((d+bd-1)/bd) * bb;
if (filedata + datasize > end)
{
Con_Printf(CON_WARNING"%s: truncated\n", fname);
Con_Printf("%s: %#x\n", fname, usage);
plugfuncs->Free(mips);
return NULL; //doesn't fit...
}
mips->mip[l].width = w;
mips->mip[l].height = h;
mips->mip[l].depth = d;
mips->mip[l].data = filedata;
mips->mip[l].datasize = datasize;
mips->mip[l].needfree = false;
filedata += datasize;
}
if (filedata != end)
{
Con_Printf(CON_WARNING"%s: trailing data\n", fname);
Con_Printf("%s: %#x\n", fname, usage);
plugfuncs->Free(mips);
return NULL; //doesn't fit...
}
return mips;
}
return NULL;
}
static plugimageloaderfuncs_t iwifuncs =
{
"InfinityWard Image",
sizeof(struct pendingtextureinfo),
false,
Image_ReadIWIFile,
};
qboolean IWI_Init(void)
{
imagefuncs = plugfuncs->GetEngineInterface(plugimagefuncs_name, sizeof(*imagefuncs));
if (!imagefuncs)
return false;
return plugfuncs->ExportInterface(plugimageloaderfuncs_name, &iwifuncs, sizeof(iwifuncs));
}