Skip to content

Spearmint BSP Format

Zack Middleton edited this page Nov 16, 2013 · 13 revisions

This is a work-in-progress specification/idea, no software actually supports this format. Format name subject to change, like everything else.

Many of id Tech 3 based games use similar but incompatible BSP map formats. The goal of Spearmint BSP format is to allow identifying the data in BSP files and allow optional new data to be added.

SBSP file

Header

It will have a different ident and version than existing games. And include number of lumps!

int ident;
int version;

int numLumps;
// followed by lumps

Lumps

Lump definitions will be a flexible size. sizeof (int) * 2 + strlen(lump->name) + 1

Lumps will be identified by name rather than number.

int filelen;
int fileofs;
char *name;

Compatibility

Support loading .sbsp files that contain it's own lump list (that is labeled) and support referencing data for lumps internally or from external files (read: legacy BSP files). That way you could have "SBSP" patch data for a game, without having to modifying all of the BSPs and redistributing them (which is probably copyright infringement and a waste of bandwidth/space).

Lumps

The SBSP format itself can have lumps with any name that are any format. It's up to the loader to know what the names mean and what format the data is. For this reason lumps should not have generic names such as "brushsides" or "hdrlight".

Reserved lump names

(q3map2 has support for writing all of these.)

  • q3_* will be the Quake 3 / Team Arena / RTCW / ET / Elite Force format lumps.
  • rbsp_* will be used the two lumps that Raven changed from q3 format in SoF2/JK2/JA (brush sides and draw surfaces)
    • Could include both q3_* and rbsp_* brush sides and draw surfaces in the same BSP (incase loader only supports/wants one or the other).
    • Might want to create new lumps that contain only the new stuff added to rbsp? Doesn't help compat with Raven engines, it would save space in q3-compatible BSPs though. I want all maps to have brushside draw surface indexes (for cool point as surface get shader name {Spearmint's cg_drawShaderInfo}, if nothing else).
  • ql_ads will be the QuakeLive advertisements lump format.

New lumps for cross-game compatibility

bsp_external (name subject to change)

Set external bsp to load data from. All lumps after bsp_external are assumed to be in the external bsp.

TODO: Should there be support for multiple bsp_external lumps? Might be nice to have a single file containing legacy_bitflags for each game?

This could be used for referencing data in a legacy BSP or another SBSP. The header doesn't need to be read from the referenced BSP. The main SBSP file has the lump info.

legacy_bitflags (name subject to change)

Define strings for surface flags and content flags, allowing engine to identify and convert bit flags to it's own internal bits. Might get a little complicated supporting SOF2/JK2/JA material bits, should be possible.

The BSP itself is likely dependent on external textures and/or game entities. It would be useful for the Spearmint Engine as it attempts to load BSPs/gamelogic for multiple games.

Not sure you could make a BSP that was fully useable in both Q3 and RTCW-MP, due to different items and weapons names etc. Could add "notRtcw" key to rtcw-mp (so vanilla rtcw-mp would just spam about some missing entity classes. (Q3 and Team Arena already have notq3 and notta entity keys.)

##Load concept

#define LUMP_BLAH 0
#define LUMP_RBSP_BLAH 1
struct {
    string name;
    pointer lump;
    int file; // external bsp file index
} lumpinfolist = {
{ "q3_blah", NULL, -1 },
{ "rbsp_blah", NULL, -1 },
};

open file

check ident and version

for lumpinfo in lumpinfolist
    lumpinfo->lump = NULL;
    lumpinfo->file = -1;

file = -1;

for lump in lumplist
{
if lump->name == "bsp_external"
    file++;
    externalBsp[file].name = readString
    externalBsp[file].length = readInt
    externalBsp[file].checksum = readInt
    continue;

for lumpinfo in lumpinfolist
    if lumpinfo->name == lump->name
         lumpinfo->lump = lump;
         lumpinfo->file = file;
         break;
if not found lumpinfo for lump and cvar for showing unknown lumps is true
    Com_Printf("Unknown lump '%s' in '%s'\n", lump->name, bspname);
}

// Now we know which lumps are referenced and what files they're in.
// So check if have enough ones to load a level.
// Convert lumps into the format we want (change contents and surface bit flags, etc).
Clone this wiki locally