scummvm/engines/sci/engine/file.cpp
Filippos Karapetis aeac51d726 SCI: Implement the file operations needed for the save dialog in Phantasmagoria
Phantasmagoria's scripts keep polling for the existence of the savegame
index file and request to read and write it using the same parameters
when opening it. The index file is closed and reopened for every save
slot, which is slow and can be much slower on non-desktop devices.
Also, the game scripts request seeking in writable streams and request
to expand the existing index file.

To provide this functionality and to reduce constant slow file opening
and closing, this virtual class has been introduced
2012-06-13 12:26:49 +03:00

139 lines
3.4 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "common/savefile.h"
#include "common/stream.h"
#include "sci/sci.h"
#include "sci/engine/file.h"
namespace Sci {
#ifdef ENABLE_SCI32
VirtualIndexFile::VirtualIndexFile(Common::String fileName) : _fileName(fileName), _changed(false) {
Common::SeekableReadStream *inFile = g_sci->getSaveFileManager()->openForLoading(fileName);
_bufferSize = inFile->size();
_buffer = new char[_bufferSize];
inFile->read(_buffer, _bufferSize);
_ptr = _buffer;
delete inFile;
}
VirtualIndexFile::~VirtualIndexFile() {
close();
_bufferSize = 0;
delete[] _buffer;
_buffer = 0;
}
uint32 VirtualIndexFile::read(char *buffer, uint32 size) {
uint32 curPos = _ptr - _buffer;
uint32 finalSize = MIN<uint32>(size, _bufferSize - curPos);
char *localPtr = buffer;
for (uint32 i = 0; i < finalSize; i++)
*localPtr++ = *_ptr++;
return finalSize;
}
uint32 VirtualIndexFile::write(const char *buffer, uint32 size) {
_changed = true;
uint32 curPos = _ptr - _buffer;
// Check if the buffer needs to be resized
if (curPos + size >= _bufferSize) {
_bufferSize = curPos + size + 1;
char *tmp = _buffer;
_buffer = new char[_bufferSize];
_ptr = _buffer + curPos;
memcpy(_buffer, tmp, _bufferSize);
delete[] tmp;
}
for (uint32 i = 0; i < size; i++)
*_ptr++ = *buffer++;
return size;
}
uint32 VirtualIndexFile::readLine(char *buffer, uint32 size) {
uint32 startPos = _ptr - _buffer;
uint32 bytesRead = 0;
char *localPtr = buffer;
// This is not a full-blown implementation of readLine, but it
// suffices for Phantasmagoria
while (startPos + bytesRead < size) {
bytesRead++;
if (*_ptr == 0 || *_ptr == 0x0A) {
_ptr++;
*localPtr = 0;
return bytesRead;
} else {
*localPtr++ = *_ptr++;
}
}
return bytesRead;
}
bool VirtualIndexFile::seek(int32 offset, int whence) {
uint32 startPos = _ptr - _buffer;
assert(offset >= 0);
switch (whence) {
case SEEK_CUR:
assert(startPos + offset < _bufferSize);
_ptr += offset;
break;
case SEEK_SET:
assert(offset < _bufferSize);
_ptr = _buffer + offset;
break;
case SEEK_END:
assert(_bufferSize - offset >= 0);
_ptr = _buffer + (_bufferSize - offset);
break;
}
return true;
}
void VirtualIndexFile::close() {
if (_changed) {
Common::WriteStream *outFile = g_sci->getSaveFileManager()->openForSaving(_fileName);
outFile->write(_buffer, _bufferSize);
delete outFile;
}
// Maintain the buffer, and seek to the beginning of it
_ptr = _buffer;
}
#endif
} // End of namespace Sci