diff options
author | Thanasis Antoniou | 2019-06-20 03:43:43 +0300 |
---|---|---|
committer | Thanasis Antoniou | 2019-06-20 10:12:16 +0300 |
commit | e6c61ff67b8600fa2cc7d7f894d96fec0d99a11a (patch) | |
tree | 541388822553484ed72640c8e7ddc7a3d46d51b3 | |
parent | 0f9abb8e62ba5b031579129e04989c07f139b5f4 (diff) | |
download | scummvm-rg350-e6c61ff67b8600fa2cc7d7f894d96fec0d99a11a.tar.gz scummvm-rg350-e6c61ff67b8600fa2cc7d7f894d96fec0d99a11a.tar.bz2 scummvm-rg350-e6c61ff67b8600fa2cc7d7f894d96fec0d99a11a.zip |
BLADERUNNER: Fix crash in restored mode with CDFRAMESx.DAT
-rw-r--r-- | engines/bladerunner/slice_animations.cpp | 103 | ||||
-rw-r--r-- | engines/bladerunner/slice_animations.h | 7 |
2 files changed, 83 insertions, 27 deletions
diff --git a/engines/bladerunner/slice_animations.cpp b/engines/bladerunner/slice_animations.cpp index f4fc134e8f..15a5a5079e 100644 --- a/engines/bladerunner/slice_animations.cpp +++ b/engines/bladerunner/slice_animations.cpp @@ -86,17 +86,27 @@ bool SliceAnimations::open(const Common::String &name) { SliceAnimations::~SliceAnimations() { for (uint32 i = 0; i != _pages.size(); ++i) free(_pages[i]._data); + + // close open files + _coreAnimPageFile.close(0); + if (!_vm->_cutContent) { + _framesPageFile.close(_framesPageFile._fileNumber); + } else { + for (uint i = 0; i < 5; ++i) { + _framesPageFile.close(i); + } + } } bool SliceAnimations::openCoreAnim() { - return _coreAnimPageFile.open("COREANIM.DAT"); + return _coreAnimPageFile.open("COREANIM.DAT", 0); } bool SliceAnimations::openFrames(int fileNumber) { if (_framesPageFile._fileNumber == -1) { // Running for the first time, need to probe // First, try HDFRAMES.DAT - if (_framesPageFile.open("HDFRAMES.DAT")) { + if (_framesPageFile.open("HDFRAMES.DAT", 0)) { _framesPageFile._fileNumber = 0; return true; @@ -108,43 +118,82 @@ bool SliceAnimations::openFrames(int fileNumber) { if (_framesPageFile._fileNumber == 0) // HDFRAMES.DAT return true; - if (_framesPageFile._fileNumber == fileNumber) + if (!_vm->_cutContent && _framesPageFile._fileNumber == fileNumber) return true; - _framesPageFile.close(); - - _framesPageFile._fileNumber = fileNumber; - - if (fileNumber == 1 && _framesPageFile.open("CDFRAMES.DAT")) {// For Chapter1 we try both CDFRAMES.DAT and CDFRAMES1.DAT + if (_vm->_cutContent && _framesPageFile._fileNumber == 5) // all frame files loaded return true; - } - if (_framesPageFile.open(Common::String::format("CDFRAMES%d.DAT", fileNumber))) { + if (!_vm->_cutContent) { + // _fileNumber can normally be in [1,4] + // but it will be "5" if we switched from restored content to original + if (_framesPageFile._fileNumber == 5) { + for (uint i = 1; i < 5; ++i) { + _framesPageFile.close(i); + } + } else if (_framesPageFile._fileNumber > 0) { + _framesPageFile.close(_framesPageFile._fileNumber); + } + _framesPageFile._fileNumber = fileNumber; + // For Chapter1 we try both CDFRAMES.DAT and CDFRAMES1.DAT + if (fileNumber == 1 && _framesPageFile.open("CDFRAMES.DAT", fileNumber)) { + return true; + } + + if (_framesPageFile.open(Common::String::format("CDFRAMES%d.DAT", fileNumber), fileNumber)) { + return true; + } + } else { + // Restored cut content case + // open all four CDFRAMESx.DAT files in slots [1,5] + // So that all animation resources are available at all times as if we just had the single HDFRAMES.DAT file + for (uint i = 1; i < 5; ++i) { + _framesPageFile.close(i); + if (i == 1 + && (!_framesPageFile.open("CDFRAMES.DAT", i)) + && (!_framesPageFile.open(Common::String::format("CDFRAMES%d.DAT", i), i)) + ) { + // For Chapter1 we try both CDFRAMES.DAT and CDFRAMES1.DAT + return false; + } else if(i != 1 && + !_framesPageFile.open(Common::String::format("CDFRAMES%d.DAT", i), i) + ) { + return false; + } + } + _framesPageFile._fileNumber = 5; return true; } return false; } -bool SliceAnimations::PageFile::open(const Common::String &name) { - if (!_file.open(name)) +bool SliceAnimations::PageFile::open(const Common::String &name, int8 fileIdx) { + if (!_files[fileIdx].open(name)) return false; - uint32 timestamp = _file.readUint32LE(); + uint32 timestamp = _files[fileIdx].readUint32LE(); if (timestamp != _sliceAnimations->_timestamp) return false; - _pageOffsets.resize(_sliceAnimations->_pageCount); - for (uint32 i = 0; i != _sliceAnimations->_pageCount; ++i) - _pageOffsets[i] = -1; + if (!_sliceAnimations->_vm->_cutContent + || (_pageOffsets.size() < _sliceAnimations->_pageCount) ){ + _pageOffsets.resize(_sliceAnimations->_pageCount); + _pageOffsetsFileIdx.resize(_sliceAnimations->_pageCount); + for (uint32 i = 0; i != _sliceAnimations->_pageCount; ++i) { + _pageOffsets[i] = -1; + _pageOffsetsFileIdx[i] = -1; + } + } - uint32 pageCount = _file.readUint32LE(); + uint32 pageCount = _files[fileIdx].readUint32LE(); uint32 dataOffset = 8 + 4 * pageCount; for (uint32 i = 0; i != pageCount; ++i) { - uint32 pageNumber = _file.readUint32LE(); + uint32 pageNumber = _files[fileIdx].readUint32LE(); if (pageNumber == 0xffffffff) continue; _pageOffsets[pageNumber] = dataOffset + i * _sliceAnimations->_pageSize; + _pageOffsetsFileIdx[pageNumber] = fileIdx; } // debug(5, "PageFile::Open: page file \"%s\" opened with %d pages", name.c_str(), pageCount); @@ -152,23 +201,29 @@ bool SliceAnimations::PageFile::open(const Common::String &name) { return true; } -void SliceAnimations::PageFile::close() { - if (_file.isOpen()) { - _file.close(); +void SliceAnimations::PageFile::close(int8 fileIdx) { + if (fileIdx >= 0 && fileIdx < 5) { + if (_files[fileIdx].isOpen()) { + _files[fileIdx].close(); + } } } void *SliceAnimations::PageFile::loadPage(uint32 pageNumber) { - if (_pageOffsets[pageNumber] == -1) + if (_pageOffsets.size() < _sliceAnimations->_pageCount + || _pageOffsetsFileIdx.size() < _sliceAnimations->_pageCount + || _pageOffsets[pageNumber] == -1 + || _pageOffsetsFileIdx[pageNumber] == -1) { return nullptr; + } uint32 pageSize = _sliceAnimations->_pageSize; // TODO: Retire oldest pages if we exceed some memory limit void *data = malloc(pageSize); - _file.seek(_pageOffsets[pageNumber], SEEK_SET); - uint32 r = _file.read(data, pageSize); + _files[_pageOffsetsFileIdx[pageNumber]].seek(_pageOffsets[pageNumber], SEEK_SET); + uint32 r = _files[_pageOffsetsFileIdx[pageNumber]].read(data, pageSize); assert(r == pageSize); return data; diff --git a/engines/bladerunner/slice_animations.h b/engines/bladerunner/slice_animations.h index 0732e596ea..79dd6462ee 100644 --- a/engines/bladerunner/slice_animations.h +++ b/engines/bladerunner/slice_animations.h @@ -66,13 +66,14 @@ class SliceAnimations { struct PageFile { int _fileNumber; SliceAnimations *_sliceAnimations; - Common::File _file; + Common::File _files[5]; Common::Array<int32> _pageOffsets; + Common::Array<int8> _pageOffsetsFileIdx; PageFile(SliceAnimations *sliceAnimations) : _sliceAnimations(sliceAnimations), _fileNumber(-1) {} - bool open(const Common::String &name); - void close(); + bool open(const Common::String &name, int8 fileIdx); + void close(int8 fileIdx); void *loadPage(uint32 page); }; |