aboutsummaryrefslogtreecommitdiff
path: root/engines/toon/resource.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/toon/resource.cpp')
-rw-r--r--engines/toon/resource.cpp154
1 files changed, 110 insertions, 44 deletions
diff --git a/engines/toon/resource.cpp b/engines/toon/resource.cpp
index 61e3ffb111..d635c5ab79 100644
--- a/engines/toon/resource.cpp
+++ b/engines/toon/resource.cpp
@@ -32,10 +32,18 @@
namespace Toon {
-Resources::Resources(ToonEngine *vm) : _vm(vm) {
+Resources::Resources(ToonEngine *vm) : _vm(vm), _cacheSize(0) {
+ _resourceCache.clear();
}
Resources::~Resources() {
+
+ while (!_resourceCache.empty()) {
+ CacheEntry *temp = _resourceCache.back();
+ _resourceCache.pop_back();
+ delete temp;
+ }
+
while(!_pakFiles.empty()) {
PakFile *temp = _pakFiles.back();
_pakFiles.pop_back();
@@ -45,8 +53,73 @@ Resources::~Resources() {
purgeFileData();
}
-void Resources::openPackage(Common::String fileName, bool preloadEntirePackage) {
- debugC(1, kDebugResource, "openPackage(%s, %d)", fileName.c_str(), (preloadEntirePackage) ? 1 : 0);
+void Resources::removePackageFromCache(Common::String packName) {
+ // I'm not sure what's a good strategy here. It seems unnecessary to
+ // actually remove the cached resources, because the player may be
+ // wandering back and forth between rooms. So for now, do nothing.
+}
+
+bool Resources::getFromCache(Common::String fileName, uint32 *fileSize, uint8 **fileData) {
+ for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
+ if ((*entry)->_data && (*entry)->_fileName.compareToIgnoreCase(fileName) == 0) {
+ debugC(5, kDebugResource, "getFromCache(%s) - Got %d bytes from %s", fileName.c_str(), (*entry)->_size, (*entry)->_packName.c_str());
+ (*entry)->_age = 0;
+ *fileSize = (*entry)->_size;
+ *fileData = (*entry)->_data;
+ return true;
+ }
+ }
+ return false;
+}
+
+void Resources::addToCache(Common::String packName, Common::String fileName, uint32 fileSize, uint8 *fileData) {
+ debugC(5, kDebugResource, "addToCache(%s, %s, %d) - Total Size: %d", packName.c_str(), fileName.c_str(), fileSize, _cacheSize + fileSize);
+ for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
+ if ((*entry)->_data) {
+ (*entry)->_age++;
+ }
+ }
+ _cacheSize += fileSize;
+
+ while (_cacheSize > MAX_CACHE_SIZE) {
+ CacheEntry *bestEntry = 0;
+ for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
+ if ((*entry)->_data) {
+ if (!bestEntry || ((*entry)->_age >= bestEntry->_age && (*entry)->_size >= bestEntry->_size)) {
+ bestEntry = *entry;
+ }
+ }
+ }
+ if (!bestEntry)
+ break;
+
+ free(bestEntry->_data);
+ bestEntry->_data = 0;
+ _cacheSize -= bestEntry->_size;
+ debugC(5, kDebugResource, "Freed %s (%s) to reclaim %d bytes", bestEntry->_fileName.c_str(), bestEntry->_packName.c_str(), bestEntry->_size);
+ }
+
+ for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
+ if (!(*entry)->_data) {
+ (*entry)->_packName = packName;
+ (*entry)->_fileName = fileName;
+ (*entry)->_age = 0;
+ (*entry)->_size = fileSize;
+ (*entry)->_data = fileData;
+ return;
+ }
+ }
+
+ CacheEntry *entry = new CacheEntry();
+ entry->_packName = packName;
+ entry->_fileName = fileName;
+ entry->_size = fileSize;
+ entry->_data = fileData;
+ _resourceCache.push_back(entry);
+}
+
+void Resources::openPackage(Common::String fileName) {
+ debugC(1, kDebugResource, "openPackage(%s)", fileName.c_str());
Common::File file;
bool opened = file.open(fileName);
@@ -55,15 +128,16 @@ void Resources::openPackage(Common::String fileName, bool preloadEntirePackage)
return;
PakFile *pakFile = new PakFile();
- pakFile->open(&file, fileName, preloadEntirePackage);
+ pakFile->open(&file, fileName);
- if (preloadEntirePackage)
- file.close();
+ file.close();
_pakFiles.push_back(pakFile);
}
void Resources::closePackage(Common::String fileName) {
+
+ removePackageFromCache(fileName);
for (uint32 i = 0; i < _pakFiles.size(); i++) {
if (_pakFiles[i]->getPackName() == fileName) {
delete _pakFiles[i];
@@ -91,13 +165,21 @@ uint8 *Resources::getFileData(Common::String fileName, uint32 *fileSize) {
_allocatedFileData.push_back(memory);
return memory;
} else {
- for (uint32 i = 0; i < _pakFiles.size(); i++) {
- uint32 locFileSize = 0;
- uint8 *locFileData = 0;
+ uint32 locFileSize = 0;
+ uint8 *locFileData = 0;
+
+ if (getFromCache(fileName, &locFileSize, &locFileData)) {
+ *fileSize = locFileSize;
+ return locFileData;
+ }
+
+ for (uint32 i = 0; i < _pakFiles.size(); i++) {
+
locFileData = _pakFiles[i]->getFileData(fileName, &locFileSize);
if (locFileData) {
*fileSize = locFileSize;
+ addToCache(_pakFiles[i]->getPackName(), fileName, locFileSize, locFileData);
return locFileData;
}
}
@@ -139,22 +221,12 @@ void Resources::purgeFileData() {
Common::SeekableReadStream *PakFile::createReadStream(Common::String fileName) {
debugC(1, kDebugResource, "createReadStream(%s)", fileName.c_str());
- int32 offset = 0;
- int32 size = 0;
- for (uint32 i = 0; i < _numFiles; i++) {
- if (fileName.compareToIgnoreCase(_files[i]._name) == 0) {
- size = _files[i]._size;
- offset = _files[i]._offset;
- break;
- }
- }
- if (!size)
- return 0;
-
- if (_fileHandle)
- return new Common::SeekableSubReadStream(_fileHandle, offset, offset + size);
+ uint32 fileSize = 0;
+ uint8 *buffer = getFileData(fileName, &fileSize);
+ if (buffer)
+ return new Common::MemoryReadStream(buffer, fileSize, DisposeAfterUse::YES);
else
- return new Common::MemoryReadStream(_buffer + offset, size);
+ return 0;
}
uint8 *PakFile::getFileData(Common::String fileName, uint32 *fileSize) {
@@ -162,16 +234,26 @@ uint8 *PakFile::getFileData(Common::String fileName, uint32 *fileSize) {
for (uint32 i = 0; i < _numFiles; i++) {
if (fileName.compareToIgnoreCase(_files[i]._name) == 0) {
- *fileSize = _files[i]._size;
- return _buffer + _files[i]._offset;
+ Common::File file;
+ if (file.open(_packName)) {
+ *fileSize = _files[i]._size;
+ file.seek(_files[i]._offset);
+
+ // Use malloc() because that's what MemoryReadStream
+ // uses to dispose of the memory when it's done.
+ uint8 *buffer = (uint8 *)malloc(*fileSize);
+ file.read(buffer, *fileSize);
+ file.close();
+ return buffer;
+ }
}
}
return 0;
}
-void PakFile::open(Common::SeekableReadStream *rs, Common::String packName, bool preloadEntirePackage) {
- debugC(1, kDebugResource, "open(rs, %d)", (preloadEntirePackage) ? 1 : 0);
+void PakFile::open(Common::SeekableReadStream *rs, Common::String packName) {
+ debugC(1, kDebugResource, "open(rs)");
char buffer[64];
int32 currentPos = 0;
@@ -199,30 +281,14 @@ void PakFile::open(Common::SeekableReadStream *rs, Common::String packName, bool
_numFiles++;
_files.push_back(newFile);
}
-
- if (preloadEntirePackage) {
- _bufferSize = rs->size();
- delete[] _buffer;
- _buffer = new uint8[_bufferSize];
- rs->seek(0);
- rs->read(_buffer, _bufferSize);
- }
}
void PakFile::close() {
- delete[] _buffer;
- if (_fileHandle) {
- _fileHandle->close();
- delete _fileHandle;
- }
}
PakFile::PakFile() {
- _bufferSize = 0;
- _buffer = NULL;
- _fileHandle = NULL;
}
PakFile::~PakFile() {