aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sherlock/decompress.cpp128
-rw-r--r--engines/sherlock/inventory.cpp8
-rw-r--r--engines/sherlock/map.cpp10
-rw-r--r--engines/sherlock/objects.cpp90
-rw-r--r--engines/sherlock/objects.h34
-rw-r--r--engines/sherlock/resources.cpp94
-rw-r--r--engines/sherlock/resources.h25
-rw-r--r--engines/sherlock/scalpel/scalpel.cpp17
-rw-r--r--engines/sherlock/scene.cpp211
-rw-r--r--engines/sherlock/scene.h41
-rw-r--r--engines/sherlock/screen.cpp74
-rw-r--r--engines/sherlock/screen.h19
-rw-r--r--engines/sherlock/settings.cpp3
-rw-r--r--engines/sherlock/sherlock.cpp5
-rw-r--r--engines/sherlock/sherlock.h7
-rw-r--r--engines/sherlock/sound.cpp1
-rw-r--r--engines/sherlock/talk.cpp8
-rw-r--r--engines/sherlock/talk.h4
-rw-r--r--engines/sherlock/tattoo/tattoo.cpp28
-rw-r--r--engines/sherlock/tattoo/tattoo.h5
-rw-r--r--engines/sherlock/user_interface.cpp125
-rw-r--r--engines/sherlock/user_interface.h170
22 files changed, 861 insertions, 246 deletions
diff --git a/engines/sherlock/decompress.cpp b/engines/sherlock/decompress.cpp
new file mode 100644
index 0000000000..8e02da3212
--- /dev/null
+++ b/engines/sherlock/decompress.cpp
@@ -0,0 +1,128 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "sherlock/decompress.h"
+
+namespace Sherlock {
+
+/**
+ * Decompresses an LZW compressed resource. If no outSize is specified, it will
+ * decompress the entire resource. If, however, an explicit size is specified,
+ * then it means we're already within a resource, and only want to decompress
+ * part of it.
+ */
+Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source, int32 outSize) {
+ if (outSize == -1) {
+ source.seek(5);
+ outSize = source.readSint32LE();
+ }
+
+ byte lzWindow[4096];
+ uint16 lzWindowPos;
+ uint16 cmd;
+
+ byte *outBuffer = new byte[outSize];
+ byte *outBufferEnd = outBuffer + outSize;
+ Common::MemoryReadStream *outS = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
+
+ memset(lzWindow, 0xFF, 0xFEE);
+ lzWindowPos = 0xFEE;
+ cmd = 0;
+
+ do {
+ cmd >>= 1;
+ if (!(cmd & 0x100))
+ cmd = source.readByte() | 0xFF00;
+
+ if (cmd & 1) {
+ byte literal = source.readByte();
+ *outBuffer++ = literal;
+ lzWindow[lzWindowPos] = literal;
+ lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
+ } else {
+ int copyPos, copyLen;
+ copyPos = source.readByte();
+ copyLen = source.readByte();
+ copyPos = copyPos | ((copyLen & 0xF0) << 4);
+ copyLen = (copyLen & 0x0F) + 3;
+ while (copyLen--) {
+ byte literal = lzWindow[copyPos];
+ copyPos = (copyPos + 1) & 0x0FFF;
+ *outBuffer++ = literal;
+ lzWindow[lzWindowPos] = literal;
+ lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
+ }
+ }
+ } while (outBuffer < outBufferEnd);
+
+ return outS;
+}
+
+
+/**
+ * Decompresses a Rose Tattoo resource
+ *
+Common::SeekableReadStream *decompress32(Common::SeekableReadStream &source, int32 outSize) {
+ if (outSize == -1) {
+ outSize = source.readSint32LE();
+ }
+
+ byte lzWindow[8192];
+ byte *outBuffer = new byte[outSize];
+ byte *outBufferEnd = outBuffer + outSize;
+ Common::MemoryReadStream *outS = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
+
+ memset(lzWindow, 0xFF, 8192);
+ int lzWindowPos = 0xFEE;
+ int cmd = 0;
+
+ do {
+ cmd >>= 1;
+ if (!(cmd & 0x100))
+ cmd = source.readByte() | 0xFF00;
+
+ if (cmd & 1) {
+ byte literal = source.readByte();
+ *outBuffer++ = literal;
+ lzWindow[lzWindowPos] = literal;
+ lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
+ } else {
+ int copyPos, copyLen;
+ copyPos = source.readByte();
+ copyLen = source.readByte();
+ copyPos = copyPos | ((copyLen & 0xF0) << 4);
+ copyLen = (copyLen & 0x0F) + 3;
+ while (copyLen--) {
+ byte literal = lzWindow[copyPos];
+ copyPos = (copyPos + 1) & 0x0FFF;
+ *outBuffer++ = literal;
+ lzWindow[lzWindowPos] = literal;
+ lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
+ }
+ }
+ } while (outBuffer < outBufferEnd);
+
+ return outS;
+}
+*/
+
+} // namespace Sherlock
diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp
index 7f216a35c3..bbb7c75aea 100644
--- a/engines/sherlock/inventory.cpp
+++ b/engines/sherlock/inventory.cpp
@@ -243,7 +243,8 @@ void Inventory::drawInventory(InvNewMode mode) {
screen._backBuffer = &screen._backBuffer1;
}
- ui._oldUse = -1;
+ assert(IS_SERRATED_SCALPEL);
+ ((ScalpelUserInterface *)_vm->_ui)->_oldUse = -1;
}
void Inventory::invCommands(bool slamIt) {
@@ -318,9 +319,12 @@ void Inventory::highlight(int index, byte color) {
}
void Inventory::refreshInv() {
+ if (IS_ROSE_TATTOO)
+ return;
+
Screen &screen = *_vm->_screen;
Talk &talk = *_vm->_talk;
- UserInterface &ui = *_vm->_ui;
+ ScalpelUserInterface &ui = *(ScalpelUserInterface *)_vm->_ui;
ui._invLookFlag = true;
freeInv();
diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp
index 42775ae4b0..44ca7cd44c 100644
--- a/engines/sherlock/map.cpp
+++ b/engines/sherlock/map.cpp
@@ -22,6 +22,7 @@
#include "sherlock/map.h"
#include "sherlock/sherlock.h"
+#include "common/system.h"
namespace Sherlock {
@@ -50,7 +51,7 @@ const byte *MapPaths::getPath(int srcLocation, int destLocation) {
/*----------------------------------------------------------------*/
-Map::Map(SherlockEngine *vm) : _vm(vm), _topLine(SHERLOCK_SCREEN_WIDTH, 12) {
+Map::Map(SherlockEngine *vm): _vm(vm), _topLine(g_system->getWidth(), 12) {
_active = false;
_mapCursors = nullptr;
_shapes = nullptr;
@@ -83,8 +84,13 @@ void Map::loadSequences(int count, const byte *seq) {
}
void Map::loadData() {
+ // TODO: Remove this
+ if (_vm->getGameID() == GType_RoseTattoo)
+ return;
+
// Load the list of location names
- Common::SeekableReadStream *txtStream = _vm->_res->load("chess.txt");
+ Common::SeekableReadStream *txtStream = _vm->_res->load(
+ _vm->getGameID() == GType_SerratedScalpel ? "chess.txt" : "map.txt");
int streamSize = txtStream->size();
while (txtStream->pos() < streamSize) {
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index 02f2526ae9..f3803518ee 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -113,8 +113,8 @@ void Sprite::adjustSprite() {
people.gotoStand(*this);
}
} else if (!map._active) {
- _position.y = CLIP((int)_position.y, UPPER_LIMIT, LOWER_LIMIT);
- _position.x = CLIP((int)_position.x, LEFT_LIMIT, RIGHT_LIMIT);
+ _position.y = CLIP((int)_position.y, (int)UPPER_LIMIT, (int)LOWER_LIMIT);
+ _position.x = CLIP((int)_position.x, (int)LEFT_LIMIT, (int)RIGHT_LIMIT);
}
if (!map._active || (map._frameChangeFlag = !map._frameChangeFlag))
@@ -373,9 +373,14 @@ UseType::UseType() {
_useFlag = 0;
}
-void UseType::load(Common::SeekableReadStream &s) {
+void UseType::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
char buffer[12];
+ if (isRoseTattoo) {
+ s.read(buffer, 12);
+ _verb = Common::String(buffer);
+ }
+
_cAnimNum = s.readByte();
_cAnimSpeed = s.readByte();
if (_cAnimSpeed & 0x80)
@@ -387,7 +392,9 @@ void UseType::load(Common::SeekableReadStream &s) {
}
_useFlag = s.readSint16LE();
- s.skip(6);
+
+ if (!isRoseTattoo)
+ s.skip(6);
s.read(buffer, 12);
_target = Common::String(buffer);
@@ -434,9 +441,16 @@ Object::Object() {
_descOffset = 0;
_seqCounter2 = 0;
_seqSize = 0;
+
+ _quickDraw = 0;
+ _scaleVal = 0;
+ _requiredFlag1 = 0;
+ _gotoSeq = 0;
+ _talkSeq = 0;
+ _restoreSlot = 0;
}
-void Object::load(Common::SeekableReadStream &s) {
+void Object::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
char buffer[41];
s.read(buffer, 12);
_name = Common::String(buffer);
@@ -468,10 +482,10 @@ void Object::load(Common::SeekableReadStream &s) {
_goto.x = s.readSint16LE();
_goto.y = s.readSint16LE();
- _pickup = s.readByte();
- _defaultCommand = s.readByte();
- _lookFlag = s.readUint16LE();
- _pickupFlag = s.readUint16LE();
+ _pickup = isRoseTattoo ? 0 : s.readByte();
+ _defaultCommand = isRoseTattoo ? 0 : s.readByte();
+ _lookFlag = s.readSint16LE();
+ _pickupFlag = isRoseTattoo ? 0 : s.readSint16LE();
_requiredFlag = s.readSint16LE();
_noShapeSize.x = s.readUint16LE();
_noShapeSize.y = s.readUint16LE();
@@ -479,26 +493,45 @@ void Object::load(Common::SeekableReadStream &s) {
_misc = s.readByte();
_maxFrames = s.readUint16LE();
_flags = s.readByte();
- _aOpen.load(s);
+
+ if (!isRoseTattoo)
+ _aOpen.load(s);
+
_aType = (AType)s.readByte();
_lookFrames = s.readByte();
_seqCounter = s.readByte();
_lookPosition.x = s.readUint16LE();
- _lookPosition.y = s.readByte();
+ _lookPosition.y = isRoseTattoo ? s.readSint16LE() : s.readByte();
_lookFacing = s.readByte();
_lookcAnim = s.readByte();
- _aClose.load(s);
+
+ if (!isRoseTattoo)
+ _aClose.load(s);
+
_seqStack = s.readByte();
_seqTo = s.readByte();
_descOffset = s.readUint16LE();
_seqCounter2 = s.readByte();
_seqSize = s.readUint16LE();
- s.skip(1);
- _aMove.load(s);
- s.skip(8);
- for (int idx = 0; idx < USE_COUNT; ++idx)
- _use[idx].load(s);
+ if (isRoseTattoo) {
+ for (int idx = 0; idx < 6; ++idx)
+ _use[idx].load(s, true);
+
+ _quickDraw = s.readByte();
+ _scaleVal = s.readUint16LE();
+ _requiredFlag1 = s.readSint16LE();
+ _gotoSeq = s.readByte();
+ _talkSeq = s.readByte();
+ _restoreSlot = s.readByte();
+ } else {
+ s.skip(1);
+ _aMove.load(s);
+ s.skip(8);
+
+ for (int idx = 0; idx < 4; ++idx)
+ _use[idx].load(s, false);
+ }
}
void Object::toggleHidden() {
@@ -1032,17 +1065,30 @@ const Common::Rect Object::getOldBounds() const {
/*----------------------------------------------------------------*/
-void CAnim::load(Common::SeekableReadStream &s) {
+void CAnim::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
char buffer[12];
s.read(buffer, 12);
_name = Common::String(buffer);
- s.read(_sequences, 30);
+ if (isRoseTattoo) {
+ Common::fill(&_sequences[0], &_sequences[30], 0);
+ _size = s.readUint32LE();
+ } else {
+ s.read(_sequences, 30);
+ }
+
_position.x = s.readSint16LE();
_position.y = s.readSint16LE();
- _size = s.readUint32LE();
- _type = (SpriteType)s.readUint16LE();
- _flags = s.readByte();
+
+ if (isRoseTattoo) {
+ _flags = s.readByte();
+ _scaleVal = s.readSint16LE();
+ } else {
+ _size = s.readUint32LE();
+ _type = (SpriteType)s.readUint16LE();
+ _flags = s.readByte();
+ }
+
_goto.x = s.readSint16LE();
_goto.y = s.readSint16LE();
_gotoDir = s.readSint16LE();
diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h
index bbd068eef7..b61e7e24fe 100644
--- a/engines/sherlock/objects.h
+++ b/engines/sherlock/objects.h
@@ -179,13 +179,14 @@ struct UseType {
Common::String _names[NAMES_COUNT];
int _useFlag; // Which flag USE will set (if any)
Common::String _target;
+ Common::String _verb;
UseType();
/**
* Load the data for the UseType
*/
- void load(Common::SeekableReadStream &s);
+ void load(Common::SeekableReadStream &s, bool isRoseTattoo);
};
enum { OBJ_BEHIND = 1, OBJ_FLIPPED = 2, OBJ_FORWARD = 4, TURNON_OBJ = 0x20, TURNOFF_OBJ = 0x40 };
@@ -233,35 +234,45 @@ public:
int _pickup;
int _defaultCommand; // Default right-click command
int _lookFlag; // Which flag LOOK will set (if any)
- int _pickupFlag; // Which flag PICKUP will set (if any)
int _requiredFlag; // Object will be hidden if not set
Common::Point _noShapeSize; // Size of a NO_SHAPE
int _status; // Status (open/closed, moved/not)
int8 _misc; // Misc field -- use varies with type
int _maxFrames; // Number of frames
int _flags; // Tells if object can be walked behind
- ActionType _aOpen; // Holds data for moving object
AType _aType; // Tells if this is an object, person, talk, etc.
int _lookFrames; // How many frames to play of the look anim before pausing
int _seqCounter; // How many times this sequence has been executed
Common::Point _lookPosition; // Where to walk when examining object
int _lookFacing; // Direction to face when examining object
int _lookcAnim;
- ActionType _aClose;
int _seqStack; // Allows gosubs to return to calling frame
int _seqTo; // Allows 1-5, 8-3 type sequences encoded in 2 bytes
uint _descOffset; // Tells where description starts in DescText
int _seqCounter2; // Counter of calling frame sequence
uint _seqSize; // Tells where description starts
+ UseType _use[6]; // Serrated Scalpel uses 4, Rose Tattoo 6
+
+ // Serrated Scalpel fields
+ int _pickupFlag; // Which flag PICKUP will set (if any)
+ ActionType _aOpen; // Holds data for moving object
+ ActionType _aClose;
ActionType _aMove;
- UseType _use[USE_COUNT];
+
+ // Rose Tattoo fields
+ int _quickDraw;
+ int _scaleVal;
+ int _requiredFlag1;
+ int _gotoSeq;
+ int _talkSeq;
+ int _restoreSlot;
Object();
/**
* Load the data for the object
*/
- void load(Common::SeekableReadStream &s);
+ void load(Common::SeekableReadStream &s, bool isRoseTattoo);
/**
* Toggle the type of an object between hidden and active
@@ -326,20 +337,25 @@ public:
struct CAnim {
Common::String _name; // Name
- byte _sequences[MAX_FRAME]; // Animation sequences
Common::Point _position; // Position
int _size; // Size of uncompressed animation
- SpriteType _type;
int _flags; // Tells if can be walked behind
Common::Point _goto; // coords holmes should walk to before starting canim
int _gotoDir;
Common::Point _teleportPos; // Location Holmes shoul teleport to after
int _teleportDir; // playing canim
+ // Scalpel specific
+ byte _sequences[MAX_FRAME]; // Animation sequences
+ SpriteType _type;
+
+ // Rose Tattoo specific
+ int _scaleVal; // How much the canim is scaled
+
/**
* Load the data for the animation
*/
- void load(Common::SeekableReadStream &s);
+ void load(Common::SeekableReadStream &s, bool isRoseTattoo);
};
struct SceneImage {
diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp
index 091ef3ea12..864622e74b 100644
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@ -65,7 +65,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
- Common::SeekableReadStream *decompressed = _vm->_res->decompressLZ(stream);
+ Common::SeekableReadStream *decompressed = _vm->_res->decompress(stream);
cacheEntry.resize(decompressed->size());
decompressed->read(&cacheEntry[0], decompressed->size());
@@ -103,8 +103,11 @@ void Resources::addToCache(const Common::String &filename) {
// Check to see if the file is a library
Common::SeekableReadStream *stream = load(filename);
uint32 header = stream->readUint32BE();
+
if (header == MKTAG('L', 'I', 'B', 26))
- loadLibraryIndex(filename, stream);
+ loadLibraryIndex(filename, stream, false);
+ else if (header == MKTAG('L', 'I', 'C', 26))
+ loadLibraryIndex(filename, stream, true);
delete stream;
}
@@ -159,12 +162,14 @@ Common::SeekableReadStream *Resources::load(const Common::String &filename) {
void Resources::decompressIfNecessary(Common::SeekableReadStream *&stream) {
bool isCompressed = stream->readUint32BE() == MKTAG('L', 'Z', 'V', 26);
- stream->seek(-4, SEEK_CUR);
if (isCompressed) {
- Common::SeekableReadStream *newStream = decompressLZ(*stream);
+ int outSize = stream->readUint32LE();
+ Common::SeekableReadStream *newStream = decompressLZ(*stream, outSize);
delete stream;
stream = newStream;
+ } else {
+ stream->seek(-4, SEEK_CUR);
}
}
@@ -174,7 +179,7 @@ Common::SeekableReadStream *Resources::load(const Common::String &filename, cons
// Check if the library has already had it's index read, and if not, load it
if (!_indexes.contains(libraryFile))
- loadLibraryIndex(libraryFile, libStream);
+ loadLibraryIndex(libraryFile, libStream, false);
// Extract the data for the specified resource and return it
LibraryEntry &entry = _indexes[libraryFile][filename];
@@ -192,7 +197,7 @@ bool Resources::exists(const Common::String &filename) const {
}
void Resources::loadLibraryIndex(const Common::String &libFilename,
- Common::SeekableReadStream *stream) {
+ Common::SeekableReadStream *stream, bool isNewStyle) {
uint32 offset, nextOffset;
// Create an index entry
@@ -203,6 +208,9 @@ void Resources::loadLibraryIndex(const Common::String &libFilename,
stream->seek(4);
int count = stream->readUint16LE();
+ if (isNewStyle)
+ stream->seek((count + 1) * 8, SEEK_CUR);
+
// Loop through reading in the entries
for (int idx = 0; idx < count; ++idx) {
// Read the name of the resource
@@ -231,24 +239,48 @@ int Resources::resourceIndex() const {
return _resourceIndex;
}
-Common::SeekableReadStream *Resources::decompressLZ(Common::SeekableReadStream &source) {
- if (_vm->getGameID() == GType_SerratedScalpel) {
- uint32 id = source.readUint32BE();
- assert(id == MKTAG('L', 'Z', 'V', 0x1A));
- }
+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);
+
+ uint32 id = source.readUint32BE();
+ assert(id == MKTAG('L', 'Z', 'V', 0x1A));
+
+ uint32 outputSize = source.readUint32LE();
+ return decompressLZ(source, outputSize);
+}
+
+Common::SeekableReadStream *Resources::decompress(Common::SeekableReadStream &source, uint32 outSize) {
+ int inSize = (_vm->getGameID() == GType_RoseTattoo) ? source.readUint32LE() : -1;
+ byte *outBuffer = (byte *)malloc(outSize);
+ Common::MemoryReadStream *outStream = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
+
+ decompressLZ(source, outBuffer, outSize, inSize);
+
+ return outStream;
+}
- uint32 size = source.readUint32LE();
- return decompressLZ(source, size);
+void Resources::decompress(Common::SeekableReadStream &source, byte *buffer, uint32 outSize) {
+ int inputSize = (_vm->getGameID() == GType_RoseTattoo) ? source.readUint32LE() : -1;
+
+ decompressLZ(source, buffer, outSize, inputSize);
}
Common::SeekableReadStream *Resources::decompressLZ(Common::SeekableReadStream &source, uint32 outSize) {
+ byte *dataOut = (byte *)malloc(outSize);
+ decompressLZ(source, dataOut, outSize, -1);
+
+ return new Common::MemoryReadStream(dataOut, outSize, DisposeAfterUse::YES);
+}
+
+void Resources::decompressLZ(Common::SeekableReadStream &source, byte *outBuffer, int32 outSize, int32 inSize) {
byte lzWindow[4096];
uint16 lzWindowPos;
uint16 cmd;
- byte *outBuffer = (byte *)malloc(outSize);
byte *outBufferEnd = outBuffer + outSize;
- Common::MemoryReadStream *outS = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
+ int endPos = source.pos() + inSize;
memset(lzWindow, 0xFF, 0xFEE);
lzWindowPos = 0xFEE;
@@ -264,8 +296,7 @@ Common::SeekableReadStream *Resources::decompressLZ(Common::SeekableReadStream &
*outBuffer++ = literal;
lzWindow[lzWindowPos] = literal;
lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
- }
- else {
+ } else {
int copyPos, copyLen;
copyPos = source.readByte();
copyLen = source.readByte();
@@ -279,9 +310,7 @@ Common::SeekableReadStream *Resources::decompressLZ(Common::SeekableReadStream &
lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
}
}
- } while (outBuffer < outBufferEnd);
-
- return outS;
+ } while ((outSize == -1 || outBuffer < outBufferEnd) || (inSize == -1 || source.pos() < endPos));
}
/*----------------------------------------------------------------*/
@@ -325,13 +354,14 @@ void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette, bool
// 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._offset.y = stream.readByte();
frame._rleEncoded = !skipPalette && frame._rleEncoded;
if (frame._paletteBase) {
@@ -385,6 +415,28 @@ void ImageFile::decompressFrame(ImageFrame &frame, const byte *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();
diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h
index fb91b30f94..659ecf0110 100644
--- a/engines/sherlock/resources.h
+++ b/engines/sherlock/resources.h
@@ -90,7 +90,7 @@ private:
/**
* Reads in the index from a library file, and caches it's index for later use
*/
- void loadLibraryIndex(const Common::String &libFilename, Common::SeekableReadStream *stream);
+ void loadLibraryIndex(const Common::String &libFilename, Common::SeekableReadStream *stream, bool isNewStyle);
public:
Resources(SherlockEngine *vm);
@@ -140,14 +140,29 @@ public:
int resourceIndex() const;
/**
- * Decompresses an LZW block of data with a specified output size
+ * Decompresses LZW compressed data
+ */
+ Common::SeekableReadStream *decompress(Common::SeekableReadStream &source);
+
+ /**
+ * Decompresses LZW compressed data
+ */
+ Common::SeekableReadStream *decompress(Common::SeekableReadStream &source, uint32 outSize);
+
+ /**
+ * Decompresses LZW compressed data
+ */
+ void decompress(Common::SeekableReadStream &source, byte *buffer, uint32 outSize);
+
+ /**
+ * Decompresses LZW compressed data
*/
static Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source, uint32 outSize);
-
+
/**
- * Decompress an LZW compressed resource
+ * Decompresses LZW compressed data
*/
- Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source);
+ static void decompressLZ(Common::SeekableReadStream &source, byte *outBuffer, int32 outSize, int32 inSize);
};
struct ImageFrame {
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index 7875f22c47..ccc9c8abca 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -23,6 +23,7 @@
#include "sherlock/scalpel/scalpel.h"
#include "sherlock/sherlock.h"
#include "sherlock/animation.h"
+#include "engines/util.h"
namespace Sherlock {
@@ -378,6 +379,9 @@ ScalpelEngine::~ScalpelEngine() {
}
void ScalpelEngine::initialize() {
+ initGraphics(320, 200, false);
+
+ // Let the base engine intialize
SherlockEngine::initialize();
_darts = new Darts(this);
@@ -386,6 +390,13 @@ void ScalpelEngine::initialize() {
_flags[3] = true; // Turn on Alley
_flags[39] = true; // Turn on Baker Street
+ // Add some more files to the cache
+ _res->addToCache("portrait.lib");
+ _res->addToCache("sequence.txt");
+ _res->addToCache("EPILOGUE.SND");
+ _res->addToCache("snd.snd");
+ _res->addToCache("title.snd");
+
if (!isDemo()) {
// Load the map co-ordinates for each scene and sequence data
_map->loadPoints(NUM_PLACES, &MAP_X[0], &MAP_Y[0], &MAP_TRANSLATE[0]);
@@ -579,9 +590,9 @@ bool ScalpelEngine::scrollCredits() {
_screen->transBlitFrom(creditsImages[1], Common::Point(10, 400 - idx), false, 0);
// Don't show credit text on the top and bottom ten rows of the screen
- _screen->blitFrom(_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, 10));
- _screen->blitFrom(_screen->_backBuffer1, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - 10),
- Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 10, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+ _screen->blitFrom(_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, _screen->w(), 10));
+ _screen->blitFrom(_screen->_backBuffer1, Common::Point(0, _screen->h() - 10),
+ Common::Rect(0, _screen->h() - 10, _screen->w(), _screen->h()));
_events->delay(100);
}
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 5ae7e25258..2c80bfbd39 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -23,6 +23,7 @@
#include "sherlock/scene.h"
#include "sherlock/sherlock.h"
#include "sherlock/scalpel/scalpel.h"
+#include "sherlock/screen.h"
namespace Sherlock {
@@ -33,13 +34,38 @@ static const int FS_TRANS[8] = {
/*----------------------------------------------------------------*/
-void BgFileHeader::load(Common::SeekableReadStream &s) {
+BgFileHeader::BgFileHeader() {
+ _numStructs = -1;
+ _numImages = -1;
+ _numcAnimations = -1;
+ _descSize = -1;
+ _seqSize = -1;
+
+ // Serrated Scalpel
+ _fill = -1;
+
+ // Rose Tattoo
+ _scrollSize = -1;
+ _bytesWritten = -1;
+ _fadeStyle = -1;
+ Common::fill(&_palette[0], &_palette[PALETTE_SIZE], 0);
+}
+
+void BgFileHeader::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
_numStructs = s.readUint16LE();
_numImages = s.readUint16LE();
_numcAnimations = s.readUint16LE();
_descSize = s.readUint16LE();
_seqSize = s.readUint16LE();
- _fill = s.readUint16LE();
+
+ if (isRoseTattoo) {
+ _scrollSize = s.readUint16LE();
+ _bytesWritten = s.readUint32LE();
+ _fadeStyle = s.readByte();
+ } else {
+ _fill = s.readUint16LE();
+
+ }
}
/*----------------------------------------------------------------*/
@@ -55,18 +81,30 @@ void BgFileHeaderInfo::load(Common::SeekableReadStream &s) {
/*----------------------------------------------------------------*/
-void Exit::load(Common::SeekableReadStream &s) {
- int xp = s.readSint16LE();
- int yp = s.readSint16LE();
- int xSize = s.readSint16LE();
- int ySize = s.readSint16LE();
- _bounds = Common::Rect(xp, yp, xp + xSize, yp + ySize);
+void Exit::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
+ if (isRoseTattoo) {
+ char buffer[41];
+ s.read(buffer, 41);
+ _dest = Common::String(buffer);
+ }
+ left = s.readSint16LE();
+ top = s.readSint16LE();
+ setWidth(s.readUint16LE());
+ setHeight(s.readUint16LE());
+
+ _image = isRoseTattoo ? s.readByte() : 0;
_scene = s.readSint16LE();
- _allow = s.readSint16LE();
+
+ if (!isRoseTattoo)
+ _allow = s.readSint16LE();
+
_people.x = s.readSint16LE();
_people.y = s.readSint16LE();
_peopleDir = s.readUint16LE();
+
+ if (isRoseTattoo)
+ _allow = s.readSint16LE();
}
/*----------------------------------------------------------------*/
@@ -100,7 +138,19 @@ int ObjectArray::indexOf(const Object &obj) const {
/*----------------------------------------------------------------*/
-Scene::Scene(SherlockEngine *vm) : _vm(vm) {
+void ScaleZone::load(Common::SeekableReadStream &s) {
+ left = s.readSint16LE();
+ top = s.readSint16LE();
+ setWidth(s.readUint16LE());
+ setHeight(s.readUint16LE());
+
+ _topNumber = s.readByte();
+ _bottomNumber = s.readByte();
+}
+
+/*----------------------------------------------------------------*/
+
+Scene::Scene(SherlockEngine *vm): _vm(vm) {
for (int idx = 0; idx < SCENES_COUNT; ++idx)
Common::fill(&_sceneStats[idx][0], &_sceneStats[idx][65], false);
_currentScene = -1;
@@ -115,6 +165,7 @@ Scene::Scene(SherlockEngine *vm) : _vm(vm) {
_animating = 0;
_doBgAnimDone = true;
_tempFadeStyle = 0;
+ _exitZone = -1;
}
Scene::~Scene() {
@@ -194,6 +245,7 @@ bool Scene::loadScene(const Common::String &filename) {
Events &events = *_vm->_events;
Map &map = *_vm->_map;
People &people = *_vm->_people;
+ Resources &res = *_vm->_res;
SaveManager &saves = *_vm->_saves;
Screen &screen = *_vm->_screen;
Sound &sound = *_vm->_sound;
@@ -213,7 +265,7 @@ bool Scene::loadScene(const Common::String &filename) {
_sequenceBuffer.clear();
//
- // Load background shapes from <filename>.rrm
+ // Load the room resource file for the scene
//
Common::String rrmFile = filename + ".rrm";
@@ -222,15 +274,35 @@ bool Scene::loadScene(const Common::String &filename) {
Common::SeekableReadStream *rrmStream = _vm->_res->load(rrmFile);
rrmStream->seek(39);
- _version = rrmStream->readByte();
- _lzwMode = _version == 10;
+ if (IS_SERRATED_SCALPEL) {
+ _version = rrmStream->readByte();
+ _lzwMode = _version == 10;
+ } else {
+ _lzwMode = rrmStream->readByte() > 0;
+ }
// Go to header and read it in
rrmStream->seek(rrmStream->readUint32LE());
+
BgFileHeader bgHeader;
- bgHeader.load(*rrmStream);
+ bgHeader.load(*rrmStream, IS_ROSE_TATTOO);
_invGraphicItems = bgHeader._numImages + 1;
+ if (IS_ROSE_TATTOO) {
+ screen.initPaletteFade(bgHeader._bytesWritten);
+ screen.fadeRead(*rrmStream, screen._cMap, PALETTE_SIZE);
+ screen.setupBGArea(screen._cMap);
+
+ screen.initScrollVars();
+
+ // Read in background
+ if (_lzwMode) {
+ res.decompress(*rrmStream, (byte *)screen._backBuffer1.getPixels(), SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCREEN_HEIGHT);
+ } else {
+ rrmStream->read(screen._backBuffer1.getPixels(), SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCREEN_HEIGHT);
+ }
+ }
+
// Read in the shapes header info
Common::Array<BgFileHeaderInfo> bgInfo;
bgInfo.resize(bgHeader._numStructs);
@@ -239,10 +311,30 @@ bool Scene::loadScene(const Common::String &filename) {
bgInfo[idx].load(*rrmStream);
// Read information
- if (!_lzwMode) {
+ if (IS_SERRATED_SCALPEL) {
+ Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream :
+ res.decompress(*rrmStream, bgHeader._numStructs * 569 + bgHeader._descSize + bgHeader._seqSize);
+
_bgShapes.resize(bgHeader._numStructs);
for (int idx = 0; idx < bgHeader._numStructs; ++idx)
- _bgShapes[idx].load(*rrmStream);
+ _bgShapes[idx].load(*infoStream, false);
+
+ if (bgHeader._descSize) {
+ _descText.resize(bgHeader._descSize);
+ infoStream->read(&_descText[0], bgHeader._descSize);
+ }
+
+ if (bgHeader._seqSize) {
+ _sequenceBuffer.resize(bgHeader._seqSize);
+ infoStream->read(&_sequenceBuffer[0], bgHeader._seqSize);
+ }
+
+ if (_lzwMode)
+ delete infoStream;
+ } else if (!_lzwMode) {
+ _bgShapes.resize(bgHeader._numStructs);
+ for (int idx = 0; idx < bgHeader._numStructs; ++idx)
+ _bgShapes[idx].load(*rrmStream, false);
if (bgHeader._descSize) {
_descText.resize(bgHeader._descSize);
@@ -261,7 +353,7 @@ bool Scene::loadScene(const Common::String &filename) {
_bgShapes.resize(bgHeader._numStructs);
for (int idx = 0; idx < bgHeader._numStructs; ++idx)
- _bgShapes[idx].load(*infoStream);
+ _bgShapes[idx].load(*infoStream, false);
delete infoStream;
@@ -294,7 +386,7 @@ bool Scene::loadScene(const Common::String &filename) {
// Read in the image data
Common::SeekableReadStream *imageStream = _lzwMode ?
- Resources::decompressLZ(*rrmStream, bgInfo[idx]._filesize) :
+ res.decompress(*rrmStream, bgInfo[idx]._filesize) :
rrmStream->readStream(bgInfo[idx]._filesize);
_images[idx + 1]._images = new ImageFile(*imageStream);
@@ -322,13 +414,14 @@ bool Scene::loadScene(const Common::String &filename) {
// Load in cAnim list
_cAnim.clear();
if (bgHeader._numcAnimations) {
+ int animSize = IS_SERRATED_SCALPEL ? 65 : 47;
Common::SeekableReadStream *canimStream = _lzwMode ?
- Resources::decompressLZ(*rrmStream, 65 * bgHeader._numcAnimations) :
- rrmStream->readStream(65 * bgHeader._numcAnimations);
+ res.decompress(*rrmStream, animSize * bgHeader._numcAnimations) :
+ rrmStream->readStream(animSize * bgHeader._numcAnimations);
_cAnim.resize(bgHeader._numcAnimations);
for (uint idx = 0; idx < _cAnim.size(); ++idx)
- _cAnim[idx].load(*canimStream);
+ _cAnim[idx].load(*canimStream, IS_ROSE_TATTOO);
delete canimStream;
}
@@ -336,7 +429,7 @@ bool Scene::loadScene(const Common::String &filename) {
// Read in the room bounding areas
int size = rrmStream->readUint16LE();
Common::SeekableReadStream *boundsStream = !_lzwMode ? rrmStream :
- Resources::decompressLZ(*rrmStream, size);
+ res.decompress(*rrmStream, size);
_zones.resize(size / 10);
for (uint idx = 0; idx < _zones.size(); ++idx) {
@@ -351,10 +444,11 @@ bool Scene::loadScene(const Common::String &filename) {
delete boundsStream;
// Ensure we've reached the path version byte
- if (rrmStream->readByte() != 254)
+ if (rrmStream->readByte() != (IS_SERRATED_SCALPEL ? 254 : 251))
error("Invalid scene path data");
// Load the walk directory
+ assert(_zones.size() < MAX_ZONES);
for (uint idx1 = 0; idx1 < _zones.size(); ++idx1) {
for (uint idx2 = 0; idx2 < _zones.size(); ++idx2)
_walkDirectory[idx1][idx2] = rrmStream->readSint16LE();
@@ -363,7 +457,7 @@ bool Scene::loadScene(const Common::String &filename) {
// Read in the walk data
size = rrmStream->readUint16LE();
Common::SeekableReadStream *walkStream = !_lzwMode ? rrmStream :
- Resources::decompressLZ(*rrmStream, size);
+ res.decompress(*rrmStream, size);
_walkData.resize(size);
walkStream->read(&_walkData[0], size);
@@ -371,15 +465,27 @@ bool Scene::loadScene(const Common::String &filename) {
if (_lzwMode)
delete walkStream;
+ if (IS_ROSE_TATTOO) {
+ // Read in the entrance
+ _entrance.load(*rrmStream);
+
+ // Load scale zones
+ _scaleZones.resize(rrmStream->readByte());
+ for (uint idx = 0; idx < _scaleZones.size(); ++idx)
+ _scaleZones[idx].load(*rrmStream);
+ }
+
// Read in the exits
+ _exitZone = -1;
int numExits = rrmStream->readByte();
_exits.resize(numExits);
for (int idx = 0; idx < numExits; ++idx)
- _exits[idx].load(*rrmStream);
+ _exits[idx].load(*rrmStream, IS_ROSE_TATTOO);
- // Read in the entrance
- _entrance.load(*rrmStream);
+ if (IS_SERRATED_SCALPEL)
+ // Read in the entrance
+ _entrance.load(*rrmStream);
// Initialize sound list
int numSounds = rrmStream->readByte();
@@ -388,24 +494,34 @@ bool Scene::loadScene(const Common::String &filename) {
for (int idx = 0; idx < numSounds; ++idx)
_sounds[idx].load(*rrmStream);
- for (int idx = 0; idx < numSounds; ++idx)
- sound.loadSound(_sounds[idx]._name, _sounds[idx]._priority);
+ loadSceneSounds();
- // Read in palette
- rrmStream->read(screen._cMap, PALETTE_SIZE);
- for (int idx = 0; idx < PALETTE_SIZE; ++idx)
- screen._cMap[idx] = VGA_COLOR_TRANS(screen._cMap[idx]);
+ if (IS_ROSE_TATTOO) {
+ // Load the object sound list
+ char buffer[27];
+
+ _objSoundList.resize(rrmStream->readUint16LE());
+ for (uint idx = 0; idx < _objSoundList.size(); ++idx) {
+ rrmStream->read(buffer, 27);
+ _objSoundList[idx] = Common::String(buffer);
+ }
+ } else {
+ // Read in palette
+ rrmStream->read(screen._cMap, PALETTE_SIZE);
+ for (int idx = 0; idx < PALETTE_SIZE; ++idx)
+ screen._cMap[idx] = VGA_COLOR_TRANS(screen._cMap[idx]);
- Common::copy(screen._cMap, screen._cMap + PALETTE_SIZE, screen._sMap);
+ Common::copy(screen._cMap, screen._cMap + PALETTE_SIZE, screen._sMap);
- // Read in the background
- Common::SeekableReadStream *bgStream = !_lzwMode ? rrmStream :
- Resources::decompressLZ(*rrmStream, SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT);
+ // Read in the background
+ Common::SeekableReadStream *bgStream = !_lzwMode ? rrmStream :
+ res.decompress(*rrmStream, SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT);
- bgStream->read(screen._backBuffer1.getPixels(), SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT);
+ bgStream->read(screen._backBuffer1.getPixels(), SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT);
- if (_lzwMode)
- delete bgStream;
+ if (_lzwMode)
+ delete bgStream;
+ }
// Backup the image and set the palette
screen._backBuffer2.blitFrom(screen._backBuffer1);
@@ -472,6 +588,13 @@ bool Scene::loadScene(const Common::String &filename) {
return flag;
}
+void Scene::loadSceneSounds() {
+ Sound &sound = *_vm->_sound;
+
+ for (uint idx = 0; idx < _sounds.size(); ++idx)
+ sound.loadSound(_sounds[idx]._name, _sounds[idx]._priority);
+}
+
void Scene::checkSceneStatus() {
if (_sceneStats[_currentScene][64]) {
for (uint idx = 0; idx < 64; ++idx) {
@@ -793,7 +916,7 @@ void Scene::updateBackground() {
Exit *Scene::checkForExit(const Common::Rect &r) {
for (uint idx = 0; idx < _exits.size(); ++idx) {
- if (_exits[idx]._bounds.intersects(r))
+ if (_exits[idx].intersects(r))
return &_exits[idx];
}
@@ -1112,7 +1235,7 @@ void Scene::doBgAnim() {
_canimShapes[idx].checkObject();
}
- if (_currentScene == 12 && _vm->getGameID() == GType_SerratedScalpel)
+ if (_currentScene == 12 && IS_SERRATED_SCALPEL)
((Scalpel::ScalpelEngine *)_vm)->eraseMirror12();
// Restore the back buffer from the back buffer 2 in the changed area
@@ -1185,7 +1308,7 @@ void Scene::doBgAnim() {
checkBgShapes(people[AL]._imageFrame,
Common::Point(people[AL]._position.x / 100, people[AL]._position.y / 100));
- if (_currentScene == 12 && _vm->getGameID() == GType_SerratedScalpel)
+ if (_currentScene == 12 && IS_SERRATED_SCALPEL)
((Scalpel::ScalpelEngine *)_vm)->doMirror12();
// Draw all active shapes which are behind the person
@@ -1295,7 +1418,7 @@ void Scene::doBgAnim() {
}
}
- if (_currentScene == 12 && _vm->getGameID() == GType_SerratedScalpel)
+ if (_currentScene == 12 && IS_SERRATED_SCALPEL)
((Scalpel::ScalpelEngine *)_vm)->flushMirror12();
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index 88d12a3fb0..0cbd775c56 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -29,6 +29,7 @@
#include "common/serializer.h"
#include "sherlock/objects.h"
#include "sherlock/resources.h"
+#include "sherlock/screen.h"
namespace Sherlock {
@@ -44,12 +45,23 @@ struct BgFileHeader {
int _numcAnimations;
int _descSize;
int _seqSize;
+
+ // Serrated Scalpel
int _fill;
+ // Rose Tattoo
+ int _scrollSize;
+ int _bytesWritten; // Size of the main body of the RRM
+ int _fadeStyle; // Fade style
+ byte _palette[PALETTE_SIZE]; // Palette
+
+
+ BgFileHeader();
+
/**
* Load the data for the object
*/
- void load(Common::SeekableReadStream &s);
+ void load(Common::SeekableReadStream &s, bool isRoseTattoo);
};
struct BgFileHeaderInfo {
@@ -63,18 +75,20 @@ struct BgFileHeaderInfo {
void load(Common::SeekableReadStream &s);
};
-struct Exit {
- Common::Rect _bounds;
-
+class Exit: public Common::Rect {
+public:
int _scene;
int _allow;
Common::Point _people;
int _peopleDir;
+ Common::String _dest;
+ int _image; // Arrow image to use
+
/**
* Load the data for the object
*/
- void load(Common::SeekableReadStream &s);
+ void load(Common::SeekableReadStream &s, bool isRoseTattoo);
};
struct SceneEntry {
@@ -106,6 +120,14 @@ public:
int indexOf(const Object &obj) const;
};
+class ScaleZone: public Common::Rect {
+public:
+ int _topNumber; // Numerator of scale size at the top of the zone
+ int _bottomNumber; // Numerator of scale size at the bottom of the zone
+
+ void load(Common::SeekableReadStream &s);
+};
+
class Scene {
private:
SherlockEngine *_vm;
@@ -124,6 +146,11 @@ private:
bool loadScene(const Common::String &filename);
/**
+ * Loads sounds for the scene
+ */
+ void loadSceneSounds();
+
+ /**
* Set objects to their current persistent state. This includes things such as
* opening or moving them
*/
@@ -154,6 +181,7 @@ private:
* will remain the same on future visits to the scene
*/
void saveSceneStatus();
+
public:
int _currentScene;
int _goToScene;
@@ -173,9 +201,12 @@ public:
int _walkDirectory[MAX_ZONES][MAX_ZONES];
Common::Array<byte> _walkData;
Common::Array<Exit> _exits;
+ int _exitZone;
SceneEntry _entrance;
Common::Array<SceneSound> _sounds;
ObjectArray _canimShapes;
+ Common::Array<ScaleZone> _scaleZones;
+ Common::StringArray _objSoundList;
bool _restoreFlag;
int _animating;
bool _doBgAnimDone;
diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp
index e70d0614d1..24f7660743 100644
--- a/engines/sherlock/screen.cpp
+++ b/engines/sherlock/screen.cpp
@@ -28,9 +28,9 @@
namespace Sherlock {
-Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), _vm(vm),
- _backBuffer1(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT),
- _backBuffer2(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT),
+Screen::Screen(SherlockEngine *vm) : Surface(g_system->getWidth(), g_system->getHeight()), _vm(vm),
+ _backBuffer1(g_system->getWidth(), g_system->getHeight()),
+ _backBuffer2(g_system->getWidth(), g_system->getHeight()),
_backBuffer(&_backBuffer1) {
_transitionSeed = 1;
_fadeStyle = false;
@@ -38,7 +38,15 @@ Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCR
_fontHeight = 0;
Common::fill(&_cMap[0], &_cMap[PALETTE_SIZE], 0);
Common::fill(&_sMap[0], &_sMap[PALETTE_SIZE], 0);
+ Common::fill(&_tMap[0], &_tMap[PALETTE_SIZE], 0);
setFont(1);
+
+ // Rose Tattoo specific fields
+ _fadeBytesRead = _fadeBytesToRead = 0;
+ _oldFadePercent = 0;
+ _scrollSize = 0;
+ _currentScroll = 0;
+ _targetScroll = 0;
}
Screen::~Screen() {
@@ -179,7 +187,7 @@ void Screen::randomTransition() {
_transitionSeed = _transitionSeed * TRANSITION_MULTIPLIER + 1;
int offset = _transitionSeed & 0xFFFF;
- if (offset < (SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCREEN_HEIGHT))
+ if (offset < (this->w() * this->h()))
*((byte *)getPixels() + offset) = *((const byte *)_backBuffer->getPixels() + offset);
if (idx != 0 && (idx % 300) == 0) {
@@ -199,12 +207,12 @@ void Screen::randomTransition() {
void Screen::verticalTransition() {
Events &events = *_vm->_events;
- byte table[SHERLOCK_SCREEN_WIDTH];
- Common::fill(&table[0], &table[SHERLOCK_SCREEN_WIDTH], 0);
+ byte table[640];
+ Common::fill(&table[0], &table[640], 0);
- for (int yp = 0; yp < SHERLOCK_SCREEN_HEIGHT; ++yp) {
- for (int xp = 0; xp < SHERLOCK_SCREEN_WIDTH; ++xp) {
- int temp = (table[xp] >= 197) ? SHERLOCK_SCREEN_HEIGHT - table[xp] :
+ for (int yp = 0; yp < this->h(); ++yp) {
+ for (int xp = 0; xp < this->w(); ++xp) {
+ int temp = (table[xp] >= (this->h() - 3)) ? this->h() - table[xp] :
_vm->getRandomNumber(3) + 1;
if (temp) {
@@ -221,7 +229,7 @@ void Screen::verticalTransition() {
void Screen::restoreBackground(const Common::Rect &r) {
if (r.width() > 0 && r.height() > 0) {
Common::Rect tempRect = r;
- tempRect.clip(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
+ tempRect.clip(Common::Rect(0, 0, this->w(), SHERLOCK_SCENE_HEIGHT));
if (tempRect.isValidRect())
_backBuffer1.blitFrom(_backBuffer2, Common::Point(tempRect.left, tempRect.top), tempRect);
@@ -235,7 +243,7 @@ void Screen::slamArea(int16 xp, int16 yp, int16 width, int16 height) {
void Screen::slamRect(const Common::Rect &r) {
if (r.width() && r.height() > 0) {
Common::Rect tempRect = r;
- tempRect.clip(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+ tempRect.clip(Common::Rect(0, 0, this->w(), this->h()));
if (tempRect.isValidRect())
blitFrom(*_backBuffer, Common::Point(tempRect.left, tempRect.top), tempRect);
@@ -281,13 +289,13 @@ void Screen::print(const Common::Point &pt, byte color, const char *formatStr, .
pos.y--; // Font is always drawing one line higher
if (!pos.x)
// Center text horizontally
- pos.x = (SHERLOCK_SCREEN_WIDTH - width) / 2;
+ pos.x = (this->w() - width) / 2;
Common::Rect textBounds(pos.x, pos.y, pos.x + width, pos.y + _fontHeight);
- if (textBounds.right > SHERLOCK_SCREEN_WIDTH)
- textBounds.moveTo(SHERLOCK_SCREEN_WIDTH - width, textBounds.top);
- if (textBounds.bottom > SHERLOCK_SCREEN_HEIGHT)
- textBounds.moveTo(textBounds.left, SHERLOCK_SCREEN_HEIGHT - _fontHeight);
+ if (textBounds.right > this->w())
+ textBounds.moveTo(this->w() - width, textBounds.top);
+ if (textBounds.bottom > this->h())
+ textBounds.moveTo(textBounds.left, this->h() - _fontHeight);
// Write out the string at the given position
writeString(str, Common::Point(textBounds.left, textBounds.top), color);
@@ -416,7 +424,7 @@ void Screen::resetDisplayBounds() {
Common::Rect Screen::getDisplayBounds() {
return (_backBuffer == &_sceneSurface) ? Common::Rect(0, 0, _sceneSurface.w(), _sceneSurface.h()) :
- Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
+ Common::Rect(0, 0, this->w(), this->h());
}
void Screen::synchronize(Common::Serializer &s) {
@@ -426,4 +434,36 @@ void Screen::synchronize(Common::Serializer &s) {
setFont(fontNumb);
}
+void Screen::initPaletteFade(int bytesToRead) {
+ Common::copy(&_cMap[0], &_cMap[PALETTE_SIZE], &_sMap[0]);
+ Common::copy(&_cMap[0], &_cMap[PALETTE_SIZE], &_tMap[0]);
+
+ // Set how many bytes need to be read / have been read
+ _fadeBytesRead = 0;
+ _fadeBytesToRead = bytesToRead;
+ _oldFadePercent = 0;
+}
+
+int Screen::fadeRead(Common::SeekableReadStream &stream, byte *buf, int totalSize) {
+ warning("TODO: fadeRead");
+ stream.read(buf, totalSize);
+ return totalSize;
+}
+
+/**
+ * Creates a grey-scale version of the passed palette
+ */
+void Screen::setupBGArea(const byte cMap[PALETTE_SIZE]) {
+ warning("TODO");
+}
+
+/**
+ * Initializes scroll variables
+ */
+void Screen::initScrollVars() {
+ _scrollSize = 0;
+ _currentScroll = 0;
+ _targetScroll = 0;
+}
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h
index a2c0aa3c84..f4cd6fd955 100644
--- a/engines/sherlock/screen.h
+++ b/engines/sherlock/screen.h
@@ -66,6 +66,15 @@ private:
int _fontHeight;
Surface _sceneSurface;
+ // Rose Tattoo fields
+ int _fadeBytesRead, _fadeBytesToRead;
+ int _oldFadePercent;
+ byte _lookupTable[PALETTE_COUNT];
+ byte _lookupTable1[PALETTE_COUNT];
+ int _scrollSize;
+ int _currentScroll;
+ int _targetScroll;
+private:
/**
* Merges together overlapping dirty areas of the screen
*/
@@ -92,6 +101,7 @@ public:
bool _fadeStyle;
byte _cMap[PALETTE_SIZE];
byte _sMap[PALETTE_SIZE];
+ byte _tMap[PALETTE_SIZE];
public:
Screen(SherlockEngine *vm);
virtual ~Screen();
@@ -232,6 +242,15 @@ public:
* Synchronize the data for a savegame
*/
void synchronize(Common::Serializer &s);
+
+ // Rose Tattoo specific methods
+ void initPaletteFade(int bytesToRead);
+
+ int fadeRead(Common::SeekableReadStream &stream, byte *buf, int totalSize);
+
+ void setupBGArea(const byte cMap[PALETTE_SIZE]);
+
+ void initScrollVars();
};
} // End of namespace Sherlock
diff --git a/engines/sherlock/settings.cpp b/engines/sherlock/settings.cpp
index bf5294f08b..cae5c6c67a 100644
--- a/engines/sherlock/settings.cpp
+++ b/engines/sherlock/settings.cpp
@@ -209,9 +209,10 @@ void Settings::show(SherlockEngine *vm) {
Screen &screen = *vm->_screen;
Sound &sound = *vm->_sound;
Talk &talk = *vm->_talk;
- UserInterface &ui = *vm->_ui;
+ ScalpelUserInterface &ui = *(ScalpelUserInterface *)vm->_ui;
bool updateConfig = false;
+ assert(vm->getGameID() == GType_SerratedScalpel);
Settings settings(vm);
settings.drawInteface(false);
diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp
index d4644d4d9d..5973823f96 100644
--- a/engines/sherlock/sherlock.cpp
+++ b/engines/sherlock/sherlock.cpp
@@ -25,7 +25,6 @@
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/debug-channels.h"
-#include "engines/util.h"
namespace Sherlock {
@@ -70,8 +69,6 @@ SherlockEngine::~SherlockEngine() {
}
void SherlockEngine::initialize() {
- initGraphics(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT, false);
-
DebugMan.addDebugChannel(kDebugScript, "scripts", "Script debug level");
ImageFile::setVm(this);
@@ -99,7 +96,7 @@ void SherlockEngine::initialize() {
_screen = new Screen(this);
_sound = new Sound(this, _mixer);
_talk = new Talk(this);
- _ui = new UserInterface(this);
+ _ui = UserInterface::init(this);
// Load game settings
loadConfig();
diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h
index 24a72076ef..bf8c0d6aaf 100644
--- a/engines/sherlock/sherlock.h
+++ b/engines/sherlock/sherlock.h
@@ -58,8 +58,8 @@ enum GameType {
GType_RoseTattoo = 1
};
-#define SHERLOCK_SCREEN_WIDTH 320
-#define SHERLOCK_SCREEN_HEIGHT 200
+#define SHERLOCK_SCREEN_WIDTH _vm->_screen->w()
+#define SHERLOCK_SCREEN_HEIGHT _vm->_screen->h()
#define SHERLOCK_SCENE_HEIGHT 138
struct SherlockGameDescription;
@@ -197,6 +197,9 @@ public:
void synchronize(Common::Serializer &s);
};
+#define IS_ROSE_TATTOO (_vm->getGameID() == GType_RoseTattoo)
+#define IS_SERRATED_SCALPEL (_vm->getGameID() == GType_SerratedScalpel)
+
} // End of namespace Sherlock
#endif
diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp
index 4f27481f5b..06f6a0f264 100644
--- a/engines/sherlock/sound.cpp
+++ b/engines/sherlock/sound.cpp
@@ -63,6 +63,7 @@ Sound::Sound(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
_musicOn = true;
_speechOn = true;
+ _vm->_res->addToCache("MUSIC.LIB");
if (!_vm->_interactiveFl)
_vm->_res->addToCache("TITLE.SND");
else {
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index 319d1a383f..1a926a543d 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -172,9 +172,11 @@ void Talk::talkTo(const Common::String &filename) {
while (!_sequenceStack.empty())
pullSequence();
- // Restore any pressed button
- if (!ui._windowOpen && savedMode != STD_MODE)
- ui.restoreButton((int)(savedMode - 1));
+ if (IS_SERRATED_SCALPEL) {
+ // Restore any pressed button
+ if (!ui._windowOpen && savedMode != STD_MODE)
+ ((ScalpelUserInterface *)_vm->_ui)->restoreButton((int)(savedMode - 1));
+ }
// Clear the ui counter so that anything displayed on the info line
// before the window was opened isn't cleared
diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h
index d26259dbfd..48290e965e 100644
--- a/engines/sherlock/talk.h
+++ b/engines/sherlock/talk.h
@@ -123,10 +123,10 @@ struct TalkSequences {
};
class SherlockEngine;
-class UserInterface;
+class ScalpelUserInterface;
class Talk {
- friend class UserInterface;
+ friend class ScalpelUserInterface;
private:
SherlockEngine *_vm;
Common::Stack<SequenceEntry> _savedSequences;
diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp
index d4059ac413..3c684ff3ee 100644
--- a/engines/sherlock/tattoo/tattoo.cpp
+++ b/engines/sherlock/tattoo/tattoo.cpp
@@ -21,6 +21,7 @@
*/
#include "sherlock/tattoo/tattoo.h"
+#include "engines/util.h"
namespace Sherlock {
@@ -30,6 +31,33 @@ void TattooEngine::showOpening() {
// TODO
}
+/**
+ * Initialize the engine
+ */
+void TattooEngine::initialize() {
+ initGraphics(640, 480, true);
+
+ // Initialize the base engine
+ SherlockEngine::initialize();
+
+ _flags.resize(100 * 8);
+
+ // Add some more files to the cache
+ _res->addToCache("walk.lib");
+ _res->addToCache("sound.lib");
+
+ // Starting scene
+ _scene->_goToScene = 91;
+}
+
+/**
+ * Starting a scene within the game
+ */
+void TattooEngine::startScene() {
+ // TODO
+}
+
+
} // End of namespace Tattoo
} // End of namespace Scalpel
diff --git a/engines/sherlock/tattoo/tattoo.h b/engines/sherlock/tattoo/tattoo.h
index b98395597c..7bdeec55d1 100644
--- a/engines/sherlock/tattoo/tattoo.h
+++ b/engines/sherlock/tattoo/tattoo.h
@@ -31,10 +31,15 @@ namespace Tattoo {
class TattooEngine : public SherlockEngine {
protected:
+ virtual void initialize();
+
virtual void showOpening();
+
+ virtual void startScene();
public:
TattooEngine(OSystem *syst, const SherlockGameDescription *gameDesc) :
SherlockEngine(syst, gameDesc) {}
+
virtual ~TattooEngine() {}
};
diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp
index 524ecf3d2f..7a6722a218 100644
--- a/engines/sherlock/user_interface.cpp
+++ b/engines/sherlock/user_interface.cpp
@@ -78,57 +78,66 @@ const char *const MUSE[] = {
"Doors don't smoke"
};
-/*----------------------------------------------------------------*/
+
+
+UserInterface *UserInterface::init(SherlockEngine *vm) {
+ if (vm->getGameID() == GType_SerratedScalpel)
+ return new ScalpelUserInterface(vm);
+ else
+ return new TattooUserInterface(vm);
+}
UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) {
- if (_vm->_interactiveFl) {
- _controls = new ImageFile("menu.all");
- _controlPanel = new ImageFile("controls.vgs");
- } else {
- _controls = nullptr;
- _controlPanel = nullptr;
- }
+ _menuMode = STD_MODE;
+ _menuCounter = 0;
+ _infoFlag = false;
+ _windowOpen = false;
+ _endKeyActive = true;
+ _invLookFlag = 0;
+ _slideWindows = true;
+ _helpStyle = false;
+ _windowBounds = Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH - 1, SHERLOCK_SCREEN_HEIGHT - 1);
+ _lookScriptFlag = false;
+
+ _key = _oldKey = '\0';
+ _selector = _oldSelector = -1;
+ _temp = _oldTemp = 0;
+ _temp1 = 0;
+ _lookHelp = 0;
+}
+
+/*----------------------------------------------------------------*/
+ScalpelUserInterface::ScalpelUserInterface(SherlockEngine *vm): UserInterface(vm) {
+ _controls = new ImageFile("menu.all");
+ _controlPanel = new ImageFile("controls.vgs");
+ _keyPress = '\0';
+ _lookHelp = 0;
_bgFound = 0;
_oldBgFound = -1;
- _keyPress = '\0';
- _helpStyle = false;
- _menuCounter = 0;
- _menuMode = STD_MODE;
_help = _oldHelp = 0;
- _lookHelp = 0;
_key = _oldKey = '\0';
_temp = _oldTemp = 0;
- _temp1 = 0;
- _invLookFlag = 0;
- _windowOpen = false;
- _oldLook = false;
+ _oldLook = 0;
_keyboardInput = false;
_pause = false;
_cNum = 0;
- _selector = _oldSelector = -1;
- _windowBounds = Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH - 1,
- SHERLOCK_SCREEN_HEIGHT - 1);
- _slideWindows = true;
_find = 0;
_oldUse = 0;
- _endKeyActive = true;
- _lookScriptFlag = false;
- _infoFlag = false;
}
-UserInterface::~UserInterface() {
+ScalpelUserInterface::~ScalpelUserInterface() {
delete _controls;
delete _controlPanel;
}
-void UserInterface::reset() {
+void ScalpelUserInterface::reset() {
_oldKey = -1;
_help = _oldHelp = -1;
_oldTemp = _temp = -1;
}
-void UserInterface::drawInterface(int bufferNum) {
+void ScalpelUserInterface::drawInterface(int bufferNum) {
Screen &screen = *_vm->_screen;
if (bufferNum & 1)
@@ -139,7 +148,7 @@ void UserInterface::drawInterface(int bufferNum) {
screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK);
}
-void UserInterface::handleInput() {
+void ScalpelUserInterface::handleInput() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
People &people = *_vm->_people;
@@ -392,7 +401,7 @@ void UserInterface::handleInput() {
}
}
-void UserInterface::depressButton(int num) {
+void ScalpelUserInterface::depressButton(int num) {
Screen &screen = *_vm->_screen;
Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]);
@@ -401,7 +410,7 @@ void UserInterface::depressButton(int num) {
screen.slamArea(pt.x, pt.y, pt.x + frame._width, pt.y + frame._height);
}
-void UserInterface::restoreButton(int num) {
+void ScalpelUserInterface::restoreButton(int num) {
Screen &screen = *_vm->_screen;
Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]);
Graphics::Surface &frame = (*_controls)[num]._frame;
@@ -416,7 +425,7 @@ void UserInterface::restoreButton(int num) {
}
}
-void UserInterface::pushButton(int num) {
+void ScalpelUserInterface::pushButton(int num) {
Events &events = *_vm->_events;
_oldKey = -1;
@@ -433,7 +442,7 @@ void UserInterface::pushButton(int num) {
restoreButton(num);
}
-void UserInterface::toggleButton(int num) {
+void ScalpelUserInterface::toggleButton(int num) {
Screen &screen = *_vm->_screen;
if (_menuMode != (MenuMode)(num + 1)) {
@@ -461,7 +470,7 @@ void UserInterface::toggleButton(int num) {
}
}
-void UserInterface::clearInfo() {
+void ScalpelUserInterface::clearInfo() {
if (_infoFlag) {
_vm->_screen->vgaBar(Common::Rect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 19,
INFO_LINE + 10), INFO_BLACK);
@@ -470,14 +479,14 @@ void UserInterface::clearInfo() {
}
}
-void UserInterface::clearWindow() {
+void ScalpelUserInterface::clearWindow() {
if (_windowOpen) {
_vm->_screen->vgaBar(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2,
SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND);
}
}
-void UserInterface::whileMenuCounter() {
+void ScalpelUserInterface::whileMenuCounter() {
if (!(--_menuCounter) || _vm->_events->checkInput()) {
_menuCounter = 0;
_infoFlag = true;
@@ -485,7 +494,7 @@ void UserInterface::whileMenuCounter() {
}
}
-void UserInterface::examine() {
+void ScalpelUserInterface::examine() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
People &people = *_vm->_people;
@@ -536,7 +545,7 @@ void UserInterface::examine() {
}
}
-void UserInterface::lookScreen(const Common::Point &pt) {
+void ScalpelUserInterface::lookScreen(const Common::Point &pt) {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
Scene &scene = *_vm->_scene;
@@ -649,7 +658,7 @@ void UserInterface::lookScreen(const Common::Point &pt) {
}
}
-void UserInterface::lookInv() {
+void ScalpelUserInterface::lookInv() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
Screen &screen = *_vm->_screen;
@@ -674,7 +683,7 @@ void UserInterface::lookInv() {
}
}
-void UserInterface::doEnvControl() {
+void ScalpelUserInterface::doEnvControl() {
Events &events = *_vm->_events;
SaveManager &saves = *_vm->_saves;
Scene &scene = *_vm->_scene;
@@ -976,7 +985,7 @@ void UserInterface::doEnvControl() {
}
}
-void UserInterface::doInvControl() {
+void ScalpelUserInterface::doInvControl() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
Scene &scene = *_vm->_scene;
@@ -1199,7 +1208,7 @@ void UserInterface::doInvControl() {
}
}
-void UserInterface::doLookControl() {
+void ScalpelUserInterface::doLookControl() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
Screen &screen = *_vm->_screen;
@@ -1260,7 +1269,7 @@ void UserInterface::doLookControl() {
}
}
-void UserInterface::doMainControl() {
+void ScalpelUserInterface::doMainControl() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
SaveManager &saves = *_vm->_saves;
@@ -1398,7 +1407,7 @@ void UserInterface::doMainControl() {
}
}
-void UserInterface::doMiscControl(int allowed) {
+void ScalpelUserInterface::doMiscControl(int allowed) {
Events &events = *_vm->_events;
Scene &scene = *_vm->_scene;
Talk &talk = *_vm->_talk;
@@ -1447,7 +1456,7 @@ void UserInterface::doMiscControl(int allowed) {
}
}
-void UserInterface::doPickControl() {
+void ScalpelUserInterface::doPickControl() {
Events &events = *_vm->_events;
Scene &scene = *_vm->_scene;
Talk &talk = *_vm->_talk;
@@ -1470,7 +1479,7 @@ void UserInterface::doPickControl() {
}
}
-void UserInterface::doTalkControl() {
+void ScalpelUserInterface::doTalkControl() {
Events &events = *_vm->_events;
Journal &journal = *_vm->_journal;
People &people = *_vm->_people;
@@ -1720,7 +1729,7 @@ void UserInterface::doTalkControl() {
}
}
-void UserInterface::journalControl() {
+void ScalpelUserInterface::journalControl() {
Events &events = *_vm->_events;
Journal &journal = *_vm->_journal;
Scene &scene = *_vm->_scene;
@@ -1768,7 +1777,7 @@ void UserInterface::journalControl() {
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
}
-void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) {
+void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool firstTime) {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
Screen &screen = *_vm->_screen;
@@ -1936,11 +1945,11 @@ void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) {
}
}
-void UserInterface::printObjectDesc() {
+void ScalpelUserInterface::printObjectDesc() {
printObjectDesc(_cAnimStr, true);
}
-void UserInterface::summonWindow(const Surface &bgSurface, bool slideUp) {
+void ScalpelUserInterface::summonWindow(const Surface &bgSurface, bool slideUp) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
@@ -1979,7 +1988,7 @@ void UserInterface::summonWindow(const Surface &bgSurface, bool slideUp) {
_windowOpen = true;
}
-void UserInterface::summonWindow(bool slideUp, int height) {
+void ScalpelUserInterface::summonWindow(bool slideUp, int height) {
Screen &screen = *_vm->_screen;
// Extract the window that's been drawn on the back buffer
@@ -1996,7 +2005,7 @@ void UserInterface::summonWindow(bool slideUp, int height) {
summonWindow(tempSurface, slideUp);
}
-void UserInterface::banishWindow(bool slideUp) {
+void ScalpelUserInterface::banishWindow(bool slideUp) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
@@ -2062,7 +2071,7 @@ void UserInterface::banishWindow(bool slideUp) {
_menuMode = STD_MODE;
}
-void UserInterface::checkUseAction(const UseType *use, const Common::String &invName,
+void ScalpelUserInterface::checkUseAction(const UseType *use, const Common::String &invName,
const char *const messages[], int objNum, bool giveMode) {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
@@ -2155,7 +2164,7 @@ void UserInterface::checkUseAction(const UseType *use, const Common::String &inv
events.setCursor(ARROW);
}
-void UserInterface::checkAction(ActionType &action, const char *const messages[], int objNum) {
+void ScalpelUserInterface::checkAction(ActionType &action, const char *const messages[], int objNum) {
Events &events = *_vm->_events;
People &people = *_vm->_people;
Scene &scene = *_vm->_scene;
@@ -2287,4 +2296,14 @@ void UserInterface::checkAction(ActionType &action, const char *const messages[]
events.setCursor(ARROW);
}
+/*----------------------------------------------------------------*/
+
+TattooUserInterface::TattooUserInterface(SherlockEngine *vm): UserInterface(vm) {
+ //
+}
+
+void TattooUserInterface::handleInput() {
+ // TODO
+}
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h
index 1f7b5feaab..8a0f4f5613 100644
--- a/engines/sherlock/user_interface.h
+++ b/engines/sherlock/user_interface.h
@@ -61,20 +61,91 @@ extern const char *const PRESS_KEY_TO_CONTINUE;
class SherlockEngine;
class Inventory;
class Talk;
-class UserInterface;
class UserInterface {
+protected:
+ SherlockEngine *_vm;
+
+ UserInterface(SherlockEngine *vm);
+public:
+ MenuMode _menuMode;
+ int _menuCounter;
+ bool _infoFlag;
+ bool _windowOpen;
+ bool _endKeyActive;
+ int _invLookFlag;
+ bool _slideWindows;
+ bool _helpStyle;
+ Common::Rect _windowBounds;
+ bool _lookScriptFlag;
+
+ // TODO: Not so sure these should be in the base class. May want to refactor them to SherlockEngine, or refactor
+ // various Scalpel dialogs to keep their own private state of key/selections
+ char _key, _oldKey;
+ int _selector, _oldSelector;
+ int _temp, _oldTemp;
+ int _temp1;
+ int _lookHelp;
+public:
+ static UserInterface *init(SherlockEngine *vm);
+
+ /**
+ * Resets the user interface
+ */
+ virtual void reset() {}
+
+ /**
+ * Draw the user interface onto the screen's back buffers
+ */
+ virtual void drawInterface(int bufferNum = 3) {}
+
+ /**
+ * Main input handler for the user interface
+ */
+ virtual void handleInput() {}
+
+ /**
+ * Displays a passed window by gradually scrolling it vertically on-screen
+ */
+ virtual void summonWindow(const Surface &bgSurface, bool slideUp = true) {}
+
+ /**
+ * Slide the window stored in the back buffer onto the screen
+ */
+ virtual void summonWindow(bool slideUp = true, int height = CONTROLS_Y) {}
+
+ /**
+ * Close a currently open window
+ * @param flag 0 = slide old window down, 1 = slide prior UI back up
+ */
+ virtual void banishWindow(bool slideUp = true) {}
+
+ /**
+ * Clears the info line of the screen
+ */
+ virtual void clearInfo() {}
+
+ /**
+ * Clear any active text window
+ */
+ virtual void clearWindow() {}
+
+ /**
+ * Print the previously selected object's decription
+ */
+ virtual void printObjectDesc() {}
+};
+
+class ScalpelUserInterface: public UserInterface {
friend class Inventory;
friend class Settings;
friend class Talk;
private:
- SherlockEngine *_vm;
ImageFile *_controlPanel;
ImageFile *_controls;
- int _bgFound;
- int _oldBgFound;
char _keyPress;
int _lookHelp;
+ int _bgFound, _oldBgFound;
int _help, _oldHelp;
char _key, _oldKey;
int _temp, _oldTemp;
@@ -82,10 +153,7 @@ private:
bool _keyboardInput;
bool _pause;
int _cNum;
- int _selector, _oldSelector;
Common::String _cAnimStr;
- bool _lookScriptFlag;
- Common::Rect _windowBounds;
Common::String _descStr;
int _find;
int _oldUse;
@@ -178,81 +246,81 @@ private:
* Called for OPEN, CLOSE, and MOVE actions are being done
*/
void checkAction(ActionType &action, const char *const messages[], int objNum);
-public:
- MenuMode _menuMode;
- int _menuCounter;
- bool _infoFlag;
- bool _windowOpen;
- bool _endKeyActive;
- int _invLookFlag;
- int _temp1;
- bool _slideWindows;
- bool _helpStyle;
-public:
- UserInterface(SherlockEngine *vm);
- ~UserInterface();
/**
- * Resets the user interface
+ * Print the previously selected object's decription
*/
- void reset();
+ void printObjectDesc(const Common::String &str, bool firstTime);
+public:
+ ScalpelUserInterface(SherlockEngine *vm);
+ ~ScalpelUserInterface();
/**
- * Draw the user interface onto the screen's back buffers
+ * Handles counting down whilst checking for input, then clears the info line.
*/
- void drawInterface(int bufferNum = 3);
+ void whileMenuCounter();
/**
- * Main input handler for the user interface
+ * Draws the image for the given user interface button in the up
+ * (not selected) position
*/
- void handleInput();
-
+ void restoreButton(int num);
+public:
/**
- * Clears the info line of the screen
+ * Resets the user interface
*/
- void clearInfo();
+ virtual void reset();
/**
- * Clear any active text window
+ * Main input handler for the user interface
*/
- void clearWindow();
+ virtual void handleInput();
/**
- * Handles counting down whilst checking for input, then clears the info line.
- */
- void whileMenuCounter();
+ * Draw the user interface onto the screen's back buffers
+ */
+ virtual void drawInterface(int bufferNum = 3);
/**
- * Print the description of an object
+ * Displays a passed window by gradually scrolling it vertically on-screen
*/
- void printObjectDesc(const Common::String &str, bool firstTime);
-
+ virtual void summonWindow(const Surface &bgSurface, bool slideUp = true);
+
/**
- * Print the previously selected object's decription
+ * Slide the window stored in the back buffer onto the screen
*/
- void printObjectDesc();
+ virtual void summonWindow(bool slideUp = true, int height = CONTROLS_Y);
/**
- * Displays a passed window by gradually scrolling it vertically on-screen
+ * Close a currently open window
+ * @param flag 0 = slide old window down, 1 = slide prior UI back up
*/
- void summonWindow(const Surface &bgSurface, bool slideUp = true);
-
+ virtual void banishWindow(bool slideUp = true);
+
/**
- * Slide the window stored in the back buffer onto the screen
+ * Clears the info line of the screen
*/
- void summonWindow(bool slideUp = true, int height = CONTROLS_Y);
-
+ virtual void clearInfo();
+
/**
- * Close a currently open window
- * @param flag 0 = slide old window down, 1 = slide prior UI back up
+ * Clear any active text window
*/
- void banishWindow(bool slideUp = true);
+ virtual void clearWindow();
/**
- * Draws the image for the given user interface button in the up
- * (not selected) position
+ * Print the previously selected object's decription
+ */
+ virtual void printObjectDesc();
+};
+
+class TattooUserInterface : public UserInterface {
+public:
+ TattooUserInterface(SherlockEngine *vm);
+public:
+ /**
+ * Main input handler for the user interface
*/
- void restoreButton(int num);
+ virtual void handleInput();
};
} // End of namespace Sherlock