Add vtf loading to hl2 plugin, too.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6112 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
485f2299c0
commit
195fd2b6f3
5 changed files with 256 additions and 15 deletions
|
@ -1213,6 +1213,7 @@ IF(FTE_PLUG_HL2)
|
|||
plugins/plugin.c
|
||||
plugins/hl2/hl2.c
|
||||
plugins/hl2/fs_vpk.c
|
||||
plugins/hl2/img_vtf.c
|
||||
)
|
||||
SET_TARGET_PROPERTIES(plug_hl2 PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;MULTITHREAD;${FTE_LIB_DEFINES}")
|
||||
TARGET_LINK_LIBRARIES(plug_hl2 ${SYS_LIBS} ${ZLIB_LIBRARIES})
|
||||
|
|
|
@ -415,7 +415,7 @@ $(PLUG_PREFIX)openssl$(PLUG_NATIVE_EXT): net_ssl_openssl.c plugin.c
|
|||
|
||||
#####################
|
||||
#for compat with half-life 2's file formats
|
||||
$(PLUG_PREFIX)hl2$(PLUG_NATIVE_EXT): hl2/fs_vpk.c hl2/hl2.c plugin.c
|
||||
$(PLUG_PREFIX)hl2$(PLUG_NATIVE_EXT): hl2/fs_vpk.c hl2/img_vtf.c hl2/hl2.c plugin.c
|
||||
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -DMULTITHREAD -o $@ -shared $(PLUG_CFLAGS) $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
|
||||
#NATIVE_PLUGINS+=hl2
|
||||
|
||||
|
|
|
@ -8,9 +8,6 @@ static plugthreadfuncs_t *threading;
|
|||
#define Sys_LockMutex(m) (threading?threading->LockMutex(m):true)
|
||||
#define Sys_UnlockMutex if(threading)threading->UnlockMutex
|
||||
#define Sys_DestroyMutex if(threading)threading->DestroyMutex
|
||||
#define Z_Malloc(x) calloc(x,1)
|
||||
#define BZ_Malloc malloc
|
||||
#define Z_Free free
|
||||
|
||||
|
||||
|
||||
|
@ -104,9 +101,9 @@ static void QDECL FSVPK_ClosePath(searchpathfuncs_t *handle)
|
|||
pak->fragments[i]->pub.ClosePath(&pak->fragments[i]->pub);
|
||||
pak->fragments[i] = NULL;
|
||||
}
|
||||
Z_Free(pak->fragments);
|
||||
Z_Free(pak->treedata);
|
||||
Z_Free(pak);
|
||||
plugfuncs->Free(pak->fragments);
|
||||
plugfuncs->Free(pak->treedata);
|
||||
plugfuncs->Free(pak);
|
||||
}
|
||||
static void QDECL FSVPK_BuildHash(searchpathfuncs_t *handle, int depth, void (QDECL *AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle))
|
||||
{
|
||||
|
@ -287,7 +284,7 @@ static qboolean QDECL VFSVPK_Close(vfsfile_t *vfs)
|
|||
{
|
||||
vfsvpk_t *vfsp = (void*)vfs;
|
||||
FSVPK_ClosePath(&vfsp->parentpak->pub); //tell the parent that we don't need it open any more (reference counts)
|
||||
Z_Free(vfsp); //free ourselves.
|
||||
plugfuncs->Free(vfsp); //free ourselves.
|
||||
return true;
|
||||
}
|
||||
static vfsfile_t *QDECL FSVPK_OpenVFS(searchpathfuncs_t *handle, flocation_t *loc, const char *mode)
|
||||
|
@ -305,12 +302,12 @@ static vfsfile_t *QDECL FSVPK_OpenVFS(searchpathfuncs_t *handle, flocation_t *lo
|
|||
return NULL;
|
||||
pack = pack->fragments[frag];
|
||||
|
||||
vfs = Z_Malloc(sizeof(vfsvpk_t));
|
||||
vfs = plugfuncs->Malloc(sizeof(vfsvpk_t));
|
||||
|
||||
vfs->parentpak = pack;
|
||||
if (!Sys_LockMutex(pack->mutex))
|
||||
{
|
||||
Z_Free(vfs);
|
||||
plugfuncs->Free(vfs);
|
||||
return NULL;
|
||||
}
|
||||
vfs->parentpak->references++;
|
||||
|
@ -470,12 +467,12 @@ static searchpathfuncs_t *QDECL FSVPK_LoadArchive (vfsfile_t *file, searchpathfu
|
|||
return NULL;
|
||||
}
|
||||
|
||||
tree = BZ_Malloc(header.tablesize);
|
||||
tree = plugfuncs->Malloc(header.tablesize);
|
||||
read = VFS_READ(packhandle, tree, header.tablesize);
|
||||
|
||||
numpackfiles = FSVPK_WalkTree(NULL, tree, tree+read);
|
||||
|
||||
vpk = (vpk_t*)Z_Malloc (sizeof (*vpk) + sizeof(*vpk->files)*(numpackfiles-1));
|
||||
vpk = (vpk_t*)plugfuncs->Malloc (sizeof (*vpk) + sizeof(*vpk->files)*(numpackfiles-1));
|
||||
vpk->treedata = tree;
|
||||
vpk->treesize = read;
|
||||
vpk->numfiles = numpackfiles;
|
||||
|
@ -503,7 +500,7 @@ static searchpathfuncs_t *QDECL FSVPK_LoadArchive (vfsfile_t *file, searchpathfu
|
|||
vpk->pub.GeneratePureCRC = FSVPK_GeneratePureCRC;
|
||||
vpk->pub.OpenVFS = FSVPK_OpenVFS;
|
||||
|
||||
vpk->fragments = Z_Malloc(vpk->numfragments*sizeof(*vpk->fragments));
|
||||
vpk->fragments = plugfuncs->Malloc(vpk->numfragments*sizeof(*vpk->fragments));
|
||||
for(frag = 0; frag < vpk->numfragments; frag++)
|
||||
{
|
||||
flocation_t loc;
|
||||
|
@ -521,7 +518,7 @@ static searchpathfuncs_t *QDECL FSVPK_LoadArchive (vfsfile_t *file, searchpathfu
|
|||
if (!packhandle)
|
||||
continue;
|
||||
|
||||
vpk->fragments[frag] = f = (vpk_t*)Z_Malloc(sizeof(*f));
|
||||
vpk->fragments[frag] = f = (vpk_t*)plugfuncs->Malloc(sizeof(*f));
|
||||
// Q_strncpyz(f->descname, splitname, sizeof(f->descname));
|
||||
f->handle = packhandle;
|
||||
// f->rawsize = VFS_GETLEN(f->raw);
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
#include "../plugin.h"
|
||||
qboolean VPK_Init(void);
|
||||
qboolean VTF_Init(void);
|
||||
|
||||
qboolean Plug_Init(void)
|
||||
{
|
||||
return VPK_Init();
|
||||
if (!VPK_Init())
|
||||
return false;
|
||||
if (!VTF_Init())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
238
plugins/hl2/img_vtf.c
Normal file
238
plugins/hl2/img_vtf.c
Normal file
|
@ -0,0 +1,238 @@
|
|||
#include "../plugin.h"
|
||||
|
||||
static plugimagefuncs_t *imagefuncs;
|
||||
|
||||
//many of these look like dupes, not really sure how they're meant to work. probably legacy.
|
||||
typedef enum {
|
||||
VMF_INVALID=-1,
|
||||
VMF_RGBA8=0,
|
||||
// VMF_ABGR8=1,
|
||||
VMF_RGB8=2,
|
||||
VMF_BGR8=3,
|
||||
// VMF_RGB565=4,
|
||||
VMF_I8=5,
|
||||
VMF_IA8=6,
|
||||
// VMF_P8=7,
|
||||
// VMF_A8=8,
|
||||
// VMF_RGB8_BS=9,
|
||||
// VMF_BGR8_BS=10,
|
||||
// VMF_ARGB_BS=11,
|
||||
VMF_BGRA8=12,
|
||||
VMF_BC1=13,
|
||||
VMF_BC2=14,
|
||||
VMF_BC3=15,
|
||||
VMF_BGRX8=16,
|
||||
// VMF_BGR565=17,
|
||||
// VMF_BGRX5551=18,
|
||||
// VMF_BGRA4444=19,
|
||||
VMF_BC1A=20,
|
||||
// VMF_BGRA5551=21,
|
||||
VMF_UV88=22,
|
||||
// VMF_UVWQ8=23,
|
||||
VMF_RGBA16F=24,
|
||||
// VMF_RGBA16N=25,
|
||||
// VMF_UVLX8=26,
|
||||
VMF_MAX
|
||||
} fmtfmt_t;
|
||||
static uploadfmt_t ImageVTF_VtfToFTE(fmtfmt_t f)
|
||||
{
|
||||
switch(f)
|
||||
{
|
||||
case VMF_BC1:
|
||||
return PTI_BC1_RGB;
|
||||
case VMF_BC1A:
|
||||
return PTI_BC1_RGBA;
|
||||
case VMF_BC2:
|
||||
return PTI_BC2_RGBA;
|
||||
case VMF_BC3:
|
||||
return PTI_BC3_RGBA;
|
||||
case VMF_RGB8:
|
||||
return PTI_RGB8;
|
||||
case VMF_RGBA8:
|
||||
return PTI_RGBA8;
|
||||
case VMF_BGR8:
|
||||
return PTI_BGR8;
|
||||
case VMF_BGRA8:
|
||||
return PTI_BGRA8;
|
||||
case VMF_BGRX8:
|
||||
return PTI_BGRX8;
|
||||
case VMF_RGBA16F:
|
||||
return PTI_RGBA16F;
|
||||
case VMF_UV88:
|
||||
return PTI_RG8;
|
||||
case VMF_I8:
|
||||
return PTI_L8;
|
||||
case VMF_IA8:
|
||||
return PTI_L8A8;
|
||||
case VMF_INVALID:
|
||||
return PTI_INVALID;
|
||||
|
||||
default:
|
||||
return PTI_INVALID;
|
||||
}
|
||||
}
|
||||
static struct pendingtextureinfo *Image_ReadVTFFile(unsigned int flags, const char *fname, qbyte *filedata, size_t filesize)
|
||||
{
|
||||
//FIXME: cba with endian.
|
||||
struct vtf_s
|
||||
{
|
||||
char magic[4];
|
||||
unsigned int major,minor;
|
||||
unsigned int headersize;
|
||||
|
||||
unsigned short width, height;
|
||||
unsigned int flags;
|
||||
unsigned short numframes, firstframe;
|
||||
unsigned int pad1;
|
||||
|
||||
vec3_t reflectivity;
|
||||
float pad2;
|
||||
|
||||
float bumpmapscale;
|
||||
unsigned int imgformat;
|
||||
unsigned char mipmapcount;
|
||||
unsigned char lowresfmt_misaligned[4];
|
||||
unsigned char lowreswidth;
|
||||
unsigned char lowresheight;
|
||||
|
||||
//7.2
|
||||
unsigned char depth_misaligned[2];
|
||||
//7.3
|
||||
unsigned char pad3[3];
|
||||
unsigned int numresources;
|
||||
} *vtf;
|
||||
fmtfmt_t vmffmt, lrfmt;
|
||||
unsigned int bw, bh, bd, bb;
|
||||
qbyte *end = filedata + filesize;
|
||||
unsigned int faces, frame, frames, miplevel, miplevels, img;
|
||||
unsigned int w, h, d = 1;
|
||||
size_t datasize;
|
||||
unsigned int version;
|
||||
|
||||
struct pendingtextureinfo *mips;
|
||||
|
||||
vtf = (void*)filedata;
|
||||
|
||||
if (memcmp(vtf->magic, "VTF\0", 4))
|
||||
return NULL;
|
||||
|
||||
version = (vtf->major<<16)|vtf->minor;
|
||||
if (version > 0x00070005)
|
||||
{
|
||||
Con_Printf("%s: VTF version %i.%i is not supported\n", fname, vtf->major, vtf->minor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lrfmt = (vtf->lowresfmt_misaligned[0]<<0)|(vtf->lowresfmt_misaligned[1]<<16)|(vtf->lowresfmt_misaligned[2]<<16)|(vtf->lowresfmt_misaligned[3]<<24);
|
||||
vmffmt = vtf->imgformat;
|
||||
|
||||
mips = NULL;
|
||||
if (version >= 0x00070003)
|
||||
{
|
||||
int i;
|
||||
struct
|
||||
{
|
||||
unsigned int rtype;
|
||||
unsigned int rdata; //usually an offset.
|
||||
} *restable = (void*)(filedata+sizeof(*vtf));
|
||||
for (i = 0; i < vtf->numresources; i++, restable++)
|
||||
{
|
||||
if ((restable->rtype & 0x00ffffff) == 0x30)
|
||||
{
|
||||
mips = plugfuncs->Malloc(sizeof(*mips));
|
||||
mips->extrafree = filedata;
|
||||
filedata += restable->rdata;
|
||||
break;
|
||||
}
|
||||
//other unknown resource types.
|
||||
}
|
||||
}
|
||||
if (!mips)
|
||||
{
|
||||
mips = plugfuncs->Malloc(sizeof(*mips));
|
||||
mips->extrafree = filedata;
|
||||
|
||||
//skip the header
|
||||
filedata += vtf->headersize;
|
||||
//and skip the low-res image too.
|
||||
if (vtf->lowreswidth && vtf->lowresheight)
|
||||
imagefuncs->BlockSizeForEncoding(ImageVTF_VtfToFTE(lrfmt), &bb, &bw, &bh, &bd);
|
||||
else
|
||||
bb=bw=bh=bd=1;
|
||||
datasize = ((vtf->lowreswidth+bw-1)/bw) * ((vtf->lowresheight+bh-1)/bh) * ((1/*vtf->lowresdepth*/+bd-1)/bd) * bb;
|
||||
filedata += datasize;
|
||||
}
|
||||
|
||||
//now handle the high-res image
|
||||
if (mips)
|
||||
{
|
||||
mips->type = (vtf->flags & 0x4000)?PTI_CUBE:PTI_2D;
|
||||
|
||||
mips->encoding = ImageVTF_VtfToFTE(vmffmt);
|
||||
imagefuncs->BlockSizeForEncoding(mips->encoding, &bb, &bw, &bh, &bd);
|
||||
|
||||
miplevels = vtf->mipmapcount;
|
||||
frames = 1;//vtf->numframes;
|
||||
faces = ((mips->type==PTI_CUBE)?6:1); //no cubemaps yet.
|
||||
|
||||
mips->mipcount = miplevels * frames;
|
||||
while (mips->mipcount > countof(mips->mip))
|
||||
{
|
||||
if (miplevels > 1)
|
||||
miplevels--;
|
||||
else
|
||||
frames--;
|
||||
mips->mipcount = miplevels * frames;
|
||||
}
|
||||
if (!mips->mipcount)
|
||||
{
|
||||
plugfuncs->Free(mips);
|
||||
return NULL;
|
||||
}
|
||||
for (miplevel = vtf->mipmapcount; miplevel-- > 0;)
|
||||
{ //smallest to largest, which is awkward.
|
||||
w = vtf->width>>miplevel;
|
||||
h = vtf->height>>miplevel;
|
||||
if (!w)
|
||||
w = 1;
|
||||
if (!h)
|
||||
h = 1;
|
||||
datasize = ((w+bw-1)/bw) * ((h+bh-1)/bh) * ((d+bd-1)/bd) * bb;
|
||||
for (frame = 0; frame < vtf->numframes; frame++)
|
||||
{
|
||||
if (miplevel < miplevels)
|
||||
{
|
||||
img = miplevel + frame*miplevels;
|
||||
if (img >= countof(mips->mip))
|
||||
break; //erk?
|
||||
if (filedata + datasize > end)
|
||||
break; //no more data here...
|
||||
mips->mip[img].width = w;
|
||||
mips->mip[img].height = h;
|
||||
mips->mip[img].depth = faces;
|
||||
mips->mip[img].data = filedata;
|
||||
mips->mip[img].datasize = datasize*faces;
|
||||
}
|
||||
filedata += datasize*faces;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mips;
|
||||
}
|
||||
|
||||
static plugimageloaderfuncs_t vtffuncs =
|
||||
{
|
||||
"Valve Texture File",
|
||||
sizeof(struct pendingtextureinfo),
|
||||
true,
|
||||
Image_ReadVTFFile,
|
||||
};
|
||||
|
||||
qboolean VTF_Init(void)
|
||||
{
|
||||
imagefuncs = plugfuncs->GetEngineInterface(plugimagefuncs_name, sizeof(*imagefuncs));
|
||||
if (!imagefuncs)
|
||||
return false;
|
||||
return plugfuncs->ExportInterface(plugimageloaderfuncs_name, &vtffuncs, sizeof(vtffuncs));
|
||||
}
|
||||
|
Loading…
Reference in a new issue