1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "common/substream.h"
24 #include "access/files.h"
25 #include "access/amazon/amazon_resources.h"
26 #include "access/martian/martian_resources.h"
27 #include "access/access.h"
28
29 namespace Access {
30
FileIdent()31 FileIdent::FileIdent() {
32 _fileNum = -1;
33 _subfile = 0;
34 }
35
load(Common::SeekableReadStream & s)36 void FileIdent::load(Common::SeekableReadStream &s) {
37 _fileNum = s.readSint16LE();
38 _subfile = s.readUint16LE();
39 }
40
41 /*------------------------------------------------------------------------*/
42
CellIdent()43 CellIdent:: CellIdent() {
44 _cell = 0;
45 }
46
CellIdent(int cell,int fileNum,int subfile)47 CellIdent::CellIdent(int cell, int fileNum, int subfile) {
48 _cell = cell;
49 _fileNum = fileNum;
50 _subfile = subfile;
51 }
52
53 /*------------------------------------------------------------------------*/
54
Resource()55 Resource::Resource() {
56 _stream = nullptr;
57 _size = 0;
58 _data = nullptr;
59 }
60
~Resource()61 Resource::~Resource() {
62 delete[] _data;
63 delete _stream;
64 }
65
Resource(byte * p,int size)66 Resource::Resource(byte *p, int size) {
67 _data = p;
68 _size = size;
69 _stream = new Common::MemoryReadStream(p, size);
70 }
71
data()72 byte *Resource::data() {
73 if (_data == nullptr) {
74 _data = new byte[_size];
75 int pos = _stream->pos();
76 _stream->seek(0);
77 _stream->read(_data, _size);
78 _stream->seek(pos);
79 }
80
81 return _data;
82 }
83
84 /*------------------------------------------------------------------------*/
85
FileManager(AccessEngine * vm)86 FileManager::FileManager(AccessEngine *vm) : _vm(vm) {
87 _fileNumber = -1;
88 _setPaletteFlag = true;
89 }
90
~FileManager()91 FileManager::~FileManager() {
92 }
93
loadFile(int fileNum,int subfile)94 Resource *FileManager::loadFile(int fileNum, int subfile) {
95 Resource *res = new Resource();
96 setAppended(res, fileNum);
97 gotoAppended(res, subfile);
98
99 handleFile(res);
100 return res;
101 }
102
loadFile(const FileIdent & fileIdent)103 Resource *FileManager::loadFile(const FileIdent &fileIdent) {
104 return loadFile(fileIdent._fileNum, fileIdent._subfile);
105 }
106
loadFile(const Common::String & filename)107 Resource *FileManager::loadFile(const Common::String &filename) {
108 Resource *res = new Resource();
109
110 // Open the file
111 openFile(res, filename);
112
113 // Set up stream for the entire file
114 res->_size = res->_file.size();
115 res->_stream = res->_file.readStream(res->_size);
116
117 handleFile(res);
118 return res;
119 }
120
existFile(const Common::String & filename)121 bool FileManager::existFile(const Common::String &filename) {
122 Common::File f;
123 return f.exists(filename);
124 }
125
openFile(Resource * res,const Common::String & filename)126 void FileManager::openFile(Resource *res, const Common::String &filename) {
127 // Open up the file
128 _fileNumber = -1;
129 if (!res->_file.open(filename))
130 error("Could not open file - %s", filename.c_str());
131 }
132
loadScreen(Graphics::ManagedSurface * dest,int fileNum,int subfile)133 void FileManager::loadScreen(Graphics::ManagedSurface *dest, int fileNum, int subfile) {
134 Resource *res = loadFile(fileNum, subfile);
135 handleScreen(dest, res);
136 delete res;
137 }
138
handleScreen(Graphics::ManagedSurface * dest,Resource * res)139 void FileManager::handleScreen(Graphics::ManagedSurface *dest, Resource *res) {
140 _vm->_screen->loadRawPalette(res->_stream);
141 if (_setPaletteFlag)
142 _vm->_screen->setPalette();
143 _setPaletteFlag = true;
144
145 // The remainder of the file after the palette may be separately compressed,
146 // so call handleFile to handle it if it is
147 res->_size -= res->_stream->pos();
148 handleFile(res);
149
150 Graphics::Surface destSurface = dest->getSubArea(Common::Rect(0, 0,
151 _vm->_screen->w, _vm->_screen->h));
152
153 if (destSurface.w == destSurface.pitch) {
154 res->_stream->read((byte *)destSurface.getPixels(), destSurface.w * destSurface.h);
155 } else {
156 for (int y = 0; y < destSurface.h; ++y) {
157 byte *pDest = (byte *)destSurface.getBasePtr(0, y);
158 res->_stream->read(pDest, destSurface.w);
159 }
160 }
161 }
162
loadScreen(int fileNum,int subfile)163 void FileManager::loadScreen(int fileNum, int subfile) {
164 loadScreen(_vm->_screen, fileNum, subfile);
165 }
166
loadScreen(const Common::String & filename)167 void FileManager::loadScreen(const Common::String &filename) {
168 Resource *res = loadFile(filename);
169 handleScreen(_vm->_screen, res);
170 delete res;
171 }
172
handleFile(Resource * res)173 void FileManager::handleFile(Resource *res) {
174 char header[3];
175 res->_stream->read(&header[0], 3);
176 res->_stream->seek(-3, SEEK_CUR);
177
178 bool isCompressed = !strncmp(header, "DBE", 3);
179
180 // If the data is compressed, uncompress it and replace the stream
181 // in the resource with the decompressed one
182 if (isCompressed) {
183 // Read in the entire compressed data
184 byte *src = new byte[res->_size];
185 res->_stream->read(src, res->_size);
186
187 // Decompress the data
188 res->_size = decompressDBE(src, &res->_data);
189
190 // Replace the default resource stream with a stream for the decompressed data
191 delete res->_stream;
192 res->_file.close();
193 res->_stream = new Common::MemoryReadStream(res->_data, res->_size);
194
195 delete[] src;
196 }
197 }
198
setAppended(Resource * res,int fileNum)199 void FileManager::setAppended(Resource *res, int fileNum) {
200 // Open the file for access
201 if (!res->_file.open(_vm->_res->FILENAMES[fileNum]))
202 error("Could not open file %s", _vm->_res->FILENAMES[fileNum].c_str());
203
204 // If a different file has been opened then previously, load its index
205 if (_fileNumber != fileNum) {
206 _fileNumber = fileNum;
207
208 // Read in the file index
209 int count = res->_file.readUint16LE();
210 assert(count <= 100);
211 _fileIndex.resize(count);
212 for (int i = 0; i < count; ++i)
213 _fileIndex[i] = res->_file.readUint32LE();
214 }
215 }
216
gotoAppended(Resource * res,int subfile)217 void FileManager::gotoAppended(Resource *res, int subfile) {
218 uint32 offset = _fileIndex[subfile];
219 uint32 size = (subfile == (int)_fileIndex.size() - 1) ? res->_file.size() - offset :
220 _fileIndex[subfile + 1] - offset;
221
222 res->_size = size;
223 res->_stream = new Common::SeekableSubReadStream(&res->_file, offset, offset + size);
224 }
225
226 } // End of namespace Access
227