From b4a011300a9c49e786a8c1b6d07ed96469e87af2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 11 Oct 2020 20:57:20 +0200 Subject: [PATCH] - implemented proper delta serialization for sectors and walls. --- source/blood/src/blood.cpp | 5 +- source/blood/src/db.cpp | 151 +++++++++++++++++++++++------------ source/blood/src/db.h | 2 +- source/blood/src/replace.cpp | 1 - source/build/include/build.h | 27 ++----- source/core/maploader.cpp | 26 +++++- source/core/savegamehelp.cpp | 13 +-- 7 files changed, 137 insertions(+), 88 deletions(-) diff --git a/source/blood/src/blood.cpp b/source/blood/src/blood.cpp index 1442f8505..c486ebbb6 100644 --- a/source/blood/src/blood.cpp +++ b/source/blood/src/blood.cpp @@ -129,10 +129,7 @@ void StartLevel(MapRecord* level) memset(xsprite, 0, sizeof(xsprite)); memset(sprite, 0, kMaxSprites * sizeof(spritetype)); //drawLoadingScreen(); - if (dbLoadMap(currentLevel->fileName, (int*)&startpos.x, (int*)&startpos.y, (int*)&startpos.z, &startang, &startsectnum, nullptr)) - { - I_Error("%s: Unable to load map", level->DisplayName()); - } + dbLoadMap(currentLevel->fileName, (int*)&startpos.x, (int*)&startpos.y, (int*)&startpos.z, &startang, &startsectnum, nullptr); SECRET_SetMapName(currentLevel->DisplayName(), currentLevel->name); STAT_NewLevel(currentLevel->fileName); wsrand(dbReadMapCRC(currentLevel->LabelName())); diff --git a/source/blood/src/db.cpp b/source/blood/src/db.cpp index 15d14d4b5..13e9bad13 100644 --- a/source/blood/src/db.cpp +++ b/source/blood/src/db.cpp @@ -457,10 +457,41 @@ struct spritetypedisk int16_t hitag; int16_t extra; }; + +struct sectortypedisk +{ + int16_t wallptr, wallnum; + int32_t ceilingz, floorz; + uint16_t ceilingstat, floorstat; + int16_t ceilingpicnum, ceilingheinum; + int8_t ceilingshade; + uint8_t ceilingpal, ceilingxpanning, ceilingypanning; + int16_t floorpicnum, floorheinum; + int8_t floorshade; + uint8_t floorpal, floorxpanning, floorypanning; + uint8_t visibility, fogpal; + int16_t type; + int16_t hitag; + int16_t extra; +}; + +struct walltypedisk +{ + int32_t x, y; + int16_t point2, nextwall, nextsector; + uint16_t cstat; + int16_t picnum, overpicnum; + int8_t shade; + uint8_t pal, xrepeat, yrepeat, xpanning, ypanning; + int16_t type; + int16_t hitag; + int16_t extra; +}; + #pragma pack(pop) -int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short *pSector, unsigned int *pCRC) { +void dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short *pSector, unsigned int *pCRC) { int16_t tpskyoff[256]; ClearAutomap(); #ifdef NOONE_EXTENSIONS @@ -477,15 +508,13 @@ int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short if (!fr.isOpen()) { - Printf("Error opening map file %s", mapname.GetChars()); - return -1; + I_Error("Error opening map file %s", mapname.GetChars()); } MAPSIGNATURE header; fr.Read(&header, 6); if (memcmp(header.signature, "BLM\x1a", 4)) { - Printf("%s: Map file corrupted", mapname.GetChars()); - return -1; + I_Error("%s: Map file corrupted", mapname.GetChars()); } byte_1A76C8 = 0; if ((LittleShort(header.version) & 0xff00) == 0x700) { @@ -499,8 +528,7 @@ int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short #endif } else { - Printf("%s: Map file is wrong version", mapname.GetChars()); - return -1; + I_Error("%s: Map file is wrong version", mapname.GetChars()); } MAPHEADER mapHeader; @@ -542,14 +570,12 @@ int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short } else { - Printf("%s: Corrupted Map file", mapname.GetChars()); - return -1; + I_Error("%s: Corrupted Map file", mapname.GetChars()); } } else if (mapHeader.at16) { - Printf("%s: Corrupted Map file", mapname.GetChars()); - return -1; + I_Error("%s: Corrupted Map file", mapname.GetChars()); } parallaxtype = mapHeader.at1a; gMapRev = mapHeader.at1b; @@ -587,27 +613,37 @@ int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short for (int i = 0; i < numsectors; i++) { sectortype *pSector = §or[i]; - fr.Read(pSector, sizeof(sectortype)); + sectortypedisk load; + fr.Read(&load, sizeof(sectortypedisk)); if (byte_1A76C8) { - dbCrypt((char*)pSector, sizeof(sectortype), gMapRev*sizeof(sectortype)); + dbCrypt((char*)&load, sizeof(sectortypedisk), gMapRev*sizeof(sectortypedisk)); } - pSector->wallptr = LittleShort(pSector->wallptr); - pSector->wallnum = LittleShort(pSector->wallnum); - pSector->ceilingz = LittleLong(pSector->ceilingz); - pSector->floorz = LittleLong(pSector->floorz); - pSector->ceilingstat = LittleShort(pSector->ceilingstat); - pSector->floorstat = LittleShort(pSector->floorstat); - pSector->ceilingpicnum = LittleShort(pSector->ceilingpicnum); - pSector->ceilingheinum = LittleShort(pSector->ceilingheinum); - pSector->floorpicnum = LittleShort(pSector->floorpicnum); - pSector->floorheinum = LittleShort(pSector->floorheinum); - pSector->type = LittleShort(pSector->type); - pSector->hitag = LittleShort(pSector->hitag); - pSector->extra = LittleShort(pSector->extra); - - qsector_filler[i] = pSector->fogpal; + pSector->wallptr = LittleShort(load.wallptr); + pSector->wallnum = LittleShort(load.wallnum); + pSector->ceilingz = LittleLong(load.ceilingz); + pSector->floorz = LittleLong(load.floorz); + pSector->ceilingstat = LittleShort(load.ceilingstat); + pSector->floorstat = LittleShort(load.floorstat); + pSector->ceilingpicnum = LittleShort(load.ceilingpicnum); + pSector->ceilingheinum = LittleShort(load.ceilingheinum); + pSector->floorpicnum = LittleShort(load.floorpicnum); + pSector->floorheinum = LittleShort(load.floorheinum); + pSector->type = LittleShort(load.type); + pSector->hitag = LittleShort(load.hitag); + pSector->extra = LittleShort(load.extra); + pSector->ceilingshade = load.ceilingshade; + pSector->ceilingpal = load.ceilingpal; + pSector->ceilingxpanning = load.ceilingxpanning; + pSector->ceilingypanning = load.ceilingypanning; + pSector->floorshade = load.floorshade; + pSector->floorpal = load.floorpal; + pSector->floorxpanning = load.floorxpanning; + pSector->floorypanning = load.floorypanning; + pSector->visibility = load.visibility; + qsector_filler[i] = load.fogpal; pSector->fogpal = 0; + if (sector[i].extra > 0) { char pBuffer[nXSectorSize]; @@ -711,22 +747,30 @@ int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short for (int i = 0; i < numwalls; i++) { walltype *pWall = &wall[i]; - fr.Read(pWall, sizeof(walltype)); + walltypedisk load; + fr.Read(&load, sizeof(walltypedisk)); if (byte_1A76C8) { - dbCrypt((char*)pWall, sizeof(walltype), (gMapRev*sizeof(sectortype)) | 0x7474614d); + dbCrypt((char*)&load, sizeof(walltypedisk), (gMapRev*sizeof(sectortypedisk)) | 0x7474614d); } - pWall->x = LittleLong(pWall->x); - pWall->y = LittleLong(pWall->y); - pWall->point2 = LittleShort(pWall->point2); - pWall->nextwall = LittleShort(pWall->nextwall); - pWall->nextsector = LittleShort(pWall->nextsector); - pWall->cstat = LittleShort(pWall->cstat); - pWall->picnum = LittleShort(pWall->picnum); - pWall->overpicnum = LittleShort(pWall->overpicnum); - pWall->type = LittleShort(pWall->type); - pWall->hitag = LittleShort(pWall->hitag); - pWall->extra = LittleShort(pWall->extra); + pWall->x = LittleLong(load.x); + pWall->y = LittleLong(load.y); + pWall->point2 = LittleShort(load.point2); + pWall->nextwall = LittleShort(load.nextwall); + pWall->nextsector = LittleShort(load.nextsector); + pWall->cstat = LittleShort(load.cstat); + pWall->picnum = LittleShort(load.picnum); + pWall->overpicnum = LittleShort(load.overpicnum); + pWall->type = LittleShort(load.type); + pWall->hitag = LittleShort(load.hitag); + pWall->extra = LittleShort(load.extra); + pWall->shade = load.shade; + pWall->pal = load.pal; + pWall->xrepeat = load.xrepeat; + pWall->xpanning = load.xpanning; + pWall->yrepeat = load.yrepeat; + pWall->ypanning = load.ypanning; + if (wall[i].extra > 0) { char pBuffer[nXWallSize]; @@ -927,8 +971,7 @@ int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short if (CalcCRC32(buffer.Data(), buffer.Size() -4) != nCRC) { - Printf("%s: Map File does not match CRC", mapname.GetChars()); - return -1; + I_Error("%s: Map File does not match CRC", mapname.GetChars()); } if (pCRC) *pCRC = nCRC; @@ -945,14 +988,12 @@ int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short } else { - Printf("%s: Corrupted Map file", mapname.GetChars()); - return -1; + I_Error("%s: Corrupted Map file", mapname.GetChars()); } } else if (gSongId != 0) { - Printf("%s: Corrupted Map file", mapname.GetChars()); - return -1; + I_Error("%s: Corrupted Map file", mapname.GetChars()); } if ((header.version & 0xff00) == 0x600) @@ -1002,14 +1043,18 @@ int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short } } - return 0; -} -int32_t qloadboard(const char* filename, char flags, vec3_t* dapos, int16_t* daang, int16_t* dacursectnum) -{ - // NUKE-TODO: implement flags, see mapedit.cpp - return dbLoadMap(filename, &dapos->x, &dapos->y, &dapos->z, (short*)daang, (short*)dacursectnum, NULL); + memcpy(wallbackup, wall, sizeof(wallbackup)); + memcpy(sectorbackup, sector, sizeof(sectorbackup)); + // todo: back up xsector and xwall as well } END_BLD_NS + +// only used by the backup loader. +void qloadboard(const char* filename, char flags, vec3_t* dapos, int16_t* daang, int16_t* dacursectnum) +{ + Blood::dbLoadMap(filename, &dapos->x, &dapos->y, &dapos->z, (short*)daang, (short*)dacursectnum, NULL); + Blood::dbInit(); // clean up immediately. +} diff --git a/source/blood/src/db.h b/source/blood/src/db.h index 1cb0ae149..6f255bbce 100644 --- a/source/blood/src/db.h +++ b/source/blood/src/db.h @@ -356,6 +356,6 @@ unsigned short dbInsertXSector(int nSector); void dbInit(void); void PropagateMarkerReferences(void); unsigned int dbReadMapCRC(const char *pPath); -int dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short *pSector, unsigned int *pCRC); +void dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, short *pSector, unsigned int *pCRC); END_BLD_NS diff --git a/source/blood/src/replace.cpp b/source/blood/src/replace.cpp index 2589d7cd3..fc74d7950 100644 --- a/source/blood/src/replace.cpp +++ b/source/blood/src/replace.cpp @@ -76,7 +76,6 @@ int32_t qinsertsprite(int16_t nSector, int16_t nStat); int32_t qdeletesprite(int16_t nSprite); int32_t qchangespritesect(int16_t nSprite, int16_t nSector); int32_t qchangespritestat(int16_t nSprite, int16_t nStatus); -int32_t qloadboard(const char* filename, char flags, vec3_t* dapos, int16_t* daang, int16_t* dacursectnum); void HookReplaceFunctions(void) { diff --git a/source/build/include/build.h b/source/build/include/build.h index 952f7a954..001372cff 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -248,7 +248,6 @@ struct usermaphack_t extern usermaphack_t g_loadedMapHack; -#if !defined DEBUG_MAIN_ARRAYS EXTERN spriteext_t *spriteext; EXTERN spritesmooth_t *spritesmooth; @@ -256,31 +255,16 @@ EXTERN sectortype *sector; EXTERN walltype *wall; EXTERN spritetype *sprite; EXTERN tspriteptr_t tsprite; -#else -#endif + +extern sectortype sectorbackup[MAXSECTORS]; +extern walltype wallbackup[MAXWALLS]; static inline tspriteptr_t renderMakeTSpriteFromSprite(tspriteptr_t const tspr, uint16_t const spritenum) { auto const spr = &sprite[spritenum]; - tspr->pos = spr->pos; - tspr->cstat = spr->cstat; - tspr->picnum = spr->picnum; - tspr->shade = spr->shade; - tspr->pal = spr->pal; - tspr->blend = spr->blend; - tspr->xrepeat = spr->xrepeat; - tspr->yrepeat = spr->yrepeat; - tspr->xoffset = spr->xoffset; - tspr->yoffset = spr->yoffset; - tspr->sectnum = spr->sectnum; - tspr->statnum = spr->statnum; - tspr->ang = spr->ang; - tspr->vel = spr->vel; - tspr->lotag = spr->lotag; - tspr->hitag = spr->hitag; - tspr->extra = spr->extra; + *tspr = *spr; tspr->clipdist = 0; tspr->owner = spritenum; @@ -561,9 +545,8 @@ void engineUnInit(void); void initspritelists(void); void engineLoadBoard(const char *filename, int flags, vec3_t *dapos, int16_t *daang, int16_t *dacursectnum); -int32_t engineLoadMHK(const char *filename); +void loadMapBackup(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); int32_t qloadkvx(int32_t voxindex, const char *filename); void vox_undefine(int32_t const); diff --git a/source/core/maploader.cpp b/source/core/maploader.cpp index ebbff0f41..d1955707a 100644 --- a/source/core/maploader.cpp +++ b/source/core/maploader.cpp @@ -40,6 +40,7 @@ #include "printf.h" #include "inputstate.h" #include "md4.h" +#include "gamecontrol.h" static void ReadSectorV7(FileReader& fr, sectortype& sect) @@ -63,7 +64,7 @@ static void ReadSectorV7(FileReader& fr, sectortype& sect) sect.floorxpanning = fr.ReadUInt8(); sect.floorypanning = fr.ReadUInt8(); sect.visibility = fr.ReadUInt8(); - sect.fogpal = fr.ReadUInt8(); // note: currently unused. + sect.fogpal = fr.ReadUInt8(); // note: currently unused, except for Blood. sect.lotag = fr.ReadInt16(); sect.hitag = fr.ReadInt16(); sect.extra = fr.ReadInt16(); @@ -440,4 +441,27 @@ void engineLoadBoard(const char* filename, int flags, vec3_t* pos, int16_t* ang, guniqhudid = 0; G_LoadMapHack(filename); + memcpy(wallbackup, wall, sizeof(wallbackup)); + memcpy(sectorbackup, sector, sizeof(sectorbackup)); } + + +void qloadboard(const char* filename, char flags, vec3_t* dapos, int16_t* daang, int16_t* dacursectnum); + + +// loads a map into the backup buffer. +void loadMapBackup(const char* filename) +{ + vec3_t pos; + int16_t scratch; + + if (g_gameType & GAMEFLAG_BLOOD) + { + qloadboard(filename, 0, &pos, &scratch, &scratch); + } + else + { + engineLoadBoard(filename, 0, &pos, &scratch, &scratch); + initspritelists(); + } +} \ No newline at end of file diff --git a/source/core/savegamehelp.cpp b/source/core/savegamehelp.cpp index 34e25e077..e93023b4e 100644 --- a/source/core/savegamehelp.cpp +++ b/source/core/savegamehelp.cpp @@ -56,6 +56,10 @@ #include "gamestate.h" #include "razemenu.h" + +sectortype sectorbackup[MAXSECTORS]; +walltype wallbackup[MAXWALLS]; + static CompositeSavegameWriter savewriter; static FResourceFile *savereader; void LoadEngineState(); @@ -135,6 +139,7 @@ bool OpenSaveGameForRead(const char *name) info->Unlock(); // Load system-side data from savegames. + loadMapBackup(currentLevel->fileName); LoadEngineState(); SerializeSession(arc); // must be AFTER LoadEngineState because it needs info from it. gi->SerializeGameState(arc); @@ -468,8 +473,6 @@ static walltype zwal; FSerializer &Serialize(FSerializer &arc, const char *key, sectortype &c, sectortype *def) { - def = &zsec; - if (arc.isReading()) c = {}; if (arc.BeginObject(key)) { arc("wallptr", c.wallptr, def->wallptr) @@ -502,8 +505,6 @@ FSerializer &Serialize(FSerializer &arc, const char *key, sectortype &c, sectort FSerializer &Serialize(FSerializer &arc, const char *key, walltype &c, walltype *def) { - def = &zwal; - if (arc.isReading()) c = {}; if (arc.BeginObject(key)) { arc("x", c.x, def->x) @@ -533,9 +534,9 @@ void SerializeMap(FSerializer& arc) if (arc.BeginObject("engine")) { arc ("numsectors", numsectors) - .Array("sectors", sector, numsectors) + .Array("sectors", sector, sectorbackup, numsectors) ("numwalls", numwalls) - .Array("walls", wall, numwalls) + .Array("walls", wall, wallbackup, numwalls) .EndObject(); }