Fix support for extended mips.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5748 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2020-08-18 01:59:55 +00:00
parent da6b6c3e6c
commit 8dcf4db927

View file

@ -473,7 +473,7 @@ struct opts_s
};
static qboolean ImgTool_MipExport(struct opts_s *args, vfsfile_t *outfile, struct pendingtextureinfo *in, const char *mipname, int wadtype);
static struct pendingtextureinfo *ImgTool_DecodeMiptex(struct opts_s *args, miptex_t *mip);
static struct pendingtextureinfo *ImgTool_DecodeMiptex(struct opts_s *args, miptex_t *mip, size_t fsize);
void Image_GenerateMips(struct pendingtextureinfo *mips, unsigned int flags);
int Image_WritePNG (const char *filename, enum fs_relative fsroot, int compression, void **buffers, int numbuffers, qintptr_t bufferstride, int width, int height, enum uploadfmt fmt, qboolean writemetadata);
qboolean WriteTGA(const char *filename, enum fs_relative fsroot, const qbyte *fte_restrict rgb_buffer, qintptr_t bytestride, int width, int height, enum uploadfmt fmt);
@ -838,7 +838,7 @@ static struct pendingtextureinfo *ImgTool_Read(struct opts_s *args, const char *
{
const char *ex = COM_GetFileExtension(inname, NULL);
if (!strcasecmp(ex, ".mip"))
in = ImgTool_DecodeMiptex(args, (miptex_t*)indata);
in = ImgTool_DecodeMiptex(args, (miptex_t*)indata, fsize);
else
in = Image_LoadMipsFromMemory(args->flags|IF_NOMIPMAP, inname, inname, indata, fsize);
if (!in)
@ -1230,10 +1230,10 @@ static void ImgTool_Convert(struct opts_s *args, struct pendingtextureinfo *in,
fflush(stdout);
}
static struct pendingtextureinfo *ImgTool_DecodeMiptex(struct opts_s *args, miptex_t *mip)
static struct pendingtextureinfo *ImgTool_DecodeMiptex(struct opts_s *args, miptex_t *mip, size_t size)
{
qbyte *data = (qbyte*)mip + (mip->offsets[2]?mip->offsets[2] + (mip->width>>2)*(mip->height>>2):sizeof(miptex_t));
qbyte *dataend = (qbyte*)mip + (mip->offsets[3]);
qbyte *data = (qbyte*)mip + (mip->offsets[3]?mip->offsets[3] + (mip->width>>3)*(mip->height>>3):sizeof(miptex_t));
qbyte *dataend = (qbyte*)mip + size;
struct pendingtextureinfo *out = Z_Malloc(sizeof(*out));
qbyte *newdata = NULL;
int neww=0, newh=0, sz;
@ -1242,7 +1242,7 @@ static struct pendingtextureinfo *ImgTool_DecodeMiptex(struct opts_s *args, mipt
out->encoding = PTI_INVALID;
Con_Printf("%s: Invalid miptex extension\n", mip->name);
Con_DPrintf("%s: width %i, height %i\n", mip->name, mip->width, mip->height);
//header [legacymip0 legacymip1 legacymip2] [extsize extcode extdata]*n [legacymip3]
//extcode NAME: extdata-8 bytes of replacement name
@ -1256,6 +1256,9 @@ static struct pendingtextureinfo *ImgTool_DecodeMiptex(struct opts_s *args, mipt
Con_DPrintf("offset[1]: %i\n", mip->offsets[1]);
Con_DPrintf("offset[2]: %i\n", mip->offsets[2]);
Con_DPrintf("offset[3]: %i\n", mip->offsets[3]);
if (data+4 < dataend && data[0]==0x00 && data[1]==0xfb&&data[2]==0x2b&&data[3]==0xaf) //magic id to say that there's actually extensions here...
{
data+=4;
for (; data+4 < dataend; data += sz)
{ //we could recognise more,
uploadfmt_t fmt = PTI_INVALID;
@ -1310,6 +1313,7 @@ static struct pendingtextureinfo *ImgTool_DecodeMiptex(struct opts_s *args, mipt
else
Con_Printf("%s: Chain size of %u doesn't match expected %u\n", mip->name, (unsigned)csz-16, sz-16);
}
}
//only use our if there were no corrupt sections.
if (data == dataend && newdata && neww && newh)
@ -1352,6 +1356,27 @@ static struct pendingtextureinfo *ImgTool_DecodeMiptex(struct opts_s *args, mipt
if (args)
{
if (args->defaultext && !strcasecmp(args->defaultext, "mip"))
{
char newout[MAX_OSPATH];
size_t k = strlen(mip->name);
vfsfile_t *fs;
memcpy(newout, mip->name, k);
newout[k++] = '.';
strcpy(newout+k, args->defaultext);
fs = FS_OpenVFS(newout, "wb", FS_SYSTEM);
if (!fs)
Con_Printf("%s(%s): Write failed\n", newout, Image_FormatName(out->encoding));
else
{
VFS_WRITE(fs, mip, size);
VFS_CLOSE(fs);
}
fflush(stdout);
}
else
ImgTool_Convert(args, out, mip->name, NULL);
return NULL;
}
@ -1379,7 +1404,7 @@ static void ImgTool_Info(struct opts_s *args, const char *inname)
case TYP_MIPTEX:
{
miptex_t *mip = (miptex_t *)(indata+e->offset);
in = ImgTool_DecodeMiptex(NULL, mip);
in = ImgTool_DecodeMiptex(NULL, mip, 0);
/*mip name SHOULD match entry name... but gah!*/
if (strcasecmp(e->name, mip->name))
@ -1414,15 +1439,22 @@ static void ImgTool_Info(struct opts_s *args, const char *inname)
dmiptexlump_t *texlump = (dmiptexlump_t*)(indata + bsp->lumps[LUMP_TEXTURES].fileofs);
miptex_t *miptex;
size_t i;
size_t sz = bsp->lumps[LUMP_TEXTURES].filelen;
printf("%-20s: bsp file (%u textures)\n", inname, texlump->nummiptex);
for (i = 0; i < texlump->nummiptex; i++)
for (i = texlump->nummiptex; i --> 0; )
{
if (texlump->dataofs[i] < 0 || texlump->dataofs[i] >= bsp->lumps[LUMP_TEXTURES].filelen)
{
char syn[MAX_QPATH];
sprintf(syn, "unnamed%u", (unsigned)i);
printf("\t%16.16s: <NO DATA>\n", syn);
continue;
}
miptex = (miptex_t*)((qbyte*)texlump + texlump->dataofs[i]);
in = ImgTool_DecodeMiptex(NULL, miptex);
in = ImgTool_DecodeMiptex(NULL, miptex, sz - texlump->dataofs[i]);
sz = texlump->dataofs[i];
if (in->encoding != PTI_P8)
printf("\t%16.16s: %u*%u%s (%s: %i*%i)\n", miptex->name, miptex->width, miptex->height, miptex->offsets[0]?"":" (external data)", Image_FormatName(in->encoding), in->mip[0].width, in->mip[0].height);
else
@ -1432,9 +1464,14 @@ static void ImgTool_Info(struct opts_s *args, const char *inname)
}
else
{
const miptex_t *mip = NULL;
const char *ex = COM_GetFileExtension(inname, NULL);
if (!strcasecmp(ex, ".mip"))
in = ImgTool_DecodeMiptex(NULL, (miptex_t*)indata);
{
in = ImgTool_DecodeMiptex(NULL, (miptex_t*)indata, fsize);
if (fsize >= sizeof(miptex_t))
mip = (const miptex_t*)indata;
}
else
in = Image_LoadMipsFromMemory(args->flags|IF_NOMIPMAP, inname, inname, indata, fsize);
if (!in)
@ -1445,6 +1482,9 @@ static void ImgTool_Info(struct opts_s *args, const char *inname)
printf("%-20s(%s): %s, %i*%i*%i, %u bytes\n", inname, Image_FormatName(in->encoding), imagetypename[in->type], in->mip[0].width, in->mip[0].height, in->mip[0].depth, (unsigned)in->mip[0].datasize);
else
{
if (mip)
printf("%-20s(%s): \"%s\"%s %i*%i, %i mips\n", inname, Image_FormatName(in->encoding), mip->name, mip->offsets[0]?"":" (stripped)", mip->width, mip->height, in->mipcount);
else
printf("%-20s(%s): %s, %i*%i*%i, %i mips\n", inname, Image_FormatName(in->encoding), imagetypename[in->type], in->mip[0].width, in->mip[0].height, in->mip[0].depth, in->mipcount);
for (m = 0; m < in->mipcount; m++)
printf("\t%u: %i*%i*%i, %u\n", (unsigned)m, in->mip[m].width, in->mip[m].height, in->mip[m].depth, (unsigned)in->mip[m].datasize);
@ -1690,7 +1730,7 @@ static void ImgTool_WadExtract(struct opts_s *args, const char *wadname)
break;
}
ImgTool_DecodeMiptex(args, mip);
ImgTool_DecodeMiptex(args, mip, e->dsize);
}
break;
case TYP_QPIC:
@ -1749,14 +1789,18 @@ static void ImgTool_WadExtract(struct opts_s *args, const char *wadname)
dmiptexlump_t *texlump = (dmiptexlump_t*)(indata + bsp->lumps[LUMP_TEXTURES].fileofs);
miptex_t *miptex;
size_t i;
for (i = 0; i < texlump->nummiptex; i++)
size_t sz = bsp->lumps[LUMP_TEXTURES].filelen;
for (i = texlump->nummiptex; i --> 0; )
{
if (texlump->dataofs[i] < 0 || texlump->dataofs[i] >= bsp->lumps[LUMP_TEXTURES].filelen)
continue;
miptex = (miptex_t*)((qbyte*)texlump + texlump->dataofs[i]);
if (*miptex->name && miptex->width && miptex->height && miptex->offsets[0]>0)
ImgTool_DecodeMiptex(args, miptex);
{
ImgTool_DecodeMiptex(args, miptex, sz - texlump->dataofs[i]);
sz = texlump->dataofs[i];
}
}
}
else
@ -1800,13 +1844,13 @@ static qboolean ImgTool_MipExport(struct opts_s *args, vfsfile_t *outfile, struc
if (!ImgTool_ConvertPixelFormat(args, mipname, highcolour))
{
Con_Printf("%s: Unable to convert to requested pixel format\n", mipname);
ImgTool_FreeMips(highcolour);
// ImgTool_FreeMips(highcolour);
highcolour = NULL;
}
else if (highcolour->mip[highcolour->mipcount-1].width != 1 || highcolour->mip[highcolour->mipcount-1].height != 1)
{
Con_Printf("%s: Mipchain truncated\n", mipname);
ImgTool_FreeMips(highcolour);
// ImgTool_FreeMips(highcolour);
highcolour = NULL;
}
else for (u = 1; u < highcolour->mipcount; u++)
@ -1815,7 +1859,7 @@ static qboolean ImgTool_MipExport(struct opts_s *args, vfsfile_t *outfile, struc
highcolour->mip[u].height!= max(1,highcolour->mip[u-1].height>>1))
{
Con_Printf("%s: Mipchain sized wrongly\n", mipname);
ImgTool_FreeMips(highcolour);
// ImgTool_FreeMips(highcolour);
highcolour = NULL;
break;
}
@ -1858,7 +1902,7 @@ static qboolean ImgTool_MipExport(struct opts_s *args, vfsfile_t *outfile, struc
case PTI_E5BGR9: highcode = "EXP5"; break; //gl3+
default:
Con_Printf("%s: unsupported pixel format(%s) for miptex\n", mipname, Image_FormatName(highcolour->encoding));
ImgTool_FreeMips(highcolour);
// ImgTool_FreeMips(highcolour);
highcolour = NULL;
break;
}
@ -2018,6 +2062,11 @@ static void ImgTool_WadConvert(struct opts_s *args, const char *destpath, const
return;
}
if (!strcasecmp(COM_GetFileExtension(destpath, NULL), ".bsp"))
{
}
else
{
qpics = !strcasecmp("gfx.wad", COM_SkipPath(destpath));
f = FS_OpenVFS(destpath, "wb", FS_SYSTEM);
@ -2134,6 +2183,7 @@ static void ImgTool_WadConvert(struct opts_s *args, const char *destpath, const
VFS_SEEK(f, 0);
VFS_WRITE(f, &wad2, sizeof(wad2));
VFS_CLOSE(f);
}
free(wadentries);
FileList_Release(&list);