Ticket #9284: toon-resourcecache.diff
File toon-resourcecache.diff, 10.1 KB (added by , 14 years ago) |
---|
-
engines/toon/resource.cpp
diff --git a/engines/toon/resource.cpp b/engines/toon/resource.cpp index 61e3ffb..0e21ebf 100644
a b 32 32 33 33 namespace Toon { 34 34 35 Resources::Resources(ToonEngine *vm) : _vm(vm) { 35 Resources::Resources(ToonEngine *vm) : _vm(vm), _cacheSize(0) { 36 _resourceCache.clear(); 36 37 } 37 38 38 39 Resources::~Resources() { 40 while (!_resourceCache.empty()) { 41 CacheEntry *temp = _resourceCache.back(); 42 _resourceCache.pop_back(); 43 delete temp; 44 } 45 39 46 while(!_pakFiles.empty()) { 40 47 PakFile *temp = _pakFiles.back(); 41 48 _pakFiles.pop_back(); … … Resources::~Resources() { 45 52 purgeFileData(); 46 53 } 47 54 48 void Resources::openPackage(Common::String fileName, bool preloadEntirePackage) { 49 debugC(1, kDebugResource, "openPackage(%s, %d)", fileName.c_str(), (preloadEntirePackage) ? 1 : 0); 55 void Resources::removePackageFromCache(Common::String packName) { 56 // I'm not sure what's a good strategy here. It seems unnecessary to 57 // actually remove the cached resources, because the player may be 58 // wandering back and forth between rooms. So for now, do nothing. 59 } 60 61 bool Resources::getFromCache(Common::String fileName, uint32 *fileSize, uint8 **fileData) { 62 for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) { 63 if ((*entry)->_fileName.compareToIgnoreCase(fileName) == 0) { 64 debugC(5, kDebugResource, "getFromCache(%s) - Got %d bytes from %s", fileName.c_str(), (*entry)->_size, (*entry)->_packName.c_str()); 65 (*entry)->_age = 0; 66 *fileSize = (*entry)->_size; 67 *fileData = (*entry)->_data; 68 return true; 69 } 70 } 71 return false; 72 } 73 74 void Resources::addToCache(Common::String packName, Common::String fileName, uint32 fileSize, uint8 *fileData) { 75 debugC(5, kDebugResource, "addToCache(%s, %s, %d) - Total Size: %d", packName.c_str(), fileName.c_str(), fileSize, _cacheSize + fileSize); 76 77 for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) { 78 if ((*entry)->_data) { 79 (*entry)->_age++; 80 } 81 } 82 83 _cacheSize += fileSize; 84 85 while (_cacheSize > MAX_CACHE_SIZE) { 86 CacheEntry *bestEntry = 0; 87 for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) { 88 if ((*entry)->_data) { 89 if (!bestEntry || ((*entry)->_age >= bestEntry->_age && (*entry)->_size >= bestEntry->_size)) { 90 bestEntry = *entry; 91 } 92 } 93 } 94 if (!bestEntry) 95 break; 96 free(bestEntry->_data); 97 bestEntry->_data = 0; 98 _cacheSize -= bestEntry->_size; 99 debugC(5, kDebugResource, "Freed %s (%s) to reclaim %d bytes", bestEntry->_fileName.c_str(), bestEntry->_packName.c_str(), bestEntry->_size); 100 } 101 102 for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) { 103 if (!(*entry)->_data) { 104 (*entry)->_packName = packName; 105 (*entry)->_fileName = fileName; 106 (*entry)->_age = 0; 107 (*entry)->_size = fileSize; 108 (*entry)->_data = fileData; 109 return; 110 } 111 } 112 113 CacheEntry *entry = new CacheEntry(); 114 entry->_packName = packName; 115 entry->_fileName = fileName; 116 entry->_size = fileSize; 117 entry->_data = fileData; 118 _resourceCache.push_back(entry); 119 } 120 121 void Resources::openPackage(Common::String fileName) { 122 debugC(1, kDebugResource, "openPackage(%s)", fileName.c_str()); 50 123 51 124 Common::File file; 52 125 bool opened = file.open(fileName); … … void Resources::openPackage(Common::String fileName, bool preloadEntirePackage) 55 128 return; 56 129 57 130 PakFile *pakFile = new PakFile(); 58 pakFile->open(&file, fileName, preloadEntirePackage); 59 60 if (preloadEntirePackage) 61 file.close(); 131 pakFile->open(&file, fileName); 62 132 133 file.close(); 63 134 _pakFiles.push_back(pakFile); 64 135 } 65 136 66 137 void Resources::closePackage(Common::String fileName) { 138 removePackageFromCache(fileName); 67 139 for (uint32 i = 0; i < _pakFiles.size(); i++) { 68 140 if (_pakFiles[i]->getPackName() == fileName) { 69 141 delete _pakFiles[i]; … … uint8 *Resources::getFileData(Common::String fileName, uint32 *fileSize) { 91 163 _allocatedFileData.push_back(memory); 92 164 return memory; 93 165 } else { 94 for (uint32 i = 0; i < _pakFiles.size(); i++) { 95 uint32 locFileSize = 0; 96 uint8 *locFileData = 0; 166 uint32 locFileSize = 0; 167 uint8 *locFileData = 0; 97 168 169 if (getFromCache(fileName, &locFileSize, &locFileData)) { 170 *fileSize = locFileSize; 171 return locFileData; 172 } 173 174 for (uint32 i = 0; i < _pakFiles.size(); i++) { 98 175 locFileData = _pakFiles[i]->getFileData(fileName, &locFileSize); 99 176 if (locFileData) { 100 177 *fileSize = locFileSize; 178 addToCache(_pakFiles[i]->getPackName(), fileName, locFileSize, locFileData); 101 179 return locFileData; 102 180 } 103 181 } … … void Resources::purgeFileData() { 136 214 } 137 215 _allocatedFileData.clear(); 138 216 } 217 139 218 Common::SeekableReadStream *PakFile::createReadStream(Common::String fileName) { 140 219 debugC(1, kDebugResource, "createReadStream(%s)", fileName.c_str()); 141 220 142 int32 offset = 0; 143 int32 size = 0; 144 for (uint32 i = 0; i < _numFiles; i++) { 145 if (fileName.compareToIgnoreCase(_files[i]._name) == 0) { 146 size = _files[i]._size; 147 offset = _files[i]._offset; 148 break; 149 } 150 } 151 if (!size) 152 return 0; 221 uint32 fileSize = 0; 222 uint8 *buffer = getFileData(fileName, &fileSize); 153 223 154 if ( _fileHandle)155 return new Common:: SeekableSubReadStream(_fileHandle, offset, offset + size);224 if (buffer) 225 return new Common::MemoryReadStream(buffer, fileSize, DisposeAfterUse::YES); 156 226 else 157 return new Common::MemoryReadStream(_buffer + offset, size);227 return 0; 158 228 } 159 229 160 230 uint8 *PakFile::getFileData(Common::String fileName, uint32 *fileSize) { … … uint8 *PakFile::getFileData(Common::String fileName, uint32 *fileSize) { 162 232 163 233 for (uint32 i = 0; i < _numFiles; i++) { 164 234 if (fileName.compareToIgnoreCase(_files[i]._name) == 0) { 165 *fileSize = _files[i]._size; 166 return _buffer + _files[i]._offset; 235 Common::File file; 236 237 if (file.open(_packName)) { 238 *fileSize = _files[i]._size; 239 file.seek(_files[i]._offset); 240 241 // Use malloc() because that's what MemoryReadStream 242 // uses to dispose of the memory when it's done. 243 uint8 *buffer = (uint8 *)malloc(*fileSize); 244 file.read(buffer, *fileSize); 245 file.close(); 246 return buffer; 247 } 167 248 } 168 249 } 169 250 170 251 return 0; 171 252 } 172 253 173 void PakFile::open(Common::SeekableReadStream *rs, Common::String packName , bool preloadEntirePackage) {174 debugC(1, kDebugResource, "open(rs , %d)", (preloadEntirePackage) ? 1 : 0);254 void PakFile::open(Common::SeekableReadStream *rs, Common::String packName) { 255 debugC(1, kDebugResource, "open(rs)"); 175 256 176 257 char buffer[64]; 177 258 int32 currentPos = 0; … … void PakFile::open(Common::SeekableReadStream *rs, Common::String packName, bool 199 280 _numFiles++; 200 281 _files.push_back(newFile); 201 282 } 202 203 if (preloadEntirePackage) {204 _bufferSize = rs->size();205 delete[] _buffer;206 _buffer = new uint8[_bufferSize];207 rs->seek(0);208 rs->read(_buffer, _bufferSize);209 }210 283 } 211 284 212 285 void PakFile::close() { 213 delete[] _buffer;214 215 if (_fileHandle) {216 _fileHandle->close();217 delete _fileHandle;218 }219 286 } 220 287 221 288 PakFile::PakFile() { 222 _bufferSize = 0;223 _buffer = NULL;224 225 _fileHandle = NULL;226 289 } 227 290 228 291 PakFile::~PakFile() { -
engines/toon/resource.h
diff --git a/engines/toon/resource.h b/engines/toon/resource.h index e117c8e..590dfcd 100644
a b 31 31 #include "common/file.h" 32 32 #include "common/stream.h" 33 33 34 #define MAX_CACHE_SIZE (2 * 1024 * 1024) 35 34 36 namespace Toon { 35 37 36 38 class PakFile { … … public: 38 40 PakFile(); 39 41 ~PakFile(); 40 42 41 void open(Common::SeekableReadStream *rs, Common::String packName , bool preloadEntirePackage);43 void open(Common::SeekableReadStream *rs, Common::String packName); 42 44 uint8 *getFileData(Common::String fileName, uint32 *fileSize); 43 45 Common::String getPackName() { return _packName; } 44 46 Common::SeekableReadStream *createReadStream(Common::String fileName); … … protected: 52 54 }; 53 55 Common::String _packName; 54 56 55 uint8 *_buffer;56 int32 _bufferSize;57 58 57 uint32 _numFiles; 59 58 Common::Array<File> _files; 60 59 Common::File *_fileHandle; … … protected: 62 61 63 62 class ToonEngine; 64 63 64 class CacheEntry { 65 public: 66 CacheEntry() : _age(0), _size(0), _data(0) {} 67 ~CacheEntry() { 68 free(_data); 69 } 70 71 Common::String _packName; 72 Common::String _fileName; 73 uint32 _age; 74 uint32 _size; 75 uint8 *_data; 76 }; 77 65 78 class Resources { 66 79 public: 67 80 Resources(ToonEngine *vm); 68 81 ~Resources(); 69 void openPackage(Common::String file , bool preloadEntirePackage);82 void openPackage(Common::String file); 70 83 void closePackage(Common::String fileName); 71 84 Common::SeekableReadStream *openFile(Common::String file); 72 85 uint8 *getFileData(Common::String fileName, uint32 *fileSize); // this memory must be copied to your own structures! … … protected: 76 89 ToonEngine *_vm; 77 90 Common::Array<uint8 *> _allocatedFileData; 78 91 Common::Array<PakFile *> _pakFiles; 92 uint32 _cacheSize; 93 Common::Array<CacheEntry *> _resourceCache; 94 95 void removePackageFromCache(Common::String packName); 96 bool getFromCache(Common::String fileName, uint32 *fileSize, uint8 **fileData); 97 void addToCache(Common::String packName, Common::String fileName, uint32 fileSize, uint8 *fileData); 79 98 }; 80 99 81 100 } // End of namespace Toon -
engines/toon/toon.cpp
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp index d65230d..a6cb8a7 100644
a b void ToonEngine::init() { 106 106 107 107 _pathFinding = new PathFinding(this); 108 108 109 resources()->openPackage("LOCAL.PAK" , true);110 resources()->openPackage("ONETIME.PAK" , true);111 resources()->openPackage("DREW.PAK" , true);109 resources()->openPackage("LOCAL.PAK"); 110 resources()->openPackage("ONETIME.PAK"); 111 resources()->openPackage("DREW.PAK"); 112 112 113 113 for (int32 i = 0; i < 32; i++) 114 114 _characters[i] = NULL; … … void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) { 1080 1080 1081 1081 // load package 1082 1082 strcpy(temp, createRoomFilename(Common::String::format("%s.PAK", _gameState->_locations[_gameState->_currentScene]._name).c_str()).c_str()); 1083 resources()->openPackage(temp , true);1083 resources()->openPackage(temp); 1084 1084 1085 1085 strcpy(temp, state()->_locations[SceneId]._name); 1086 1086 strcat(temp, ".NPP");