client: Add RBSP initial support

Structures sizes should be mosly correct and have found by estimate
sizes that could have lump size mod equal to zero as for other formats.
Possition of fields are taken from IBSP structures, that could be
incorrect. All other fields marked as unknow/unused.
This commit is contained in:
Denis Pauk 2024-04-11 00:12:55 +03:00
parent d4bc315363
commit c13074758a
3 changed files with 193 additions and 13 deletions

View file

@ -168,6 +168,28 @@ static const size_t idbsplumps[HEADER_LUMPS] = {
sizeof(dareaportal_t), // LUMP_AREAPORTALS
};
static const size_t rbsplumps[HEADER_LUMPS] = {
sizeof(char), // LUMP_ENTITIES
sizeof(dplane_t), // LUMP_PLANES
sizeof(dvertex_t), // LUMP_VERTEXES
sizeof(char), // LUMP_VISIBILITY
sizeof(dnode_t), // LUMP_NODES
sizeof(texrinfo_t), // LUMP_TEXINFO
sizeof(drface_t), // LUMP_FACES
sizeof(char), // LUMP_LIGHTING
sizeof(dleaf_t), // LUMP_LEAFS
sizeof(short), // LUMP_LEAFFACES
sizeof(short), // LUMP_LEAFBRUSHES
sizeof(dedge_t), // LUMP_EDGES
sizeof(int), // LUMP_SURFEDGES
sizeof(dmodel_t), // LUMP_MODELS
sizeof(dbrush_t), // LUMP_BRUSHES
sizeof(drbrushside_t), // LUMP_BRUSHSIDES
0, // LUMP_POP
sizeof(darea_t), // LUMP_AREAS
sizeof(dareaportal_t), // LUMP_AREAPORTALS
};
static const size_t qbsplumps[HEADER_LUMPS] = {
sizeof(char), // LUMP_ENTITIES
sizeof(dplane_t), // LUMP_PLANES
@ -216,16 +238,26 @@ Mod_LoadValidateLumps(const char *name, const dheader_t *header)
qboolean error = false;
maptype_t maptype;
if ((header->ident == IDBSPHEADER) ||
(header->ident == RBSPHEADER))
if (header->ident == IDBSPHEADER)
{
rules = idbsplumps;
if (header->version == BSPDKMVERSION)
{
maptype = map_daikatana;
/* SiN demos used same version ids as Daikatana */
if ((header->lumps[LUMP_TEXINFO].filelen % sizeof(texrinfo_t) == 0) &&
(header->lumps[LUMP_FACES].filelen % sizeof(drface_t) == 0))
{
rules = rbsplumps;
maptype = map_sin;
}
else
{
rules = idbsplumps;
maptype = map_daikatana;
}
}
else
{
rules = idbsplumps;
maptype = map_quake2;
}
}
@ -234,6 +266,11 @@ Mod_LoadValidateLumps(const char *name, const dheader_t *header)
rules = qbsplumps;
maptype = map_quake2;
}
else if (header->ident == RBSPHEADER)
{
rules = rbsplumps;
maptype = map_sin;
}
else
{
rules = NULL;

View file

@ -1373,6 +1373,39 @@ CMod_LoadSurfaces(const char *name, mapsurface_t **map_surfaces, int *numtexinfo
}
}
static void
CMod_LoadRSurfaces(const char *name, mapsurface_t **map_surfaces, int *numtexinfo,
const byte *cmod_base, const lump_t *l, maptype_t maptype)
{
texrinfo_t *in;
mapsurface_t *out;
int i, count;
in = (void *)(cmod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
Com_Error(ERR_DROP, "%s: funny lump size", __func__);
}
count = l->filelen / sizeof(*in);
if (count < 1)
{
Com_Error(ERR_DROP, "%s: Map with no surfaces", __func__);
}
*numtexinfo = count;
out = *map_surfaces = Hunk_Alloc(count * sizeof(*out));
for (i = 0; i < count; i++, in++, out++)
{
Q_strlcpy(out->c.name, in->texture, sizeof(out->c.name));
Q_strlcpy(out->rname, in->texture, sizeof(out->rname));
out->c.flags = Mod_LoadSurfConvertFlags(LittleLong(in->flags), maptype);
}
}
static void
CMod_LoadNodes(const char *name, cnode_t **map_nodes, int *numnodes,
cplane_t *map_planes, const byte *cmod_base, const lump_t *l)
@ -1739,6 +1772,51 @@ CMod_LoadQLeafBrushes(const char *name, unsigned int **map_leafbrushes,
}
}
static void
CMod_LoadRBrushSides(const char *name, cbrushside_t **map_brushsides, int *numbrushsides,
cplane_t *map_planes, int numplanes, mapsurface_t *map_surfaces, int numtexinfo,
const byte *cmod_base, const lump_t *l)
{
int i;
cbrushside_t *out;
drbrushside_t *in;
int count;
in = (void *)(cmod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
Com_Error(ERR_DROP, "%s: Map %s funny lump size", __func__, name);
}
count = l->filelen / sizeof(*in);
/* need to save space for box planes */
if (count < 1)
{
Com_Error(ERR_DROP, "%s: Map %s with no planes", __func__, name);
}
out = *map_brushsides = Hunk_Alloc((count + EXTRA_LUMP_BRUSHSIDES) * sizeof(*out));
*numbrushsides = count;
for (i = 0; i < count; i++, in++, out++)
{
int j, num;
num = LittleShort(in->planenum);
j = LittleShort(in->texinfo);
if (j >= numtexinfo || num > numplanes)
{
Com_Error(ERR_DROP, "%s: Bad brushside texinfo", __func__);
}
out->plane = map_planes + num;
out->surface = (j >= 0) ? &map_surfaces[j] : &nullsurface;
}
}
static void
CMod_LoadBrushSides(const char *name, cbrushside_t **map_brushsides, int *numbrushsides,
cplane_t *map_planes, int numplanes, mapsurface_t *map_surfaces, int numtexinfo,
@ -2053,8 +2131,16 @@ CM_LoadCachedMap(const char *name, model_t *mod)
/* load into heap */
strcpy(mod->name, name);
hunkSize += Mod_CalcLumpHunkSize(&header.lumps[LUMP_TEXINFO],
sizeof(texinfo_t), sizeof(mapsurface_t), EXTRA_LUMP_TEXINFO);
if (maptype == map_sin)
{
hunkSize += Mod_CalcLumpHunkSize(&header.lumps[LUMP_TEXINFO],
sizeof(texrinfo_t), sizeof(mapsurface_t), EXTRA_LUMP_TEXINFO);
}
else
{
hunkSize += Mod_CalcLumpHunkSize(&header.lumps[LUMP_TEXINFO],
sizeof(texinfo_t), sizeof(mapsurface_t), EXTRA_LUMP_TEXINFO);
}
if ((header.ident == IDBSPHEADER) ||
(header.ident == RBSPHEADER))
@ -2090,8 +2176,16 @@ CM_LoadCachedMap(const char *name, model_t *mod)
if ((header.ident == IDBSPHEADER) ||
(header.ident == RBSPHEADER))
{
hunkSize += Mod_CalcLumpHunkSize(&header.lumps[LUMP_BRUSHSIDES],
sizeof(dbrushside_t), sizeof(cbrushside_t), EXTRA_LUMP_BRUSHSIDES);
if (maptype == map_sin)
{
hunkSize += Mod_CalcLumpHunkSize(&header.lumps[LUMP_BRUSHSIDES],
sizeof(drbrushside_t), sizeof(cbrushside_t), EXTRA_LUMP_BRUSHSIDES);
}
else
{
hunkSize += Mod_CalcLumpHunkSize(&header.lumps[LUMP_BRUSHSIDES],
sizeof(dbrushside_t), sizeof(cbrushside_t), EXTRA_LUMP_BRUSHSIDES);
}
hunkSize += Mod_CalcLumpHunkSize(&header.lumps[LUMP_NODES],
sizeof(dnode_t), sizeof(cnode_t), EXTRA_LUMP_NODES);
}
@ -2116,8 +2210,16 @@ CM_LoadCachedMap(const char *name, model_t *mod)
mod->extradata = Hunk_Begin(hunkSize);
CMod_LoadSurfaces(mod->name, &mod->map_surfaces, &mod->numtexinfo,
cmod_base, &header.lumps[LUMP_TEXINFO], maptype);
if (maptype == map_sin)
{
CMod_LoadRSurfaces(mod->name, &mod->map_surfaces, &mod->numtexinfo,
cmod_base, &header.lumps[LUMP_TEXINFO], maptype);
}
else
{
CMod_LoadSurfaces(mod->name, &mod->map_surfaces, &mod->numtexinfo,
cmod_base, &header.lumps[LUMP_TEXINFO], maptype);
}
if ((header.ident == IDBSPHEADER) ||
(header.ident == RBSPHEADER))
@ -2152,9 +2254,18 @@ CM_LoadCachedMap(const char *name, model_t *mod)
if ((header.ident == IDBSPHEADER) ||
(header.ident == RBSPHEADER))
{
CMod_LoadBrushSides(mod->name, &mod->map_brushsides, &mod->numbrushsides,
mod->map_planes, mod->numplanes, mod->map_surfaces, mod->numtexinfo,
cmod_base, &header.lumps[LUMP_BRUSHSIDES]);
if (maptype == map_sin)
{
CMod_LoadRBrushSides(mod->name, &mod->map_brushsides, &mod->numbrushsides,
mod->map_planes, mod->numplanes, mod->map_surfaces, mod->numtexinfo,
cmod_base, &header.lumps[LUMP_BRUSHSIDES]);
}
else
{
CMod_LoadBrushSides(mod->name, &mod->map_brushsides, &mod->numbrushsides,
mod->map_planes, mod->numplanes, mod->map_surfaces, mod->numtexinfo,
cmod_base, &header.lumps[LUMP_BRUSHSIDES]);
}
}
else
{

View file

@ -969,5 +969,37 @@ typedef struct
#define RBSPHEADER (('P' << 24) + ('S' << 16) + ('B' << 8) + 'R') /* little-endian "RBSP" */
#define BSPSINVERSION 1
typedef struct texsininfo_s
{
float vecs[2][4]; /* [s/t][xyz offset] */
int flags; /* miptex flags + overrides light emission, etc */
char texture[64]; /* texture name (textures*.wal) */
int nexttexinfo; /* for animations, -1 = end of chain */
char unknown[76]; /* no idea what is it */
} texrinfo_t;
#define MAXSINLIGHTMAPS 16
typedef struct
{
unsigned short planenum;
short side;
int firstedge; /* we must support > 64k edges */
short numedges;
short texinfo;
/* lighting info */
byte styles[MAXSINLIGHTMAPS];
int lightofs; /* start of [numstyles*surfsize] samples */
int unknown; /* no idea what is it */
} drface_t;
typedef struct
{
unsigned short planenum; /* facing out of the leaf */
short texinfo;
int unknown; /* no idea what is it */
} drbrushside_t;
#endif