diff options
Diffstat (limited to 'engines/gargoyle/streams.cpp')
-rw-r--r-- | engines/gargoyle/streams.cpp | 106 |
1 files changed, 98 insertions, 8 deletions
diff --git a/engines/gargoyle/streams.cpp b/engines/gargoyle/streams.cpp index 93335b9c0e..99ced12ce1 100644 --- a/engines/gargoyle/streams.cpp +++ b/engines/gargoyle/streams.cpp @@ -508,11 +508,47 @@ glui32 MemoryStream::getLineUni(glui32 *ubuf, glui32 len) { /*--------------------------------------------------------------------------*/ -FileStream::FileStream(Streams *streams, uint32 rock, bool unicode) : - Stream(streams, true, false, rock, unicode), _lastOp(0), _textFile(false) { - // TODO: Set up files - _outFile = nullptr; - _inFile = nullptr; +FileStream::FileStream(Streams *streams, frefid_t fref, glui32 fmode, glui32 rock, bool unicode) : + Stream(streams, true, false, rock, unicode), _lastOp(0), _textFile(false), + _inFile(nullptr), _outFile(nullptr), _inStream(nullptr) { + Common::String fname = fref->_slotNumber == -1 ? fref->_filename : fref->getSaveName(); + + if (fmode == filemode_Write || fmode == filemode_ReadWrite || fmode == filemode_WriteAppend) { + _outFile = g_system->getSavefileManager()->openForSaving(fname, fref->_slotNumber != -1); + if (!_outFile) + error("Could open file for writing - %s", fname.c_str()); + + if (fref->_slotNumber != -1) + writeSavegameHeader(_outFile, fref->_description); + } else if (fmode == filemode_Read) { + if (_file.open(fname)) { + _inStream = &_file; + } else { + _inFile = g_system->getSavefileManager()->openForLoading(fname); + _inStream = _inFile; + } + + if (!_inStream) + error("Could not open for reading - %s", fname.c_str()); + + if (_inFile) { + // It's a save file, so skip over the header + SavegameHeader header; + if (!readSavegameHeader(_inStream, header)) + error("Invalid savegame"); + + g_vm->_events->setTotalPlayTicks(header._totalFrames); + } + } +} + +FileStream::~FileStream() { + _file.close(); + delete _inFile; + if (_outFile) { + _outFile->finalize(); + delete _outFile; + } } void FileStream::ensureOp(FileMode mode) { @@ -798,7 +834,6 @@ glsi32 FileStream::getCharUni() { } } - glui32 FileStream::getBufferUni(glui32 *buf, glui32 len) { if (!_readable) return 0; @@ -926,6 +961,55 @@ glui32 FileStream::getLineUni(glui32 *ubuf, glui32 len) { } } +bool FileStream::readSavegameHeader(Common::SeekableReadStream *stream, SavegameHeader &header) { + header._totalFrames = 0; + + // Validate the header Id + if (stream->readUint32BE() != MKTAG('G', 'A', 'R', 'G')) + return false; + + // Check the savegame version + header._version = stream->readByte(); + if (header._version > SAVEGAME_VERSION) + error("Savegame is too recent"); + + // Read in name + char c; + while ((c = stream->readByte()) != '\0') + header._saveName += c; + + // Read in save date/time + header._year = stream->readUint16LE(); + header._month = stream->readUint16LE(); + header._day = stream->readUint16LE(); + header._hour = stream->readUint16LE(); + header._minute = stream->readUint16LE(); + header._totalFrames = stream->readUint32LE(); + + return true; +} + +void FileStream::writeSavegameHeader(Common::WriteStream *stream, const Common::String &saveName) { + // Write out a savegame header + stream->writeUint32BE(MKTAG('G', 'A', 'R', 'G')); + + stream->writeByte(SAVEGAME_VERSION); + + // Write savegame name + stream->write(saveName.c_str(), saveName.size()); + stream->writeByte('\0'); + + // Write out the save date/time + TimeDate td; + g_system->getTimeAndDate(td); + stream->writeUint16LE(td.tm_year + 1900); + stream->writeUint16LE(td.tm_mon + 1); + stream->writeUint16LE(td.tm_mday); + stream->writeUint16LE(td.tm_hour); + stream->writeUint16LE(td.tm_min); + stream->writeUint32LE(g_vm->_events->getTotalPlayTicks()); +} + /*--------------------------------------------------------------------------*/ Streams::Streams() : _streamList(nullptr), _currentStream(nullptr) { @@ -936,13 +1020,19 @@ Streams::~Streams() { delete _streamList; } -WindowStream *Streams::addWindowStream(Window *window) { +FileStream *Streams::openFileStream(frefid_t fref, glui32 fmode, glui32 rock, bool unicode) { + FileStream *stream = new FileStream(this, fref, fmode, rock, unicode); + addStream(stream); + return stream; +} + +WindowStream *Streams::openWindowStream(Window *window) { WindowStream *stream = new WindowStream(this, window); addStream(stream); return stream; } -MemoryStream *Streams::addMemoryStream(void *buf, size_t buflen, FileMode mode, uint32 rock, bool unicode) { +MemoryStream *Streams::openMemoryStream(void *buf, size_t buflen, FileMode mode, uint32 rock, bool unicode) { MemoryStream *stream = new MemoryStream(this, buf, buflen, mode, rock, unicode); addStream(stream); return stream; |