collision: create IBSP -> QBSP convert logic

This commit is contained in:
Denis Pauk 2024-04-14 10:38:50 +03:00
parent 12aaebf80e
commit 53d69f98e5
3 changed files with 499 additions and 23 deletions

View file

@ -253,7 +253,7 @@ Mod_MaptypeName(maptype_t maptype)
return maptypename;
}
maptype_t
static maptype_t
Mod_LoadGetRules(const dheader_t *header, const size_t **rules)
{
if (header->ident == IDBSPHEADER)
@ -281,27 +281,25 @@ Mod_LoadGetRules(const dheader_t *header, const size_t **rules)
return map_daikatana;
}
}
else
else if (header->version == BSPVERSION)
{
*rules = idbsplumps;
return map_quake2;
}
}
else if (header->ident == QBSPHEADER)
else if (header->ident == QBSPHEADER && header->version == BSPVERSION)
{
*rules = qbsplumps;
return map_quake2;
}
else if (header->ident == RBSPHEADER)
else if (header->ident == RBSPHEADER && header->version == BSPSINVERSION)
{
*rules = rbsplumps;
return map_sin;
}
else
{
*rules = NULL;
return map_quake2;
}
*rules = NULL;
return map_quake2;
}
maptype_t
@ -381,3 +379,482 @@ Mod_LoadSurfConvertFlags(int flags, maptype_t maptype)
return sflags;
}
byte *
Mod_Load2QBSP(const char *name, byte *inbuf, size_t filesize, size_t *out_len,
maptype_t *maptype)
{
const size_t *rules = NULL;
size_t result_size;
dheader_t header, *outheader;
int s, xofs, numlumps;
qboolean error = false;
byte *outbuf;
for (s = 0; s < sizeof(dheader_t) / 4; s++)
{
((int *)&header)[s] = LittleLong(((int *)inbuf)[s]);
}
result_size = sizeof(dheader_t);
*maptype = Mod_LoadGetRules(&header, &rules);
if (rules)
{
for (s = 0; s < HEADER_LUMPS; s++)
{
if (rules[s])
{
if (header.lumps[s].filelen % rules[s])
{
Com_Printf("%s: Map %s lump #%d: incorrect size %d / " YQ2_COM_PRIdS "\n",
__func__, name, s, header.lumps[s].filelen, rules[s]);
error = true;
}
result_size += (
qbsplumps[s] * header.lumps[s].filelen / rules[s]
);
}
}
}
Com_Printf("Map %s %c%c%c%c with version %d (%s)\n",
name,
(header.ident >> 0) & 0xFF,
(header.ident >> 8) & 0xFF,
(header.ident >> 16) & 0xFF,
(header.ident >> 24) & 0xFF,
header.version, Mod_MaptypeName(*maptype));
if (error || !rules)
{
Com_Error(ERR_DROP, "%s: Map %s has incorrect lumps",
__func__, name);
}
/* find end of last lump */
xofs = 0;
numlumps = HEADER_LUMPS;
if ((header.version == BSPDKMVERSION) &&
(*maptype == map_daikatana))
{
numlumps = 21;
}
for (s = 0; s < numlumps; s++)
{
xofs = Q_max(xofs,
(header.lumps[s].fileofs + header.lumps[s].filelen + 3) & ~3);
}
if (xofs + sizeof(bspx_header_t) < filesize)
{
result_size += (filesize - xofs);
}
result_size += 4;
outbuf = malloc(result_size);
outheader = (dheader_t*)outbuf;
outheader->ident = QBSPHEADER;
outheader->version = BSPVERSION;
int ofs = sizeof(dheader_t);
/* mark offsets for all lumps */
for (s = 0; s < HEADER_LUMPS; s++)
{
if (rules[s])
{
outheader->lumps[s].fileofs = ofs;
outheader->lumps[s].filelen = (
qbsplumps[s] * header.lumps[s].filelen / rules[s]
);
ofs += outheader->lumps[s].filelen;
}
}
if ((filesize - xofs) > 0)
{
bspx_header_t *bspx_header;
bspx_lump_t *lump;
int numlumps, i;
ofs = ((ofs + 3) & ~3);
bspx_header = (bspx_header_t *)(outbuf + ofs);
/* copy BSPX */
memcpy(bspx_header, inbuf + xofs, (filesize - xofs));
/* fix positions */
numlumps = LittleLong(bspx_header->numlumps);
lump = (bspx_lump_t*)(bspx_header + 1);
for (i = 0; i < numlumps; i++, lump++)
{
int fileofs;
/* move fileofs to correct place */
fileofs = LittleLong(lump->fileofs);
fileofs += (ofs - xofs);
lump->fileofs = LittleLong(fileofs);
}
}
/* Copy LUMP_ENTITIES */
memcpy(outbuf + outheader->lumps[LUMP_ENTITIES].fileofs,
inbuf + header.lumps[LUMP_ENTITIES].fileofs,
header.lumps[LUMP_ENTITIES].filelen);
/* Copy LUMP_PLANES */
{
int i, count = header.lumps[LUMP_PLANES].filelen / rules[LUMP_PLANES];
dplane_t *in, *out;
in = (dplane_t *)(inbuf + header.lumps[LUMP_PLANES].fileofs);
out = (dplane_t *)(outbuf + outheader->lumps[LUMP_PLANES].fileofs);
for (i = 0; i < count; i++)
{
int j;
for (j = 0; j < 3; j++)
{
out->normal[j] = LittleFloat(in->normal[j]);
}
out->dist = LittleFloat(in->dist);
out->type = LittleLong(in->type);
out++;
in++;
}
}
/* Copy LUMP_VERTEXES */
{
int i, count = header.lumps[LUMP_VERTEXES].filelen / rules[LUMP_VERTEXES];
dvertex_t *in, *out;
in = (dvertex_t *)(inbuf + header.lumps[LUMP_VERTEXES].fileofs);
out = (dvertex_t *)(outbuf + outheader->lumps[LUMP_VERTEXES].fileofs);
for (i = 0; i < count; i++)
{
int j;
for (j = 0; j < 3; j++)
{
out->point[j] = LittleFloat(in->point[j]);
}
out++;
in++;
}
}
/* Copy LUMP_VISIBILITY */
memcpy(outbuf + outheader->lumps[LUMP_VISIBILITY].fileofs,
inbuf + header.lumps[LUMP_VISIBILITY].fileofs,
header.lumps[LUMP_VISIBILITY].filelen);
/* Copy LUMP_NODES */
{
int i, count = header.lumps[LUMP_NODES].filelen / rules[LUMP_NODES];
dnode_t *in;
dqnode_t *out;
in = (dnode_t *)(inbuf + header.lumps[LUMP_NODES].fileofs);
out = (dqnode_t *)(outbuf + outheader->lumps[LUMP_NODES].fileofs);
for (i = 0; i < count; i++)
{
int j;
for (j = 0; j < 3; j++)
{
out->mins[j] = LittleShort(in->mins[j]);
out->maxs[3 + j] = LittleShort(in->maxs[j]);
}
out->planenum = LittleLong(in->planenum);
out->firstface = LittleShort(in->firstface) & 0xFFFF;
out->numfaces = LittleShort(in->numfaces) & 0xFFFF;
for (j = 0; j < 2; j++)
{
out->children[j] = LittleLong(in->children[j]);
}
out++;
in++;
}
}
/* Copy LUMP_TEXINFO */
{
int i, count = header.lumps[LUMP_TEXINFO].filelen / rules[LUMP_TEXINFO];
texinfo_t *in;
texinfo_t *out;
in = (texinfo_t *)(inbuf + header.lumps[LUMP_TEXINFO].fileofs);
out = (texinfo_t *)(outbuf + outheader->lumps[LUMP_TEXINFO].fileofs);
for (i = 0; i < count; i++)
{
int j;
for (j = 0; j < 4; j++)
{
out->vecs[0][j] = LittleFloat(in->vecs[0][j]);
out->vecs[1][j] = LittleFloat(in->vecs[1][j]);
}
out->flags = LittleLong(in->flags);
out->nexttexinfo = LittleLong(in->nexttexinfo);
strncpy(out->texture, in->texture,
Q_min(sizeof(out->texture), sizeof(in->texture)));
out++;
in++;
}
}
/* Copy LUMP_FACES */
{
int i, count = header.lumps[LUMP_FACES].filelen / rules[LUMP_FACES];
dface_t *in;
dqface_t *out;
in = (dface_t *)(inbuf + header.lumps[LUMP_FACES].fileofs);
out = (dqface_t *)(outbuf + outheader->lumps[LUMP_FACES].fileofs);
for (i = 0; i < count; i++)
{
out->planenum = LittleShort(in->planenum);
out->side = LittleShort(in->side);
out->firstedge = LittleLong(in->firstedge);
out->numedges = LittleShort(in->numedges);
out->texinfo = LittleShort(in->texinfo);
memcpy(out->styles, in->styles, Q_min(sizeof(out->styles), sizeof(in->styles)));
out->lightofs = LittleLong(in->lightofs) & 0xFFFFFFFF;
out++;
in++;
}
}
/* Copy LUMP_LIGHTING */
memcpy(outbuf + outheader->lumps[LUMP_LIGHTING].fileofs,
inbuf + header.lumps[LUMP_LIGHTING].fileofs,
header.lumps[LUMP_LIGHTING].filelen);
/* Copy LUMP_LEAFS */
{
int i, count = header.lumps[LUMP_LEAFS].filelen / rules[LUMP_LEAFS];
dleaf_t *in;
dqleaf_t *out;
in = (dleaf_t *)(inbuf + header.lumps[LUMP_LEAFS].fileofs);
out = (dqleaf_t *)(outbuf + outheader->lumps[LUMP_LEAFS].fileofs);
for (i = 0; i < count; i++)
{
int j;
for (j = 0; j < 3; j++)
{
out->mins[j] = LittleShort(in->mins[j]);
out->maxs[3 + j] = LittleShort(in->maxs[j]);
}
out->contents = LittleLong(in->contents);
out->cluster = LittleShort(in->cluster);
out->area = LittleShort(in->area);
/* make unsigned long from signed short */
out->firstleafface = LittleShort(in->firstleafface) & 0xFFFF;
out->numleaffaces = LittleShort(in->numleaffaces) & 0xFFFF;
out->firstleafbrush = LittleShort(in->firstleafbrush) & 0xFFFF;
out->numleafbrushes = LittleShort(in->numleafbrushes) & 0xFFFF;
out++;
in++;
}
}
/* Copy LUMP_LEAFFACES */
{
int i, count = header.lumps[LUMP_LEAFFACES].filelen / rules[LUMP_LEAFFACES];
short *in;
int *out;
in = (short *)(inbuf + header.lumps[LUMP_LEAFFACES].fileofs);
out = (int *)(outbuf + outheader->lumps[LUMP_LEAFFACES].fileofs);
for (i = 0; i < count; i++)
{
*out = LittleShort(*in) & 0xFFFF;
out++;
in++;
}
}
/* Copy LUMP_LEAFBRUSHES */
{
int i, count = header.lumps[LUMP_LEAFBRUSHES].filelen / rules[LUMP_LEAFBRUSHES];
short *in;
int *out;
in = (short *)(inbuf + header.lumps[LUMP_LEAFBRUSHES].fileofs);
out = (int *)(outbuf + outheader->lumps[LUMP_LEAFBRUSHES].fileofs);
for (i = 0; i < count; i++)
{
*out = LittleLong(*in);
out++;
in++;
}
}
/* Copy LUMP_EDGES */
{
int i, count = header.lumps[LUMP_EDGES].filelen / rules[LUMP_EDGES];
dedge_t *in;
dqedge_t *out;
in = (dedge_t *)(inbuf + header.lumps[LUMP_EDGES].fileofs);
out = (dqedge_t *)(outbuf + outheader->lumps[LUMP_EDGES].fileofs);
for (i = 0; i < count; i++)
{
out->v[0] = (unsigned short)LittleShort(in->v[0]);
out->v[1] = (unsigned short)LittleShort(in->v[1]);
out++;
in++;
}
}
/* Copy LUMP_SURFEDGES */
{
int i, count = header.lumps[LUMP_SURFEDGES].filelen / rules[LUMP_SURFEDGES];
short *in;
int *out;
in = (short *)(inbuf + header.lumps[LUMP_SURFEDGES].fileofs);
out = (int *)(outbuf + outheader->lumps[LUMP_SURFEDGES].fileofs);
for (i = 0; i < count; i++)
{
*out = LittleLong(*in);
out++;
in++;
}
}
/* Copy LUMP_MODELS */
{
int i, count = header.lumps[LUMP_MODELS].filelen / rules[LUMP_MODELS];
dmodel_t *in;
dmodel_t *out;
in = (dmodel_t *)(inbuf + header.lumps[LUMP_MODELS].fileofs);
out = (dmodel_t *)(outbuf + outheader->lumps[LUMP_MODELS].fileofs);
for (i = 0; i < count; i++)
{
int j;
for (j = 0; j < 3; j++)
{
out->mins[j] = LittleFloat(in->mins[j]);
out->maxs[j] = LittleFloat(in->maxs[j]);
out->origin[j] = LittleFloat(in->origin[j]);
}
out->headnode = LittleLong(in->headnode);
out->firstface = LittleLong(in->firstface);
out->numfaces = LittleLong(in->numfaces);
out++;
in++;
}
}
/* Copy LUMP_BRUSHES */
{
int i, count = header.lumps[LUMP_BRUSHES].filelen / rules[LUMP_BRUSHES];
dbrush_t *in;
dbrush_t *out;
in = (dbrush_t *)(inbuf + header.lumps[LUMP_BRUSHES].fileofs);
out = (dbrush_t *)(outbuf + outheader->lumps[LUMP_BRUSHES].fileofs);
for (i = 0; i < count; i++)
{
out->firstside = LittleLong(in->firstside) & 0xFFFFFFFF;
out->numsides = LittleLong(in->numsides) & 0xFFFFFFFF;
out->contents = LittleLong(in->contents);
out++;
in++;
}
}
/* Copy LUMP_BRUSHSIDES */
{
int i, count = header.lumps[LUMP_BRUSHSIDES].filelen / rules[LUMP_BRUSHSIDES];
dbrushside_t *in;
dqbrushside_t *out;
in = (dbrushside_t *)(inbuf + header.lumps[LUMP_BRUSHSIDES].fileofs);
out = (dqbrushside_t *)(outbuf + outheader->lumps[LUMP_BRUSHSIDES].fileofs);
for (i = 0; i < count; i++)
{
out->planenum = LittleShort(in->planenum);
out->texinfo = LittleShort(in->texinfo);
out++;
in++;
}
}
/* Copy LUMP_AREAS */
{
int i, count = header.lumps[LUMP_AREAS].filelen / rules[LUMP_AREAS];
darea_t *in;
darea_t *out;
in = (darea_t *)(inbuf + header.lumps[LUMP_AREAS].fileofs);
out = (darea_t *)(outbuf + outheader->lumps[LUMP_AREAS].fileofs);
for (i = 0; i < count; i++)
{
out->numareaportals = LittleLong(in->numareaportals);
out->firstareaportal = LittleLong(in->firstareaportal);
out++;
in++;
}
}
/* Copy LUMP_AREAPORTALS */
{
int count = header.lumps[LUMP_AREAPORTALS].filelen / rules[LUMP_AREAPORTALS];
dareaportal_t *in;
dareaportal_t *out;
in = (dareaportal_t *)(inbuf + header.lumps[LUMP_AREAPORTALS].fileofs);
out = (dareaportal_t *)(outbuf + outheader->lumps[LUMP_AREAPORTALS].fileofs);
memcpy(out, in, sizeof(dareaportal_t) * count);
}
*out_len = result_size;
return outbuf;
}

View file

@ -2067,29 +2067,27 @@ CM_ModFreeAll(void)
static void
CM_LoadCachedMap(const char *name, model_t *mod)
{
int i, length, hunkSize = 0;
int filelen, hunkSize = 0;
const byte *cmod_base;
maptype_t maptype;
dheader_t header;
unsigned *buf;
size_t length;
byte *buf, *filebuf;
length = FS_LoadFile(name, (void **)&buf);
filelen = FS_LoadFile(name, (void **)&filebuf);
if (!buf || length <= 0)
if (!filebuf || filelen <= 0)
{
Com_Printf("%s: Couldn't load %s\n", __func__, name);
return;
}
mod->checksum = LittleLong(Com_BlockChecksum(buf, length));
mod->checksum = LittleLong(Com_BlockChecksum(filebuf, filelen));
buf = Mod_Load2QBSP(name, (byte *)filebuf, filelen, &length, &maptype);
header = *(dheader_t *)buf;
for (i = 0; i < sizeof(dheader_t) / 4; i++)
{
((int *)&header)[i] = LittleLong(((int *)&header)[i]);
}
if ((header.ident != IDBSPHEADER) &&
(header.ident != RBSPHEADER) &&
(header.ident != QBSPHEADER))
@ -2123,8 +2121,6 @@ CM_LoadCachedMap(const char *name, model_t *mod)
__func__, name, header.version, BSPSINVERSION);
}
maptype = Mod_LoadValidateLumps(name, &header);
cmod_base = (byte *)buf;
/* load into heap */
@ -2297,7 +2293,7 @@ CM_LoadCachedMap(const char *name, model_t *mod)
if (!mod->map_vis)
{
Com_Error(ERR_DROP, "%s: Map %s has visual clusters.",
Com_Error(ERR_DROP, "%s: Map %s has no visual clusters.",
__func__, name);
}
@ -2314,7 +2310,8 @@ CM_LoadCachedMap(const char *name, model_t *mod)
Com_DPrintf("Allocated %d from expected %d hunk size\n",
mod->extradatasize, hunkSize);
FS_FreeFile(buf);
free(buf);
FS_FreeFile(filebuf);
}
/*

View file

@ -56,5 +56,7 @@ extern void Mod_LoadVisibility(const char *name, dvis_t **vis, int *numvisibilit
extern void Mod_LoadPlanes(const char *name, cplane_t **planes, int *numplanes,
const byte *mod_base, const lump_t *l);
extern maptype_t Mod_LoadValidateLumps(const char *name, const dheader_t *header);
extern byte *Mod_Load2QBSP(const char *name, byte *in, size_t filesize,
size_t *out_len, maptype_t *maptype);
#endif