aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Kiewitz2015-06-11 22:11:24 +0200
committerMartin Kiewitz2015-06-11 22:11:24 +0200
commit9ce2cbca9f6f42c33a86d5896d360b1b8a8250f7 (patch)
tree1623b99e1371f27b45e2a59d6781ee7294670340
parent7ff3336a65ec19283ef44919d21e7c4542d7cc3f (diff)
downloadscummvm-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.cpp95
-rw-r--r--engines/sherlock/image_file.h9
-rw-r--r--engines/sherlock/scene.cpp19
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