diff --git a/engines/prince/resource.h b/engines/prince/resource.h index a2cd8a62621..8fb2b94bd97 100644 --- a/engines/prince/resource.h +++ b/engines/prince/resource.h @@ -24,14 +24,19 @@ #define PRINCE_RESOURCE_H #include "common/stream.h" +#include "common/memstream.h" #include "common/archive.h" #include "common/debug-channels.h" #include "common/ptr.h" +#include "prince/decompress.h" + namespace Prince { namespace Resource { +static Common::SeekableReadStream *getDecompressedStream(Common::SeekableReadStream *stream); + template bool loadFromStream(T &resource, Common::SeekableReadStream &stream) { return resource.loadStream(stream); @@ -39,13 +44,15 @@ bool loadFromStream(T &resource, Common::SeekableReadStream &stream) { template bool loadResource(T *resource, const char *resourceName, bool required) { - Common::ScopedPtr stream(SearchMan.createReadStreamForMember(resourceName)); - if (!stream) { + Common::SeekableReadStream *stream_(SearchMan.createReadStreamForMember(resourceName)); + if (!stream_) { if (required) error("Can't load %s", resourceName); return false; } + Common::ScopedPtr stream(getDecompressedStream(stream_)); + return loadFromStream(*resource, *stream); } @@ -61,26 +68,30 @@ bool loadResource(Common::Array &array, Common::SeekableReadStream &stream, b template bool loadResource(Common::Array &array, const char *resourceName, bool required = true) { - Common::ScopedPtr stream(SearchMan.createReadStreamForMember(resourceName)); - if (!stream) { + Common::SeekableReadStream *stream_(SearchMan.createReadStreamForMember(resourceName)); + if (!stream_) { if (required) error("Can't load %s", resourceName); return false; } + Common::ScopedPtr stream(getDecompressedStream(stream_)); + return loadResource(array, *stream, required); } template bool loadResource(Common::Array &array, const char *resourceName, bool required = true) { - Common::ScopedPtr stream(SearchMan.createReadStreamForMember(resourceName)); - if (!stream) { + Common::SeekableReadStream *stream_(SearchMan.createReadStreamForMember(resourceName)); + if (!stream_) { if (required) error("Can't load %s", resourceName); return false; } + Common::ScopedPtr stream(getDecompressedStream(stream_)); + // FIXME: This is stupid. Maybe loadFromStream should be helper method that returns initialized object while (true) { T* t = new T(); @@ -93,6 +104,28 @@ bool loadResource(Common::Array &array, const char *resourceName, bool requ return true; } +static Common::SeekableReadStream *getDecompressedStream(Common::SeekableReadStream *stream) { + byte header[4]; + + stream->read(header, 4); + stream->seek(0); + + if (READ_BE_UINT32(header) == MKTAG('M', 'A', 'S', 'M')) { + byte *buffer = (byte *)malloc(stream->size()); + stream->read(buffer, stream->size()); + + Decompressor dec; + uint32 decompLen = READ_BE_UINT32(buffer + 14); + byte *decompData = (byte *)malloc(decompLen); + dec.decompress(buffer + 18, decompData, decompLen); + free(buffer); + + return new Common::MemoryReadStream(decompData, decompLen, DisposeAfterUse::YES); + } else { + return stream; + } +} + } } // End of namespace Prince