Permalink
Browse files

SUPERNOVA: Implements de-/serialization

WIP. It is currently broken.
  • Loading branch information...
Joefish committed Aug 28, 2017
1 parent 64565aa commit 6092e398db36c329aa18bd6739d5008e14b0c5e9
@@ -27,6 +27,72 @@
namespace Supernova {
bool Room::serialize(Common::WriteStream *out) {
if (out->err())
return false;
out->writeByte(_id);
for (int i = 0; i < kMaxSection; ++i)
out->writeByte(_shown[i]);
int numObjects = 0;
while ((_objectState[numObjects]._id != INVALIDOBJECT) && (numObjects < kMaxObject))
++numObjects;
out->writeByte(numObjects);
for (int i = 0; i < numObjects; ++i) {
out->writeSint16LE(_objectState[i]._name.size() + 1);
out->writeString(_objectState[i]._name.c_str());
out->writeSint16LE(_objectState[i]._description.size() + 1);
out->writeString(_objectState[i]._description.c_str());
out->writeByte(_objectState[i]._roomId);
out->writeByte(_objectState[i]._id);
out->writeSint16LE(_objectState[i]._type);
out->writeByte(_objectState[i]._click);
out->writeByte(_objectState[i]._click2);
out->writeByte(_objectState[i]._section);
out->writeByte(_objectState[i]._exitRoom);
out->writeByte(_objectState[i]._direction);
}
out->writeByte(_seen);
return !out->err();
}
bool Room::deserialize(Common::ReadStream *in) {
if (in->err())
return false;
in->readByte();
for (int i = 0; i < kMaxSection; ++i)
_shown[i] = in->readByte();
int numObjects = in->readByte();
int bufferSize = 0;
char stringBuffer[256];
for (int i = 0; i < numObjects; ++i) {
bufferSize = in->readSint16LE();
in->read(stringBuffer, bufferSize > 256 ? 256 : bufferSize);
_objectState[i]._name = stringBuffer;
bufferSize = in->readSint16LE();
in->read(stringBuffer, bufferSize > 256 ? 256 : bufferSize);
_objectState[i]._description = stringBuffer;
_objectState[i]._roomId = in->readByte();
_objectState[i]._id = static_cast<ObjectID>(in->readByte());
_objectState[i]._type = static_cast<ObjectType>(in->readSint16LE());
_objectState[i]._click = in->readByte();
_objectState[i]._click2 = in->readByte();
_objectState[i]._section = in->readByte();
_objectState[i]._exitRoom = static_cast<RoomID>(in->readByte());
_objectState[i]._direction = in->readByte();
}
_seen = in->readByte();
return !in->err();
}
void Intro::onEntrance() {
}
@@ -70,6 +70,8 @@ class Room {
virtual bool interact(Action verb, Object &obj1, Object &obj2) {
return false;
}
virtual bool serialize(Common::WriteStream *out);
virtual bool deserialize(Common::ReadStream *in);
protected:
int _fileNumber;
@@ -22,11 +22,104 @@
#include "common/system.h"
#include "graphics/palette.h"
#include "gui/message.h"
#include "supernova/supernova.h"
#include "supernova/state.h"
namespace Supernova {
bool GameManager::serialize(Common::WriteStream *out) {
if (out->err())
return false;
// GameState
out->writeSint32LE(_state._time);
out->writeSint32LE(_state._timeSleep);
out->writeSint32LE(_state._timeAlarm);
out->writeSint32LE(_state._eventTime);
out->writeSint32LE(_state._arrivalDaysLeft);
out->writeSint32LE(_state._shipEnergyDaysLeft);
out->writeSint32LE(_state._landingModuleEnergyDaysLeft);
out->writeUint16LE(_state._greatFlag);
out->writeSint16LE(_state._timeRobot);
out->writeSint16LE(_state._money);
out->writeByte(_state._coins);
out->writeByte(_state._shoes);
out->writeByte(_state._destination);
out->writeByte(_state._language);
out->writeByte(_state._corridorSearch);
out->writeByte(_state._alarmOn);
out->writeByte(_state._terminalStripConnected);
out->writeByte(_state._terminalStripWire);
out->writeByte(_state._cableConnected);
out->writeByte(_state._powerOff);
out->writeByte(_state._dream);
// Inventory
out->writeSByte(_inventory.getSize());
out->writeSByte(_inventoryScroll);
for (int i = 0; i < _inventory.getSize(); ++i) {
Object *objectStateBegin = _rooms[_inventory.get(i)->_roomId]->getObject(0);
byte objectIndex = _inventory.get(i) - objectStateBegin;
out->writeByte(_inventory.get(i)->_roomId);
out->writeByte(objectIndex);
}
// Rooms
for (int i = 0; i < kRoomsNum; ++i) {
_rooms[i]->serialize(out);
}
return !out->err();
}
bool GameManager::deserialize(Common::ReadStream *in) {
if (in->err()) {
return false;
}
// GameState
_state._time = in->readSint32LE();
_state._timeSleep = in->readSint32LE();
_state._timeAlarm = in->readSint32LE();
_state._eventTime = in->readSint32LE();
_state._arrivalDaysLeft = in->readSint32LE();
_state._shipEnergyDaysLeft = in->readSint32LE();
_state._landingModuleEnergyDaysLeft = in->readSint32LE();
_state._greatFlag = in->readUint16LE();
_state._timeRobot = in->readSint16LE();
_state._money = in->readSint16LE();
_state._coins = in->readByte();
_state._shoes = in->readByte();
_state._destination = in->readByte();
_state._language = in->readByte();
_state._corridorSearch = in->readByte();
_state._alarmOn = in->readByte();
_state._terminalStripConnected = in->readByte();
_state._terminalStripWire = in->readByte();
_state._cableConnected = in->readByte();
_state._powerOff = in->readByte();
_state._dream = in->readByte();
// Inventory
int inventorySize = in->readSByte();
_inventoryScroll = in->readSByte();
_inventory.clear();
for (int i = 0; i < inventorySize; ++i) {
RoomID objectRoom = static_cast<RoomID>(in->readByte());
int objectIndex = in->readByte();
_inventory.add(*_rooms[objectRoom]->getObject(objectIndex));
}
// Rooms
for (int i = 0; i < kRoomsNum; ++i) {
_rooms[i]->deserialize(in);
}
return !in->err();
}
Inventory::Inventory()
: _numObjects(0)
{}
@@ -101,6 +101,8 @@ class GameManager {
void processInput(Common::KeyState &state);
void processInput();
void executeRoom();
bool serialize(Common::WriteStream *out);
bool deserialize(Common::ReadStream *in);
SupernovaEngine *_vm;
Common::KeyState _key;
@@ -110,6 +110,8 @@ SupernovaEngine::SupernovaEngine(OSystem *syst)
, _screenWidth(320)
, _screenHeight(200)
, _messageDisplayed(false)
, _allowLoadGame(true)
, _allowSaveGame(false)
{
// const Common::FSNode gameDataDir(ConfMan.get("path"));
// SearchMan.addSubDirectoryMatching(gameDataDir, "sound");
@@ -211,6 +213,10 @@ bool SupernovaEngine::hasFeature(EngineFeature f) const {
switch (f) {
case kSupportsRTL:
return true;
case kSupportsLoadingDuringRuntime:
return true;
case kSupportsSavingDuringRuntime:
return true;
default:
return false;
}
@@ -787,6 +793,79 @@ Common::MemoryReadStream *SupernovaEngine::convertToMod(const char *filename, in
return new Common::MemoryReadStream(buffer.getData(), buffer.size());
}
bool SupernovaEngine::canLoadGameStateCurrently() {
return _allowLoadGame;
}
Common::Error SupernovaEngine::loadGameState(int slot) {
return (loadGame(slot) ? Common::kNoError : Common::kWritingFailed);
}
bool SupernovaEngine::canSaveGameStateCurrently() {
return _allowSaveGame;
}
Common::Error SupernovaEngine::saveGameState(int slot, const Common::String &desc) {
return (saveGame(slot, desc) ? Common::kNoError : Common::kWritingFailed);
}
bool SupernovaEngine::loadGame(int slot) {
GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Load game:", "Load:", false);
int loadGameSlot = dialog->runModalWithCurrentTarget();
delete dialog;
if (loadGameSlot < 0 || loadGameSlot > 10)
return false;
Common::String filename = Common::String::format("msn_save.%02d", loadGameSlot);
// Common::InSaveFile *savefile = _saveFileMan->openForLoading(filename);
Common::InSaveFile *savefile = _saveFileMan->openRawFile(filename);
if (!savefile)
return false;
int descriptionSize = savefile->readSint16LE();
savefile->skip(descriptionSize);
savefile->skip(6);
// Graphics::skipThumbnail(*savefile);
_gm->deserialize(savefile);
delete savefile;
return true;
}
bool SupernovaEngine::saveGame(int slot, const Common::String &description) {
GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser("Save game:", "Save", true);
int saveGameSlot = dialog->runModalWithCurrentTarget();
Common::String saveGameDescription = dialog->getResultString();
delete dialog;
if (saveGameSlot < 0 || saveGameSlot > 10)
return false;
Common::String filename = Common::String::format("msn_save.%02d", saveGameSlot);
Common::OutSaveFile *savefile = _saveFileMan->openForSaving(filename, false);
if (!savefile)
return false;
TimeDate currentDate;
_system->getTimeAndDate(currentDate);
uint32 saveDate = (currentDate.tm_mday & 0xFF) << 24 | ((currentDate.tm_mon + 1) & 0xFF) << 16 | ((currentDate.tm_year + 1900) & 0xFFFF);
uint16 saveTime = (currentDate.tm_hour & 0xFF) << 8 | ((currentDate.tm_min) & 0xFF);
savefile->writeSint16LE(saveGameDescription.size() + 1);
savefile->write(saveGameDescription.c_str(), saveGameDescription.size() + 1);
savefile->writeUint32LE(saveDate);
savefile->writeUint16LE(saveTime);
// Graphics::saveThumbnail(*savefile);
_gm->serialize(savefile);
savefile->finalize();
delete savefile;
return true;
}
ScreenBufferStack::ScreenBufferStack()
: _last(_buffer) {
@@ -95,6 +95,8 @@ class SupernovaEngine : public Engine {
Common::Event _event;
int _screenWidth;
int _screenHeight;
bool _allowLoadGame;
bool _allowSaveGame;
byte _imageIndex;
byte _sectionIndex;
@@ -133,9 +135,15 @@ class SupernovaEngine : public Engine {
void renderBox(int x, int y, int width, int height, byte color);
void setColor63(byte value);
void command_print();
bool loadGame(int slot);
bool saveGame(int slot, const Common::String &description);
Common::MemoryReadStream *convertToMod(const char *filename, int version = 1);
virtual Common::Error loadGameState(int slot);
virtual bool canLoadGameStateCurrently();
virtual Common::Error saveGameState(int slot, const Common::String &desc);
virtual bool canSaveGameStateCurrently();
virtual bool hasFeature(EngineFeature f) const;
virtual void pauseEngineIntern(bool pause);
};

0 comments on commit 6092e39

Please sign in to comment.