- rewrote map loader to work independently of data structure sizes.

This is needed to extend a few fields that are too narrow - e.g. the texture offset fields have no room for interpolating scrolling textures.
Blood not done yet, will also need to be changed to get rid of the limits.
This commit is contained in:
Christoph Oelckers 2020-09-22 21:44:33 +02:00
parent 28c5c72605
commit 880b811e0d
10 changed files with 446 additions and 833 deletions

View file

@ -788,6 +788,7 @@ set (PCH_SOURCES
core/inputstate.cpp
core/maphack.cpp
core/mapinfo.cpp
core/maploader.cpp
core/searchpaths.cpp
core/screenjob.cpp
core/initfs.cpp

View file

@ -1128,9 +1128,6 @@ int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short
}
}
g_loadedMapVersion = 7;
return 0;
}

View file

@ -51,10 +51,6 @@ enum rendmode_t {
#define MAXWALLSV8 16384
#define MAXSPRITESV8 16384
#define MAXSECTORSV7 1024
#define MAXWALLSV7 8192
#define MAXSPRITESV7 4096
#define MAXVOXMIPS 5
@ -216,13 +212,6 @@ typedef struct {
float alpha;
// NOTE: keep 'tspr' on an 8-byte boundary:
tspriteptr_t tspr;
#if !defined UINTPTR_MAX
# error Need UINTPTR_MAX define to select between 32- and 64-bit structs
#endif
#if UINTPTR_MAX == 0xffffffff
/* On a 32-bit build, pad the struct so it has the same size everywhere. */
intptr_t dummy_;
#endif
} spriteext_t;
typedef struct {
@ -260,7 +249,6 @@ enum
EXTERN int32_t guniqhudid;
EXTERN int32_t spritesortcnt;
extern int32_t g_loadedMapVersion;
struct usermaphack_t
{
@ -586,7 +574,7 @@ int32_t engineInit(void);
void engineUnInit(void);
void initspritelists(void);
int32_t engineLoadBoard(const char *filename, char flags, vec3_t *dapos, int16_t *daang, int16_t *dacursectnum);
void engineLoadBoard(const char *filename, int flags, vec3_t *dapos, int16_t *daang, int16_t *dacursectnum);
int32_t engineLoadMHK(const char *filename);
void G_LoadMapHack(const char* filename);
int32_t saveboard(const char *filename, const vec3_t *dapos, int16_t daang, int16_t dacursectnum);

View file

@ -245,55 +245,6 @@ typedef struct
//////////////////// END Version 7 map format ////////////////
//////////////////// Lunatic new-generation map format ////////////////////
#if defined NEW_MAP_FORMAT
// 44 bytes
typedef struct
{
StructTracker(Sector, int16_t) wallptr, wallnum;
StructTracker(Sector, int16_t) ceilingpicnum, ceilingheinum, ceilingbunch;
StructTracker(Sector, uint16_t) ceilingstat;
StructTracker(Sector, int32_t) ceilingz;
StructTracker(Sector, int8_t) ceilingshade;
StructTracker(Sector, uint8_t) ceilingpal, /*CM_FLOORZ:*/ ceilingxpanning, ceilingypanning;
StructTracker(Sector, int16_t) floorpicnum, floorheinum, floorbunch;
StructTracker(Sector, uint16_t) floorstat;
StructTracker(Sector, int32_t) floorz;
StructTracker(Sector, int8_t) floorshade;
StructTracker(Sector, uint8_t) floorpal, floorxpanning, floorypanning;
StructTracker(Sector, uint8_t) /*CM_CEILINGZ:*/ visibility, fogpal;
StructTracker(Sector, int16_t) lotag, hitag;
StructTracker(Sector, int16_t) extra;
} StructName(sectortypevx);
// 38 bytes
typedef struct
{
union {
struct
{
StructTracker(Wall, int32_t) x, y;
};
vec2_t pos;
};
StructTracker(Wall, int16_t) point2, nextwall, nextsector;
StructTracker(Wall, int16_t) upwall, dnwall;
StructTracker(Wall, uint16_t) cstat;
StructTracker(Wall, int16_t) picnum, overpicnum;
StructTracker(Wall, int8_t) shade;
StructTracker(Wall, uint8_t) pal, xrepeat, yrepeat, xpanning, ypanning;
StructTracker(Wall, int16_t) lotag, hitag;
StructTracker(Wall, int16_t) extra;
StructTracker(Wall, uint8_t) blend, filler_;
} StructName(walltypevx);
#endif
// NOTE: spritetype is currently the same for V7/8/9 and VX in-memory map formats.
//////////////////// END Lunatic new-generation map format ////////////////
#undef StructTracker
#undef StructName

View file

@ -39,9 +39,6 @@
#endif
int32_t mapversion=7; // JBF 20040211: default mapversion to 7
int32_t g_loadedMapVersion = -1; // -1: none (e.g. started new)
int32_t rendmode=0;
int32_t glrendmode = REND_POLYMOST;
int32_t r_rortexture = 0;
@ -1934,499 +1931,6 @@ void renderDrawMapView(int32_t dax, int32_t day, int32_t zoome, int16_t ang)
renderSetAspect(oviewingrange, oyxaspect);
}
//////////////////// LOADING AND SAVING ROUTINES ////////////////////
static FORCE_INLINE int32_t have_maptext(void)
{
return (mapversion >= 10);
}
static void enginePrepareLoadBoard(FileReader & fr, vec3_t *dapos, int16_t *daang, int16_t *dacursectnum)
{
memset(spriteext, 0, sizeof(spriteext_t) * MAXSPRITES);
memset(spritesmooth, 0, sizeof(spritesmooth_t) * (MAXSPRITES + MAXUNIQHUDID));
initspritelists();
ClearAutomap();
#ifdef USE_OPENGL
Polymost_prepare_loadboard();
#endif
if (!have_maptext())
{
fr.Read(&dapos->x,4); dapos->x = B_LITTLE32(dapos->x);
fr.Read(&dapos->y,4); dapos->y = B_LITTLE32(dapos->y);
fr.Read(&dapos->z,4); dapos->z = B_LITTLE32(dapos->z);
fr.Read(daang,2); *daang = B_LITTLE16(*daang) & 2047;
fr.Read(dacursectnum,2); *dacursectnum = B_LITTLE16(*dacursectnum);
}
}
static int32_t engineFinishLoadBoard(const char *filename, const vec3_t *dapos, int16_t *dacursectnum, int16_t numsprites, char myflags)
{
int32_t i, realnumsprites=numsprites, numremoved;
#if !defined USE_OPENGL || !defined POLYMER
UNREFERENCED_PARAMETER(myflags);
#endif
for (i=0; i<numsprites; i++)
{
int32_t removeit = 0;
if ((sprite[i].cstat & 48) == 48)
sprite[i].cstat &= ~48;
if (sprite[i].statnum == MAXSTATUS)
{
// Sprite was removed in loadboard() -> check_sprite(). Insert it
// for now, because we must maintain the sprite numbering.
sprite[i].statnum = sprite[i].sectnum = 0;
removeit = 1;
}
insertsprite(sprite[i].sectnum, sprite[i].statnum);
if (removeit)
{
// Flag .statnum==MAXSTATUS, temporarily creating an inconsistency
// with sprite list.
sprite[i].statnum = MAXSTATUS;
realnumsprites--;
}
}
if (numsprites != realnumsprites)
{
for (i=0; i<numsprites; i++)
if (sprite[i].statnum == MAXSTATUS)
{
// Now remove it for real!
sprite[i].statnum = 0;
deletesprite(i);
}
}
numremoved = (numsprites-realnumsprites);
numsprites = realnumsprites;
assert(numsprites == Numsprites);
//Must be after loading sectors, etc!
updatesector(dapos->x, dapos->y, dacursectnum);
{
memset(spriteext, 0, sizeof(spriteext_t)*MAXSPRITES);
memset(wallext, 0, sizeof(wallext_t)*MAXWALLS);
memset(spritesmooth, 0, sizeof(spritesmooth_t)*(MAXSPRITES+MAXUNIQHUDID));
}
guniqhudid = 0;
G_LoadMapHack(filename);
return numremoved;
}
#define MYMAXSECTORS() (MAXSECTORS==MAXSECTORSV7 || mapversion <= 7 ? MAXSECTORSV7 : MAXSECTORSV8)
#define MYMAXWALLS() (MAXSECTORS==MAXSECTORSV7 || mapversion <= 7 ? MAXWALLSV7 : MAXWALLSV8)
#define MYMAXSPRITES() (MAXSECTORS==MAXSECTORSV7 || mapversion <= 7 ? MAXSPRITESV7 : MAXSPRITESV8)
// Sprite checking
static void remove_sprite(int32_t i)
{
memset(&sprite[i], 0, sizeof(spritetype));
sprite[i].statnum = MAXSTATUS;
sprite[i].sectnum = MAXSECTORS;
}
// This is only to be run after reading the sprite array!
static void check_sprite(int32_t i)
{
if ((unsigned)sprite[i].statnum >= MAXSTATUS)
{
Printf("Map error: sprite #%d (%d,%d) with illegal statnum (%d) REMOVED.\n",
i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), TrackerCast(sprite[i].statnum));
remove_sprite(i);
}
else if ((unsigned)sprite[i].picnum >= MAXTILES)
{
Printf("Map error: sprite #%d (%d,%d) with illegal picnum (%d) REMOVED.\n",
i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), TrackerCast(sprite[i].sectnum));
remove_sprite(i);
}
else if ((unsigned)sprite[i].sectnum >= (unsigned)numsectors)
{
const int32_t osectnum = sprite[i].sectnum;
sprite[i].sectnum = -1;
updatesector(sprite[i].x, sprite[i].y, &sprite[i].sectnum);
if (sprite[i].sectnum < 0)
remove_sprite(i);
Printf("Map error: sprite #%d (%d,%d) with illegal sector (%d) ",
i, TrackerCast(sprite[i].x), TrackerCast(sprite[i].y), osectnum);
if (sprite[i].statnum != MAXSTATUS)
Printf("changed to sector %d.\n", TrackerCast(sprite[i].sectnum));
else
Printf("REMOVED.\n");
}
}
#include "md4.h"
// flags: 1, 2: former parameter "fromwhere"
// 4: don't call polymer_loadboard
// 8: don't autoexec <mapname>.cfg
// returns: on success, number of removed sprites
// -1: file not found
// -2: invalid version
// -3: invalid number of sectors, walls or sprites
// <= -4: map-text error
int32_t engineLoadBoard(const char *filename, char flags, vec3_t *dapos, int16_t *daang, int16_t *dacursectnum)
{
inputState.ClearAllInput();
int32_t i;
int16_t numsprites;
const char myflags = flags&(~3);
flags &= 3;
FileReader fr = fileSystem.OpenFileReader(filename);
if (!fr.isOpen())
{ mapversion = 7; return -1; }
if (fr.Read(&mapversion, 4) != 4)
{
return -2;
}
{
int32_t ok = 0;
{
// Not map-text. We expect a little-endian version int now.
mapversion = B_LITTLE32(mapversion);
#if MAXSECTORS==MAXSECTORSV8
// v8 engine
ok |= (mapversion==8);
#endif
ok |= (mapversion==7);
}
if (!ok)
{
return -2;
}
}
enginePrepareLoadBoard(fr, dapos, daang, dacursectnum);
////////// Read sectors //////////
fr.Read(&numsectors,2); numsectors = B_LITTLE16(numsectors);
if ((unsigned)numsectors >= MYMAXSECTORS() + 1)
{
error:
numsectors = 0;
numwalls = 0;
numsprites = 0;
return -3;
}
fr.Read(sector, sizeof(sectortypev7)*numsectors);
for (i=numsectors-1; i>=0; i--)
{
sector[i].wallptr = B_LITTLE16(sector[i].wallptr);
sector[i].wallnum = B_LITTLE16(sector[i].wallnum);
sector[i].ceilingz = B_LITTLE32(sector[i].ceilingz);
sector[i].floorz = B_LITTLE32(sector[i].floorz);
sector[i].ceilingstat = B_LITTLE16(sector[i].ceilingstat);
sector[i].floorstat = B_LITTLE16(sector[i].floorstat);
sector[i].ceilingpicnum = B_LITTLE16(sector[i].ceilingpicnum);
sector[i].ceilingheinum = B_LITTLE16(sector[i].ceilingheinum);
sector[i].floorpicnum = B_LITTLE16(sector[i].floorpicnum);
sector[i].floorheinum = B_LITTLE16(sector[i].floorheinum);
sector[i].lotag = B_LITTLE16(sector[i].lotag);
sector[i].hitag = B_LITTLE16(sector[i].hitag);
sector[i].extra = B_LITTLE16(sector[i].extra);
}
////////// Read walls //////////
fr.Read(&numwalls,2); numwalls = B_LITTLE16(numwalls);
if ((unsigned)numwalls >= MYMAXWALLS()+1) goto error;
fr.Read( wall, sizeof(walltypev7)*numwalls);
for (i=numwalls-1; i>=0; i--)
{
wall[i].x = B_LITTLE32(wall[i].x);
wall[i].y = B_LITTLE32(wall[i].y);
wall[i].point2 = B_LITTLE16(wall[i].point2);
wall[i].nextwall = B_LITTLE16(wall[i].nextwall);
wall[i].nextsector = B_LITTLE16(wall[i].nextsector);
wall[i].cstat = B_LITTLE16(wall[i].cstat);
wall[i].picnum = B_LITTLE16(wall[i].picnum);
wall[i].overpicnum = B_LITTLE16(wall[i].overpicnum);
wall[i].lotag = B_LITTLE16(wall[i].lotag);
wall[i].hitag = B_LITTLE16(wall[i].hitag);
wall[i].extra = B_LITTLE16(wall[i].extra);
}
////////// Read sprites //////////
fr.Read(&numsprites,2); numsprites = B_LITTLE16(numsprites);
if ((unsigned)numsprites >= MYMAXSPRITES()+1) goto error;
fr.Read( sprite, sizeof(spritetype)*numsprites);
fr.Seek(0, FileReader::SeekSet);
auto buffer = fr.Read();
md4once(buffer.Data(), buffer.Size(), g_loadedMapHack.md4);
// Done reading file.
if (!have_maptext())
{
for (i=numsprites-1; i>=0; i--)
{
sprite[i].x = B_LITTLE32(sprite[i].x);
sprite[i].y = B_LITTLE32(sprite[i].y);
sprite[i].z = B_LITTLE32(sprite[i].z);
sprite[i].cstat = B_LITTLE16(sprite[i].cstat);
sprite[i].picnum = B_LITTLE16(sprite[i].picnum);
sprite[i].sectnum = B_LITTLE16(sprite[i].sectnum);
sprite[i].statnum = B_LITTLE16(sprite[i].statnum);
sprite[i].ang = B_LITTLE16(sprite[i].ang);
sprite[i].owner = B_LITTLE16(sprite[i].owner);
sprite[i].xvel = B_LITTLE16(sprite[i].xvel);
sprite[i].yvel = B_LITTLE16(sprite[i].yvel);
sprite[i].zvel = B_LITTLE16(sprite[i].zvel);
sprite[i].lotag = B_LITTLE16(sprite[i].lotag);
sprite[i].hitag = B_LITTLE16(sprite[i].hitag);
sprite[i].extra = B_LITTLE16(sprite[i].extra);
check_sprite(i);
}
}
else
{
for (i=numsprites-1; i>=0; i--)
check_sprite(i);
}
// Back up the map version of the *loaded* map. Must be before yax_update().
g_loadedMapVersion = mapversion;
if ((myflags&8)==0)
{
// Per-map ART
artSetupMapArt(filename);
}
return engineFinishLoadBoard(filename, dapos, dacursectnum, numsprites, myflags);
}
//
// loadboardv5/6
//
#include "engine_oldmap.h"
// Powerslave uses v6
// Witchaven 1 and TekWar and LameDuke use v5
int32_t engineLoadBoardV5V6(const char *filename, char fromwhere, vec3_t *dapos, int16_t *daang, int16_t *dacursectnum)
{
int32_t i;
int16_t numsprites;
struct sectortypev5 v5sect;
struct walltypev5 v5wall;
struct spritetypev5 v5spr;
struct sectortypev6 v6sect;
struct walltypev6 v6wall;
struct spritetypev6 v6spr;
FileReader fr = fileSystem.OpenFileReader(filename);
if (!fr.isOpen())
{ mapversion = 5L; return -1; }
fr.Read(&mapversion,4); mapversion = B_LITTLE32(mapversion);
if (mapversion != 5L && mapversion != 6L) { return -2; }
enginePrepareLoadBoard(fr, dapos, daang, dacursectnum);
fr.Read(&numsectors,2); numsectors = B_LITTLE16(numsectors);
if (numsectors > MAXSECTORS) { return -1; }
for (i=0; i<numsectors; i++)
{
switch (mapversion)
{
case 5:
fr.Read(&v5sect,sizeof(struct sectortypev5));
v5sect.wallptr = B_LITTLE16(v5sect.wallptr);
v5sect.wallnum = B_LITTLE16(v5sect.wallnum);
v5sect.ceilingpicnum = B_LITTLE16(v5sect.ceilingpicnum);
v5sect.floorpicnum = B_LITTLE16(v5sect.floorpicnum);
v5sect.ceilingheinum = B_LITTLE16(v5sect.ceilingheinum);
v5sect.floorheinum = B_LITTLE16(v5sect.floorheinum);
v5sect.ceilingz = B_LITTLE32(v5sect.ceilingz);
v5sect.floorz = B_LITTLE32(v5sect.floorz);
v5sect.lotag = B_LITTLE16(v5sect.lotag);
v5sect.hitag = B_LITTLE16(v5sect.hitag);
v5sect.extra = B_LITTLE16(v5sect.extra);
break;
case 6:
fr.Read(&v6sect,sizeof(struct sectortypev6));
v6sect.wallptr = B_LITTLE16(v6sect.wallptr);
v6sect.wallnum = B_LITTLE16(v6sect.wallnum);
v6sect.ceilingpicnum = B_LITTLE16(v6sect.ceilingpicnum);
v6sect.floorpicnum = B_LITTLE16(v6sect.floorpicnum);
v6sect.ceilingheinum = B_LITTLE16(v6sect.ceilingheinum);
v6sect.floorheinum = B_LITTLE16(v6sect.floorheinum);
v6sect.ceilingz = B_LITTLE32(v6sect.ceilingz);
v6sect.floorz = B_LITTLE32(v6sect.floorz);
v6sect.lotag = B_LITTLE16(v6sect.lotag);
v6sect.hitag = B_LITTLE16(v6sect.hitag);
v6sect.extra = B_LITTLE16(v6sect.extra);
break;
}
switch (mapversion)
{
case 5:
convertv5sectv6(&v5sect,&v6sect);
fallthrough__;
case 6:
convertv6sectv7(&v6sect,&sector[i]);
break;
}
}
fr.Read(&numwalls,2); numwalls = B_LITTLE16(numwalls);
if (numwalls > MAXWALLS) { return -1; }
for (i=0; i<numwalls; i++)
{
switch (mapversion)
{
case 5:
fr.Read(&v5wall,sizeof(struct walltypev5));
v5wall.x = B_LITTLE32(v5wall.x);
v5wall.y = B_LITTLE32(v5wall.y);
v5wall.point2 = B_LITTLE16(v5wall.point2);
v5wall.picnum = B_LITTLE16(v5wall.picnum);
v5wall.overpicnum = B_LITTLE16(v5wall.overpicnum);
v5wall.cstat = B_LITTLE16(v5wall.cstat);
v5wall.nextsector1 = B_LITTLE16(v5wall.nextsector1);
v5wall.nextwall1 = B_LITTLE16(v5wall.nextwall1);
v5wall.nextsector2 = B_LITTLE16(v5wall.nextsector2);
v5wall.nextwall2 = B_LITTLE16(v5wall.nextwall2);
v5wall.lotag = B_LITTLE16(v5wall.lotag);
v5wall.hitag = B_LITTLE16(v5wall.hitag);
v5wall.extra = B_LITTLE16(v5wall.extra);
break;
case 6:
fr.Read(&v6wall,sizeof(struct walltypev6));
v6wall.x = B_LITTLE32(v6wall.x);
v6wall.y = B_LITTLE32(v6wall.y);
v6wall.point2 = B_LITTLE16(v6wall.point2);
v6wall.nextsector = B_LITTLE16(v6wall.nextsector);
v6wall.nextwall = B_LITTLE16(v6wall.nextwall);
v6wall.picnum = B_LITTLE16(v6wall.picnum);
v6wall.overpicnum = B_LITTLE16(v6wall.overpicnum);
v6wall.cstat = B_LITTLE16(v6wall.cstat);
v6wall.lotag = B_LITTLE16(v6wall.lotag);
v6wall.hitag = B_LITTLE16(v6wall.hitag);
v6wall.extra = B_LITTLE16(v6wall.extra);
break;
}
switch (mapversion)
{
case 5:
convertv5wallv6(&v5wall,&v6wall,i);
fallthrough__;
case 6:
convertv6wallv7(&v6wall,&wall[i]);
break;
}
}
fr.Read(&numsprites,2); numsprites = B_LITTLE16(numsprites);
if (numsprites > MAXSPRITES) { return -1; }
for (i=0; i<numsprites; i++)
{
switch (mapversion)
{
case 5:
fr.Read(&v5spr,sizeof(struct spritetypev5));
v5spr.x = B_LITTLE32(v5spr.x);
v5spr.y = B_LITTLE32(v5spr.y);
v5spr.z = B_LITTLE32(v5spr.z);
v5spr.picnum = B_LITTLE16(v5spr.picnum);
v5spr.ang = B_LITTLE16(v5spr.ang);
v5spr.xvel = B_LITTLE16(v5spr.xvel);
v5spr.yvel = B_LITTLE16(v5spr.yvel);
v5spr.zvel = B_LITTLE16(v5spr.zvel);
v5spr.owner = B_LITTLE16(v5spr.owner);
v5spr.sectnum = B_LITTLE16(v5spr.sectnum);
v5spr.statnum = B_LITTLE16(v5spr.statnum);
v5spr.lotag = B_LITTLE16(v5spr.lotag);
v5spr.hitag = B_LITTLE16(v5spr.hitag);
v5spr.extra = B_LITTLE16(v5spr.extra);
break;
case 6:
fr.Read(&v6spr,sizeof(struct spritetypev6));
v6spr.x = B_LITTLE32(v6spr.x);
v6spr.y = B_LITTLE32(v6spr.y);
v6spr.z = B_LITTLE32(v6spr.z);
v6spr.cstat = B_LITTLE16(v6spr.cstat);
v6spr.picnum = B_LITTLE16(v6spr.picnum);
v6spr.ang = B_LITTLE16(v6spr.ang);
v6spr.xvel = B_LITTLE16(v6spr.xvel);
v6spr.yvel = B_LITTLE16(v6spr.yvel);
v6spr.zvel = B_LITTLE16(v6spr.zvel);
v6spr.owner = B_LITTLE16(v6spr.owner);
v6spr.sectnum = B_LITTLE16(v6spr.sectnum);
v6spr.statnum = B_LITTLE16(v6spr.statnum);
v6spr.lotag = B_LITTLE16(v6spr.lotag);
v6spr.hitag = B_LITTLE16(v6spr.hitag);
v6spr.extra = B_LITTLE16(v6spr.extra);
break;
}
switch (mapversion)
{
case 5:
convertv5sprv6(&v5spr,&v6spr);
fallthrough__;
case 6:
convertv6sprv7(&v6spr,&sprite[i]);
break;
}
check_sprite(i);
}
// Done reading file.
g_loadedMapVersion = mapversion;
return engineFinishLoadBoard(filename, dapos, dacursectnum, numsprites, 0);
}
//
// setgamemode
//

View file

@ -1,261 +0,0 @@
/* For single inclusion into engine.c only! */
#pragma pack(push,1)
struct sectortypev5
{
uint16_t wallptr, wallnum;
int16_t ceilingpicnum, floorpicnum;
int16_t ceilingheinum, floorheinum;
int32_t ceilingz, floorz;
int8_t ceilingshade, floorshade;
char ceilingxpanning, floorxpanning;
char ceilingypanning, floorypanning;
char ceilingstat, floorstat;
char ceilingpal, floorpal;
char visibility;
int16_t lotag, hitag;
int16_t extra;
};
struct walltypev5
{
int32_t x, y;
int16_t point2;
int16_t picnum, overpicnum;
int8_t shade;
int16_t cstat;
char xrepeat, yrepeat, xpanning, ypanning;
int16_t nextsector1, nextwall1;
int16_t nextsector2, nextwall2;
int16_t lotag, hitag;
int16_t extra;
};
struct spritetypev5
{
int32_t x, y, z;
char cstat;
int8_t shade;
char xrepeat, yrepeat;
int16_t picnum, ang, xvel, yvel, zvel, owner;
int16_t sectnum, statnum;
int16_t lotag, hitag;
int16_t extra;
};
struct sectortypev6
{
uint16_t wallptr, wallnum;
int16_t ceilingpicnum, floorpicnum;
int16_t ceilingheinum, floorheinum;
int32_t ceilingz, floorz;
int8_t ceilingshade, floorshade;
char ceilingxpanning, floorxpanning;
char ceilingypanning, floorypanning;
char ceilingstat, floorstat;
char ceilingpal, floorpal;
char visibility;
int16_t lotag, hitag, extra;
};
struct walltypev6
{
int32_t x, y;
int16_t point2, nextsector, nextwall;
int16_t picnum, overpicnum;
int8_t shade;
char pal;
int16_t cstat;
char xrepeat, yrepeat, xpanning, ypanning;
int16_t lotag, hitag, extra;
};
struct spritetypev6
{
int32_t x, y, z;
int16_t cstat;
int8_t shade;
char pal, clipdist;
char xrepeat, yrepeat;
int8_t xoffset, yoffset;
int16_t picnum, ang, xvel, yvel, zvel, owner;
int16_t sectnum, statnum;
int16_t lotag, hitag, extra;
};
#pragma pack(pop)
static int16_t sectorofwallv5(int16_t theline)
{
int16_t i, startwall, endwall, sucksect;
sucksect = -1;
for (i=0; i<numsectors; i++)
{
startwall = sector[i].wallptr;
endwall = startwall + sector[i].wallnum - 1;
if ((theline >= startwall) && (theline <= endwall))
{
sucksect = i;
break;
}
}
return(sucksect);
}
static void convertv5sectv6(struct sectortypev5 *from, struct sectortypev6 *to)
{
to->wallptr = from->wallptr;
to->wallnum = from->wallnum;
to->ceilingpicnum = from->ceilingpicnum;
to->floorpicnum = from->floorpicnum;
to->ceilingheinum = from->ceilingheinum;
to->floorheinum = from->floorheinum;
to->ceilingz = from->ceilingz;
to->floorz = from->floorz;
to->ceilingshade = from->ceilingshade;
to->floorshade = from->floorshade;
to->ceilingxpanning = from->ceilingxpanning;
to->floorxpanning = from->floorxpanning;
to->ceilingypanning = from->ceilingypanning;
to->floorypanning = from->floorypanning;
to->ceilingstat = from->ceilingstat;
to->floorstat = from->floorstat;
to->ceilingpal = from->ceilingpal;
to->floorpal = from->floorpal;
to->visibility = from->visibility;
to->lotag = from->lotag;
to->hitag = from->hitag;
to->extra = from->extra;
}
static void convertv5wallv6(struct walltypev5 *from, struct walltypev6 *to, int32_t i)
{
to->x = from->x;
to->y = from->y;
to->point2 = from->point2;
to->nextsector = from->nextsector1;
to->nextwall = from->nextwall1;
to->picnum = from->picnum;
to->overpicnum = from->overpicnum;
to->shade = from->shade;
to->pal = sector[sectorofwallv5((int16_t)i)].floorpal;
to->cstat = from->cstat;
to->xrepeat = from->xrepeat;
to->yrepeat = from->yrepeat;
to->xpanning = from->xpanning;
to->ypanning = from->ypanning;
to->lotag = from->lotag;
to->hitag = from->hitag;
to->extra = from->extra;
}
static void convertv5sprv6(struct spritetypev5 *from, struct spritetypev6 *to)
{
int16_t j;
to->x = from->x;
to->y = from->y;
to->z = from->z;
to->cstat = from->cstat;
to->shade = from->shade;
j = from->sectnum;
if ((sector[j].ceilingstat&1) > 0)
to->pal = sector[j].ceilingpal;
else
to->pal = sector[j].floorpal;
to->clipdist = 32;
to->xrepeat = from->xrepeat;
to->yrepeat = from->yrepeat;
to->xoffset = 0;
to->yoffset = 0;
to->picnum = from->picnum;
to->ang = from->ang;
to->xvel = from->xvel;
to->yvel = from->yvel;
to->zvel = from->zvel;
to->owner = from->owner;
to->sectnum = from->sectnum;
to->statnum = from->statnum;
to->lotag = from->lotag;
to->hitag = from->hitag;
to->extra = from->extra;
}
static void convertv6sectv7(struct sectortypev6 *from, sectortype *to)
{
to->ceilingz = from->ceilingz;
to->floorz = from->floorz;
to->wallptr = from->wallptr;
to->wallnum = from->wallnum;
to->ceilingpicnum = from->ceilingpicnum;
to->ceilingheinum = max(min(((int32_t)from->ceilingheinum)<<5,32767),-32768);
if ((from->ceilingstat&2) == 0) to->ceilingheinum = 0;
to->ceilingshade = from->ceilingshade;
to->ceilingpal = from->ceilingpal;
to->ceilingxpanning = from->ceilingxpanning;
to->ceilingypanning = from->ceilingypanning;
to->floorpicnum = from->floorpicnum;
to->floorheinum = max(min(((int32_t)from->floorheinum)<<5,32767),-32768);
if ((from->floorstat&2) == 0) to->floorheinum = 0;
to->floorshade = from->floorshade;
to->floorpal = from->floorpal;
to->floorxpanning = from->floorxpanning;
to->floorypanning = from->floorypanning;
to->ceilingstat = from->ceilingstat;
to->floorstat = from->floorstat;
to->visibility = from->visibility;
to->fogpal = 0;
to->lotag = from->lotag;
to->hitag = from->hitag;
to->extra = from->extra;
#ifdef NEW_MAP_FORMAT
to->ceilingbunch = to->floorbunch = -1;
#endif
}
static void convertv6wallv7(struct walltypev6 *from, walltype *to)
{
to->x = from->x;
to->y = from->y;
to->point2 = from->point2;
to->nextwall = from->nextwall;
to->nextsector = from->nextsector;
to->cstat = from->cstat;
to->picnum = from->picnum;
to->overpicnum = from->overpicnum;
to->shade = from->shade;
to->pal = from->pal;
to->xrepeat = from->xrepeat;
to->yrepeat = from->yrepeat;
to->xpanning = from->xpanning;
to->ypanning = from->ypanning;
to->lotag = from->lotag;
to->hitag = from->hitag;
to->extra = from->extra;
#ifdef NEW_MAP_FORMAT
to->upwall = to->dnwall = -1;
#endif
}
static void convertv6sprv7(struct spritetypev6 *from, spritetype *to)
{
to->x = from->x;
to->y = from->y;
to->z = from->z;
to->cstat = from->cstat;
to->picnum = from->picnum;
to->shade = from->shade;
to->pal = from->pal;
to->clipdist = from->clipdist;
to->blend = 0;
to->xrepeat = from->xrepeat;
to->yrepeat = from->yrepeat;
to->xoffset = from->xoffset;
to->yoffset = from->yoffset;
to->sectnum = from->sectnum;
to->statnum = from->statnum;
to->ang = from->ang;
to->owner = from->owner;
to->xvel = from->xvel;
to->yvel = from->yvel;
to->zvel = from->zvel;
to->lotag = from->lotag;
to->hitag = from->hitag;
to->extra = from->extra;
}

440
source/core/maploader.cpp Normal file
View file

@ -0,0 +1,440 @@
/*
** maploader.cpp
**
** Map loader for non-Blood maps
**
**---------------------------------------------------------------------------
** Copyright 2020 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include <stdint.h>
#include "build.h"
#include "files.h"
#include "automap.h"
#include "printf.h"
#include "inputstate.h"
#include "md4.h"
static void ReadSectorV7(FileReader& fr, sectortype& sect)
{
sect.wallptr = fr.ReadInt16();
sect.wallnum = fr.ReadInt16();
sect.ceilingz = fr.ReadInt32();
sect.floorz = fr.ReadInt32();
sect.ceilingstat = fr.ReadUInt16();
sect.floorstat = fr.ReadUInt16();
sect.ceilingpicnum = fr.ReadUInt16();
sect.ceilingheinum = fr.ReadUInt16();
sect.ceilingshade = fr.ReadInt8();
sect.ceilingpal = fr.ReadUInt8();
sect.ceilingxpanning = fr.ReadUInt8();
sect.ceilingypanning = fr.ReadUInt8();
sect.floorpicnum = fr.ReadUInt16();
sect.floorheinum = fr.ReadUInt16();
sect.floorshade = fr.ReadInt8();
sect.floorpal = fr.ReadUInt8();
sect.floorxpanning = fr.ReadUInt8();
sect.floorypanning = fr.ReadUInt8();
sect.visibility = fr.ReadUInt8();
sect.fogpal = fr.ReadUInt8(); // note: currently unused.
sect.lotag = fr.ReadInt16();
sect.hitag = fr.ReadInt16();
sect.extra = fr.ReadInt16();
}
static void ReadSectorV6(FileReader& fr, sectortype& sect)
{
sect.wallptr = fr.ReadUInt16();
sect.wallnum = fr.ReadUInt16();
sect.ceilingpicnum = fr.ReadUInt16();
sect.floorpicnum = fr.ReadUInt16();
sect.ceilingheinum = fr.ReadUInt16();
sect.floorheinum = fr.ReadUInt16();
sect.ceilingz = fr.ReadInt32();
sect.floorz = fr.ReadInt32();
sect.ceilingshade = fr.ReadInt8();
sect.floorshade = fr.ReadInt8();
sect.ceilingxpanning = fr.ReadUInt8();
sect.floorxpanning = fr.ReadUInt8();
sect.ceilingypanning = fr.ReadUInt8();
sect.floorypanning = fr.ReadUInt8();
sect.ceilingstat = fr.ReadUInt8();
sect.floorstat = fr.ReadUInt8();
sect.ceilingpal = fr.ReadUInt8();
sect.floorpal = fr.ReadUInt8();
sect.visibility = fr.ReadUInt8();
sect.lotag = fr.ReadInt16();
sect.hitag = fr.ReadInt16();
sect.extra = fr.ReadInt16();
}
static void ReadSectorV5(FileReader& fr, sectortype& sect)
{
sect.wallptr = fr.ReadInt16();
sect.wallnum = fr.ReadInt16();
sect.ceilingpicnum = fr.ReadUInt16();
sect.floorpicnum = fr.ReadUInt16();
sect.ceilingheinum = clamp(fr.ReadUInt16(), -32768, 32767);
sect.floorheinum = clamp(fr.ReadUInt16(), -32768, 32767);
sect.ceilingz = fr.ReadInt32();
sect.floorz = fr.ReadInt32();
sect.ceilingshade = fr.ReadInt8();
sect.floorshade = fr.ReadInt8();
sect.ceilingxpanning = fr.ReadUInt8();
sect.floorxpanning = fr.ReadUInt8();
sect.ceilingypanning = fr.ReadUInt8();
sect.floorypanning = fr.ReadUInt8();
sect.ceilingstat = fr.ReadUInt8();
sect.floorstat = fr.ReadUInt8();
sect.ceilingpal = fr.ReadUInt8();
sect.floorpal = fr.ReadUInt8();
sect.visibility = fr.ReadUInt8();
sect.lotag = fr.ReadInt16();
sect.hitag = fr.ReadInt16();
sect.extra = fr.ReadInt16();
if ((sect.ceilingstat & 2) == 0) sect.ceilingheinum = 0;
if ((sect.floorstat & 2) == 0) sect.floorheinum = 0;
}
static void ReadWallV7(FileReader& fr, walltype& wall)
{
wall.pos.x = fr.ReadInt32();
wall.pos.y = fr.ReadInt32();
wall.point2 = fr.ReadInt16();
wall.nextwall = fr.ReadInt16();
wall.nextsector = fr.ReadInt16();
wall.cstat = fr.ReadUInt16();
wall.picnum = fr.ReadInt16();
wall.overpicnum = fr.ReadInt16();
wall.shade = fr.ReadInt8();
wall.pal = fr.ReadUInt8();
wall.xrepeat = fr.ReadUInt8();
wall.yrepeat = fr.ReadUInt8();
wall.xpanning = fr.ReadUInt8();
wall.ypanning = fr.ReadUInt8();
wall.lotag = fr.ReadInt16();
wall.hitag = fr.ReadInt16();
wall.extra = fr.ReadInt16();
}
static void ReadWallV6(FileReader& fr, walltype& wall)
{
wall.pos.x = fr.ReadInt32();
wall.pos.y = fr.ReadInt32();
wall.point2 = fr.ReadInt16();
wall.nextsector = fr.ReadInt16();
wall.nextwall = fr.ReadInt16();
wall.picnum = fr.ReadInt16();
wall.overpicnum = fr.ReadInt16();
wall.shade = fr.ReadInt8();
wall.pal = fr.ReadUInt8();
wall.cstat = fr.ReadUInt16();
wall.xrepeat = fr.ReadUInt8();
wall.yrepeat = fr.ReadUInt8();
wall.xpanning = fr.ReadUInt8();
wall.ypanning = fr.ReadUInt8();
wall.lotag = fr.ReadInt16();
wall.hitag = fr.ReadInt16();
wall.extra = fr.ReadInt16();
}
static void ReadWallV5(FileReader& fr, walltype& wall)
{
wall.pos.x = fr.ReadInt32();
wall.pos.y = fr.ReadInt32();
wall.point2 = fr.ReadInt16();
wall.picnum = fr.ReadInt16();
wall.overpicnum = fr.ReadInt16();
wall.shade = fr.ReadInt8();
wall.cstat = fr.ReadUInt16();
wall.xrepeat = fr.ReadUInt8();
wall.yrepeat = fr.ReadUInt8();
wall.xpanning = fr.ReadUInt8();
wall.ypanning = fr.ReadUInt8();
wall.nextsector = fr.ReadInt16();
wall.nextwall = fr.ReadInt16();
fr.Seek(4, FileReader::SeekSet); // skip over 2 unused 16 bit values
wall.lotag = fr.ReadInt16();
wall.hitag = fr.ReadInt16();
wall.extra = fr.ReadInt16();
}
static void SetWallPalV5()
{
for (int i = 0; i < numsectors; i++)
{
int startwall = sector[i].wallptr;
int endwall = startwall + sector[i].wallnum;
for (int w = startwall; w < endwall; w++)
{
wall[w].pal = sector[i].floorpal;
}
}
}
static void ValidateSprite(spritetype& spr)
{
int index = &spr - sprite;
bool bugged = false;
if ((unsigned)spr.statnum >= MAXSTATUS)
{
Printf("Sprite #%d (%d,%d) has invalid statnum %d.\n", index, spr.x, spr.y, spr.statnum);
bugged = true;
}
else if ((unsigned)spr.picnum >= MAXTILES)
{
Printf("Sprite #%d (%d,%d) has invalid picnum %d.\n", index, spr.x, spr.y, spr.picnum);
bugged = true;
}
else if ((unsigned)spr.sectnum >= (unsigned)numsectors)
{
const int32_t osectnum = spr.sectnum;
spr.sectnum = -1;
updatesector(spr.x, spr.y, &spr.sectnum);
bugged = spr.sectnum < 0;
if (bugged) Printf("Sprite #%d (%d,%d) with invalid sector %d\n", index, spr.x, spr.y, spr.sectnum);
}
if (bugged)
{
spr = {};
spr.statnum = MAXSTATUS;
spr.sectnum = MAXSECTORS;
}
}
static void ReadSpriteV7(FileReader& fr, spritetype& spr)
{
spr.pos.x = fr.ReadInt32();
spr.pos.y = fr.ReadInt32();
spr.pos.z = fr.ReadInt32();
spr.cstat = fr.ReadUInt16();
spr.picnum = fr.ReadInt16();
spr.shade = fr.ReadInt8();
spr.pal = fr.ReadUInt8();
spr.clipdist = fr.ReadUInt8();
spr.blend = fr.ReadUInt8();
spr.xrepeat = fr.ReadUInt8();
spr.yrepeat = fr.ReadUInt8();
spr.xoffset = fr.ReadInt8();
spr.yoffset = fr.ReadInt8();
spr.sectnum = fr.ReadInt16();
spr.statnum = fr.ReadInt16();
spr.ang = fr.ReadInt16();
spr.owner = fr.ReadInt16();
spr.xvel = fr.ReadInt16();
spr.yvel = fr.ReadInt16();
spr.zvel = fr.ReadInt16();
spr.lotag = fr.ReadInt16();
spr.hitag = fr.ReadInt16();
spr.extra = fr.ReadInt16();
ValidateSprite(spr);
}
static void ReadSpriteV6(FileReader& fr, spritetype& spr)
{
spr.pos.x = fr.ReadInt32();
spr.pos.y = fr.ReadInt32();
spr.pos.z = fr.ReadInt32();
spr.cstat = fr.ReadUInt16();
spr.shade = fr.ReadInt8();
spr.pal = fr.ReadUInt8();
spr.clipdist = fr.ReadUInt8();
spr.xrepeat = fr.ReadUInt8();
spr.yrepeat = fr.ReadUInt8();
spr.xoffset = fr.ReadInt8();
spr.yoffset = fr.ReadInt8();
spr.picnum = fr.ReadInt16();
spr.ang = fr.ReadInt16();
spr.xvel = fr.ReadInt16();
spr.yvel = fr.ReadInt16();
spr.zvel = fr.ReadInt16();
spr.owner = fr.ReadInt16();
spr.sectnum = fr.ReadInt16();
spr.statnum = fr.ReadInt16();
spr.lotag = fr.ReadInt16();
spr.hitag = fr.ReadInt16();
spr.extra = fr.ReadInt16();
spr.blend = 0;
ValidateSprite(spr);
}
static void ReadSpriteV5(FileReader& fr, spritetype& spr)
{
spr.pos.x = fr.ReadInt32();
spr.pos.y = fr.ReadInt32();
spr.pos.z = fr.ReadInt32();
spr.cstat = fr.ReadUInt16();
spr.shade = fr.ReadInt8();
spr.xrepeat = fr.ReadUInt8();
spr.yrepeat = fr.ReadUInt8();
spr.picnum = fr.ReadInt16();
spr.ang = fr.ReadInt16();
spr.xvel = fr.ReadInt16();
spr.yvel = fr.ReadInt16();
spr.zvel = fr.ReadInt16();
spr.owner = fr.ReadInt16();
spr.sectnum = fr.ReadInt16();
spr.statnum = fr.ReadInt16();
spr.lotag = fr.ReadInt16();
spr.hitag = fr.ReadInt16();
spr.extra = fr.ReadInt16();
int sec = spr.sectnum;
if ((sector[sec].ceilingstat & 1) > 0)
spr.pal = sector[sec].ceilingpal;
else
spr.pal = sector[sec].floorpal;
spr.blend = 0;
spr.clipdist = 32;
spr.xoffset = 0;
spr.yoffset = 0;
ValidateSprite(spr);
}
static void insertAllSprites(const char* filename, const vec3_t* pos, int16_t* cursectnum, int16_t numsprites)
{
// This function is stupid because it exploits side effects of insertsprite and should be redone by only inserting the valid sprites.
int i, realnumsprites = numsprites;
for (i = 0; i < numsprites; i++)
{
bool removeit = false;
auto& spr = sprite[i];
if (spr.statnum == MAXSTATUS)
{
spr.statnum = spr.sectnum = 0;
removeit = true;
}
insertsprite(spr.sectnum, spr.statnum);
if (removeit)
{
sprite[i].statnum = MAXSTATUS;
realnumsprites--;
}
}
if (numsprites != realnumsprites)
{
for (i = 0; i < numsprites; i++)
if (sprite[i].statnum == MAXSTATUS)
{
// Now remove it for real!
sprite[i].statnum = 0;
deletesprite(i);
}
}
assert(realnumsprites == Numsprites);
}
void engineLoadBoard(const char* filename, int flags, vec3_t* pos, int16_t* ang, int16_t* cursectnum)
{
inputState.ClearAllInput();
FileReader fr = fileSystem.OpenFileReader(filename);
if (!fr.isOpen()) I_Error("Unable to open map %s", filename);
int mapversion = fr.ReadInt32();
if (mapversion < 5 || mapversion > 9) // 9 is most likely useless but let's try anyway.
{
I_Error("%s: Invalid map format, expcted 5-9, got %d", filename, mapversion);
}
memset(spriteext, 0, sizeof(spriteext_t) * MAXSPRITES);
memset(spritesmooth, 0, sizeof(spritesmooth_t) * (MAXSPRITES + MAXUNIQHUDID));
initspritelists();
ClearAutomap();
Polymost_prepare_loadboard();
pos->x = fr.ReadInt32();
pos->y = fr.ReadInt32();
pos->z = fr.ReadInt32();
*ang = fr.ReadInt16() & 2047;
*cursectnum = fr.ReadUInt16();
numsectors = fr.ReadUInt16();
if ((unsigned)numsectors > MAXSECTORS) I_Error("%s: Invalid map, too many sectors", filename);
for (int i = 0; i < numsectors; i++)
{
switch (mapversion)
{
case 5: ReadSectorV5(fr, sector[i]); break;
case 6: ReadSectorV6(fr, sector[i]); break;
default: ReadSectorV7(fr, sector[i]); break;
}
}
numwalls = fr.ReadUInt16();
if ((unsigned)numwalls > MAXWALLS) I_Error("%s: Invalid map, too many walls", filename);
for (int i = 0; i < numwalls; i++)
{
switch (mapversion)
{
case 5: ReadWallV5(fr, wall[i]); break;
case 6: ReadWallV6(fr, wall[i]); break;
default: ReadWallV7(fr, wall[i]); break;
}
}
int numsprites = fr.ReadUInt16();
if ((unsigned)numsprites > MAXSPRITES) I_Error("%s: Invalid map, too many sprites", filename);
for (int i = 0; i < numsprites; i++)
{
switch (mapversion)
{
case 5: ReadSpriteV5(fr, sprite[i]); break;
case 6: ReadSpriteV6(fr, sprite[i]); break;
default: ReadSpriteV7(fr, sprite[i]); break;
}
}
artSetupMapArt(filename);
insertAllSprites(filename, pos, cursectnum, numsprites);
for (int i = 0; i < numsprites; i++)
{
if ((sprite[i].cstat & 48) == 48) sprite[i].cstat &= ~48;
}
//Must be last.
updatesector(pos->x, pos->y, cursectnum);
guniqhudid = 0;
G_LoadMapHack(filename);
}

View file

@ -141,9 +141,7 @@ uint8_t LoadLevel(int nMap)
}
vec3_t startPos;
int status = engineLoadBoard(currentLevel->fileName, 0, &startPos, &inita, &initsect);
if (status == -2)
status = engineLoadBoardV5V6(currentLevel->fileName, 0, &startPos, &inita, &initsect);
engineLoadBoard(currentLevel->fileName, 0, &startPos, &inita, &initsect);
initx = startPos.x;
inity = startPos.y;
initz = startPos.z;

View file

@ -864,10 +864,8 @@ static int LoadTheMap(MapRecord *mi, struct player_struct *p, int gamemode)
I_Error("Cannot load user maps with shareware version!\n");
}
if (engineLoadBoard(mi->fileName, VOLUMEONE, &p->pos, &lbang, &p->cursectnum) < 0)
{
I_Error("Map \"%s\" not found or invalid map version!\n", mi->fileName.GetChars());
}
engineLoadBoard(mi->fileName, VOLUMEONE, &p->pos, &lbang, &p->cursectnum);
currentLevel = mi;
SECRET_SetMapName(mi->DisplayName(), mi->name);
STAT_NewLevel(mi->fileName);

View file

@ -332,10 +332,7 @@ void InitLevel(MapRecord *maprec)
}
int16_t ang;
if (engineLoadBoard(maprec->fileName, SW_SHAREWARE ? 1 : 0, (vec3_t*)&Player[0], &ang, &Player[0].cursectnum) == -1)
{
I_Error("Map not found: %s", maprec->fileName.GetChars());
}
engineLoadBoard(maprec->fileName, SW_SHAREWARE ? 1 : 0, (vec3_t*)&Player[0], &ang, &Player[0].cursectnum);
currentLevel = maprec;
SECRET_SetMapName(currentLevel->DisplayName(), currentLevel->name);
STAT_NewLevel(currentLevel->fileName);