- implemented the automap serializer.

Also optimized the base64 encoder to avoid creating endless memory copies, thanks to using std::string which is a really poor container for this kind of stuff when workig with larger blocks of data.
This commit is contained in:
Christoph Oelckers 2020-09-06 13:39:57 +02:00
parent 809f8b5d4b
commit e8452a79e8
8 changed files with 115 additions and 46 deletions

View file

@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "automap.h"
#include "compat.h" #include "compat.h"
#include "build.h" #include "build.h"
#include "mmulti.h" #include "mmulti.h"
@ -704,7 +705,7 @@ void playerStart(int nPlayer, int bNewLevel)
playerResetPosture(pPlayer); playerResetPosture(pPlayer);
seqSpawn(pDudeInfo->seqStartID, 3, pSprite->extra, -1); seqSpawn(pDudeInfo->seqStartID, 3, pSprite->extra, -1);
if (pPlayer == gMe) if (pPlayer == gMe)
SetBitString(show2dsprite, pSprite->index); show2dsprite.Set(pSprite->index);
int top, bottom; int top, bottom;
GetSpriteExtents(pSprite, &top, &bottom); GetSpriteExtents(pSprite, &top, &bottom);
pSprite->z -= bottom - pSprite->z; pSprite->z -= bottom - pSprite->z;

View file

@ -54,6 +54,7 @@
#include "engineerrors.h" #include "engineerrors.h"
#include "textures.h" #include "textures.h"
#include "texturemanager.h" #include "texturemanager.h"
#include "base64.h"
extern DObject *WP_NOCHANGE; extern DObject *WP_NOCHANGE;
bool save_full = false; // for testing. Should be removed afterward. bool save_full = false; // for testing. Should be removed afterward.
@ -771,6 +772,31 @@ error:
return buff; return buff;
} }
//==========================================================================
//
//
//
//==========================================================================
FSerializer &FSerializer::SerializeMemory(const char *key, void* mem, size_t length)
{
if (isWriting())
{
auto array = base64_encode((const uint8_t*)mem, length);
AddString(key, (const char*)array.Data());
}
else
{
auto cp = GetString(key);
if (key)
{
base64_decode(mem, length, cp);
}
}
return *this;
}
//========================================================================== //==========================================================================
// //
// //

View file

@ -95,6 +95,7 @@ public:
virtual FSerializer &Sprite(const char *key, int32_t &spritenum, int32_t *def); virtual FSerializer &Sprite(const char *key, int32_t &spritenum, int32_t *def);
// This is only needed by the type system. // This is only needed by the type system.
virtual FSerializer& StatePointer(const char* key, void* ptraddr, bool *res); virtual FSerializer& StatePointer(const char* key, void* ptraddr, bool *res);
FSerializer& SerializeMemory(const char* key, void* mem, size_t length);
FSerializer &StringPtr(const char *key, const char *&charptr); // This only retrieves the address but creates no permanent copy of the string unlike the regular char* serializer. FSerializer &StringPtr(const char *key, const char *&charptr); // This only retrieves the address but creates no permanent copy of the string unlike the regular char* serializer.
FSerializer &AddString(const char *key, const char *charptr); FSerializer &AddString(const char *key, const char *charptr);

View file

@ -32,6 +32,7 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au)
#include "c_cvars.h" #include "c_cvars.h"
#include "gstrings.h" #include "gstrings.h"
#include "printf.h" #include "printf.h"
#include "serializer.h"
bool automapping; bool automapping;
@ -40,6 +41,27 @@ FixedBitArray<MAXSECTORS> show2dsector;
FixedBitArray<MAXWALLS> show2dwall; FixedBitArray<MAXWALLS> show2dwall;
FixedBitArray<MAXSPRITES> show2dsprite; FixedBitArray<MAXSPRITES> show2dsprite;
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void SerializeAutomap(FSerializer& arc)
{
if (arc.BeginObject("automap"))
{
arc("automapping", automapping)
("fullmap", gFullMap)
// Only store what's needed. Unfortunately for sprites it is not that easy
.SerializeMemory("mappedsectors", show2dsector.Storage(), (numsectors + 7) / 8)
.SerializeMemory("mappedwalls", show2dwall.Storage(), (numwalls + 7) / 8)
.SerializeMemory("mappedsprites", show2dsprite.Storage(), MAXSPRITES / 8)
.EndObject();
}
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// //

View file

@ -3,13 +3,15 @@
#include "tarray.h" #include "tarray.h"
#include "build.h" #include "build.h"
class FSerializer;
extern bool automapping; extern bool automapping;
extern bool gFullMap; extern bool gFullMap;
extern FixedBitArray<MAXSECTORS> show2dsector; extern FixedBitArray<MAXSECTORS> show2dsector;
extern FixedBitArray<MAXWALLS> show2dwall; extern FixedBitArray<MAXWALLS> show2dwall;
extern FixedBitArray<MAXSPRITES> show2dsprite; extern FixedBitArray<MAXSPRITES> show2dsprite;
void SerializeAutomap(FSerializer& arc);
void ClearAutomap(); void ClearAutomap();
void MarkSectorSeen(int sect); void MarkSectorSeen(int sect);
void DrawOverheadMap(int x, int y, int ang); void DrawOverheadMap(int x, int y, int ang);

View file

@ -51,6 +51,7 @@
#include "raze_music.h" #include "raze_music.h"
#include "raze_sound.h" #include "raze_sound.h"
#include "gamestruct.h" #include "gamestruct.h"
#include "automap.h"
static CompositeSavegameWriter savewriter; static CompositeSavegameWriter savewriter;
static FResourceFile *savereader; static FResourceFile *savereader;
@ -73,6 +74,7 @@ static void SerializeSession(FSerializer& arc)
Mus_Serialize(arc); Mus_Serialize(arc);
quoteMgr.Serialize(arc); quoteMgr.Serialize(arc);
S_SerializeSounds(arc); S_SerializeSounds(arc);
SerializeAutomap(arc);
} }
//============================================================================= //=============================================================================
@ -126,8 +128,8 @@ bool OpenSaveGameForRead(const char *name)
info->Unlock(); info->Unlock();
// Load system-side data from savegames. // Load system-side data from savegames.
SerializeSession(arc);
LoadEngineState(); LoadEngineState();
SerializeSession(arc); // must be AFTER LoadEngineState because it needs info from it.
gi->SerializeGameState(arc); gi->SerializeGameState(arc);
} }
return savereader != nullptr; return savereader != nullptr;

View file

@ -6,9 +6,7 @@
#ifndef BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A #ifndef BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A
#define BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A #define BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A
#include <string> TArray<uint8_t> base64_encode(unsigned char const* bytes_to_encode, size_t in_len);
void base64_decode(void* memory, size_t len, const char* encoded_string);
std::string base64_encode(unsigned char const* , unsigned int len);
std::string base64_decode(std::string const& s);
#endif /* BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A */ #endif /* BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A */

View file

@ -6,6 +6,7 @@
Version: 1.01.00 Version: 1.01.00
Copyright (C) 2004-2017 René Nyffenegger Copyright (C) 2004-2017 René Nyffenegger
Copyright (C) 2020 Christoph Oelckers
This source code is provided 'as-is', without any express or implied This source code is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages warranty. In no event will the author be held liable for any damages
@ -27,22 +28,33 @@
René Nyffenegger rene.nyffenegger@adp-gmbh.ch René Nyffenegger rene.nyffenegger@adp-gmbh.ch
*/ Addapted by Christoph Oelckers to FSerializer's needs where std::string is not a good container.
*/
#include <stdint.h>
#include "base64.h" #include "base64.h"
static const std::string base64_chars = static const char *base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz" "abcdefghijklmnopqrstuvwxyz"
"0123456789+/"; "0123456789+/";
inline int base64toindex(int c)
static inline bool is_base64(unsigned char c) { {
return (isalnum(c) || (c == '+') || (c == '/')); if (c >= 'A' && c <= 'Z') return c - 'A';
if (c >= 'a' && c <= 'z') return c - 'a' + 26;
if (c >= '0' && c <= '9') return c - '0' + 52;
if (c == '+') return 62;
if (c == '/') return 63;
return -1;
} }
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) { static inline bool is_base64(unsigned char c) {
std::string ret; return base64toindex(c) >= 0;
}
TArray<uint8_t> base64_encode(unsigned char const* bytes_to_encode, size_t in_len) {
TArray<uint8_t> reta((in_len+5)/6 + 6);
int i = 0; int i = 0;
int j = 0; int j = 0;
unsigned char char_array_3[3]; unsigned char char_array_3[3];
@ -57,7 +69,7 @@ std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_
char_array_4[3] = char_array_3[2] & 0x3f; char_array_4[3] = char_array_3[2] & 0x3f;
for(i = 0; (i <4) ; i++) for(i = 0; (i <4) ; i++)
ret += base64_chars[char_array_4[i]]; reta.Push(base64_chars[char_array_4[i]]);
i = 0; i = 0;
} }
} }
@ -72,50 +84,55 @@ std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
for (j = 0; (j < i + 1); j++) for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]]; reta.Push(base64_chars[char_array_4[j]]);
while((i++ < 3)) while((i++ < 3))
ret += '='; reta.Push('=');
} }
return ret; return reta;
} }
std::string base64_decode(std::string const& encoded_string) { void base64_decode(void *memory, size_t maxlen, const char *encoded_string) {
size_t in_len = encoded_string.size(); size_t in_len = strlen(encoded_string);
int i = 0; int i = 0;
int j = 0; int j = 0;
int in_ = 0; int in_ = 0;
unsigned char char_array_4[4], char_array_3[3]; unsigned char char_array_4[4], char_array_3[3];
std::string ret; uint8_t* dest = (uint8_t*)memory;
uint8_t* end = dest + maxlen;
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++; char_array_4[i++] = encoded_string[in_]; in_++;
if (i ==4) { if (i == 4) {
for (i = 0; i <4; i++) for (i = 0; i < 4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]) & 0xff; char_array_4[i] = base64toindex(char_array_4[i]) & 0xff;
char_array_3[0] = ( char_array_4[0] << 2 ) + ((char_array_4[1] & 0x30) >> 4); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++) for (i = 0; (i < 3); i++)
ret += char_array_3[i]; *dest++ = char_array_3[i];
i = 0; if (dest >= end) return;
i = 0;
}
} }
}
if (i) { if (i) {
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]) & 0xff; char_array_4[j] = base64toindex(char_array_4[j]) & 0xff;
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; for (j = 0; (j < i - 1); j++)
} {
*dest++ = char_array_3[j];
return ret; if (dest >= end) return;
}
}
while (dest < end) *dest++ = 0;
} }