ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

packfile.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "common/endian.h"
00024 #include "common/stream.h"
00025 
00026 #include "engines/grim/update/packfile.h"
00027 
00028 namespace Grim {
00029 
00030 const uint32 PackFile::_knownOffsets[] = { 0x1c000, 0x21000, 0x23000, 0x24000, 0 };
00031 
00032 PackFile::PackFile(Common::SeekableReadStream *data):
00033     _codeTable(nullptr), _orgStream(data), _offset(0), _kCodeTableSize(0x100) {
00034 
00035     uint32 magicContainer, magicCabinet, key;
00036 
00037     for (int i = 0; _knownOffsets[i] != 0; ++i) {
00038         if (_knownOffsets[i] > uint32(_orgStream->size()))
00039             continue;
00040 
00041         _orgStream->seek(_knownOffsets[i]);
00042 
00043         //Check for content signature
00044         magicContainer = _orgStream->readUint32BE();
00045         if (!err() && magicContainer == MKTAG('1','C','N','T')) {
00046             key = _orgStream->readUint32LE();
00047             createCodeTable(key);
00048             _offset = _orgStream->pos();
00049 
00050             //Check for cabinet signature
00051             magicCabinet = readUint32BE();
00052             if (!err() && magicCabinet == MKTAG('M','S','C','F'))
00053                 break;
00054             else {
00055                 delete[] _codeTable;
00056                 _codeTable = nullptr;
00057                 _offset = 0;
00058                 continue;
00059             }
00060         }
00061     }
00062 
00063     _size = _orgStream->size() - _offset;
00064     _orgStream->seek(_offset);
00065 }
00066 
00067 
00068 PackFile::~PackFile() {
00069     delete[] _codeTable;
00070 
00071     delete _orgStream;
00072 }
00073 
00074 bool PackFile::err() const {
00075     return _orgStream->err();
00076 }
00077 
00078 void PackFile::clearErr() {
00079     _orgStream->clearErr();
00080 }
00081 
00082 void PackFile::createCodeTable(uint32 key) {
00083     const uint32 kRandA = 0x343FD;
00084     const uint32 kRandB = 0x269EC3;
00085     uint32 value = key;
00086 
00087     delete[] _codeTable;
00088     _codeTable = new uint16[_kCodeTableSize * 2];
00089 
00090     for (uint i = 0; i < _kCodeTableSize; i++) {
00091         value = kRandA * value + kRandB;
00092         _codeTable[i] = uint16((value >> 16) & 0x7FFF);
00093     }
00094 }
00095 
00096 void PackFile::decode(uint8 *data, uint32 dataSize, uint32 start_point) {
00097     for (uint32 i = 0; i < dataSize; i++) {
00098         data[i] ^= uint8(_codeTable[(i + start_point) % _kCodeTableSize]);
00099         data[i] -= uint8(_codeTable[(i + start_point) % _kCodeTableSize] >> 8);
00100     }
00101 }
00102 
00103 uint32 PackFile::read(void *dataPtr, uint32 dataSize) {
00104     uint32 start_point, count;
00105 
00106     start_point = uint32(pos());
00107     count = _orgStream->read(dataPtr, dataSize);
00108 
00109     if (err() || count != dataSize)
00110         return 0;
00111 
00112     if (_codeTable)
00113         decode((uint8*)dataPtr, count, start_point);
00114 
00115     return count;
00116 }
00117 
00118 bool PackFile::eos() const {
00119     return _orgStream->eos();
00120 }
00121 
00122 int32 PackFile::pos() const {
00123     return _orgStream->pos() - _offset;
00124 }
00125 
00126 int32 PackFile::size() const {
00127     return _size;
00128 }
00129 
00130 bool PackFile::seek(int32 offset, int whence) {
00131     if (_codeTable && whence == SEEK_SET)
00132         offset += _offset;
00133     return _orgStream->seek(offset, whence);
00134 }
00135 
00136 } // end of namespace Grim


Generated on Sat Feb 23 2019 05:01:13 for ResidualVM by doxygen 1.7.1
curved edge   curved edge