diff options
author | Martin Kiewitz | 2015-06-11 22:11:24 +0200 |
---|---|---|
committer | Martin Kiewitz | 2015-06-11 22:11:24 +0200 |
commit | 9ce2cbca9f6f42c33a86d5896d360b1b8a8250f7 (patch) | |
tree | 1623b99e1371f27b45e2a59d6781ee7294670340 | |
parent | 7ff3336a65ec19283ef44919d21e7c4542d7cc3f (diff) | |
download | scummvm-rg350-9ce2cbca9f6f42c33a86d5896d360b1b8a8250f7.tar.gz scummvm-rg350-9ce2cbca9f6f42c33a86d5896d360b1b8a8250f7.tar.bz2 scummvm-rg350-9ce2cbca9f6f42c33a86d5896d360b1b8a8250f7.zip |
SHERLOCK: 3DO: support images inside room files
-rw-r--r-- | engines/sherlock/image_file.cpp | 95 | ||||
-rw-r--r-- | engines/sherlock/image_file.h | 9 | ||||
-rw-r--r-- | engines/sherlock/scene.cpp | 19 |
3 files changed, 104 insertions, 19 deletions
diff --git a/engines/sherlock/image_file.cpp b/engines/sherlock/image_file.cpp index 54af3d8a18..56e0e082d1 100644 --- a/engines/sherlock/image_file.cpp +++ b/engines/sherlock/image_file.cpp @@ -255,8 +255,8 @@ ImageFile3DO::ImageFile3DO(const Common::String &name) { delete dataStream; } -ImageFile3DO::ImageFile3DO(Common::SeekableReadStream &stream, bool roomData) { - load(stream, false); +ImageFile3DO::ImageFile3DO(Common::SeekableReadStream &stream, bool isRoomData) { + load(stream, isRoomData); } ImageFile3DO::~ImageFile3DO() { @@ -265,9 +265,15 @@ ImageFile3DO::~ImageFile3DO() { // (*this)[idx]._frame.free(); } -void ImageFile3DO::load(Common::SeekableReadStream &stream, bool roomData) { - uint32 headerId = stream.readUint32BE(); +void ImageFile3DO::load(Common::SeekableReadStream &stream, bool isRoomData) { + uint32 headerId = 0; + if (isRoomData) { + load3DOCelRoomData(stream); + return; + } + + headerId = stream.readUint32BE(); assert(!stream.eos()); // Seek back to the start @@ -522,6 +528,87 @@ void ImageFile3DO::load3DOCelFile(Common::SeekableReadStream &stream) { } } +// Reads 3DO .cel data (room file format) +void ImageFile3DO::load3DOCelRoomData(Common::SeekableReadStream &stream) { + int streamSize = stream.size(); + uint16 roomDataHeader_size = 0; + + ImageFrame imageFrame; + + // CCB chunk (cel control block) + uint32 ccbFlags = 0; + bool ccbFlags_compressed = false; + uint16 ccbPPMP0 = 0; + uint16 ccbPPMP1 = 0; + uint32 ccbPRE0 = 0; + byte ccbPRE0_bitsPerPixel = 0; + uint32 ccbPRE1 = 0; + uint32 ccbWidth = 0; + uint32 ccbHeight = 0; + // cel data + uint32 celDataSize = 0; + byte *celDataPtr = NULL; + + while (stream.pos() < streamSize) { + ImageFrame frame; + + // 3DO sherlock holmes room data header + stream.skip(4); // Possibly UINT16 width, UINT16 height?!?! + roomDataHeader_size = stream.readUint16BE(); + stream.skip(2); // seems to be filler + + // 3DO raw cel control block + ccbFlags = stream.readUint32BE(); + stream.skip(3 * 4); // skip over 3 pointer fields, which are used in memory only by 3DO hardware + stream.skip(8 * 4); // skip over 8 offset fields + ccbPPMP0 = stream.readUint16BE(); + ccbPPMP1 = stream.readUint16BE(); + ccbPRE0 = stream.readUint32BE(); + ccbPRE1 = stream.readUint32BE(); + ccbWidth = stream.readUint32BE(); + ccbHeight = stream.readUint32BE(); + + if (ccbFlags & 0x200) // bit 9 + ccbFlags_compressed = true; + + // PRE0 first 3 bits define how many bits per encoded pixel are used + ccbPRE0_bitsPerPixel = imagefile3DO_cel_bitsPerPixelLookupTable[ccbPRE0 & 0x07]; + if (!ccbPRE0_bitsPerPixel) + error("load3DOCelRoomData: Invalid CCB PRE0 bits per pixel"); + + if (ccbPRE0_bitsPerPixel != 16) { + // We currently support 16-bits per pixel in here + error("load3DOCelRoomData: bits per pixel < 16?!?!?"); + } + + // cel data follows + assert(roomDataHeader_size > 68); + // size field does not include the 8 byte header + celDataSize = roomDataHeader_size - 68; + + // read data into memory + celDataPtr = new byte[celDataSize]; + + stream.read(celDataPtr, celDataSize); + + // Set up frame + imageFrame._width = ccbWidth; + imageFrame._height = ccbHeight; + imageFrame._paletteBase = 0; + imageFrame._offset.x = 0; + imageFrame._offset.y = 0; + imageFrame._rleEncoded = ccbFlags_compressed; + imageFrame._size = 0; + + // Decompress/copy this frame + decompress3DOCelFrame(imageFrame, celDataPtr, celDataSize, ccbPRE0_bitsPerPixel, NULL); + + delete[] celDataPtr; + + push_back(imageFrame); + } +} + static uint16 imagefile3DO_cel_bitsMask[17] = { 0, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, diff --git a/engines/sherlock/image_file.h b/engines/sherlock/image_file.h index bf41a3bf98..5cdf1db4be 100644 --- a/engines/sherlock/image_file.h +++ b/engines/sherlock/image_file.h @@ -105,7 +105,7 @@ private: /** * Load the data of the sprite */ - void load(Common::SeekableReadStream &stream, bool animImages); + void load(Common::SeekableReadStream &stream, bool isRoomData); /** * convert pixel RGB values from RGB555 to RGB565 @@ -117,6 +117,11 @@ private: */ void load3DOCelFile(Common::SeekableReadStream &stream); + /** + * Load 3DO cel data (room file format) + */ + void load3DOCelRoomData(Common::SeekableReadStream &stream); + inline uint16 celGetBits(const byte *&dataPtr, byte bitCount, byte &dataBitsLeft); /** @@ -131,7 +136,7 @@ private: public: ImageFile3DO(const Common::String &name); - ImageFile3DO(Common::SeekableReadStream &stream, bool roomData = false); + ImageFile3DO(Common::SeekableReadStream &stream, bool isRoomData = false); ~ImageFile3DO(); static void setVm(SherlockEngine *vm); }; diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 028e262999..e4807733c9 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -656,21 +656,14 @@ bool Scene::loadScene(const Common::String &filename) { _images[idx + 1]._filesize = bgInfo[idx]._filesize; _images[idx + 1]._maxFrames = bgInfo[idx]._maxFrames; - // Read the image data - // It seems it's a 8 byte header per frame - // followed by a copy of the cel header - // which is then followed by cel data - // TODO - warning("image %d, maxFrames %d", idx, bgInfo[idx]._maxFrames); - warning("size %d", bgInfo[idx]._filesize); + // Read image data into memory + Common::SeekableReadStream *imageStream = roomStream->readStream(bgInfo[idx]._filesize); - // Read in the image data - //Common::SeekableReadStream *imageStream = roomStream->readStream(bgInfo[idx]._filesize); + // Load image data into an ImageFile array as room file data + // which is basically a fixed header, followed by a raw cel header, followed by regular cel data + _images[idx + 1]._images = new ImageFile3DO(*imageStream, true); - //_images[idx + 1]._images = new ImageFile(*imageStream); - - //delete imageStream; - warning("end"); + delete imageStream; } // === BGSHAPES === Set up the bgShapes |