aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sherlock/animation.cpp2
-rw-r--r--engines/sherlock/events.cpp2
-rw-r--r--engines/sherlock/fonts.cpp34
-rw-r--r--engines/sherlock/image_file.cpp129
-rw-r--r--engines/sherlock/image_file.h15
-rw-r--r--engines/sherlock/people.cpp2
-rw-r--r--engines/sherlock/scalpel/scalpel.cpp18
-rw-r--r--engines/sherlock/scalpel/scalpel_user_interface.cpp4
8 files changed, 181 insertions, 25 deletions
diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp
index 50cb200d0b..bbf7c913b7 100644
--- a/engines/sherlock/animation.cpp
+++ b/engines/sherlock/animation.cpp
@@ -169,7 +169,7 @@ bool Animation::play3DO(const Common::String &filename, bool intro, int minDelay
// Load initial image
Common::String graphicsName = "prologue/" + filename + ".3da";
- ImageFile3DO images(graphicsName);
+ ImageFile3DO images(graphicsName, kImageFile3DOType_Animation);
events.wait(minDelay);
diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp
index 74ed72ed41..297437ed49 100644
--- a/engines/sherlock/events.cpp
+++ b/engines/sherlock/events.cpp
@@ -59,7 +59,7 @@ void Events::loadCursors(const Common::String &filename) {
_cursorImages = new ImageFile(filename);
} else {
// 3DO
- _cursorImages = new ImageFile3DO(filename, true);
+ _cursorImages = new ImageFile3DO(filename, kImageFile3DOType_RoomFormat);
}
_cursorId = INVALID_CURSOR;
}
diff --git a/engines/sherlock/fonts.cpp b/engines/sherlock/fonts.cpp
index 57241bfa00..c6657cd580 100644
--- a/engines/sherlock/fonts.cpp
+++ b/engines/sherlock/fonts.cpp
@@ -45,15 +45,35 @@ void Fonts::free() {
void Fonts::setFont(int fontNum) {
_fontNumber = fontNum;
- if (_platform == Common::kPlatform3DO)
- return;
-
- Common::String fname = Common::String::format("FONT%d.VGS", fontNum + 1);
-
- // Discard any previous font and read in new one
+ // Discard previous font
delete _font;
- _font = new ImageFile(fname);
+ Common::String fontFilename;
+
+ if (_platform != Common::kPlatform3DO) {
+ // PC
+ // use FONT[number].VGS, which is a regular sherlock graphic file
+ fontFilename = Common::String::format("FONT%d.VGS", fontNum + 1);
+
+ // load font data
+ _font = new ImageFile(fontFilename);
+ } else {
+ // 3DO
+ switch (fontNum) {
+ case 0:
+ case 1:
+ fontFilename = "helvetica14.font";
+ break;
+ case 2:
+ fontFilename = "darts.font";
+ break;
+ default:
+ error("setFont(): unsupported 3DO font number");
+ }
+ // load font data
+ _font = new ImageFile3DO(fontFilename, kImageFile3DOType_Font);
+ }
+
// Iterate through the frames to find the tallest font character
_fontHeight = 0;
for (uint idx = 0; idx < _font->size(); ++idx)
diff --git a/engines/sherlock/image_file.cpp b/engines/sherlock/image_file.cpp
index 43d3cf3de2..a42b443e3c 100644
--- a/engines/sherlock/image_file.cpp
+++ b/engines/sherlock/image_file.cpp
@@ -243,20 +243,41 @@ void ImageFile3DO::setVm(SherlockEngine *vm) {
_vm = vm;
}
-ImageFile3DO::ImageFile3DO(const Common::String &name, bool isRoomDataFormat) {
+ImageFile3DO::ImageFile3DO(const Common::String &name, ImageFile3DOType imageFile3DOType) {
Common::File *dataStream = new Common::File();
if (!dataStream->open(name)) {
error("unable to open %s\n", name.c_str());
}
- load(*dataStream, isRoomDataFormat);
+ switch(imageFile3DOType) {
+ case kImageFile3DOType_Animation:
+ loadAnimationFile(*dataStream);
+ break;
+ case kImageFile3DOType_Cel:
+ case kImageFile3DOType_CelAnimation:
+ load3DOCelFile(*dataStream);
+ break;
+ case kImageFile3DOType_RoomFormat:
+ load3DOCelRoomData(*dataStream);
+ break;
+ case kImageFile3DOType_Font:
+ loadFont(*dataStream);
+ break;
+ default:
+ error("unknown Imagefile-3DO-Type");
+ break;
+ }
delete dataStream;
}
ImageFile3DO::ImageFile3DO(Common::SeekableReadStream &stream, bool isRoomData) {
- load(stream, isRoomData);
+ if (!isRoomData) {
+ load(stream, isRoomData);
+ } else {
+ load3DOCelRoomData(stream);
+ }
}
ImageFile3DO::~ImageFile3DO() {
@@ -775,4 +796,106 @@ void ImageFile3DO::decompress3DOCelFrame(ImageFrame &frame, const byte *dataPtr,
}
}
+// Reads Sherlock Holmes 3DO font file
+void ImageFile3DO::loadFont(Common::SeekableReadStream &stream) {
+ uint32 streamSize = stream.size();
+ uint32 header_offsetWidthTable = 0;
+ uint32 header_offsetBitsTable = 0;
+ uint32 header_fontHeight = 0;
+ uint32 header_bytesPerLine = 0;
+ uint32 header_maxChar = 0;
+ uint32 header_charCount = 0;
+
+ byte *widthTablePtr = NULL;
+ uint32 bitsTableSize = 0;
+ byte *bitsTablePtr = NULL;
+
+ stream.skip(2); // Unknown bytes
+ stream.skip(2); // Unknown bytes (0x000E)
+ header_offsetWidthTable = stream.readUint32BE();
+ header_offsetBitsTable = stream.readUint32BE();
+ stream.skip(4); // Unknown bytes (0x00000004)
+ header_fontHeight = stream.readUint32BE();
+ header_bytesPerLine = stream.readUint32BE();
+ header_maxChar = stream.readUint32BE();
+
+ assert(header_maxChar <= 255);
+ header_charCount = header_maxChar + 1;
+
+ // Allocate memory for width table
+ widthTablePtr = new byte[header_charCount];
+
+ stream.seek(header_offsetWidthTable);
+ stream.read(widthTablePtr, header_charCount);
+
+ // Allocate memory for the bits
+ assert(header_offsetBitsTable < streamSize); // Security check
+ bitsTableSize = streamSize - header_offsetBitsTable;
+ bitsTablePtr = new byte[bitsTableSize];
+ stream.read(bitsTablePtr, bitsTableSize);
+
+ // Now extract all characters
+ uint16 curChar = 0;
+ const byte *curBitsLinePtr = bitsTablePtr;
+ const byte *curBitsPtr = NULL;
+ byte curBitsLeft = 0;
+ uint32 curCharHeightLeft = 0;
+ uint32 curCharWidthLeft = 0;
+ byte curBits = 0;
+
+ for (curChar = 0; curChar < header_charCount; curChar++) {
+ // create frame
+ {
+ ImageFrame imageFrame;
+
+ imageFrame._width = widthTablePtr[curChar];
+ imageFrame._height = header_fontHeight;
+ imageFrame._paletteBase = 0;
+ imageFrame._offset.x = 0;
+ imageFrame._offset.y = 0;
+ imageFrame._rleEncoded = false;
+ imageFrame._size = 0;
+
+ // Extract pixels
+ imageFrame._frame.create(imageFrame._width, imageFrame._height, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
+ uint16 *dest = (uint16 *)imageFrame._frame.getPixels();
+ Common::fill(dest, dest + imageFrame._width * imageFrame._height, 0);
+
+#if 0
+ curCharHeightLeft = header_fontHeight;
+ while (curCharHeightLeft) {
+ curCharWidthLeft = widthTablePtr[curChar];
+ curBitsPtr = curBitsLinePtr;
+ curBitsLeft = 8;
+
+ while (curCharWidthLeft) {
+ curBits = celGetBits(curBitsPtr, 2, curBitsLeft);
+ switch (curBits) {
+ case 0: // Transparent
+ break;
+ case 1: // regular color
+ *dest = 0xFFFF;
+ break;
+ case 2: // front
+ //*dest = 0xFFFF; //0x333;
+ break;
+ case 3: // shadow
+ //*dest = 0x1111;
+ break;
+ }
+ dest++;
+
+ curCharWidthLeft--;
+ }
+
+ curCharHeightLeft--;
+ curBitsLinePtr += header_bytesPerLine;
+ }
+#endif
+
+ push_back(imageFrame);
+ }
+ }
+}
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/image_file.h b/engines/sherlock/image_file.h
index ddca4b883e..f24e831440 100644
--- a/engines/sherlock/image_file.h
+++ b/engines/sherlock/image_file.h
@@ -94,6 +94,14 @@ public:
static void setVm(SherlockEngine *vm);
};
+enum ImageFile3DOType {
+ kImageFile3DOType_Animation = 0,
+ kImageFile3DOType_Cel = 1,
+ kImageFile3DOType_CelAnimation = 2,
+ kImageFile3DOType_RoomFormat = 3,
+ kImageFile3DOType_Font = 4
+};
+
struct ImageFile3DOPixelLookupTable {
uint16 pixelColor[256];
};
@@ -134,8 +142,13 @@ private:
*/
void loadAnimationFile(Common::SeekableReadStream &stream);
+ /**
+ * Load Sherlock Holmes 3DO font file
+ */
+ void loadFont(Common::SeekableReadStream &stream);
+
public:
- ImageFile3DO(const Common::String &name, bool isRoomDataFormat = false);
+ ImageFile3DO(const Common::String &name, ImageFile3DOType imageFile3DOType);
ImageFile3DO(Common::SeekableReadStream &stream, bool isRoomData = false);
~ImageFile3DO();
static void setVm(SherlockEngine *vm);
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp
index 1a3e8d2d5d..5684a94e9b 100644
--- a/engines/sherlock/people.cpp
+++ b/engines/sherlock/people.cpp
@@ -286,7 +286,7 @@ bool People::loadWalk() {
_data[PLAYER]->_images = new ImageFile("walk.vgs");
} else {
// Load walk.anim on 3DO, which is a cel animation file
- _data[PLAYER]->_images = new ImageFile3DO("walk.anim");
+ _data[PLAYER]->_images = new ImageFile3DO("walk.anim", kImageFile3DOType_CelAnimation);
}
_data[PLAYER]->setImageFrame();
_data[PLAYER]->_walkLoaded = true;
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index 02e0f383bc..4fe3b0327c 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -531,7 +531,7 @@ bool ScalpelEngine::showOfficeCutscene() {
// 3DO variant
bool ScalpelEngine::show3DOSplash() {
// 3DO EA Splash screen
- ImageFile3DO titleImage_3DOSplash("3DOSplash.cel");
+ ImageFile3DO titleImage_3DOSplash("3DOSplash.cel", kImageFile3DOType_Cel);
_screen->transBlitFrom(titleImage_3DOSplash[0]._frame, Common::Point(0, -20));
bool finished = _events->delay(3000, true);
@@ -576,7 +576,7 @@ bool ScalpelEngine::showCityCutscene3DO() {
_screen->_backBuffer2.blitFrom(*_screen); // save into backbuffer 2, for restoring later
// "London, England"
- ImageFile3DO titleImage_London("title2a.cel");
+ ImageFile3DO titleImage_London("title2a.cel", kImageFile3DOType_Cel);
_screen->_backBuffer1.transBlitFrom(titleImage_London[0]._frame, Common::Point(30, 50));
_screen->fadeIntoScreen3DO(1);
@@ -584,7 +584,7 @@ bool ScalpelEngine::showCityCutscene3DO() {
if (finished) {
// "November, 1888"
- ImageFile3DO titleImage_November("title2b.cel");
+ ImageFile3DO titleImage_November("title2b.cel", kImageFile3DOType_Cel);
_screen->_backBuffer1.transBlitFrom(titleImage_November[0]._frame, Common::Point(100, 100));
_screen->fadeIntoScreen3DO(1);
@@ -604,7 +604,7 @@ bool ScalpelEngine::showCityCutscene3DO() {
_screen->_backBuffer1.blitFrom(*_screen); // save into backbuffer 1, used for fade
// "Sherlock Holmes" (title)
- ImageFile3DO titleImage_SherlockHolmesTitle("title1ab.cel");
+ ImageFile3DO titleImage_SherlockHolmesTitle("title1ab.cel", kImageFile3DOType_Cel);
_screen->_backBuffer1.transBlitFrom(titleImage_SherlockHolmesTitle[0]._frame, Common::Point(34, 5));
// Blend in
@@ -613,7 +613,7 @@ bool ScalpelEngine::showCityCutscene3DO() {
// Title should fade in, Copyright should be displayed a bit after that
if (finished) {
- ImageFile3DO titleImage_Copyright("title1c.cel");
+ ImageFile3DO titleImage_Copyright("title1c.cel", kImageFile3DOType_Cel);
_screen->transBlitFrom(titleImage_Copyright[0]._frame, Common::Point(20, 190));
finished = _events->delay(3500, true);
@@ -631,7 +631,7 @@ bool ScalpelEngine::showCityCutscene3DO() {
if (finished) {
// "In the alley behind the Regency Theatre..."
- ImageFile3DO titleImage_InTheAlley("title1d.cel");
+ ImageFile3DO titleImage_InTheAlley("title1d.cel", kImageFile3DOType_Cel);
_screen->_backBuffer1.transBlitFrom(titleImage_InTheAlley[0]._frame, Common::Point(72, 51));
// Fade in
@@ -667,7 +667,7 @@ bool ScalpelEngine::showAlleyCutscene3DO() {
if (finished) {
// Show screaming victim
- ImageFile3DO titleImage_ScreamingVictim("scream.cel");
+ ImageFile3DO titleImage_ScreamingVictim("scream.cel", kImageFile3DOType_Cel);
_screen->clear();
_screen->transBlitFrom(titleImage_ScreamingVictim[0]._frame, Common::Point(0, 0));
@@ -698,7 +698,7 @@ bool ScalpelEngine::showAlleyCutscene3DO() {
if (finished) {
// "Early the following morning on Baker Street..."
- ImageFile3DO titleImage_EarlyTheFollowingMorning("title3.cel");
+ ImageFile3DO titleImage_EarlyTheFollowingMorning("title3.cel", kImageFile3DOType_Cel);
_screen->_backBuffer1.transBlitFrom(titleImage_EarlyTheFollowingMorning[0]._frame, Common::Point(35, 51));
// Fade in
@@ -751,7 +751,7 @@ bool ScalpelEngine::showOfficeCutscene3DO() {
if (finished) {
// Show the note
- ImageFile3DO titleImage_CoffeeNote("note.cel");
+ ImageFile3DO titleImage_CoffeeNote("note.cel", kImageFile3DOType_Cel);
_screen->clear();
_screen->transBlitFrom(titleImage_CoffeeNote[0]._frame, Common::Point(0, 0));
diff --git a/engines/sherlock/scalpel/scalpel_user_interface.cpp b/engines/sherlock/scalpel/scalpel_user_interface.cpp
index 80a36fe9cb..739eb5d1bb 100644
--- a/engines/sherlock/scalpel/scalpel_user_interface.cpp
+++ b/engines/sherlock/scalpel/scalpel_user_interface.cpp
@@ -92,8 +92,8 @@ ScalpelUserInterface::ScalpelUserInterface(SherlockEngine *vm): UserInterface(vm
_controlPanel = new ImageFile("controls.vgs");
} else {
// 3DO
- _controls = new ImageFile3DO("menu.all", true);
- _controlPanel = new ImageFile3DO("controls.vgs", true);
+ _controls = new ImageFile3DO("menu.all", kImageFile3DOType_RoomFormat);
+ _controlPanel = new ImageFile3DO("controls.vgs", kImageFile3DOType_RoomFormat);
}
} else {
_controls = nullptr;