Skip to content

Commit

Permalink
tyrutils-ericw-spike
Browse files Browse the repository at this point in the history
Added features:
qbsp:
	parser: string escape verification.
	arg: -wrbrushes		(bspx) Includes a list of brushes for brush-based collision
	arg: -wrbrushesonly	-wrbrushes combined with -noclip argument
	arg: -notex		Write only placeholder textures, to depend upon replacements
	field: _smooth		Names a texture within the entity for which lighting should be smoothed (softens columns etc).
	field: _lmscale		Generates an LMSHIFT bspx lump for use by a light util. Note that both scaled and unscaled lighting will normally be used.

light:
	worldfield: _lightmap_scale	Forces all surfaces+submodels to use this specific lightmap scale. Removes LMSHIFT field.
	arg: -lmscale				Equivelent to _lightmap_scale worldspawn key.
	field: _project_texture		Specifies that a light should project this texture.
	field: _project_mangle		Specifies the pitch+yaw+roll angles for a texture projection (overriding mangle).
	field: _project_fov			Specifies the fov angle for a texture projection.
	arg:	-bspxlit				Writes rgb data into the bsp itself.
	arg: -bspx					Writes both rgb and directions data into the bsp itself.
	arg: -novanilla				Fallback scaled lighting will be omitted. Standard grey lighting will be ommitted if there are coloured lights. Implies -bspxlit. -lit will no longer be implied by the presence of coloured lights.

bspinfo:
	displays bspx lumps.

vis:
	no changes
  • Loading branch information
ericwa committed Dec 12, 2015
1 parent 1213279 commit 98b5306
Show file tree
Hide file tree
Showing 26 changed files with 1,860 additions and 152 deletions.
28 changes: 28 additions & 0 deletions README.txt
@@ -1,3 +1,31 @@
tyrutils-ericw-spike

Added features:
qbsp:
parser: string escape verification.
arg: -wrbrushes (bspx) Includes a list of brushes for brush-based collision
arg: -wrbrushesonly -wrbrushes combined with -noclip argument
arg: -notex Write only placeholder textures, to depend upon replacements
field: _smooth Names a texture within the entity for which lighting should be smoothed (softens columns etc).
field: _lmscale Generates an LMSHIFT bspx lump for use by a light util. Note that both scaled and unscaled lighting will normally be used.

light:
worldfield: _lightmap_scale Forces all surfaces+submodels to use this specific lightmap scale. Removes LMSHIFT field.
arg: -lmscale Equivelent to _lightmap_scale worldspawn key.
field: _project_texture Specifies that a light should project this texture.
field: _project_mangle Specifies the pitch+yaw+roll angles for a texture projection (overriding mangle).
field: _project_fov Specifies the fov angle for a texture projection.
arg: -bspxlit Writes rgb data into the bsp itself.
arg: -bspx Writes both rgb and directions data into the bsp itself.
arg: -novanilla Fallback scaled lighting will be omitted. Standard grey lighting will be ommitted if there are coloured lights. Implies -bspxlit. -lit will no longer be implied by the presence of coloured lights.

bspinfo:
displays bspx lumps.

vis:
no changes


Updated 2015-07-13

--------------------------
Expand Down
158 changes: 151 additions & 7 deletions common/bspfile.c
Expand Up @@ -1051,20 +1051,82 @@ CopyLump(const dheader_t *header, int lumpnum, void *destptr)
}
}

void BSPX_AddLump(bspdata_t *bspdata, const char *xname, const void *xdata, size_t xsize)
{
bspxentry_t *e;
bspxentry_t **link;
if (!xdata)
{
for (link = &bspdata->bspxentries; *link; )
{
e = *link;
if (!strcmp(e->lumpname, xname))
{
*link = e->next;
free(e);
break;
}
else
link = &(*link)->next;
}
return;
}
for (e = bspdata->bspxentries; e; e = e->next)
{
if (!strcmp(e->lumpname, xname))
break;
}
if (!e)
{
e = malloc(sizeof(*e));
memset(e, 0, sizeof(*e));
strncpy(e->lumpname, xname, sizeof(e->lumpname));
e->next = bspdata->bspxentries;
bspdata->bspxentries = e;
}

e->lumpdata = xdata;
e->lumpsize = xsize;
}
const void *BSPX_GetLump(bspdata_t *bspdata, const char *xname, size_t *xsize)
{
bspxentry_t *e;
for (e = bspdata->bspxentries; e; e = e->next)
{
if (!strcmp(e->lumpname, xname))
break;
}
if (e)
{
if (xsize)
*xsize = e->lumpsize;
return e->lumpdata;
}
else
{
if (xsize)
*xsize = 0;
return NULL;
}
}

/*
* =============
* LoadBSPFile
* =============
*/
void
LoadBSPFile(const char *filename, bspdata_t *bspdata)
LoadBSPFile(char *filename, bspdata_t *bspdata)
{
dheader_t *header;
int i;
uint32_t bspxofs, flen;
const bspx_header_t *bspx;

/* load the file header */
LoadFile(filename, &header);
flen = LoadFilePak(filename, &header);

bspdata->bspxentries = NULL;
/* check the file version */
header->version = LittleLong(header->version);
logprint("BSP is version %s\n", BSPVersionString(header->version));
Expand Down Expand Up @@ -1155,6 +1217,40 @@ LoadBSPFile(const char *filename, bspdata_t *bspdata)
bsp->entdatasize = CopyLump(header, LUMP_ENTITIES, &bsp->dentdata);
}

/*bspx header is positioned exactly+4align at the end of the last lump position (regardless of order)*/
for (i = 0, bspxofs = 0; i < BSP_LUMPS; i++)
{
if (bspxofs < header->lumps[i].fileofs + header->lumps[i].filelen)
bspxofs = header->lumps[i].fileofs + header->lumps[i].filelen;
}
bspxofs = (bspxofs+3) & ~3;
/*okay, so that's where it *should* be if it exists */
if (bspxofs + sizeof(*bspx) <= flen)
{
uint32_t xlumps;
const bspx_lump_t *xlump;
bspx = (const bspx_header_t*)((const byte*)header + bspxofs);
xlump = (const bspx_lump_t*)(bspx+1);
xlumps = LittleLong(bspx->numlumps);
if (!memcmp(&bspx->id,"BSPX",4) && xlumps >= 0 && bspxofs+sizeof(*bspx)+sizeof(*xlump)*xlumps <= flen)
{
/*header seems valid so far. just add the lumps as we normally would if we were generating them, ensuring that they get written out anew*/
while(xlumps --> 0)
{
uint32_t ofs = LittleLong(xlump[xlumps].fileofs);
uint32_t len = LittleLong(xlump[xlumps].filelen);
void *lumpdata = malloc(len);
memcpy(lumpdata, (const byte*)header + ofs, len);
BSPX_AddLump(bspdata, xlump[xlumps].lumpname, lumpdata, len);
}
}
else
{
if (!memcmp(&bspx->id,"BSPX",4))
printf("invalid bspx header\n");
}
}

/* everything has been copied out */
free(header);

Expand All @@ -1177,7 +1273,8 @@ AddLump(bspfile_t *bspfile, int lumpnum, const void *data, int count)
size_t size;

/* FIXME - bad API, needing to byte swap back and forth... */
switch (LittleLong(bspfile->header.version)) {
switch (LittleLong(bspfile->header.version))
{
case BSPVERSION:
size = lumpspec_bsp29[lumpnum].size * count;
break;
Expand All @@ -1190,14 +1287,13 @@ AddLump(bspfile_t *bspfile, int lumpnum, const void *data, int count)
default:
Error("Unsupported BSP version: %d",
LittleLong(bspfile->header.version));

}

lump->fileofs = LittleLong(ftell(bspfile->file));
lump->filelen = LittleLong(size);
SafeWrite(bspfile->file, data, (size + 3) & ~3);
if (size % 4)
SafeWrite(bspfile->file, pad, size % 4);
SafeWrite(bspfile->file, data, size);
if (size & 3)
SafeWrite(bspfile->file, pad, 4 - (size & 3));
}

static void
Expand Down Expand Up @@ -1318,6 +1414,46 @@ WriteBSPFile(const char *filename, bspdata_t *bspdata)
AddLump(&bspfile, LUMP_TEXTURES, bsp->dtexdata.base, bsp->texdatasize);
}

/*BSPX lumps are at a 4-byte alignment after the last of any official lump*/
if (bspdata->bspxentries)
{
bspx_header_t xheader;
bspxentry_t *x;
bspx_lump_t xlumps[64];
uint32_t l;
uint32_t bspxheader = ftell(bspfile.file);
if (bspxheader & 3)
Error("BSPX header is misaligned");
xheader.id[0] = 'B';
xheader.id[1] = 'S';
xheader.id[2] = 'P';
xheader.id[3] = 'X';
xheader.numlumps = 0;
for (x = bspdata->bspxentries; x; x = x->next)
xheader.numlumps++;

if (xheader.numlumps > sizeof(xlumps)/sizeof(xlumps[0])) /*eep*/
xheader.numlumps = sizeof(xlumps)/sizeof(xlumps[0]);

SafeWrite(bspfile.file, &xheader, sizeof(xheader));
SafeWrite(bspfile.file, xlumps, xheader.numlumps * sizeof(xlumps[0]));

for (x = bspdata->bspxentries, l = 0; x && l < xheader.numlumps; x = x->next, l++)
{
byte pad[4] = {0};
xlumps[l].filelen = LittleLong(x->lumpsize);
xlumps[l].fileofs = LittleLong(ftell(bspfile.file));
strncpy(xlumps[l].lumpname, x->lumpname, sizeof(xlumps[l].lumpname));
SafeWrite(bspfile.file, x->lumpdata, x->lumpsize);
if (x->lumpsize % 4)
SafeWrite(bspfile.file, pad, x->lumpsize % 4);
}

fseek(bspfile.file, bspxheader, SEEK_SET);
SafeWrite(bspfile.file, &xheader, sizeof(xheader));
SafeWrite(bspfile.file, xlumps, xheader.numlumps * sizeof(xlumps[0]));
}

fseek(bspfile.file, 0, SEEK_SET);
SafeWrite(bspfile.file, &bspfile.header, sizeof(bspfile.header));

Expand Down Expand Up @@ -1421,4 +1557,12 @@ PrintBSPFileSizes(const bspdata_t *bspdata)
logprint("%7s %-12s %10i\n", "", "visdata", bsp->visdatasize);
logprint("%7s %-12s %10i\n", "", "entdata", bsp->entdatasize);
}

if (bspdata->bspxentries)
{
bspxentry_t *x;
for (x = bspdata->bspxentries; x; x = x->next) {
logprint("%7s %-12s %10i\n", "BSPX", x->lumpname, x->lumpsize);
}
}
}
106 changes: 106 additions & 0 deletions common/cmdlib.c
Expand Up @@ -479,6 +479,112 @@ SafeWrite(FILE *f, const void *buffer, int count)
Error("File read failure");
}

typedef struct {
char magic[4];
unsigned int tableofs;
unsigned int numfiles;
} pakheader_t;
typedef struct {
char name[56];
unsigned int offset;
unsigned int length;
} pakfile_t;

/*
* ==============
* LoadFilePak
* reads a file directly out of a pak, to make re-lighting friendlier
* writes to the filename, stripping the pak part of the name
* ==============
*/
int
LoadFilePak(char *filename, void *destptr)
{
byte **bufferptr = destptr;
byte *buffer;
FILE *file;
int length;
char *e = NULL;

file = fopen(filename, "rb");
if (!file)
{
e = filename + strlen(filename);
for(;;)
{
while(e > filename)
if (*--e == '/')
break;
if (*e == '/')
{
*e = 0;
file = fopen(filename, "rb");
if (file)
{
byte **bufferptr = destptr;
pakheader_t header;
unsigned int i;
const char *innerfile = e+1;
length = -1;
SafeRead(file, &header, sizeof(header));

header.numfiles = LittleLong(header.numfiles) / sizeof(pakfile_t);
header.tableofs = LittleLong(header.tableofs);

if (!strncmp(header.magic, "PACK", 4))
{
pakfile_t *files = malloc(header.numfiles * sizeof(*files));
// printf("%s: %u files\n", pakfilename, header.numfiles);
fseek(file, header.tableofs, SEEK_SET);
SafeRead(file, files, header.numfiles * sizeof(*files));

for (i = 0; i < header.numfiles; i++)
{
if (!strcmp(files[i].name, innerfile))
{
fseek(file, files[i].offset, SEEK_SET);
*bufferptr = malloc(files[i].length + 1);
SafeRead(file, *bufferptr, files[i].length);
length = files[i].length;
break;
}
}
free(files);
}

fclose(file);
if (length < 0)
Error("Unable to find %s inside %s", innerfile, filename);

while(e > filename)
if (*--e == '/')
{
strcpy(e+1, innerfile);
return length;
}
strcpy(filename, innerfile);
return length;
}
*e = '/';
}
}
Error("Error opening %s: %s", filename, strerror(errno));
}


file = SafeOpenRead(filename);
length = Sys_filelength(file);
buffer = *bufferptr = malloc(length + 1);
if (!buffer)
Error("%s: allocation of %i bytes failed.", __func__, length);

SafeRead(file, buffer, length);
fclose(file);
buffer[length] = 0;

return length;
}

/*
* ==============
* LoadFile
Expand Down

0 comments on commit 98b5306

Please sign in to comment.