- 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 <string.h>
#include "automap.h"
#include "compat.h"
#include "build.h"
#include "mmulti.h"
@ -704,7 +705,7 @@ void playerStart(int nPlayer, int bNewLevel)
playerResetPosture(pPlayer);
seqSpawn(pDudeInfo->seqStartID, 3, pSprite->extra, -1);
if (pPlayer == gMe)
SetBitString(show2dsprite, pSprite->index);
show2dsprite.Set(pSprite->index);
int top, bottom;
GetSpriteExtents(pSprite, &top, &bottom);
pSprite->z -= bottom - pSprite->z;

View file

@ -54,6 +54,7 @@
#include "engineerrors.h"
#include "textures.h"
#include "texturemanager.h"
#include "base64.h"
extern DObject *WP_NOCHANGE;
bool save_full = false; // for testing. Should be removed afterward.
@ -771,6 +772,31 @@ error:
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);
// This is only needed by the type system.
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 &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 "gstrings.h"
#include "printf.h"
#include "serializer.h"
bool automapping;
@ -40,6 +41,27 @@ FixedBitArray<MAXSECTORS> show2dsector;
FixedBitArray<MAXWALLS> show2dwall;
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 "build.h"
class FSerializer;
extern bool automapping;
extern bool gFullMap;
extern FixedBitArray<MAXSECTORS> show2dsector;
extern FixedBitArray<MAXWALLS> show2dwall;
extern FixedBitArray<MAXSPRITES> show2dsprite;
void SerializeAutomap(FSerializer& arc);
void ClearAutomap();
void MarkSectorSeen(int sect);
void DrawOverheadMap(int x, int y, int ang);

View file

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

View file

@ -6,9 +6,7 @@
#ifndef BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A
#define BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A
#include <string>
std::string base64_encode(unsigned char const* , unsigned int len);
std::string base64_decode(std::string const& s);
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);
#endif /* BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A */

View file

@ -6,6 +6,7 @@
Version: 1.01.00
Copyright (C) 2004-2017 René Nyffenegger
Copyright (C) 2020 Christoph Oelckers
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
@ -27,22 +28,33 @@
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"
static const std::string base64_chars =
static const char *base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static inline bool is_base64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
inline int base64toindex(int 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) {
std::string ret;
static inline bool is_base64(unsigned char c) {
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 j = 0;
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;
for(i = 0; (i <4) ; i++)
ret += base64_chars[char_array_4[i]];
reta.Push(base64_chars[char_array_4[i]]);
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);
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))
ret += '=';
reta.Push('=');
}
return ret;
return reta;
}
std::string base64_decode(std::string const& encoded_string) {
size_t in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
void base64_decode(void *memory, size_t maxlen, const char *encoded_string) {
size_t in_len = strlen(encoded_string);
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
uint8_t* dest = (uint8_t*)memory;
uint8_t* end = dest + maxlen;
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i ==4) {
for (i = 0; i <4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]) & 0xff;
while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i == 4) {
for (i = 0; i < 4; i++)
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[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[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[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
for (i = 0; (i < 3); i++)
*dest++ = char_array_3[i];
if (dest >= end) return;
i = 0;
}
}
}
if (i) {
for (j = 0; j < i; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]) & 0xff;
if (i) {
for (j = 0; j < i; j++)
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[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
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);
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}
return ret;
for (j = 0; (j < i - 1); j++)
{
*dest++ = char_array_3[j];
if (dest >= end) return;
}
}
while (dest < end) *dest++ = 0;
}