Skip to content

Commit

Permalink
Merge pull request #557 from RichieSams/replace_pluto
Browse files Browse the repository at this point in the history
SWORD25: Replace 'Pluto' lua persistance code with re-written, platform-agnostic code
  • Loading branch information
sev- committed Jan 4, 2015
2 parents 7da4823 + e4f74b6 commit 2587852
Show file tree
Hide file tree
Showing 22 changed files with 2,365 additions and 2,805 deletions.
7 changes: 7 additions & 0 deletions engines/sword25/kernel/outputpersistenceblock.cpp
Expand Up @@ -41,6 +41,13 @@ OutputPersistenceBlock::OutputPersistenceBlock() {
_data.reserve(INITIAL_BUFFER_SIZE);
}

void OutputPersistenceBlock::write(const void *data, uint32 size) {
writeMarker(BLOCK_MARKER);

write(size);
rawWrite(data, size);
}

void OutputPersistenceBlock::write(int32 value) {
writeMarker(SINT_MARKER);
value = TO_LE_32(value);
Expand Down
1 change: 1 addition & 0 deletions engines/sword25/kernel/outputpersistenceblock.h
Expand Up @@ -41,6 +41,7 @@ class OutputPersistenceBlock : public PersistenceBlock {
public:
OutputPersistenceBlock();

void write(const void *data, uint32 size);
void write(int32 value);
void write(uint32 value);
void write(float value);
Expand Down
7 changes: 4 additions & 3 deletions engines/sword25/module.mk
Expand Up @@ -82,9 +82,10 @@ MODULE_OBJS := \
util/lua/lvm.o \
util/lua/lzio.o \
util/lua/scummvm_file.o \
util/pluto/pdep.o \
util/pluto/pluto.o \
util/pluto/plzio.o
util/double_serialization.o \
util/lua_persistence_util.o \
util/lua_persist.o \
util/lua_unpersist.o

# This module can be built as a plugin
ifeq ($(ENABLE_SWORD25), DYNAMIC_PLUGIN)
Expand Down
61 changes: 12 additions & 49 deletions engines/sword25/script/luascript.cpp
Expand Up @@ -29,7 +29,7 @@
*
*/

#include "common/array.h"
#include "common/memstream.h"
#include "common/debug-channels.h"

#include "sword25/sword25.h"
Expand All @@ -43,7 +43,7 @@
#include "sword25/util/lua/lua.h"
#include "sword25/util/lua/lualib.h"
#include "sword25/util/lua/lauxlib.h"
#include "sword25/util/pluto/pluto.h"
#include "sword25/util/lua_persistence.h"

namespace Sword25 {

Expand Down Expand Up @@ -112,10 +112,6 @@ bool LuaScriptEngine::init() {
// Place the error handler function in the Lua registry, and remember the index
_pcallErrorhandlerRegistryIndex = luaL_ref(_state, LUA_REGISTRYINDEX);

// Initialize the Pluto-Persistence library
luaopen_pluto(_state);
lua_pop(_state, 1);

// Initialize debugging callback
if (DebugMan.isDebugChannelEnabled(kDebugScript)) {
int mask = 0;
Expand Down Expand Up @@ -383,19 +379,8 @@ bool pushPermanentsTable(lua_State *L, PERMANENT_TABLE_TYPE tableType) {

return true;
}
}

namespace {
int chunkwriter(lua_State *L, const void *p, size_t sz, void *ud) {
Common::Array<byte> & chunkData = *reinterpret_cast<Common::Array<byte> * >(ud);
const byte *buffer = reinterpret_cast<const byte *>(p);

while (sz--)
chunkData.push_back(*buffer++);

return 1;
}
}
} // End of anonymous namespace

bool LuaScriptEngine::persist(OutputPersistenceBlock &writer) {
// Empty the Lua stack. pluto_persist() xepects that the stack is empty except for its parameters
Expand All @@ -409,12 +394,12 @@ bool LuaScriptEngine::persist(OutputPersistenceBlock &writer) {
pushPermanentsTable(_state, PTT_PERSIST);
lua_getglobal(_state, "_G");

// Lua persists and stores the data in a Common::Array
Common::Array<byte> chunkData;
pluto_persist(_state, chunkwriter, &chunkData);
// Lua persists and stores the data in a WriteStream
Common::MemoryWriteStreamDynamic writeStream;
Lua::persistLua(_state, &writeStream);

// Persistenzdaten in den Writer schreiben.
writer.writeByteArray(chunkData);
writer.write(writeStream.getData(), writeStream.size());

// Die beiden Tabellen vom Stack nehmen.
lua_pop(_state, 2);
Expand All @@ -424,24 +409,6 @@ bool LuaScriptEngine::persist(OutputPersistenceBlock &writer) {

namespace {

struct ChunkreaderData {
void *BufferPtr;
size_t Size;
bool BufferReturned;
};

const char *chunkreader(lua_State *L, void *ud, size_t *sz) {
ChunkreaderData &cd = *reinterpret_cast<ChunkreaderData *>(ud);

if (!cd.BufferReturned) {
cd.BufferReturned = true;
*sz = cd.Size;
return reinterpret_cast<const char *>(cd.BufferPtr);
} else {
return 0;
}
}

void clearGlobalTable(lua_State *L, const char **exceptions) {
// Iterate over all elements of the global table
lua_pushvalue(L, LUA_GLOBALSINDEX);
Expand Down Expand Up @@ -479,7 +446,8 @@ void clearGlobalTable(lua_State *L, const char **exceptions) {
// Perform garbage collection, so that all removed elements are deleted
lua_gc(L, LUA_GCCOLLECT, 0);
}
}

} // End of anonymous namespace

bool LuaScriptEngine::unpersist(InputPersistenceBlock &reader) {
// Empty the Lua stack. pluto_persist() xepects that the stack is empty except for its parameters
Expand Down Expand Up @@ -512,22 +480,17 @@ bool LuaScriptEngine::unpersist(InputPersistenceBlock &reader) {
// Persisted Lua data
Common::Array<byte> chunkData;
reader.readByteArray(chunkData);
Common::MemoryReadStream readStream(&chunkData[0], chunkData.size(), DisposeAfterUse::NO);

// Chunk-Reader initialisation. It is used with pluto_unpersist to restore read data
ChunkreaderData cd;
cd.BufferPtr = &chunkData[0];
cd.Size = chunkData.size();
cd.BufferReturned = false;

pluto_unpersist(_state, chunkreader, &cd);
Lua::unpersistLua(_state, &readStream);

// Permanents-Table is removed from stack
lua_remove(_state, -2);

// The read elements in the global table about
lua_pushnil(_state);
while (lua_next(_state, -2) != 0) {
// The referenec to the global table (_G) must not be overwritten, or ticks from Lua total
// The reference to the global table (_G) must not be overwritten, or ticks from Lua total
bool isGlobalReference = lua_isstring(_state, -2) && strcmp(lua_tostring(_state, -2), "_G") == 0;
if (!isGlobalReference) {
lua_pushvalue(_state, -2);
Expand Down
138 changes: 138 additions & 0 deletions engines/sword25/util/double_serialization.cpp
@@ -0,0 +1,138 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/

#include "sword25/util/double_serialization.h"

#include "common/scummsys.h"


namespace Util {

SerializedDouble encodeDouble(double value) {
// Split the value into its significand and exponent
int exponent;
double significand = frexp(value, &exponent);

// Shift the the first part of the significand into the integer range
double shiftedsignificandPart = ldexp(abs(significand), 32);
uint32 significandOne = uint32(floor(shiftedsignificandPart));

// Shift the remainder of the significand into the integer range
shiftedsignificandPart -= significandOne;
uint32 significandTwo = (uint32)(ldexp(shiftedsignificandPart, 31));

SerializedDouble returnValue;
returnValue.significandOne = significandOne; // SignificandOne
returnValue.signAndSignificandTwo = ((uint32)(value < 0 ? 1 : 0) << 31) | // Sign
significandTwo; // SignificandTwo
returnValue.exponent = (int16)exponent;
return returnValue;
}

double decodeDouble(SerializedDouble value) {
// Expand the exponent and the parts of the significand
int exponent = (int)value.exponent;
double expandedsignificandOne = (double)value.significandOne;
double expandedsignificandTwo = (double)(value.signAndSignificandTwo & 0x7FFFFFFF);

// Deflate the significand
double shiftedsignificand = ldexp(expandedsignificandTwo, -21);
double significand = ldexp(expandedsignificandOne + shiftedsignificand, -32);

// Re-calculate the actual double
double returnValue = ldexp(significand, exponent);

// Check the sign bit and return
return ((value.signAndSignificandTwo & 0x80000000) == 0x80000000) ? -returnValue : returnValue;
}

uint64 encodeDouble_64(double value) {
// Split the value into its significand and exponent
int exponent;
double significand = frexp(value, &exponent);

// Shift the significand into the integer range
double shiftedsignificand = ldexp(abs(significand), 53);

// Combine everything using the IEEE standard
uint64 uintsignificand = (uint64)shiftedsignificand;
return ((uint64)(value < 0 ? 1 : 0) << 63) | // Sign
((uint64)(exponent + 1023) << 52) | // Exponent stored as an offset to 1023
(uintsignificand & 0x000FFFFFFFFFFFFF); // significand with MSB inferred
}

double decodeDouble_64(uint64 value) {
// Expand the exponent and significand
int exponent = (int)((value >> 52) & 0x7FF) - 1023;
double expandedsignificand = (double)(0x10000000000000 /* Inferred MSB */ | (value & 0x000FFFFFFFFFFFFF));

// Deflate the significand
int temp;
double significand = frexp(expandedsignificand, &temp);

// Re-calculate the actual double
double returnValue = ldexp(significand, exponent);

// Check the sign bit and return
return ((value & 0x8000000000000000) == 0x8000000000000000) ? -returnValue : returnValue;
}

CompactSerializedDouble encodeDouble_Compact(double value) {
// Split the value into its significand and exponent
int exponent;
double significand = frexp(value, &exponent);

// Shift the the first part of the significand into the integer range
double shiftedsignificandPart = ldexp(abs(significand), 32);
uint32 significandOne = uint32(floor(shiftedsignificandPart));

// Shift the remainder of the significand into the integer range
shiftedsignificandPart -= significandOne;
uint32 significandTwo = (uint32)(ldexp(shiftedsignificandPart, 21));

CompactSerializedDouble returnValue;
returnValue.signAndSignificandOne = ((uint32)(value < 0 ? 1 : 0) << 31) | // Sign
(significandOne & 0x7FFFFFFF); // significandOne with MSB inferred
// Exponent stored as an offset to 1023
returnValue.exponentAndSignificandTwo = ((uint32)(exponent + 1023) << 21) | significandTwo;

return returnValue;
}

double decodeDouble_Compact(CompactSerializedDouble value) {
// Expand the exponent and the parts of the significand
int exponent = (int)(value.exponentAndSignificandTwo >> 21) - 1023;
double expandedsignificandOne = (double)(0x80000000 /* Inferred MSB */ | (value.signAndSignificandOne & 0x7FFFFFFF));
double expandedsignificandTwo = (double)(value.exponentAndSignificandTwo & 0x1FFFFF);

// Deflate the significand
double shiftedsignificand = ldexp(expandedsignificandTwo, -21);
double significand = ldexp(expandedsignificandOne + shiftedsignificand, -32);

// Re-calculate the actual double
double returnValue = ldexp(significand, exponent);

// Check the sign bit and return
return ((value.signAndSignificandOne & 0x80000000) == 0x80000000) ? -returnValue : returnValue;
}

} // End of namespace Sword25
95 changes: 95 additions & 0 deletions engines/sword25/util/double_serialization.h
@@ -0,0 +1,95 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/

#ifndef DOUBLE_SERIALIZATION_H
#define DOUBLE_SERIALIZATION_H

#include "common/types.h"


namespace Util {

struct SerializedDouble {
uint32 significandOne;
uint32 signAndSignificandTwo;
int16 exponent;
};

struct CompactSerializedDouble {
uint32 signAndSignificandOne;
uint32 exponentAndSignificandTwo;
};

/**
* Encodes a double as two uint32 and a one int16
*
* Supports denormalized numbers. Does NOT support NaN, or Inf
*
* @param value The value to encode
* @return The encoded value
*/
SerializedDouble encodeDouble(double value);
/**
* Decodes a previously encoded double
*
* @param value The value to decode
* @return The decoded value
*/
double decodeDouble(SerializedDouble value);

/**
* Encodes a double as a uint64
*
* Does NOT support denormalized numbers. Does NOT support NaN, or Inf
*
* @param value The value to encode
* @return The encoded value
*/
uint64 encodeDouble_64(double value);
/**
* Decodes a previously encoded double
*
* @param value The value to decode
* @return The decoded value
*/
double decodeDouble_64(uint64 value);

/**
* Encodes a double as two uint32
*
* Does NOT support denormalized numbers. Does NOT support NaN, or Inf
*
* @param value The value to encode
* @return The encoded value
*/
CompactSerializedDouble encodeDouble_Compact(double value);
/**
* Decodes a previously encoded double
*
* @param value The value to decode
* @return The decoded value
*/
double decodeDouble_Compact(CompactSerializedDouble value);

} // End of namespace Sword25

#endif

0 comments on commit 2587852

Please sign in to comment.