Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SCI: Implement the file operations needed for the save dialog in Phan…
…tasmagoria 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
- Loading branch information
Showing
6 changed files
with
351 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
/* 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* 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. | ||
* | ||
*/ | ||
|
||
#ifndef SCI_ENGINE_FILE_H | ||
#define SCI_ENGINE_FILE_H | ||
|
||
#include "common/scummsys.h" | ||
|
||
namespace Sci { | ||
|
||
#ifdef ENABLE_SCI32 | ||
|
||
/** | ||
* An implementation of a virtual file that supports basic read and write | ||
* operations simultaneously. | ||
* | ||
* This class has been initially implemented for Phantasmagoria, which has its | ||
* own custom save/load code. The load code keeps checking for the existence | ||
* of the save index file and keeps closing and reopening it for each save | ||
* slot. This is notoriously slow and clumsy, and introduces noticeable delays, | ||
* especially for non-desktop systems. Also, its game scripts request to open | ||
* the index file for reading and writing with the same parameters | ||
* (SaveManager::setCurrentSave and SaveManager::getCurrentSave). Moreover, | ||
* the game scripts reopen the index file for writing in order to update it | ||
* and seek within it. We do not support seeking in writeable streams, and the | ||
* fact that our saved games are ZIP files makes this operation even more | ||
* expensive. Finally, the savegame index file is supposed to be expanded when | ||
* a new save slot is added. | ||
* For the aforementioned reasons, this class has been implemented, which offers | ||
* the basic functionality needed by the game scripts in Phantasmagoria. | ||
*/ | ||
class VirtualIndexFile { | ||
public: | ||
VirtualIndexFile(Common::String fileName); | ||
~VirtualIndexFile(); | ||
|
||
uint32 read(char *buffer, uint32 size); | ||
uint32 readLine(char *buffer, uint32 size); | ||
uint32 write(const char *buffer, uint32 size); | ||
bool seek(int32 offset, int whence); | ||
void close(); | ||
|
||
private: | ||
char *_buffer; | ||
uint32 _bufferSize; | ||
char *_ptr; | ||
|
||
Common::String _fileName; | ||
bool _changed; | ||
}; | ||
|
||
#endif | ||
|
||
} // End of namespace Sci | ||
|
||
#endif // SCI_ENGINE_FILE_H |
Oops, something went wrong.