aboutsummaryrefslogtreecommitdiff
path: root/engines/sherlock/resources.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sherlock/resources.cpp')
-rw-r--r--engines/sherlock/resources.cpp326
1 files changed, 113 insertions, 213 deletions
diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp
index 2e6a0c2d7c..c4093048bd 100644
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@ -64,7 +64,7 @@ void Cache::load(const Common::String &name, Common::SeekableReadStream &stream)
// Check whether the file is compressed
if (signature == MKTAG('L', 'Z', 'V', 26)) {
- // It's compressed, so decompress the file and store it's data in the cache entry
+ // It's compressed, so decompress the file and store its data in the cache entry
Common::SeekableReadStream *decompressed = _vm->_res->decompress(stream);
cacheEntry.resize(decompressed->size());
decompressed->read(&cacheEntry[0], decompressed->size());
@@ -89,18 +89,37 @@ Resources::Resources(SherlockEngine *vm) : _vm(vm), _cache(vm) {
_resourceIndex = -1;
if (_vm->_interactiveFl) {
- addToCache("vgs.lib");
- addToCache("talk.lib");
- addToCache("journal.txt");
+ if (!IS_3DO) {
+ addToCache("vgs.lib");
+ addToCache("talk.lib");
+ addToCache("journal.txt");
+
+ if (IS_SERRATED_SCALPEL) {
+ addToCache("sequence.txt");
+ addToCache("portrait.lib");
+ } else {
+ addToCache("walk.lib");
+ }
+ } else {
+ // 3DO
- if (IS_SERRATED_SCALPEL) {
- addToCache("sequence.txt");
- addToCache("portrait.lib");
+ // ITEM data from VGS.LIB is in ITEM.LIB
+ addToCache("item.lib");
+
+ // talk.lib - resources themselves seem to be the same, although a few texts were slightly changed
+ addToCache("talk.lib");
+
+ // remaining files are missing
+ // portraits were replaced with FMV
}
}
}
void Resources::addToCache(const Common::String &filename) {
+ // Return immediately if the library has already been loaded
+ if (_indexes.contains(filename))
+ return;
+
_cache.load(filename);
// Check to see if the file is a library
@@ -176,16 +195,27 @@ void Resources::decompressIfNecessary(Common::SeekableReadStream *&stream) {
}
}
-Common::SeekableReadStream *Resources::load(const Common::String &filename, const Common::String &libraryFile) {
+Common::SeekableReadStream *Resources::load(const Common::String &filename, const Common::String &libraryFile,
+ bool suppressErrors) {
// Open up the library for access
Common::SeekableReadStream *libStream = load(libraryFile);
- // Check if the library has already had it's index read, and if not, load it
+ // Check if the library has already had its index read, and if not, load it
if (!_indexes.contains(libraryFile))
loadLibraryIndex(libraryFile, libStream, false);
+ LibraryIndex &libIndex = _indexes[libraryFile];
+
+ // Handle if resource is not present
+ if (!libIndex.contains(filename)) {
+ if (!suppressErrors)
+ error("Could not find resource - %s", filename.c_str());
+
+ delete libStream;
+ return nullptr;
+ }
// Extract the data for the specified resource and return it
- LibraryEntry &entry = _indexes[libraryFile][filename];
+ LibraryEntry &entry = libIndex[filename];
libStream->seek(entry._offset);
Common::SeekableReadStream *stream = libStream->readStream(entry._size);
decompressIfNecessary(stream);
@@ -203,38 +233,80 @@ void Resources::loadLibraryIndex(const Common::String &libFilename,
Common::SeekableReadStream *stream, bool isNewStyle) {
uint32 offset, nextOffset;
+ // Return immediately if the library has already been loaded
+ if (_indexes.contains(libFilename))
+ return;
+
// Create an index entry
_indexes[libFilename] = LibraryIndex();
LibraryIndex &index = _indexes[libFilename];
// Read in the number of resources
stream->seek(4);
- int count = stream->readUint16LE();
+ int count = 0;
- if (isNewStyle)
- stream->seek((count + 1) * 8, SEEK_CUR);
+ if (!IS_3DO) {
+ // PC
+ count = stream->readUint16LE();
- // Loop through reading in the entries
- for (int idx = 0; idx < count; ++idx) {
- // Read the name of the resource
- char resName[13];
- stream->read(resName, 13);
- resName[12] = '\0';
+ if (isNewStyle)
+ stream->seek((count + 1) * 8, SEEK_CUR);
- // Read the offset
- offset = stream->readUint32LE();
+ // Loop through reading in the entries
+ for (int idx = 0; idx < count; ++idx) {
+ // Read the name of the resource
+ char resName[13];
+ stream->read(resName, 13);
+ resName[12] = '\0';
- if (idx == (count - 1)) {
- nextOffset = stream->size();
- } else {
- // Read the size by jumping forward to read the next entry's offset
- stream->seek(13, SEEK_CUR);
- nextOffset = stream->readUint32LE();
- stream->seek(-17, SEEK_CUR);
+ // Read the offset
+ offset = stream->readUint32LE();
+
+ if (idx == (count - 1)) {
+ nextOffset = stream->size();
+ } else {
+ // Read the size by jumping forward to read the next entry's offset
+ stream->seek(13, SEEK_CUR);
+ nextOffset = stream->readUint32LE();
+ stream->seek(-17, SEEK_CUR);
+ }
+
+ // Add the entry to the index
+ index[resName] = LibraryEntry(idx, offset, nextOffset - offset);
}
- // Add the entry to the index
- index[resName] = LibraryEntry(idx, offset, nextOffset - offset);
+ } else {
+ // 3DO
+ count = stream->readUint16BE();
+
+ // 3DO header
+ // Loop through reading in the entries
+
+ // Read offset of first entry
+ offset = stream->readUint32BE();
+
+ for (int idx = 0; idx < count; ++idx) {
+
+ // Read the name of the resource
+ char resName[13];
+ stream->read(resName, 13);
+ resName[12] = '\0';
+
+ stream->skip(3); // filler
+
+ if (idx == (count - 1)) {
+ nextOffset = stream->size();
+ } else {
+ // Read the offset of the next entry
+ nextOffset = stream->readUint32BE();
+ }
+
+ // Add the entry to the index
+ index[resName] = LibraryEntry(idx, offset, nextOffset - offset);
+
+ // use next offset as current offset
+ offset = nextOffset;
+ }
}
}
@@ -242,10 +314,18 @@ int Resources::resourceIndex() const {
return _resourceIndex;
}
+void Resources::getResourceNames(const Common::String &libraryFile, Common::StringArray &names) {
+ addToCache(libraryFile);
+ LibraryIndex &libIndex = _indexes[libraryFile];
+ for (LibraryIndex::iterator i = libIndex.begin(); i != libIndex.end(); ++i) {
+ names.push_back(i->_key);
+ }
+}
+
Common::SeekableReadStream *Resources::decompress(Common::SeekableReadStream &source) {
// This variation can't be used by Rose Tattoo, since compressed resources include the input size,
// not the output size. Which means their decompression has to be done via passed buffers
- assert(_vm->getGameID() == GType_SerratedScalpel);
+ assert(IS_SERRATED_SCALPEL);
uint32 id = source.readUint32BE();
assert(id == MKTAG('L', 'Z', 'V', 0x1A));
@@ -255,7 +335,7 @@ Common::SeekableReadStream *Resources::decompress(Common::SeekableReadStream &so
}
Common::SeekableReadStream *Resources::decompress(Common::SeekableReadStream &source, uint32 outSize) {
- int inSize = (_vm->getGameID() == GType_RoseTattoo) ? source.readSint32LE() : -1;
+ int inSize = IS_ROSE_TATTOO ? source.readSint32LE() : -1;
byte *outBuffer = (byte *)malloc(outSize);
Common::MemoryReadStream *outStream = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
@@ -265,7 +345,7 @@ Common::SeekableReadStream *Resources::decompress(Common::SeekableReadStream &so
}
void Resources::decompress(Common::SeekableReadStream &source, byte *buffer, uint32 outSize) {
- int inputSize = (_vm->getGameID() == GType_RoseTattoo) ? source.readSint32LE() : -1;
+ int inputSize = IS_ROSE_TATTOO ? source.readSint32LE() : -1;
decompressLZ(source, buffer, outSize, inputSize);
}
@@ -316,184 +396,4 @@ void Resources::decompressLZ(Common::SeekableReadStream &source, byte *outBuffer
} while ((outSize == -1 || outBuffer < outBufferEnd) && (inSize == -1 || source.pos() < endPos));
}
-/*----------------------------------------------------------------*/
-
-SherlockEngine *ImageFile::_vm;
-
-void ImageFile::setVm(SherlockEngine *vm) {
- _vm = vm;
-}
-
-ImageFile::ImageFile(const Common::String &name, bool skipPal, bool animImages) {
- Common::SeekableReadStream *stream = _vm->_res->load(name);
-
- Common::fill(&_palette[0], &_palette[PALETTE_SIZE], 0);
- load(*stream, skipPal, animImages);
-
- delete stream;
-}
-
-ImageFile::ImageFile(Common::SeekableReadStream &stream, bool skipPal) {
- Common::fill(&_palette[0], &_palette[PALETTE_SIZE], 0);
- load(stream, skipPal, false);
-}
-
-ImageFile::~ImageFile() {
- for (uint idx = 0; idx < size(); ++idx)
- (*this)[idx]._frame.free();
-}
-
-void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette, bool animImages) {
- loadPalette(stream);
-
- int streamSize = stream.size();
- while (stream.pos() < streamSize) {
- ImageFrame frame;
- frame._width = stream.readUint16LE() + 1;
- frame._height = stream.readUint16LE() + 1;
- frame._paletteBase = stream.readByte();
-
- if (animImages) {
- // Animation cutscene image files use a 16-bit x offset
- frame._offset.x = stream.readUint16LE();
- frame._rleEncoded = (frame._offset.x & 0xff) == 1;
- frame._offset.y = stream.readByte();
- } else {
- // Standard image files have a separate byte for the RLE flag, and an 8-bit X offset
- frame._rleEncoded = stream.readByte() == 1;
- frame._offset.x = stream.readByte();
- frame._offset.y = stream.readByte();
- }
-
- frame._rleEncoded = !skipPalette && frame._rleEncoded;
-
- if (frame._paletteBase) {
- // Nibble packed frame data
- frame._size = (frame._width * frame._height) / 2;
- } else if (frame._rleEncoded) {
- // This size includes the header size, which we subtract
- frame._size = stream.readUint16LE() - 11;
- frame._rleMarker = stream.readByte();
- } else {
- // Uncompressed data
- frame._size = frame._width * frame._height;
- }
-
- // Load data for frame and decompress it
- byte *data = new byte[frame._size];
- stream.read(data, frame._size);
- decompressFrame(frame, data);
- delete[] data;
-
- push_back(frame);
- }
-}
-
-void ImageFile::loadPalette(Common::SeekableReadStream &stream) {
- // Check for palette
- int v1 = stream.readUint16LE() + 1;
- int v2 = stream.readUint16LE() + 1;
- stream.skip(1); // Skip paletteBase byte
- bool rleEncoded = stream.readByte() == 1;
- int palSize = v1 * v2;
-
- if ((palSize - 12) == PALETTE_SIZE && !rleEncoded) {
- // Found palette, so read it in
- stream.seek(2 + 12, SEEK_CUR);
- for (int idx = 0; idx < PALETTE_SIZE; ++idx)
- _palette[idx] = VGA_COLOR_TRANS(stream.readByte());
- } else {
- // Not a palette, so rewind to start of frame data for normal frame processing
- stream.seek(-6, SEEK_CUR);
- }
-}
-
-void ImageFile::decompressFrame(ImageFrame &frame, const byte *src) {
- frame._frame.create(frame._width, frame._height, Graphics::PixelFormat::createFormatCLUT8());
-
- if (frame._paletteBase) {
- // Nibble-packed
- byte *pDest = (byte *)frame._frame.getPixels();
- for (uint idx = 0; idx < frame._size; ++idx, ++src) {
- *pDest++ = *src & 0xF;
- *pDest++ = (*src >> 4);
- }
- } else if (frame._rleEncoded && _vm->getGameID() == GType_RoseTattoo) {
- // Rose Tattoo run length encoding doesn't use the RLE marker byte
- byte *dst = (byte *)frame._frame.getPixels();
-
- for (int yp = 0; yp < frame._height; ++yp) {
- int xSize = frame._width;
- while (xSize > 0) {
- // Skip a given number of pixels
- byte skip = *src++;
- dst += skip;
- xSize -= skip;
- if (!xSize)
- break;
-
- // Get a run length, and copy the following number of pixels
- int rleCount = *src++;
- xSize -= rleCount;
- while (rleCount-- > 0)
- *dst++ = *src++;
- }
- assert(xSize == 0);
- }
- } else if (frame._rleEncoded) {
- // RLE encoded
- byte *dst = (byte *)frame._frame.getPixels();
-
- int frameSize = frame._width * frame._height;
- while (frameSize > 0) {
- if (*src == frame._rleMarker) {
- byte rleColor = src[1];
- byte rleCount = src[2];
- src += 3;
- frameSize -= rleCount;
- while (rleCount--)
- *dst++ = rleColor;
- } else {
- *dst++ = *src++;
- --frameSize;
- }
- }
- assert(frameSize == 0);
- } else {
- // Uncompressed frame
- Common::copy(src, src + frame._width * frame._height,
- (byte *)frame._frame.getPixels());
- }
-}
-
-/*----------------------------------------------------------------*/
-
-int ImageFrame::sDrawXSize(int scaleVal) const {
- int width = _width;
- int scale = scaleVal == 0 ? 1 : scaleVal;
-
- if (scaleVal >= 256)
- --width;
-
- int result = width * 256 / scale;
- if (scaleVal >= 256)
- ++result;
-
- return result;
-}
-
-int ImageFrame::sDrawYSize(int scaleVal) const {
- int height = _height;
- int scale = scaleVal == 0 ? 1 : scaleVal;
-
- if (scaleVal >= 256)
- --height;
-
- int result = height * 256 / scale;
- if (scaleVal >= 256)
- ++result;
-
- return result;
-}
-
} // End of namespace Sherlock