ObjectManager uses a new T::restoreObject(SaveGame*) function to restore saved objects.

This function replaces newObject() and allows more flexibility.
This commit is contained in:
Giulio Camuffo 2011-03-21 06:58:36 +08:00 committed by Paweł Kołodziejski
parent 59dcece9ae
commit e89ca555ef
10 changed files with 116 additions and 240 deletions

View File

@ -67,12 +67,14 @@ public:
state->writeByte(_vals[2]);
}
bool restoreState(SaveGame *state) {
_vals[0] = state->readByte();
_vals[1] = state->readByte();
_vals[2] = state->readByte();
static ObjectPtr<Object> restoreObject(SaveGame *state) {
Color *c = new Color();
ObjectPtr<Object> ptr(c);
c->_vals[0] = state->readByte();
c->_vals[1] = state->readByte();
c->_vals[2] = state->readByte();
return true;
return ptr;
}
};

View File

@ -36,180 +36,75 @@ using namespace std;
namespace Grim {
Font::Font(const char *filename, const char *data, int len) : Object() {
load(filename, data, len);
_fname = filename;
_filename = filename;
_numChars = READ_LE_UINT32(data);
_dataSize = READ_LE_UINT32(data + 4);
_height = READ_LE_UINT32(data + 8);
_baseOffsetY = READ_LE_UINT32(data + 12);
_firstChar = READ_LE_UINT32(data + 24);
_lastChar = READ_LE_UINT32(data + 28);
data += 32;
// Read character indexes - are the key/value reversed?
_charIndex = new uint16[_numChars];
if (!_charIndex)
error("Could not load font %s. Out of memory", filename);
for (uint i = 0; i < _numChars; ++i) {
_charIndex[i] = READ_LE_UINT16(data + 2 * i);
}
data += _numChars * 2;
// Read character headers
_charHeaders = new CharHeader[_numChars];
if (!_charHeaders)
error("Could not load font %s. Out of memory", filename);
for (uint i = 0; i < _numChars; ++i) {
_charHeaders[i].offset = READ_LE_UINT32(data);
_charHeaders[i].width = *(int8 *)(data + 4);
_charHeaders[i].startingCol = *(int8 *)(data + 5);
_charHeaders[i].startingLine = *(int8 *)(data + 6);
_charHeaders[i].dataWidth = READ_LE_UINT32(data + 8);
_charHeaders[i].dataHeight = READ_LE_UINT32(data + 12);
data += 16;
}
// Read font data
_fontData = new byte[_dataSize];
if (!_fontData)
error("Could not load font %s. Out of memory", filename);
memcpy(_fontData, data, _dataSize);
}
Font::Font() :
Object() {
_charIndex = NULL;
}
Font::~Font() {
if (_charIndex) {
delete[] _charIndex;
delete[] _charHeaders;
delete[] _fontData;
if (_charIndex) {
delete[] _charIndex;
delete[] _charHeaders;
delete[] _fontData;
g_resourceloader->uncacheFont(this);
}
}
void Font::load(const char *filename, const char *data, int len) {
_fname = filename;
_filename = filename;
_numChars = READ_LE_UINT32(data);
_dataSize = READ_LE_UINT32(data + 4);
_height = READ_LE_UINT32(data + 8);
_baseOffsetY = READ_LE_UINT32(data + 12);
_firstChar = READ_LE_UINT32(data + 24);
_lastChar = READ_LE_UINT32(data + 28);
data += 32;
// Read character indexes - are the key/value reversed?
_charIndex = new uint16[_numChars];
if (!_charIndex)
error("Could not load font %s. Out of memory", filename);
for (uint i = 0; i < _numChars; ++i) {
_charIndex[i] = READ_LE_UINT16(data + 2 * i);
}
data += _numChars * 2;
// Read character headers
_charHeaders = new CharHeader[_numChars];
if (!_charHeaders)
error("Could not load font %s. Out of memory", filename);
for (uint i = 0; i < _numChars; ++i) {
_charHeaders[i].offset = READ_LE_UINT32(data);
_charHeaders[i].width = *(int8 *)(data + 4);
_charHeaders[i].startingCol = *(int8 *)(data + 5);
_charHeaders[i].startingLine = *(int8 *)(data + 6);
_charHeaders[i].dataWidth = READ_LE_UINT32(data + 8);
_charHeaders[i].dataHeight = READ_LE_UINT32(data + 12);
data += 16;
}
// Read font data
_fontData = new byte[_dataSize];
if (!_fontData)
error("Could not load font %s. Out of memory", filename);
memcpy(_fontData, data, _dataSize);
}
}
void Font::saveState(SaveGame *savedState) const {
int32 size;
const char *str;
str = _fname.c_str();
size = strlen(str);
savedState->writeLESint32(size);
savedState->write(str, size);
// savedState->writeLESint32(_fname.size());
// savedState->write(_fname.c_str(), _fname.size());
// savedState->writeLESint32(_filename.size());
// savedState->write(_filename.c_str(), _filename.size());
//
// //_fontData
// savedState->writeLEUint32(_dataSize);
// PointerId ptr = makeIdFromPointer(_fontData);
// // cout<<ptr.low<<endl;
// savedState->writeLEUint32(ptr.low);
// savedState->writeLEUint32(ptr.hi);
// for (uint32 i = 0; i < _dataSize; ++i) {
// savedState->writeByte(_fontData[i]);
// }
//
// //_charHeaders
// savedState->writeLEUint32(_numChars);
// ptr = makeIdFromPointer(_charHeaders);
// savedState->writeLEUint32(ptr.low);
// savedState->writeLEUint32(ptr.hi);
// // cout<<_numChars<<endl;
// for (uint32 i = 0; i < _numChars; ++i) {
// savedState->writeLESint32(_charHeaders[i].offset);
// savedState->writeLESint32(_charHeaders[i].width);
// savedState->writeLESint32(_charHeaders[i].startingCol);
// savedState->writeLESint32(_charHeaders[i].startingLine);
// savedState->writeLESint32(_charHeaders[i].dataWidth);
// savedState->writeLESint32(_charHeaders[i].dataHeight);
// }
//
// //_charIndex
// ptr = makeIdFromPointer(_charIndex);
// savedState->writeLEUint32(ptr.low);
// savedState->writeLEUint32(ptr.hi);
// for (uint32 i = 0; i < _numChars; ++i) {
// savedState->writeLEUint32(_charIndex[i]);
// }
//
// savedState->writeLEUint32(_firstChar);
// savedState->writeLEUint32(_lastChar);
// savedState->writeLEUint32(_height);
// savedState->writeLEUint32(_baseOffsetY);
savedState->writeCharString(_fname.c_str());
}
bool Font::restoreState(SaveGame *savedState) {
int32 size;
char *str = 0;
ObjectPtr<Object> Font::restoreObject(SaveGame *state) {
const char *fname = state->readCharString();
FontPtr font = g_resourceloader->getFont(fname);
delete[] fname;
ObjectPtr<Object> ptr = font.object();
// load actor name
size = savedState->readLESint32();
str = new char[size + 1];
savedState->read(str, size);
str[size] = '\0';
Block *b = g_resourceloader->getBlock(str);
if (b) {
load(str, b->data(), b->len());
}
delete[] str;
return true;
// int32 size = savedState->readLESint32();
// char *str = new char[size];
// savedState->read(str, size);
// _fname.load(str, size);
// delete str;
// size = savedState->readLESint32();
// str = new char[size];
// savedState->read(str, size);
// _filename.load(str, size);
// delete str;
//
// _dataSize = savedState->readLEUint32();
// PointerId ptr;
// ptr.low = savedState->readLEUint32();
// ptr.hi = savedState->readLEUint32();
// _fontData = static_cast<byte *>(makePointerFromId(ptr));
// for (uint32 i = 0; i < _dataSize; ++i) {
// _fontData[i] = savedState->readByte();
// }
//
// _numChars = savedState->readLEUint32();
// ptr.low = savedState->readLEUint32();
// ptr.hi = savedState->readLEUint32();
// _charHeaders = static_cast<CharHeader *>(makePointerFromId(ptr));
// for (uint32 i = 0; i < _numChars; ++i) {
// _charHeaders[i].offset = savedState->readLESint32();
// _charHeaders[i].width = savedState->readLESint32();
// _charHeaders[i].startingCol = savedState->readLESint32();
// _charHeaders[i].startingLine = savedState->readLESint32();
// _charHeaders[i].dataWidth = savedState->readLESint32();
// _charHeaders[i].dataHeight = savedState->readLESint32();
// }
//
// //_charIndex
// ptr.low = savedState->readLEUint32();
// ptr.hi = savedState->readLEUint32();
// _charIndex = static_cast<uint16 *>(makePointerFromId(ptr));
// for (uint32 i = 0; i < _numChars; ++i) {
// _charIndex[i] = savedState->readLEUint32();
// }
//
// _firstChar = savedState->readLEUint32();
// _lastChar = savedState->readLEUint32();
// _height = savedState->readLEUint32();
// _baseOffsetY = savedState->readLEUint32();
return ptr;
}
uint16 Font::getCharIndex(unsigned char c) {

View File

@ -37,11 +37,9 @@ class Font : public Object {
GRIM_OBJECT(Font)
public:
Font(const char *filename, const char *data, int len);
Font() : Object() { _charIndex = 0; }
Font();
~Font();
void load(const char *filename, const char *data, int len);
Common::String getFilename() { return _filename; }
int32 getHeight() { return _height; }
int32 getBaseOffsetY() { return _baseOffsetY; }
@ -53,7 +51,7 @@ public:
const byte *getCharData(unsigned char c) { return _fontData + (_charHeaders[getCharIndex(c)].offset); }
void saveState(SaveGame *savedState) const;
bool restoreState(SaveGame *savedState);
static ObjectPtr<Object> restoreObject(SaveGame *savedState);
static const uint8 emerFont[][13];
private:

View File

@ -61,10 +61,10 @@ namespace Grim {
static const bool color = ObjectManager::registerType<Color>();
static const bool luafile = ObjectManager::registerType<LuaFile>();
static const bool bitmap = ObjectManager::registerType<Bitmap>();
static const bool costume = ObjectManager::registerType<Costume>();
// static const bool bitmap = ObjectManager::registerType<Bitmap>();
// static const bool costume = ObjectManager::registerType<Costume>();
static const bool font = ObjectManager::registerType<Font>();
static const bool material = ObjectManager::registerType<Material>();
// static const bool material = ObjectManager::registerType<Material>();
static bool g_lua_initialized = false;

View File

@ -120,24 +120,26 @@ void LuaFile::saveState(SaveGame *state) const {
state->writeLESint32(_stderr);
}
bool LuaFile::restoreState(SaveGame *state) {
_name = state->readString();;
_filename = state->readString();
ObjectPtr<Object> LuaFile::restoreObject(SaveGame *state) {
LuaFile *l = new LuaFile();
l->_name = state->readString();
l->_filename = state->readString();
if (state->readLESint32()) {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
_in = saveFileMan->openForLoading(_filename.c_str());
l->_in = saveFileMan->openForLoading(l->_filename.c_str());
}
if (state->readLESint32()) {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
_out = saveFileMan->openForSaving(_filename.c_str());
l->_out = saveFileMan->openForSaving(l->_filename.c_str());
}
_stdin = state->readLESint32();
_stdout = state->readLESint32();
_stderr = state->readLESint32();
l->_stdin = state->readLESint32();
l->_stdout = state->readLESint32();
l->_stderr = state->readLESint32();
return true;
return ObjectPtr<Object>(l);
}
static int32 gettag(int32 i) {

View File

@ -286,7 +286,10 @@ void lua_Restore(RestoreStream restoreStream, RestoreSint32 restoreSint32, Resto
int id = restoreUint32();
pointer = g_grim->objectState(id);
} else {
pointer = ObjectManager::restoreObject(g_grim->_savedState);
ObjectPtr<Object> p = ObjectManager::restoreObject(g_grim->_savedState);
Object *o = p.object();
o->reference();
pointer = o;
}
if (!pointer) {
pointer = makePointerFromId(ptr);

View File

@ -56,7 +56,7 @@ public:
~LuaFile();
void saveState(SaveGame *state) const;
bool restoreState(SaveGame *state);
static ObjectPtr<Object> restoreObject(SaveGame *state);
void close();
bool isOpen() const;

View File

@ -2738,7 +2738,7 @@ static void GetImage() {
const char *bitmapName = lua_getstring(nameObj);
BitmapPtr ptr = g_resourceloader->getBitmap(bitmapName).object();
Bitmap *image = ptr.object();
image->ref();
image->reference();
lua_pushusertag(image, MKID_BE('VBUF'));
}
@ -2747,7 +2747,7 @@ static void FreeImage() {
if (!lua_isuserdata(param) || lua_tag(param) != MKID_BE('VBUF'))
return;
Bitmap *bitmap = static_cast<Bitmap *>(lua_getuserdata(param));
bitmap->deref();
bitmap->dereference();
killBitmapPrimitives(bitmap);
}
@ -3648,7 +3648,7 @@ static void LockFont() {
const char *fontName = lua_getstring(param1);
FontPtr ptr = g_resourceloader->getFont(fontName);
Font *result = ptr.object();
result->ref();
result->reference();
if (result) {
lua_pushusertag(result, MKID_BE('FONT'));
return;

View File

@ -4,9 +4,11 @@
#include "engines/grim/lua/lobject.h"
#include "engines/grim/font.h"
namespace Grim {
typedef Object *(*CreatorFunc)();
typedef ObjectPtr<Object> (*CreatorFunc)(SaveGame *);
Common::HashMap<Common::String, CreatorFunc> ObjectManager::_creators;
Object::Object() : _refCount(0) {
@ -22,18 +24,6 @@ Object::~Object() {
}
}
void Object::save(SaveGame *state) const {
state->writeLEUint32(_refCount);
saveState(state);
}
bool Object::restore(SaveGame *state) {
_refCount = state->readLEUint32();
return restoreState(state);
}
void Object::saveState(SaveGame */*state*/) const {
}
@ -42,11 +32,11 @@ bool Object::restoreState(SaveGame */*state*/) {
return false;
}
void Object::ref() {
void Object::reference() {
++_refCount;
}
void Object::deref() {
void Object::dereference() {
if (_refCount > 0) {
--_refCount;
}
@ -65,32 +55,23 @@ void ObjectManager::saveObject(SaveGame *state, Object *object) {
state->writeLEUint32(len);
state->write(str, len);
object->save(state);
object->saveState(state);
}
Object *ObjectManager::restoreObject(SaveGame *state) {
int32 len = state->readLEUint32();
char *str = new char[len + 1];
state->read(str, len);
str[len] = '\0';
ObjectPtr<Object> ObjectManager::restoreObject(SaveGame *state) {
const char *str = state->readCharString();
Object *o = newObject(str);
ObjectPtr<Object> ptr;
Common::String type = str;
delete[] str;
o->restore(state);
return o;
}
Object *ObjectManager::newObject(const char *typeName) {
Common::String type = typeName;
if (_creators.contains(type)) {
CreatorFunc func = _creators.getVal(type);
Object *o = (func)();
return o;
ptr = (func)(state);
} else {
warning("Type name \"%s\" not registered", typeName);
error("Type name \"%s\" not registered", type.c_str());
}
return 0;
return ptr;
}
}

View File

@ -31,8 +31,8 @@
#include "common/hash-str.h"
#include "common/func.h"
#include "common/list.h"
#include <iostream>
using namespace std;
#include "common/debug.h"
namespace Grim {
class SaveGame;
@ -45,16 +45,12 @@ public:
virtual const char *typeName() const { return ""; }
void save(SaveGame *state) const;
bool restore(SaveGame *state);
void ref();
void deref();
protected:
virtual void saveState(SaveGame *state) const;
virtual bool restoreState(SaveGame *state);
void reference();
void dereference();
private:
int _refCount;
Common::List<Pointer *> _pointers;
@ -87,7 +83,7 @@ public:
ObjectPtr(T *obj) :
_obj(obj) {
if (obj) {
_obj->ref();
_obj->reference();
addPointer(obj);
}
}
@ -98,7 +94,7 @@ public:
~ObjectPtr() {
if (_obj) {
rmPointer(_obj);
_obj->deref();
_obj->dereference();
}
}
@ -106,14 +102,14 @@ public:
if (obj != _obj) {
if (_obj) {
rmPointer(_obj);
_obj->deref();
_obj->dereference();
_obj = NULL;
}
if (obj) {
_obj = obj;
_obj->ref();
_obj->reference();
addPointer(obj);
}
}
@ -124,14 +120,14 @@ public:
if (_obj != ptr._obj) {
if (_obj) {
rmPointer(_obj);
_obj->deref();
_obj->dereference();
_obj = NULL;
}
if (ptr._obj) {
_obj = ptr._obj;
_obj->ref();
_obj->reference();
addPointer(_obj);
}
}
@ -176,8 +172,7 @@ private:
class ObjectManager {
public:
static void saveObject(SaveGame *state, Object *object);
static Object *restoreObject(SaveGame *state);
static Object *newObject(const char *typeName);
static ObjectPtr<Object> restoreObject(SaveGame *state);
template<class T> static bool registerType() {
T obj;
@ -186,7 +181,7 @@ public:
warning("Type name %s already registered", type.c_str());
return false;
}
_creators.setVal(type, &createObj<T>);
_creators.setVal(type, T::restoreObject);
return true;
}
@ -196,7 +191,7 @@ private:
return new T();
}
typedef Object *(*CreatorFunc)();
typedef ObjectPtr<Object> (*CreatorFunc)(SaveGame *);
static Common::HashMap<Common::String, CreatorFunc> _creators;
};