Skip to content

Commit

Permalink
PETKA: implemented saving/loading system
Browse files Browse the repository at this point in the history
  • Loading branch information
voltya committed Aug 25, 2019
1 parent 9303464 commit 9a9f152
Show file tree
Hide file tree
Showing 9 changed files with 315 additions and 1 deletion.
12 changes: 12 additions & 0 deletions engines/petka/big_dialogue.cpp
Expand Up @@ -20,6 +20,7 @@
*
*/

#include "common/debug.h"
#include "common/stream.h"

#include "petka/base.h"
Expand Down Expand Up @@ -342,4 +343,15 @@ void BigDialogue::sub40B670(int arg) {
}
}

void BigDialogue::load(Common::ReadStream *s) {
_codeSize = s->readUint32LE();
s->read(_code, 4 * _codeSize);

}

void BigDialogue::save(Common::WriteStream *s) {
s->writeUint32LE(_codeSize);
s->write(_code, 4 * _codeSize);
}

} // End of namespace Petka
3 changes: 3 additions & 0 deletions engines/petka/big_dialogue.h
Expand Up @@ -71,6 +71,9 @@ class BigDialogue {

const Common::U32String *getSpeechInfo(int *talkerId, const char **soundName, int unk);

void load(Common::ReadStream *s);
void save(Common::WriteStream *s);

private:
void loadSpeechesInfo();

Expand Down
61 changes: 61 additions & 0 deletions engines/petka/detection.cpp
Expand Up @@ -20,6 +20,9 @@
*
*/

#include "common/system.h"
#include "common/savefile.h"

#include "engines/advancedDetector.h"

#include "petka/petka.h"
Expand Down Expand Up @@ -48,9 +51,67 @@ class PetkaMetaEngine : public AdvancedMetaEngine {
return "Red Comrades (C) S.K.I.F";
}

virtual bool hasFeature(MetaEngineFeature f) const;
virtual int getMaximumSaveSlot() const { return 18; }
virtual SaveStateList listSaves(const char *target) const;
virtual void removeSaveState(const char *target, int slot) const;
virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
};

bool PetkaMetaEngine::hasFeature(MetaEngineFeature f) const {
return
(f == kSupportsListSaves) ||
(f == kSupportsDeleteSave) ||
(f == kSavesSupportMetaInfo) ||
(f == kSavesSupportThumbnail) ||
(f == kSavesSupportCreationDate) ||
(f == kSavesSupportPlayTime);
}

SaveStateList PetkaMetaEngine::listSaves(const char *target) const {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Common::String pattern = Common::String::format("%s.s##", target);
Common::StringArray filenames = saveFileMan->listSavefiles(pattern);

SaveStateList saveList;
for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
// Obtain the last 2 digits of the filename, since they correspond to the save slot
int slotNum = atoi(file->c_str() + file->size() - 2);
if (slotNum >= 0 && slotNum <= getMaximumSaveSlot()) {
Common::ScopedPtr<Common::InSaveFile> in(saveFileMan->openForLoading(*file));
if (in) {
SaveStateDescriptor desc;
desc.setSaveSlot(slotNum);
if (Petka::readSaveHeader(*in.get(), desc))
saveList.push_back(desc);
}
}
}

// Sort saves based on slot number.
Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}

void PetkaMetaEngine::removeSaveState(const char *target, int slot) const {
g_system->getSavefileManager()->removeSavefile(Petka::generateSaveName(slot, target));
}

SaveStateDescriptor PetkaMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
Common::ScopedPtr<Common::InSaveFile> f(g_system->getSavefileManager()->openForLoading(Petka::generateSaveName(slot, target)));

if (f) {
SaveStateDescriptor desc;
if (!Petka::readSaveHeader(*f.get(), desc, false))
return SaveStateDescriptor();

return desc;
}

return SaveStateDescriptor();
}

bool PetkaMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
if (desc)
*engine = new Petka::PetkaEngine(syst, desc);
Expand Down
1 change: 1 addition & 0 deletions engines/petka/module.mk
Expand Up @@ -6,6 +6,7 @@ MODULE_OBJS = \
file_mgr.o \
flc.o \
petka.o \
saveload.o \
q_manager.o \
q_system.o \
sound.o \
Expand Down
2 changes: 1 addition & 1 deletion engines/petka/objects/object_case.h
Expand Up @@ -41,7 +41,7 @@ class QObjectCase : public QObject {
void removeItem(int id);
void setInv(int id1, int id2);

private:
public:
Common::Array<int> _items;
uint _clickedObjIndex;
int _itemIndex;
Expand Down
15 changes: 15 additions & 0 deletions engines/petka/petka.h
Expand Up @@ -24,8 +24,11 @@
#define PETKA_PETKA_H

#include "common/random.h"
#include "common/stream.h"
#include "common/savefile.h"

#include "engines/engine.h"
#include "engines/savestate.h"

#include "gui/debugger.h"

Expand Down Expand Up @@ -86,6 +89,12 @@ class PetkaEngine : public Engine {
Common::RandomSource &getRnd();
const Common::String &getSpeechPath();

virtual Common::Error loadGameState(int slot) override;
bool canLoadGameStateCurrently() override;

Common::Error saveGameState(int slot, const Common::String &desc) override;
bool canSaveGameStateCurrently() override;

private:
void loadStores();

Expand All @@ -107,7 +116,10 @@ class PetkaEngine : public Engine {
Common::String _chapterStoreName;

uint8 _part;
uint8 _nextPart;
uint8 _chapter;
bool _shouldChangePart;
Common::String _saveName;
};

class Console : public GUI::Debugger {
Expand All @@ -118,6 +130,9 @@ class Console : public GUI::Debugger {

extern PetkaEngine *g_vm;

WARN_UNUSED_RESULT bool readSaveHeader(Common::InSaveFile &in, SaveStateDescriptor &desc, bool skipThumbnail = true);
Common::String generateSaveName(int slot, const char *gameId);

} // End of namespace Petka

#endif
92 changes: 92 additions & 0 deletions engines/petka/q_system.cpp
Expand Up @@ -35,7 +35,9 @@
#include "petka/objects/object_case.h"
#include "petka/objects/object_star.h"
#include "petka/objects/heroes.h"
#include "petka/big_dialogue.h"
#include "petka/q_system.h"
#include "petka/video.h"

namespace Petka {

Expand Down Expand Up @@ -234,4 +236,94 @@ void QSystem::setChapayev() {
}
}

static Common::String readString(Common::ReadStream *s) {
Common::String string;
uint32 len = s->readUint32LE();
char *buffer = (char *)malloc(len);
s->read(buffer, len);
string = Common::String(buffer, len);
free(buffer);
return string;
}

static void writeString(Common::WriteStream *s, const Common::String &string) {
s->writeUint32LE(string.size());
s->write(string.c_str(), string.size());
}

void QSystem::load(Common::ReadStream *s) {
uint count = s->readUint32LE();
for (uint i = 0; i < count; ++i) {
QMessageObject *obj = findObject(readString(s));
obj->_field_38 = s->readUint32LE();
obj->_status = s->readUint32LE();
obj->_resourceId = s->readUint32LE();
obj->_z = s->readUint32LE();
obj->_x = s->readUint32LE();
obj->_y = s->readUint32LE();
obj->_isShown = s->readUint32LE();
obj->_isActive = s->readUint32LE();
obj->_animate = s->readUint32LE();
}

uint itemSize = s->readUint32LE();
_case->_items.clear();
for (uint i = 0; i < itemSize; ++i) {
_case->_items.push_back(s->readSint32LE());
}

_room = (QObjectBG *)findObject(readString(s));
if (_room) {
_mainInterface->loadRoom(_room->_id, true);
}

g_vm->getBigDialogue()->load(s);

_cursor->_resourceId = s->readUint32LE();
_cursor->_actionType = s->readUint32LE();
int invObjId = s->readSint32LE();
if (invObjId != -1) {
_cursor->_invObj = findObject(invObjId);
} else {
_cursor->_invObj = nullptr;
}

g_vm->videoSystem()->makeAllDirty();
}

void QSystem::save(Common::WriteStream *s) {
s->writeUint32LE(_allObjects.size());
for (uint i = 0; i < _allObjects.size(); ++i) {
writeString(s, _allObjects[i]->_name);
s->writeUint32LE(_allObjects[i]->_field_38);
s->writeUint32LE(_allObjects[i]->_status);
s->writeUint32LE(_allObjects[i]->_resourceId);
s->writeUint32LE(_allObjects[i]->_z);
s->writeUint32LE(_allObjects[i]->_x);
s->writeUint32LE(_allObjects[i]->_y);
s->writeUint32LE(_allObjects[i]->_isShown);
s->writeUint32LE(_allObjects[i]->_isActive);
s->writeUint32LE(_allObjects[i]->_animate);
}

s->writeUint32LE(_case->_items.size());
for (uint i = 0; i < _case->_items.size(); ++i) {
s->writeSint32LE(_case->_items[i]);
}

writeString(s, _room->_name);

// heroes (no impl)

g_vm->getBigDialogue()->save(s);

s->writeUint32LE(_cursor->_resourceId);
s->writeUint32LE(_cursor->_actionType);
if (_cursor->_invObj) {
s->writeSint32LE(_cursor->_invObj->_resourceId);
} else {
s->writeSint32LE(-1);
}
}

}
3 changes: 3 additions & 0 deletions engines/petka/q_system.h
Expand Up @@ -24,6 +24,7 @@
#define PETKA_Q_SYSTEM_H

#include "common/ptr.h"
#include "common/stream.h"
#include "common/list.h"

#include "petka/objects/object_bg.h"
Expand All @@ -49,6 +50,8 @@ class QSystem {
~QSystem();

bool init();
void load(Common::ReadStream *s);
void save(Common::WriteStream *s);

void update();

Expand Down

0 comments on commit 9a9f152

Please sign in to comment.