aboutsummaryrefslogtreecommitdiff
path: root/engines/xeen/files.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/xeen/files.cpp')
-rw-r--r--engines/xeen/files.cpp281
1 files changed, 235 insertions, 46 deletions
diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp
index 06dd3d12a7..375b9df65a 100644
--- a/engines/xeen/files.cpp
+++ b/engines/xeen/files.cpp
@@ -26,6 +26,7 @@
#include "common/textconsole.h"
#include "xeen/xeen.h"
#include "xeen/files.h"
+#include "xeen/saves.h"
namespace Xeen {
@@ -120,7 +121,7 @@ int BaseCCArchive::listMembers(Common::ArchiveMemberList &list) const {
CCArchive::CCArchive(const Common::String &filename, bool encoded):
BaseCCArchive(), _filename(filename), _encoded(encoded) {
- File f(filename);
+ File f(filename, SearchMan);
loadIndex(&f);
}
@@ -128,7 +129,7 @@ CCArchive::CCArchive(const Common::String &filename, const Common::String &prefi
bool encoded): BaseCCArchive(), _filename(filename),
_prefix(prefix), _encoded(encoded) {
_prefix.toLowercase();
- File f(filename);
+ File f(filename, SearchMan);
loadIndex(&f);
}
@@ -183,71 +184,68 @@ Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::S
/*------------------------------------------------------------------------*/
-CCArchive *FileManager::_archives[3];
-
FileManager::FileManager(XeenEngine *vm) {
Common::File f;
- int sideNum = 0;
-
- File::_currentArchive = ANY_ARCHIVE;
_isDarkCc = vm->getGameID() == GType_DarkSide;
- _archives[0] = _archives[1] = _archives[2] = nullptr;
-
- if (vm->getGameID() != GType_DarkSide) {
- _archives[0] = new CCArchive("xeen.cc", "xeen", true);
- SearchMan.add("xeen", _archives[0]);
- sideNum = 1;
+
+ File::_xeenCc = (vm->getGameID() == GType_DarkSide) ? nullptr :
+ new CCArchive("xeen.cc", "xeen", true);
+ File::_darkCc = (vm->getGameID() == GType_Clouds) ? nullptr :
+ new CCArchive("dark.cc", "dark", true);
+ if (Common::File::exists("intro.cc")) {
+ CCArchive *introCc = new CCArchive("intro.cc", "intro", true);
+ SearchMan.add("intro", introCc);
}
- if (vm->getGameID() == GType_DarkSide || vm->getGameID() == GType_WorldOfXeen) {
- _archives[sideNum] = new CCArchive("dark.cc", "dark", true);
- SearchMan.add("dark", _archives[sideNum]);
- }
+ File::_currentArchive = vm->getGameID() == GType_DarkSide ?
+ File::_darkCc : File::_xeenCc;
+ assert(File::_currentArchive);
+}
- if (f.exists("intro.cc")) {
- _archives[2] = new CCArchive("intro.cc", "intro", true);
- SearchMan.add("intro", _archives[2]);
- }
+FileManager::~FileManager() {
+ SearchMan.remove("intro");
+ delete File::_xeenCc;
+ delete File::_darkCc;
}
-void FileManager::setGameCc(bool isDarkCc) {
- _isDarkCc = isDarkCc;
- File::_currentArchive = isDarkCc ? ALTSIDE_ARCHIVE : GAME_ARCHIVE;
+void FileManager::setGameCc(int ccMode) {
+ if (g_vm->getGameID() != GType_WorldOfXeen)
+ ccMode = 1;
+
+ File::setCurrentArchive(ccMode);
+ _isDarkCc = ccMode != 0;
}
/*------------------------------------------------------------------------*/
-ArchiveType File::_currentArchive;
+CCArchive *File::_xeenCc;
+CCArchive *File::_darkCc;
+SaveArchive *File::_xeenSave;
+SaveArchive *File::_darkSave;
+BaseCCArchive *File::_currentArchive;
+SaveArchive *File::_currentSave;
File::File(const Common::String &filename) {
File::open(filename);
}
-File::File(const Common::String &filename, ArchiveType archiveType) {
- File::open(filename, archiveType);
-}
-
File::File(const Common::String &filename, Common::Archive &archive) {
File::open(filename, archive);
}
+File::File(const Common::String &filename, int ccMode) {
+ File::open(filename, ccMode);
+}
+
bool File::open(const Common::String &filename) {
- return File::open(filename, _currentArchive);
-}
-
-bool File::open(const Common::String &filename, ArchiveType archiveType) {
- if (archiveType == ANY_ARCHIVE) {
- Common::File::open(filename);
- } else {
- CCArchive &archive = *FileManager::_archives[archiveType];
- if (!Common::File::open(filename, archive))
- // If not in the designated archive, try opening from any archive,
- // or as a standalone file in the filesystem
- Common::File::open(filename);
+ if (!_currentSave || !Common::File::open(filename, *_currentSave)) {
+ if (!Common::File::open(filename, *_currentArchive)) {
+ // Could not find in current archive, so try intro.cc or in folder
+ if (!Common::File::open(filename))
+ error("Could not open file - %s", filename.c_str());
+ }
}
- if (!isOpen())
- error("Could not open file - %s", filename.c_str());
return true;
}
@@ -257,6 +255,36 @@ bool File::open(const Common::String &filename, Common::Archive &archive) {
return true;
}
+bool File::open(const Common::String &filename, int ccMode) {
+ FileManager &files = *g_vm->_files;
+ int oldMode = files._isDarkCc ? 1 : 0;
+
+ files.setGameCc(ccMode);
+ File::open(filename);
+ files.setGameCc(oldMode);
+
+ return true;
+}
+
+void File::setCurrentArchive(int ccMode) {
+ switch (ccMode) {
+ case 0:
+ _currentArchive = _xeenCc;
+ _currentSave = _xeenSave;
+ break;
+
+ case 1:
+ _currentArchive = _darkCc;
+ _currentSave = _darkSave;
+ break;
+
+ default:
+ break;
+ }
+
+ assert(_currentArchive);
+}
+
Common::String File::readString() {
Common::String result;
char c;
@@ -267,18 +295,179 @@ Common::String File::readString() {
return result;
}
+bool File::exists(const Common::String &filename) {
+ if (!_currentSave || !_currentSave->hasFile(filename)) {
+ if (!_currentArchive->hasFile(filename)) {
+ // Could not find in current archive, so try intro.cc or in folder
+ return Common::File::exists(filename);
+ }
+ }
+
+ return true;
+}
+
+bool File::exists(const Common::String &filename, int ccMode) {
+ FileManager &files = *g_vm->_files;
+ int oldMode = files._isDarkCc ? 1 : 0;
+
+ files.setGameCc(ccMode);
+ bool result = exists(filename);
+ files.setGameCc(oldMode);
+
+ return result;
+}
+
+void File::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP) {
+ byte data = 0;
+
+ int bitCounter = 0;
+ for (bool *p = startP; p < endP; ++p, bitCounter = (bitCounter + 1) % 8) {
+ if (bitCounter == 0) {
+ if (s.isLoading() || p != startP)
+ s.syncAsByte(data);
+
+ if (s.isSaving())
+ data = 0;
+ }
+
+ if (s.isLoading())
+ *p = ((data >> bitCounter) & 1) != 0;
+ else if (*p)
+ data |= 1 << bitCounter;
+ }
+
+ if (s.isSaving())
+ s.syncAsByte(data);
+}
+
/*------------------------------------------------------------------------*/
void StringArray::load(const Common::String &name) {
- load(name, ANY_ARCHIVE);
+ File f(name);
+ clear();
+ while (f.pos() < f.size())
+ push_back(f.readString());
}
-void StringArray::load(const Common::String &name, ArchiveType archiveType) {
- File f(name, archiveType);
+void StringArray::load(const Common::String &name, int ccMode) {
+ File f(name, ccMode);
clear();
while (f.pos() < f.size())
push_back(f.readString());
}
+/*------------------------------------------------------------------------*/
+
+SaveArchive::SaveArchive(Party *party) : BaseCCArchive(), _party(party) {
+ _data = nullptr;
+}
+
+SaveArchive::~SaveArchive() {
+ for (Common::HashMap<uint16, Common::MemoryWriteStreamDynamic *>::iterator it = _newData.begin(); it != _newData.end(); it++) {
+ delete (*it)._value;
+ }
+ delete[] _data;
+}
+
+Common::SeekableReadStream *SaveArchive::createReadStreamForMember(const Common::String &name) const {
+ CCEntry ccEntry;
+
+ // If the given resource has already been perviously "written" to the
+ // save manager, then return that new resource
+ uint16 id = BaseCCArchive::convertNameToId(name);
+ if (_newData.contains(id)) {
+ Common::MemoryWriteStreamDynamic *stream = _newData[id];
+ return new Common::MemoryReadStream(stream->getData(), stream->size());
+ }
+
+ // Retrieve the resource from the loaded savefile
+ if (getHeaderEntry(name, ccEntry)) {
+ // Open the correct CC entry
+ return new Common::MemoryReadStream(_data + ccEntry._offset, ccEntry._size);
+ }
+
+ return nullptr;
+}
+
+void SaveArchive::load(Common::SeekableReadStream *stream) {
+ loadIndex(stream);
+
+ delete[] _data;
+ _data = new byte[stream->size()];
+ stream->seek(0);
+ stream->read(_data, stream->size());
+
+ // Load in the character stats and active party
+ Common::SeekableReadStream *chr = createReadStreamForMember("maze.chr");
+ Common::Serializer sChr(chr, nullptr);
+ _party->_roster.synchronize(sChr);
+ delete chr;
+
+ Common::SeekableReadStream *pty = createReadStreamForMember("maze.pty");
+ Common::Serializer sPty(pty, nullptr);
+ _party->synchronize(sPty);
+ delete pty;
+}
+
+void SaveArchive::reset(CCArchive *src) {
+ Common::MemoryWriteStreamDynamic saveFile(DisposeAfterUse::YES);
+ File fIn;
+
+ g_vm->_files->setGameCc(g_vm->getGameID() == GType_DarkSide ? 1 : 0);
+ const int RESOURCES[6] = { 0x2A0C, 0x2A1C, 0x2A2C, 0x2A3C, 0x284C, 0x2A5C };
+ for (int i = 0; i < 6; ++i) {
+ Common::String filename = Common::String::format("%.4x", RESOURCES[i]);
+ if (src->hasFile(filename)) {
+ // Read in the next resource
+ fIn.open(filename, *src);
+ byte *data = new byte[fIn.size()];
+ fIn.read(data, fIn.size());
+
+ // Copy it to the combined savefile resource
+ saveFile.write(data, fIn.size());
+ delete[] data;
+ fIn.close();
+ }
+ }
+
+ assert(saveFile.size() > 0);
+ Common::MemoryReadStream f(saveFile.getData(), saveFile.size());
+ load(&f);
+}
+
+/*------------------------------------------------------------------------*/
+
+OutFile::OutFile(const Common::String &filename) :
+ _filename(filename), _backingStream(DisposeAfterUse::YES) {
+ _archive = File::_currentSave;
+}
+
+OutFile::OutFile(const Common::String &filename, SaveArchive *archive) :
+ _filename(filename), _archive(archive), _backingStream(DisposeAfterUse::YES) {
+}
+
+OutFile::OutFile(const Common::String &filename, int ccMode) :
+ _filename(filename), _backingStream(DisposeAfterUse::YES) {
+ g_vm->_files->setGameCc(ccMode);
+ _archive = File::_currentSave;
+}
+
+uint32 OutFile::write(const void *dataPtr, uint32 dataSize) {
+ return _backingStream.write(dataPtr, dataSize);
+}
+
+int32 OutFile::pos() const {
+ return _backingStream.pos();
+}
+
+void OutFile::finalize() {
+ uint16 id = BaseCCArchive::convertNameToId(_filename);
+
+ if (!_archive->_newData.contains(id))
+ _archive->_newData[id] = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
+
+ Common::MemoryWriteStreamDynamic *out = _archive->_newData[id];
+ out->write(_backingStream.getData(), _backingStream.size());
+}
} // End of namespace Xeen