diff --git a/source/blood/src/common_game.h b/source/blood/src/common_game.h index 711bce245..5a52a73b1 100644 --- a/source/blood/src/common_game.h +++ b/source/blood/src/common_game.h @@ -82,7 +82,6 @@ kMediumGoo = 2, // STATNUMS ///////////////////////////////////////////////////// enum { -kStatNothing = -1, kStatDecoration = 0, kStatFX = 1, kStatExplosion = 2, diff --git a/source/blood/src/db.cpp b/source/blood/src/db.cpp index 13e9bad13..e2a3639a5 100644 --- a/source/blood/src/db.cpp +++ b/source/blood/src/db.cpp @@ -104,7 +104,7 @@ void RemoveSpriteSect(int nSprite) { headspritesect[nSector] = nextspritesect[nSprite]; } - sprite[nSprite].sectnum = -1; + sprite[nSprite].sectnum = MAXSECTORS; } void InsertSpriteStat(int nSprite, int nStat) @@ -148,7 +148,7 @@ void RemoveSpriteStat(int nSprite) { headspritestat[nStat] = nextspritestat[nSprite]; } - sprite[nSprite].statnum = kStatNothing; + sprite[nSprite].statnum = MAXSTATUS; gStatCount[nStat]--; } diff --git a/source/build/include/build.h b/source/build/include/build.h index 001372cff..9c60120e6 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -201,12 +201,7 @@ typedef struct { int16_t angoff, pitch, roll; vec3_t pivot_offset, position_offset; uint8_t flags; - uint8_t xpanning, ypanning; // EDuke script hacks. - uint8_t filler; - uint32_t filler2; float alpha; - // NOTE: keep 'tspr' on an 8-byte boundary: - tspriteptr_t tspr; } spriteext_t; typedef struct { @@ -328,7 +323,6 @@ enum { PALETTE_TRANSLUC = 1<<2, }; -EXTERN char showinvisibility; EXTERN int32_t g_visibility, parallaxvisibility; // blendtable[1] to blendtable[numalphatabs] are considered to be diff --git a/source/build/include/compat.h b/source/build/include/compat.h index 70de736da..6c03955a1 100644 --- a/source/build/include/compat.h +++ b/source/build/include/compat.h @@ -11,6 +11,7 @@ #include "m_alloc.h" #include "intvec.h" #include "m_swap.h" +#include "serializer.h" ////////// Compiler detection ////////// @@ -242,5 +243,18 @@ void bfirst_search_try(T *const list, uint8_t *const bitmap, T *const eltnumptr, /* End dependence on compat.o object. */ +inline FSerializer& Serialize(FSerializer& arc, const char* key, vec3_t& c, vec3_t* def) +{ + if (def && !memcmp(&c, def, sizeof(c))) return arc; + if (arc.BeginObject(key)) + { + arc("x", c.x, def? &def->x : nullptr) + ("y", c.y, def ? &def->y : nullptr) + ("z", c.z, def ? &def->z : nullptr) + .EndObject(); + } + return arc; +} + #endif // compat_h_ diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index 5655bc537..d4e4226eb 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -943,8 +943,6 @@ int32_t engineInit(void) xyaspect = -1; - showinvisibility = 0; - voxelmemory.Reset(); for (i=0; icstat & 0x8000 && !showinvisibility) || spr->xrepeat == 0 || spr->yrepeat == 0) + if ((spr->cstat & 0x8000) || spr->xrepeat == 0 || spr->yrepeat == 0) continue; vec2_t const s = { spr->x-globalposx, spr->y-globalposy }; @@ -3204,21 +3204,6 @@ void polymost_drawsprite(int32_t snum) otex.v = -ytex.v * (pxy[3].y + .001f); } - // sprite panning - if (spriteext[spritenum].xpanning) - { - ytex.u -= ytex.d * ((float) (spriteext[spritenum].xpanning) * (1.0f / 255.f)) * ftsiz.x; - otex.u -= otex.d * ((float) (spriteext[spritenum].xpanning) * (1.0f / 255.f)) * ftsiz.x; - drawpoly_srepeat = 1; - } - - if (spriteext[spritenum].ypanning) - { - ytex.v -= ytex.d * ((float) (spriteext[spritenum].ypanning) * (1.0f / 255.f)) * ftsiz.y; - otex.v -= otex.d * ((float) (spriteext[spritenum].ypanning) * (1.0f / 255.f)) * ftsiz.y; - drawpoly_trepeat = 1; - } - // Clip sprites to ceilings/floors when no parallaxing and not sloped if (!(sector[tspr->sectnum].ceilingstat & 3)) { @@ -3363,15 +3348,6 @@ void polymost_drawsprite(int32_t snum) t1 = 1.f - t1; } - // sprite panning - if (spriteext[spritenum].xpanning) - { - float const xpan = ((float)(spriteext[spritenum].xpanning) * (1.0f / 255.f)); - t0 -= xpan; - t1 -= xpan; - drawpoly_srepeat = 1; - } - xtex.u = (t0 * ryp0 - t1 * ryp1) * gxyaspect * ftsiz.x / (sx0 - sx1); ytex.u = 0; otex.u = t0 * ryp0 * gxyaspect * ftsiz.x - xtex.u * sx0; @@ -3401,16 +3377,6 @@ void polymost_drawsprite(int32_t snum) otex.v = -xtex.v * sx0 - ytex.v * sf0; } - // sprite panning - if (spriteext[spritenum].ypanning) - { - float const ypan = ((float)(spriteext[spritenum].ypanning) * (1.0f / 255.f)) * ftsiz.y; - xtex.v -= xtex.d * ypan; - ytex.v -= ytex.d * ypan; - otex.v -= otex.d * ypan; - drawpoly_trepeat = 1; - } - // Clip sprites to ceilings/floors when no parallaxing if (!(sector[tspr->sectnum].ceilingstat & 1)) { @@ -3596,23 +3562,6 @@ void polymost_drawsprite(int32_t snum) otex.u = ftsiz.x * otex.d - otex.u; } - // sprite panning - if (spriteext[spritenum].xpanning) - { - float const f = ((float)(spriteext[spritenum].xpanning) * (1.0f / 255.f)) * ftsiz.x; - ytex.u -= ytex.d * f; - otex.u -= otex.d * f; - drawpoly_srepeat = 1; - } - - if (spriteext[spritenum].ypanning) - { - float const f = ((float)(spriteext[spritenum].ypanning) * (1.0f / 255.f)) * ftsiz.y; - ytex.v -= ytex.d * f; - otex.v -= otex.d * f; - drawpoly_trepeat = 1; - } - vec2_16_t tempsiz = { (int16_t)tsiz.x, (int16_t)tsiz.y }; pow2xsplit = 0; diff --git a/source/common/engine/serializer.h b/source/common/engine/serializer.h index 6110ca4b4..22f32f73c 100644 --- a/source/common/engine/serializer.h +++ b/source/common/engine/serializer.h @@ -125,6 +125,12 @@ public: return Serialize(*this, key, obj, save_full? nullptr : &def); } + template + FSerializer& operator()(const char* key, T& obj, T* def) + { + return Serialize(*this, key, obj, !def || save_full ? nullptr : def); + } + template FSerializer &Array(const char *key, T *obj, int count, bool fullcompare = false) { @@ -172,6 +178,29 @@ public: return *this; } + template + FSerializer &SparseArray(const char *key, T *obj, int count, const Map &map, bool fullcompare = false) + { + if (BeginArray(key)) + { + int max = count; + if (isReading()) + { + max = ArraySize(); + } + for (int i = 0; i < count; i++) + { + if (map[i]) + { + Serialize(*this, nullptr, obj[i], (T*)nullptr); + if (--max < 0) break; + } + } + EndArray(); + } + return *this; + } + template FSerializer &Enum(const char *key, T &obj) { diff --git a/source/core/savegamehelp.cpp b/source/core/savegamehelp.cpp index e93023b4e..75b5b2f4a 100644 --- a/source/core/savegamehelp.cpp +++ b/source/core/savegamehelp.cpp @@ -62,11 +62,10 @@ walltype wallbackup[MAXWALLS]; static CompositeSavegameWriter savewriter; static FResourceFile *savereader; -void LoadEngineState(); -void SaveEngineState(); void WriteSavePic(FileWriter* file, int width, int height); extern FString BackupSaveGame; void SerializeMap(FSerializer &arc); +FixedBitArray activeSprites; CVAR(String, cl_savedir, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) @@ -140,8 +139,7 @@ bool OpenSaveGameForRead(const char *name) // Load system-side data from savegames. loadMapBackup(currentLevel->fileName); - LoadEngineState(); - SerializeSession(arc); // must be AFTER LoadEngineState because it needs info from it. + SerializeSession(arc); gi->SerializeGameState(arc); } return savereader != nullptr; @@ -236,7 +234,6 @@ bool OpenSaveGameForWrite(const char* filename, const char *name) // Handle system-side modules that need to persist data in savegames here, in a central place. savegamesession.OpenWriter(save_formatted); SerializeSession(savegamesession); - SaveEngineState(); gi->SerializeGameState(savegamesession); buff = savegamesession.GetCompressedOutput(); AddCompressedSavegameChunk("session.json", buff); @@ -431,24 +428,6 @@ FString G_BuildSaveName (const char *prefix) #include "build.h" #include "mmulti.h" -static void sv_prespriteextsave() -{ - for (int i = 0; i < MAXSPRITES; i++) - if (spriteext[i].mdanimtims) - { - spriteext[i].mdanimtims -= mdtims; - if (spriteext[i].mdanimtims == 0) - spriteext[i].mdanimtims++; - } -} -static void sv_postspriteext() -{ - for (int i = 0; i < MAXSPRITES; i++) - if (spriteext[i].mdanimtims) - spriteext[i].mdanimtims += mdtims; -} - - static const int magic = 0xbeefcafe; void WriteMagic(FileWriter *fw) { @@ -468,8 +447,68 @@ void CheckMagic(FileReader& fr) #define V(x) x static spritetype zsp; -static sectortype zsec; -static walltype zwal; +static spriteext_t zspx; + +FSerializer &Serialize(FSerializer &arc, const char *key, spritetype &c, spritetype *def) +{ + def = &zsp; // always delta against 0 + if (arc.BeginObject(key)) + { + arc("x", c.x, def->x) + ("y", c.y, def->y) + ("z", c.z, def->z) + ("cstat", c.cstat, def->cstat) + ("picnum", c.picnum, def->picnum) + ("shade", c.shade, def->shade) + ("pal", c.pal, def->pal) + ("clipdist", c.clipdist, def->clipdist) + ("blend", c.blend, def->blend) + ("xrepeat", c.xrepeat, def->xrepeat) + ("yrepeat", c.yrepeat, def->yrepeat) + ("xoffset", c.xoffset, def->xoffset) + ("yoffset", c.yoffset, def->yoffset) + ("statnum", c.statnum) + ("sectnum", c.sectnum) + ("ang", c.ang, def->ang) + ("owner", c.owner, def->owner) + ("xvel", c.xvel, def->xvel) + ("yvel", c.yvel, def->yvel) + ("zvel", c.zvel, def->zvel) + ("lotag", c.lotag, def->lotag) + ("hitag", c.hitag, def->hitag) + ("extra", c.extra, def->extra) + ("detail", c.detail, def->detail) + .EndObject(); + } + return arc; +} + +FSerializer& Serialize(FSerializer& arc, const char* key, spriteext_t& c, spriteext_t* def) +{ + if (arc.isWriting() && c.mdanimtims) + { + c.mdanimtims -= mdtims; + if (c.mdanimtims == 0) c.mdanimtims++; + } + + def = &zspx; // always delta against 0 + if (arc.BeginObject(key)) + { + arc("mdanimtims", c.mdanimtims, def->mdanimtims) + ("mdanimcur", c.mdanimcur, def->mdanimcur) + ("angoff", c.angoff, def->angoff) + ("pitch", c.pitch, def->pitch) + ("roll", c.roll, def->roll) + ("pivot_offset", c.pivot_offset, def->pivot_offset) + ("position_offset", c.position_offset, def->position_offset) + ("flags", c.flags, def->flags) + ("alpha", c.alpha, def->alpha) + .EndObject(); + } + + if (c.mdanimtims) c.mdanimtims += mdtims; + return arc; +} FSerializer &Serialize(FSerializer &arc, const char *key, sectortype &c, sectortype *def) { @@ -529,109 +568,88 @@ FSerializer &Serialize(FSerializer &arc, const char *key, walltype &c, walltype return arc; } + void SerializeMap(FSerializer& arc) { + // create a map of all used sprites so that we can use that elsewhere to only save what's needed. + activeSprites.Zero(); + if (arc.isWriting()) + { + for (int i=0; iWrite(sprite, sizeof(spritetype) * MAXSPRITES); - WriteMagic(fw); - fw->Write(headspritesect, sizeof(headspritesect)); - fw->Write(prevspritesect, sizeof(prevspritesect)); - fw->Write(nextspritesect, sizeof(nextspritesect)); - fw->Write(headspritestat, sizeof(headspritestat)); - fw->Write(prevspritestat, sizeof(prevspritestat)); - fw->Write(nextspritestat, sizeof(nextspritestat)); - WriteMagic(fw); - for (int i = 0; i < MAXTILES; i++) - { - fw->Write(&picanm[i], sizeof(picanm[i])); - } - WriteMagic(fw); - - - fw->Write(&tailspritefree, sizeof(tailspritefree)); - fw->Write(&myconnectindex, sizeof(myconnectindex)); - fw->Write(&connecthead, sizeof(connecthead)); - fw->Write(connectpoint2, sizeof(connectpoint2)); - fw->Write(&randomseed, sizeof(randomseed)); - fw->Write(&numshades, sizeof(numshades)); - fw->Write(&showinvisibility, sizeof(showinvisibility)); - WriteMagic(fw); - - fw->Write(&g_visibility, sizeof(g_visibility)); - fw->Write(¶llaxtype, sizeof(parallaxtype)); - fw->Write(¶llaxvisibility, sizeof(parallaxvisibility)); - fw->Write(¶llaxyoffs_override, sizeof(parallaxyoffs_override)); - fw->Write(¶llaxyscale_override, sizeof(parallaxyscale_override)); - fw->Write(&pskybits_override, sizeof(pskybits_override)); - WriteMagic(fw); - - fw->Write(&Numsprites, sizeof(Numsprites)); - sv_prespriteextsave(); - fw->Write(spriteext, sizeof(spriteext_t) * MAXSPRITES); - fw->Write(&randomseed, sizeof(randomseed)); - sv_postspriteext(); - WriteMagic(fw); - -} - -void LoadEngineState() -{ - auto fr = ReadSavegameChunk("engine.bin"); - if (fr.isOpen()) - { - memset(sprite, 0, sizeof(sprite[0]) * MAXSPRITES); - - fr.Read(sprite, sizeof(spritetype) * MAXSPRITES); - CheckMagic(fr); - fr.Read(headspritesect, sizeof(headspritesect)); - fr.Read(prevspritesect, sizeof(prevspritesect)); - fr.Read(nextspritesect, sizeof(nextspritesect)); - fr.Read(headspritestat, sizeof(headspritestat)); - fr.Read(prevspritestat, sizeof(prevspritestat)); - fr.Read(nextspritestat, sizeof(nextspritestat)); - CheckMagic(fr); - for (int i = 0; i < MAXTILES; i++) + if (arc.BeginArray("picanm")) // write this in the most compact form available. { - fr.Read(&picanm[i], sizeof(picanm[i])); + for (int i = 0; i < MAXTILES; i++) + { + arc(nullptr, picanm[i].sf) + (nullptr, picanm[i].extra); + } + arc.EndArray(); } - CheckMagic(fr); - fr.Read(&tailspritefree, sizeof(tailspritefree)); - fr.Read(&myconnectindex, sizeof(myconnectindex)); - fr.Read(&connecthead, sizeof(connecthead)); - fr.Read(connectpoint2, sizeof(connectpoint2)); - fr.Read(&randomseed, sizeof(randomseed)); - fr.Read(&numshades, sizeof(numshades)); - fr.Read(&showinvisibility, sizeof(showinvisibility)); - CheckMagic(fr); + arc.EndObject(); + } - fr.Read(&g_visibility, sizeof(g_visibility)); - fr.Read(¶llaxtype, sizeof(parallaxtype)); - fr.Read(¶llaxvisibility, sizeof(parallaxvisibility)); - fr.Read(¶llaxyoffs_override, sizeof(parallaxyoffs_override)); - fr.Read(¶llaxyscale_override, sizeof(parallaxyscale_override)); - fr.Read(&pskybits_override, sizeof(pskybits_override)); - CheckMagic(fr); - fr.Read(&Numsprites, sizeof(Numsprites)); - fr.Read(spriteext, sizeof(spriteext_t) * MAXSPRITES); - fr.Read(&randomseed, sizeof(randomseed)); - sv_postspriteext(); - CheckMagic(fr); - - fr.Close(); + // Undo the simplification. + for (int i = 0; i < MAXSPRITES; i++) + { + if (nextspritestat[i] == -2) nextspritestat[i] = i + 1; + if (nextspritesect[i] == -2) nextspritesect[i] = i + 1; + if (prevspritestat[i] == -2) prevspritestat[i] = i - 1; + if (prevspritesect[i] == -2) prevspritesect[i] = i - 1; } } diff --git a/source/core/savegamehelp.h b/source/core/savegamehelp.h index ee086fc74..ceb25a28f 100644 --- a/source/core/savegamehelp.h +++ b/source/core/savegamehelp.h @@ -20,8 +20,6 @@ int G_ValidateSavegame(FileReader &fr, FString *savetitle, bool formenu); void G_LoadGame(const char* filename); void G_SaveGame(const char* fn, const char* desc, bool ok4q, bool forceq); -void SaveEngineState(); -void LoadEngineState(); void M_Autosave(); #define SAVEGAME_EXT ".dsave" diff --git a/source/sw/src/sprite.cpp b/source/sw/src/sprite.cpp index 1f7795f64..688ece610 100644 --- a/source/sw/src/sprite.cpp +++ b/source/sw/src/sprite.cpp @@ -4632,7 +4632,7 @@ NewStateGroup(short SpriteNum, STATEp StateGroup[]) // Kind of a goofy check, but it should catch alot of invalid states! // BTW, 6144 is the max tile number allowed in editart. - if (u->State && (u->State->Pic < 0 || u->State->Pic > 6144)) // JBF: verify this! + if (u->State && (u->State->Pic < 0 || u->State->Pic > MAXTILES)) // JBF: verify this! return 0; u->Rot = StateGroup;