[Scummvm-cvs-logs] scummvm master -> d0a0f85fc524fc6e744c2a73c5c2413d411b4041
wjp
wjp at usecode.org
Tue Jun 2 00:04:33 CEST 2015
This automated email contains information about 92 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
7a46c84c0d SHERLOCK: Beginnings of Rose Tattoo engine
32d7690e54 SHERLOCK: Update sound initialization for Rose Tattoo
af651e19a4 Merge branch 'sherlock' into sherlock2
602741172d SHERLOCK: Move caching Scalpel sound libraries from Sound to Scalpel engine
7897b72f65 SHERLOCK: Fix decompression for Rose Tattoo
5f5051d7be SHERLOCK: Scene loading for shapes, desc, scripts for Rose Tattoo
2cfc6a0a0c SHERLOCK: Fix broken Scalpel scene loading
7963c64c06 SHERLOCK: Remove accidentally committed debug info
7aa804b5cc SHERLOCK: Implement Tattoo version of image RLE compression
46e27b6293 SHERLOCK: Update CAnim loading for Rose Tattoo
3683719932 SHERLOCK: Implement remaining Rose Tattoo scene data loading
40f7fff429 SHERLOCK: Beginnings of UserInterface split for Scalpel vs Tattoo
b4b6bf63db Merge branch 'master' into sherlock2
c8cfca749a SHERLOCK: Fix Rose Tattoo scene loading problems from merge
bcc31b2a66 SHERLOCK: Implemented Tattoo loadWalk changes
1e291b0b25 SHERLOCK: Implemented initial RT palette loading
1ede084055 SHERLOCK: Implement more scene loading and setNPCPath
79f11bd381 SHERLOCK: Make virtual destructors for user interface classes
79a33dc3b6 SHERLOCK: Create separate opcode list for Scalpel vs Tattoo
55ab34b981 SHERLOCK: Fully implemented RT opcodes array
8a808654c8 SHERLOCK: Splitting Talk up to implement individual opcode methods
b4849f21d2 SHERLOCK: Implement method stubs for Tattoo opcodes
f9a2d091e9 SHERLOCK: Fix script opcode table lookup
5513f72510 SHERLOCK: Implement cmdSetNPCWalkGraphics method
1f9f01c571 SHERLOCK: Implement cmdNextSong
8331fa886f SHERLOCK: Fix People data initialization and general start fixes
ef4d8be853 SHERLOCK: Fix display of first RT scene background
40afa01369 SHERLOCK: Fix palette for RT scene
bcb8c02ba1 SHERLOCK: Free freeing and resetting People list
1a1010f0ab SHERLOCK: Cleanup of checkBgShapes and updateBackground
e1e39ea3d2 SHERLOCK: Add define for fixed integer multiplier
0cc79979fc SHERLOCK: Fix map display
30edd4efb8 SHERLOCK: Starting to split Scene class, implemented checkBgShapes changes
483a72b8b8 SHERLOK: Beginnings of split of doBgAnim logic
0d4163c6e9 SHERLOCK: Implemented initial background clearing of RT doBgAnim
45b4989b55 SHERLOCK: Implement RT scrolling code
f4902b516e SHERLOCK: Moving split up classes into their own files
88d2458143 SHERLOCK: Implement additions to updateBackground, some method stubs
a6607ff2d6 SHERLOCK: Implemented flushScaleImage and scale calculations
895189e3ff SHERLOCK: More RT doBgAnim code, interface draw
6b95fc6b11 Merge branch 'sherlock2'
9c09f243ea Merge branch 'master' of https://github.com/scummvm/scummvm
4e40441614 TSAGE: Fix incorrectly named header defines
0cc5313689 SHERLOCK: midi parser delta reading changed
17aeb52649 SHERLOCK: Fix non-interactive Scalpel demo
a7f9e4c317 SHERLOCK: Fix compilation with GCC
560bc65fc4 SHERLOCK: Silence GCC warning.
2555111149 SHERLOCK: Fix incorrect if statement
442fb84768 SHERLOCK: Make some of the scalpel user interface fields public
1f7555c2ca SHERLOCK: Further compilation fixes
a3008e8f01 FMOPL: Fix confusing "opl_driver" behavior
8b9de5cdc9 SHERLOCK: implement SysEx 0xFC loop/not loop
3dd81bfb35 SHERLOCK: renamed SysEx to System META event
f3d1ffdaaf SHERLOCK: adlib: add support for percussion
52ca97fe63 SHERLOCK: midiparser block META event 0xFF for now
fd33a100a1 SHERLOCK: Beginnings of Scalpel logo display
9da6a90713 SHERLOCK: adlib: implement in-use-channel usage
ec56344ed7 SHERLOCK: Free memory leaks from unreleased sound resources
6ce9be2404 SHERLOCK: adlib: in-use timer, thx LordHoto
4942571e63 SHERLOCK: adlib: fix "in-use" usage voiceOnOff()
6796444f08 SHERLOCK: Fix restoring info line when talk window closes
59d81c0aa1 SHERLOCK: Added lightweight TsAGE object for handling logo animations
40f5d26c92 TSAGE: Fix typo in comment
3c9a5f02d2 MADS: Remove unnecessary semicolon
742b04cc49 VOYEUR: Remove unnecessary semicolon
35fe594133 SHERLOCK: clean up adlib driver
2826a06bc5 SHERLOCK: Fix regression in conversations
656906da42 SHERLOCK: More of the Scalpel logo implemented
53f6e1903b SHERLOCK: Implement TsAGE object mover code for Scalpel logo display
141ff4d08d SHERLOCK: Fix white screen on Sclapel logo
b1cae87251 SHERLOCK: Fix brief black screen in EA logo intro
b01dee457a SHERLOCK: Added missing setAnimMode() call
c822e849de SHERLOCK: Move scroll variables from Screen to TattooUserInterface
f2bced65ac SHERLOCK: Implemented Tattoo UI drawInterface
90be81b284 SHERLOCK: debug levels for AdLib & Music
c79b0d1db9 SHERLOCK: Silence GCC warning
6b8452538f SHERLOCK: Implement remainder of RT doBgAnim
79bf0a05ee SHERLOCK: Remove unused variable
171117677d SHERLOCK: implement 2 palette faes for the intro
d52aa528d5 SHERLOCK: Formatting fix
e028eb4425 SHERLOCK: intro changes
3b2c045212 SHERLOCK: Fix bug when opening the journal
621ed75677 SHERLOCK: Clean up the static people data arrays
bf12f04c45 SHERLOCK: Fix closing namespace comments
2143ade072 SHERLOCK: Erase the hand cursor when that part of the intro is done
049ca42bb2 SHERLOCK: intro timing + fixes
3025a44157 SHERLOCK: fix flicker during EA logo intro
de837f2719 SHERLOCK: add fade out to street scene intro
c20fbeaf6f SHERLOCK: add comments about waitUntilTick()
b752c1f5bb SHERLOCK: intro: play constable anim slower
0500dc2408 SHERLOCK: remove debug #ifs
d0a0f85fc5 SHERLOCK: Remove unnecessary object positioning
Commit: 7a46c84c0d02ec3fb5aa9d607519af8fbcd2715e
https://github.com/scummvm/scummvm/commit/7a46c84c0d02ec3fb5aa9d607519af8fbcd2715e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-12T22:02:59-04:00
Commit Message:
SHERLOCK: Beginnings of Rose Tattoo engine
Changed paths:
engines/sherlock/decompress.cpp
engines/sherlock/map.cpp
engines/sherlock/objects.cpp
engines/sherlock/objects.h
engines/sherlock/resources.cpp
engines/sherlock/resources.h
engines/sherlock/scalpel/scalpel.cpp
engines/sherlock/scene.cpp
engines/sherlock/scene.h
engines/sherlock/screen.cpp
engines/sherlock/screen.h
engines/sherlock/sherlock.cpp
engines/sherlock/sherlock.h
engines/sherlock/tattoo/tattoo.cpp
engines/sherlock/tattoo/tattoo.h
engines/sherlock/user_interface.cpp
diff --git a/engines/sherlock/decompress.cpp b/engines/sherlock/decompress.cpp
index dfa5732..8e02da3 100644
--- a/engines/sherlock/decompress.cpp
+++ b/engines/sherlock/decompress.cpp
@@ -77,4 +77,52 @@ Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source, int
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/map.cpp b/engines/sherlock/map.cpp
index e178dec..c2eedd4 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 {
@@ -52,7 +53,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;
@@ -94,8 +95,13 @@ void Map::loadSequences(int count, const byte *seq) {
* Load data needed for the map
*/
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 b4371cd..772f9d2 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -122,8 +122,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))
@@ -393,9 +393,14 @@ UseType::UseType() {
/**
* Load the data for the UseType
*/
-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)
@@ -407,9 +412,12 @@ void UseType::load(Common::SeekableReadStream &s) {
}
_useFlag = s.readSint16LE();
- _dFlag[0] = s.readSint16LE();
- _lFlag[0] = s.readSint16LE();
- _lFlag[1] = s.readSint16LE();
+
+ if (!isRoseTattoo) {
+ _dFlag[0] = s.readSint16LE();
+ _lFlag[0] = s.readSint16LE();
+ _lFlag[1] = s.readSint16LE();
+ }
s.read(buffer, 12);
_target = Common::String(buffer);
@@ -456,12 +464,19 @@ Object::Object() {
_descOffset = 0;
_seqCounter2 = 0;
_seqSize = 0;
+
+ _quickDraw = 0;
+ _scaleVal = 0;
+ _requiredFlag1 = 0;
+ _gotoSeq = 0;
+ _talkSeq = 0;
+ _restoreSlot = 0;
}
/**
* Load the data for the object
*/
-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);
@@ -496,7 +511,8 @@ void Object::load(Common::SeekableReadStream &s) {
_pickup = s.readByte();
_defaultCommand = s.readByte();
_lookFlag = s.readUint16LE();
- _pickupFlag = s.readUint16LE();
+ if (!isRoseTattoo)
+ _pickupFlag = s.readUint16LE();
_requiredFlag = s.readSint16LE();
_noShapeSize.x = s.readUint16LE();
_noShapeSize.y = s.readUint16LE();
@@ -504,26 +520,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 < 4; ++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.readUint16LE();
+ _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);
+ }
}
/**
diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h
index 4068973..2073f06 100644
--- a/engines/sherlock/objects.h
+++ b/engines/sherlock/objects.h
@@ -159,9 +159,10 @@ struct UseType {
int _dFlag[1];
int _lFlag[2];
Common::String _target;
+ Common::String _verb;
UseType();
- void load(Common::SeekableReadStream &s);
+ void load(Common::SeekableReadStream &s, bool isRoseTattoo);
};
class Object {
@@ -197,32 +198,42 @@ 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[4];
+
+ // Rose Tattoo fields
+ int _quickDraw;
+ int _scaleVal;
+ int _requiredFlag1;
+ int _gotoSeq;
+ int _talkSeq;
+ int _restoreSlot;
Object();
- void load(Common::SeekableReadStream &s);
+ void load(Common::SeekableReadStream &s, bool isRoseTattoo);
void toggleHidden();
diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp
index f50f780..9f2704a 100644
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@ -107,9 +107,7 @@ Resources::Resources() {
addToCache("vgs.lib");
addToCache("talk.lib");
- addToCache("sequence.txt");
addToCache("journal.txt");
- addToCache("portrait.lib");
}
/**
@@ -122,8 +120,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;
}
@@ -193,7 +194,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];
@@ -216,7 +217,7 @@ bool Resources::exists(const Common::String &filename) const {
* Reads in the index from a library file, and caches it's index for later use
*/
void Resources::loadLibraryIndex(const Common::String &libFilename,
- Common::SeekableReadStream *stream) {
+ Common::SeekableReadStream *stream, bool isNewStyle) {
uint32 offset, nextOffset;
// Create an index entry
@@ -227,6 +228,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
@@ -304,10 +308,12 @@ 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();
diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h
index e1f97f1..bbaac60 100644
--- a/engines/sherlock/resources.h
+++ b/engines/sherlock/resources.h
@@ -70,7 +70,8 @@ private:
LibraryIndexes _indexes;
int _resourceIndex;
- void loadLibraryIndex(const Common::String &libFilename, Common::SeekableReadStream *stream);
+ void loadLibraryIndex(const Common::String &libFilename, Common::SeekableReadStream *stream,
+ bool isNewStyle);
public:
Resources();
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index 6959e43..b982079 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 {
@@ -242,6 +243,9 @@ ScalpelEngine::~ScalpelEngine() {
* Game initialization
*/
void ScalpelEngine::initialize() {
+ initGraphics(320, 200, false);
+
+ // Let the base engine intialize
SherlockEngine::initialize();
_darts = new Darts(this);
@@ -250,11 +254,13 @@ void ScalpelEngine::initialize() {
_flags[3] = true; // Turn on Alley
_flags[39] = true; // Turn on Baker Street
- if (!getIsDemo()) {
+ // Add some more files to the cache
+ _res->addToCache("sequence.txt");
+ _res->addToCache("portrait.lib");
+
// Load the map co-ordinates for each scene and sequence data
_map->loadPoints(NUM_PLACES, &MAP_X[0], &MAP_Y[0], &MAP_TRANSLATE[0]);
_map->loadSequences(3, &MAP_SEQUENCES[0][0]);
- }
// Load the inventory
loadInventory();
@@ -454,9 +460,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 f473004..d4662ed 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -24,16 +24,42 @@
#include "sherlock/sherlock.h"
#include "sherlock/scalpel/scalpel.h"
#include "sherlock/decompress.h"
+#include "sherlock/screen.h"
namespace Sherlock {
-void BgFileHeader::synchronize(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::synchronize(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();
+
+ }
}
/*----------------------------------------------------------------*/
@@ -215,6 +241,7 @@ bool Scene::loadScene(const Common::String &filename) {
Sound &sound = *_vm->_sound;
UserInterface &ui = *_vm->_ui;
bool flag;
+ Common::Array<BgfileheaderInfo> bgInfo;
_walkedInScene = false;
@@ -229,7 +256,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";
@@ -238,30 +265,52 @@ bool Scene::loadScene(const Common::String &filename) {
Common::SeekableReadStream *rrmStream = _vm->_res->load(rrmFile);
rrmStream->seek(39);
- _version = rrmStream->readByte();
- _lzwMode = _version == 10;
+ if (_vm->getGameID() == GType_SerratedScalpel) {
+ _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.synchronize(*rrmStream);
+ bgHeader.synchronize(*rrmStream, _vm->getGameID() == GType_RoseTattoo);
_invGraphicItems = bgHeader._numImages + 1;
+ if (_vm->getGameID() == GType_RoseTattoo) {
+ screen.initPaletteFade(bgHeader._bytesWritten);
+ screen.fadeRead(*rrmStream, screen._cMap, PALETTE_SIZE);
+ screen.setupBGArea(screen._cMap);
+
+ screen.initScrollVars();
+
+ // Read in background
+ if (_lzwMode) {
+ Common::SeekableReadStream *stream = decompressLZ(*rrmStream, SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCREEN_HEIGHT);
+ stream->read(screen._backBuffer1.getPixels(), stream->size());
+ delete stream;
+ } 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);
for (uint idx = 0; idx < bgInfo.size(); ++idx)
bgInfo[idx].synchronize(*rrmStream);
// Read information
+ int shapeSize = _vm->getGameID() == GType_SerratedScalpel ? 569 : 591;
Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream :
- decompressLZ(*rrmStream, bgHeader._numImages * 569 +
+ decompressLZ(*rrmStream, bgHeader._numImages * shapeSize +
bgHeader._descSize + bgHeader._seqSize);
_bgShapes.resize(bgHeader._numStructs);
for (int idx = 0; idx < bgHeader._numStructs; ++idx)
- _bgShapes[idx].load(*infoStream);
+ _bgShapes[idx].load(*infoStream, _vm->getGameID() == GType_RoseTattoo);
if (bgHeader._descSize) {
_descText.resize(bgHeader._descSize);
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index 96714c4..b4b88fa 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,9 +45,19 @@ struct BgFileHeader {
int _numcAnimations;
int _descSize;
int _seqSize;
+
+ // Serrated Scalpel
int _fill;
- void synchronize(Common::SeekableReadStream &s);
+ // Rose Tattoo
+ int _scrollSize;
+ int _bytesWritten; // Size of the main body of the RRM
+ int _fadeStyle; // Fade style
+ byte _palette[PALETTE_SIZE]; // Palette
+
+
+ BgFileHeader();
+ void synchronize(Common::SeekableReadStream &s, bool isRoseTattoo);
};
struct BgfileheaderInfo {
diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp
index fb155bf..0ca10b4 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,11 +38,19 @@ 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);
// Set dummy surface used for restricted scene drawing
_sceneSurface.format = Graphics::PixelFormat::createFormatCLUT8();
- _sceneSurface.pitch = SHERLOCK_SCREEN_WIDTH;
+ _sceneSurface.pitch = pitch;
+
+ // Rose Tattoo specific fields
+ _fadeBytesRead = _fadeBytesToRead = 0;
+ _oldFadePercent = 0;
+ _scrollSize = 0;
+ _currentScroll = 0;
+ _targetScroll = 0;
}
Screen::~Screen() {
@@ -213,7 +221,7 @@ void Screen::randomTransition() {
_transitionSeed = _transitionSeed * TRANSITION_MULTIPLIER + 1;
int offset = _transitionSeed & 65535;
- 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 % 100) == 0) {
@@ -236,12 +244,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) {
@@ -261,7 +269,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);
@@ -281,7 +289,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);
@@ -338,13 +346,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);
@@ -505,7 +513,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);
}
/**
@@ -518,4 +526,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 501506f..2538916 100644
--- a/engines/sherlock/screen.h
+++ b/engines/sherlock/screen.h
@@ -67,6 +67,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:
void mergeDirtyRects();
bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
@@ -80,6 +89,7 @@ public:
bool _fadeStyle;
byte _cMap[PALETTE_SIZE];
byte _sMap[PALETTE_SIZE];
+ byte _tMap[PALETTE_SIZE];
public:
Screen(SherlockEngine *vm);
virtual ~Screen();
@@ -132,6 +142,15 @@ public:
int fontNumber() const { return _fontNumber; }
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/sherlock.cpp b/engines/sherlock/sherlock.cpp
index 2a5d9ec..318267b 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 {
@@ -71,8 +70,6 @@ SherlockEngine::~SherlockEngine() {
* Does basic initialization of the game engine
*/
void SherlockEngine::initialize() {
- initGraphics(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT, false);
-
DebugMan.addDebugChannel(kDebugScript, "scripts", "Script debug level");
ImageFile::setVm(this);
diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h
index 501fdcb..e21ac8c 100644
--- a/engines/sherlock/sherlock.h
+++ b/engines/sherlock/sherlock.h
@@ -62,8 +62,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;
diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp
index d4059ac..9039e3f 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,32 @@ 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");
+
+ // 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 b983955..7bdeec5 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 41505b8..8e72540 100644
--- a/engines/sherlock/user_interface.cpp
+++ b/engines/sherlock/user_interface.cpp
@@ -81,8 +81,13 @@ const char *const MUSE[] = {
/*----------------------------------------------------------------*/
UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) {
- _controls = new ImageFile("menu.all");
- _controlPanel = new ImageFile("controls.vgs");
+ if (_vm->getGameID() == GType_SerratedScalpel) {
+ _controls = new ImageFile("menu.all");
+ _controlPanel = new ImageFile("controls.vgs");
+ } else {
+ _controls = nullptr;
+ _controlPanel = nullptr;
+ }
_bgFound = 0;
_oldBgFound = -1;
_keycode = Common::KEYCODE_INVALID;
Commit: 32d7690e549f5af8fb5f88d9434ae0f54c0e6c69
https://github.com/scummvm/scummvm/commit/32d7690e549f5af8fb5f88d9434ae0f54c0e6c69
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-13T08:26:25-04:00
Commit Message:
SHERLOCK: Update sound initialization for Rose Tattoo
Changed paths:
engines/sherlock/sound.cpp
diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp
index 09e55ec..70451a6 100644
--- a/engines/sherlock/sound.cpp
+++ b/engines/sherlock/sound.cpp
@@ -45,7 +45,7 @@ Sound::Sound(SherlockEngine *vm, Audio::Mixer *mixer): _vm(vm), _mixer(mixer) {
_speechOn = true;
_vm->_res->addToCache("MUSIC.LIB");
- _vm->_res->addToCache("SND.SND");
+ _vm->_res->addToCache(_vm->getGameID() == GType_SerratedScalpel ? "SND.SND" : "SOUND.LIB");
}
/**
Commit: af651e19a421781a1498de0e66909a2e9450611c
https://github.com/scummvm/scummvm/commit/af651e19a421781a1498de0e66909a2e9450611c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-16T09:29:40-04:00
Commit Message:
Merge branch 'sherlock' into sherlock2
Conflicts:
engines/sherlock/decompress.cpp
engines/sherlock/objects.cpp
engines/sherlock/objects.h
engines/sherlock/scene.cpp
engines/sherlock/scene.h
engines/sherlock/sound.cpp
Changed paths:
A engines/sherlock/surface.cpp
A engines/sherlock/surface.h
R engines/sherlock/decompress.h
R engines/sherlock/graphics.cpp
R engines/sherlock/graphics.h
engines/sherlock/detection.cpp
engines/sherlock/detection_tables.h
engines/sherlock/inventory.cpp
engines/sherlock/inventory.h
engines/sherlock/map.cpp
engines/sherlock/map.h
engines/sherlock/module.mk
engines/sherlock/resources.cpp
engines/sherlock/resources.h
engines/sherlock/saveload.cpp
engines/sherlock/scalpel/scalpel.cpp
engines/sherlock/scene.cpp
engines/sherlock/scene.h
engines/sherlock/screen.cpp
engines/sherlock/screen.h
engines/sherlock/sherlock.cpp
engines/sherlock/sherlock.h
engines/sherlock/sound.cpp
engines/sherlock/talk.cpp
engines/sherlock/talk.h
engines/sherlock/tattoo/tattoo.cpp
engines/sherlock/user_interface.cpp
engines/sherlock/user_interface.h
diff --cc engines/sherlock/resources.h
index bbaac60,d5e83a1..041f1c6
--- a/engines/sherlock/resources.h
+++ b/engines/sherlock/resources.h
@@@ -70,10 -72,9 +72,10 @@@ private
LibraryIndexes _indexes;
int _resourceIndex;
- void loadLibraryIndex(const Common::String &libFilename, Common::SeekableReadStream *stream);
+ void loadLibraryIndex(const Common::String &libFilename, Common::SeekableReadStream *stream,
+ bool isNewStyle);
public:
- Resources();
+ Resources(SherlockEngine *vm);
void addToCache(const Common::String &filename);
void addToCache(const Common::String &filename, const Common::String &libFilename);
diff --cc engines/sherlock/scalpel/scalpel.cpp
index b982079,6959e43..521aeb3
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@@ -254,10 -250,7 +254,11 @@@ void ScalpelEngine::initialize()
_flags[3] = true; // Turn on Alley
_flags[39] = true; // Turn on Baker Street
- if (!getIsDemo()) {
+ // Add some more files to the cache
- _res->addToCache("sequence.txt");
+ _res->addToCache("portrait.lib");
++ _res->addToCache("sequence.txt");
++ _res->addToCache("snd.snd");
+
// Load the map co-ordinates for each scene and sequence data
_map->loadPoints(NUM_PLACES, &MAP_X[0], &MAP_Y[0], &MAP_TRANSLATE[0]);
_map->loadSequences(3, &MAP_SEQUENCES[0][0]);
diff --cc engines/sherlock/scene.cpp
index d4662ed,9fbf25c..0a25d3d
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@@ -23,8 -23,6 +23,7 @@@
#include "sherlock/scene.h"
#include "sherlock/sherlock.h"
#include "sherlock/scalpel/scalpel.h"
- #include "sherlock/decompress.h"
+#include "sherlock/screen.h"
namespace Sherlock {
@@@ -236,6 -227,6 +250,7 @@@ bool Scene::loadScene(const Common::Str
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;
@@@ -274,38 -260,20 +289,38 @@@
// Go to header and read it in
rrmStream->seek(rrmStream->readUint32LE());
+
BgFileHeader bgHeader;
- bgHeader.load(*rrmStream);
+ bgHeader.synchronize(*rrmStream, _vm->getGameID() == GType_RoseTattoo);
_invGraphicItems = bgHeader._numImages + 1;
+ if (_vm->getGameID() == GType_RoseTattoo) {
+ screen.initPaletteFade(bgHeader._bytesWritten);
+ screen.fadeRead(*rrmStream, screen._cMap, PALETTE_SIZE);
+ screen.setupBGArea(screen._cMap);
+
+ screen.initScrollVars();
+
+ // Read in background
+ if (_lzwMode) {
- Common::SeekableReadStream *stream = decompressLZ(*rrmStream, SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCREEN_HEIGHT);
++ Common::SeekableReadStream *stream = res.decompressLZ(*rrmStream);
+ stream->read(screen._backBuffer1.getPixels(), stream->size());
+ delete stream;
+ } else {
+ rrmStream->read(screen._backBuffer1.getPixels(), SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCREEN_HEIGHT);
+ }
+ }
+
// Read in the shapes header info
bgInfo.resize(bgHeader._numStructs);
for (uint idx = 0; idx < bgInfo.size(); ++idx)
- bgInfo[idx].synchronize(*rrmStream);
+ bgInfo[idx].load(*rrmStream);
// Read information
+ int shapeSize = _vm->getGameID() == GType_SerratedScalpel ? 569 : 591;
Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream :
- decompressLZ(*rrmStream, bgHeader._numImages * shapeSize +
- Resources::decompressLZ(*rrmStream, bgHeader._numImages * 569 +
++ Resources::decompressLZ(*rrmStream, bgHeader._numImages * shapeSize +
bgHeader._descSize + bgHeader._seqSize);
_bgShapes.resize(bgHeader._numStructs);
diff --cc engines/sherlock/screen.cpp
index 0ca10b4,cbf18f1..349bf4d
--- a/engines/sherlock/screen.cpp
+++ b/engines/sherlock/screen.cpp
@@@ -221,10 -214,10 +222,10 @@@ void Screen::randomTransition()
_transitionSeed = _transitionSeed * TRANSITION_MULTIPLIER + 1;
int offset = _transitionSeed & 65535;
- 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 % 100) == 0) {
+ if (idx != 0 && (idx % 300) == 0) {
// Ensure there's a full screen dirty rect for the next frame update
if (_dirtyRects.empty())
addDirtyRect(Common::Rect(0, 0, this->w, this->h));
diff --cc engines/sherlock/sound.cpp
index 70451a6,59098c3..0019079
--- a/engines/sherlock/sound.cpp
+++ b/engines/sherlock/sound.cpp
@@@ -45,7 -45,9 +45,8 @@@ Sound::Sound(SherlockEngine *vm, Audio:
_speechOn = true;
_vm->_res->addToCache("MUSIC.LIB");
- _vm->_res->addToCache(_vm->getGameID() == GType_SerratedScalpel ? "SND.SND" : "SOUND.LIB");
+ _vm->_res->addToCache("TITLE.SND");
+ _vm->_res->addToCache("EPILOGUE.SND");
- _vm->_res->addToCache("SND.SND");
}
/**
diff --cc engines/sherlock/tattoo/tattoo.cpp
index 9039e3f,d4059ac..3c684ff
--- a/engines/sherlock/tattoo/tattoo.cpp
+++ b/engines/sherlock/tattoo/tattoo.cpp
@@@ -31,32 -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
Commit: 602741172d9e1b187228655f4361f8850d44155b
https://github.com/scummvm/scummvm/commit/602741172d9e1b187228655f4361f8850d44155b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-16T09:33:42-04:00
Commit Message:
SHERLOCK: Move caching Scalpel sound libraries from Sound to Scalpel engine
Changed paths:
engines/sherlock/scalpel/scalpel.cpp
engines/sherlock/sound.cpp
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index 521aeb3..eff5898 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -257,7 +257,9 @@ void ScalpelEngine::initialize() {
// 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");
// Load the map co-ordinates for each scene and sequence data
_map->loadPoints(NUM_PLACES, &MAP_X[0], &MAP_Y[0], &MAP_TRANSLATE[0]);
diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp
index 0019079..3a30864 100644
--- a/engines/sherlock/sound.cpp
+++ b/engines/sherlock/sound.cpp
@@ -45,8 +45,6 @@ Sound::Sound(SherlockEngine *vm, Audio::Mixer *mixer): _vm(vm), _mixer(mixer) {
_speechOn = true;
_vm->_res->addToCache("MUSIC.LIB");
- _vm->_res->addToCache("TITLE.SND");
- _vm->_res->addToCache("EPILOGUE.SND");
}
/**
Commit: 7897b72f655c8f65fd206aea12cfd06921d75124
https://github.com/scummvm/scummvm/commit/7897b72f655c8f65fd206aea12cfd06921d75124
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-16T10:52:38-04:00
Commit Message:
SHERLOCK: Fix decompression for Rose Tattoo
Changed paths:
engines/sherlock/resources.cpp
engines/sherlock/resources.h
engines/sherlock/scene.cpp
diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp
index bff80c2..0203011 100644
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@ -76,7 +76,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());
@@ -170,7 +170,7 @@ Common::SeekableReadStream *Resources::load(const Common::String &filename) {
if (resStream->readUint32BE() == MKTAG('L', 'Z', 'V', 26)) {
resStream->seek(0);
// It's compressed, so decompress the sub-file and return it
- Common::SeekableReadStream *decompressed = decompressLZ(*resStream);
+ Common::SeekableReadStream *decompressed = decompress(*resStream);
delete stream;
delete resStream;
return decompressed;
@@ -413,27 +413,45 @@ void ImageFile::decompressFrame(ImageFrame &frame, const byte *src) {
/**
* Decompress an LZW compressed resource
*/
-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);
+}
+
+/**
+ * Decompress an LZW compressed resource
+ */
+void Resources::decompress(Common::SeekableReadStream &source, byte *buffer, uint32 outSize) {
+ assert(_vm->getGameID() == GType_RoseTattoo);
- uint32 size = source.readUint32LE();
- return decompressLZ(source, size);
+ uint32 inputSize = source.readUint32LE();
+ decompressLZ(source, buffer, outSize, inputSize);
}
/**
* Decompresses an LZW block of data with a specified output size
*/
Common::SeekableReadStream *Resources::decompressLZ(Common::SeekableReadStream &source, uint32 outSize) {
+ byte *outBuffer = (byte *)malloc(outSize);
+ Common::MemoryReadStream *outStream = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
+
+ decompressLZ(source, outSize);
+ return outStream;
+}
+
+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);
+ uint32 endPos = source.pos() + inSize;
memset(lzWindow, 0xFF, 0xFEE);
lzWindowPos = 0xFEE;
@@ -463,9 +481,7 @@ Common::SeekableReadStream *Resources::decompressLZ(Common::SeekableReadStream &
lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
}
}
- } while (outBuffer < outBufferEnd);
-
- return outS;
+ } while ((!outSize || outBuffer < outBufferEnd) && (!inSize || source.pos() < endPos));
}
} // End of namespace Sherlock
diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h
index 041f1c6..0765ce4 100644
--- a/engines/sherlock/resources.h
+++ b/engines/sherlock/resources.h
@@ -90,8 +90,10 @@ public:
int resourceIndex() const;
+ Common::SeekableReadStream *decompress(Common::SeekableReadStream &source);
+ void decompress(Common::SeekableReadStream &source, byte *buffer, uint32 outSize);
+ static void decompressLZ(Common::SeekableReadStream &source, byte *outBuffer, int32 outSize, int32 inSize);
static Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source, uint32 outSize);
- Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source);
};
struct ImageFrame {
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 0a25d3d..e473217 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -303,9 +303,7 @@ bool Scene::loadScene(const Common::String &filename) {
// Read in background
if (_lzwMode) {
- Common::SeekableReadStream *stream = res.decompressLZ(*rrmStream);
- stream->read(screen._backBuffer1.getPixels(), stream->size());
- delete stream;
+ 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);
}
Commit: 5f5051d7be5317153ae079c0c9c32ec2008c4a2c
https://github.com/scummvm/scummvm/commit/5f5051d7be5317153ae079c0c9c32ec2008c4a2c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-16T12:27:58-04:00
Commit Message:
SHERLOCK: Scene loading for shapes, desc, scripts for Rose Tattoo
Changed paths:
engines/sherlock/resources.cpp
engines/sherlock/resources.h
engines/sherlock/scene.cpp
diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp
index 0203011..9acba0b 100644
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@ -428,10 +428,22 @@ Common::SeekableReadStream *Resources::decompress(Common::SeekableReadStream &so
/**
* Decompress an LZW compressed resource
*/
+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;
+}
+
+/**
+ * Decompress an LZW compressed resource
+ */
void Resources::decompress(Common::SeekableReadStream &source, byte *buffer, uint32 outSize) {
- assert(_vm->getGameID() == GType_RoseTattoo);
+ int inputSize = (_vm->getGameID() == GType_RoseTattoo) ? source.readUint32LE() : -1;
- uint32 inputSize = source.readUint32LE();
decompressLZ(source, buffer, outSize, inputSize);
}
@@ -442,7 +454,7 @@ Common::SeekableReadStream *Resources::decompressLZ(Common::SeekableReadStream &
byte *outBuffer = (byte *)malloc(outSize);
Common::MemoryReadStream *outStream = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
- decompressLZ(source, outSize);
+ decompressLZ(source, outBuffer, outSize, -1);
return outStream;
}
@@ -451,7 +463,7 @@ void Resources::decompressLZ(Common::SeekableReadStream &source, byte *outBuffer
uint16 lzWindowPos;
uint16 cmd;
byte *outBufferEnd = outBuffer + outSize;
- uint32 endPos = source.pos() + inSize;
+ int32 endPos = source.pos() + inSize;
memset(lzWindow, 0xFF, 0xFEE);
lzWindowPos = 0xFEE;
diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h
index 0765ce4..a320852 100644
--- a/engines/sherlock/resources.h
+++ b/engines/sherlock/resources.h
@@ -91,6 +91,7 @@ public:
int resourceIndex() const;
Common::SeekableReadStream *decompress(Common::SeekableReadStream &source);
+ Common::SeekableReadStream *decompress(Common::SeekableReadStream &source, uint32 outSize);
void decompress(Common::SeekableReadStream &source, byte *buffer, uint32 outSize);
static void decompressLZ(Common::SeekableReadStream &source, byte *outBuffer, int32 outSize, int32 inSize);
static Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source, uint32 outSize);
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index e473217..54155db 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -316,28 +316,52 @@ bool Scene::loadScene(const Common::String &filename) {
bgInfo[idx].load(*rrmStream);
// Read information
- int shapeSize = _vm->getGameID() == GType_SerratedScalpel ? 569 : 591;
- Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream :
- Resources::decompressLZ(*rrmStream, bgHeader._numImages * shapeSize +
- bgHeader._descSize + bgHeader._seqSize);
+ if (_vm->getGameID() == GType_SerratedScalpel) {
+ Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream :
+ res.decompress(*rrmStream, bgHeader._numImages * 569 + bgHeader._descSize + bgHeader._seqSize);
+
+ _bgShapes.resize(bgHeader._numStructs);
+ for (int idx = 0; idx < bgHeader._numStructs; ++idx)
+ _bgShapes[idx].load(*infoStream, _vm->getGameID() == GType_RoseTattoo);
+
+ 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 {
+ // Load shapes
+ Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream : res.decompress(*rrmStream, bgHeader._numImages * 625);
+
+ _bgShapes.resize(bgHeader._numStructs);
+ for (int idx = 0; idx < bgHeader._numStructs; ++idx)
+ _bgShapes[idx].load(*infoStream, _vm->getGameID() == GType_RoseTattoo);
- _bgShapes.resize(bgHeader._numStructs);
- for (int idx = 0; idx < bgHeader._numStructs; ++idx)
- _bgShapes[idx].load(*infoStream, _vm->getGameID() == GType_RoseTattoo);
+ if (_lzwMode)
+ delete infoStream;
- if (bgHeader._descSize) {
+ // Load description text
_descText.resize(bgHeader._descSize);
- infoStream->read(&_descText[0], bgHeader._descSize);
- }
+ if (_lzwMode)
+ res.decompress(*rrmStream, (byte *)&_descText[0], bgHeader._descSize);
+ else
+ rrmStream->read(&_descText[0], bgHeader._descSize);
- if (bgHeader._seqSize) {
+ // Load sequences
_sequenceBuffer.resize(bgHeader._seqSize);
- infoStream->read(&_sequenceBuffer[0], bgHeader._seqSize);
+ if (_lzwMode)
+ res.decompress(*rrmStream, &_sequenceBuffer[0], bgHeader._seqSize);
+ else
+ rrmStream->read(&_sequenceBuffer[0], bgHeader._seqSize);
}
- if (_lzwMode)
- delete infoStream;
-
// Set up the list of images used by the scene
_images.resize(bgHeader._numImages + 1);
for (int idx = 0; idx < bgHeader._numImages; ++idx) {
Commit: 2cfc6a0a0c3e5ab1e65c7544da395ed8c8379b6b
https://github.com/scummvm/scummvm/commit/2cfc6a0a0c3e5ab1e65c7544da395ed8c8379b6b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-16T16:46:35-04:00
Commit Message:
SHERLOCK: Fix broken Scalpel scene loading
Changed paths:
engines/sherlock/objects.cpp
engines/sherlock/resources.cpp
engines/sherlock/scene.cpp
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index 772f9d2..9620a01 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -477,6 +477,7 @@ Object::Object() {
* Load the data for the object
*/
void Object::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
+ uint32 p = s.pos(); warning("%.4x", p);
char buffer[41];
s.read(buffer, 12);
_name = Common::String(buffer);
@@ -508,11 +509,10 @@ void Object::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
_goto.x = s.readSint16LE();
_goto.y = s.readSint16LE();
- _pickup = s.readByte();
- _defaultCommand = s.readByte();
- _lookFlag = s.readUint16LE();
- if (!isRoseTattoo)
- _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();
@@ -547,7 +547,7 @@ void Object::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
_quickDraw = s.readByte();
_scaleVal = s.readUint16LE();
- _requiredFlag1 = s.readUint16LE();
+ _requiredFlag1 = s.readSint16LE();
_gotoSeq = s.readByte();
_talkSeq = s.readByte();
_restoreSlot = s.readByte();
@@ -559,6 +559,7 @@ void Object::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
for (int idx = 0; idx < 4; ++idx)
_use[idx].load(s, false);
}
+ warning("%.4x", s.pos() - p);
}
/**
diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp
index 9acba0b..1c154a3 100644
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@ -324,7 +324,6 @@ void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette, bool
frame._offset.y = stream.readByte();
}
- frame._offset.y = stream.readByte();
frame._rleEncoded = !skipPalette && frame._rleEncoded;
if (frame._paletteBase) {
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 54155db..bf8d837 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -318,11 +318,11 @@ bool Scene::loadScene(const Common::String &filename) {
// Read information
if (_vm->getGameID() == GType_SerratedScalpel) {
Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream :
- res.decompress(*rrmStream, bgHeader._numImages * 569 + bgHeader._descSize + bgHeader._seqSize);
+ 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(*infoStream, _vm->getGameID() == GType_RoseTattoo);
+ _bgShapes[idx].load(*infoStream, false);
if (bgHeader._descSize) {
_descText.resize(bgHeader._descSize);
@@ -338,11 +338,11 @@ bool Scene::loadScene(const Common::String &filename) {
delete infoStream;
} else {
// Load shapes
- Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream : res.decompress(*rrmStream, bgHeader._numImages * 625);
+ Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream : res.decompress(*rrmStream, bgHeader._numStructs * 625);
_bgShapes.resize(bgHeader._numStructs);
for (int idx = 0; idx < bgHeader._numStructs; ++idx)
- _bgShapes[idx].load(*infoStream, _vm->getGameID() == GType_RoseTattoo);
+ _bgShapes[idx].load(*infoStream, true);
if (_lzwMode)
delete infoStream;
Commit: 7963c64c06e5765c5ca96917a8b4a2c7258c6f37
https://github.com/scummvm/scummvm/commit/7963c64c06e5765c5ca96917a8b4a2c7258c6f37
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-16T17:01:28-04:00
Commit Message:
SHERLOCK: Remove accidentally committed debug info
Changed paths:
engines/sherlock/objects.cpp
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index 9620a01..c6254ee 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -477,7 +477,6 @@ Object::Object() {
* Load the data for the object
*/
void Object::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
- uint32 p = s.pos(); warning("%.4x", p);
char buffer[41];
s.read(buffer, 12);
_name = Common::String(buffer);
@@ -559,7 +558,6 @@ void Object::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
for (int idx = 0; idx < 4; ++idx)
_use[idx].load(s, false);
}
- warning("%.4x", s.pos() - p);
}
/**
Commit: 7aa804b5ccd3489c852bbde01362bd2ce91d6cf8
https://github.com/scummvm/scummvm/commit/7aa804b5ccd3489c852bbde01362bd2ce91d6cf8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-16T22:27:36-04:00
Commit Message:
SHERLOCK: Implement Tattoo version of image RLE compression
Changed paths:
engines/sherlock/resources.cpp
engines/sherlock/scene.cpp
diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp
index 1c154a3..24fef3f 100644
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@ -383,6 +383,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/scene.cpp b/engines/sherlock/scene.cpp
index bf8d837..0348964 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -370,7 +370,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);
Commit: 46e27b6293c0de767c9713c08e89e63dcf52fcc3
https://github.com/scummvm/scummvm/commit/46e27b6293c0de767c9713c08e89e63dcf52fcc3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-16T22:48:24-04:00
Commit Message:
SHERLOCK: Update CAnim loading for Rose Tattoo
Changed paths:
engines/sherlock/objects.cpp
engines/sherlock/objects.h
engines/sherlock/scene.cpp
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index c6254ee..2576ff0 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -1135,17 +1135,30 @@ const Common::Rect Object::getOldBounds() const {
/**
* Load the data for the animation
*/
-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 2073f06..fd4a103 100644
--- a/engines/sherlock/objects.h
+++ b/engines/sherlock/objects.h
@@ -256,17 +256,22 @@ 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
- void load(Common::SeekableReadStream &s);
+ // Scalpel specific
+ byte _sequences[MAX_FRAME]; // Animation sequences
+ SpriteType _type;
+
+ // Rose Tattoo specific
+ int _scaleVal; // How much the canim is scaled
+
+ void load(Common::SeekableReadStream &s, bool isRoseTattoo);
};
struct SceneImage {
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 0348964..0ac2eec 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -398,13 +398,14 @@ bool Scene::loadScene(const Common::String &filename) {
// Load in cAnim list
_cAnim.clear();
if (bgHeader._numcAnimations) {
+ int animSize = _vm->getGameID() == GType_SerratedScalpel ? 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, _vm->getGameID() == GType_RoseTattoo);
delete canimStream;
}
Commit: 3683719932882ab60fa1a6c22d19889c9734c355
https://github.com/scummvm/scummvm/commit/3683719932882ab60fa1a6c22d19889c9734c355
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-17T07:20:06-04:00
Commit Message:
SHERLOCK: Implement remaining Rose Tattoo scene data loading
Changed paths:
engines/sherlock/scene.cpp
engines/sherlock/scene.h
engines/sherlock/sherlock.h
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 0ac2eec..96cfac0 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -80,18 +80,30 @@ void BgfileheaderInfo::load(Common::SeekableReadStream &s) {
/**
* Load the data for the object
*/
-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();
}
/*----------------------------------------------------------------*/
@@ -134,6 +146,21 @@ int ObjectArray::indexOf(const Object &obj) const {
/*----------------------------------------------------------------*/
+/**
+ * Load the data for the object
+ */
+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);
@@ -153,6 +180,7 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) {
_animating = 0;
_doBgAnimDone = true;
_tempFadeStyle = 0;
+ _exitZone = -1;
}
Scene::~Scene() {
@@ -280,7 +308,7 @@ bool Scene::loadScene(const Common::String &filename) {
Common::SeekableReadStream *rrmStream = _vm->_res->load(rrmFile);
rrmStream->seek(39);
- if (_vm->getGameID() == GType_SerratedScalpel) {
+ if (IS_SERRATED_SCALPEL) {
_version = rrmStream->readByte();
_lzwMode = _version == 10;
} else {
@@ -291,10 +319,10 @@ bool Scene::loadScene(const Common::String &filename) {
rrmStream->seek(rrmStream->readUint32LE());
BgFileHeader bgHeader;
- bgHeader.synchronize(*rrmStream, _vm->getGameID() == GType_RoseTattoo);
+ bgHeader.synchronize(*rrmStream, IS_ROSE_TATTOO);
_invGraphicItems = bgHeader._numImages + 1;
- if (_vm->getGameID() == GType_RoseTattoo) {
+ if (IS_ROSE_TATTOO) {
screen.initPaletteFade(bgHeader._bytesWritten);
screen.fadeRead(*rrmStream, screen._cMap, PALETTE_SIZE);
screen.setupBGArea(screen._cMap);
@@ -316,7 +344,7 @@ bool Scene::loadScene(const Common::String &filename) {
bgInfo[idx].load(*rrmStream);
// Read information
- if (_vm->getGameID() == GType_SerratedScalpel) {
+ if (IS_SERRATED_SCALPEL) {
Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream :
res.decompress(*rrmStream, bgHeader._numStructs * 569 + bgHeader._descSize + bgHeader._seqSize);
@@ -398,14 +426,14 @@ bool Scene::loadScene(const Common::String &filename) {
// Load in cAnim list
_cAnim.clear();
if (bgHeader._numcAnimations) {
- int animSize = _vm->getGameID() == GType_SerratedScalpel ? 65 : 47;
+ int animSize = IS_SERRATED_SCALPEL ? 65 : 47;
Common::SeekableReadStream *canimStream = _lzwMode ?
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, _vm->getGameID() == GType_RoseTattoo);
+ _cAnim[idx].load(*canimStream, IS_ROSE_TATTOO);
delete canimStream;
}
@@ -413,7 +441,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) {
@@ -428,10 +456,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();
@@ -440,7 +469,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);
@@ -448,15 +477,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();
@@ -465,24 +506,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);
@@ -551,6 +602,16 @@ bool Scene::loadScene(const Common::String &filename) {
}
/**
+ * Load all the sound effects specified for the current scene
+ */
+void Scene::loadSceneSounds() {
+ Sound &sound = *_vm->_sound;
+
+ for (uint idx = 0; idx < _sounds.size(); ++idx)
+ sound.loadSound(_sounds[idx]._name, _sounds[idx]._priority);
+}
+
+/**
* Set objects to their current persistent state. This includes things such as
* opening or moving them
*/
@@ -908,7 +969,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];
}
@@ -1243,7 +1304,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
@@ -1316,7 +1377,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
@@ -1426,7 +1487,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 86b1e3d..9454a4e 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -68,15 +68,17 @@ 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;
- void load(Common::SeekableReadStream &s);
+ Common::String _dest;
+ int _image; // Arrow image to use
+
+ void load(Common::SeekableReadStream &s, bool isRoseTattoo);
};
struct SceneEntry {
@@ -99,6 +101,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;
@@ -109,6 +119,8 @@ private:
bool loadScene(const Common::String &filename);
+ void loadSceneSounds();
+
void checkSceneStatus();
void checkInventory();
@@ -118,6 +130,7 @@ private:
void checkBgShapes(ImageFrame *frame, const Common::Point &pt);
void saveSceneStatus();
+
public:
int _currentScene;
int _goToScene;
@@ -141,9 +154,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/sherlock.h b/engines/sherlock/sherlock.h
index 9261ad5..2688b51 100644
--- a/engines/sherlock/sherlock.h
+++ b/engines/sherlock/sherlock.h
@@ -139,6 +139,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
Commit: 40f7fff42977d01c8bac81d462580c2c8ec39dc3
https://github.com/scummvm/scummvm/commit/40f7fff42977d01c8bac81d462580c2c8ec39dc3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-17T08:09:14-04:00
Commit Message:
SHERLOCK: Beginnings of UserInterface split for Scalpel vs Tattoo
Changed paths:
engines/sherlock/inventory.cpp
engines/sherlock/inventory.h
engines/sherlock/settings.cpp
engines/sherlock/sherlock.cpp
engines/sherlock/talk.cpp
engines/sherlock/talk.h
engines/sherlock/user_interface.cpp
engines/sherlock/user_interface.h
diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp
index 1997807..397575d 100644
--- a/engines/sherlock/inventory.cpp
+++ b/engines/sherlock/inventory.cpp
@@ -274,7 +274,8 @@ void Inventory::drawInventory(int flag) {
screen._backBuffer = &screen._backBuffer1;
}
- ui._oldUse = -1;
+ assert(IS_SERRATED_SCALPEL);
+ ((ScalpelUserInterface *)_vm->_ui)->_oldUse = -1;
}
/**
@@ -356,31 +357,6 @@ void Inventory::highlight(int index, byte color) {
}
/**
- * Support method for updating the screen
- */
-void Inventory::doInvJF() {
- Screen &screen = *_vm->_screen;
- Talk &talk = *_vm->_talk;
- UserInterface &ui = *_vm->_ui;
-
- ui._invLookFlag = true;
- freeInv();
-
- ui._infoFlag = true;
- ui.clearInfo();
-
- screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(0, CONTROLS_Y),
- Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
- ui.examine();
-
- if (!talk._talkToAbort) {
- screen._backBuffer2.blitFrom((*ui._controlPanel)[0]._frame,
- Common::Point(0, CONTROLS_Y));
- loadInv();
- }
-}
-
-/**
* Adds a shape from the scene to the player's inventory
*/
int Inventory::putNameInInventory(const Common::String &name) {
diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h
index eb5aebd..5b9374d 100644
--- a/engines/sherlock/inventory.h
+++ b/engines/sherlock/inventory.h
@@ -95,8 +95,6 @@ public:
void highlight(int index, byte color);
- void doInvJF();
-
int putNameInInventory(const Common::String &name);
int putItemInInventory(Object &obj);
diff --git a/engines/sherlock/settings.cpp b/engines/sherlock/settings.cpp
index ffa1f05..73c99bf 100644
--- a/engines/sherlock/settings.cpp
+++ b/engines/sherlock/settings.cpp
@@ -223,9 +223,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 eea3dcb..80a4383 100644
--- a/engines/sherlock/sherlock.cpp
+++ b/engines/sherlock/sherlock.cpp
@@ -89,7 +89,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/talk.cpp b/engines/sherlock/talk.cpp
index d656431..c67b98b 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -193,9 +193,11 @@ void Talk::talkTo(const Common::String &filename) {
while (!_sequenceStack.empty())
pullSequence();
- // Restore any pressed button
- if (!ui._windowOpen && savedMode != STD_MODE)
- ui.restoreButton(savedMode - 1);
+ if (IS_SERRATED_SCALPEL) {
+ // Restore any pressed button
+ if (!ui._windowOpen && savedMode != STD_MODE)
+ ((ScalpelUserInterface *)_vm->_ui)->restoreButton(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 b1a7358..5c87d79 100644
--- a/engines/sherlock/talk.h
+++ b/engines/sherlock/talk.h
@@ -120,10 +120,10 @@ struct TalkSequences {
};
class SherlockEngine;
-class UserInterface;
+class ScalpelUserInterface;
class Talk {
- friend class UserInterface;
+ friend class ScalpelUserInterface;
private:
Common::Array<TalkSequences> STILL_SEQUENCES;
Common::Array<TalkSequences> TALK_SEQUENCES;
diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp
index 1ab8fe7..efe6c8e 100644
--- a/engines/sherlock/user_interface.cpp
+++ b/engines/sherlock/user_interface.cpp
@@ -78,45 +78,53 @@ 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->getGameID() == GType_SerratedScalpel) {
- _controls = new ImageFile("menu.all");
- _controlPanel = new ImageFile("controls.vgs");
- } else {
- _controls = nullptr;
- _controlPanel = nullptr;
- }
- _bgFound = 0;
- _oldBgFound = -1;
- _keycode = Common::KEYCODE_INVALID;
- _helpStyle = false;
- _menuCounter = 0;
_menuMode = STD_MODE;
- _help = _oldHelp = 0;
- _lookHelp = 0;
+ _menuCounter = 0;
+ _infoFlag = false;
+ _windowOpen = false;
+ _endKeyActive = true;
+ _invLookFlag = 0;
+ _windowStyle = 1; // Sliding windows
+ _helpStyle = false;
+ _lookScriptFlag = false;
+
_key = _oldKey = 0;
+ _selector = _oldSelector = -1;
_temp = _oldTemp = 0;
_temp1 = 0;
- _invLookFlag = 0;
- _windowOpen = false;
+ _lookHelp = 0;
+}
+
+/*----------------------------------------------------------------*/
+
+ScalpelUserInterface::ScalpelUserInterface(SherlockEngine *vm): UserInterface(vm) {
+ _controls = new ImageFile("menu.all");
+ _controlPanel = new ImageFile("controls.vgs");
+ _bgFound = 0;
+ _oldBgFound = -1;
+ _keycode = Common::KEYCODE_INVALID;
+ _help = _oldHelp = 0;
_oldLook = false;
_keyboardInput = false;
_pause = false;
_cNum = 0;
- _selector = _oldSelector = -1;
_windowBounds = Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH - 1,
SHERLOCK_SCREEN_HEIGHT - 1);
- _windowStyle = 1; // Sliding windows
_find = 0;
_oldUse = 0;
- _endKeyActive = true;
- _lookScriptFlag = false;
- _infoFlag = false;
}
-UserInterface::~UserInterface() {
+ScalpelUserInterface::~ScalpelUserInterface() {
delete _controls;
delete _controlPanel;
}
@@ -124,7 +132,7 @@ UserInterface::~UserInterface() {
/**
* Resets the user interface
*/
-void UserInterface::reset() {
+void ScalpelUserInterface::reset() {
_oldKey = -1;
_help = _oldHelp = -1;
_oldTemp = _temp = -1;
@@ -133,7 +141,7 @@ void UserInterface::reset() {
/**
* Draw the user interface onto the screen's back buffers
*/
-void UserInterface::drawInterface(int bufferNum) {
+void ScalpelUserInterface::drawInterface(int bufferNum) {
Screen &screen = *_vm->_screen;
if (bufferNum & 1)
@@ -147,7 +155,7 @@ void UserInterface::drawInterface(int bufferNum) {
/**
* Main input handler for the user interface
*/
-void UserInterface::handleInput() {
+void ScalpelUserInterface::handleInput() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
People &people = *_vm->_people;
@@ -405,7 +413,7 @@ void UserInterface::handleInput() {
/**
* Draws the image for a user interface button in the down/pressed state.
*/
-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]);
@@ -418,7 +426,7 @@ void UserInterface::depressButton(int num) {
* Draws the image for the given user interface button in the up
* (not selected) position
*/
-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;
@@ -437,7 +445,7 @@ void UserInterface::restoreButton(int num) {
* If he mouse button is pressed, then calls depressButton to draw the button
* as pressed; if not, it will show it as released with a call to "restoreButton".
*/
-void UserInterface::pushButton(int num) {
+void ScalpelUserInterface::pushButton(int num) {
Events &events = *_vm->_events;
_oldKey = -1;
@@ -459,7 +467,7 @@ void UserInterface::pushButton(int num) {
* have already been drawn. This simply takes care of switching the mode around
* accordingly
*/
-void UserInterface::toggleButton(int num) {
+void ScalpelUserInterface::toggleButton(int num) {
Screen &screen = *_vm->_screen;
if (_menuMode != (num + 1)) {
@@ -490,7 +498,7 @@ void UserInterface::toggleButton(int num) {
/**
* Clears the info line of the screen
*/
-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);
@@ -502,7 +510,7 @@ void UserInterface::clearInfo() {
/**
* Clear any active text window
*/
-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);
@@ -512,7 +520,7 @@ void UserInterface::clearWindow() {
/**
* Handles counting down whilst checking for input, then clears the info line.
*/
-void UserInterface::whileMenuCounter() {
+void ScalpelUserInterface::whileMenuCounter() {
if (!(--_menuCounter) || _vm->_events->checkInput()) {
_menuCounter = 0;
_infoFlag = true;
@@ -524,7 +532,7 @@ void UserInterface::whileMenuCounter() {
* Creates a text window and uses it to display the in-depth description
* of the highlighted object
*/
-void UserInterface::examine() {
+void ScalpelUserInterface::examine() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
People &people = *_vm->_people;
@@ -578,7 +586,7 @@ void UserInterface::examine() {
/**
* Print the name of an object in the scene
*/
-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;
@@ -694,7 +702,7 @@ void UserInterface::lookScreen(const Common::Point &pt) {
/**
* Gets the item in the inventory the mouse is on and display's it's description
*/
-void UserInterface::lookInv() {
+void ScalpelUserInterface::lookInv() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
Screen &screen = *_vm->_screen;
@@ -722,7 +730,7 @@ void UserInterface::lookInv() {
/**
* Handles input when the file list window is being displayed
*/
-void UserInterface::doEnvControl() {
+void ScalpelUserInterface::doEnvControl() {
Events &events = *_vm->_events;
SaveManager &saves = *_vm->_saves;
Scene &scene = *_vm->_scene;
@@ -1028,12 +1036,13 @@ void UserInterface::doEnvControl() {
/**
* Handle input whilst the inventory is active
*/
-void UserInterface::doInvControl() {
+void ScalpelUserInterface::doInvControl() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
Scene &scene = *_vm->_scene;
Screen &screen = *_vm->_screen;
Talk &talk = *_vm->_talk;
+ UserInterface &ui = *_vm->_ui;
int colors[8];
Common::Point mousePos = events.mousePos();
@@ -1197,7 +1206,7 @@ void UserInterface::doInvControl() {
if ((mousePos.y < CONTROLS_Y1) && (inv._invMode == 1) && (_find >= 0) && (_find < 1000)) {
if (!scene._bgShapes[_find]._examine.empty() &&
scene._bgShapes[_find]._examine[0] >= ' ')
- inv.doInvJF();
+ ui.doInvJF();
} else if (_selector != -1 || _find >= 0) {
// Selector is the inventory object that was clicked on, or selected.
// If it's -1, then no inventory item is highlighted yet. Otherwise,
@@ -1205,7 +1214,7 @@ void UserInterface::doInvControl() {
if (_selector != -1 && inv._invMode == INVMODE_LOOK
&& mousePos.y >(CONTROLS_Y1 + 11))
- inv.doInvJF();
+ ui.doInvJF();
if (talk._talkToAbort)
return;
@@ -1255,7 +1264,7 @@ void UserInterface::doInvControl() {
/**
* Handles waiting whilst an object's description window is open.
*/
-void UserInterface::doLookControl() {
+void ScalpelUserInterface::doLookControl() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
Screen &screen = *_vm->_screen;
@@ -1319,7 +1328,7 @@ void UserInterface::doLookControl() {
/**
* Handles input until one of the user interface buttons/commands is selected
*/
-void UserInterface::doMainControl() {
+void ScalpelUserInterface::doMainControl() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
SaveManager &saves = *_vm->_saves;
@@ -1460,7 +1469,7 @@ void UserInterface::doMainControl() {
/**
* Handles the input for the MOVE, OPEN, and CLOSE commands
*/
-void UserInterface::doMiscControl(int allowed) {
+void ScalpelUserInterface::doMiscControl(int allowed) {
Events &events = *_vm->_events;
Scene &scene = *_vm->_scene;
Talk &talk = *_vm->_talk;
@@ -1512,7 +1521,7 @@ void UserInterface::doMiscControl(int allowed) {
/**
* Handles input for picking up items
*/
-void UserInterface::doPickControl() {
+void ScalpelUserInterface::doPickControl() {
Events &events = *_vm->_events;
Scene &scene = *_vm->_scene;
Talk &talk = *_vm->_talk;
@@ -1539,7 +1548,7 @@ void UserInterface::doPickControl() {
* Handles input when in talk mode. It highlights the buttons and available statements,
* and handles allowing the user to click on them
*/
-void UserInterface::doTalkControl() {
+void ScalpelUserInterface::doTalkControl() {
Events &events = *_vm->_events;
Journal &journal = *_vm->_journal;
People &people = *_vm->_people;
@@ -1795,7 +1804,7 @@ void UserInterface::doTalkControl() {
* the user interface, it uses so many internal UI fields, that it sort of made some sense
* to put it in the UserInterface class.
*/
-void UserInterface::journalControl() {
+void ScalpelUserInterface::journalControl() {
Events &events = *_vm->_events;
Journal &journal = *_vm->_journal;
Scene &scene = *_vm->_scene;
@@ -1846,7 +1855,7 @@ void UserInterface::journalControl() {
/**
* Print the description of an object
*/
-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;
@@ -2017,14 +2026,14 @@ void UserInterface::printObjectDesc(const Common::String &str, bool firstTime) {
/**
* Print the previously selected object's decription
*/
-void UserInterface::printObjectDesc() {
+void ScalpelUserInterface::printObjectDesc() {
printObjectDesc(_cAnimStr, true);
}
/**
* Displays a passed window by gradually scrolling it vertically on-screen
*/
-void UserInterface::summonWindow(const Surface &bgSurface, bool slideUp) {
+void ScalpelUserInterface::summonWindow(const Surface &bgSurface, bool slideUp) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
@@ -2067,7 +2076,7 @@ void UserInterface::summonWindow(const Surface &bgSurface, bool slideUp) {
/**
* Slide the window stored in the back buffer onto the screen
*/
-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
@@ -2088,7 +2097,7 @@ void UserInterface::summonWindow(bool slideUp, int height) {
* Close a currently open window
* @param flag 0 = slide old window down, 1 = slide prior UI back up
*/
-void UserInterface::banishWindow(bool slideUp) {
+void ScalpelUserInterface::banishWindow(bool slideUp) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
@@ -2157,7 +2166,7 @@ void UserInterface::banishWindow(bool slideUp) {
/**
* Checks to see whether a USE action is valid on the given object
*/
-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, int giveMode) {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
@@ -2253,7 +2262,7 @@ void UserInterface::checkUseAction(const UseType *use, const Common::String &inv
/**
* Called for OPEN, CLOSE, and MOVE actions are being done
*/
-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;
@@ -2385,4 +2394,39 @@ void UserInterface::checkAction(ActionType &action, const char *const messages[]
events.setCursor(ARROW);
}
+/**
+ * Support method for updating the screen
+ */
+void ScalpelUserInterface::doInvJF() {
+ Inventory &inv = *_vm->_inventory;
+ Screen &screen = *_vm->_screen;
+ Talk &talk = *_vm->_talk;
+
+ _invLookFlag = true;
+ inv.freeInv();
+
+ _infoFlag = true;
+ clearInfo();
+
+ screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(0, CONTROLS_Y),
+ Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+ examine();
+
+ if (!talk._talkToAbort) {
+ screen._backBuffer2.blitFrom((*_controlPanel)[0]._frame,
+ Common::Point(0, CONTROLS_Y));
+ inv.loadInv();
+ }
+}
+
+/*----------------------------------------------------------------*/
+
+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 2ff6071..acbb0c0 100644
--- a/engines/sherlock/user_interface.h
+++ b/engines/sherlock/user_interface.h
@@ -61,31 +61,64 @@ 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;
+ int _windowStyle;
+ 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
+ int _key, _oldKey;
+ int _selector, _oldSelector;
+ int _temp, _oldTemp;
+ int _temp1;
+ int _lookHelp;
+public:
+ static UserInterface *init(SherlockEngine *vm);
+
+ virtual void reset() {}
+ virtual void drawInterface(int bufferNum = 3) {}
+ virtual void handleInput() {}
+
+ virtual void doInvJF() {}
+ virtual void summonWindow(const Surface &bgSurface, bool slideUp = true) {}
+ virtual void summonWindow(bool slideUp = true, int height = CONTROLS_Y) {}
+ virtual void banishWindow(bool slideUp = true) {}
+ virtual void clearInfo() {}
+ virtual void clearWindow() {}
+
+ 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;
int _keycode;
- int _lookHelp;
int _help, _oldHelp;
- int _key, _oldKey;
- int _temp, _oldTemp;
int _oldLook;
bool _keyboardInput;
bool _pause;
int _cNum;
- int _selector, _oldSelector;
Common::String _cAnimStr;
- bool _lookScriptFlag;
- Common::Rect _windowBounds;
Common::String _descStr;
int _find;
int _oldUse;
@@ -114,39 +147,38 @@ private:
void checkUseAction(const UseType *use, const Common::String &invName, const char *const messages[],
int objNum, int giveMode);
void checkAction(ActionType &action, const char *const messages[], int objNum);
+
+ void printObjectDesc(const Common::String &str, bool firstTime);
public:
- MenuMode _menuMode;
- int _menuCounter;
- bool _infoFlag;
- bool _windowOpen;
- bool _endKeyActive;
- int _invLookFlag;
- int _temp1;
- int _windowStyle;
- bool _helpStyle;
-public:
- UserInterface(SherlockEngine *vm);
- ~UserInterface();
+ ScalpelUserInterface(SherlockEngine *vm);
+ ~ScalpelUserInterface();
- void reset();
+ void whileMenuCounter();
- void drawInterface(int bufferNum = 3);
+ void restoreButton(int num);
+public:
+ virtual void reset();
- void handleInput();
+ virtual void handleInput();
- void clearInfo();
- void clearWindow();
+ virtual void drawInterface(int bufferNum = 3);
- void whileMenuCounter();
+ virtual void doInvJF();
- void printObjectDesc(const Common::String &str, bool firstTime);
- void printObjectDesc();
+ virtual void summonWindow(const Surface &bgSurface, bool slideUp = true);
+ virtual void summonWindow(bool slideUp = true, int height = CONTROLS_Y);
+ virtual void banishWindow(bool slideUp = true);
+ virtual void clearInfo();
+ virtual void clearWindow();
- void summonWindow(const Surface &bgSurface, bool slideUp = true);
- void summonWindow(bool slideUp = true, int height = CONTROLS_Y);
- void banishWindow(bool slideUp = true);
+ virtual void printObjectDesc();
+};
- void restoreButton(int num);
+class TattooUserInterface : public UserInterface {
+public:
+ TattooUserInterface(SherlockEngine *vm);
+public:
+ virtual void handleInput();
};
} // End of namespace Sherlock
Commit: b4b6bf63dbfd3f952f4ca207467315396b53bd23
https://github.com/scummvm/scummvm/commit/b4b6bf63dbfd3f952f4ca207467315396b53bd23
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-22T22:31:21-04:00
Commit Message:
Merge branch 'master' into sherlock2
Changed paths:
NEWS
README
audio/mods/protracker.cpp
backends/graphics/openglsdl/openglsdl-graphics.cpp
backends/graphics/surfacesdl/surfacesdl-graphics.cpp
backends/graphics/surfacesdl/surfacesdl-graphics.h
devtools/scumm-md5.txt
engines/agi/agi.cpp
engines/agi/agi.h
engines/agi/detection.cpp
engines/agi/detection_tables.h
engines/agi/font.h
engines/agi/graphics.cpp
engines/agi/graphics.h
engines/agi/preagi.cpp
engines/agi/sound_pcjr.cpp
engines/agi/text.cpp
engines/agos/rooms.cpp
engines/agos/saveload.cpp
engines/cine/detection_tables.h
engines/fullpipe/scene.cpp
engines/kyra/sound_adlib.cpp
engines/mads/action.cpp
engines/mads/action.h
engines/mads/animation.cpp
engines/mads/animation.h
engines/mads/assets.cpp
engines/mads/assets.h
engines/mads/audio.cpp
engines/mads/audio.h
engines/mads/compression.cpp
engines/mads/compression.h
engines/mads/debugger.cpp
engines/mads/debugger.h
engines/mads/detection.cpp
engines/mads/detection_tables.h
engines/mads/dialogs.cpp
engines/mads/dialogs.h
engines/mads/dragonsphere/dragonsphere_scenes.cpp
engines/mads/dragonsphere/dragonsphere_scenes.h
engines/mads/dragonsphere/game_dragonsphere.cpp
engines/mads/dragonsphere/game_dragonsphere.h
engines/mads/events.cpp
engines/mads/events.h
engines/mads/font.cpp
engines/mads/font.h
engines/mads/game.cpp
engines/mads/game.h
engines/mads/game_data.cpp
engines/mads/game_data.h
engines/mads/globals.cpp
engines/mads/globals.h
engines/mads/hotspots.cpp
engines/mads/hotspots.h
engines/mads/inventory.cpp
engines/mads/inventory.h
engines/mads/mads.cpp
engines/mads/mads.h
engines/mads/menu_views.cpp
engines/mads/menu_views.h
engines/mads/messages.cpp
engines/mads/messages.h
engines/mads/msurface.cpp
engines/mads/msurface.h
engines/mads/nebular/dialogs_nebular.cpp
engines/mads/nebular/dialogs_nebular.h
engines/mads/nebular/game_nebular.cpp
engines/mads/nebular/game_nebular.h
engines/mads/nebular/globals_nebular.cpp
engines/mads/nebular/globals_nebular.h
engines/mads/nebular/menu_nebular.cpp
engines/mads/nebular/menu_nebular.h
engines/mads/nebular/nebular_scenes.cpp
engines/mads/nebular/nebular_scenes.h
engines/mads/nebular/nebular_scenes1.cpp
engines/mads/nebular/nebular_scenes1.h
engines/mads/nebular/nebular_scenes2.cpp
engines/mads/nebular/nebular_scenes2.h
engines/mads/nebular/nebular_scenes3.cpp
engines/mads/nebular/nebular_scenes3.h
engines/mads/nebular/nebular_scenes4.cpp
engines/mads/nebular/nebular_scenes4.h
engines/mads/nebular/nebular_scenes5.cpp
engines/mads/nebular/nebular_scenes5.h
engines/mads/nebular/nebular_scenes6.cpp
engines/mads/nebular/nebular_scenes6.h
engines/mads/nebular/nebular_scenes7.cpp
engines/mads/nebular/nebular_scenes7.h
engines/mads/nebular/nebular_scenes8.cpp
engines/mads/nebular/nebular_scenes8.h
engines/mads/nebular/sound_nebular.cpp
engines/mads/nebular/sound_nebular.h
engines/mads/palette.cpp
engines/mads/palette.h
engines/mads/phantom/game_phantom.cpp
engines/mads/phantom/game_phantom.h
engines/mads/phantom/phantom_scenes.cpp
engines/mads/phantom/phantom_scenes.h
engines/mads/player.cpp
engines/mads/player.h
engines/mads/rails.cpp
engines/mads/rails.h
engines/mads/resources.cpp
engines/mads/resources.h
engines/mads/scene.cpp
engines/mads/scene.h
engines/mads/screen.cpp
engines/mads/screen.h
engines/mads/sequence.cpp
engines/mads/sequence.h
engines/mads/sound.cpp
engines/mads/sound.h
engines/mads/sprites.cpp
engines/mads/sprites.h
engines/mads/staticres.cpp
engines/mads/staticres.h
engines/mads/user_interface.cpp
engines/mads/user_interface.h
engines/queen/walk.cpp
engines/saga/scene.cpp
engines/sci/console.cpp
engines/sci/console.h
engines/sci/detection_tables.h
engines/sci/engine/script.cpp
engines/sci/engine/script.h
engines/sci/engine/script_patches.cpp
engines/sci/engine/workarounds.cpp
engines/scumm/scumm-md5.h
engines/sherlock/animation.cpp
engines/sherlock/animation.h
engines/sherlock/debugger.cpp
engines/sherlock/debugger.h
engines/sherlock/detection.cpp
engines/sherlock/detection_tables.h
engines/sherlock/events.cpp
engines/sherlock/events.h
engines/sherlock/inventory.cpp
engines/sherlock/inventory.h
engines/sherlock/journal.cpp
engines/sherlock/journal.h
engines/sherlock/map.cpp
engines/sherlock/map.h
engines/sherlock/objects.cpp
engines/sherlock/objects.h
engines/sherlock/people.cpp
engines/sherlock/people.h
engines/sherlock/resources.cpp
engines/sherlock/resources.h
engines/sherlock/saveload.cpp
engines/sherlock/saveload.h
engines/sherlock/scalpel/darts.cpp
engines/sherlock/scalpel/darts.h
engines/sherlock/scalpel/scalpel.cpp
engines/sherlock/scalpel/scalpel.h
engines/sherlock/scene.cpp
engines/sherlock/scene.h
engines/sherlock/screen.cpp
engines/sherlock/screen.h
engines/sherlock/settings.cpp
engines/sherlock/settings.h
engines/sherlock/sherlock.cpp
engines/sherlock/sherlock.h
engines/sherlock/sound.cpp
engines/sherlock/sound.h
engines/sherlock/surface.cpp
engines/sherlock/surface.h
engines/sherlock/talk.cpp
engines/sherlock/talk.h
engines/sherlock/user_interface.cpp
engines/sherlock/user_interface.h
engines/toon/toon.cpp
diff --cc engines/sherlock/inventory.cpp
index 397575d,7f216a3..bbb7c75
--- a/engines/sherlock/inventory.cpp
+++ b/engines/sherlock/inventory.cpp
@@@ -274,14 -243,9 +243,10 @@@ void Inventory::drawInventory(InvNewMod
screen._backBuffer = &screen._backBuffer1;
}
- ui._oldUse = -1;
+ assert(IS_SERRATED_SCALPEL);
+ ((ScalpelUserInterface *)_vm->_ui)->_oldUse = -1;
}
- /**
- * Prints the line of inventory commands at the top of an inventory window with
- * the correct highlighting
- */
void Inventory::invCommands(bool slamIt) {
Screen &screen = *_vm->_screen;
UserInterface &ui = *_vm->_ui;
@@@ -356,9 -317,27 +318,30 @@@ void Inventory::highlight(int index, by
screen.slamArea(8 + slot * 52, 165, 44, 30);
}
- /**
- * Adds a shape from the scene to the player's inventory
- */
+ 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();
+
+ ui._infoFlag = true;
+ ui.clearInfo();
+
+ screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(0, CONTROLS_Y),
+ Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+ ui.examine();
+
+ if (!talk._talkToAbort) {
+ screen._backBuffer2.blitFrom((*ui._controlPanel)[0], Common::Point(0, CONTROLS_Y));
+ loadInv();
+ }
+ }
+
int Inventory::putNameInInventory(const Common::String &name) {
Scene &scene = *_vm->_scene;
int matches = 0;
diff --cc engines/sherlock/map.cpp
index 46e233b,42775ae..44ca7cd
--- a/engines/sherlock/map.cpp
+++ b/engines/sherlock/map.cpp
@@@ -91,17 -82,9 +83,14 @@@ void Map::loadSequences(int count, cons
Common::copy(seq, seq + MAX_FRAME, &_sequences[idx][0]);
}
- /**
- * Load data needed for the map
- */
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 --cc engines/sherlock/objects.cpp
index 2576ff0,02f2526..f380351
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@@ -386,21 -371,11 +371,16 @@@ void ActionType::load(Common::SeekableR
UseType::UseType() {
_cAnimNum = _cAnimSpeed = 0;
_useFlag = 0;
- _dFlag[0] = 0;
- _lFlag[0] = _lFlag[1] = 0;
}
- /**
- * Load the data for the UseType
- */
-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)
@@@ -412,12 -387,7 +392,9 @@@
}
_useFlag = s.readSint16LE();
- s.skip(6);
+
- if (!isRoseTattoo) {
- _dFlag[0] = s.readSint16LE();
- _lFlag[0] = s.readSint16LE();
- _lFlag[1] = s.readSint16LE();
- }
++ if (!isRoseTattoo)
++ s.skip(6);
s.read(buffer, 12);
_target = Common::String(buffer);
@@@ -464,19 -434,9 +441,16 @@@ Object::Object()
_descOffset = 0;
_seqCounter2 = 0;
_seqSize = 0;
+
+ _quickDraw = 0;
+ _scaleVal = 0;
+ _requiredFlag1 = 0;
+ _gotoSeq = 0;
+ _talkSeq = 0;
+ _restoreSlot = 0;
}
- /**
- * Load the data for the object
- */
-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);
@@@ -539,30 -493,14 +513,27 @@@
_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);
+ }
}
- /**
- * Toggle the type of an object between hidden and active
- */
void Object::toggleHidden() {
if (_type != HIDDEN && _type != HIDE_SHAPE && _type != INVALID) {
if (_seqTo != 0)
@@@ -1132,10 -1032,7 +1065,7 @@@ const Common::Rect Object::getOldBounds
/*----------------------------------------------------------------*/
- /**
- * Load the data for the animation
- */
-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);
diff --cc engines/sherlock/objects.h
index fd4a103,bbd068e..b61e7e2
--- a/engines/sherlock/objects.h
+++ b/engines/sherlock/objects.h
@@@ -154,17 -176,21 +176,22 @@@ struct ActionType
struct UseType {
int _cAnimNum;
int _cAnimSpeed;
- Common::String _names[4];
+ Common::String _names[NAMES_COUNT];
int _useFlag; // Which flag USE will set (if any)
- int _dFlag[1];
- int _lFlag[2];
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 };
+ #define USE_COUNT 4
+
class Object {
private:
static SherlockEngine *_vm;
@@@ -233,24 -258,69 +269,69 @@@ public
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
+ */
void toggleHidden();
+ /**
+ * Check the state of the object
+ */
void checkObject();
+ /**
+ * Checks for codes
+ * @param name The name to check for codes
+ * @param messages Provides a lookup list of messages that can be printed
+ * @returns 0 if no codes are found, 1 if codes were found
+ */
int checkNameForCodes(const Common::String &name, const char *const messages[]);
+ /**
+ * Handle setting any flags associated with the object
+ */
void setFlagsAndToggles();
+ /**
+ * Adjusts the sprite's position and animation sequence, advancing by 1 frame.
+ * If the end of the sequence is reached, the appropriate action is taken.
+ */
void adjustObject();
+ /**
+ * Handles trying to pick up an object. If allowed, plays an y necessary animation for picking
+ * up the item, and then adds it to the player's inventory
+ */
int pickUpObject(const char *const messages[]);
+ /**
+ * Return the frame width
+ */
int frameWidth() const { return _imageFrame ? _imageFrame->_frame.w : 0; }
+
+ /**
+ * Return the frame height
+ */
int frameHeight() const { return _imageFrame ? _imageFrame->_frame.h : 0; }
+
+ /**
+ * Returns the current bounds for the sprite
+ */
const Common::Rect getNewBounds() const;
+
+ /**
+ * Returns the bounds for a sprite without a shape
+ */
const Common::Rect getNoShapeBounds() const;
+
+ /**
+ * Returns the old bounsd for the sprite from the previous frame
+ */
const Common::Rect getOldBounds() const;
};
@@@ -264,14 -336,10 +345,17 @@@ struct CAnim
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 --cc engines/sherlock/resources.cpp
index 24fef3f,091ef3e..864622e
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@@ -193,9 -157,17 +160,19 @@@ Common::SeekableReadStream *Resources::
return stream;
}
- /**
- * Loads a specific resource from a given library file
- */
+ 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);
+ }
+ }
+
Common::SeekableReadStream *Resources::load(const Common::String &filename, const Common::String &libraryFile) {
// Open up the library for access
Common::SeekableReadStream *libStream = load(libraryFile);
@@@ -221,11 -191,8 +196,8 @@@ bool Resources::exists(const Common::St
return f.exists(filename) || _cache.isCached(filename);
}
- /**
- * Reads in the index from a library file, and caches it's index for later use
- */
void Resources::loadLibraryIndex(const Common::String &libFilename,
- Common::SeekableReadStream *stream) {
+ Common::SeekableReadStream *stream, bool isNewStyle) {
uint32 offset, nextOffset;
// Create an index entry
@@@ -272,6 -231,59 +239,80 @@@ 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;
+ 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 {
++ } 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;
++ } while ((outSize == -1 || outBuffer < outBufferEnd) || (inSize == -1 || source.pos() < endPos));
+ }
+
/*----------------------------------------------------------------*/
SherlockEngine *ImageFile::_vm;
diff --cc engines/sherlock/resources.h
index a320852,fb91b30..659ecf0
--- a/engines/sherlock/resources.h
+++ b/engines/sherlock/resources.h
@@@ -72,29 -87,67 +87,82 @@@ private
LibraryIndexes _indexes;
int _resourceIndex;
- void loadLibraryIndex(const Common::String &libFilename, Common::SeekableReadStream *stream,
- bool isNewStyle);
+ /**
+ * 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);
+ /**
+ * Adds the specified file to the cache. If it's a library file, takes care of
+ * loading it's index for future use
+ */
void addToCache(const Common::String &filename);
+
+ /**
+ * Adds a resource from a library file to the cache
+ */
void addToCache(const Common::String &filename, const Common::String &libFilename);
+
+ /**
+ * Adds a given stream to the cache under the given name
+ */
void addToCache(const Common::String &filename, Common::SeekableReadStream &stream);
+
bool isInCache(const Common::String &filename) const { return _cache.isCached(filename); }
+ /**
+ * Checks the passed stream, and if is compressed, deletes it and replaces it with it's uncompressed data
+ */
+ void decompressIfNecessary(Common::SeekableReadStream *&stream);
+
+ /**
+ * Returns a stream for a given file
+ */
Common::SeekableReadStream *load(const Common::String &filename);
+ /**
+ * Loads a specific resource from a given library file
+ */
Common::SeekableReadStream *load(const Common::String &filename, const Common::String &libraryFile);
+ /**
+ * Returns true if the given file exists on disk or in the cache
+ */
bool exists(const Common::String &filename) const;
+ /**
+ * Returns the index of the last loaded resource in it's given library file.
+ * This will be used primarily when loading talk files, so the engine can
+ * update the given conversation number in the journal
+ */
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);
- static void decompressLZ(Common::SeekableReadStream &source, byte *outBuffer, int32 outSize, int32 inSize);
++
++ /**
++ * 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 --cc engines/sherlock/scalpel/scalpel.cpp
index eff5898,7875f22..ccc9c8a
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@@ -239,13 -377,7 +378,10 @@@ ScalpelEngine::~ScalpelEngine()
delete _darts;
}
- /**
- * Game initialization
- */
void ScalpelEngine::initialize() {
+ initGraphics(320, 200, false);
+
+ // Let the base engine intialize
SherlockEngine::initialize();
_darts = new Darts(this);
@@@ -254,16 -386,12 +390,19 @@@
_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");
+
- // Load the map co-ordinates for each scene and sequence data
- _map->loadPoints(NUM_PLACES, &MAP_X[0], &MAP_Y[0], &MAP_TRANSLATE[0]);
- _map->loadSequences(3, &MAP_SEQUENCES[0][0]);
+ 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]);
+ _map->loadSequences(3, &MAP_SEQUENCES[0][0]);
+ _map->_oldCharPoint = BAKER_ST_EXTERIOR;
+ }
// Load the inventory
loadInventory();
@@@ -463,9 -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, _screen->w, 10));
- _screen->blitFrom(_screen->_backBuffer1, Common::Point(0, _screen->h - 10),
- Common::Rect(0, _screen->h - 10, _screen->w, _screen->h));
- _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 --cc engines/sherlock/scene.cpp
index 96cfac0,5ae7e25..2c80bfb
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@@ -27,24 -26,14 +27,31 @@@
namespace Sherlock {
+ static const int FS_TRANS[8] = {
+ STOP_UP, STOP_UPRIGHT, STOP_RIGHT, STOP_DOWNRIGHT, STOP_DOWN,
+ STOP_DOWNLEFT, STOP_LEFT, STOP_UPLEFT
+ };
+
+ /*----------------------------------------------------------------*/
+
-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::synchronize(Common::SeekableReadStream &s, bool isRoseTattoo) {
++void BgFileHeader::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
_numStructs = s.readUint16LE();
_numImages = s.readUint16LE();
_numcAnimations = s.readUint16LE();
@@@ -77,27 -55,15 +81,24 @@@ void BgFileHeaderInfo::load(Common::See
/*----------------------------------------------------------------*/
- /**
- * Load the data for the object
- */
-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();
@@@ -146,22 -100,7 +138,19 @@@ int ObjectArray::indexOf(const Object &
/*----------------------------------------------------------------*/
- /**
- * Load the data for the object
- */
-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;
@@@ -317,77 -227,63 +283,99 @@@ bool Scene::loadScene(const Common::Str
// Go to header and read it in
rrmStream->seek(rrmStream->readUint32LE());
+
BgFileHeader bgHeader;
- bgHeader.synchronize(*rrmStream, IS_ROSE_TATTOO);
- 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);
for (uint idx = 0; idx < bgInfo.size(); ++idx)
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);
+ rrmStream->read(&_descText[0], bgHeader._descSize);
+ }
+
+ if (bgHeader._seqSize) {
+ _sequenceBuffer.resize(bgHeader._seqSize);
+ rrmStream->read(&_sequenceBuffer[0], bgHeader._seqSize);
+ }
} else {
- // Load shapes
- Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream : res.decompress(*rrmStream, bgHeader._numStructs * 625);
+ Common::SeekableReadStream *infoStream;
+
+ // Read shapes
+ infoStream = Resources::decompressLZ(*rrmStream, bgHeader._numStructs * 569);
_bgShapes.resize(bgHeader._numStructs);
for (int idx = 0; idx < bgHeader._numStructs; ++idx)
- _bgShapes[idx].load(*infoStream, true);
- _bgShapes[idx].load(*infoStream);
++ _bgShapes[idx].load(*infoStream, false);
+
+ delete infoStream;
+
+ // Read description texts
+ if (bgHeader._descSize) {
+ infoStream = Resources::decompressLZ(*rrmStream, bgHeader._descSize);
+
+ _descText.resize(bgHeader._descSize);
+ infoStream->read(&_descText[0], bgHeader._descSize);
- if (_lzwMode)
delete infoStream;
+ }
- // Load description text
- _descText.resize(bgHeader._descSize);
- if (_lzwMode)
- res.decompress(*rrmStream, (byte *)&_descText[0], bgHeader._descSize);
- else
- rrmStream->read(&_descText[0], bgHeader._descSize);
+ // Read sequences
+ if (bgHeader._seqSize) {
+ infoStream = Resources::decompressLZ(*rrmStream, bgHeader._seqSize);
- // Load sequences
- _sequenceBuffer.resize(bgHeader._seqSize);
- if (_lzwMode)
- res.decompress(*rrmStream, &_sequenceBuffer[0], bgHeader._seqSize);
- else
- rrmStream->read(&_sequenceBuffer[0], bgHeader._seqSize);
+ _sequenceBuffer.resize(bgHeader._seqSize);
+ infoStream->read(&_sequenceBuffer[0], bgHeader._seqSize);
+
+ delete infoStream;
+ }
}
// Set up the list of images used by the scene
@@@ -601,20 -472,6 +588,13 @@@
return flag;
}
- /**
- * Load all the sound effects specified for the current scene
- */
+void Scene::loadSceneSounds() {
+ Sound &sound = *_vm->_sound;
+
+ for (uint idx = 0; idx < _sounds.size(); ++idx)
+ sound.loadSound(_sounds[idx]._name, _sounds[idx]._priority);
+}
+
- /**
- * Set objects to their current persistent state. This includes things such as
- * opening or moving them
- */
void Scene::checkSceneStatus() {
if (_sceneStats[_currentScene][64]) {
for (uint idx = 0; idx < 64; ++idx) {
@@@ -964,12 -791,9 +914,9 @@@ void Scene::updateBackground()
screen.resetDisplayBounds();
}
- /**
- * Check whether the passed area intersects with one of the scene's exits
- */
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];
}
diff --cc engines/sherlock/scene.h
index 9454a4e,88d12a3..0cbd775
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@@ -45,22 -44,15 +45,26 @@@ 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();
- void synchronize(Common::SeekableReadStream &s, bool isRoseTattoo);
++
+ /**
+ * Load the data for the object
+ */
- void load(Common::SeekableReadStream &s);
++ void load(Common::SeekableReadStream &s, bool isRoseTattoo);
};
- struct BgfileheaderInfo {
+ struct BgFileHeaderInfo {
int _filesize; // How long images are
int _maxFrames; // How many unique frames in object
Common::String _filename; // Filename of object
@@@ -75,10 -71,10 +82,13 @@@ public
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 {
@@@ -113,24 -110,50 +132,56 @@@ class Scene
private:
SherlockEngine *_vm;
Common::String _rrmName;
- int _selector;
- bool _lookHelp;
bool _loadingSavedGame;
+ /**
+ * Loads the data associated for a given scene. The .BGD file's format is:
+ * BGHEADER: Holds an index for the rest of the file
+ * STRUCTS: The objects for the scene
+ * IMAGES: The graphic information for the structures
+ *
+ * The _misc field of the structures contains the number of the graphic image
+ * that it should point to after loading; _misc is then set to 0.
+ */
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
+ */
void checkSceneStatus();
+ /**
+ * Checks scene objects against the player's inventory items. If there are any
+ * matching names, it means the given item has already been picked up, and should
+ * be hidden in the scene.
+ */
void checkInventory();
+ /**
+ * Set up any entrance co-ordinates or entrance canimations, and then transition
+ * in the scene
+ */
void transitionToScene();
+ /**
+ * Checks all the background shapes. If a background shape is animating,
+ * it will flag it as needing to be drawn. If a non-animating shape is
+ * colliding with another shape, it will also flag it as needing drawing
+ */
void checkBgShapes(ImageFrame *frame, const Common::Point &pt);
+ /**
+ * Restores objects to the correct status. This ensures that things like being opened or moved
+ * will remain the same on future visits to the scene
+ */
void saveSceneStatus();
+
public:
int _currentScene;
int _goToScene;
diff --cc engines/sherlock/screen.cpp
index 349bf4d,e70d061..24f7660
--- a/engines/sherlock/screen.cpp
+++ b/engines/sherlock/screen.cpp
@@@ -38,19 -38,7 +38,15 @@@ Screen::Screen(SherlockEngine *vm) : Su
_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);
+
- // Set dummy surface used for restricted scene drawing
- _sceneSurface.format = Graphics::PixelFormat::createFormatCLUT8();
- _sceneSurface.pitch = pitch;
-
+ // Rose Tattoo specific fields
+ _fadeBytesRead = _fadeBytesToRead = 0;
+ _oldFadePercent = 0;
+ _scrollSize = 0;
+ _currentScroll = 0;
+ _targetScroll = 0;
}
Screen::~Screen() {
@@@ -220,9 -177,9 +185,9 @@@ void Screen::randomTransition()
for (int idx = 0; idx <= 65535 && !_vm->shouldQuit(); ++idx) {
_transitionSeed = _transitionSeed * TRANSITION_MULTIPLIER + 1;
- int offset = _transitionSeed & 65535;
+ int offset = _transitionSeed & 0xFFFF;
- if (offset < (this->w * this->h))
- 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) {
@@@ -242,15 -199,12 +207,12 @@@
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 < this->h; ++yp) {
- for (int xp = 0; xp < this->w; ++xp) {
- int temp = (table[xp] >= (this->h - 3)) ? this->h - table[xp] :
- 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) {
@@@ -267,10 -221,7 +229,7 @@@
void Screen::restoreBackground(const Common::Rect &r) {
if (r.width() > 0 && r.height() > 0) {
Common::Rect tempRect = r;
- tempRect.clip(Common::Rect(0, 0, this->w, SHERLOCK_SCENE_HEIGHT));
- 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);
@@@ -287,10 -235,7 +243,7 @@@ void Screen::slamArea(int16 xp, int16 y
void Screen::slamRect(const Common::Rect &r) {
if (r.width() && r.height() > 0) {
Common::Rect tempRect = r;
- tempRect.clip(Common::Rect(0, 0, this->w, this->h));
- 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);
@@@ -347,13 -281,13 +289,13 @@@ void Screen::print(const Common::Point
pos.y--; // Font is always drawing one line higher
if (!pos.x)
// Center text horizontally
- pos.x = (this->w - width) / 2;
- 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 > this->w)
- textBounds.moveTo(this->w - width, textBounds.top);
- if (textBounds.bottom > this->h)
- textBounds.moveTo(textBounds.left, this->h - _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);
@@@ -509,17 -414,11 +422,11 @@@ void Screen::resetDisplayBounds()
_backBuffer = &_backBuffer1;
}
- /**
- * Return the size of the current display window
- */
Common::Rect Screen::getDisplayBounds() {
- return (_backBuffer == &_sceneSurface) ? Common::Rect(0, 0, _sceneSurface.w, _sceneSurface.h) :
- Common::Rect(0, 0, this->w, this->h);
+ 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());
}
- /**
- * Synchronize the data for a savegame
- */
void Screen::synchronize(Common::Serializer &s) {
int fontNumb = _fontNumber;
s.syncAsByte(fontNumb);
diff --cc engines/sherlock/screen.h
index 8a8eca1,a2c0aa3..f4cd6fd
--- a/engines/sherlock/screen.h
+++ b/engines/sherlock/screen.h
@@@ -66,21 -66,25 +66,34 @@@ 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
+ */
void mergeDirtyRects();
+ /**
+ * Returns the union of two dirty area rectangles
+ */
bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
+ /**
+ * Draws the given string into the back buffer using the images stored in _font
+ */
void writeString(const Common::String &str, const Common::Point &pt, byte color);
protected:
+ /**
+ * Adds a rectangle to the list of modified areas of the screen during the
+ * current frame
+ */
virtual void addDirtyRect(const Common::Rect &r);
public:
Surface _backBuffer1, _backBuffer2;
@@@ -140,16 -228,10 +238,19 @@@ public
int fontNumber() const { return _fontNumber; }
+ /**
+ * 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 --cc engines/sherlock/sherlock.cpp
index 80a4383,d4644d4..5973823
--- a/engines/sherlock/sherlock.cpp
+++ b/engines/sherlock/sherlock.cpp
@@@ -67,10 -69,9 +68,7 @@@ SherlockEngine::~SherlockEngine()
delete _res;
}
- /**
- * Does basic initialization of the game engine
- */
void SherlockEngine::initialize() {
- initGraphics(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT, false);
-
DebugMan.addDebugChannel(kDebugScript, "scripts", "Script debug level");
ImageFile::setVm(this);
diff --cc engines/sherlock/sherlock.h
index 2688b51,24a7207..bf8c0d6
--- a/engines/sherlock/sherlock.h
+++ b/engines/sherlock/sherlock.h
@@@ -62,8 -58,8 +58,8 @@@ enum GameType
GType_RoseTattoo = 1
};
- #define SHERLOCK_SCREEN_WIDTH _vm->_screen->w
- #define SHERLOCK_SCREEN_HEIGHT _vm->_screen->h
-#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;
diff --cc engines/sherlock/sound.cpp
index 3a30864,4f27481..06f6a0f
--- a/engines/sherlock/sound.cpp
+++ b/engines/sherlock/sound.cpp
@@@ -44,12 -63,19 +63,20 @@@ Sound::Sound(SherlockEngine *vm, Audio:
_musicOn = true;
_speechOn = true;
+ _vm->_res->addToCache("MUSIC.LIB");
+ if (!_vm->_interactiveFl)
+ _vm->_res->addToCache("TITLE.SND");
+ else {
+ _vm->_res->addToCache("MUSIC.LIB");
+ _vm->_res->addToCache("SND.SND");
+
+ if (!_vm->isDemo()) {
+ _vm->_res->addToCache("TITLE.SND");
+ _vm->_res->addToCache("EPILOGUE.SND");
+ }
+ }
}
- /**
- * Saves sound-related settings
- */
void Sound::syncSoundSettings() {
_digitized = !ConfMan.getBool("mute");
_music = !ConfMan.getBool("mute") && !ConfMan.getBool("music_mute");
diff --cc engines/sherlock/talk.cpp
index c67b98b,319d1a3..1a926a5
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@@ -193,11 -172,9 +172,11 @@@ void Talk::talkTo(const Common::String
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(savedMode - 1);
++ ((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 --cc engines/sherlock/talk.h
index 5c87d79,d26259d..48290e9
--- a/engines/sherlock/talk.h
+++ b/engines/sherlock/talk.h
@@@ -120,14 -123,11 +123,11 @@@ struct TalkSequences
};
class SherlockEngine;
-class UserInterface;
+class ScalpelUserInterface;
class Talk {
- friend class UserInterface;
+ friend class ScalpelUserInterface;
private:
- Common::Array<TalkSequences> STILL_SEQUENCES;
- Common::Array<TalkSequences> TALK_SEQUENCES;
- private:
SherlockEngine *_vm;
Common::Stack<SequenceEntry> _savedSequences;
Common::Stack<SequenceEntry> _sequenceStack;
diff --cc engines/sherlock/user_interface.cpp
index efe6c8e,524ecf3..7a6722a
--- a/engines/sherlock/user_interface.cpp
+++ b/engines/sherlock/user_interface.cpp
@@@ -78,70 -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;
- _windowStyle = 1; // Sliding windows
++ _slideWindows = true;
+ _helpStyle = false;
++ _windowBounds = Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH - 1, SHERLOCK_SCREEN_HEIGHT - 1);
+ _lookScriptFlag = false;
+
- _key = _oldKey = 0;
++ _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;
- _keycode = Common::KEYCODE_INVALID;
- _keyPress = '\0';
- _helpStyle = false;
- _menuCounter = 0;
- _menuMode = STD_MODE;
_help = _oldHelp = 0;
- _oldLook = false;
- _lookHelp = 0;
+ _key = _oldKey = '\0';
+ _temp = _oldTemp = 0;
- _temp1 = 0;
- _invLookFlag = 0;
- _windowOpen = false;
- _oldLook = false;
++ _oldLook = 0;
_keyboardInput = false;
_pause = false;
_cNum = 0;
- _windowBounds = Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH - 1,
- SHERLOCK_SCREEN_HEIGHT - 1);
- _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;
}
- /**
- * Resets the user interface
- */
-void UserInterface::reset() {
+void ScalpelUserInterface::reset() {
_oldKey = -1;
_help = _oldHelp = -1;
_oldTemp = _temp = -1;
}
- /**
- * Draw the user interface onto the screen's back buffers
- */
-void UserInterface::drawInterface(int bufferNum) {
+void ScalpelUserInterface::drawInterface(int bufferNum) {
Screen &screen = *_vm->_screen;
if (bufferNum & 1)
@@@ -152,10 -139,7 +148,7 @@@
screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK);
}
- /**
- * Main input handler for the user interface
- */
-void UserInterface::handleInput() {
+void ScalpelUserInterface::handleInput() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
People &people = *_vm->_people;
@@@ -410,23 -392,16 +401,16 @@@
}
}
- /**
- * Draws the image for a user interface button in the down/pressed state.
- */
-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]);
- Graphics::Surface &s = (*_controls)[num]._frame;
- screen._backBuffer1.transBlitFrom(s, pt);
- screen.slamArea(pt.x, pt.y, pt.x + s.w, pt.y + s.h);
+ ImageFrame &frame = (*_controls)[num];
+ screen._backBuffer1.transBlitFrom(frame, pt);
+ screen.slamArea(pt.x, pt.y, pt.x + frame._width, pt.y + frame._height);
}
- /**
- * Draws the image for the given user interface button in the up
- * (not selected) position
- */
-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;
@@@ -441,11 -416,7 +425,7 @@@
}
}
- /**
- * If he mouse button is pressed, then calls depressButton to draw the button
- * as pressed; if not, it will show it as released with a call to "restoreButton".
- */
-void UserInterface::pushButton(int num) {
+void ScalpelUserInterface::pushButton(int num) {
Events &events = *_vm->_events;
_oldKey = -1;
@@@ -462,15 -433,10 +442,10 @@@
restoreButton(num);
}
- /**
- * By the time this method has been called, the graphics for the button change
- * have already been drawn. This simply takes care of switching the mode around
- * accordingly
- */
-void UserInterface::toggleButton(int num) {
+void ScalpelUserInterface::toggleButton(int num) {
Screen &screen = *_vm->_screen;
- if (_menuMode != (num + 1)) {
+ if (_menuMode != (MenuMode)(num + 1)) {
_menuMode = (MenuMode)(num + 1);
_oldKey = COMMANDS[num];
_oldTemp = num;
@@@ -495,10 -461,7 +470,7 @@@
}
}
- /**
- * Clears the info line of the screen
- */
-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);
@@@ -507,20 -470,14 +479,14 @@@
}
}
- /**
- * Clear any active text window
- */
-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);
}
}
- /**
- * Handles counting down whilst checking for input, then clears the info line.
- */
-void UserInterface::whileMenuCounter() {
+void ScalpelUserInterface::whileMenuCounter() {
if (!(--_menuCounter) || _vm->_events->checkInput()) {
_menuCounter = 0;
_infoFlag = true;
@@@ -528,11 -485,7 +494,7 @@@
}
}
- /**
- * Creates a text window and uses it to display the in-depth description
- * of the highlighted object
- */
-void UserInterface::examine() {
+void ScalpelUserInterface::examine() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
People &people = *_vm->_people;
@@@ -583,10 -536,7 +545,7 @@@
}
}
- /**
- * Print the name of an object in the scene
- */
-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;
@@@ -699,10 -649,7 +658,7 @@@
}
}
- /**
- * Gets the item in the inventory the mouse is on and display's it's description
- */
-void UserInterface::lookInv() {
+void ScalpelUserInterface::lookInv() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
Screen &screen = *_vm->_screen;
@@@ -727,10 -674,7 +683,7 @@@
}
}
- /**
- * Handles input when the file list window is being displayed
- */
-void UserInterface::doEnvControl() {
+void ScalpelUserInterface::doEnvControl() {
Events &events = *_vm->_events;
SaveManager &saves = *_vm->_saves;
Scene &scene = *_vm->_scene;
@@@ -1033,10 -976,7 +985,7 @@@
}
}
- /**
- * Handle input whilst the inventory is active
- */
-void UserInterface::doInvControl() {
+void ScalpelUserInterface::doInvControl() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
Scene &scene = *_vm->_scene;
@@@ -1261,10 -1199,7 +1208,7 @@@
}
}
- /**
- * Handles waiting whilst an object's description window is open.
- */
-void UserInterface::doLookControl() {
+void ScalpelUserInterface::doLookControl() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
Screen &screen = *_vm->_screen;
@@@ -1325,10 -1260,7 +1269,7 @@@
}
}
- /**
- * Handles input until one of the user interface buttons/commands is selected
- */
-void UserInterface::doMainControl() {
+void ScalpelUserInterface::doMainControl() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
SaveManager &saves = *_vm->_saves;
@@@ -1466,10 -1398,7 +1407,7 @@@
}
}
- /**
- * Handles the input for the MOVE, OPEN, and CLOSE commands
- */
-void UserInterface::doMiscControl(int allowed) {
+void ScalpelUserInterface::doMiscControl(int allowed) {
Events &events = *_vm->_events;
Scene &scene = *_vm->_scene;
Talk &talk = *_vm->_talk;
@@@ -1518,10 -1447,7 +1456,7 @@@
}
}
- /**
- * Handles input for picking up items
- */
-void UserInterface::doPickControl() {
+void ScalpelUserInterface::doPickControl() {
Events &events = *_vm->_events;
Scene &scene = *_vm->_scene;
Talk &talk = *_vm->_talk;
@@@ -1544,11 -1470,7 +1479,7 @@@
}
}
- /**
- * Handles input when in talk mode. It highlights the buttons and available statements,
- * and handles allowing the user to click on them
- */
-void UserInterface::doTalkControl() {
+void ScalpelUserInterface::doTalkControl() {
Events &events = *_vm->_events;
Journal &journal = *_vm->_journal;
People &people = *_vm->_people;
@@@ -1798,13 -1720,7 +1729,7 @@@
}
}
- /**
- * Handles events when the Journal is active.
- * @remarks Whilst this would in theory be better in the Journal class, since it displays in
- * the user interface, it uses so many internal UI fields, that it sort of made some sense
- * to put it in the UserInterface class.
- */
-void UserInterface::journalControl() {
+void ScalpelUserInterface::journalControl() {
Events &events = *_vm->_events;
Journal &journal = *_vm->_journal;
Scene &scene = *_vm->_scene;
@@@ -1852,10 -1768,7 +1777,7 @@@
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
}
- /**
- * Print the description of an object
- */
-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;
@@@ -2023,17 -1936,11 +1945,11 @@@
}
}
- /**
- * Print the previously selected object's decription
- */
-void UserInterface::printObjectDesc() {
+void ScalpelUserInterface::printObjectDesc() {
printObjectDesc(_cAnimStr, true);
}
- /**
- * Displays a passed window by gradually scrolling it vertically on-screen
- */
-void UserInterface::summonWindow(const Surface &bgSurface, bool slideUp) {
+void ScalpelUserInterface::summonWindow(const Surface &bgSurface, bool slideUp) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
@@@ -2073,10 -1979,7 +1988,7 @@@
_windowOpen = true;
}
- /**
- * Slide the window stored in the back buffer onto the screen
- */
-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
@@@ -2093,11 -1996,7 +2005,7 @@@
summonWindow(tempSurface, slideUp);
}
- /**
- * Close a currently open window
- * @param flag 0 = slide old window down, 1 = slide prior UI back up
- */
-void UserInterface::banishWindow(bool slideUp) {
+void ScalpelUserInterface::banishWindow(bool slideUp) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
@@@ -2163,11 -2062,8 +2071,8 @@@
_menuMode = STD_MODE;
}
- /**
- * Checks to see whether a USE action is valid on the given object
- */
-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, int giveMode) {
+ const char *const messages[], int objNum, bool giveMode) {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
Scene &scene = *_vm->_scene;
@@@ -2259,10 -2155,7 +2164,7 @@@
events.setCursor(ARROW);
}
- /**
- * Called for OPEN, CLOSE, and MOVE actions are being done
- */
-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;
@@@ -2394,39 -2287,4 +2296,14 @@@
events.setCursor(ARROW);
}
- /**
- * Support method for updating the screen
- */
- void ScalpelUserInterface::doInvJF() {
- Inventory &inv = *_vm->_inventory;
- Screen &screen = *_vm->_screen;
- Talk &talk = *_vm->_talk;
-
- _invLookFlag = true;
- inv.freeInv();
-
- _infoFlag = true;
- clearInfo();
-
- screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(0, CONTROLS_Y),
- Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
- examine();
-
- if (!talk._talkToAbort) {
- screen._backBuffer2.blitFrom((*_controlPanel)[0]._frame,
- Common::Point(0, CONTROLS_Y));
- inv.loadInv();
- }
- }
-
+/*----------------------------------------------------------------*/
+
+TattooUserInterface::TattooUserInterface(SherlockEngine *vm): UserInterface(vm) {
+ //
+}
+
+void TattooUserInterface::handleInput() {
+ // TODO
+}
+
} // End of namespace Sherlock
diff --cc engines/sherlock/user_interface.h
index acbb0c0,1f7b5fe..8a0f4f5
--- a/engines/sherlock/user_interface.h
+++ b/engines/sherlock/user_interface.h
@@@ -61,59 -61,23 +61,94 @@@ extern const char *const PRESS_KEY_TO_C
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;
- int _windowStyle;
++ 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
- int _key, _oldKey;
++ 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() {}
+
- virtual void doInvJF() {}
++ /**
++ * 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;
- int _keycode;
+ char _keyPress;
+ int _lookHelp;
++ int _bgFound, _oldBgFound;
int _help, _oldHelp;
+ char _key, _oldKey;
+ int _temp, _oldTemp;
int _oldLook;
bool _keyboardInput;
bool _pause;
@@@ -123,62 -90,169 +158,169 @@@
int _find;
int _oldUse;
private:
+ /**
+ * Draws the image for a user interface button in the down/pressed state.
+ */
void depressButton(int num);
+ /**
+ * If he mouse button is pressed, then calls depressButton to draw the button
+ * as pressed; if not, it will show it as released with a call to "restoreButton".
+ */
void pushButton(int num);
+ /**
+ * By the time this method has been called, the graphics for the button change
+ * have already been drawn. This simply takes care of switching the mode around
+ * accordingly
+ */
void toggleButton(int num);
+ /**
+ * Creates a text window and uses it to display the in-depth description
+ * of the highlighted object
+ */
void examine();
+ /**
+ * Print the name of an object in the scene
+ */
void lookScreen(const Common::Point &pt);
+ /**
+ * Gets the item in the inventory the mouse is on and display's it's description
+ */
void lookInv();
+ /**
+ * Handles input when the file list window is being displayed
+ */
void doEnvControl();
+
+ /**
+ * Handle input whilst the inventory is active
+ */
void doInvControl();
+
+ /**
+ * Handles waiting whilst an object's description window is open.
+ */
void doLookControl();
+
+ /**
+ * Handles input until one of the user interface buttons/commands is selected
+ */
void doMainControl();
+
+ /**
+ * Handles the input for the MOVE, OPEN, and CLOSE commands
+ */
void doMiscControl(int allowed);
+
+ /**
+ * Handles input for picking up items
+ */
void doPickControl();
+
+ /**
+ * Handles input when in talk mode. It highlights the buttons and available statements,
+ * and handles allowing the user to click on them
+ */
void doTalkControl();
+
+ /**
+ * Handles events when the Journal is active.
+ * @remarks Whilst this would in theory be better in the Journal class, since it displays in
+ * the user interface, it uses so many internal UI fields, that it sort of made some sense
+ * to put it in the UserInterface class.
+ */
void journalControl();
+ /**
+ * Checks to see whether a USE action is valid on the given object
+ */
void checkUseAction(const UseType *use, const Common::String &invName, const char *const messages[],
- int objNum, int giveMode);
+ int objNum, bool giveMode);
+
+ /**
+ * 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);
- virtual void doInvJF();
-
+ /**
- * 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
Commit: c8cfca749a5da09aead4ca0c499def9afab5317c
https://github.com/scummvm/scummvm/commit/c8cfca749a5da09aead4ca0c499def9afab5317c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-23T10:39:47-04:00
Commit Message:
SHERLOCK: Fix Rose Tattoo scene loading problems from merge
Changed paths:
engines/sherlock/resources.cpp
engines/sherlock/scalpel/scalpel.cpp
engines/sherlock/scene.cpp
engines/sherlock/sound.cpp
engines/sherlock/tattoo/tattoo.cpp
diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp
index 864622e..4e10ba9 100644
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@ -91,9 +91,12 @@ Resources::Resources(SherlockEngine *vm) : _vm(vm), _cache(vm) {
if (_vm->_interactiveFl) {
addToCache("vgs.lib");
addToCache("talk.lib");
- addToCache("sequence.txt");
addToCache("journal.txt");
- addToCache("portrait.lib");
+
+ if (IS_SERRATED_SCALPEL) {
+ addToCache("sequence.txt");
+ addToCache("portrait.lib");
+ }
}
}
@@ -310,7 +313,7 @@ void Resources::decompressLZ(Common::SeekableReadStream &source, byte *outBuffer
lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
}
}
- } while ((outSize == -1 || outBuffer < outBufferEnd) || (inSize == -1 || source.pos() < endPos));
+ } while ((outSize == -1 || outBuffer < outBufferEnd) && (inSize == -1 || source.pos() < endPos));
}
/*----------------------------------------------------------------*/
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index ccc9c8a..7209c34 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -390,13 +390,6 @@ 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]);
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 2c80bfb..933e60d 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -311,27 +311,32 @@ bool Scene::loadScene(const Common::String &filename) {
bgInfo[idx].load(*rrmStream);
// Read information
- if (IS_SERRATED_SCALPEL) {
- Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream :
- res.decompress(*rrmStream, bgHeader._numStructs * 569 + bgHeader._descSize + bgHeader._seqSize);
+ if (IS_ROSE_TATTOO) {
+ // Load shapes
+ Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream : res.decompress(*rrmStream, bgHeader._numStructs * 625);
_bgShapes.resize(bgHeader._numStructs);
for (int idx = 0; idx < bgHeader._numStructs; ++idx)
- _bgShapes[idx].load(*infoStream, false);
+ _bgShapes[idx].load(*infoStream, _vm->getGameID() == GType_RoseTattoo);
- if (bgHeader._descSize) {
- _descText.resize(bgHeader._descSize);
- infoStream->read(&_descText[0], bgHeader._descSize);
- }
+ if (_lzwMode)
+ delete infoStream;
- if (bgHeader._seqSize) {
- _sequenceBuffer.resize(bgHeader._seqSize);
- infoStream->read(&_sequenceBuffer[0], bgHeader._seqSize);
- }
+ // Load description text
+ _descText.resize(bgHeader._descSize);
+ if (_lzwMode)
+ res.decompress(*rrmStream, (byte *)&_descText[0], bgHeader._descSize);
+ else
+ rrmStream->read(&_descText[0], bgHeader._descSize);
+ // Load sequences
+ _sequenceBuffer.resize(bgHeader._seqSize);
if (_lzwMode)
- delete infoStream;
+ res.decompress(*rrmStream, &_sequenceBuffer[0], bgHeader._seqSize);
+ else
+ rrmStream->read(&_sequenceBuffer[0], bgHeader._seqSize);
} else if (!_lzwMode) {
+ // Serrated Scalpel uncompressed info
_bgShapes.resize(bgHeader._numStructs);
for (int idx = 0; idx < bgHeader._numStructs; ++idx)
_bgShapes[idx].load(*rrmStream, false);
@@ -346,6 +351,7 @@ bool Scene::loadScene(const Common::String &filename) {
rrmStream->read(&_sequenceBuffer[0], bgHeader._seqSize);
}
} else {
+ // Serrated Scalpel compressed info
Common::SeekableReadStream *infoStream;
// Read shapes
diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp
index 06f6a0f..b8fe61d 100644
--- a/engines/sherlock/sound.cpp
+++ b/engines/sherlock/sound.cpp
@@ -68,11 +68,16 @@ Sound::Sound(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
_vm->_res->addToCache("TITLE.SND");
else {
_vm->_res->addToCache("MUSIC.LIB");
- _vm->_res->addToCache("SND.SND");
+
+ if (IS_ROSE_TATTOO) {
+ _vm->_res->addToCache("SOUND.LIB");
+ } else {
+ _vm->_res->addToCache("SND.SND");
- if (!_vm->isDemo()) {
- _vm->_res->addToCache("TITLE.SND");
- _vm->_res->addToCache("EPILOGUE.SND");
+ if (!_vm->isDemo()) {
+ _vm->_res->addToCache("TITLE.SND");
+ _vm->_res->addToCache("EPILOGUE.SND");
+ }
}
}
}
diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp
index 3c684ff..9039e3f 100644
--- a/engines/sherlock/tattoo/tattoo.cpp
+++ b/engines/sherlock/tattoo/tattoo.cpp
@@ -44,7 +44,6 @@ void TattooEngine::initialize() {
// Add some more files to the cache
_res->addToCache("walk.lib");
- _res->addToCache("sound.lib");
// Starting scene
_scene->_goToScene = 91;
Commit: bcc31b2a663545ec448d886d8ed16546593f849e
https://github.com/scummvm/scummvm/commit/bcc31b2a663545ec448d886d8ed16546593f849e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-23T16:06:29-04:00
Commit Message:
SHERLOCK: Implemented Tattoo loadWalk changes
Changed paths:
engines/sherlock/map.cpp
engines/sherlock/map.h
engines/sherlock/objects.cpp
engines/sherlock/objects.h
engines/sherlock/people.cpp
engines/sherlock/people.h
engines/sherlock/scalpel/scalpel.cpp
engines/sherlock/scene.cpp
diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp
index 44ca7cd..4f034d8 100644
--- a/engines/sherlock/map.cpp
+++ b/engines/sherlock/map.cpp
@@ -65,8 +65,12 @@ Map::Map(SherlockEngine *vm): _vm(vm), _topLine(g_system->getWidth(), 12) {
_oldCharPoint = 0;
_frameChangeFlag = false;
- for (int idx = 0; idx < MAX_HOLMES_SEQUENCE; ++idx)
- Common::fill(&_sequences[idx][0], &_sequences[idx][MAX_FRAME], 0);
+ // Initialise the initial walk sequence set
+ _walkSequences.resize(MAX_HOLMES_SEQUENCE);
+ for (int idx = 0; idx < MAX_HOLMES_SEQUENCE; ++idx) {
+ _walkSequences[idx]._sequences.resize(MAX_FRAME);
+ Common::fill(&_walkSequences[idx]._sequences[0], &_walkSequences[idx]._sequences[0] + MAX_FRAME, 0);
+ }
if (!_vm->isDemo())
loadData();
@@ -80,7 +84,7 @@ void Map::loadPoints(int count, const int *xList, const int *yList, const int *t
void Map::loadSequences(int count, const byte *seq) {
for (int idx = 0; idx < count; ++idx, seq += MAX_FRAME)
- Common::copy(seq, seq + MAX_FRAME, &_sequences[idx][0]);
+ Common::copy(seq, seq + MAX_FRAME, &_walkSequences[idx]._sequences[0]);
}
void Map::loadData() {
@@ -289,7 +293,7 @@ void Map::setupSprites() {
p._type = CHARACTER;
p._position = Common::Point(12400, 5000);
p._sequenceNumber = 0;
- p._sequences = &_sequences;
+ p._walkSequences = _walkSequences;
p._images = _shapes;
p._imageFrame = nullptr;
p._frameNumber = 0;
diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h
index ab70b08..198b31e 100644
--- a/engines/sherlock/map.h
+++ b/engines/sherlock/map.h
@@ -76,7 +76,7 @@ private:
ImageFile *_mapCursors;
ImageFile *_shapes;
ImageFile *_iconShapes;
- byte _sequences[MAX_HOLMES_SEQUENCE][MAX_FRAME];
+ Common::Array<WalkSequence> _walkSequences;
Point32 _lDrawnPos;
int _point;
bool _placesShown;
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index f380351..0709f6b 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -46,7 +46,7 @@ void Sprite::clear() {
_description = "";
_examine.clear();
_pickUp = "";
- _sequences = nullptr;
+ _walkSequences.clear();
_images = nullptr;
_imageFrame = nullptr;
_walkCount = 0;
@@ -63,12 +63,21 @@ void Sprite::clear() {
_status = 0;
_misc = 0;
_numFrames = 0;
+ _altImages = nullptr;
+ _altSequences = false;
+ Common::fill(&_stopFrames[0], &_stopFrames[8], (ImageFrame *)nullptr);
}
void Sprite::setImageFrame() {
- int imageNumber = (*_sequences)[_sequenceNumber][_frameNumber] +
- (*_sequences)[_sequenceNumber][0] - 2;
- _imageFrame = &(*_images)[imageNumber];
+ int frameNum = MAX(_frameNumber, 0);
+ int imageNumber = _walkSequences[_sequenceNumber][frameNum];
+
+ if (IS_SERRATED_SCALPEL)
+ imageNumber = imageNumber + +_walkSequences[_sequenceNumber][0] - 2;
+ else if (imageNumber > _numFrames)
+ imageNumber = 1;
+
+ _imageFrame = &(_altSequences ? *_altImages : *_images)[imageNumber];
}
void Sprite::adjustSprite() {
@@ -120,7 +129,7 @@ void Sprite::adjustSprite() {
if (!map._active || (map._frameChangeFlag = !map._frameChangeFlag))
++_frameNumber;
- if ((*_sequences)[_sequenceNumber][_frameNumber] == 0) {
+ if (_walkSequences[_sequenceNumber][_frameNumber] == 0) {
switch (_sequenceNumber) {
case STOP_UP:
case STOP_DOWN:
diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h
index b61e7e2..761c03d 100644
--- a/engines/sherlock/objects.h
+++ b/engines/sherlock/objects.h
@@ -46,7 +46,10 @@ enum SpriteType {
REMOVE = 5, // Object should be removed next frame
NO_SHAPE = 6, // Background object with no shape
HIDDEN = 7, // Hidden backgruond object
- HIDE_SHAPE = 8 // Object needs to be hidden
+ HIDE_SHAPE = 8, // Object needs to be hidden
+
+ // Rose Tattoo
+ HIDDEN_CHARACTER = 128
};
enum AType {
@@ -98,16 +101,31 @@ public:
void operator-=(const Point32 &delta) { x -= delta.x; y -= delta.y; }
};
+
+struct WalkSequence {
+ Common::String _vgsName;
+ bool _horizFlip;
+ Common::Array<byte> _sequences;
+
+ WalkSequence() : _vgsName(nullptr), _horizFlip(false) {}
+ const byte &operator[](int idx) { return _sequences[idx]; }
+
+ /**
+ * Load data for the sequence from a stream
+ */
+ void load(Common::SeekableReadStream &s);
+};
+
class Sprite {
private:
static SherlockEngine *_vm;
public:
Common::String _name;
Common::String _description;
- Common::StringArray _examine; // Examine in-depth description
+ Common::String _examine; // Examine in-depth description
Common::String _pickUp; // Message for if you can't pick up object
- const uint8 (*_sequences)[MAX_HOLMES_SEQUENCE][MAX_FRAME]; // Holds animation sequences
+ Common::Array<WalkSequence> _walkSequences; // Holds animation sequences
ImageFile *_images; // Sprite images
ImageFrame *_imageFrame; // Pointer to shape in the images
int _walkCount; // Character walk counter
@@ -124,8 +142,12 @@ public:
int _status; // Status: open/closed, moved/not moved
int8 _misc; // Miscellaneous use
int _numFrames; // How many frames the object has
+ ImageFile *_altImages;
+ bool _altSequences;
+ ImageFrame *_stopFrames[8]; // Stop/rest frame for each direction
public:
Sprite() { clear(); }
+
static void setVm(SherlockEngine *vm) { _vm = vm; }
/**
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp
index 3a630fd..638cbf6 100644
--- a/engines/sherlock/people.cpp
+++ b/engines/sherlock/people.cpp
@@ -50,10 +50,37 @@ static const uint8 CHARACTER_SEQUENCES[MAX_HOLMES_SEQUENCE][MAX_FRAME] = {
{ 52, 1, 2, 3, 4, 0 } // Goto Stand Down Left
};
+// Rose Tattoo walk image libraries
+// Walk resources within WALK.LIB
+#define NUM_IN_WALK_LIB 10
+const char *const WALK_LIB_NAMES[10] = {
+ "SVGAWALK.VGS",
+ "COATWALK.VGS",
+ "WATSON.VGS",
+ "NOHAT.VGS",
+ "TUPRIGHT.VGS",
+ "TRIGHT.VGS",
+ "TDOWNRG.VGS",
+ "TWUPRIGH.VGS",
+ "TWRIGHT.VGS",
+ "TWDOWNRG.VGS"
+};
+
+/*----------------------------------------------------------------*/
+
+void WalkSequence::load(Common::SeekableReadStream &s) {
+ char buffer[9];
+ s.read(buffer, 9);
+ _vgsName = Common::String(buffer);
+ _horizFlip = s.readByte() != 0;
+
+ _sequences.resize(s.readUint16LE());
+ s.read(&_sequences[0], _sequences.size());
+}
+
/*----------------------------------------------------------------*/
People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) {
- _walkLoaded = false;
_holmesOn = true;
_oldWalkSequence = -1;
_allowWalkAbort = false;
@@ -68,13 +95,18 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) {
_holmesQuotient = 0;
_hSavedPos = Common::Point(-1, -1);
_hSavedFacing = -1;
+ _forceWalkReload = false;
+ _useWalkLib = false;
_portrait._sequences = new byte[32];
}
People::~People() {
- if (_walkLoaded)
- delete _data[PLAYER]._images;
+ for (int idx = 0; idx < MAX_PLAYERS; ++idx) {
+ if (_data[idx]._walkLoaded)
+ delete _data[PLAYER]._images;
+ }
+
delete _talkPics;
delete[] _portrait._sequences;
}
@@ -88,7 +120,6 @@ void People::reset() {
p._type = CHARACTER;
p._position = Common::Point(10000, 11000);
p._sequenceNumber = STOP_DOWNRIGHT;
- p._sequences = &CHARACTER_SEQUENCES;
p._imageFrame = nullptr;
p._frameNumber = 1;
p._delta = Common::Point(0, 0);
@@ -102,32 +133,106 @@ void People::reset() {
p._goto = Common::Point(0, 0);
p._status = 0;
+ // Load the default walk sequences
+ p._walkSequences.resize(MAX_HOLMES_SEQUENCE);
+ for (int idx = 0; idx < MAX_HOLMES_SEQUENCE; ++idx) {
+ p._walkSequences[idx]._sequences.clear();
+
+ const byte *pSrc = &CHARACTER_SEQUENCES[idx][0];
+ do {
+ p._walkSequences[idx]._sequences.push_back(*pSrc);
+ } while (*pSrc++);
+ }
+
// Reset any walk path in progress when Sherlock leaves scenes
_walkTo.clear();
}
bool People::loadWalk() {
- if (_walkLoaded) {
- return false;
+ Resources &res = *_vm->_res;
+ bool result = false;
+
+ if (IS_SERRATED_SCALPEL) {
+ if (_data[PLAYER]._walkLoaded) {
+ return false;
+ } else {
+ _data[PLAYER]._images = new ImageFile("walk.vgs");
+ _data[PLAYER].setImageFrame();
+ _data[PLAYER]._walkLoaded = true;
+
+ result = true;
+ }
} else {
- _data[PLAYER]._images = new ImageFile("walk.vgs");
- _data[PLAYER].setImageFrame();
- _walkLoaded = true;
+ for (int idx = 0; idx < MAX_PLAYERS; ++idx) {
+ if (!_data[idx]._walkLoaded && (_data[idx]._type == CHARACTER || _data[idx]._type == HIDDEN_CHARACTER)) {
+ if (_data[idx]._type == HIDDEN_CHARACTER)
+ _data[idx]._type = INVALID;
+
+ // See if this is one of the more used Walk Graphics stored in WALK.LIB
+ for (int libNum = 0; libNum < NUM_IN_WALK_LIB; ++libNum) {
+ if (!_data[0]._walkVGSName.compareToIgnoreCase(WALK_LIB_NAMES[libNum])) {
+ _useWalkLib = true;
+ break;
+ }
+ }
+
+ // Load the images for the character
+ _data[idx]._images = new ImageFile(_data[idx]._walkVGSName, false);
+ _data[idx]._numFrames = _data[idx]._images->size();
+
+ // Load walk sequence data
+ Common::String fname = Common::String(_data[idx]._walkVGSName.c_str(), strchr(_data[idx]._walkVGSName.c_str(), '.'));
+ fname += ".SEQ";
+
+ // Load the walk sequence data
+ Common::SeekableReadStream *stream = res.load(fname, _useWalkLib ? "walk.lib" : "vgs.lib");
+
+ _data[idx]._walkSequences.resize(stream->readByte());
+
+ for (uint seqNum = 0; seqNum < _data[idx]._walkSequences.size(); ++seqNum)
+ _data[idx]._walkSequences[seqNum].load(*stream);
+
+ // Close the sequences resource
+ delete stream;
+ _useWalkLib = false;
+
+ _data[idx]._frameNumber = 0;
+ _data[idx].setImageFrame();
+
+ // Set the stop Frames pointers
+ for (int dirNum = 0; dirNum < 8; ++dirNum) {
+ int count = 0;
+ while (_data[idx]._walkSequences[dirNum + 8][count] != 0)
+ ++count;
+ count += 2;
+ count = _data[idx]._walkSequences[dirNum + 8][count] - 1;
+ _data[idx]._stopFrames[dirNum] = &(*_data[idx]._images)[count];
+ }
- return true;
+ result = true;
+ _data[idx]._walkLoaded = true;
+ } else if (_data[idx]._type != CHARACTER) {
+ _data[idx]._walkLoaded = false;
+ }
+ }
}
+
+ _forceWalkReload = false;
+ return result;
}
bool People::freeWalk() {
- if (_walkLoaded) {
- delete _player._images;
- _player._images = nullptr;
+ bool result = false;
- _walkLoaded = false;
- return true;
- } else {
- return false;
+ for (int idx = 0; idx < MAX_PLAYERS; ++idx) {
+ if (_data[idx]._walkLoaded) {
+ delete _data[idx]._images;
+ _data[idx]._images = nullptr;
+ result = true;
+ }
}
+
+ return result;
}
void People::setWalking() {
@@ -553,9 +658,24 @@ void People::setTalking(int speaker) {
void People::synchronize(Common::Serializer &s) {
s.syncAsByte(_holmesOn);
- s.syncAsSint16LE(_player._position.x);
- s.syncAsSint16LE(_player._position.y);
- s.syncAsSint16LE(_player._sequenceNumber);
+
+ if (IS_SERRATED_SCALPEL) {
+ s.syncAsSint16LE(_player._position.x);
+ s.syncAsSint16LE(_player._position.y);
+ s.syncAsSint16LE(_player._sequenceNumber);
+ } else {
+ for (int idx = 0; idx < MAX_PLAYERS; ++idx) {
+ Person &p = _data[idx];
+ s.syncAsSint16LE(p._position.x);
+ s.syncAsSint16LE(p._position.y);
+ s.syncAsSint16LE(p._sequenceNumber);
+ s.syncAsSint16LE(p._type);
+ s.syncString(p._walkVGSName);
+ s.syncString(p._description);
+ s.syncString(p._examine);
+ }
+ }
+
s.syncAsSint16LE(_holmesQuotient);
if (s.isLoading()) {
diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h
index 8244fd9..f3e7950 100644
--- a/engines/sherlock/people.h
+++ b/engines/sherlock/people.h
@@ -30,13 +30,11 @@
namespace Sherlock {
-// Player definitions. The game has theoretical support for two player characters but only the first one is used.
-// Watson is, instead, handled by a different sprite in each scene, with a very simple initial movement, if any
enum PeopleId {
PLAYER = 0,
AL = 0,
PEG = 1,
- MAX_PLAYERS = 2
+ MAX_PLAYERS = 6
};
// Animation sequence identifiers for characters
@@ -63,20 +61,24 @@ struct PersonData {
_name(name), _portrait(portrait), _stillSequences(stillSequences), _talkSequences(talkSequences) {}
};
-class SherlockEngine;
-
class Person : public Sprite {
public:
- Person() : Sprite() {}
-
+ bool _walkLoaded;
Common::String _portrait;
+
+ // Rose Tattoo fields
+ Common::String _walkVGSName; // Name of walk library person is using
+ Common::Array<WalkSequence> _walkSequences;
+public:
+ Person() : Sprite(), _walkLoaded(false) {}
};
+class SherlockEngine;
+
class People {
private:
SherlockEngine *_vm;
Person _data[MAX_PLAYERS];
- bool _walkLoaded;
int _oldWalkSequence;
int _srcZone, _destZone;
public:
@@ -97,6 +99,8 @@ public:
bool _speakerFlip;
bool _holmesFlip;
int _holmesQuotient;
+ bool _forceWalkReload;
+ bool _useWalkLib;
public:
People(SherlockEngine *vm);
~People();
@@ -113,7 +117,7 @@ public:
/**
* Returns true if Sherlock is visible on the screen and enabled
*/
- bool isHolmesActive() const { return _walkLoaded && _holmesOn; }
+ bool isHolmesActive() const { return _data[0]._walkLoaded && _holmesOn; }
/**
* Reset the player data
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index 7209c34..2a107b4 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -837,9 +837,11 @@ void ScalpelEngine::eraseMirror12() {
void ScalpelEngine::doMirror12() {
People &people = *_people;
+ Person &player = people._player;
+
Common::Point pt((*_people)[AL]._position.x / 100, (*_people)[AL]._position.y / 100);
- int frameNum = (*people[AL]._sequences)[people[AL]._sequenceNumber][people[AL]._frameNumber] +
- (*people[AL]._sequences)[people[AL]._sequenceNumber][0] - 2;
+ int frameNum = player._walkSequences[player._sequenceNumber][player._frameNumber] +
+ player._walkSequences[player._sequenceNumber][0] - 2;
switch ((*_people)[AL]._sequenceNumber) {
case WALK_DOWN:
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 933e60d..4672e3e 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -536,7 +536,7 @@ bool Scene::loadScene(const Common::String &filename) {
delete rrmStream;
}
- // Clear user interface area and draw controls
+ // Handle drawing any on-screen interface
ui.drawInterface();
checkSceneStatus();
@@ -568,7 +568,7 @@ bool Scene::loadScene(const Common::String &filename) {
checkInventory();
// Handle starting any music for the scene
- if (sound._musicOn && sound.loadSong(_currentScene)) {
+ if (IS_SERRATED_SCALPEL && sound._musicOn && sound.loadSong(_currentScene)) {
if (sound._music)
sound.startSong();
}
Commit: 1e291b0b25719f61f7173d9f8ae7e0da5164b526
https://github.com/scummvm/scummvm/commit/1e291b0b25719f61f7173d9f8ae7e0da5164b526
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-24T07:46:25-04:00
Commit Message:
SHERLOCK: Implemented initial RT palette loading
Changed paths:
engines/sherlock/scene.cpp
engines/sherlock/screen.cpp
engines/sherlock/screen.h
engines/sherlock/tattoo/tattoo.cpp
engines/sherlock/tattoo/tattoo.h
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 4672e3e..e625dae 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -514,9 +514,7 @@ bool Scene::loadScene(const Common::String &filename) {
} 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]);
-
+ screen.translatePalette(screen._cMap);
Common::copy(screen._cMap, screen._cMap + PALETTE_SIZE, screen._sMap);
// Read in the background
diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp
index 24f7660..bb9dbd7 100644
--- a/engines/sherlock/screen.cpp
+++ b/engines/sherlock/screen.cpp
@@ -39,7 +39,7 @@ Screen::Screen(SherlockEngine *vm) : Surface(g_system->getWidth(), g_system->get
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);
+ setFont(IS_SERRATED_SCALPEL ? 1 : 4);
// Rose Tattoo specific fields
_fadeBytesRead = _fadeBytesToRead = 0;
@@ -466,4 +466,9 @@ void Screen::initScrollVars() {
_targetScroll = 0;
}
+void Screen::translatePalette(byte palette[PALETTE_SIZE]) {
+ for (int idx = 0; idx < PALETTE_SIZE; ++idx)
+ palette[idx] = VGA_COLOR_TRANS(palette[idx]);
+}
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h
index f4cd6fd..58c7d8f 100644
--- a/engines/sherlock/screen.h
+++ b/engines/sherlock/screen.h
@@ -251,6 +251,12 @@ public:
void setupBGArea(const byte cMap[PALETTE_SIZE]);
void initScrollVars();
+
+ /**
+ * Translate a palette from 6-bit RGB values to full 8-bit values suitable for passing
+ * to the underlying palette manager
+ */
+ static void translatePalette(byte palette[PALETTE_SIZE]);
};
} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp
index 9039e3f..47a7c2a 100644
--- a/engines/sherlock/tattoo/tattoo.cpp
+++ b/engines/sherlock/tattoo/tattoo.cpp
@@ -47,6 +47,9 @@ void TattooEngine::initialize() {
// Starting scene
_scene->_goToScene = 91;
+
+ // Load an initial palette
+ loadInitialPalette();
}
/**
@@ -56,6 +59,15 @@ void TattooEngine::startScene() {
// TODO
}
+void TattooEngine::loadInitialPalette() {
+ byte palette[768];
+ Common::SeekableReadStream *stream = _res->load("room.pal");
+ stream->read(palette, PALETTE_SIZE);
+ _screen->translatePalette(palette);
+ _screen->setPalette(palette);
+
+ delete stream;
+}
} // End of namespace Tattoo
diff --git a/engines/sherlock/tattoo/tattoo.h b/engines/sherlock/tattoo/tattoo.h
index 7bdeec5..b9224e0 100644
--- a/engines/sherlock/tattoo/tattoo.h
+++ b/engines/sherlock/tattoo/tattoo.h
@@ -30,6 +30,11 @@ namespace Sherlock {
namespace Tattoo {
class TattooEngine : public SherlockEngine {
+private:
+ /**
+ * Loads the initial palette for the game
+ */
+ void loadInitialPalette();
protected:
virtual void initialize();
Commit: 1ede08405595cafe5792aa514a4bc3309602e40f
https://github.com/scummvm/scummvm/commit/1ede08405595cafe5792aa514a4bc3309602e40f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-24T10:56:22-04:00
Commit Message:
SHERLOCK: Implement more scene loading and setNPCPath
Changed paths:
engines/sherlock/objects.h
engines/sherlock/people.cpp
engines/sherlock/people.h
engines/sherlock/scene.cpp
engines/sherlock/scene.h
engines/sherlock/sound.cpp
engines/sherlock/sound.h
diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h
index 761c03d..f104762 100644
--- a/engines/sherlock/objects.h
+++ b/engines/sherlock/objects.h
@@ -107,7 +107,7 @@ struct WalkSequence {
bool _horizFlip;
Common::Array<byte> _sequences;
- WalkSequence() : _vgsName(nullptr), _horizFlip(false) {}
+ WalkSequence() : _horizFlip(false) {}
const byte &operator[](int idx) { return _sequences[idx]; }
/**
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp
index 638cbf6..7879f29 100644
--- a/engines/sherlock/people.cpp
+++ b/engines/sherlock/people.cpp
@@ -80,6 +80,18 @@ void WalkSequence::load(Common::SeekableReadStream &s) {
/*----------------------------------------------------------------*/
+Person::Person() : Sprite(), _walkLoaded(false), _npcIndex(0), _npcStack(0), _npcPause(false) {
+ Common::fill(&_npcPath[0], &_npcPath[MAX_NPC_PATH], 0);
+}
+
+void Person::clearNPC() {
+ Common::fill(&_npcPath[0], &_npcPath[MAX_NPC_PATH], 0);
+ _npcIndex = _npcStack = 0;
+ _npcName = "";
+}
+
+/*----------------------------------------------------------------*/
+
People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) {
_holmesOn = true;
_oldWalkSequence = -1;
diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h
index f3e7950..a196878 100644
--- a/engines/sherlock/people.h
+++ b/engines/sherlock/people.h
@@ -34,7 +34,9 @@ enum PeopleId {
PLAYER = 0,
AL = 0,
PEG = 1,
- MAX_PLAYERS = 6
+ MAX_PLAYERS = 6,
+ MAX_NPC = 5,
+ MAX_NPC_PATH = 200
};
// Animation sequence identifiers for characters
@@ -66,11 +68,23 @@ public:
bool _walkLoaded;
Common::String _portrait;
+ // NPC related fields
+ int _npcIndex;
+ int _npcStack;
+ bool _npcPause;
+ byte _npcPath[MAX_NPC_PATH];
+ Common::String _npcName;
+
// Rose Tattoo fields
Common::String _walkVGSName; // Name of walk library person is using
Common::Array<WalkSequence> _walkSequences;
public:
- Person() : Sprite(), _walkLoaded(false) {}
+ Person();
+
+ /**
+ * Clear the NPC related data
+ */
+ void clearNPC();
};
class SherlockEngine;
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index e625dae..0f679d7 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -249,6 +249,7 @@ bool Scene::loadScene(const Common::String &filename) {
SaveManager &saves = *_vm->_saves;
Screen &screen = *_vm->_screen;
Sound &sound = *_vm->_sound;
+ Talk &talk = *_vm->_talk;
UserInterface &ui = *_vm->_ui;
bool flag;
@@ -264,6 +265,36 @@ bool Scene::loadScene(const Common::String &filename) {
_cAnim.clear();
_sequenceBuffer.clear();
+ // Check if it's a scene we need to keep trakc track of how many times we've visited
+ for (int idx = (int)_sceneTripCounters.size() - 1; idx >= 0; --idx) {
+ if (_sceneTripCounters[idx]._sceneNumber == _currentScene) {
+ if (--_sceneTripCounters[idx]._numTimes == 0) {
+ _vm->setFlags(_sceneTripCounters[idx]._flag);
+ _sceneTripCounters.remove_at(idx);
+ }
+ }
+ }
+
+ if (IS_ROSE_TATTOO) {
+ // Set the NPC paths for the scene
+ setNPCPath(0);
+
+ // Handle loading music for the scene
+ if (sound._midiDrvLoaded) {
+ if (talk._scriptMoreFlag != 1 && talk._scriptMoreFlag != 3)
+ sound._nextSongName = Common::String::format("res%02d", _currentScene);
+
+ // If it's a new song, then start it up
+ if (sound._currentSongName.compareToIgnoreCase(sound._nextSongName)) {
+ if (sound.loadSong(sound._nextSongName)) {
+ sound.setMIDIVolume(sound._musicVolume);
+ if (sound._musicOn)
+ sound.startSong();
+ }
+ }
+ }
+ }
+
//
// Load the room resource file for the scene
//
@@ -1585,4 +1616,26 @@ void Scene::synchronize(Common::Serializer &s) {
}
}
+void Scene::setNPCPath(int npc) {
+ People &people = *_vm->_people;
+ Talk &talk = *_vm->_talk;
+
+ people[npc].clearNPC();
+ people[npc]._name = Common::String::format("WATS%.2dA", _currentScene);
+
+ // If we're in the middle of a script that will continue once the scene is loaded,
+ // return without calling the path script
+ if (talk._scriptMoreFlag == 1 || talk._scriptMoreFlag == 3)
+ return;
+
+ // Turn off all the NPCs, since the talk script will turn them back on as needed
+ for (uint idx = 0; idx < MAX_NPC; ++idx)
+ people[idx + 1]._type = INVALID;
+
+ // Call the path script for the scene
+ Common::String pathFile = Common::String::format("PATH%.2dA", _currentScene);
+ talk.talkTo(pathFile);
+}
+
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index 0cbd775..b0b5624 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -128,6 +128,16 @@ public:
void load(Common::SeekableReadStream &s);
};
+struct SceneTripEntry {
+ bool _flag;
+ int _sceneNumber;
+ int _numTimes;
+
+ SceneTripEntry() : _flag(false), _sceneNumber(0), _numTimes(0) {}
+ SceneTripEntry(bool flag, int sceneNumber, int numTimes) : _flag(flag),
+ _sceneNumber(sceneNumber), _numTimes(numTimes) {}
+};
+
class Scene {
private:
SherlockEngine *_vm;
@@ -212,6 +222,7 @@ public:
bool _doBgAnimDone;
int _tempFadeStyle;
int _cAnimFramePause;
+ Common::Array<SceneTripEntry> _sceneTripCounters;
public:
Scene(SherlockEngine *vm);
~Scene();
@@ -291,6 +302,13 @@ public:
* Synchronize the data for a savegame
*/
void synchronize(Common::Serializer &s);
+
+ /**
+ * Resets the NPC path information when entering a new scene.
+ * @remarks The default talk file for the given NPC is set to WATS##A, where ## is
+ * the scene number being entered
+ */
+ void setNPCPath(int npc);
};
} // End of namespace Sherlock
diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp
index b8fe61d..279dd44 100644
--- a/engines/sherlock/sound.cpp
+++ b/engines/sherlock/sound.cpp
@@ -58,6 +58,8 @@ Sound::Sound(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
_soundPlaying = false;
_soundIsOn = &_soundPlaying;
_curPriority = 0;
+ _midiDrvLoaded = false;
+ _musicVolume = 0;
_soundOn = true;
_musicOn = true;
@@ -231,12 +233,19 @@ void Sound::stopMusic() {
warning("TODO: Sound::stopMusic");
}
-int Sound::loadSong(int songNumber) {
+bool Sound::loadSong(int songNumber) {
// TODO
warning("TODO: Sound::loadSong");
- return 0;
+ return false;
}
+bool Sound::loadSong(const Common::String &name) {
+ // TODO
+ warning("TODO: Sound::loadSong");
+ return false;
+}
+
+
void Sound::startSong() {
// TODO
warning("TODO: Sound::startSong");
@@ -264,5 +273,9 @@ void Sound::freeDigiSound() {
_soundPlaying = false;
}
+void Sound::setMIDIVolume(int volume) {
+ // TODO
+}
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h
index 689e615..06450ff 100644
--- a/engines/sherlock/sound.h
+++ b/engines/sherlock/sound.h
@@ -58,6 +58,9 @@ public:
bool _soundPlaying;
bool *_soundIsOn;
byte *_digiBuf;
+ bool _midiDrvLoaded;
+ Common::String _currentSongName, _nextSongName;
+ int _musicVolume;
public:
Sound(SherlockEngine *vm, Audio::Mixer *mixer);
@@ -94,7 +97,8 @@ public:
/**
* Load a specified song
*/
- int loadSong(int songNumber);
+ bool loadSong(int songNumber);
+ bool loadSong(const Common::String &name);
/**
* Start playing a song
@@ -119,6 +123,7 @@ public:
void stopSndFuncPtr(int v1, int v2);
void waitTimerRoland(uint time);
void freeDigiSound();
+ void setMIDIVolume(int volume);
};
} // End of namespace Sherlock
Commit: 79f11bd381b468a8fcca860ee3c2232606324fa5
https://github.com/scummvm/scummvm/commit/79f11bd381b468a8fcca860ee3c2232606324fa5
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-24T10:58:00-04:00
Commit Message:
SHERLOCK: Make virtual destructors for user interface classes
Changed paths:
engines/sherlock/user_interface.h
diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h
index 8a0f4f5..2203ddf 100644
--- a/engines/sherlock/user_interface.h
+++ b/engines/sherlock/user_interface.h
@@ -88,6 +88,7 @@ public:
int _lookHelp;
public:
static UserInterface *init(SherlockEngine *vm);
+ virtual ~UserInterface() {}
/**
* Resets the user interface
@@ -253,7 +254,7 @@ private:
void printObjectDesc(const Common::String &str, bool firstTime);
public:
ScalpelUserInterface(SherlockEngine *vm);
- ~ScalpelUserInterface();
+ virtual ~ScalpelUserInterface();
/**
* Handles counting down whilst checking for input, then clears the info line.
@@ -317,6 +318,8 @@ class TattooUserInterface : public UserInterface {
public:
TattooUserInterface(SherlockEngine *vm);
public:
+ virtual ~TattooUserInterface() {}
+
/**
* Main input handler for the user interface
*/
Commit: 79a33dc3b6e4717ae519405893169af81dcc2335
https://github.com/scummvm/scummvm/commit/79a33dc3b6e4717ae519405893169af81dcc2335
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-24T12:23:25-04:00
Commit Message:
SHERLOCK: Create separate opcode list for Scalpel vs Tattoo
Changed paths:
engines/sherlock/journal.cpp
engines/sherlock/talk.cpp
engines/sherlock/talk.h
diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp
index 564db59..b4b05da 100644
--- a/engines/sherlock/journal.cpp
+++ b/engines/sherlock/journal.cpp
@@ -135,6 +135,7 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
Screen &screen = *_vm->_screen;
Talk &talk = *_vm->_talk;
JournalEntry &journalEntry = _journal[_index];
+ const byte *opcodes = talk._opcodes;
Common::String dirFilename = _directory[journalEntry._converseNum];
bool replyOnly = journalEntry._replyOnly;
@@ -243,7 +244,7 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
byte c = *replyP++;
// Is it a control character?
- if (c < SWITCH_SPEAKER) {
+ if (c < opcodes[0]) {
// Nope. Set flag for allowing control codes to insert spaces
ctrlSpace = true;
assert(c >= ' ');
@@ -290,7 +291,7 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
byte v;
do {
v = *strP++;
- } while (v && (v < SWITCH_SPEAKER) && (v != '.') && (v != '!') && (v != '?'));
+ } while (v && (v < opcodes[0]) && (v != '.') && (v != '!') && (v != '?'));
if (v == '?')
journalString += " asked, \"";
@@ -306,11 +307,11 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
journalString += c;
do {
journalString += *replyP++;
- } while (*replyP && *replyP < SWITCH_SPEAKER && *replyP != '{' && *replyP != '}');
+ } while (*replyP && *replyP < opcodes[0] && *replyP != '{' && *replyP != '}');
commentJustPrinted = false;
}
- } else if (c == SWITCH_SPEAKER) {
+ } else if (c == opcodes[OP_SWITCH_SPEAKER]) {
if (!startOfReply) {
if (!commentFlag && !commentJustPrinted)
journalString += "\"\n";
@@ -337,7 +338,7 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
byte v;
do {
v = *strP++;
- } while (v && v < SWITCH_SPEAKER && v != '.' && v != '!' && v != '?');
+ } while (v && v < opcodes[0] && v != '.' && v != '!' && v != '?');
if (v == '?')
journalString += " asked, \"";
@@ -345,59 +346,42 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
journalString += " said, \"";
} else {
// Control code, so move past it and any parameters
- switch (c) {
- case RUN_CANIMATION:
- case ASSIGN_PORTRAIT_LOCATION:
- case PAUSE:
- case PAUSE_WITHOUT_CONTROL:
- case WALK_TO_CANIMATION:
+ if (c == opcodes[OP_RUN_CANIMATION] || c == opcodes[OP_ASSIGN_PORTRAIT_LOCATION] ||
+ c == opcodes[OP_PAUSE] || c == opcodes[OP_PAUSE_WITHOUT_CONTROL] ||
+ c == opcodes[OP_WALK_TO_CANIMATION]) {
// These commands have a single parameter
++replyP;
- break;
- case ADJUST_OBJ_SEQUENCE:
+ } else if (c == opcodes[OP_ADJUST_OBJ_SEQUENCE]) {
replyP += (replyP[0] & 127) + replyP[1] + 2;
- break;
- case WALK_TO_COORDS:
- case MOVE_MOUSE:
+ } else if (c == opcodes[OP_WALK_TO_COORDS] || c == opcodes[OP_MOVE_MOUSE]) {
replyP += 4;
- break;
-
- case SET_FLAG:
- case IF_STATEMENT:
+
+ } else if (c == opcodes[OP_SET_FLAG] || c == opcodes[OP_IF_STATEMENT]) {
replyP += 2;
- break;
- case SFX_COMMAND:
- case PLAY_PROLOGUE:
- case CALL_TALK_FILE:
+ } else if (c == opcodes[OP_SFX_COMMAND] || c == opcodes[OP_PLAY_PROLOGUE] ||
+ c == opcodes[OP_CALL_TALK_FILE]) {
replyP += 8;
break;
- case TOGGLE_OBJECT:
- case ADD_ITEM_TO_INVENTORY:
- case SET_OBJECT:
- case DISPLAY_INFO_LINE:
- case REMOVE_ITEM_FROM_INVENTORY:
+ } else if (c == opcodes[OP_TOGGLE_OBJECT] || c == opcodes[OP_ADD_ITEM_TO_INVENTORY] ||
+ c == opcodes[OP_SET_OBJECT] || c == opcodes[OP_DISPLAY_INFO_LINE] ||
+ c == opcodes[OP_REMOVE_ITEM_FROM_INVENTORY]) {
replyP += (*replyP & 127) + 1;
- break;
- case GOTO_SCENE:
+ } else if (c == opcodes[OP_GOTO_SCENE]) {
replyP += 5;
- break;
- case CARRIAGE_RETURN:
+ } else if (c == opcodes[OP_CARRIAGE_RETURN]) {
journalString += "\n";
- break;
-
- default:
- break;
}
// Put a space in the output for a control character, unless it's
// immediately coming after another control character
- if (ctrlSpace && c != ASSIGN_PORTRAIT_LOCATION && c != CARRIAGE_RETURN && !commentJustPrinted) {
+ if (ctrlSpace && c != opcodes[OP_ASSIGN_PORTRAIT_LOCATION] && c != opcodes[OP_CARRIAGE_RETURN] &&
+ !commentJustPrinted) {
journalString += " ";
ctrlSpace = false;
}
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index 1a926a5..7379d04 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -28,6 +28,51 @@ namespace Sherlock {
#define SPEAKER_REMOVE 0x80
+const byte SCALPEL_OPCODES[] = {
+ 128, // OP_SWITCH_SPEAKER
+ 129, // OP_RUN_CANIMATION
+ 130, // OP_ASSIGN_PORTRAIT_LOCATION
+ 131, // OP_PAUSE
+ 132, // OP_REMOVE_PORTRAIT
+ 133, // OP_CLEAR_WINDOW
+ 134, // OP_ADJUST_OBJ_SEQUENCE
+ 135, // OP_WALK_TO_COORDS
+ 136, // OP_PAUSE_WITHOUT_CONTROL
+ 137, // OP_BANISH_WINDOW
+ 138, // OP_SUMMON_WINDOW
+ 139, // OP_SET_FLAG
+ 140, // OP_SFX_COMMAND
+ 141, // OP_TOGGLE_OBJECT
+ 142, // OP_STEALTH_MODE_ACTIVE
+ 143, // OP_IF_STATEMENT
+ 144, // OP_ELSE_STATEMENT
+ 145, // OP_END_IF_STATEMENT
+ 146, // OP_STEALTH_MODE_DEACTIVATE
+ 147, // OP_TURN_HOLMES_OFF
+ 148, // OP_TURN_HOLMES_ON
+ 149, // OP_GOTO_SCENE
+ 150, // OP_PLAY_PROLOGUE
+ 151, // OP_ADD_ITEM_TO_INVENTORY
+ 152, // OP_SET_OBJECT
+ 153, // OP_CALL_TALK_FILE
+ 143, // OP_MOVE_MOUSE
+ 155, // OP_DISPLAY_INFO_LINE
+ 156, // OP_CLEAR_INFO_LINE
+ 157, // OP_WALK_TO_CANIMATION
+ 158, // OP_REMOVE_ITEM_FROM_INVENTORY
+ 159, // OP_ENABLE_END_KEY
+ 160, // OP_DISABLE_END_KEY
+ 161 // OP_CARRIAGE_RETURN
+};
+
+const byte TATTOO_OPCODES[] = {
+ 170, // OP_SWITCH_SPEAKER
+ 171, // OP_RUN_CANIMATION
+ 0 // TODO reset of opcodes
+};
+
+/*----------------------------------------------------------------*/
+
SequenceEntry::SequenceEntry() {
_objNum = 0;
_frameNumber = 0;
@@ -103,6 +148,7 @@ Talk::Talk(SherlockEngine *vm) : _vm(vm) {
_moreTalkDown = _moreTalkUp = false;
_scriptMoreFlag = 0;
_scriptSaveIndex = -1;
+ _opcodes = IS_SERRATED_SCALPEL ? SCALPEL_OPCODES : TATTOO_OPCODES;
}
void Talk::talkTo(const Common::String &filename) {
@@ -572,7 +618,7 @@ void Talk::stripVoiceCommands() {
// Scan for an sound effect byte, which indicates to play a sound
for (uint idx = 0; idx < statement._reply.size(); ++idx) {
- if (statement._reply[idx] == (char)SFX_COMMAND) {
+ if (statement._reply[idx] == (char)_opcodes[OP_SFX_COMMAND]) {
// Replace instruction character with a space, and delete the
// rest of the name following it
statement._reply = Common::String(statement._reply.c_str(),
@@ -952,7 +998,7 @@ void Talk::doScript(const Common::String &script) {
}
// Check if the script begins with a Stealh Mode Active command
- if (str[0] == STEALTH_MODE_ACTIVE || _talkStealth) {
+ if (str[0] == _opcodes[OP_STEALTH_MODE_ACTIVE] || _talkStealth) {
_talkStealth = 2;
_speaker |= SPEAKER_REMOVE;
} else {
@@ -960,7 +1006,7 @@ void Talk::doScript(const Common::String &script) {
ui.clearWindow();
// Need to switch speakers?
- if (str[0] == SWITCH_SPEAKER) {
+ if (str[0] == _opcodes[OP_SWITCH_SPEAKER]) {
_speaker = str[1] - 1;
str += 2;
pullSequence();
@@ -971,7 +1017,7 @@ void Talk::doScript(const Common::String &script) {
}
// Assign portrait location?
- if (str[0] == ASSIGN_PORTRAIT_LOCATION) {
+ if (str[0] == _opcodes[OP_ASSIGN_PORTRAIT_LOCATION]) {
switch (str[1] & 15) {
case 1:
people._portraitSide = 20;
@@ -993,7 +1039,7 @@ void Talk::doScript(const Common::String &script) {
}
// Remove portrait?
- if (str[0] == REMOVE_PORTRAIT) {
+ if (str[0] == _opcodes[OP_REMOVE_PORTRAIT]) {
_speaker = 255;
} else {
// Nope, so set the first speaker
@@ -1012,10 +1058,9 @@ void Talk::doScript(const Common::String &script) {
// Start of comment, so skip over it
while (*str++ != '}')
;
- } else if (c >= SWITCH_SPEAKER) {
+ } else if (c >= _opcodes[0]) {
// Handle control code
- switch (c) {
- case SWITCH_SPEAKER:
+ if (c == _opcodes[OP_SWITCH_SPEAKER]) {
if (!(_speaker & SPEAKER_REMOVE))
people.clearTalking();
if (_talkToAbort)
@@ -1030,20 +1075,18 @@ void Talk::doScript(const Common::String &script) {
pullSequence();
pushSequence(_speaker);
setSequence(_speaker);
- break;
- case RUN_CANIMATION:
+ } else if (c == _opcodes[OP_RUN_CANIMATION]) {
++str;
scene.startCAnim((str[0] - 1) & 127, (str[0] & 0x80) ? -1 : 1);
if (_talkToAbort)
return;
// Check if next character is changing side or changing portrait
- if (charCount && (str[1] == SWITCH_SPEAKER || str[1] == ASSIGN_PORTRAIT_LOCATION))
+ if (charCount && (str[1] == _opcodes[OP_SWITCH_SPEAKER] || str[1] == _opcodes[OP_ASSIGN_PORTRAIT_LOCATION]))
wait = 1;
- break;
- case ASSIGN_PORTRAIT_LOCATION:
+ } else if (c == _opcodes[OP_ASSIGN_PORTRAIT_LOCATION]) {
++str;
switch (str[0] & 15) {
case 1:
@@ -1061,15 +1104,13 @@ void Talk::doScript(const Common::String &script) {
if (str[0] > 15)
people._speakerFlip = true;
- break;
- case PAUSE:
+ } else if (c == _opcodes[OP_PAUSE]) {
// Pause
charCount = *++str;
wait = pauseFlag = true;
- break;
- case REMOVE_PORTRAIT:
+ } else if (c == _opcodes[OP_REMOVE_PORTRAIT]) {
if (_speaker >= 0 && _speaker < SPEAKER_REMOVE)
people.clearTalking();
pullSequence();
@@ -1077,16 +1118,13 @@ void Talk::doScript(const Common::String &script) {
return;
_speaker |= SPEAKER_REMOVE;
- break;
- case CLEAR_WINDOW:
+ } else if (c == _opcodes[OP_CLEAR_WINDOW]) {
ui.clearWindow();
yp = CONTROLS_Y + 12;
charCount = line = 0;
- break;
- case ADJUST_OBJ_SEQUENCE:
- {
+ } else if (c == _opcodes[OP_ADJUST_OBJ_SEQUENCE]) {
// Get the name of the object to adjust
++str;
for (int idx = 0; idx < (str[0] & 127); ++idx)
@@ -1123,9 +1161,8 @@ void Talk::doScript(const Common::String &script) {
// Reset object back to beginning of new sequence
scene._bgShapes[objId]._frameNumber = 0;
continue;
- }
- case WALK_TO_COORDS:
+ } else if (c == _opcodes[OP_WALK_TO_COORDS]) {
++str;
people.walkToCoords(Common::Point(((str[0] - 1) * 256 + str[1] - 1) * 100,
@@ -1134,9 +1171,8 @@ void Talk::doScript(const Common::String &script) {
return;
str += 3;
- break;
-
- case PAUSE_WITHOUT_CONTROL:
+
+ } else if (c == _opcodes[OP_PAUSE_WITHOUT_CONTROL]) {
++str;
for (int idx = 0; idx < (str[0] - 1); ++idx) {
@@ -1148,9 +1184,8 @@ void Talk::doScript(const Common::String &script) {
events.pollEvents();
events.setButtonState();
}
- break;
- case BANISH_WINDOW:
+ } else if (c == _opcodes[OP_BANISH_WINDOW]) {
if (!(_speaker & SPEAKER_REMOVE))
people.clearTalking();
pullSequence();
@@ -1162,9 +1197,8 @@ void Talk::doScript(const Common::String &script) {
ui.banishWindow();
ui._menuMode = TALK_MODE;
noTextYet = true;
- break;
-
- case SUMMON_WINDOW:
+
+ } else if (c == _opcodes[OP_SUMMON_WINDOW]) {
drawInterface();
events._pressed = events._released = false;
events.clearKeyboard();
@@ -1175,18 +1209,15 @@ void Talk::doScript(const Common::String &script) {
screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, false, "Up");
screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, false, "Down");
}
- break;
- case SET_FLAG: {
+ } else if (c == _opcodes[OP_SET_FLAG]) {
++str;
int flag1 = (str[0] - 1) * 256 + str[1] - 1 - (str[1] == 1 ? 1 : 0);
int flag = (flag1 & 0x3fff) * (flag1 >= 0x4000 ? -1 : 1);
_vm->setFlags(flag);
++str;
- break;
- }
- case SFX_COMMAND:
+ } else if (c == _opcodes[OP_SFX_COMMAND]) {
++str;
if (sound._voices) {
for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx)
@@ -1200,22 +1231,19 @@ void Talk::doScript(const Common::String &script) {
wait = 1;
str += 7;
- break;
-
- case TOGGLE_OBJECT:
+
+ } else if (c == _opcodes[OP_TOGGLE_OBJECT]) {
++str;
for (int idx = 0; idx < str[0]; ++idx)
tempString += str[idx + 1];
scene.toggleObject(tempString);
str += str[0];
- break;
-
- case STEALTH_MODE_ACTIVE:
+
+ } else if (c == _opcodes[OP_STEALTH_MODE_ACTIVE]) {
_talkStealth = 2;
- break;
- case IF_STATEMENT: {
+ } else if (c == _opcodes[OP_IF_STATEMENT]) {
++str;
int flag = (str[0] - 1) * 256 + str[1] - 1 - (str[1] == 1 ? 1 : 0);
++str;
@@ -1225,38 +1253,32 @@ void Talk::doScript(const Common::String &script) {
if (_vm->readFlags(flag & 0x7fff) != result) {
do {
++str;
- } while (str[0] && str[0] != ELSE_STATEMENT && str[0] != END_IF_STATEMENT);
+ } while (str[0] && str[0] != _opcodes[OP_ELSE_STATEMENT] && str[0] != _opcodes[OP_END_IF_STATEMENT]);
if (!str[0])
endStr = true;
}
- break;
- }
- case ELSE_STATEMENT:
+ } else if (c == _opcodes[OP_ELSE_STATEMENT]) {
// If this is encountered here, it means that a preceeding IF statement was found,
// and evaluated to true. Now all the statements for the true block are finished,
// so skip over the block of code that would have executed if the result was false
wait = 0;
do {
++str;
- } while (str[0] && str[0] != END_IF_STATEMENT);
- break;
+ } while (str[0] && str[0] != _opcodes[OP_END_IF_STATEMENT]);
- case STEALTH_MODE_DEACTIVATE:
+ } else if (c == _opcodes[OP_STEALTH_MODE_DEACTIVATE]) {
_talkStealth = 0;
events.clearKeyboard();
- break;
-
- case TURN_HOLMES_OFF:
+
+ } else if (c == _opcodes[OP_TURN_HOLMES_OFF]) {
people._holmesOn = false;
- break;
-
- case TURN_HOLMES_ON:
+
+ } else if (c == _opcodes[OP_TURN_HOLMES_ON]) {
people._holmesOn = true;
- break;
- case GOTO_SCENE:
+ } else if (c == _opcodes[OP_GOTO_SCENE]) {
scene._goToScene = str[1] - 1;
if (scene._goToScene != 100) {
@@ -1277,26 +1299,23 @@ void Talk::doScript(const Common::String &script) {
_scriptSaveIndex = str - scriptStart;
endStr = true;
wait = 0;
- break;
-
- case PLAY_PROLOGUE:
+
+ } else if (c == _opcodes[OP_PLAY_PROLOGUE]) {
++str;
for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx)
tempString += str[idx];
anim.play(tempString, 1, 3, true, 4);
- break;
-
- case ADD_ITEM_TO_INVENTORY:
+
+ } else if (c == _opcodes[OP_ADD_ITEM_TO_INVENTORY]) {
++str;
for (int idx = 0; idx < str[0]; ++idx)
tempString += str[idx + 1];
str += str[0];
inv.putNameInInventory(tempString);
- break;
-
- case SET_OBJECT: {
+
+ } else if (c == _opcodes[OP_SET_OBJECT]) {
++str;
for (int idx = 0; idx < (str[0] & 127); ++idx)
tempString += str[idx + 1];
@@ -1313,10 +1332,8 @@ void Talk::doScript(const Common::String &script) {
object.toggleHidden();
}
}
- break;
- }
-
- case CALL_TALK_FILE: {
+
+ } else if (c == _opcodes[OP_CALL_TALK_FILE]) {
++str;
for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx)
tempString += str[idx];
@@ -1345,18 +1362,15 @@ void Talk::doScript(const Common::String &script) {
_scriptMoreFlag = 1;
endStr = true;
wait = 0;
- break;
- }
-
- case MOVE_MOUSE:
+
+ } else if (c == _opcodes[OP_MOVE_MOUSE]) {
++str;
events.moveMouse(Common::Point((str[0] - 1) * 256 + str[1] - 1, str[2]));
if (_talkToAbort)
return;
str += 3;
- break;
-
- case DISPLAY_INFO_LINE:
+
+ } else if (c == _opcodes[OP_DISPLAY_INFO_LINE]) {
++str;
for (int idx = 0; idx < str[0]; ++idx)
tempString += str[idx + 1];
@@ -1364,42 +1378,35 @@ void Talk::doScript(const Common::String &script) {
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", tempString.c_str());
ui._menuCounter = 30;
- break;
-
- case CLEAR_INFO_LINE:
+
+ } else if (c == _opcodes[OP_CLEAR_INFO_LINE]) {
ui._infoFlag = true;
ui.clearInfo();
- break;
-
- case WALK_TO_CANIMATION: {
+
+ } else if (c == _opcodes[OP_WALK_TO_CANIMATION]) {
++str;
CAnim &animation = scene._cAnim[str[0] - 1];
people.walkToCoords(animation._goto, animation._gotoDir);
if (_talkToAbort)
return;
- break;
- }
-
- case REMOVE_ITEM_FROM_INVENTORY:
+
+ } else if (c == _opcodes[OP_REMOVE_ITEM_FROM_INVENTORY]) {
++str;
for (int idx = 0; idx < str[0]; ++idx)
tempString += str[idx + 1];
str += str[0];
inv.deleteItemFromInventory(tempString);
- break;
-
- case ENABLE_END_KEY:
+
+ } else if (c == _opcodes[OP_ENABLE_END_KEY]) {
ui._endKeyActive = true;
- break;
-
- case DISABLE_END_KEY:
+
+ } else if (c == _opcodes[OP_DISABLE_END_KEY]) {
ui._endKeyActive = false;
- break;
-
- default:
- break;
+
+ } else {
+ error("Unknown opcode encountered");
}
++str;
@@ -1438,10 +1445,10 @@ void Talk::doScript(const Common::String &script) {
width += screen.charWidth(str[idx]);
++idx;
++charCount;
- } while (width < 298 && str[idx] && str[idx] != '{' && str[idx] < SWITCH_SPEAKER);
+ } while (width < 298 && str[idx] && str[idx] != '{' && str[idx] < _opcodes[0]);
if (str[idx] || width >= 298) {
- if (str[idx] < SWITCH_SPEAKER && str[idx] != '{') {
+ if (str[idx] < _opcodes[0] && str[idx] != '{') {
--idx;
--charCount;
}
@@ -1481,37 +1488,27 @@ void Talk::doScript(const Common::String &script) {
str += idx;
// If line wrap occurred, then move to after the separating space between the words
- if (str[0] < SWITCH_SPEAKER && str[0] != '{')
+ if (str[0] < _opcodes[0] && str[0] != '{')
++str;
yp += 9;
++line;
// Certain different conditions require a wait
- if ((line == 4 && str < scriptEnd && str[0] != SFX_COMMAND && str[0] != PAUSE && _speaker != -1) ||
- (line == 5 && str < scriptEnd && str[0] != PAUSE && _speaker == -1) ||
+ if ((line == 4 && str < scriptEnd && str[0] != _opcodes[OP_SFX_COMMAND] && str[0] != _opcodes[OP_PAUSE] && _speaker != -1) ||
+ (line == 5 && str < scriptEnd && str[0] != _opcodes[OP_PAUSE] && _speaker == -1) ||
endStr) {
wait = 1;
}
- switch (str >= scriptEnd ? 0 : str[0]) {
- case SWITCH_SPEAKER:
- case ASSIGN_PORTRAIT_LOCATION:
- case BANISH_WINDOW:
- case IF_STATEMENT:
- case ELSE_STATEMENT:
- case END_IF_STATEMENT:
- case GOTO_SCENE:
- case CALL_TALK_FILE:
- wait = 1;
- break;
- default:
- break;
- }
+ byte v = (str >= scriptEnd ? 0 : str[0]);
+ wait = v == _opcodes[OP_SWITCH_SPEAKER] || v == _opcodes[OP_ASSIGN_PORTRAIT_LOCATION] ||
+ v == _opcodes[OP_BANISH_WINDOW] || _opcodes[OP_IF_STATEMENT] || v == _opcodes[OP_ELSE_STATEMENT] ||
+ v == _opcodes[OP_END_IF_STATEMENT] || v == _opcodes[OP_GOTO_SCENE] || v == _opcodes[OP_CALL_TALK_FILE];
}
// Open window if it wasn't already open, and text has already been printed
- if ((openTalkWindow && wait) || (openTalkWindow && str[0] >= SWITCH_SPEAKER && str[0] != CARRIAGE_RETURN)) {
+ if ((openTalkWindow && wait) || (openTalkWindow && str[0] >= _opcodes[0] && str[0] != _opcodes[OP_CARRIAGE_RETURN])) {
if (!ui._slideWindows) {
screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
} else {
@@ -1533,12 +1530,12 @@ void Talk::doScript(const Common::String &script) {
// If a key was pressed to finish the window, see if further voice files should be skipped
if (wait >= 0 && wait < 254) {
- if (str[0] == SFX_COMMAND)
+ if (str[0] == _opcodes[OP_SFX_COMMAND])
str += 9;
}
// Clear the window unless the wait was due to a PAUSE command
- if (!pauseFlag && wait != -1 && str < scriptEnd && str[0] != SFX_COMMAND) {
+ if (!pauseFlag && wait != -1 && str < scriptEnd && str[0] != _opcodes[OP_SFX_COMMAND]) {
if (!_talkStealth)
ui.clearWindow();
yp = CONTROLS_Y + 12;
diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h
index 48290e9..bead679 100644
--- a/engines/sherlock/talk.h
+++ b/engines/sherlock/talk.h
@@ -36,42 +36,43 @@ namespace Sherlock {
#define MAX_TALK_FILES 500
enum {
- SWITCH_SPEAKER = 128,
- RUN_CANIMATION = 129,
- ASSIGN_PORTRAIT_LOCATION = 130,
- PAUSE = 131,
- REMOVE_PORTRAIT = 132,
- CLEAR_WINDOW = 133,
- ADJUST_OBJ_SEQUENCE = 134,
- WALK_TO_COORDS = 135,
- PAUSE_WITHOUT_CONTROL = 136,
- BANISH_WINDOW = 137,
- SUMMON_WINDOW = 138,
- SET_FLAG = 139,
- SFX_COMMAND = 140,
- TOGGLE_OBJECT = 141,
- STEALTH_MODE_ACTIVE = 142,
- IF_STATEMENT = 143,
- ELSE_STATEMENT = 144,
- END_IF_STATEMENT = 145,
- STEALTH_MODE_DEACTIVATE = 146,
- TURN_HOLMES_OFF = 147,
- TURN_HOLMES_ON = 148,
- GOTO_SCENE = 149,
- PLAY_PROLOGUE = 150,
- ADD_ITEM_TO_INVENTORY = 151,
- SET_OBJECT = 152,
- CALL_TALK_FILE = 153,
- MOVE_MOUSE = 154,
- DISPLAY_INFO_LINE = 155,
- CLEAR_INFO_LINE = 156,
- WALK_TO_CANIMATION = 157,
- REMOVE_ITEM_FROM_INVENTORY = 158,
- ENABLE_END_KEY = 159,
- DISABLE_END_KEY = 160,
- CARRIAGE_RETURN = 161
+ OP_SWITCH_SPEAKER = 128,
+ OP_RUN_CANIMATION = 129,
+ OP_ASSIGN_PORTRAIT_LOCATION = 130,
+ OP_PAUSE = 131,
+ OP_REMOVE_PORTRAIT = 132,
+ OP_CLEAR_WINDOW = 133,
+ OP_ADJUST_OBJ_SEQUENCE = 134,
+ OP_WALK_TO_COORDS = 135,
+ OP_PAUSE_WITHOUT_CONTROL = 136,
+ OP_BANISH_WINDOW = 137,
+ OP_SUMMON_WINDOW = 138,
+ OP_SET_FLAG = 139,
+ OP_SFX_COMMAND = 140,
+ OP_TOGGLE_OBJECT = 141,
+ OP_STEALTH_MODE_ACTIVE = 142,
+ OP_IF_STATEMENT = 143,
+ OP_ELSE_STATEMENT = 144,
+ OP_END_IF_STATEMENT = 145,
+ OP_STEALTH_MODE_DEACTIVATE = 146,
+ OP_TURN_HOLMES_OFF = 147,
+ OP_TURN_HOLMES_ON = 148,
+ OP_GOTO_SCENE = 149,
+ OP_PLAY_PROLOGUE = 150,
+ OP_ADD_ITEM_TO_INVENTORY = 151,
+ OP_SET_OBJECT = 152,
+ OP_CALL_TALK_FILE = 153,
+ OP_MOVE_MOUSE = 154,
+ OP_DISPLAY_INFO_LINE = 155,
+ OP_CLEAR_INFO_LINE = 156,
+ OP_WALK_TO_CANIMATION = 157,
+ OP_REMOVE_ITEM_FROM_INVENTORY = 158,
+ OP_ENABLE_END_KEY = 159,
+ OP_DISABLE_END_KEY = 160,
+ OP_CARRIAGE_RETURN = 161
};
+
struct SequenceEntry {
int _objNum;
Common::Array<byte> _sequences;
@@ -181,6 +182,7 @@ public:
Common::String _scriptName;
bool _moreTalkUp, _moreTalkDown;
int _converseNum;
+ const byte *_opcodes;
public:
Talk(SherlockEngine *vm);
Commit: 55ab34b981cf58e3e650926713bf72729adaa311
https://github.com/scummvm/scummvm/commit/55ab34b981cf58e3e650926713bf72729adaa311
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-24T15:17:05-04:00
Commit Message:
SHERLOCK: Fully implemented RT opcodes array
Changed paths:
engines/sherlock/talk.cpp
engines/sherlock/talk.h
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index 7379d04..bc473f7 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -62,13 +62,109 @@ const byte SCALPEL_OPCODES[] = {
158, // OP_REMOVE_ITEM_FROM_INVENTORY
159, // OP_ENABLE_END_KEY
160, // OP_DISABLE_END_KEY
- 161 // OP_CARRIAGE_RETURN
+ 161, // OP_CARRIAGE_RETURN
+ 0, // OP_MOUSE_ON_OFF
+ 0, // OP_SET_WALK_CONTROL
+ 0, // OP_SET_TALK_SEQUENCE
+ 0, // OP_PLAY_SONG
+ 0, // OP_WALK_HOLMES_AND_NPC_TO_CANIM
+ 0, // OP_SET_NPC_PATH_DEST
+ 0, // OP_NEXT_SONG
+ 0, // OP_SET_NPC_PATH_PAUSE
+ 0, // OP_PASSWORD
+ 0, // OP_SET_SCENE_ENTRY_FLAG
+ 0, // OP_WALK_NPC_TO_CANIM
+ 0, // OP_WALK_HOLMES_AND_NPC_TO_COORDS
+ 0, // OP_WALK_HOLMES_AND_NPC_TO_COORDS
+ 0, // OP_SET_NPC_TALK_FILE
+ 0, // OP_TURN_NPC_OFF
+ 0, // OP_TURN_NPC_ON
+ 0, // OP_NPC_DESC_ON_OFF
+ 0, // OP_NPC_PATH_PAUSE_TAKING_NOTES
+ 0, // OP_NPC_PATH_PAUSE_LOOKING_HOLMES
+ 0, // OP_ENABLE_TALK_INTERRUPTS
+ 0, // OP_DISABLE_TALK_INTERRUPTS
+ 0, // OP_SET_NPC_INFO_LINE
+ 0, // OP_SET_NPC_POSITION
+ 0, // OP_NPC_PATH_LABEL
+ 0, // OP_PATH_GOTO_LABEL
+ 0, // OP_PATH_IF_FLAG_GOTO_LABEL
+ 0, // OP_NPC_WALK_GRAPHICS
+ 0, // OP_NPC_VERB
+ 0, // OP_NPC_VERB_CANIM
+ 0, // OP_NPC_VERB_SCRIPT
+ 0, // OP_RESTORE_PEOPLE_SEQUENCE
+ 0, // OP_NPC_VERB_TARGET
+ 0 // OP_TURN_SOUNDS_OFF
};
const byte TATTOO_OPCODES[] = {
170, // OP_SWITCH_SPEAKER
171, // OP_RUN_CANIMATION
- 0 // TODO reset of opcodes
+ 0, // OP_ASSIGN_PORTRAIT_LOCATION
+ 173, // OP_PAUSE
+ 0, // OP_REMOVE_PORTRAIT
+ 0, // OP_CLEAR_WINDOW
+ 176, // OP_ADJUST_OBJ_SEQUENCE
+ 177, // OP_WALK_TO_COORDS
+ 178, // OP_PAUSE_WITHOUT_CONTROL
+ 179, // OP_BANISH_WINDOW
+ 0, // OP_SUMMON_WINDOW
+ 181, // OP_SET_FLAG
+ 0, // OP_SFX_COMMAND
+ 183, // OP_TOGGLE_OBJECT
+ 184, // OP_STEALTH_MODE_ACTIVE
+ 0, // OP_IF_STATEMENT
+ 0, // OP_ELSE_STATEMENT
+ 0, // OP_END_IF_STATEMENT
+ 188, // OP_STEALTH_MODE_DEACTIVATE
+ 189, // OP_TURN_HOLMES_OFF
+ 190, // OP_TURN_HOLMES_ON
+ 191, // OP_GOTO_SCENE
+ 0, // OP_PLAY_PROLOGUE
+ 193, // OP_ADD_ITEM_TO_INVENTORY
+ 194, // OP_SET_OBJECT
+ 172, // OP_CALL_TALK_FILE
+ 0, // OP_MOVE_MOUSE
+ 0, // OP_DISPLAY_INFO_LINE
+ 0, // OP_CLEAR_INFO_LINE
+ 199, // OP_WALK_TO_CANIMATION
+ 200, // OP_REMOVE_ITEM_FROM_INVENTORY
+ 201, // OP_ENABLE_END_KEY
+ 202, // OP_DISABLE_END_KEY
+ 0, // OP_CARRIAGE_RETURN
+ 174, // OP_MOUSE_ON_OFF
+ 175, // OP_SET_WALK_CONTROL
+ 180, // OP_SET_TALK_SEQUENCE
+ 182, // OP_PLAY_SONG
+ 187, // OP_WALK_HOLMES_AND_NPC_TO_CANIM
+ 192, // OP_SET_NPC_PATH_DEST
+ 195, // OP_NEXT_SONG
+ 196, // OP_SET_NPC_PATH_PAUSE
+ 197, // OP_PASSWORD
+ 198, // OP_SET_SCENE_ENTRY_FLAG
+ 185, // OP_WALK_NPC_TO_CANIM
+ 204, // OP_WALK_HOLMES_AND_NPC_TO_COORDS
+ 205, // OP_SET_NPC_TALK_FILE
+ 206, // OP_TURN_NPC_OFF
+ 207, // OP_TURN_NPC_ON
+ 208, // OP_NPC_DESC_ON_OFF
+ 209, // OP_NPC_PATH_PAUSE_TAKING_NOTES
+ 210, // OP_NPC_PATH_PAUSE_LOOKING_HOLMES
+ 211, // OP_ENABLE_TALK_INTERRUPTS
+ 212, // OP_DISABLE_TALK_INTERRUPTS
+ 213, // OP_SET_NPC_INFO_LINE
+ 214, // OP_SET_NPC_POSITION
+ 215, // OP_NPC_PATH_LABEL
+ 216, // OP_PATH_GOTO_LABEL
+ 217, // OP_PATH_IF_FLAG_GOTO_LABEL
+ 218, // OP_NPC_WALK_GRAPHICS
+ 220, // OP_NPC_VERB
+ 221, // OP_NPC_VERB_CANIM
+ 222, // OP_NPC_VERB_SCRIPT
+ 224, // OP_RESTORE_PEOPLE_SEQUENCE
+ 226, // OP_NPC_VERB_TARGET
+ 227 // OP_TURN_SOUNDS_OFF
};
/*----------------------------------------------------------------*/
diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h
index bead679..b30b4ad 100644
--- a/engines/sherlock/talk.h
+++ b/engines/sherlock/talk.h
@@ -36,40 +36,73 @@ namespace Sherlock {
#define MAX_TALK_FILES 500
enum {
- OP_SWITCH_SPEAKER = 128,
- OP_RUN_CANIMATION = 129,
- OP_ASSIGN_PORTRAIT_LOCATION = 130,
- OP_PAUSE = 131,
- OP_REMOVE_PORTRAIT = 132,
- OP_CLEAR_WINDOW = 133,
- OP_ADJUST_OBJ_SEQUENCE = 134,
- OP_WALK_TO_COORDS = 135,
- OP_PAUSE_WITHOUT_CONTROL = 136,
- OP_BANISH_WINDOW = 137,
- OP_SUMMON_WINDOW = 138,
- OP_SET_FLAG = 139,
- OP_SFX_COMMAND = 140,
- OP_TOGGLE_OBJECT = 141,
- OP_STEALTH_MODE_ACTIVE = 142,
- OP_IF_STATEMENT = 143,
- OP_ELSE_STATEMENT = 144,
- OP_END_IF_STATEMENT = 145,
- OP_STEALTH_MODE_DEACTIVATE = 146,
- OP_TURN_HOLMES_OFF = 147,
- OP_TURN_HOLMES_ON = 148,
- OP_GOTO_SCENE = 149,
- OP_PLAY_PROLOGUE = 150,
- OP_ADD_ITEM_TO_INVENTORY = 151,
- OP_SET_OBJECT = 152,
- OP_CALL_TALK_FILE = 153,
- OP_MOVE_MOUSE = 154,
- OP_DISPLAY_INFO_LINE = 155,
- OP_CLEAR_INFO_LINE = 156,
- OP_WALK_TO_CANIMATION = 157,
- OP_REMOVE_ITEM_FROM_INVENTORY = 158,
- OP_ENABLE_END_KEY = 159,
- OP_DISABLE_END_KEY = 160,
- OP_CARRIAGE_RETURN = 161
+ OP_SWITCH_SPEAKER = 0,
+ OP_RUN_CANIMATION = 1,
+ OP_ASSIGN_PORTRAIT_LOCATION = 2,
+ OP_PAUSE = 3,
+ OP_REMOVE_PORTRAIT = 4,
+ OP_CLEAR_WINDOW = 5,
+ OP_ADJUST_OBJ_SEQUENCE = 6,
+ OP_WALK_TO_COORDS = 7,
+ OP_PAUSE_WITHOUT_CONTROL = 8,
+ OP_BANISH_WINDOW = 9,
+ OP_SUMMON_WINDOW = 10,
+ OP_SET_FLAG = 11,
+ OP_SFX_COMMAND = 12,
+ OP_TOGGLE_OBJECT = 13,
+ OP_STEALTH_MODE_ACTIVE = 14,
+ OP_IF_STATEMENT = 15,
+ OP_ELSE_STATEMENT = 16,
+ OP_END_IF_STATEMENT = 17,
+ OP_STEALTH_MODE_DEACTIVATE = 18,
+ OP_TURN_HOLMES_OFF = 19,
+ OP_TURN_HOLMES_ON = 20,
+ OP_GOTO_SCENE = 21,
+ OP_PLAY_PROLOGUE = 22,
+ OP_ADD_ITEM_TO_INVENTORY = 23,
+ OP_SET_OBJECT = 24,
+ OP_CALL_TALK_FILE = 25,
+ OP_MOVE_MOUSE = 26,
+ OP_DISPLAY_INFO_LINE = 27,
+ OP_CLEAR_INFO_LINE = 28,
+ OP_WALK_TO_CANIMATION = 29,
+ OP_REMOVE_ITEM_FROM_INVENTORY = 30,
+ OP_ENABLE_END_KEY = 31,
+ OP_DISABLE_END_KEY = 32,
+ OP_CARRIAGE_RETURN = 33,
+
+ OP_MOUSE_OFF_ON = 34,
+ OP_SET_WALK_CONTROL = 35,
+ OP_SET_TALK_SEQUENCE = 36,
+ OP_PLAY_SONG = 37,
+ OP_WALK_HOLMES_AND_NPC_TO_CANIM = 38,
+ OP_SET_NPC_PATH_DEST = 39,
+ OP_NEXT_SONG = 40,
+ OP_SET_NPC_PATH_PAUSE = 41,
+ OP_NEED_PASSWORD = 42,
+ OP_SET_SCENE_ENTRY_FLAG = 43,
+ OP_WALK_NPC_TO_CANIM = 44,
+ OP_WALK_HOLMES_AND_NPC_TO_COORDS = 45,
+ OP_SET_NPC_TALK_FILE = 46,
+ OP_TURN_NPC_OFF = 47,
+ OP_TURN_NPC_ON = 48,
+ OP_NPC_DESC_ON_OFF = 49,
+ OP_NPC_PATH_PAUSE_TAKING_NOTES = 50,
+ OP_NPC_PATH_PAUSE_LOOKING_HOLMES = 51,
+ OP_ENABLE_TALK_INTERRUPTS = 52,
+ OP_DISABLE_TALK_INTERRUPTS = 53,
+ OP_SET_NPC_INFO_LINE = 54,
+ OP_SET_NPC_POSITION = 54,
+ OP_NPC_PATH_LABEL = 55,
+ OP_PATH_GOTO_LABEL = 56,
+ OP_PATH_IF_FLAG_GOTO_LABEL = 57,
+ OP_NPC_WALK_GRAPHICS = 58,
+ OP_NPC_VERB = 59,
+ OP_NPC_VERB_CANIM = 60,
+ OP_NPC_VERB_SCRIPT = 61,
+ OP_RESTORE_PEOPLE_SEQUENCE = 62,
+ OP_NPC_VERB_TARGET = 63,
+ OP_TURN_SOUNDS_OFF = 64
};
Commit: 8a808654c8a342711fa34bdfbee29296496902d8
https://github.com/scummvm/scummvm/commit/8a808654c8a342711fa34bdfbee29296496902d8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-24T18:59:25-04:00
Commit Message:
SHERLOCK: Splitting Talk up to implement individual opcode methods
Changed paths:
engines/sherlock/sherlock.cpp
engines/sherlock/talk.cpp
engines/sherlock/talk.h
diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp
index 5973823..14f2433 100644
--- a/engines/sherlock/sherlock.cpp
+++ b/engines/sherlock/sherlock.cpp
@@ -95,7 +95,7 @@ void SherlockEngine::initialize() {
_scene = new Scene(this);
_screen = new Screen(this);
_sound = new Sound(this, _mixer);
- _talk = new Talk(this);
+ _talk = Talk::init(this);
_ui = UserInterface::init(this);
// Load game settings
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index bc473f7..9b22ee1 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -231,6 +231,13 @@ void TalkSequences::clear() {
/*----------------------------------------------------------------*/
+Talk *Talk::init(SherlockEngine *vm) {
+ if (vm->getGameID() == GType_SerratedScalpel)
+ return new ScalpelTalk(vm);
+ else
+ return new TattooTalk(vm);
+}
+
Talk::Talk(SherlockEngine *vm) : _vm(vm) {
_talkCounter = 0;
_talkToAbort = false;
@@ -245,6 +252,14 @@ Talk::Talk(SherlockEngine *vm) : _vm(vm) {
_scriptMoreFlag = 0;
_scriptSaveIndex = -1;
_opcodes = IS_SERRATED_SCALPEL ? SCALPEL_OPCODES : TATTOO_OPCODES;
+
+ _charCount = 0;
+ _line = 0;
+ _yp = 0;
+ _wait = 0;
+ _pauseFlag = false;
+ _seqCount = 0;
+ _scriptStart = _scriptEnd = nullptr;
}
void Talk::talkTo(const Common::String &filename) {
@@ -1063,34 +1078,29 @@ void Talk::setStillSeq(int speaker) {
}
void Talk::doScript(const Common::String &script) {
- Animation &anim = *_vm->_animation;
- Events &events = *_vm->_events;
- Inventory &inv = *_vm->_inventory;
- Map &map = *_vm->_map;
People &people = *_vm->_people;
Scene &scene = *_vm->_scene;
Screen &screen = *_vm->_screen;
- Sound &sound = *_vm->_sound;
UserInterface &ui = *_vm->_ui;
- int wait = 0;
- bool pauseFlag = false;
- bool endStr = false;
- int yp = CONTROLS_Y + 12;
- int charCount = 0;
- int line = 0;
- bool noTextYet = true;
bool openTalkWindow = false;
- int seqCount;
_savedSequences.clear();
- const byte *scriptStart = (const byte *)script.c_str();
- const byte *scriptEnd = scriptStart + script.size();
- const byte *str = scriptStart;
+ _scriptStart = (const byte *)script.c_str();
+ _scriptEnd = _scriptStart + script.size();
+ const byte *str = _scriptStart;
+ _yp = CONTROLS_Y + 12;
+ _charCount = 0;
+ _line = 0;
+ _wait = 0;
+ _pauseFlag = false;
+ _seqCount = 0;
+ _noTextYet = true;
+ _endStr = false;
if (_scriptMoreFlag) {
_scriptMoreFlag = 0;
- str = scriptStart + _scriptSaveIndex;
+ str = _scriptStart + _scriptSaveIndex;
}
// Check if the script begins with a Stealh Mode Active command
@@ -1145,371 +1155,31 @@ void Talk::doScript(const Common::String &script) {
do {
Common::String tempString;
- wait = 0;
+ _wait = 0;
byte c = str[0];
if (!c) {
- endStr = true;
+ _endStr = true;
} else if (c == '{') {
// Start of comment, so skip over it
while (*str++ != '}')
;
- } else if (c >= _opcodes[0]) {
+ } else if (_opcodeTable[c]) {
// Handle control code
- if (c == _opcodes[OP_SWITCH_SPEAKER]) {
- if (!(_speaker & SPEAKER_REMOVE))
- people.clearTalking();
- if (_talkToAbort)
- return;
-
- ui.clearWindow();
- yp = CONTROLS_Y + 12;
- charCount = line = 0;
-
- _speaker = *++str - 1;
- people.setTalking(_speaker);
- pullSequence();
- pushSequence(_speaker);
- setSequence(_speaker);
-
- } else if (c == _opcodes[OP_RUN_CANIMATION]) {
- ++str;
- scene.startCAnim((str[0] - 1) & 127, (str[0] & 0x80) ? -1 : 1);
- if (_talkToAbort)
- return;
-
- // Check if next character is changing side or changing portrait
- if (charCount && (str[1] == _opcodes[OP_SWITCH_SPEAKER] || str[1] == _opcodes[OP_ASSIGN_PORTRAIT_LOCATION]))
- wait = 1;
-
- } else if (c == _opcodes[OP_ASSIGN_PORTRAIT_LOCATION]) {
- ++str;
- switch (str[0] & 15) {
- case 1:
- people._portraitSide = 20;
- break;
- case 2:
- people._portraitSide = 220;
- break;
- case 3:
- people._portraitSide = 120;
- break;
- default:
- break;
- }
-
- if (str[0] > 15)
- people._speakerFlip = true;
-
- } else if (c == _opcodes[OP_PAUSE]) {
- // Pause
- charCount = *++str;
- wait = pauseFlag = true;
-
- } else if (c == _opcodes[OP_REMOVE_PORTRAIT]) {
- if (_speaker >= 0 && _speaker < SPEAKER_REMOVE)
- people.clearTalking();
- pullSequence();
- if (_talkToAbort)
- return;
-
- _speaker |= SPEAKER_REMOVE;
-
- } else if (c == _opcodes[OP_CLEAR_WINDOW]) {
- ui.clearWindow();
- yp = CONTROLS_Y + 12;
- charCount = line = 0;
-
- } else if (c == _opcodes[OP_ADJUST_OBJ_SEQUENCE]) {
- // Get the name of the object to adjust
- ++str;
- for (int idx = 0; idx < (str[0] & 127); ++idx)
- tempString += str[idx + 2];
-
- // Scan for object
- int objId = -1;
- for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) {
- if (tempString.equalsIgnoreCase(scene._bgShapes[idx]._name))
- objId = idx;
- }
- if (objId == -1)
- error("Could not find object %s to change", tempString.c_str());
-
- // Should the script be overwritten?
- if (str[0] > 0x80) {
- // Save the current sequence
- _savedSequences.push(SequenceEntry());
- SequenceEntry &seqEntry = _savedSequences.top();
- seqEntry._objNum = objId;
- seqEntry._seqTo = scene._bgShapes[objId]._seqTo;
- for (uint idx = 0; idx < scene._bgShapes[objId]._seqSize; ++idx)
- seqEntry._sequences.push_back(scene._bgShapes[objId]._sequences[idx]);
- }
-
- // Get number of bytes to change
- seqCount = str[1];
- str += (str[0] & 127) + 2;
-
- // Copy in the new sequence
- for (int idx = 0; idx < seqCount; ++idx, ++str)
- scene._bgShapes[objId]._sequences[idx] = str[0] - 1;
-
- // Reset object back to beginning of new sequence
- scene._bgShapes[objId]._frameNumber = 0;
+ switch ((this->*_opcodeTable[c - 128])(str)) {
+ case RET_EXIT:
+ return;
+ case RET_CONTINUE:
continue;
-
- } else if (c == _opcodes[OP_WALK_TO_COORDS]) {
- ++str;
-
- people.walkToCoords(Common::Point(((str[0] - 1) * 256 + str[1] - 1) * 100,
- str[2] * 100), str[3] - 1);
- if (_talkToAbort)
- return;
-
- str += 3;
-
- } else if (c == _opcodes[OP_PAUSE_WITHOUT_CONTROL]) {
- ++str;
-
- for (int idx = 0; idx < (str[0] - 1); ++idx) {
- scene.doBgAnim();
- if (_talkToAbort)
- return;
-
- // Check for button press
- events.pollEvents();
- events.setButtonState();
- }
-
- } else if (c == _opcodes[OP_BANISH_WINDOW]) {
- if (!(_speaker & SPEAKER_REMOVE))
- people.clearTalking();
- pullSequence();
-
- if (_talkToAbort)
- return;
-
- _speaker |= SPEAKER_REMOVE;
- ui.banishWindow();
- ui._menuMode = TALK_MODE;
- noTextYet = true;
-
- } else if (c == _opcodes[OP_SUMMON_WINDOW]) {
- drawInterface();
- events._pressed = events._released = false;
- events.clearKeyboard();
- noTextYet = false;
-
- if (_speaker != -1) {
- screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_NULL, false, "Exit");
- screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, false, "Up");
- screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, false, "Down");
- }
-
- } else if (c == _opcodes[OP_SET_FLAG]) {
- ++str;
- int flag1 = (str[0] - 1) * 256 + str[1] - 1 - (str[1] == 1 ? 1 : 0);
- int flag = (flag1 & 0x3fff) * (flag1 >= 0x4000 ? -1 : 1);
- _vm->setFlags(flag);
- ++str;
-
- } else if (c == _opcodes[OP_SFX_COMMAND]) {
- ++str;
- if (sound._voices) {
- for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx)
- tempString += str[idx];
- sound.playSound(tempString, WAIT_RETURN_IMMEDIATELY);
-
- // Set voices to wait for more
- sound._voices = 2;
- sound._speechOn = (*sound._soundIsOn);
- }
-
- wait = 1;
- str += 7;
-
- } else if (c == _opcodes[OP_TOGGLE_OBJECT]) {
- ++str;
- for (int idx = 0; idx < str[0]; ++idx)
- tempString += str[idx + 1];
-
- scene.toggleObject(tempString);
- str += str[0];
-
- } else if (c == _opcodes[OP_STEALTH_MODE_ACTIVE]) {
- _talkStealth = 2;
-
- } else if (c == _opcodes[OP_IF_STATEMENT]) {
- ++str;
- int flag = (str[0] - 1) * 256 + str[1] - 1 - (str[1] == 1 ? 1 : 0);
- ++str;
- wait = 0;
-
- bool result = flag < 0x8000;
- if (_vm->readFlags(flag & 0x7fff) != result) {
- do {
- ++str;
- } while (str[0] && str[0] != _opcodes[OP_ELSE_STATEMENT] && str[0] != _opcodes[OP_END_IF_STATEMENT]);
-
- if (!str[0])
- endStr = true;
- }
-
- } else if (c == _opcodes[OP_ELSE_STATEMENT]) {
- // If this is encountered here, it means that a preceeding IF statement was found,
- // and evaluated to true. Now all the statements for the true block are finished,
- // so skip over the block of code that would have executed if the result was false
- wait = 0;
- do {
- ++str;
- } while (str[0] && str[0] != _opcodes[OP_END_IF_STATEMENT]);
-
- } else if (c == _opcodes[OP_STEALTH_MODE_DEACTIVATE]) {
- _talkStealth = 0;
- events.clearKeyboard();
-
- } else if (c == _opcodes[OP_TURN_HOLMES_OFF]) {
- people._holmesOn = false;
-
- } else if (c == _opcodes[OP_TURN_HOLMES_ON]) {
- people._holmesOn = true;
-
- } else if (c == _opcodes[OP_GOTO_SCENE]) {
- scene._goToScene = str[1] - 1;
-
- if (scene._goToScene != 100) {
- // Not going to the map overview
- map._oldCharPoint = scene._goToScene;
- map._overPos.x = map[scene._goToScene].x * 100 - 600;
- map._overPos.y = map[scene._goToScene].y * 100 + 900;
-
- // Run a canimation?
- if (str[2] > 100) {
- people._hSavedFacing = str[2];
- people._hSavedPos = Common::Point(160, 100);
- }
- }
- str += 6;
-
- _scriptMoreFlag = (scene._goToScene == 100) ? 2 : 1;
- _scriptSaveIndex = str - scriptStart;
- endStr = true;
- wait = 0;
-
- } else if (c == _opcodes[OP_PLAY_PROLOGUE]) {
- ++str;
- for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx)
- tempString += str[idx];
-
- anim.play(tempString, 1, 3, true, 4);
-
- } else if (c == _opcodes[OP_ADD_ITEM_TO_INVENTORY]) {
- ++str;
- for (int idx = 0; idx < str[0]; ++idx)
- tempString += str[idx + 1];
- str += str[0];
-
- inv.putNameInInventory(tempString);
-
- } else if (c == _opcodes[OP_SET_OBJECT]) {
- ++str;
- for (int idx = 0; idx < (str[0] & 127); ++idx)
- tempString += str[idx + 1];
-
- // Set comparison state according to if we want to hide or unhide
- bool state = (str[0] >= SPEAKER_REMOVE);
- str += str[0] & 127;
-
- for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) {
- Object &object = scene._bgShapes[idx];
- if (tempString.equalsIgnoreCase(object._name)) {
- // Only toggle the object if it's not in the desired state already
- if ((object._type == HIDDEN && state) || (object._type != HIDDEN && !state))
- object.toggleHidden();
- }
- }
-
- } else if (c == _opcodes[OP_CALL_TALK_FILE]) {
- ++str;
- for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx)
- tempString += str[idx];
- str += 8;
-
- int scriptCurrentIndex = str - scriptStart;
-
- // Save the current script position and new talk file
- if (_scriptStack.size() < 9) {
- ScriptStackEntry rec1;
- rec1._name = _scriptName;
- rec1._currentIndex = scriptCurrentIndex;
- rec1._select = _scriptSelect;
- _scriptStack.push(rec1);
-
- // Push the new talk file onto the stack
- ScriptStackEntry rec2;
- rec2._name = tempString;
- rec2._currentIndex = 0;
- rec2._select = 100;
- _scriptStack.push(rec2);
- } else {
- error("Script stack overflow");
- }
-
- _scriptMoreFlag = 1;
- endStr = true;
- wait = 0;
-
- } else if (c == _opcodes[OP_MOVE_MOUSE]) {
- ++str;
- events.moveMouse(Common::Point((str[0] - 1) * 256 + str[1] - 1, str[2]));
- if (_talkToAbort)
- return;
- str += 3;
-
- } else if (c == _opcodes[OP_DISPLAY_INFO_LINE]) {
- ++str;
- for (int idx = 0; idx < str[0]; ++idx)
- tempString += str[idx + 1];
- str += str[0];
-
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", tempString.c_str());
- ui._menuCounter = 30;
-
- } else if (c == _opcodes[OP_CLEAR_INFO_LINE]) {
- ui._infoFlag = true;
- ui.clearInfo();
-
- } else if (c == _opcodes[OP_WALK_TO_CANIMATION]) {
- ++str;
- CAnim &animation = scene._cAnim[str[0] - 1];
-
- people.walkToCoords(animation._goto, animation._gotoDir);
- if (_talkToAbort)
- return;
-
- } else if (c == _opcodes[OP_REMOVE_ITEM_FROM_INVENTORY]) {
- ++str;
- for (int idx = 0; idx < str[0]; ++idx)
- tempString += str[idx + 1];
- str += str[0];
-
- inv.deleteItemFromInventory(tempString);
-
- } else if (c == _opcodes[OP_ENABLE_END_KEY]) {
- ui._endKeyActive = true;
-
- } else if (c == _opcodes[OP_DISABLE_END_KEY]) {
- ui._endKeyActive = false;
-
- } else {
- error("Unknown opcode encountered");
+ default:
+ break;
}
++str;
} else {
// If the window isn't yet open, draw the window before printing starts
- if (!ui._windowOpen && noTextYet) {
- noTextYet = false;
+ if (!ui._windowOpen && _noTextYet) {
+ _noTextYet = false;
drawInterface();
if (_talkTo != -1) {
@@ -1520,19 +1190,19 @@ void Talk::doScript(const Common::String &script) {
}
// If it's the first line, display the speaker
- if (!line && _speaker >= 0 && _speaker < (int)people._characters.size()) {
+ if (!_line && _speaker >= 0 && _speaker < (int)people._characters.size()) {
// If the window is open, display the name directly on-screen.
// Otherwise, simply draw it on the back buffer
if (ui._windowOpen) {
- screen.print(Common::Point(16, yp), TALK_FOREGROUND, "%s",
+ screen.print(Common::Point(16, _yp), TALK_FOREGROUND, "%s",
people._characters[_speaker & 127]._name);
} else {
- screen.gPrint(Common::Point(16, yp - 1), TALK_FOREGROUND, "%s",
+ screen.gPrint(Common::Point(16, _yp - 1), TALK_FOREGROUND, "%s",
people._characters[_speaker & 127]._name);
openTalkWindow = true;
}
- yp += 9;
+ _yp += 9;
}
// Find amount of text that will fit on the line
@@ -1540,23 +1210,23 @@ void Talk::doScript(const Common::String &script) {
do {
width += screen.charWidth(str[idx]);
++idx;
- ++charCount;
+ ++_charCount;
} while (width < 298 && str[idx] && str[idx] != '{' && str[idx] < _opcodes[0]);
if (str[idx] || width >= 298) {
if (str[idx] < _opcodes[0] && str[idx] != '{') {
--idx;
- --charCount;
+ --_charCount;
}
} else {
- endStr = true;
+ _endStr = true;
}
// If word wrap is needed, find the start of the current word
if (width >= 298) {
while (str[idx] != ' ') {
--idx;
- --charCount;
+ --_charCount;
}
}
@@ -1566,16 +1236,16 @@ void Talk::doScript(const Common::String &script) {
// If the speaker indicates a description file, print it in yellow
if (_speaker != -1) {
if (ui._windowOpen) {
- screen.print(Common::Point(16, yp), COMMAND_FOREGROUND, "%s", lineStr.c_str());
+ screen.print(Common::Point(16, _yp), COMMAND_FOREGROUND, "%s", lineStr.c_str());
} else {
- screen.gPrint(Common::Point(16, yp - 1), COMMAND_FOREGROUND, "%s", lineStr.c_str());
+ screen.gPrint(Common::Point(16, _yp - 1), COMMAND_FOREGROUND, "%s", lineStr.c_str());
openTalkWindow = true;
}
} else {
if (ui._windowOpen) {
- screen.print(Common::Point(16, yp), COMMAND_FOREGROUND, "%s", lineStr.c_str());
+ screen.print(Common::Point(16, _yp), COMMAND_FOREGROUND, "%s", lineStr.c_str());
} else {
- screen.gPrint(Common::Point(16, yp - 1), COMMAND_FOREGROUND, "%s", lineStr.c_str());
+ screen.gPrint(Common::Point(16, _yp - 1), COMMAND_FOREGROUND, "%s", lineStr.c_str());
openTalkWindow = true;
}
}
@@ -1587,24 +1257,24 @@ void Talk::doScript(const Common::String &script) {
if (str[0] < _opcodes[0] && str[0] != '{')
++str;
- yp += 9;
- ++line;
+ _yp += 9;
+ ++_line;
// Certain different conditions require a wait
- if ((line == 4 && str < scriptEnd && str[0] != _opcodes[OP_SFX_COMMAND] && str[0] != _opcodes[OP_PAUSE] && _speaker != -1) ||
- (line == 5 && str < scriptEnd && str[0] != _opcodes[OP_PAUSE] && _speaker == -1) ||
- endStr) {
- wait = 1;
+ if ((_line == 4 && str < _scriptEnd && str[0] != _opcodes[OP_SFX_COMMAND] && str[0] != _opcodes[OP_PAUSE] && _speaker != -1) ||
+ (_line == 5 && str < _scriptEnd && str[0] != _opcodes[OP_PAUSE] && _speaker == -1) ||
+ _endStr) {
+ _wait = 1;
}
- byte v = (str >= scriptEnd ? 0 : str[0]);
- wait = v == _opcodes[OP_SWITCH_SPEAKER] || v == _opcodes[OP_ASSIGN_PORTRAIT_LOCATION] ||
+ byte v = (str >= _scriptEnd ? 0 : str[0]);
+ _wait = v == _opcodes[OP_SWITCH_SPEAKER] || v == _opcodes[OP_ASSIGN_PORTRAIT_LOCATION] ||
v == _opcodes[OP_BANISH_WINDOW] || _opcodes[OP_IF_STATEMENT] || v == _opcodes[OP_ELSE_STATEMENT] ||
v == _opcodes[OP_END_IF_STATEMENT] || v == _opcodes[OP_GOTO_SCENE] || v == _opcodes[OP_CALL_TALK_FILE];
}
// Open window if it wasn't already open, and text has already been printed
- if ((openTalkWindow && wait) || (openTalkWindow && str[0] >= _opcodes[0] && str[0] != _opcodes[OP_CARRIAGE_RETURN])) {
+ if ((openTalkWindow && _wait) || (openTalkWindow && str[0] >= _opcodes[0] && str[0] != _opcodes[OP_CARRIAGE_RETURN])) {
if (!ui._slideWindows) {
screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
} else {
@@ -1615,34 +1285,34 @@ void Talk::doScript(const Common::String &script) {
openTalkWindow = false;
}
- if (wait) {
+ if (_wait) {
// Handling pausing
- if (!pauseFlag && charCount < 160)
- charCount = 160;
+ if (!_pauseFlag && _charCount < 160)
+ _charCount = 160;
- wait = waitForMore(charCount);
- if (wait == -1)
- endStr = true;
+ _wait = waitForMore(_charCount);
+ if (_wait == -1)
+ _endStr = true;
// If a key was pressed to finish the window, see if further voice files should be skipped
- if (wait >= 0 && wait < 254) {
+ if (_wait >= 0 && _wait < 254) {
if (str[0] == _opcodes[OP_SFX_COMMAND])
str += 9;
}
// Clear the window unless the wait was due to a PAUSE command
- if (!pauseFlag && wait != -1 && str < scriptEnd && str[0] != _opcodes[OP_SFX_COMMAND]) {
+ if (!_pauseFlag && _wait != -1 && str < _scriptEnd && str[0] != _opcodes[OP_SFX_COMMAND]) {
if (!_talkStealth)
ui.clearWindow();
- yp = CONTROLS_Y + 12;
- charCount = line = 0;
+ _yp = CONTROLS_Y + 12;
+ _charCount = _line = 0;
}
- pauseFlag = false;
+ _pauseFlag = false;
}
- } while (!_vm->shouldQuit() && !endStr);
+ } while (!_vm->shouldQuit() && !_endStr);
- if (wait != -1) {
+ if (_wait != -1) {
for (int ssIndex = 0; ssIndex < (int)_savedSequences.size(); ++ssIndex) {
SequenceEntry &seq = _savedSequences[ssIndex];
Object &object = scene._bgShapes[seq._objNum];
@@ -1757,4 +1427,559 @@ void Talk::synchronize(Common::Serializer &s) {
}
}
+OpcodeReturn Talk::cmdAddItemToInventory(const byte *&str) {
+ Inventory &inv = *_vm->_inventory;
+ Common::String tempString;
+
+ ++str;
+ for (int idx = 0; idx < str[0]; ++idx)
+ tempString += str[idx + 1];
+ str += str[0];
+
+ inv.putNameInInventory(tempString);
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdAdjustObjectSequence(const byte *&str) {
+ Scene &scene = *_vm->_scene;
+ Common::String tempString;
+
+ // Get the name of the object to adjust
+ ++str;
+ for (int idx = 0; idx < (str[0] & 127); ++idx)
+ tempString += str[idx + 2];
+
+ // Scan for object
+ int objId = -1;
+ for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) {
+ if (tempString.equalsIgnoreCase(scene._bgShapes[idx]._name))
+ objId = idx;
+ }
+ if (objId == -1)
+ error("Could not find object %s to change", tempString.c_str());
+
+ // Should the script be overwritten?
+ if (str[0] > 0x80) {
+ // Save the current sequence
+ _savedSequences.push(SequenceEntry());
+ SequenceEntry &seqEntry = _savedSequences.top();
+ seqEntry._objNum = objId;
+ seqEntry._seqTo = scene._bgShapes[objId]._seqTo;
+ for (uint idx = 0; idx < scene._bgShapes[objId]._seqSize; ++idx)
+ seqEntry._sequences.push_back(scene._bgShapes[objId]._sequences[idx]);
+ }
+
+ // Get number of bytes to change
+ _seqCount = str[1];
+ str += (str[0] & 127) + 2;
+
+ // Copy in the new sequence
+ for (int idx = 0; idx < _seqCount; ++idx, ++str)
+ scene._bgShapes[objId]._sequences[idx] = str[0] - 1;
+
+ // Reset object back to beginning of new sequence
+ scene._bgShapes[objId]._frameNumber = 0;
+
+ return RET_CONTINUE;
+}
+
+OpcodeReturn Talk::cmdBanishWindow(const byte *&str) {
+ People &people = *_vm->_people;
+ UserInterface &ui = *_vm->_ui;
+
+ if (!(_speaker & SPEAKER_REMOVE))
+ people.clearTalking();
+ pullSequence();
+
+ if (_talkToAbort)
+ return RET_EXIT;
+
+ _speaker |= SPEAKER_REMOVE;
+ ui.banishWindow();
+ ui._menuMode = TALK_MODE;
+ _noTextYet = true;
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdDisableEndKey(const byte *&str) {
+ _vm->_ui->_endKeyActive = false;
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdEnableEndKey(const byte *&str) {
+ _vm->_ui->_endKeyActive = true;
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdGotoScene(const byte *&str) {
+ Map &map = *_vm->_map;
+ People &people = *_vm->_people;
+ Scene &scene = *_vm->_scene;
+ scene._goToScene = str[1] - 1;
+
+ if (scene._goToScene != 100) {
+ // Not going to the map overview
+ map._oldCharPoint = scene._goToScene;
+ map._overPos.x = map[scene._goToScene].x * 100 - 600;
+ map._overPos.y = map[scene._goToScene].y * 100 + 900;
+
+ // Run a canimation?
+ if (str[2] > 100) {
+ people._hSavedFacing = str[2];
+ people._hSavedPos = Common::Point(160, 100);
+ }
+ }
+ str += 6;
+
+ _scriptMoreFlag = (scene._goToScene == 100) ? 2 : 1;
+ _scriptSaveIndex = str - _scriptStart;
+ _endStr = true;
+ _wait = 0;
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdHolmesOff(const byte *&str) {
+ _vm->_people->_holmesOn = false;
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdHolmesOn(const byte *&str) {
+ _vm->_people->_holmesOn = true;
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdPause(const byte *&str) {
+ _charCount = *++str;
+ _wait = _pauseFlag = true;
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdPauseWithoutControl(const byte *&str) {
+ Events &events = *_vm->_events;
+ Scene &scene = *_vm->_scene;
+ ++str;
+
+ for (int idx = 0; idx < (str[0] - 1); ++idx) {
+ scene.doBgAnim();
+ if (_talkToAbort)
+ return RET_EXIT;
+
+ // Check for button press
+ events.pollEvents();
+ events.setButtonState();
+ }
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdRemoveItemFromInventory(const byte *&str) {
+ Inventory &inv = *_vm->_inventory;
+ Common::String tempString;
+
+ ++str;
+ for (int idx = 0; idx < str[0]; ++idx)
+ tempString += str[idx + 1];
+ str += str[0];
+
+ inv.deleteItemFromInventory(tempString);
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdRunCAnimation(const byte *&str) {
+ Scene &scene = *_vm->_scene;
+
+ ++str;
+ scene.startCAnim((str[0] - 1) & 127, (str[0] & 0x80) ? -1 : 1);
+ if (_talkToAbort)
+ return RET_EXIT;
+
+ // Check if next character is changing side or changing portrait
+ if (_charCount && (str[1] == _opcodes[OP_SWITCH_SPEAKER] || str[1] == _opcodes[OP_ASSIGN_PORTRAIT_LOCATION]))
+ _wait = 1;
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdSetFlag(const byte *&str) {
+ ++str;
+ int flag1 = (str[0] - 1) * 256 + str[1] - 1 - (str[1] == 1 ? 1 : 0);
+ int flag = (flag1 & 0x3fff) * (flag1 >= 0x4000 ? -1 : 1);
+ _vm->setFlags(flag);
+ ++str;
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdSetObject(const byte *&str) {
+ Scene &scene = *_vm->_scene;
+ Common::String tempString;
+
+ ++str;
+ for (int idx = 0; idx < (str[0] & 127); ++idx)
+ tempString += str[idx + 1];
+
+ // Set comparison state according to if we want to hide or unhide
+ bool state = (str[0] >= SPEAKER_REMOVE);
+ str += str[0] & 127;
+
+ for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) {
+ Object &object = scene._bgShapes[idx];
+ if (tempString.equalsIgnoreCase(object._name)) {
+ // Only toggle the object if it's not in the desired state already
+ if ((object._type == HIDDEN && state) || (object._type != HIDDEN && !state))
+ object.toggleHidden();
+ }
+ }
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdStealthModeActivate(const byte *&str) {
+ _talkStealth = 2;
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdStealthModeDeactivate(const byte *&str) {
+ Events &events = *_vm->_events;
+
+ _talkStealth = 0;
+ events.clearKeyboard();
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdSwitchSpeaker(const byte *&str) {
+ People &people = *_vm->_people;
+ UserInterface &ui = *_vm->_ui;
+
+ if (!(_speaker & SPEAKER_REMOVE))
+ people.clearTalking();
+ if (_talkToAbort)
+ return RET_EXIT;
+
+ ui.clearWindow();
+ _yp = CONTROLS_Y + 12;
+ _charCount = _line = 0;
+
+ _speaker = *++str - 1;
+ people.setTalking(_speaker);
+ pullSequence();
+ pushSequence(_speaker);
+ setSequence(_speaker);
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdToggleObject(const byte *&str) {
+ Scene &scene = *_vm->_scene;
+ Common::String tempString;
+
+ ++str;
+ for (int idx = 0; idx < str[0]; ++idx)
+ tempString += str[idx + 1];
+
+ scene.toggleObject(tempString);
+ str += str[0];
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdWalkToCAnimation(const byte *&str) {
+ People &people = *_vm->_people;
+ Scene &scene = *_vm->_scene;
+
+ ++str;
+ CAnim &animation = scene._cAnim[str[0] - 1];
+ people.walkToCoords(animation._goto, animation._gotoDir);
+
+ return _talkToAbort ? RET_EXIT : RET_SUCCESS;
+}
+
+OpcodeReturn Talk::cmdWalkToCoords(const byte *&str) {
+ People &people = *_vm->_people;
+ ++str;
+
+ people.walkToCoords(Common::Point(((str[0] - 1) * 256 + str[1] - 1) * 100,
+ str[2] * 100), str[3] - 1);
+ if (_talkToAbort)
+ return RET_EXIT;
+
+ str += 3;
+ return RET_SUCCESS;
+}
+
+/*----------------------------------------------------------------*/
+
+ScalpelTalk::ScalpelTalk(SherlockEngine *vm) : Talk(vm) {
+ static OpcodeMethod OPCODE_METHODS[] = {
+ (OpcodeMethod)&ScalpelTalk::cmdSwitchSpeaker,
+ (OpcodeMethod)&ScalpelTalk::cmdRunCAnimation,
+ (OpcodeMethod)&ScalpelTalk::cmdAssignPortraitLocation,
+
+ (OpcodeMethod)&ScalpelTalk::cmdPause,
+ (OpcodeMethod)&ScalpelTalk::cmdRemovePortrait,
+ (OpcodeMethod)&ScalpelTalk::cmdClearWindow,
+ (OpcodeMethod)&ScalpelTalk::cmdAdjustObjectSequence,
+ (OpcodeMethod)&ScalpelTalk::cmdWalkToCoords,
+ (OpcodeMethod)&ScalpelTalk::cmdPauseWithoutControl,
+ (OpcodeMethod)&ScalpelTalk::cmdBanishWindow,
+ (OpcodeMethod)&ScalpelTalk::cmdSummonWindow,
+ (OpcodeMethod)&ScalpelTalk::cmdSetFlag,
+ (OpcodeMethod)&ScalpelTalk::cmdSfxCommand,
+
+ (OpcodeMethod)&ScalpelTalk::cmdToggleObject,
+ (OpcodeMethod)&ScalpelTalk::cmdStealthModeActivate,
+ (OpcodeMethod)&ScalpelTalk::cmdIf,
+ (OpcodeMethod)&ScalpelTalk::cmdElse,
+ nullptr,
+ (OpcodeMethod)&ScalpelTalk::cmdStealthModeDeactivate,
+ (OpcodeMethod)&ScalpelTalk::cmdHolmesOff,
+ (OpcodeMethod)&ScalpelTalk::cmdHolmesOn,
+ (OpcodeMethod)&ScalpelTalk::cmdGotoScene,
+ (OpcodeMethod)&ScalpelTalk::cmdPlayPrologue,
+
+ (OpcodeMethod)&ScalpelTalk::cmdAddItemToInventory,
+ (OpcodeMethod)&ScalpelTalk::cmdSetObject,
+ (OpcodeMethod)&ScalpelTalk::cmdCallTalkFile,
+ (OpcodeMethod)&ScalpelTalk::cmdMoveMouse,
+ (OpcodeMethod)&ScalpelTalk::cmdDisplayInfoLine,
+ (OpcodeMethod)&ScalpelTalk::cmdClearInfoLine,
+ (OpcodeMethod)&ScalpelTalk::cmdWalkToCAnimation,
+ (OpcodeMethod)&ScalpelTalk::cmdRemoveItemFromInventory,
+ (OpcodeMethod)&ScalpelTalk::cmdEnableEndKey,
+ (OpcodeMethod)&ScalpelTalk::cmdDisableEndKey,
+
+ (OpcodeMethod)&ScalpelTalk::cmdCarriageReturn
+ };
+
+ _opcodeTable = OPCODE_METHODS;
+}
+
+OpcodeReturn ScalpelTalk::cmdAssignPortraitLocation(const byte *&str) {
+ People &people = *_vm->_people;
+
+ ++str;
+ switch (str[0] & 15) {
+ case 1:
+ people._portraitSide = 20;
+ break;
+ case 2:
+ people._portraitSide = 220;
+ break;
+ case 3:
+ people._portraitSide = 120;
+ break;
+ default:
+ break;
+ }
+
+ if (str[0] > 15)
+ people._speakerFlip = true;
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn ScalpelTalk::cmdCallTalkFile(const byte *&str) {
+ Common::String tempString;
+
+ ++str;
+ for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx)
+ tempString += str[idx];
+ str += 8;
+
+ int scriptCurrentIndex = str - _scriptStart;
+
+ // Save the current script position and new talk file
+ if (_scriptStack.size() < 9) {
+ ScriptStackEntry rec1;
+ rec1._name = _scriptName;
+ rec1._currentIndex = scriptCurrentIndex;
+ rec1._select = _scriptSelect;
+ _scriptStack.push(rec1);
+
+ // Push the new talk file onto the stack
+ ScriptStackEntry rec2;
+ rec2._name = tempString;
+ rec2._currentIndex = 0;
+ rec2._select = 100;
+ _scriptStack.push(rec2);
+ } else {
+ error("Script stack overflow");
+ }
+
+ _scriptMoreFlag = 1;
+ _endStr = true;
+ _wait = 0;
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn ScalpelTalk::cmdClearInfoLine(const byte *&str) {
+ UserInterface &ui = *_vm->_ui;
+
+ ui._infoFlag = true;
+ ui.clearInfo();
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn ScalpelTalk::cmdClearWindow(const byte *&str) {
+ UserInterface &ui = *_vm->_ui;
+
+ ui.clearWindow();
+ _yp = CONTROLS_Y + 12;
+ _charCount = _line = 0;
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn ScalpelTalk::cmdDisplayInfoLine(const byte *&str) {
+ Screen &screen = *_vm->_screen;
+ UserInterface &ui = *_vm->_ui;
+ Common::String tempString;
+
+ ++str;
+ for (int idx = 0; idx < str[0]; ++idx)
+ tempString += str[idx + 1];
+ str += str[0];
+
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", tempString.c_str());
+ ui._menuCounter = 30;
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn ScalpelTalk::cmdElse(const byte *&str) {
+ // If this is encountered here, it means that a preceeding IF statement was found,
+ // and evaluated to true. Now all the statements for the true block are finished,
+ // so skip over the block of code that would have executed if the result was false
+ _wait = 0;
+ do {
+ ++str;
+ } while (str[0] && str[0] != _opcodes[OP_END_IF_STATEMENT]);
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn ScalpelTalk::cmdIf(const byte *&str) {
+ ++str;
+ int flag = (str[0] - 1) * 256 + str[1] - 1 - (str[1] == 1 ? 1 : 0);
+ ++str;
+ _wait = 0;
+
+ bool result = flag < 0x8000;
+ if (_vm->readFlags(flag & 0x7fff) != result) {
+ do {
+ ++str;
+ } while (str[0] && str[0] != _opcodes[OP_ELSE_STATEMENT] && str[0] != _opcodes[OP_END_IF_STATEMENT]);
+
+ if (!str[0])
+ _endStr = true;
+ }
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn ScalpelTalk::cmdMoveMouse(const byte *&str) {
+ Events &events = *_vm->_events;
+
+ ++str;
+ events.moveMouse(Common::Point((str[0] - 1) * 256 + str[1] - 1, str[2]));
+ if (_talkToAbort)
+ return RET_EXIT;
+ str += 3;
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn ScalpelTalk::cmdPlayPrologue(const byte *&str) {
+ Animation &anim = *_vm->_animation;
+ Common::String tempString;
+
+ ++str;
+ for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx)
+ tempString += str[idx];
+
+ anim.play(tempString, 1, 3, true, 4);
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn ScalpelTalk::cmdRemovePortrait(const byte *&str) {
+ People &people = *_vm->_people;
+
+ if (_speaker >= 0 && _speaker < SPEAKER_REMOVE)
+ people.clearTalking();
+ pullSequence();
+ if (_talkToAbort)
+ return RET_EXIT;
+
+ _speaker |= SPEAKER_REMOVE;
+ return RET_SUCCESS;
+}
+
+OpcodeReturn ScalpelTalk::cmdSfxCommand(const byte *&str) {
+ Sound &sound = *_vm->_sound;
+ Common::String tempString;
+
+ ++str;
+ if (sound._voices) {
+ for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx)
+ tempString += str[idx];
+ sound.playSound(tempString, WAIT_RETURN_IMMEDIATELY);
+
+ // Set voices to wait for more
+ sound._voices = 2;
+ sound._speechOn = (*sound._soundIsOn);
+ }
+
+ _wait = 1;
+ str += 7;
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn ScalpelTalk::cmdSummonWindow(const byte *&str) {
+ Events &events = *_vm->_events;
+ Screen &screen = *_vm->_screen;
+
+ drawInterface();
+ events._pressed = events._released = false;
+ events.clearKeyboard();
+ _noTextYet = false;
+
+ if (_speaker != -1) {
+ screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_NULL, false, "Exit");
+ screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, false, "Up");
+ screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, false, "Down");
+ }
+
+ return RET_SUCCESS;
+}
+
+OpcodeReturn ScalpelTalk::cmdCarriageReturn(const byte *&str) {
+ return RET_SUCCESS;
+}
+
+/*----------------------------------------------------------------*/
+
+TattooTalk::TattooTalk(SherlockEngine *vm) : Talk(vm) {
+ static OpcodeMethod OPCODE_METHODS[] = {
+ nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ (OpcodeMethod)&TattooTalk::cmdSwitchSpeaker,
+ (OpcodeMethod)&TattooTalk::cmdRunCAnimation,
+ // TODO: Implement opcode methods for new Tattoo opcodes
+ };
+
+ _opcodeTable = OPCODE_METHODS;
+}
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h
index b30b4ad..02d141d 100644
--- a/engines/sherlock/talk.h
+++ b/engines/sherlock/talk.h
@@ -105,6 +105,13 @@ enum {
OP_TURN_SOUNDS_OFF = 64
};
+enum OpcodeReturn { RET_EXIT = -1, RET_SUCCESS = 0, RET_CONTINUE = 1 };
+
+class SherlockEngine;
+class ScalpelUserInterface;
+class Talk;
+
+typedef OpcodeReturn(Talk::*OpcodeMethod)(const byte *&str);
struct SequenceEntry {
int _objNum;
@@ -156,25 +163,9 @@ struct TalkSequences {
void clear();
};
-class SherlockEngine;
-class ScalpelUserInterface;
-
class Talk {
friend class ScalpelUserInterface;
private:
- SherlockEngine *_vm;
- Common::Stack<SequenceEntry> _savedSequences;
- Common::Stack<SequenceEntry> _sequenceStack;
- Common::Stack<ScriptStackEntry> _scriptStack;
- Common::Array<Statement> _statements;
- TalkHistoryEntry _talkHistory[MAX_TALK_FILES];
- int _speaker;
- int _talkIndex;
- int _scriptSelect;
- int _talkStealth;
- int _talkToFlag;
- int _scriptSaveIndex;
-private:
/**
* Remove any voice commands from a loaded statement list
*/
@@ -207,6 +198,54 @@ private:
* the amount of text that's been displayed
*/
int waitForMore(int delay);
+protected:
+ SherlockEngine *_vm;
+ OpcodeMethod *_opcodeTable;
+ Common::Stack<SequenceEntry> _savedSequences;
+ Common::Stack<SequenceEntry> _sequenceStack;
+ Common::Stack<ScriptStackEntry> _scriptStack;
+ Common::Array<Statement> _statements;
+ TalkHistoryEntry _talkHistory[MAX_TALK_FILES];
+ int _speaker;
+ int _talkIndex;
+ int _scriptSelect;
+ int _talkStealth;
+ int _talkToFlag;
+ int _scriptSaveIndex;
+
+ // These fields are used solely by doScript, but are fields because all the script opcodes are
+ // separate methods now, and need access to these fields
+ int _yp;
+ int _charCount;
+ int _line;
+ int _wait;
+ bool _pauseFlag;
+ bool _endStr, _noTextYet;
+ int _seqCount;
+ const byte *_scriptStart, *_scriptEnd;
+protected:
+ Talk(SherlockEngine *vm);
+
+ OpcodeReturn cmdAddItemToInventory(const byte *&str);
+ OpcodeReturn cmdAdjustObjectSequence(const byte *&str);
+ OpcodeReturn cmdBanishWindow(const byte *&str);
+ OpcodeReturn cmdDisableEndKey(const byte *&str);
+ OpcodeReturn cmdEnableEndKey(const byte *&str);
+ OpcodeReturn cmdGotoScene(const byte *&str);
+ OpcodeReturn cmdHolmesOff(const byte *&str);
+ OpcodeReturn cmdHolmesOn(const byte *&str);
+ OpcodeReturn cmdPause(const byte *&str);
+ OpcodeReturn cmdPauseWithoutControl(const byte *&str);
+ OpcodeReturn cmdRemoveItemFromInventory(const byte *&str);
+ OpcodeReturn cmdRunCAnimation(const byte *&str);
+ OpcodeReturn cmdSetFlag(const byte *&str);
+ OpcodeReturn cmdSetObject(const byte *&str);
+ OpcodeReturn cmdStealthModeActivate(const byte *&str);
+ OpcodeReturn cmdStealthModeDeactivate(const byte *&str);
+ OpcodeReturn cmdSwitchSpeaker(const byte *&str);
+ OpcodeReturn cmdToggleObject(const byte *&str);
+ OpcodeReturn cmdWalkToCAnimation(const byte *&str);
+ OpcodeReturn cmdWalkToCoords(const byte *&str);
public:
bool _talkToAbort;
int _talkCounter;
@@ -216,8 +255,10 @@ public:
bool _moreTalkUp, _moreTalkDown;
int _converseNum;
const byte *_opcodes;
+
public:
- Talk(SherlockEngine *vm);
+ static Talk *init(SherlockEngine *vm);
+ virtual ~Talk() {}
/**
* Return a given talk statement
@@ -302,6 +343,32 @@ public:
void synchronize(Common::Serializer &s);
};
+class ScalpelTalk : public Talk {
+protected:
+ OpcodeReturn cmdAssignPortraitLocation(const byte *&str);
+ OpcodeReturn cmdCallTalkFile(const byte *&str);
+ OpcodeReturn cmdClearInfoLine(const byte *&str);
+ OpcodeReturn cmdClearWindow(const byte *&str);
+ OpcodeReturn cmdDisplayInfoLine(const byte *&str);
+ OpcodeReturn cmdElse(const byte *&str);
+ OpcodeReturn cmdIf(const byte *&str);
+ OpcodeReturn cmdMoveMouse(const byte *&str);
+ OpcodeReturn cmdPlayPrologue(const byte *&str);
+ OpcodeReturn cmdRemovePortrait(const byte *&str);
+ OpcodeReturn cmdSfxCommand(const byte *&str);
+ OpcodeReturn cmdSummonWindow(const byte *&str);
+ OpcodeReturn cmdCarriageReturn(const byte *&str);
+public:
+ ScalpelTalk(SherlockEngine *vm);
+ virtual ~ScalpelTalk() {}
+};
+
+class TattooTalk : public Talk {
+public:
+ TattooTalk(SherlockEngine *vm);
+ virtual ~TattooTalk() {}
+};
+
} // End of namespace Sherlock
#endif
Commit: b4849f21d27a296f0150937a0d833f2ffd1be507
https://github.com/scummvm/scummvm/commit/b4849f21d27a296f0150937a0d833f2ffd1be507
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-24T20:33:14-04:00
Commit Message:
SHERLOCK: Implement method stubs for Tattoo opcodes
Changed paths:
engines/sherlock/talk.cpp
engines/sherlock/talk.h
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index 9b22ee1..15b6409 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -1502,6 +1502,42 @@ OpcodeReturn Talk::cmdBanishWindow(const byte *&str) {
return RET_SUCCESS;
}
+OpcodeReturn Talk::cmdCallTalkFile(const byte *&str) {
+ Common::String tempString;
+
+ ++str;
+ for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx)
+ tempString += str[idx];
+ str += 8;
+
+ int scriptCurrentIndex = str - _scriptStart;
+
+ // Save the current script position and new talk file
+ if (_scriptStack.size() < 9) {
+ ScriptStackEntry rec1;
+ rec1._name = _scriptName;
+ rec1._currentIndex = scriptCurrentIndex;
+ rec1._select = _scriptSelect;
+ _scriptStack.push(rec1);
+
+ // Push the new talk file onto the stack
+ ScriptStackEntry rec2;
+ rec2._name = tempString;
+ rec2._currentIndex = 0;
+ rec2._select = 100;
+ _scriptStack.push(rec2);
+ }
+ else {
+ error("Script stack overflow");
+ }
+
+ _scriptMoreFlag = 1;
+ _endStr = true;
+ _wait = 0;
+
+ return RET_SUCCESS;
+}
+
OpcodeReturn Talk::cmdDisableEndKey(const byte *&str) {
_vm->_ui->_endKeyActive = false;
return RET_SUCCESS;
@@ -1783,41 +1819,6 @@ OpcodeReturn ScalpelTalk::cmdAssignPortraitLocation(const byte *&str) {
return RET_SUCCESS;
}
-OpcodeReturn ScalpelTalk::cmdCallTalkFile(const byte *&str) {
- Common::String tempString;
-
- ++str;
- for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx)
- tempString += str[idx];
- str += 8;
-
- int scriptCurrentIndex = str - _scriptStart;
-
- // Save the current script position and new talk file
- if (_scriptStack.size() < 9) {
- ScriptStackEntry rec1;
- rec1._name = _scriptName;
- rec1._currentIndex = scriptCurrentIndex;
- rec1._select = _scriptSelect;
- _scriptStack.push(rec1);
-
- // Push the new talk file onto the stack
- ScriptStackEntry rec2;
- rec2._name = tempString;
- rec2._currentIndex = 0;
- rec2._select = 100;
- _scriptStack.push(rec2);
- } else {
- error("Script stack overflow");
- }
-
- _scriptMoreFlag = 1;
- _endStr = true;
- _wait = 0;
-
- return RET_SUCCESS;
-}
-
OpcodeReturn ScalpelTalk::cmdClearInfoLine(const byte *&str) {
UserInterface &ui = *_vm->_ui;
@@ -1975,11 +1976,105 @@ TattooTalk::TattooTalk(SherlockEngine *vm) : Talk(vm) {
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
(OpcodeMethod)&TattooTalk::cmdSwitchSpeaker,
+
(OpcodeMethod)&TattooTalk::cmdRunCAnimation,
- // TODO: Implement opcode methods for new Tattoo opcodes
+ (OpcodeMethod)&TattooTalk::cmdCallTalkFile,
+ (OpcodeMethod)&TattooTalk::cmdPause,
+ (OpcodeMethod)&TattooTalk::cmdMouseOnOff,
+ (OpcodeMethod)&TattooTalk::cmdSetWalkControl,
+ (OpcodeMethod)&TattooTalk::cmdAdjustObjectSequence,
+ (OpcodeMethod)&TattooTalk::cmdWalkToCoords,
+ (OpcodeMethod)&TattooTalk::cmdPauseWithoutControl,
+ (OpcodeMethod)&TattooTalk::cmdBanishWindow,
+ (OpcodeMethod)&TattooTalk::cmdSetTalkSequence,
+
+ (OpcodeMethod)&TattooTalk::cmdSetFlag,
+ (OpcodeMethod)&TattooTalk::cmdPlaySong,
+ (OpcodeMethod)&TattooTalk::cmdToggleObject,
+ (OpcodeMethod)&TattooTalk::cmdStealthModeActivate,
+ (OpcodeMethod)&TattooTalk::cmdWalkNPCToCAnimation,
+ (OpcodeMethod)&TattooTalk::cmdWalkNPCToCoords,
+ (OpcodeMethod)&TattooTalk::cmdWalkHomesAndNPCToCoords,
+ (OpcodeMethod)&TattooTalk::cmdStealthModeDeactivate,
+ (OpcodeMethod)&TattooTalk::cmdHolmesOff,
+ (OpcodeMethod)&TattooTalk::cmdHolmesOn,
+
+ (OpcodeMethod)&TattooTalk::cmdGotoScene,
+ (OpcodeMethod)&TattooTalk::cmdSetNPCPathDest,
+ (OpcodeMethod)&TattooTalk::cmdAddItemToInventory,
+ (OpcodeMethod)&TattooTalk::cmdSetObject,
+ (OpcodeMethod)&TattooTalk::cmdNextSong,
+ (OpcodeMethod)&TattooTalk::cmdSetNPCPathPause,
+ (OpcodeMethod)&TattooTalk::cmdPassword,
+ (OpcodeMethod)&TattooTalk::cmdSetSceneEntryFlag,
+ (OpcodeMethod)&TattooTalk::cmdWalkToCAnimation,
+ (OpcodeMethod)&TattooTalk::cmdRemoveItemFromInventory,
+
+ (OpcodeMethod)&TattooTalk::cmdEnableEndKey,
+ (OpcodeMethod)&TattooTalk::cmdDisableEndKey,
+ nullptr,
+ (OpcodeMethod)&TattooTalk::cmdWalkHomesAndNPCToCoords,
+ (OpcodeMethod)&TattooTalk::cmdSetNPCTalkFile,
+ (OpcodeMethod)&TattooTalk::cmdSetNPCOff,
+ (OpcodeMethod)&TattooTalk::cmdSetNPCOn,
+ (OpcodeMethod)&TattooTalk::cmdSetNPCDescOnOff,
+ (OpcodeMethod)&TattooTalk::cmdSetNPCPathPauseTakingNotes,
+ (OpcodeMethod)&TattooTalk::cmdSetNPCPathPauseLookingHolmes,
+
+ (OpcodeMethod)&TattooTalk::cmdTalkInterruptsEnable,
+ (OpcodeMethod)&TattooTalk::cmdTalkInterruptsDisable,
+ (OpcodeMethod)&TattooTalk::cmdSetNPCInfoLine,
+ (OpcodeMethod)&TattooTalk::cmdSetNPCPosition,
+ (OpcodeMethod)&TattooTalk::cmdNPCLabelSet,
+ (OpcodeMethod)&TattooTalk::cmdNPCLabelGoto,
+ (OpcodeMethod)&TattooTalk::cmdNPCLabelIfFlagGoto,
+ (OpcodeMethod)&TattooTalk::cmdSetNPCWalkGraphics,
+ nullptr,
+ (OpcodeMethod)&TattooTalk::cmdSetNPCVerb,
+
+ (OpcodeMethod)&TattooTalk::cmdSetNPCVerbCAnimation,
+ (OpcodeMethod)&TattooTalk::cmdSetNPCVerbScript,
+ nullptr,
+ (OpcodeMethod)&TattooTalk::cmdRestorePeopleSequence,
+ (OpcodeMethod)&TattooTalk::cmdSetNPCVerbTarget,
+ (OpcodeMethod)&TattooTalk::cmdTurnSoundsOff
};
_opcodeTable = OPCODE_METHODS;
}
+OpcodeReturn TattooTalk::cmdMouseOnOff(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdNextSong(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdNPCLabelGoto(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdNPCLabelIfFlagGoto(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdNPCLabelSet(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdPassword(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdPlaySong(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdRestorePeopleSequence(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetNPCDescOnOff(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetNPCInfoLine(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetNPCOff(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetNPCOn(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetNPCPathDest(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetNPCPathPause(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetNPCPathPauseTakingNotes(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetNPCPathPauseLookingHolmes(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetNPCPosition(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetNPCTalkFile(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetNPCVerb(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetNPCVerbCAnimation(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetNPCVerbScript(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetNPCVerbTarget(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetNPCWalkGraphics(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetSceneEntryFlag(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetTalkSequence(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdSetWalkControl(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdTalkInterruptsDisable(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdTalkInterruptsEnable(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdTurnSoundsOff(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdWalkHolmesAndNPCToCAnimation(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdWalkNPCToCAnimation(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdWalkNPCToCoords(const byte *&str) { error("TODO: script opcode"); }
+OpcodeReturn TattooTalk::cmdWalkHomesAndNPCToCoords(const byte *&str) { error("TODO: script opcode"); }
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h
index 02d141d..dc6789c 100644
--- a/engines/sherlock/talk.h
+++ b/engines/sherlock/talk.h
@@ -229,6 +229,7 @@ protected:
OpcodeReturn cmdAddItemToInventory(const byte *&str);
OpcodeReturn cmdAdjustObjectSequence(const byte *&str);
OpcodeReturn cmdBanishWindow(const byte *&str);
+ OpcodeReturn cmdCallTalkFile(const byte *&str);
OpcodeReturn cmdDisableEndKey(const byte *&str);
OpcodeReturn cmdEnableEndKey(const byte *&str);
OpcodeReturn cmdGotoScene(const byte *&str);
@@ -346,7 +347,6 @@ public:
class ScalpelTalk : public Talk {
protected:
OpcodeReturn cmdAssignPortraitLocation(const byte *&str);
- OpcodeReturn cmdCallTalkFile(const byte *&str);
OpcodeReturn cmdClearInfoLine(const byte *&str);
OpcodeReturn cmdClearWindow(const byte *&str);
OpcodeReturn cmdDisplayInfoLine(const byte *&str);
@@ -364,6 +364,40 @@ public:
};
class TattooTalk : public Talk {
+protected:
+ OpcodeReturn cmdMouseOnOff(const byte *&str);
+ OpcodeReturn cmdNextSong(const byte *&str);
+ OpcodeReturn cmdPassword(const byte *&str);
+ OpcodeReturn cmdPlaySong(const byte *&str);
+ OpcodeReturn cmdRestorePeopleSequence(const byte *&str);
+ OpcodeReturn cmdSetNPCDescOnOff(const byte *&str);
+ OpcodeReturn cmdSetNPCInfoLine(const byte *&str);
+ OpcodeReturn cmdNPCLabelGoto(const byte *&str);
+ OpcodeReturn cmdNPCLabelIfFlagGoto(const byte *&str);
+ OpcodeReturn cmdNPCLabelSet(const byte *&str);
+ OpcodeReturn cmdSetNPCOff(const byte *&str);
+ OpcodeReturn cmdSetNPCOn(const byte *&str);
+ OpcodeReturn cmdSetNPCPathDest(const byte *&str);
+ OpcodeReturn cmdSetNPCPathPause(const byte *&str);
+ OpcodeReturn cmdSetNPCPathPauseTakingNotes(const byte *&str);
+ OpcodeReturn cmdSetNPCPathPauseLookingHolmes(const byte *&str);
+ OpcodeReturn cmdSetNPCPosition(const byte *&str);
+ OpcodeReturn cmdSetNPCTalkFile(const byte *&str);
+ OpcodeReturn cmdSetNPCVerb(const byte *&str);
+ OpcodeReturn cmdSetNPCVerbCAnimation(const byte *&str);
+ OpcodeReturn cmdSetNPCVerbScript(const byte *&str);
+ OpcodeReturn cmdSetNPCVerbTarget(const byte *&str);
+ OpcodeReturn cmdSetNPCWalkGraphics(const byte *&str);
+ OpcodeReturn cmdSetSceneEntryFlag(const byte *&str);
+ OpcodeReturn cmdSetTalkSequence(const byte *&str);
+ OpcodeReturn cmdSetWalkControl(const byte *&str);
+ OpcodeReturn cmdTalkInterruptsDisable(const byte *&str);
+ OpcodeReturn cmdTalkInterruptsEnable(const byte *&str);
+ OpcodeReturn cmdTurnSoundsOff(const byte *&str);
+ OpcodeReturn cmdWalkHolmesAndNPCToCAnimation(const byte *&str);
+ OpcodeReturn cmdWalkNPCToCAnimation(const byte *&str);
+ OpcodeReturn cmdWalkNPCToCoords(const byte *&str);
+ OpcodeReturn cmdWalkHomesAndNPCToCoords(const byte *&str);
public:
TattooTalk(SherlockEngine *vm);
virtual ~TattooTalk() {}
Commit: f9a2d091e9d3174b767221ce2f1379a6e86e80d0
https://github.com/scummvm/scummvm/commit/f9a2d091e9d3174b767221ce2f1379a6e86e80d0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-24T21:06:21-04:00
Commit Message:
SHERLOCK: Fix script opcode table lookup
Changed paths:
engines/sherlock/talk.cpp
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index 15b6409..8d553d6 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -1164,7 +1164,7 @@ void Talk::doScript(const Common::String &script) {
// Start of comment, so skip over it
while (*str++ != '}')
;
- } else if (_opcodeTable[c]) {
+ } else if (_opcodeTable[c - 128]) {
// Handle control code
switch ((this->*_opcodeTable[c - 128])(str)) {
case RET_EXIT:
Commit: 5513f725102ad95b748810328a123d7a90ddd24a
https://github.com/scummvm/scummvm/commit/5513f725102ad95b748810328a123d7a90ddd24a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-24T21:28:12-04:00
Commit Message:
SHERLOCK: Implement cmdSetNPCWalkGraphics method
Changed paths:
engines/sherlock/talk.cpp
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index 8d553d6..3e3fcce 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -1164,7 +1164,7 @@ void Talk::doScript(const Common::String &script) {
// Start of comment, so skip over it
while (*str++ != '}')
;
- } else if (_opcodeTable[c - 128]) {
+ } else if (c >= 128 && c <= 227 && _opcodeTable[c - 128]) {
// Handle control code
switch ((this->*_opcodeTable[c - 128])(str)) {
case RET_EXIT:
@@ -1789,7 +1789,14 @@ ScalpelTalk::ScalpelTalk(SherlockEngine *vm) : Talk(vm) {
(OpcodeMethod)&ScalpelTalk::cmdEnableEndKey,
(OpcodeMethod)&ScalpelTalk::cmdDisableEndKey,
- (OpcodeMethod)&ScalpelTalk::cmdCarriageReturn
+ (OpcodeMethod)&ScalpelTalk::cmdCarriageReturn,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
};
_opcodeTable = OPCODE_METHODS;
@@ -2065,7 +2072,29 @@ OpcodeReturn TattooTalk::cmdSetNPCVerb(const byte *&str) { error("TODO: script o
OpcodeReturn TattooTalk::cmdSetNPCVerbCAnimation(const byte *&str) { error("TODO: script opcode"); }
OpcodeReturn TattooTalk::cmdSetNPCVerbScript(const byte *&str) { error("TODO: script opcode"); }
OpcodeReturn TattooTalk::cmdSetNPCVerbTarget(const byte *&str) { error("TODO: script opcode"); }
-OpcodeReturn TattooTalk::cmdSetNPCWalkGraphics(const byte *&str) { error("TODO: script opcode"); }
+
+OpcodeReturn TattooTalk::cmdSetNPCWalkGraphics(const byte *&str) {
+ ++str;
+ int npc = *str - 1;
+ People &people = *_vm->_people;
+ Person &person = people[npc];
+
+ // Build up walk library name for the given NPC
+ person._walkVGSName = "";
+ for (int idx = 0; idx < 8; ++idx) {
+ if (str[idx + 1] != '~')
+ person._walkVGSName += str[idx + 1];
+ else
+ break;
+ }
+ person._walkVGSName += ".VGS";
+
+ people._forceWalkReload = true;
+ str += 8;
+
+ return RET_SUCCESS;
+}
+
OpcodeReturn TattooTalk::cmdSetSceneEntryFlag(const byte *&str) { error("TODO: script opcode"); }
OpcodeReturn TattooTalk::cmdSetTalkSequence(const byte *&str) { error("TODO: script opcode"); }
OpcodeReturn TattooTalk::cmdSetWalkControl(const byte *&str) { error("TODO: script opcode"); }
Commit: 1f9f01c5714930e96eb7713c74fe826fe85d1457
https://github.com/scummvm/scummvm/commit/1f9f01c5714930e96eb7713c74fe826fe85d1457
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-24T21:34:35-04:00
Commit Message:
SHERLOCK: Implement cmdNextSong
Changed paths:
engines/sherlock/talk.cpp
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index 3e3fcce..22e77fb 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -2051,7 +2051,24 @@ TattooTalk::TattooTalk(SherlockEngine *vm) : Talk(vm) {
}
OpcodeReturn TattooTalk::cmdMouseOnOff(const byte *&str) { error("TODO: script opcode"); }
-OpcodeReturn TattooTalk::cmdNextSong(const byte *&str) { error("TODO: script opcode"); }
+
+OpcodeReturn TattooTalk::cmdNextSong(const byte *&str) {
+ Sound &sound = *_vm->_sound;
+
+ // Get the name of the next song to play
+ ++str;
+ sound._nextSongName = "";
+ for (int idx = 0; idx < 8; ++idx) {
+ if (str[idx] != '~')
+ sound._nextSongName += str[idx];
+ else
+ break;
+ }
+ str += 7;
+
+ return RET_SUCCESS;
+}
+
OpcodeReturn TattooTalk::cmdNPCLabelGoto(const byte *&str) { error("TODO: script opcode"); }
OpcodeReturn TattooTalk::cmdNPCLabelIfFlagGoto(const byte *&str) { error("TODO: script opcode"); }
OpcodeReturn TattooTalk::cmdNPCLabelSet(const byte *&str) { error("TODO: script opcode"); }
Commit: 8331fa886f4fa9031de17652632b3a12e1f84f06
https://github.com/scummvm/scummvm/commit/8331fa886f4fa9031de17652632b3a12e1f84f06
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-24T22:33:41-04:00
Commit Message:
SHERLOCK: Fix People data initialization and general start fixes
Changed paths:
engines/sherlock/events.cpp
engines/sherlock/objects.h
engines/sherlock/people.cpp
engines/sherlock/scalpel/scalpel.cpp
engines/sherlock/talk.cpp
diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp
index 94ddc9a..c201507 100644
--- a/engines/sherlock/events.cpp
+++ b/engines/sherlock/events.cpp
@@ -42,6 +42,8 @@ Events::Events(SherlockEngine *vm) {
_pressed = _released = false;
_rightPressed = _rightReleased = false;
_oldButtons = _oldRightButton = false;
+
+ loadCursors("rmouse.vgs");
}
Events::~Events() {
diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h
index f104762..2a0de7f 100644
--- a/engines/sherlock/objects.h
+++ b/engines/sherlock/objects.h
@@ -116,12 +116,43 @@ struct WalkSequence {
void load(Common::SeekableReadStream &s);
};
+enum { REVERSE_DIRECTION = 0x80 };
+#define NAMES_COUNT 4
+
+struct ActionType {
+ int _cAnimNum;
+ int _cAnimSpeed;
+ Common::String _names[NAMES_COUNT];
+
+ /**
+ * Load the data for the action
+ */
+ void load(Common::SeekableReadStream &s);
+};
+
+struct UseType {
+ int _cAnimNum;
+ int _cAnimSpeed;
+ 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, bool isRoseTattoo);
+};
+
+
class Sprite {
private:
static SherlockEngine *_vm;
public:
- Common::String _name;
- Common::String _description;
+ Common::String _name;
+ Common::String _description;
Common::String _examine; // Examine in-depth description
Common::String _pickUp; // Message for if you can't pick up object
@@ -142,73 +173,69 @@ public:
int _status; // Status: open/closed, moved/not moved
int8 _misc; // Miscellaneous use
int _numFrames; // How many frames the object has
- ImageFile *_altImages;
- bool _altSequences;
+
+ // Rose Tattoo fields
+ int _startSeq; // Frame sequence starts at
+ int _flags; // Flags for the sprite
+ int _aType; // Tells if this is an object, person, talk, etc.
+ int _lookFrames; // How many frames to play of a canim before pausing
+ int _seqCounter; // How many times the sequence has been run
+ Common::Point _lookPosition; // Where to look when examining object
+ int _lookFacing; // Direction to face when examining object
+ int _lookCAnim;
+ int _seqStack; // Allow 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 description text for scene
+ int _seqCounter2; // Counter of calling frame sequence
+ uint _seqSize; // Size of sequence
+ UseType _use[6];
+ int _quickDraw; // Flag telling whether to use quick draw routine or not
+ int _scaleVal; // Tells how to scale the sprite
+ int _requiredFlags1; // This flag must also be set, or the sprite is hidden
+ int _gotoSeq; // Used by Talk to tell which sequence to goto when able
+ int _talkSeq; // Tells which talk sequence currently in use (Talk or Listen)
+ int _restoreSlot; // Used when talk returns to the previous sequence
+
ImageFrame *_stopFrames[8]; // Stop/rest frame for each direction
+ ImageFile *_altImages; // Images used for alternate NPC sequences
+ bool _altSequences; // Which of the sequences the alt graphics apply to (0: main, 1=NPC seq)
+ int _centerWalk; // Flag telling the walk code to offset the walk destination
+ Common::Point _adjust; // Fine tuning adjustment to position when drawn
+ int _oldWalkSequence;
public:
Sprite() { clear(); }
static void setVm(SherlockEngine *vm) { _vm = vm; }
/**
- * Reset the data for the sprite
- */
+ * Reset the data for the sprite
+ */
void clear();
/**
- * Updates the image frame poiner for the sprite
- */
+ * Updates the image frame poiner for the sprite
+ */
void setImageFrame();
/**
- * This adjusts the sprites position, as well as it's animation sequence:
- */
+ * This adjusts the sprites position, as well as it's animation sequence:
+ */
void adjustSprite();
/**
- * Checks the sprite's position to see if it's collided with any special objects
- */
+ * Checks the sprite's position to see if it's collided with any special objects
+ */
void checkSprite();
/**
- * Return frame width
- */
+ * Return frame width
+ */
int frameWidth() const { return _imageFrame ? _imageFrame->_frame.w : 0; }
-
- /**
- * Return frame height
- */
- int frameHeight() const { return _imageFrame ? _imageFrame->_frame.h : 0; }
-};
-
-enum { REVERSE_DIRECTION = 0x80 };
-#define NAMES_COUNT 4
-
-struct ActionType {
- int _cAnimNum;
- int _cAnimSpeed;
- Common::String _names[NAMES_COUNT];
-
- /**
- * Load the data for the action
- */
- void load(Common::SeekableReadStream &s);
-};
-
-struct UseType {
- int _cAnimNum;
- int _cAnimSpeed;
- 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, bool isRoseTattoo);
+ * Return frame height
+ */
+ int frameHeight() const { return _imageFrame ? _imageFrame->_frame.h : 0; }
};
enum { OBJ_BEHIND = 1, OBJ_FLIPPED = 2, OBJ_FORWARD = 4, TURNON_OBJ = 0x20, TURNOFF_OBJ = 0x40 };
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp
index 7879f29..c03dde8 100644
--- a/engines/sherlock/people.cpp
+++ b/engines/sherlock/people.cpp
@@ -124,36 +124,55 @@ People::~People() {
}
void People::reset() {
- // Note: The engine has theoretical support for two player characters but only the first one is used.
- // Watson is, instead, handled by a different sprite in each scene, with a very simple initial movement, if any
- Sprite &p = _data[PLAYER];
-
- p._description = "Sherlock Holmes!";
- p._type = CHARACTER;
- p._position = Common::Point(10000, 11000);
- p._sequenceNumber = STOP_DOWNRIGHT;
- p._imageFrame = nullptr;
- p._frameNumber = 1;
- p._delta = Common::Point(0, 0);
- p._oldPosition = Common::Point(0, 0);
- p._oldSize = Common::Point(0, 0);
- p._misc = 0;
- p._walkCount = 0;
- p._pickUp = "";
- p._allow = 0;
- p._noShapeSize = Common::Point(0, 0);
- p._goto = Common::Point(0, 0);
- p._status = 0;
-
- // Load the default walk sequences
- p._walkSequences.resize(MAX_HOLMES_SEQUENCE);
- for (int idx = 0; idx < MAX_HOLMES_SEQUENCE; ++idx) {
- p._walkSequences[idx]._sequences.clear();
-
- const byte *pSrc = &CHARACTER_SEQUENCES[idx][0];
- do {
- p._walkSequences[idx]._sequences.push_back(*pSrc);
- } while (*pSrc++);
+ _data[0]._description = "Sherlock Holmes!";
+
+ // Note: Serrated Scalpel only uses a single Person slot for Sherlock.. Watson is handled by scene sprites
+ int count = IS_SERRATED_SCALPEL ? 1 : MAX_PLAYERS;
+ for (int idx = 0; idx < count; ++idx) {
+ Sprite &p = _data[idx];
+
+ p._type = (idx == 0) ? CHARACTER : INVALID;
+ if (IS_SERRATED_SCALPEL)
+ p._position = Point32(10000, 11000);
+ else
+ p._position = Point32(36000, 29000);
+
+ p._sequenceNumber = STOP_DOWNRIGHT;
+ p._imageFrame = nullptr;
+ p._frameNumber = 1;
+ p._delta = Common::Point(0, 0);
+ p._oldPosition = Common::Point(0, 0);
+ p._oldSize = Common::Point(0, 0);
+ p._misc = 0;
+ p._walkCount = 0;
+ p._pickUp = "";
+ p._allow = 0;
+ p._noShapeSize = Common::Point(0, 0);
+ p._goto = Common::Point(0, 0);
+ p._status = 0;
+ p._seqTo = 0;
+ p._seqCounter = p._seqCounter2 = 0;
+ p._seqStack = 0;
+ p._gotoSeq = p._talkSeq = 0;
+ p._restoreSlot = 0;
+ p._startSeq = 0;
+ p._walkSequences.clear();
+ p._altImages = nullptr;
+ p._altSequences = 0;
+ p._centerWalk = true;
+ p._adjust = Common::Point(0, 0);
+
+ // Load the default walk sequences
+ p._oldWalkSequence = -1;
+ p._walkSequences.resize(MAX_HOLMES_SEQUENCE);
+ for (int idx = 0; idx < MAX_HOLMES_SEQUENCE; ++idx) {
+ p._walkSequences[idx]._sequences.clear();
+
+ const byte *pSrc = &CHARACTER_SEQUENCES[idx][0];
+ do {
+ p._walkSequences[idx]._sequences.push_back(*pSrc);
+ } while (*pSrc++);
+ }
}
// Reset any walk path in progress when Sherlock leaves scenes
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index 2a107b4..6b72188 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -813,7 +813,6 @@ void ScalpelEngine::startScene() {
break;
}
- _events->loadCursors("rmouse.vgs");
_events->setCursor(ARROW);
if (_scene->_goToScene == 99) {
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index 22e77fb..e3f8c7b 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -1577,12 +1577,20 @@ OpcodeReturn Talk::cmdGotoScene(const byte *&str) {
}
OpcodeReturn Talk::cmdHolmesOff(const byte *&str) {
- _vm->_people->_holmesOn = false;
+ People &people = *_vm->_people;
+ people._holmesOn = false;
+ if (IS_ROSE_TATTOO)
+ people[PLAYER]._type = REMOVE;
+
return RET_SUCCESS;
}
OpcodeReturn Talk::cmdHolmesOn(const byte *&str) {
- _vm->_people->_holmesOn = true;
+ People &people = *_vm->_people;
+ people._holmesOn = true;
+ if (IS_ROSE_TATTOO)
+ people[PLAYER]._type = CHARACTER;
+
return RET_SUCCESS;
}
Commit: ef4d8be853cf681f3c58db6daec78209982e5f5a
https://github.com/scummvm/scummvm/commit/ef4d8be853cf681f3c58db6daec78209982e5f5a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-24T23:15:33-04:00
Commit Message:
SHERLOCK: Fix display of first RT scene background
Changed paths:
engines/sherlock/scene.cpp
engines/sherlock/screen.cpp
engines/sherlock/sherlock.cpp
engines/sherlock/user_interface.cpp
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 0f679d7..0b4cd4e 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -615,8 +615,12 @@ bool Scene::loadScene(const Common::String &filename) {
if (!_vm->isDemo()) {
// Reset the previous map location and position on overhead map
map._oldCharPoint = _currentScene;
- map._overPos.x = map[_currentScene].x * 100 - 600;
- map._overPos.y = map[_currentScene].y * 100 + 900;
+
+ if (IS_SERRATED_SCALPEL) {
+ map._overPos.x = map[_currentScene].x * 100 - 600;
+ map._overPos.y = map[_currentScene].y * 100 + 900;
+
+ }
}
events.clearEvents();
diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp
index bb9dbd7..4dd91cf 100644
--- a/engines/sherlock/screen.cpp
+++ b/engines/sherlock/screen.cpp
@@ -182,6 +182,7 @@ void Screen::randomTransition() {
Events &events = *_vm->_events;
const int TRANSITION_MULTIPLIER = 0x15a4e35;
_dirtyRects.clear();
+ assert(IS_SERRATED_SCALPEL);
for (int idx = 0; idx <= 65535 && !_vm->shouldQuit(); ++idx) {
_transitionSeed = _transitionSeed * TRANSITION_MULTIPLIER + 1;
diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp
index 14f2433..497841f 100644
--- a/engines/sherlock/sherlock.cpp
+++ b/engines/sherlock/sherlock.cpp
@@ -207,7 +207,9 @@ void SherlockEngine::loadConfig() {
ConfMan.registerDefault("font", 1);
_screen->setFont(ConfMan.getInt("font"));
- _screen->_fadeStyle = ConfMan.getBool("fade_style");
+ if (getGameID() == GType_SerratedScalpel)
+ _screen->_fadeStyle = ConfMan.getBool("fade_style");
+
_ui->_helpStyle = ConfMan.getBool("help_style");
_ui->_slideWindows = ConfMan.getBool("window_style");
_people->_portraitsOn = ConfMan.getBool("portraits_on");
diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp
index 7a6722a..4f83e91 100644
--- a/engines/sherlock/user_interface.cpp
+++ b/engines/sherlock/user_interface.cpp
@@ -2304,6 +2304,7 @@ TattooUserInterface::TattooUserInterface(SherlockEngine *vm): UserInterface(vm)
void TattooUserInterface::handleInput() {
// TODO
+ _vm->_events->pollEventsAndWait();
}
} // End of namespace Sherlock
Commit: 40afa013696a5cebd88c3fd566175ca001d6f310
https://github.com/scummvm/scummvm/commit/40afa013696a5cebd88c3fd566175ca001d6f310
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-24T23:38:23-04:00
Commit Message:
SHERLOCK: Fix palette for RT scene
Changed paths:
engines/sherlock/scene.cpp
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 0b4cd4e..989927b 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -321,7 +321,8 @@ bool Scene::loadScene(const Common::String &filename) {
if (IS_ROSE_TATTOO) {
screen.initPaletteFade(bgHeader._bytesWritten);
- screen.fadeRead(*rrmStream, screen._cMap, PALETTE_SIZE);
+ rrmStream->read(screen._cMap, PALETTE_SIZE);
+ screen.translatePalette(screen._cMap);
screen.setupBGArea(screen._cMap);
screen.initScrollVars();
Commit: bcb8c02ba178b79b8352bb58f38f429f7f39928c
https://github.com/scummvm/scummvm/commit/bcb8c02ba178b79b8352bb58f38f429f7f39928c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-25T08:21:57-04:00
Commit Message:
SHERLOCK: Free freeing and resetting People list
Changed paths:
engines/sherlock/objects.cpp
engines/sherlock/people.cpp
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index 0709f6b..31a209f 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -73,11 +73,16 @@ void Sprite::setImageFrame() {
int imageNumber = _walkSequences[_sequenceNumber][frameNum];
if (IS_SERRATED_SCALPEL)
- imageNumber = imageNumber + +_walkSequences[_sequenceNumber][0] - 2;
+ imageNumber = imageNumber + _walkSequences[_sequenceNumber][0] - 2;
else if (imageNumber > _numFrames)
imageNumber = 1;
- _imageFrame = &(_altSequences ? *_altImages : *_images)[imageNumber];
+ // Get the images to use
+ ImageFile *images = _altSequences ? _altImages : _images;
+ assert(images);
+
+ // Set the frame pointer
+ _imageFrame = &(*images)[imageNumber];
}
void Sprite::adjustSprite() {
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp
index c03dde8..083e3c8 100644
--- a/engines/sherlock/people.cpp
+++ b/engines/sherlock/people.cpp
@@ -164,14 +164,17 @@ void People::reset() {
// Load the default walk sequences
p._oldWalkSequence = -1;
- p._walkSequences.resize(MAX_HOLMES_SEQUENCE);
- for (int idx = 0; idx < MAX_HOLMES_SEQUENCE; ++idx) {
- p._walkSequences[idx]._sequences.clear();
-
- const byte *pSrc = &CHARACTER_SEQUENCES[idx][0];
- do {
- p._walkSequences[idx]._sequences.push_back(*pSrc);
- } while (*pSrc++);
+
+ if (IS_SERRATED_SCALPEL) {
+ p._walkSequences.resize(MAX_HOLMES_SEQUENCE);
+ for (int seqIdx = 0; seqIdx < MAX_HOLMES_SEQUENCE; ++seqIdx) {
+ p._walkSequences[seqIdx]._sequences.clear();
+
+ const byte *pSrc = &CHARACTER_SEQUENCES[seqIdx][0];
+ do {
+ p._walkSequences[seqIdx]._sequences.push_back(*pSrc);
+ } while (*pSrc++);
+ }
}
}
@@ -259,6 +262,8 @@ bool People::freeWalk() {
if (_data[idx]._walkLoaded) {
delete _data[idx]._images;
_data[idx]._images = nullptr;
+
+ _data[idx]._walkLoaded = false;
result = true;
}
}
Commit: 1a1010f0ab4164bb615283f9c332afbf97f702ca
https://github.com/scummvm/scummvm/commit/1a1010f0ab4164bb615283f9c332afbf97f702ca
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-25T11:04:34-04:00
Commit Message:
SHERLOCK: Cleanup of checkBgShapes and updateBackground
Changed paths:
engines/sherlock/people.cpp
engines/sherlock/people.h
engines/sherlock/scene.cpp
engines/sherlock/scene.h
engines/sherlock/sherlock.h
engines/sherlock/talk.cpp
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp
index 083e3c8..bac147f 100644
--- a/engines/sherlock/people.cpp
+++ b/engines/sherlock/people.cpp
@@ -114,7 +114,7 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) {
}
People::~People() {
- for (int idx = 0; idx < MAX_PLAYERS; ++idx) {
+ for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
if (_data[idx]._walkLoaded)
delete _data[PLAYER]._images;
}
@@ -127,7 +127,7 @@ void People::reset() {
_data[0]._description = "Sherlock Holmes!";
// Note: Serrated Scalpel only uses a single Person slot for Sherlock.. Watson is handled by scene sprites
- int count = IS_SERRATED_SCALPEL ? 1 : MAX_PLAYERS;
+ int count = IS_SERRATED_SCALPEL ? 1 : MAX_CHARACTERS;
for (int idx = 0; idx < count; ++idx) {
Sprite &p = _data[idx];
@@ -197,7 +197,7 @@ bool People::loadWalk() {
result = true;
}
} else {
- for (int idx = 0; idx < MAX_PLAYERS; ++idx) {
+ for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
if (!_data[idx]._walkLoaded && (_data[idx]._type == CHARACTER || _data[idx]._type == HIDDEN_CHARACTER)) {
if (_data[idx]._type == HIDDEN_CHARACTER)
_data[idx]._type = INVALID;
@@ -258,7 +258,7 @@ bool People::loadWalk() {
bool People::freeWalk() {
bool result = false;
- for (int idx = 0; idx < MAX_PLAYERS; ++idx) {
+ for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
if (_data[idx]._walkLoaded) {
delete _data[idx]._images;
_data[idx]._images = nullptr;
@@ -700,7 +700,7 @@ void People::synchronize(Common::Serializer &s) {
s.syncAsSint16LE(_player._position.y);
s.syncAsSint16LE(_player._sequenceNumber);
} else {
- for (int idx = 0; idx < MAX_PLAYERS; ++idx) {
+ for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
Person &p = _data[idx];
s.syncAsSint16LE(p._position.x);
s.syncAsSint16LE(p._position.y);
diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h
index a196878..72bdc51 100644
--- a/engines/sherlock/people.h
+++ b/engines/sherlock/people.h
@@ -34,7 +34,7 @@ enum PeopleId {
PLAYER = 0,
AL = 0,
PEG = 1,
- MAX_PLAYERS = 6,
+ MAX_CHARACTERS = 6,
MAX_NPC = 5,
MAX_NPC_PATH = 200
};
@@ -92,7 +92,7 @@ class SherlockEngine;
class People {
private:
SherlockEngine *_vm;
- Person _data[MAX_PLAYERS];
+ Person _data[MAX_CHARACTERS];
int _oldWalkSequence;
int _srcZone, _destZone;
public:
@@ -120,20 +120,15 @@ public:
~People();
Person &operator[](PeopleId id) {
- assert(id < MAX_PLAYERS);
+ assert(id < MAX_CHARACTERS);
return _data[id];
}
Person &operator[](int idx) {
- assert(idx < MAX_PLAYERS);
+ assert(idx < MAX_CHARACTERS);
return _data[idx];
}
/**
- * Returns true if Sherlock is visible on the screen and enabled
- */
- bool isHolmesActive() const { return _data[0]._walkLoaded && _holmesOn; }
-
- /**
* Reset the player data
*/
void reset();
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 989927b..d7519d5 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -833,11 +833,14 @@ void Scene::transitionToScene() {
updateBackground();
+ // Actually do the transition
if (screen._fadeStyle)
screen.randomTransition();
else
screen.blitFrom(screen._backBuffer1);
+ screen.update();
+ // Start any initial animation for the scene
if (cAnimNum != -1) {
CAnim &c = _cAnim[cAnimNum];
Common::Point pt = c._goto;
@@ -865,19 +868,26 @@ int Scene::toggleObject(const Common::String &name) {
void Scene::updateBackground() {
People &people = *_vm->_people;
- Screen &screen = *_vm->_screen;
- Sprite &player = people[AL];
-
- // Restrict drawing window
- screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
// Update Holmes if he's turned on
- if (people._holmesOn)
- player.adjustSprite();
+ for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
+ if (people[idx]._type == CHARACTER)
+ people[idx].adjustSprite();
+ }
// Flag the bg shapes which need to be redrawn
- checkBgShapes(player._imageFrame, Common::Point(player._position.x / 100,
- player._position.y / 100));
+ checkBgShapes();
+
+ // Draw the shapes for the scene
+ drawAllShapes();
+}
+
+void Scene::drawAllShapes() {
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
+
+ // Restrict drawing window
+ screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
// Draw all active shapes which are behind the person
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
@@ -889,7 +899,7 @@ void Scene::updateBackground() {
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
if (_canimShapes[idx]._type == ACTIVE_BG_SHAPE && _canimShapes[idx]._misc == BEHIND)
screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame,
- _canimShapes[idx]._position, _canimShapes[idx]._flags & OBJ_FLIPPED);
+ _canimShapes[idx]._position, _canimShapes[idx]._flags & OBJ_FLIPPED);
}
// Draw all active shapes which are normal and behind the person
@@ -902,33 +912,37 @@ void Scene::updateBackground() {
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
if (_canimShapes[idx]._type == ACTIVE_BG_SHAPE && _canimShapes[idx]._misc == NORMAL_BEHIND)
screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position,
- _canimShapes[idx]._flags & OBJ_FLIPPED);
+ _canimShapes[idx]._flags & OBJ_FLIPPED);
}
- // Draw the player if he's active
- if (player._type == CHARACTER && people.isHolmesActive()) {
- bool flipped = player._sequenceNumber == WALK_LEFT || player._sequenceNumber == STOP_LEFT ||
- player._sequenceNumber == WALK_UPLEFT || player._sequenceNumber == STOP_UPLEFT ||
- player._sequenceNumber == WALK_DOWNRIGHT || player._sequenceNumber == STOP_DOWNRIGHT;
+ // Draw any active characters
+ for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
+ Person &p = people[idx];
+ if (p._type == CHARACTER && p._walkLoaded) {
+ bool flipped = IS_SERRATED_SCALPEL && (
+ p._sequenceNumber == WALK_LEFT || p._sequenceNumber == STOP_LEFT ||
+ p._sequenceNumber == WALK_UPLEFT || p._sequenceNumber == STOP_UPLEFT ||
+ p._sequenceNumber == WALK_DOWNRIGHT || p._sequenceNumber == STOP_DOWNRIGHT);
- screen._backBuffer->transBlitFrom(*player._imageFrame, Common::Point(player._position.x / 100,
- player._position.y / 100 - player.frameHeight()), flipped);
+ screen._backBuffer->transBlitFrom(*p._imageFrame, Common::Point(p._position.x / 100,
+ p._position.y / 100 - p.frameHeight()), flipped);
+ }
}
// Draw all static and active shapes that are NORMAL and are in front of the player
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) &&
- _bgShapes[idx]._misc == NORMAL_FORWARD)
+ _bgShapes[idx]._misc == NORMAL_FORWARD)
screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position,
- _bgShapes[idx]._flags & OBJ_FLIPPED);
+ _bgShapes[idx]._flags & OBJ_FLIPPED);
}
// Draw all static and active canimations that are NORMAL and are in front of the player
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
if ((_canimShapes[idx]._type == ACTIVE_BG_SHAPE || _canimShapes[idx]._type == STATIC_BG_SHAPE) &&
- _canimShapes[idx]._misc == NORMAL_FORWARD)
+ _canimShapes[idx]._misc == NORMAL_FORWARD)
screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position,
- _canimShapes[idx]._flags & OBJ_FLIPPED);
+ _canimShapes[idx]._flags & OBJ_FLIPPED);
}
// Draw all static and active shapes that are FORWARD
@@ -938,9 +952,9 @@ void Scene::updateBackground() {
_bgShapes[idx].frameHeight());
if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) &&
- _bgShapes[idx]._misc == FORWARD)
+ _bgShapes[idx]._misc == FORWARD)
screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position,
- _bgShapes[idx]._flags & OBJ_FLIPPED);
+ _bgShapes[idx]._flags & OBJ_FLIPPED);
}
// Draw all static and active canimations that are forward
@@ -948,7 +962,7 @@ void Scene::updateBackground() {
if ((_canimShapes[idx]._type == ACTIVE_BG_SHAPE || _canimShapes[idx]._type == STATIC_BG_SHAPE) &&
_canimShapes[idx]._misc == FORWARD)
screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position,
- _canimShapes[idx]._flags & OBJ_FLIPPED);
+ _canimShapes[idx]._flags & OBJ_FLIPPED);
}
screen.resetDisplayBounds();
@@ -963,7 +977,11 @@ Exit *Scene::checkForExit(const Common::Rect &r) {
return nullptr;
}
-void Scene::checkBgShapes(ImageFrame *frame, const Common::Point &pt) {
+void Scene::checkBgShapes() {
+ People &people = *_vm->_people;
+ Person &holmes = people._player;
+ Common::Point pt(holmes._position.x / 100, holmes._position.y / 100);
+
// Iterate through the shapes
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &obj = _bgShapes[idx];
@@ -986,11 +1004,9 @@ void Scene::checkBgShapes(ImageFrame *frame, const Common::Point &pt) {
if ((obj._flags & 5) == 1) {
obj._misc = (pt.y < (obj._position.y + obj._imageFrame->_frame.h - 1)) ?
NORMAL_FORWARD : NORMAL_BEHIND;
- }
- else if (!(obj._flags & 1)) {
+ } else if (!(obj._flags & 1)) {
obj._misc = BEHIND;
- }
- else if (obj._flags & 4) {
+ } else if (obj._flags & 4) {
obj._misc = FORWARD;
}
}
@@ -1345,8 +1361,7 @@ void Scene::doBgAnim() {
people[AL].adjustSprite();
// Flag the bg shapes which need to be redrawn
- checkBgShapes(people[AL]._imageFrame,
- Common::Point(people[AL]._position.x / 100, people[AL]._position.y / 100));
+ checkBgShapes();
if (_currentScene == 12 && IS_SERRATED_SCALPEL)
((Scalpel::ScalpelEngine *)_vm)->doMirror12();
@@ -1382,7 +1397,7 @@ void Scene::doBgAnim() {
}
// Draw the person if not animating
- if (people[AL]._type == CHARACTER && people.isHolmesActive()) {
+ if (people[AL]._type == CHARACTER && people[AL]._walkLoaded) {
// If Holmes is too far to the right, move him back so he's on-screen
int xRight = SHERLOCK_SCREEN_WIDTH - 2 - people[AL]._imageFrame->_frame.w;
int tempX = MIN(people[AL]._position.x / 100, xRight);
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index b0b5624..8067268 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -184,7 +184,7 @@ private:
* it will flag it as needing to be drawn. If a non-animating shape is
* colliding with another shape, it will also flag it as needing drawing
*/
- void checkBgShapes(ImageFrame *frame, const Common::Point &pt);
+ void checkBgShapes();
/**
* Restores objects to the correct status. This ensures that things like being opened or moved
@@ -192,6 +192,10 @@ private:
*/
void saveSceneStatus();
+ /**
+ * Draw all the shapes, people and NPCs in the correct order
+ */
+ void drawAllShapes();
public:
int _currentScene;
int _goToScene;
diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h
index bf8c0d6..467f20e 100644
--- a/engines/sherlock/sherlock.h
+++ b/engines/sherlock/sherlock.h
@@ -60,7 +60,7 @@ enum GameType {
#define SHERLOCK_SCREEN_WIDTH _vm->_screen->w()
#define SHERLOCK_SCREEN_HEIGHT _vm->_screen->h()
-#define SHERLOCK_SCENE_HEIGHT 138
+#define SHERLOCK_SCENE_HEIGHT (IS_SERRATED_SCALPEL ? 138 : 480)
struct SherlockGameDescription;
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index e3f8c7b..b4be5ee 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -1578,18 +1578,14 @@ OpcodeReturn Talk::cmdGotoScene(const byte *&str) {
OpcodeReturn Talk::cmdHolmesOff(const byte *&str) {
People &people = *_vm->_people;
- people._holmesOn = false;
- if (IS_ROSE_TATTOO)
- people[PLAYER]._type = REMOVE;
+ people[PLAYER]._type = REMOVE;
return RET_SUCCESS;
}
OpcodeReturn Talk::cmdHolmesOn(const byte *&str) {
People &people = *_vm->_people;
- people._holmesOn = true;
- if (IS_ROSE_TATTOO)
- people[PLAYER]._type = CHARACTER;
+ people[PLAYER]._type = CHARACTER;
return RET_SUCCESS;
}
Commit: e1e39ea3d2e358b47fc26cc52244f536ee2a0a01
https://github.com/scummvm/scummvm/commit/e1e39ea3d2e358b47fc26cc52244f536ee2a0a01
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-25T23:07:11-04:00
Commit Message:
SHERLOCK: Add define for fixed integer multiplier
Changed paths:
engines/sherlock/objects.h
engines/sherlock/scene.cpp
diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h
index 2a0de7f..7fe44c0 100644
--- a/engines/sherlock/objects.h
+++ b/engines/sherlock/objects.h
@@ -76,6 +76,7 @@ enum {
#define MAX_HOLMES_SEQUENCE 16
#define MAX_FRAME 30
+#define FIXED_INT_MULTIPLIER 100
// code put into sequences to defines 1-10 type seqs
#define SEQ_TO_CODE 67
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index d7519d5..a1a165e 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -200,8 +200,8 @@ void Scene::selectScene() {
_tempFadeStyle = 0;
}
- people._walkDest = Common::Point(people[AL]._position.x / 100,
- people[AL]._position.y / 100);
+ people._walkDest = Common::Point(people[AL]._position.x / FIXED_INT_MULTIPLIER,
+ people[AL]._position.y / FIXED_INT_MULTIPLIER);
_restoreFlag = true;
events.clearEvents();
@@ -618,8 +618,8 @@ bool Scene::loadScene(const Common::String &filename) {
map._oldCharPoint = _currentScene;
if (IS_SERRATED_SCALPEL) {
- map._overPos.x = map[_currentScene].x * 100 - 600;
- map._overPos.y = map[_currentScene].y * 100 + 900;
+ map._overPos.x = (map[_currentScene].x - 6) * FIXED_INT_MULTIPLIER;
+ map._overPos.y = (map[_currentScene].y + 9) * FIXED_INT_MULTIPLIER;
}
}
@@ -761,8 +761,8 @@ void Scene::transitionToScene() {
// Otherwise, this is a linked scene or entrance info, and must be translated
if (hSavedFacing < 8 && !saves._justLoaded) {
hSavedFacing = FS_TRANS[hSavedFacing];
- hSavedPos.x *= 100;
- hSavedPos.y *= 100;
+ hSavedPos.x *= FIXED_INT_MULTIPLIER;
+ hSavedPos.y *= FIXED_INT_MULTIPLIER;
}
}
@@ -802,7 +802,8 @@ void Scene::transitionToScene() {
}
if (Common::Rect(topLeft.x, topLeft.y, bottomRight.x, bottomRight.y).contains(
- Common::Point(people[PLAYER]._position.x / 100, people[PLAYER]._position.y / 100))) {
+ Common::Point(people[PLAYER]._position.x / FIXED_INT_MULTIPLIER,
+ people[PLAYER]._position.y / FIXED_INT_MULTIPLIER))) {
// Current point is already inside box - impact occurred on
// a previous call. So simply do nothing except talk until the
// player is clear of the box
@@ -924,8 +925,8 @@ void Scene::drawAllShapes() {
p._sequenceNumber == WALK_UPLEFT || p._sequenceNumber == STOP_UPLEFT ||
p._sequenceNumber == WALK_DOWNRIGHT || p._sequenceNumber == STOP_DOWNRIGHT);
- screen._backBuffer->transBlitFrom(*p._imageFrame, Common::Point(p._position.x / 100,
- p._position.y / 100 - p.frameHeight()), flipped);
+ screen._backBuffer->transBlitFrom(*p._imageFrame, Common::Point(p._position.x / FIXED_INT_MULTIPLIER,
+ p._position.y / FIXED_INT_MULTIPLIER - p.frameHeight()), flipped);
}
}
@@ -980,7 +981,7 @@ Exit *Scene::checkForExit(const Common::Rect &r) {
void Scene::checkBgShapes() {
People &people = *_vm->_people;
Person &holmes = people._player;
- Common::Point pt(holmes._position.x / 100, holmes._position.y / 100);
+ Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
// Iterate through the shapes
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
@@ -1400,13 +1401,13 @@ void Scene::doBgAnim() {
if (people[AL]._type == CHARACTER && people[AL]._walkLoaded) {
// If Holmes is too far to the right, move him back so he's on-screen
int xRight = SHERLOCK_SCREEN_WIDTH - 2 - people[AL]._imageFrame->_frame.w;
- int tempX = MIN(people[AL]._position.x / 100, xRight);
+ int tempX = MIN(people[AL]._position.x / FIXED_INT_MULTIPLIER, xRight);
bool flipped = people[AL]._sequenceNumber == WALK_LEFT || people[AL]._sequenceNumber == STOP_LEFT ||
people[AL]._sequenceNumber == WALK_UPLEFT || people[AL]._sequenceNumber == STOP_UPLEFT ||
people[AL]._sequenceNumber == WALK_DOWNRIGHT || people[AL]._sequenceNumber == STOP_DOWNRIGHT;
screen._backBuffer->transBlitFrom(*people[AL]._imageFrame,
- Common::Point(tempX, people[AL]._position.y / 100 - people[AL]._imageFrame->_frame.h), flipped);
+ Common::Point(tempX, people[AL]._position.y / FIXED_INT_MULTIPLIER - people[AL]._imageFrame->_frame.h), flipped);
}
// Draw all static and active shapes are NORMAL and are in front of the person
@@ -1466,8 +1467,8 @@ void Scene::doBgAnim() {
people[AL]._type = INVALID;
} else {
screen.flushImage(people[AL]._imageFrame,
- Common::Point(people[AL]._position.x / 100,
- people[AL]._position.y / 100 - people[AL].frameHeight()),
+ Common::Point(people[AL]._position.x / FIXED_INT_MULTIPLIER,
+ people[AL]._position.y / FIXED_INT_MULTIPLIER - people[AL].frameHeight()),
&people[AL]._oldPosition.x, &people[AL]._oldPosition.y,
&people[AL]._oldSize.x, &people[AL]._oldSize.y);
}
Commit: 0cc79979fc27a097037ca580dda78607080d5ac4
https://github.com/scummvm/scummvm/commit/0cc79979fc27a097037ca580dda78607080d5ac4
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-26T08:18:50-04:00
Commit Message:
SHERLOCK: Fix map display
Changed paths:
engines/sherlock/map.cpp
engines/sherlock/map.h
engines/sherlock/objects.cpp
engines/sherlock/objects.h
engines/sherlock/people.cpp
engines/sherlock/people.h
diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp
index 4f034d8..ffbca3f 100644
--- a/engines/sherlock/map.cpp
+++ b/engines/sherlock/map.cpp
@@ -293,7 +293,6 @@ void Map::setupSprites() {
p._type = CHARACTER;
p._position = Common::Point(12400, 5000);
p._sequenceNumber = 0;
- p._walkSequences = _walkSequences;
p._images = _shapes;
p._imageFrame = nullptr;
p._frameNumber = 0;
@@ -306,8 +305,8 @@ void Map::setupSprites() {
p._noShapeSize = Common::Point(0, 0);
p._goto = Common::Point(28000, 15000);
p._status = 0;
+ p._walkSequences = _walkSequences;
p.setImageFrame();
-
scene._bgShapes.clear();
}
diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h
index 198b31e..e0c7d03 100644
--- a/engines/sherlock/map.h
+++ b/engines/sherlock/map.h
@@ -76,7 +76,7 @@ private:
ImageFile *_mapCursors;
ImageFile *_shapes;
ImageFile *_iconShapes;
- Common::Array<WalkSequence> _walkSequences;
+ WalkSequences _walkSequences;
Point32 _lDrawnPos;
int _point;
bool _placesShown;
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index 31a209f..7338726 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -366,6 +366,34 @@ void Sprite::checkSprite() {
/*----------------------------------------------------------------*/
+void WalkSequence::load(Common::SeekableReadStream &s) {
+ char buffer[9];
+ s.read(buffer, 9);
+ _vgsName = Common::String(buffer);
+ _horizFlip = s.readByte() != 0;
+
+ _sequences.resize(s.readUint16LE());
+ s.read(&_sequences[0], _sequences.size());
+}
+
+/*----------------------------------------------------------------*/
+
+WalkSequences &WalkSequences::operator=(const WalkSequences &src) {
+ resize(src.size());
+ for (uint idx = 0; idx < size(); ++idx) {
+ const WalkSequence &wSrc = src[idx];
+ WalkSequence &wDest = (*this)[idx];
+ wDest._horizFlip = wSrc._horizFlip;
+
+ wDest._sequences.resize(wSrc._sequences.size());
+ Common::copy(&wSrc._sequences[0], &wSrc._sequences[0] + wSrc._sequences.size(), &wDest._sequences[0]);
+ }
+
+ return *this;
+}
+
+/*----------------------------------------------------------------*/
+
void ActionType::load(Common::SeekableReadStream &s) {
char buffer[12];
diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h
index 7fe44c0..99746c9 100644
--- a/engines/sherlock/objects.h
+++ b/engines/sherlock/objects.h
@@ -117,6 +117,11 @@ struct WalkSequence {
void load(Common::SeekableReadStream &s);
};
+class WalkSequences : public Common::Array < WalkSequence > {
+public:
+ WalkSequences &operator=(const WalkSequences &src);
+};
+
enum { REVERSE_DIRECTION = 0x80 };
#define NAMES_COUNT 4
@@ -157,7 +162,7 @@ public:
Common::String _examine; // Examine in-depth description
Common::String _pickUp; // Message for if you can't pick up object
- Common::Array<WalkSequence> _walkSequences; // Holds animation sequences
+ WalkSequences _walkSequences; // Holds animation sequences
ImageFile *_images; // Sprite images
ImageFrame *_imageFrame; // Pointer to shape in the images
int _walkCount; // Character walk counter
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp
index bac147f..6beae48 100644
--- a/engines/sherlock/people.cpp
+++ b/engines/sherlock/people.cpp
@@ -68,18 +68,6 @@ const char *const WALK_LIB_NAMES[10] = {
/*----------------------------------------------------------------*/
-void WalkSequence::load(Common::SeekableReadStream &s) {
- char buffer[9];
- s.read(buffer, 9);
- _vgsName = Common::String(buffer);
- _horizFlip = s.readByte() != 0;
-
- _sequences.resize(s.readUint16LE());
- s.read(&_sequences[0], _sequences.size());
-}
-
-/*----------------------------------------------------------------*/
-
Person::Person() : Sprite(), _walkLoaded(false), _npcIndex(0), _npcStack(0), _npcPause(false) {
Common::fill(&_npcPath[0], &_npcPath[MAX_NPC_PATH], 0);
}
@@ -156,7 +144,6 @@ void People::reset() {
p._gotoSeq = p._talkSeq = 0;
p._restoreSlot = 0;
p._startSeq = 0;
- p._walkSequences.clear();
p._altImages = nullptr;
p._altSequences = 0;
p._centerWalk = true;
@@ -164,7 +151,7 @@ void People::reset() {
// Load the default walk sequences
p._oldWalkSequence = -1;
-
+ p._walkSequences.clear();
if (IS_SERRATED_SCALPEL) {
p._walkSequences.resize(MAX_HOLMES_SEQUENCE);
for (int seqIdx = 0; seqIdx < MAX_HOLMES_SEQUENCE; ++seqIdx) {
diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h
index 72bdc51..272c418 100644
--- a/engines/sherlock/people.h
+++ b/engines/sherlock/people.h
@@ -77,7 +77,6 @@ public:
// Rose Tattoo fields
Common::String _walkVGSName; // Name of walk library person is using
- Common::Array<WalkSequence> _walkSequences;
public:
Person();
Commit: 30edd4efb80e203d7315e0fad41989c40dfe68ff
https://github.com/scummvm/scummvm/commit/30edd4efb80e203d7315e0fad41989c40dfe68ff
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-26T21:18:45-04:00
Commit Message:
SHERLOCK: Starting to split Scene class, implemented checkBgShapes changes
Changed paths:
engines/sherlock/objects.cpp
engines/sherlock/objects.h
engines/sherlock/scene.cpp
engines/sherlock/scene.h
engines/sherlock/sherlock.cpp
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index 7338726..3e8838c 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -1141,6 +1141,18 @@ void CAnim::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
/*----------------------------------------------------------------*/
+CAnimStream::CAnimStream() {
+ _stream = nullptr;
+ _frameSize = 0;
+ _images = nullptr;
+ _imageFrame = nullptr;
+ _flags = 0;
+ _scaleVal = 0;
+ _zPlacement = 0;
+}
+
+/*----------------------------------------------------------------*/
+
SceneImage::SceneImage() {
_images = nullptr;
_maxFrames = 0;
diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h
index 99746c9..ec5c2e7 100644
--- a/engines/sherlock/objects.h
+++ b/engines/sherlock/objects.h
@@ -413,6 +413,24 @@ struct CAnim {
void load(Common::SeekableReadStream &s, bool isRoseTattoo);
};
+struct CAnimStream {
+ Common::SeekableReadStream *_stream; // Stream to read frames from
+ int _frameSize; // Temporary used to store the frame size
+
+ void *_images; // TOOD: FIgure out hwo to hook up ImageFile with streaming support
+ ImageFrame *_imageFrame;
+
+ Common::Point _position; // Animation position
+ Common::Rect _oldBounds; // Bounds of previous frame
+ Common::Rect _removeBounds; // Remove area for just drawn frame
+
+ int _flags; // Flags
+ int _scaleVal; // Specifies the scale amount
+ int _zPlacement; // Used by doBgAnim for determining Z order
+
+ CAnimStream();
+};
+
struct SceneImage {
ImageFile *_images; // Object images
int _maxFrames; // How many frames in object
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index a1a165e..63203e1 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -150,6 +150,13 @@ void ScaleZone::load(Common::SeekableReadStream &s) {
/*----------------------------------------------------------------*/
+Scene *Scene::init(SherlockEngine *vm) {
+ if (vm->getGameID() == GType_SerratedScalpel)
+ return new ScalpelScene(vm);
+ else
+ return new TattooScene(vm);
+}
+
Scene::Scene(SherlockEngine *vm): _vm(vm) {
for (int idx = 0; idx < SCENES_COUNT; ++idx)
Common::fill(&_sceneStats[idx][0], &_sceneStats[idx][65], false);
@@ -978,42 +985,6 @@ Exit *Scene::checkForExit(const Common::Rect &r) {
return nullptr;
}
-void Scene::checkBgShapes() {
- People &people = *_vm->_people;
- Person &holmes = people._player;
- Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
-
- // Iterate through the shapes
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &obj = _bgShapes[idx];
- if (obj._type == STATIC_BG_SHAPE || obj._type == ACTIVE_BG_SHAPE) {
- if ((obj._flags & 5) == 1) {
- obj._misc = (pt.y < (obj._position.y + obj.frameHeight() - 1)) ?
- NORMAL_FORWARD : NORMAL_BEHIND;
- } else if (!(obj._flags & OBJ_BEHIND)) {
- obj._misc = BEHIND;
- } else if (obj._flags & OBJ_FORWARD) {
- obj._misc = FORWARD;
- }
- }
- }
-
- // Iterate through the canimshapes
- for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- Object &obj = _canimShapes[idx];
- if (obj._type == STATIC_BG_SHAPE || obj._type == ACTIVE_BG_SHAPE) {
- if ((obj._flags & 5) == 1) {
- obj._misc = (pt.y < (obj._position.y + obj._imageFrame->_frame.h - 1)) ?
- NORMAL_FORWARD : NORMAL_BEHIND;
- } else if (!(obj._flags & 1)) {
- obj._misc = BEHIND;
- } else if (obj._flags & 4) {
- obj._misc = FORWARD;
- }
- }
- }
-}
-
int Scene::startCAnim(int cAnimNum, int playRate) {
Events &events = *_vm->_events;
Map &map = *_vm->_map;
@@ -1658,5 +1629,80 @@ void Scene::setNPCPath(int npc) {
talk.talkTo(pathFile);
}
+void Scene::checkBgShapes() {
+ People &people = *_vm->_people;
+ Person &holmes = people._player;
+ Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
+
+ // Iterate through the shapes
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &obj = _bgShapes[idx];
+ if (obj._type == ACTIVE_BG_SHAPE || (IS_SERRATED_SCALPEL && obj._type == STATIC_BG_SHAPE)) {
+ if ((obj._flags & 5) == 1) {
+ obj._misc = (pt.y < (obj._position.y + obj.frameHeight() - 1)) ?
+ NORMAL_FORWARD : NORMAL_BEHIND;
+ } else if (!(obj._flags & OBJ_BEHIND)) {
+ obj._misc = BEHIND;
+ } else if (obj._flags & OBJ_FORWARD) {
+ obj._misc = FORWARD;
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------*/
+
+void ScalpelScene::checkBgShapes() {
+ People &people = *_vm->_people;
+ Person &holmes = people._player;
+ Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
+
+ // Call the base scene method to handle bg shapes
+ Scene::checkBgShapes();
+
+ // Iterate through the canim list
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ Object &obj = _canimShapes[idx];
+ if (obj._type == STATIC_BG_SHAPE || obj._type == ACTIVE_BG_SHAPE) {
+ if ((obj._flags & 5) == 1) {
+ obj._misc = (pt.y < (obj._position.y + obj._imageFrame->_frame.h - 1)) ?
+ NORMAL_FORWARD : NORMAL_BEHIND;
+ } else if (!(obj._flags & 1)) {
+ obj._misc = BEHIND;
+ } else if (obj._flags & 4) {
+ obj._misc = FORWARD;
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------*/
+
+void TattooScene::checkBgShapes() {
+ People &people = *_vm->_people;
+ Person &holmes = people._player;
+ Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
+
+ // Call the base scene method to handle bg shapes
+ Scene::checkBgShapes();
+
+ // Check for any active playing animation
+ if (_activeCAnim._images && _activeCAnim._zPlacement != REMOVE) {
+ switch (_activeCAnim._flags & 3) {
+ case 0:
+ _activeCAnim._zPlacement = BEHIND;
+ break;
+ case 1:
+ _activeCAnim._zPlacement = ((_activeCAnim._position.y + _activeCAnim._imageFrame->_frame.h - 1)) ?
+ NORMAL_FORWARD : NORMAL_BEHIND;
+ break;
+ case 2:
+ _activeCAnim._zPlacement = FORWARD;
+ break;
+ default:
+ break;
+ }
+ }
+}
} // End of namespace Sherlock
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index 8067268..50f8f07 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -140,7 +140,6 @@ struct SceneTripEntry {
class Scene {
private:
- SherlockEngine *_vm;
Common::String _rrmName;
bool _loadingSavedGame;
@@ -180,13 +179,6 @@ private:
void transitionToScene();
/**
- * Checks all the background shapes. If a background shape is animating,
- * it will flag it as needing to be drawn. If a non-animating shape is
- * colliding with another shape, it will also flag it as needing drawing
- */
- void checkBgShapes();
-
- /**
* Restores objects to the correct status. This ensures that things like being opened or moved
* will remain the same on future visits to the scene
*/
@@ -196,6 +188,17 @@ private:
* Draw all the shapes, people and NPCs in the correct order
*/
void drawAllShapes();
+protected:
+ SherlockEngine *_vm;
+
+ /**
+ * Checks all the background shapes. If a background shape is animating,
+ * it will flag it as needing to be drawn. If a non-animating shape is
+ * colliding with another shape, it will also flag it as needing drawing
+ */
+ virtual void checkBgShapes();
+
+ Scene(SherlockEngine *vm);
public:
int _currentScene;
int _goToScene;
@@ -228,8 +231,8 @@ public:
int _cAnimFramePause;
Common::Array<SceneTripEntry> _sceneTripCounters;
public:
- Scene(SherlockEngine *vm);
- ~Scene();
+ static Scene *init(SherlockEngine *vm);
+ virtual ~Scene();
/**
* Handles loading the scene specified by _goToScene
@@ -315,6 +318,32 @@ public:
void setNPCPath(int npc);
};
+class ScalpelScene : public Scene {
+protected:
+ /**
+ * Checks all the background shapes. If a background shape is animating,
+ * it will flag it as needing to be drawn. If a non-animating shape is
+ * colliding with another shape, it will also flag it as needing drawing
+ */
+ virtual void checkBgShapes();
+public:
+ ScalpelScene(SherlockEngine *vm) : Scene(vm) {}
+};
+
+class TattooScene : public Scene {
+private:
+ CAnimStream _activeCAnim;
+protected:
+ /**
+ * Checks all the background shapes. If a background shape is animating,
+ * it will flag it as needing to be drawn. If a non-animating shape is
+ * colliding with another shape, it will also flag it as needing drawing
+ */
+ virtual void checkBgShapes();
+public:
+ TattooScene(SherlockEngine *vm) : Scene(vm) {}
+};
+
} // End of namespace Sherlock
#endif
diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp
index 497841f..03c1055 100644
--- a/engines/sherlock/sherlock.cpp
+++ b/engines/sherlock/sherlock.cpp
@@ -92,7 +92,7 @@ void SherlockEngine::initialize() {
_journal = new Journal(this);
_people = new People(this);
_saves = new SaveManager(this, _targetName);
- _scene = new Scene(this);
+ _scene = Scene::init(this);
_screen = new Screen(this);
_sound = new Sound(this, _mixer);
_talk = Talk::init(this);
Commit: 483a72b8b840a9ebbb7009b3dcd20878d0ffad58
https://github.com/scummvm/scummvm/commit/483a72b8b840a9ebbb7009b3dcd20878d0ffad58
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-26T22:05:27-04:00
Commit Message:
SHERLOK: Beginnings of split of doBgAnim logic
Changed paths:
engines/sherlock/events.cpp
engines/sherlock/events.h
engines/sherlock/scene.cpp
engines/sherlock/scene.h
diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp
index c201507..a02a06c 100644
--- a/engines/sherlock/events.cpp
+++ b/engines/sherlock/events.cpp
@@ -75,6 +75,14 @@ void Events::setCursor(const Graphics::Surface &src) {
showCursor();
}
+void Events::animateCursorIfNeeded() {
+ if (_cursorId >= WAIT && _cursorId < (WAIT + 3)) {
+ CursorId newId = (WAIT + 2) ? WAIT : (CursorId)((int)_cursorId + 1);
+ setCursor(newId);
+ }
+}
+
+
void Events::showCursor() {
CursorMan.showMouse(true);
}
diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h
index c19a92d..b35109f 100644
--- a/engines/sherlock/events.h
+++ b/engines/sherlock/events.h
@@ -33,7 +33,7 @@ namespace Sherlock {
#define GAME_FRAME_RATE 60
#define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE)
-enum CursorId { ARROW = 0, MAGNIFY = 1, WAIT = 2, INVALID_CURSOR = -1 };
+enum CursorId { ARROW = 0, MAGNIFY = 1, WAIT = 2, EXIT_ZONES_START = 5, INVALID_CURSOR = -1 };
class SherlockEngine;
@@ -78,6 +78,11 @@ public:
void setCursor(const Graphics::Surface &src);
/**
+ * Animates the mouse cursor if the Wait cursor is showing
+ */
+ void animateCursorIfNeeded();
+
+ /**
* Show the mouse cursor
*/
void showCursor();
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 63203e1..41aafff 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -1199,53 +1199,15 @@ int Scene::startCAnim(int cAnimNum, int playRate) {
void Scene::doBgAnim() {
Events &events = *_vm->_events;
- Inventory &inv = *_vm->_inventory;
People &people = *_vm->_people;
Screen &screen = *_vm->_screen;
- Sound &sound = *_vm->_sound;
Talk &talk = *_vm->_talk;
- UserInterface &ui = *_vm->_ui;
-
- screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
-
- int cursorId = events.getCursor();
Common::Point mousePos = events.mousePos();
+ events.animateCursorIfNeeded();
+ screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
talk._talkToAbort = false;
- // Animate the mouse cursor
- if (cursorId >= WAIT) {
- if (++cursorId > (WAIT + 2))
- cursorId = WAIT;
-
- events.setCursor((CursorId)cursorId);
- }
-
- if (ui._menuMode == LOOK_MODE) {
- if (mousePos.y > CONTROLS_Y1)
- events.setCursor(ARROW);
- else if (mousePos.y < CONTROLS_Y)
- events.setCursor(MAGNIFY);
- }
-
- // Check for setting magnifying glass cursor
- if (ui._menuMode == INV_MODE || ui._menuMode == USE_MODE || ui._menuMode == GIVE_MODE) {
- if (inv._invMode == INVMODE_LOOK) {
- // Only show Magnifying glass cursor if it's not on the inventory command line
- if (mousePos.y < CONTROLS_Y || mousePos.y >(CONTROLS_Y1 + 13))
- events.setCursor(MAGNIFY);
- else
- events.setCursor(ARROW);
- } else {
- events.setCursor(ARROW);
- }
- }
-
- if (sound._diskSoundPlaying && !*sound._soundIsOn) {
- // Loaded sound just finished playing
- sound.freeDigiSound();
- }
-
if (_restoreFlag) {
if (people[AL]._type == CHARACTER)
people[AL].checkSprite();
@@ -1676,8 +1638,48 @@ void ScalpelScene::checkBgShapes() {
}
}
+void ScalpelScene::doBgAnim() {
+ Inventory &inv = *_vm->_inventory;
+ Events &events = *_vm->_events;
+ Sound &sound = *_vm->_sound;
+ UserInterface &ui = *_vm->_ui;
+ Common::Point mousePos = events.mousePos();
+
+ if (ui._menuMode == LOOK_MODE) {
+ if (mousePos.y > CONTROLS_Y1)
+ events.setCursor(ARROW);
+ else if (mousePos.y < CONTROLS_Y)
+ events.setCursor(MAGNIFY);
+ }
+
+ // Check for setting magnifying glass cursor
+ if (ui._menuMode == INV_MODE || ui._menuMode == USE_MODE || ui._menuMode == GIVE_MODE) {
+ if (inv._invMode == INVMODE_LOOK) {
+ // Only show Magnifying glass cursor if it's not on the inventory command line
+ if (mousePos.y < CONTROLS_Y || mousePos.y >(CONTROLS_Y1 + 13))
+ events.setCursor(MAGNIFY);
+ else
+ events.setCursor(ARROW);
+ } else {
+ events.setCursor(ARROW);
+ }
+ }
+
+ if (sound._diskSoundPlaying && !*sound._soundIsOn) {
+ // Loaded sound just finished playing
+ sound.freeDigiSound();
+ }
+
+ // Handle doing the actual drawing
+ Scene::doBgAnim();
+}
+
/*----------------------------------------------------------------*/
+TattooScene::TattooScene(SherlockEngine *vm) : Scene(vm) {
+ _arrowZone = -1;
+}
+
void TattooScene::checkBgShapes() {
People &people = *_vm->_people;
Person &holmes = people._player;
@@ -1705,4 +1707,34 @@ void TattooScene::checkBgShapes() {
}
}
+void TattooScene::doBgAnim() {
+ Events &events = *_vm->_events;
+ UserInterface &ui = *_vm->_ui;
+ Common::Point mousePos = events.mousePos();
+
+ // If we're in Look Mode, make sure the cursor is the magnifying glass
+ if (ui._menuMode == LOOK_MODE && events.getCursor() != MAGNIFY)
+ events.setCursor(MAGNIFY);
+
+ // See if the mouse is over any of the arrow zones, and if so, change the cursor to the correct
+ // arrow cursor indicating the direcetion of the exit
+ if (events.getCursor() == ARROW || events.getCursor() >= EXIT_ZONES_START) {
+ CursorId cursorId = ARROW;
+
+ if (ui._menuMode == STD_MODE && _arrowZone != -1 && _currentScene != 90) {
+ for (uint idx = 0; idx < _exits.size(); ++idx) {
+ Exit &exit = _exits[idx];
+ if (exit.contains(mousePos))
+ cursorId = (CursorId)(exit._image + EXIT_ZONES_START);
+ }
+ }
+
+ events.setCursor(cursorId);
+ }
+
+ // Handle doing the actual drawing
+ _restoreFlag = true;
+ Scene::doBgAnim();
+}
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index 50f8f07..2aecdfa 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -273,9 +273,9 @@ public:
int toggleObject(const Common::String &name);
/**
- * Animate all objects and people.
+ * Draw all objects and characters.
*/
- void doBgAnim();
+ virtual void doBgAnim();
/**
* Attempts to find a background shape within the passed bounds. If found,
@@ -328,11 +328,17 @@ protected:
virtual void checkBgShapes();
public:
ScalpelScene(SherlockEngine *vm) : Scene(vm) {}
+
+ /**
+ * Draw all objects and characters.
+ */
+ virtual void doBgAnim();
};
class TattooScene : public Scene {
private:
CAnimStream _activeCAnim;
+ int _arrowZone;
protected:
/**
* Checks all the background shapes. If a background shape is animating,
@@ -341,7 +347,12 @@ protected:
*/
virtual void checkBgShapes();
public:
- TattooScene(SherlockEngine *vm) : Scene(vm) {}
+ TattooScene(SherlockEngine *vm);
+
+ /**
+ * Draw all objects and characters.
+ */
+ virtual void doBgAnim();
};
} // End of namespace Sherlock
Commit: 0d4163c6e932bed2b85843f6ab3b5066d0353df6
https://github.com/scummvm/scummvm/commit/0d4163c6e932bed2b85843f6ab3b5066d0353df6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-27T20:26:40-04:00
Commit Message:
SHERLOCK: Implemented initial background clearing of RT doBgAnim
Changed paths:
engines/sherlock/inventory.cpp
engines/sherlock/scene.cpp
engines/sherlock/scene.h
engines/sherlock/screen.h
engines/sherlock/settings.cpp
engines/sherlock/settings.h
engines/sherlock/talk.cpp
engines/sherlock/talk.h
engines/sherlock/tattoo/tattoo.cpp
engines/sherlock/tattoo/tattoo.h
engines/sherlock/user_interface.cpp
engines/sherlock/user_interface.h
diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp
index bbb7c75..7ec0b64 100644
--- a/engines/sherlock/inventory.cpp
+++ b/engines/sherlock/inventory.cpp
@@ -244,7 +244,7 @@ void Inventory::drawInventory(InvNewMode mode) {
}
assert(IS_SERRATED_SCALPEL);
- ((ScalpelUserInterface *)_vm->_ui)->_oldUse = -1;
+ ((Scalpel::ScalpelUserInterface *)_vm->_ui)->_oldUse = -1;
}
void Inventory::invCommands(bool slamIt) {
@@ -324,7 +324,7 @@ void Inventory::refreshInv() {
Screen &screen = *_vm->_screen;
Talk &talk = *_vm->_talk;
- ScalpelUserInterface &ui = *(ScalpelUserInterface *)_vm->_ui;
+ Scalpel::ScalpelUserInterface &ui = *(Scalpel::ScalpelUserInterface *)_vm->_ui;
ui._invLookFlag = true;
freeInv();
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 41aafff..18690fb 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -24,6 +24,7 @@
#include "sherlock/sherlock.h"
#include "sherlock/scalpel/scalpel.h"
#include "sherlock/screen.h"
+#include "sherlock/tattoo/tattoo.h"
namespace Sherlock {
@@ -152,9 +153,9 @@ void ScaleZone::load(Common::SeekableReadStream &s) {
Scene *Scene::init(SherlockEngine *vm) {
if (vm->getGameID() == GType_SerratedScalpel)
- return new ScalpelScene(vm);
+ return new Scalpel::ScalpelScene(vm);
else
- return new TattooScene(vm);
+ return new Tattoo::TattooScene(vm);
}
Scene::Scene(SherlockEngine *vm): _vm(vm) {
@@ -1197,20 +1198,209 @@ int Scene::startCAnim(int cAnimNum, int playRate) {
return 1;
}
-void Scene::doBgAnim() {
+int Scene::findBgShape(const Common::Rect &r) {
+ if (!_doBgAnimDone)
+ // New frame hasn't been drawn yet
+ return -1;
+
+ for (int idx = (int)_bgShapes.size() - 1; idx >= 0; --idx) {
+ Object &o = _bgShapes[idx];
+ if (o._type != INVALID && o._type != NO_SHAPE && o._type != HIDDEN
+ && o._aType <= PERSON) {
+ if (r.intersects(o.getNewBounds()))
+ return idx;
+ } else if (o._type == NO_SHAPE) {
+ if (r.intersects(o.getNoShapeBounds()))
+ return idx;
+ }
+ }
+
+ return -1;
+}
+
+int Scene::checkForZones(const Common::Point &pt, int zoneType) {
+ int matches = 0;
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if ((o._aType == zoneType && o._type != INVALID) && o._type != HIDDEN) {
+ Common::Rect r = o._type == NO_SHAPE ? o.getNoShapeBounds() : o.getNewBounds();
+
+ if (r.contains(pt)) {
+ ++matches;
+ o.setFlagsAndToggles();
+ _vm->_talk->talkTo(o._use[0]._target);
+ }
+ }
+ }
+
+ return matches;
+}
+
+int Scene::whichZone(const Common::Point &pt) {
+ for (uint idx = 0; idx < _zones.size(); ++idx) {
+ if (_zones[idx].contains(pt))
+ return idx;
+ }
+
+ return -1;
+}
+
+int Scene::closestZone(const Common::Point &pt) {
+ int dist = 1000;
+ int zone = -1;
+
+ for (uint idx = 0; idx < _zones.size(); ++idx) {
+ Common::Point zc((_zones[idx].left + _zones[idx].right) / 2,
+ (_zones[idx].top + _zones[idx].bottom) / 2);
+ int d = ABS(zc.x - pt.x) + ABS(zc.y - pt.y);
+
+ if (d < dist) {
+ // Found a closer zone
+ dist = d;
+ zone = idx;
+ }
+ }
+
+ return zone;
+}
+
+void Scene::synchronize(Common::Serializer &s) {
+ if (s.isSaving())
+ saveSceneStatus();
+
+ if (s.isSaving()) {
+ s.syncAsSint16LE(_currentScene);
+ } else {
+ s.syncAsSint16LE(_goToScene);
+ _loadingSavedGame = true;
+ }
+
+ for (int sceneNum = 0; sceneNum < SCENES_COUNT; ++sceneNum) {
+ for (int flag = 0; flag < 65; ++flag) {
+ s.syncAsByte(_sceneStats[sceneNum][flag]);
+ }
+ }
+}
+
+void Scene::setNPCPath(int npc) {
+ People &people = *_vm->_people;
+ Talk &talk = *_vm->_talk;
+
+ people[npc].clearNPC();
+ people[npc]._name = Common::String::format("WATS%.2dA", _currentScene);
+
+ // If we're in the middle of a script that will continue once the scene is loaded,
+ // return without calling the path script
+ if (talk._scriptMoreFlag == 1 || talk._scriptMoreFlag == 3)
+ return;
+
+ // Turn off all the NPCs, since the talk script will turn them back on as needed
+ for (uint idx = 0; idx < MAX_NPC; ++idx)
+ people[idx + 1]._type = INVALID;
+
+ // Call the path script for the scene
+ Common::String pathFile = Common::String::format("PATH%.2dA", _currentScene);
+ talk.talkTo(pathFile);
+}
+
+void Scene::checkBgShapes() {
+ People &people = *_vm->_people;
+ Person &holmes = people._player;
+ Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
+
+ // Iterate through the shapes
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &obj = _bgShapes[idx];
+ if (obj._type == ACTIVE_BG_SHAPE || (IS_SERRATED_SCALPEL && obj._type == STATIC_BG_SHAPE)) {
+ if ((obj._flags & 5) == 1) {
+ obj._misc = (pt.y < (obj._position.y + obj.frameHeight() - 1)) ?
+ NORMAL_FORWARD : NORMAL_BEHIND;
+ } else if (!(obj._flags & OBJ_BEHIND)) {
+ obj._misc = BEHIND;
+ } else if (obj._flags & OBJ_FORWARD) {
+ obj._misc = FORWARD;
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------*/
+
+namespace Scalpel {
+
+void ScalpelScene::checkBgShapes() {
+ People &people = *_vm->_people;
+ Person &holmes = people._player;
+ Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
+
+ // Call the base scene method to handle bg shapes
+ Scene::checkBgShapes();
+
+ // Iterate through the canim list
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ Object &obj = _canimShapes[idx];
+ if (obj._type == STATIC_BG_SHAPE || obj._type == ACTIVE_BG_SHAPE) {
+ if ((obj._flags & 5) == 1) {
+ obj._misc = (pt.y < (obj._position.y + obj._imageFrame->_frame.h - 1)) ?
+ NORMAL_FORWARD : NORMAL_BEHIND;
+ } else if (!(obj._flags & 1)) {
+ obj._misc = BEHIND;
+ } else if (obj._flags & 4) {
+ obj._misc = FORWARD;
+ }
+ }
+ }
+}
+
+void ScalpelScene::doBgAnimCheckCursor() {
+ Inventory &inv = *_vm->_inventory;
+ Events &events = *_vm->_events;
+ Sound &sound = *_vm->_sound;
+ UserInterface &ui = *_vm->_ui;
+ Common::Point mousePos = events.mousePos();
+
+ if (ui._menuMode == LOOK_MODE) {
+ if (mousePos.y > CONTROLS_Y1)
+ events.setCursor(ARROW);
+ else if (mousePos.y < CONTROLS_Y)
+ events.setCursor(MAGNIFY);
+ }
+
+ // Check for setting magnifying glass cursor
+ if (ui._menuMode == INV_MODE || ui._menuMode == USE_MODE || ui._menuMode == GIVE_MODE) {
+ if (inv._invMode == INVMODE_LOOK) {
+ // Only show Magnifying glass cursor if it's not on the inventory command line
+ if (mousePos.y < CONTROLS_Y || mousePos.y >(CONTROLS_Y1 + 13))
+ events.setCursor(MAGNIFY);
+ else
+ events.setCursor(ARROW);
+ } else {
+ events.setCursor(ARROW);
+ }
+ }
+
+ if (sound._diskSoundPlaying && !*sound._soundIsOn) {
+ // Loaded sound just finished playing
+ sound.freeDigiSound();
+ }
+}
+
+void ScalpelScene::doBgAnim() {
+ Scalpel::ScalpelEngine &vm = *((Scalpel::ScalpelEngine *)_vm);
Events &events = *_vm->_events;
People &people = *_vm->_people;
Screen &screen = *_vm->_screen;
Talk &talk = *_vm->_talk;
- Common::Point mousePos = events.mousePos();
- events.animateCursorIfNeeded();
screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
talk._talkToAbort = false;
if (_restoreFlag) {
- if (people[AL]._type == CHARACTER)
- people[AL].checkSprite();
+ for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
+ if (people[idx]._type == CHARACTER)
+ people[idx].checkSprite();
+ }
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE)
@@ -1225,8 +1415,8 @@ void Scene::doBgAnim() {
_canimShapes[idx].checkObject();
}
- if (_currentScene == 12 && IS_SERRATED_SCALPEL)
- ((Scalpel::ScalpelEngine *)_vm)->eraseMirror12();
+ if (_currentScene == 12)
+ vm.eraseMirror12();
// Restore the back buffer from the back buffer 2 in the changed area
Common::Rect bounds(people[AL]._oldPosition.x, people[AL]._oldPosition.y,
@@ -1297,8 +1487,8 @@ void Scene::doBgAnim() {
// Flag the bg shapes which need to be redrawn
checkBgShapes();
- if (_currentScene == 12 && IS_SERRATED_SCALPEL)
- ((Scalpel::ScalpelEngine *)_vm)->doMirror12();
+ if (_currentScene == 12)
+ vm.doMirror12();
// Draw all active shapes which are behind the person
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
@@ -1407,8 +1597,8 @@ void Scene::doBgAnim() {
}
}
- if (_currentScene == 12 && IS_SERRATED_SCALPEL)
- ((Scalpel::ScalpelEngine *)_vm)->flushMirror12();
+ if (_currentScene == 12)
+ vm.flushMirror12();
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
@@ -1485,199 +1675,16 @@ void Scene::doBgAnim() {
}
}
-int Scene::findBgShape(const Common::Rect &r) {
- if (!_doBgAnimDone)
- // New frame hasn't been drawn yet
- return -1;
-
- for (int idx = (int)_bgShapes.size() - 1; idx >= 0; --idx) {
- Object &o = _bgShapes[idx];
- if (o._type != INVALID && o._type != NO_SHAPE && o._type != HIDDEN
- && o._aType <= PERSON) {
- if (r.intersects(o.getNewBounds()))
- return idx;
- } else if (o._type == NO_SHAPE) {
- if (r.intersects(o.getNoShapeBounds()))
- return idx;
- }
- }
-
- return -1;
-}
-
-int Scene::checkForZones(const Common::Point &pt, int zoneType) {
- int matches = 0;
-
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &o = _bgShapes[idx];
- if ((o._aType == zoneType && o._type != INVALID) && o._type != HIDDEN) {
- Common::Rect r = o._type == NO_SHAPE ? o.getNoShapeBounds() : o.getNewBounds();
-
- if (r.contains(pt)) {
- ++matches;
- o.setFlagsAndToggles();
- _vm->_talk->talkTo(o._use[0]._target);
- }
- }
- }
-
- return matches;
-}
-
-int Scene::whichZone(const Common::Point &pt) {
- for (uint idx = 0; idx < _zones.size(); ++idx) {
- if (_zones[idx].contains(pt))
- return idx;
- }
-
- return -1;
-}
-
-int Scene::closestZone(const Common::Point &pt) {
- int dist = 1000;
- int zone = -1;
-
- for (uint idx = 0; idx < _zones.size(); ++idx) {
- Common::Point zc((_zones[idx].left + _zones[idx].right) / 2,
- (_zones[idx].top + _zones[idx].bottom) / 2);
- int d = ABS(zc.x - pt.x) + ABS(zc.y - pt.y);
-
- if (d < dist) {
- // Found a closer zone
- dist = d;
- zone = idx;
- }
- }
-
- return zone;
-}
-
-void Scene::synchronize(Common::Serializer &s) {
- if (s.isSaving())
- saveSceneStatus();
-
- if (s.isSaving()) {
- s.syncAsSint16LE(_currentScene);
- } else {
- s.syncAsSint16LE(_goToScene);
- _loadingSavedGame = true;
- }
-
- for (int sceneNum = 0; sceneNum < SCENES_COUNT; ++sceneNum) {
- for (int flag = 0; flag < 65; ++flag) {
- s.syncAsByte(_sceneStats[sceneNum][flag]);
- }
- }
-}
-
-void Scene::setNPCPath(int npc) {
- People &people = *_vm->_people;
- Talk &talk = *_vm->_talk;
-
- people[npc].clearNPC();
- people[npc]._name = Common::String::format("WATS%.2dA", _currentScene);
-
- // If we're in the middle of a script that will continue once the scene is loaded,
- // return without calling the path script
- if (talk._scriptMoreFlag == 1 || talk._scriptMoreFlag == 3)
- return;
-
- // Turn off all the NPCs, since the talk script will turn them back on as needed
- for (uint idx = 0; idx < MAX_NPC; ++idx)
- people[idx + 1]._type = INVALID;
-
- // Call the path script for the scene
- Common::String pathFile = Common::String::format("PATH%.2dA", _currentScene);
- talk.talkTo(pathFile);
-}
-
-void Scene::checkBgShapes() {
- People &people = *_vm->_people;
- Person &holmes = people._player;
- Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
-
- // Iterate through the shapes
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &obj = _bgShapes[idx];
- if (obj._type == ACTIVE_BG_SHAPE || (IS_SERRATED_SCALPEL && obj._type == STATIC_BG_SHAPE)) {
- if ((obj._flags & 5) == 1) {
- obj._misc = (pt.y < (obj._position.y + obj.frameHeight() - 1)) ?
- NORMAL_FORWARD : NORMAL_BEHIND;
- } else if (!(obj._flags & OBJ_BEHIND)) {
- obj._misc = BEHIND;
- } else if (obj._flags & OBJ_FORWARD) {
- obj._misc = FORWARD;
- }
- }
- }
-}
+} // End of namespace Scalpel
/*----------------------------------------------------------------*/
-void ScalpelScene::checkBgShapes() {
- People &people = *_vm->_people;
- Person &holmes = people._player;
- Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
-
- // Call the base scene method to handle bg shapes
- Scene::checkBgShapes();
-
- // Iterate through the canim list
- for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- Object &obj = _canimShapes[idx];
- if (obj._type == STATIC_BG_SHAPE || obj._type == ACTIVE_BG_SHAPE) {
- if ((obj._flags & 5) == 1) {
- obj._misc = (pt.y < (obj._position.y + obj._imageFrame->_frame.h - 1)) ?
- NORMAL_FORWARD : NORMAL_BEHIND;
- } else if (!(obj._flags & 1)) {
- obj._misc = BEHIND;
- } else if (obj._flags & 4) {
- obj._misc = FORWARD;
- }
- }
- }
-}
-
-void ScalpelScene::doBgAnim() {
- Inventory &inv = *_vm->_inventory;
- Events &events = *_vm->_events;
- Sound &sound = *_vm->_sound;
- UserInterface &ui = *_vm->_ui;
- Common::Point mousePos = events.mousePos();
-
- if (ui._menuMode == LOOK_MODE) {
- if (mousePos.y > CONTROLS_Y1)
- events.setCursor(ARROW);
- else if (mousePos.y < CONTROLS_Y)
- events.setCursor(MAGNIFY);
- }
-
- // Check for setting magnifying glass cursor
- if (ui._menuMode == INV_MODE || ui._menuMode == USE_MODE || ui._menuMode == GIVE_MODE) {
- if (inv._invMode == INVMODE_LOOK) {
- // Only show Magnifying glass cursor if it's not on the inventory command line
- if (mousePos.y < CONTROLS_Y || mousePos.y >(CONTROLS_Y1 + 13))
- events.setCursor(MAGNIFY);
- else
- events.setCursor(ARROW);
- } else {
- events.setCursor(ARROW);
- }
- }
-
- if (sound._diskSoundPlaying && !*sound._soundIsOn) {
- // Loaded sound just finished playing
- sound.freeDigiSound();
- }
-
- // Handle doing the actual drawing
- Scene::doBgAnim();
-}
-
-/*----------------------------------------------------------------*/
+namespace Tattoo {
TattooScene::TattooScene(SherlockEngine *vm) : Scene(vm) {
_arrowZone = -1;
+ _mask = _mask1 = nullptr;
+ _maskCounter = 0;
}
void TattooScene::checkBgShapes() {
@@ -1707,7 +1714,7 @@ void TattooScene::checkBgShapes() {
}
}
-void TattooScene::doBgAnim() {
+void TattooScene::doBgAnimCheckCursor() {
Events &events = *_vm->_events;
UserInterface &ui = *_vm->_ui;
Common::Point mousePos = events.mousePos();
@@ -1731,10 +1738,106 @@ void TattooScene::doBgAnim() {
events.setCursor(cursorId);
}
+}
- // Handle doing the actual drawing
- _restoreFlag = true;
- Scene::doBgAnim();
+void TattooScene::doBgAnimHandleMask() {
+ TattooEngine &vm = *((TattooEngine *)_vm);
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
+ TattooUserInterface &ui = *((TattooUserInterface *)_vm->_ui);
+
+ static const int16 OFFSETS[16] = { -1, -2, -3, -3, -2, -1, -1, 0, 1, 2, 3, 3, 2, 1, 0, 0 };
+
+ if (_mask != nullptr) {
+ if (screen._backBuffer1.w() > screen.w())
+ screen.blitFrom(screen._backBuffer1, Common::Point(0, 0), Common::Rect(screen._currentScroll, 0,
+ screen._currentScroll + screen.w(), screen.h()));
+ else
+ screen.blitFrom(screen._backBuffer1);
+
+ switch (_currentScene) {
+ case 7:
+ if (++_maskCounter == 2) {
+ _maskCounter = 0;
+ if (--_maskOffset.x < 0)
+ _maskOffset.x = SHERLOCK_SCREEN_WIDTH - 1;
+ }
+ break;
+
+ case 8:
+ _maskOffset.x += 2;
+ if (_maskOffset.x >= SHERLOCK_SCREEN_WIDTH)
+ _maskOffset.x = 0;
+ break;
+
+ case 18:
+ case 68:
+ ++_maskCounter;
+ if (_maskCounter / 4 >= 16)
+ _maskCounter = 0;
+
+ _maskOffset.x = OFFSETS[_maskCounter / 4];
+ break;
+
+ case 53:
+ if (++_maskCounter == 2) {
+ _maskCounter = 0;
+ if (++_maskOffset.x == screen._backBuffer1.w())
+ _maskOffset.x = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else {
+ // Standard scene without mask, so call user interface to erase any UI elements as necessary
+ ui.doBgAnimRestoreUI();
+
+ // Restore background for any areas covered by characters and shapes
+ for (uint idx = 0; idx < MAX_CHARACTERS; ++idx)
+ screen.restoreBackground(Common::Rect(people[idx]._oldPosition.x, people[idx]._oldPosition.y,
+ people[idx]._oldPosition.x + people[idx]._oldSize.x, people[idx]._oldPosition.y + people[idx]._oldSize.y));
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &obj = _bgShapes[idx];
+
+ if ((obj._type == ACTIVE_BG_SHAPE && (obj._maxFrames > 1 || obj._delta.x != 0 || obj._delta.y != 0)) ||
+ obj._type == HIDE_SHAPE || obj._type == REMOVE)
+ screen._backBuffer1.blitFrom(*obj._imageFrame, obj._oldPosition,
+ Common::Rect(obj._oldPosition.x, obj._oldPosition.y, obj._oldPosition.x + obj._oldSize.x,
+ obj._oldPosition.y + obj._oldSize.y));
+ }
+
+ // If credits are active, erase the area they cover
+ if (vm._creditsActive)
+ vm.eraseCredits();
+ }
+}
+
+void TattooScene::doBgAnim() {
+ doBgAnimCheckCursor();
+
+// Events &events = *_vm->_events;
+ People &people = *_vm->_people;
+// Scene &scene = *_vm->_scene;
+ Screen &screen = *_vm->_screen;
+ Talk &talk = *_vm->_talk;
+
+ screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
+ talk._talkToAbort = false;
+
+ for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
+ if (people[idx]._type == CHARACTER)
+ people[idx].checkSprite();
+ }
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE)
+ _bgShapes[idx].checkObject();
+ }
}
+} // End of namespace Tattoo
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index 2aecdfa..1bd23fc 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -275,7 +275,7 @@ public:
/**
* Draw all objects and characters.
*/
- virtual void doBgAnim();
+ virtual void doBgAnim() = 0;
/**
* Attempts to find a background shape within the passed bounds. If found,
@@ -318,7 +318,11 @@ public:
void setNPCPath(int npc);
};
+namespace Scalpel {
+
class ScalpelScene : public Scene {
+private:
+ void doBgAnimCheckCursor();
protected:
/**
* Checks all the background shapes. If a background shape is animating,
@@ -335,10 +339,19 @@ public:
virtual void doBgAnim();
};
+} // End of namespace Scalpel
+
+namespace Tattoo {
+
class TattooScene : public Scene {
private:
- CAnimStream _activeCAnim;
int _arrowZone;
+ int _maskCounter;
+ Common::Point _maskOffset;
+private:
+ void doBgAnimCheckCursor();
+
+ void doBgAnimHandleMask();
protected:
/**
* Checks all the background shapes. If a background shape is animating,
@@ -347,6 +360,9 @@ protected:
*/
virtual void checkBgShapes();
public:
+ ImageFile *_mask, *_mask1;
+ CAnimStream _activeCAnim;
+public:
TattooScene(SherlockEngine *vm);
/**
@@ -355,6 +371,8 @@ public:
virtual void doBgAnim();
};
+} // End of namespace Tattoo
+
} // End of namespace Sherlock
#endif
diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h
index 58c7d8f..e730329 100644
--- a/engines/sherlock/screen.h
+++ b/engines/sherlock/screen.h
@@ -72,7 +72,6 @@ private:
byte _lookupTable[PALETTE_COUNT];
byte _lookupTable1[PALETTE_COUNT];
int _scrollSize;
- int _currentScroll;
int _targetScroll;
private:
/**
@@ -102,6 +101,7 @@ public:
byte _cMap[PALETTE_SIZE];
byte _sMap[PALETTE_SIZE];
byte _tMap[PALETTE_SIZE];
+ int _currentScroll;
public:
Screen(SherlockEngine *vm);
virtual ~Screen();
diff --git a/engines/sherlock/settings.cpp b/engines/sherlock/settings.cpp
index cae5c6c..98a13a3 100644
--- a/engines/sherlock/settings.cpp
+++ b/engines/sherlock/settings.cpp
@@ -25,6 +25,8 @@
namespace Sherlock {
+namespace Scalpel {
+
static const int SETUP_POINTS[12][4] = {
{ 4, 154, 101, 53 }, // Exit
{ 4, 165, 101, 53 }, // Music Toggle
@@ -333,4 +335,6 @@ void Settings::show(SherlockEngine *vm) {
ui._key = -1;
}
+} // End of namespace Scalpel
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/settings.h b/engines/sherlock/settings.h
index fc5fb29..ff2e647 100644
--- a/engines/sherlock/settings.h
+++ b/engines/sherlock/settings.h
@@ -28,7 +28,8 @@
namespace Sherlock {
class SherlockEngine;
-class UserInterface;
+
+namespace Scalpel {
class Settings {
private:
@@ -55,6 +56,8 @@ public:
static void show(SherlockEngine *vm);
};
+} // End of namespace Scalpel
+
} // End of namespace Sherlock
#endif
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index b4be5ee..5e9cb02 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -332,7 +332,7 @@ void Talk::talkTo(const Common::String &filename) {
if (IS_SERRATED_SCALPEL) {
// Restore any pressed button
if (!ui._windowOpen && savedMode != STD_MODE)
- ((ScalpelUserInterface *)_vm->_ui)->restoreButton((int)(savedMode - 1));
+ ((Scalpel::ScalpelUserInterface *)_vm->_ui)->restoreButton((int)(savedMode - 1));
}
// Clear the ui counter so that anything displayed on the info line
diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h
index dc6789c..a5f81f3 100644
--- a/engines/sherlock/talk.h
+++ b/engines/sherlock/talk.h
@@ -108,8 +108,8 @@ enum {
enum OpcodeReturn { RET_EXIT = -1, RET_SUCCESS = 0, RET_CONTINUE = 1 };
class SherlockEngine;
-class ScalpelUserInterface;
class Talk;
+namespace Scalpel { class ScalpelUserInterface; };
typedef OpcodeReturn(Talk::*OpcodeMethod)(const byte *&str);
@@ -164,7 +164,7 @@ struct TalkSequences {
};
class Talk {
- friend class ScalpelUserInterface;
+ friend class Scalpel::ScalpelUserInterface;
private:
/**
* Remove any voice commands from a loaded statement list
diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp
index 47a7c2a..6d90416 100644
--- a/engines/sherlock/tattoo/tattoo.cpp
+++ b/engines/sherlock/tattoo/tattoo.cpp
@@ -27,13 +27,15 @@ namespace Sherlock {
namespace Tattoo {
+TattooEngine::TattooEngine(OSystem *syst, const SherlockGameDescription *gameDesc) :
+ SherlockEngine(syst, gameDesc) {
+ _creditsActive = false;
+}
+
void TattooEngine::showOpening() {
// TODO
}
-/**
- * Initialize the engine
- */
void TattooEngine::initialize() {
initGraphics(640, 480, true);
@@ -52,9 +54,6 @@ void TattooEngine::initialize() {
loadInitialPalette();
}
-/**
- * Starting a scene within the game
- */
void TattooEngine::startScene() {
// TODO
}
@@ -69,6 +68,10 @@ void TattooEngine::loadInitialPalette() {
delete stream;
}
+void TattooEngine::eraseCredits() {
+ // TODO
+}
+
} // End of namespace Tattoo
} // End of namespace Scalpel
diff --git a/engines/sherlock/tattoo/tattoo.h b/engines/sherlock/tattoo/tattoo.h
index b9224e0..b6a8510 100644
--- a/engines/sherlock/tattoo/tattoo.h
+++ b/engines/sherlock/tattoo/tattoo.h
@@ -36,16 +36,27 @@ private:
*/
void loadInitialPalette();
protected:
+ /**
+ * Initialize the engine
+ */
virtual void initialize();
virtual void showOpening();
+ /**
+ * Starting a scene within the game
+ */
virtual void startScene();
public:
- TattooEngine(OSystem *syst, const SherlockGameDescription *gameDesc) :
- SherlockEngine(syst, gameDesc) {}
-
+ bool _creditsActive;
+public:
+ TattooEngine(OSystem *syst, const SherlockGameDescription *gameDesc);
virtual ~TattooEngine() {}
+
+ /**
+ * Erase any area of the screen covered by credits
+ */
+ void eraseCredits();
};
} // End of namespace Tattoo
diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp
index 4f83e91..06ec62b 100644
--- a/engines/sherlock/user_interface.cpp
+++ b/engines/sherlock/user_interface.cpp
@@ -82,9 +82,9 @@ const char *const MUSE[] = {
UserInterface *UserInterface::init(SherlockEngine *vm) {
if (vm->getGameID() == GType_SerratedScalpel)
- return new ScalpelUserInterface(vm);
+ return new Scalpel::ScalpelUserInterface(vm);
else
- return new TattooUserInterface(vm);
+ return new Tattoo::TattooUserInterface(vm);
}
UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) {
@@ -108,6 +108,8 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) {
/*----------------------------------------------------------------*/
+namespace Scalpel {
+
ScalpelUserInterface::ScalpelUserInterface(SherlockEngine *vm): UserInterface(vm) {
_controls = new ImageFile("menu.all");
_controlPanel = new ImageFile("controls.vgs");
@@ -2296,10 +2298,15 @@ void ScalpelUserInterface::checkAction(ActionType &action, const char *const mes
events.setCursor(ARROW);
}
+}
+
/*----------------------------------------------------------------*/
+namespace Tattoo {
+
TattooUserInterface::TattooUserInterface(SherlockEngine *vm): UserInterface(vm) {
- //
+ _menuBuffer = nullptr;
+ _invMenuBuffer = nullptr;
}
void TattooUserInterface::handleInput() {
@@ -2307,4 +2314,44 @@ void TattooUserInterface::handleInput() {
_vm->_events->pollEventsAndWait();
}
+void TattooUserInterface::doBgAnimRestoreUI() {
+ TattooScene &scene = *((TattooScene *)_vm->_scene);
+ Screen &screen = *_vm->_screen;
+
+ // If _oldMenuBounds was set, then either a new menu has been opened or the current menu has been closed.
+ // Either way, we need to restore the area where the menu was displayed
+ if (_oldMenuBounds.width() > 0)
+ screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldMenuBounds.left, _oldMenuBounds.top),
+ _oldMenuBounds);
+
+ if (_oldInvMenuBounds.width() > 0)
+ screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldInvMenuBounds.left, _oldInvMenuBounds.top),
+ _oldInvMenuBounds);
+
+ if (_menuBuffer != nullptr)
+ screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_menuBounds.left, _menuBounds.top), _menuBounds);
+ if (_invMenuBuffer != nullptr)
+ screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_invMenuBounds.left, _invMenuBounds.top), _invMenuBounds);
+
+ // If there is a Text Tag being display, restore the area underneath it
+ if (_oldTagBounds.width() > 0)
+ screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldTagBounds.left, _oldTagBounds.top),
+ _oldTagBounds);
+
+ // If there is an Inventory being shown, restore the graphics underneath it
+ if (_oldInvGraphicBounds.width() > 0)
+ screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldInvGraphicBounds.left, _oldInvGraphicBounds.top),
+ _oldInvGraphicBounds);
+
+ // If a canimation is active, restore the graphics underneath it
+ if (scene._activeCAnim._images != nullptr)
+ screen.restoreBackground(scene._activeCAnim._oldBounds);
+
+ // If a canimation just ended, remove it's graphics from the backbuffer
+ if (scene._activeCAnim._removeBounds.width() > 0)
+ screen.restoreBackground(scene._activeCAnim._removeBounds);
+}
+
+} // End of namespace Tattoo
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h
index 2203ddf..7a640ef 100644
--- a/engines/sherlock/user_interface.h
+++ b/engines/sherlock/user_interface.h
@@ -137,6 +137,8 @@ public:
virtual void printObjectDesc() {}
};
+namespace Scalpel {
+
class ScalpelUserInterface: public UserInterface {
friend class Inventory;
friend class Settings;
@@ -314,9 +316,24 @@ public:
virtual void printObjectDesc();
};
+} // End of namespace Scalpel
+
+namespace Tattoo {
+
class TattooUserInterface : public UserInterface {
+private:
+ Common::Rect _menuBounds;
+ Common::Rect _oldMenuBounds;
+ Common::Rect _invMenuBounds;
+ Common::Rect _oldInvMenuBounds;
+ Common::Rect _oldTagBounds;
+ Common::Rect _oldInvGraphicBounds;
+ Surface *_menuBuffer;
+ Surface *_invMenuBuffer;
public:
TattooUserInterface(SherlockEngine *vm);
+
+ void doBgAnimRestoreUI();
public:
virtual ~TattooUserInterface() {}
@@ -326,6 +343,8 @@ public:
virtual void handleInput();
};
+} // End of namespace Tattoo
+
} // End of namespace Sherlock
#endif
Commit: 45b4989b55a043a9d2f1806db375d9f91476ed89
https://github.com/scummvm/scummvm/commit/45b4989b55a043a9d2f1806db375d9f91476ed89
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-27T22:36:51-04:00
Commit Message:
SHERLOCK: Implement RT scrolling code
Changed paths:
engines/sherlock/people.cpp
engines/sherlock/people.h
engines/sherlock/scene.cpp
engines/sherlock/scene.h
engines/sherlock/screen.cpp
engines/sherlock/screen.h
engines/sherlock/user_interface.cpp
engines/sherlock/user_interface.h
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp
index 6beae48..f8dd8e2 100644
--- a/engines/sherlock/people.cpp
+++ b/engines/sherlock/people.cpp
@@ -97,6 +97,7 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) {
_hSavedFacing = -1;
_forceWalkReload = false;
_useWalkLib = false;
+ _walkControl = 0;
_portrait._sequences = new byte[32];
}
diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h
index 272c418..f4aba5a 100644
--- a/engines/sherlock/people.h
+++ b/engines/sherlock/people.h
@@ -114,6 +114,8 @@ public:
int _holmesQuotient;
bool _forceWalkReload;
bool _useWalkLib;
+
+ int _walkControl;
public:
People(SherlockEngine *vm);
~People();
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 18690fb..06bbabf 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -1740,7 +1740,7 @@ void TattooScene::doBgAnimCheckCursor() {
}
}
-void TattooScene::doBgAnimHandleMask() {
+void TattooScene::doBgAnimEraseBackground() {
TattooEngine &vm = *((TattooEngine *)_vm);
People &people = *_vm->_people;
Screen &screen = *_vm->_screen;
@@ -1813,6 +1813,37 @@ void TattooScene::doBgAnimHandleMask() {
if (vm._creditsActive)
vm.eraseCredits();
}
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &obj = _bgShapes[idx];
+
+ if (obj._type == NO_SHAPE && (obj._flags & 1) == 0) {
+ screen._backBuffer1.blitFrom(screen._backBuffer2, obj._position, obj.getNoShapeBounds());
+
+ obj._oldPosition = obj._position;
+ obj._oldSize = obj._noShapeSize;
+ }
+ }
+
+ // Adjust the Target Scroll if needed
+ if ((people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER - screen._currentScroll) <
+ (SHERLOCK_SCREEN_WIDTH / 8) && people[people._walkControl]._delta.x < 0) {
+
+ screen._targetScroll = (short)(people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER -
+ SHERLOCK_SCREEN_WIDTH / 8 - 250);
+ if (screen._targetScroll < 0)
+ screen._targetScroll = 0;
+ }
+
+ if ((people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER - screen._currentScroll) > (SHERLOCK_SCREEN_WIDTH / 4 * 3)
+ && people[people._walkControl]._delta.x > 0)
+ screen._targetScroll = (short)(people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER -
+ SHERLOCK_SCREEN_WIDTH / 4 * 3 + 250);
+
+ if (screen._targetScroll > screen._scrollSize)
+ screen._targetScroll = screen._scrollSize;
+
+ ui.doScroll();
}
void TattooScene::doBgAnim() {
@@ -1827,6 +1858,7 @@ void TattooScene::doBgAnim() {
screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
talk._talkToAbort = false;
+ // Check the characters and sprites for updates
for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
if (people[idx]._type == CHARACTER)
people[idx].checkSprite();
@@ -1836,6 +1868,9 @@ void TattooScene::doBgAnim() {
if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE)
_bgShapes[idx].checkObject();
}
+
+ // Erase any affected background areas
+ doBgAnimEraseBackground();
}
} // End of namespace Tattoo
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index 1bd23fc..ce07850 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -351,7 +351,7 @@ private:
private:
void doBgAnimCheckCursor();
- void doBgAnimHandleMask();
+ void doBgAnimEraseBackground();
protected:
/**
* Checks all the background shapes. If a background shape is animating,
diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp
index 4dd91cf..350341f 100644
--- a/engines/sherlock/screen.cpp
+++ b/engines/sherlock/screen.cpp
@@ -45,8 +45,10 @@ Screen::Screen(SherlockEngine *vm) : Surface(g_system->getWidth(), g_system->get
_fadeBytesRead = _fadeBytesToRead = 0;
_oldFadePercent = 0;
_scrollSize = 0;
+ _scrollSpeed = 0;
_currentScroll = 0;
_targetScroll = 0;
+ _flushScreen = false;
}
Screen::~Screen() {
diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h
index e730329..ae368cf 100644
--- a/engines/sherlock/screen.h
+++ b/engines/sherlock/screen.h
@@ -71,8 +71,6 @@ private:
int _oldFadePercent;
byte _lookupTable[PALETTE_COUNT];
byte _lookupTable1[PALETTE_COUNT];
- int _scrollSize;
- int _targetScroll;
private:
/**
* Merges together overlapping dirty areas of the screen
@@ -101,7 +99,9 @@ public:
byte _cMap[PALETTE_SIZE];
byte _sMap[PALETTE_SIZE];
byte _tMap[PALETTE_SIZE];
- int _currentScroll;
+ int _currentScroll, _targetScroll;
+ int _scrollSize, _scrollSpeed;
+ bool _flushScreen;
public:
Screen(SherlockEngine *vm);
virtual ~Screen();
diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp
index 06ec62b..5858daf 100644
--- a/engines/sherlock/user_interface.cpp
+++ b/engines/sherlock/user_interface.cpp
@@ -2352,6 +2352,31 @@ void TattooUserInterface::doBgAnimRestoreUI() {
screen.restoreBackground(scene._activeCAnim._removeBounds);
}
+void TattooUserInterface::doScroll() {
+ Screen &screen = *_vm->_screen;
+ int oldScroll = screen._currentScroll;
+
+ // If we're already at the target scroll position, nothing needs to be done
+ if (screen._targetScroll == screen._currentScroll)
+ return;
+
+ screen._flushScreen = true;
+ if (screen._targetScroll > screen._currentScroll) {
+ screen._currentScroll += screen._scrollSpeed;
+ if (screen._currentScroll > screen._targetScroll)
+ screen._currentScroll = screen._targetScroll;
+ } else if (screen._targetScroll < screen._currentScroll) {
+ screen._currentScroll -= screen._scrollSpeed;
+ if (screen._currentScroll < screen._targetScroll)
+ screen._currentScroll = screen._targetScroll;
+ }
+
+ if (_menuBuffer != nullptr)
+ _menuBounds.translate(screen._currentScroll - oldScroll, 0);
+ if (_invMenuBuffer != nullptr)
+ _invMenuBounds.translate(screen._currentScroll - oldScroll, 0);
+}
+
} // End of namespace Tattoo
} // End of namespace Sherlock
diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h
index 7a640ef..dfd6d02 100644
--- a/engines/sherlock/user_interface.h
+++ b/engines/sherlock/user_interface.h
@@ -333,7 +333,15 @@ private:
public:
TattooUserInterface(SherlockEngine *vm);
+ /**
+ * Handles restoring any areas of the back buffer that were/are covered by UI elements
+ */
void doBgAnimRestoreUI();
+
+ /**
+ * Checks to see if the screen needs to be scrolled. If so, scrolls it towards the target position
+ */
+ void doScroll();
public:
virtual ~TattooUserInterface() {}
Commit: f4902b516ec8486338b777354809171112671e5b
https://github.com/scummvm/scummvm/commit/f4902b516ec8486338b777354809171112671e5b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-28T08:31:53-04:00
Commit Message:
SHERLOCK: Moving split up classes into their own files
Changed paths:
A engines/sherlock/scalpel/scalpel_scene.cpp
A engines/sherlock/scalpel/scalpel_scene.h
A engines/sherlock/scalpel/scalpel_user_interface.cpp
A engines/sherlock/scalpel/scalpel_user_interface.h
A engines/sherlock/scalpel/settings.cpp
A engines/sherlock/scalpel/settings.h
A engines/sherlock/tattoo/tattoo_scene.cpp
A engines/sherlock/tattoo/tattoo_scene.h
A engines/sherlock/tattoo/tattoo_user_interface.cpp
A engines/sherlock/tattoo/tattoo_user_interface.h
R engines/sherlock/settings.cpp
R engines/sherlock/settings.h
engines/sherlock/inventory.cpp
engines/sherlock/module.mk
engines/sherlock/scene.cpp
engines/sherlock/scene.h
engines/sherlock/talk.cpp
engines/sherlock/user_interface.cpp
engines/sherlock/user_interface.h
diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp
index 7ec0b64..a8ecb64 100644
--- a/engines/sherlock/inventory.cpp
+++ b/engines/sherlock/inventory.cpp
@@ -22,6 +22,7 @@
#include "sherlock/inventory.h"
#include "sherlock/sherlock.h"
+#include "sherlock/scalpel/scalpel_user_interface.h"
namespace Sherlock {
@@ -200,29 +201,29 @@ void Inventory::drawInventory(InvNewMode mode) {
INV_BACKGROUND);
// Draw the buttons
- screen.makeButton(Common::Rect(INVENTORY_POINTS[0][0], CONTROLS_Y1, INVENTORY_POINTS[0][1],
- CONTROLS_Y1 + 10), INVENTORY_POINTS[0][2] - screen.stringWidth("Exit") / 2, "Exit");
- screen.makeButton(Common::Rect(INVENTORY_POINTS[1][0], CONTROLS_Y1, INVENTORY_POINTS[1][1],
- CONTROLS_Y1 + 10), INVENTORY_POINTS[1][2] - screen.stringWidth("Look") / 2, "Look");
- screen.makeButton(Common::Rect(INVENTORY_POINTS[2][0], CONTROLS_Y1, INVENTORY_POINTS[2][1],
- CONTROLS_Y1 + 10), INVENTORY_POINTS[2][2] - screen.stringWidth("Use") / 2, "Use");
- screen.makeButton(Common::Rect(INVENTORY_POINTS[3][0], CONTROLS_Y1, INVENTORY_POINTS[3][1],
- CONTROLS_Y1 + 10), INVENTORY_POINTS[3][2] - screen.stringWidth("Give") / 2, "Give");
- screen.makeButton(Common::Rect(INVENTORY_POINTS[4][0], CONTROLS_Y1, INVENTORY_POINTS[4][1],
- CONTROLS_Y1 + 10), INVENTORY_POINTS[4][2], "^^");
- screen.makeButton(Common::Rect(INVENTORY_POINTS[5][0], CONTROLS_Y1, INVENTORY_POINTS[5][1],
- CONTROLS_Y1 + 10), INVENTORY_POINTS[5][2], "^");
- screen.makeButton(Common::Rect(INVENTORY_POINTS[6][0], CONTROLS_Y1, INVENTORY_POINTS[6][1],
- CONTROLS_Y1 + 10), INVENTORY_POINTS[6][2], "_");
- screen.makeButton(Common::Rect(INVENTORY_POINTS[7][0], CONTROLS_Y1, INVENTORY_POINTS[7][1],
- CONTROLS_Y1 + 10), INVENTORY_POINTS[7][2], "__");
+ screen.makeButton(Common::Rect(Scalpel::INVENTORY_POINTS[0][0], CONTROLS_Y1, Scalpel::INVENTORY_POINTS[0][1],
+ CONTROLS_Y1 + 10), Scalpel::INVENTORY_POINTS[0][2] - screen.stringWidth("Exit") / 2, "Exit");
+ screen.makeButton(Common::Rect(Scalpel::INVENTORY_POINTS[1][0], CONTROLS_Y1, Scalpel::INVENTORY_POINTS[1][1],
+ CONTROLS_Y1 + 10), Scalpel::INVENTORY_POINTS[1][2] - screen.stringWidth("Look") / 2, "Look");
+ screen.makeButton(Common::Rect(Scalpel::INVENTORY_POINTS[2][0], CONTROLS_Y1, Scalpel::INVENTORY_POINTS[2][1],
+ CONTROLS_Y1 + 10), Scalpel::INVENTORY_POINTS[2][2] - screen.stringWidth("Use") / 2, "Use");
+ screen.makeButton(Common::Rect(Scalpel::INVENTORY_POINTS[3][0], CONTROLS_Y1, Scalpel::INVENTORY_POINTS[3][1],
+ CONTROLS_Y1 + 10), Scalpel::INVENTORY_POINTS[3][2] - screen.stringWidth("Give") / 2, "Give");
+ screen.makeButton(Common::Rect(Scalpel::INVENTORY_POINTS[4][0], CONTROLS_Y1, Scalpel::INVENTORY_POINTS[4][1],
+ CONTROLS_Y1 + 10), Scalpel::INVENTORY_POINTS[4][2], "^^");
+ screen.makeButton(Common::Rect(Scalpel::INVENTORY_POINTS[5][0], CONTROLS_Y1, Scalpel::INVENTORY_POINTS[5][1],
+ CONTROLS_Y1 + 10), Scalpel::INVENTORY_POINTS[5][2], "^");
+ screen.makeButton(Common::Rect(Scalpel::INVENTORY_POINTS[6][0], CONTROLS_Y1, Scalpel::INVENTORY_POINTS[6][1],
+ CONTROLS_Y1 + 10), Scalpel::INVENTORY_POINTS[6][2], "_");
+ screen.makeButton(Common::Rect(Scalpel::INVENTORY_POINTS[7][0], CONTROLS_Y1, Scalpel::INVENTORY_POINTS[7][1],
+ CONTROLS_Y1 + 10), Scalpel::INVENTORY_POINTS[7][2], "__");
if (tempMode == INVENTORY_DONT_DISPLAY)
mode = LOOK_INVENTORY_MODE;
_invMode = (InvMode)mode;
if (mode != PLAIN_INVENTORY) {
- ui._oldKey = INVENTORY_COMMANDS[(int)mode];
+ ui._oldKey = Scalpel::INVENTORY_COMMANDS[(int)mode];
} else {
ui._oldKey = -1;
}
@@ -252,55 +253,55 @@ void Inventory::invCommands(bool slamIt) {
UserInterface &ui = *_vm->_ui;
if (slamIt) {
- screen.buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1),
+ screen.buttonPrint(Common::Point(Scalpel::INVENTORY_POINTS[0][2], CONTROLS_Y1),
_invMode == INVMODE_EXIT ? COMMAND_HIGHLIGHTED :COMMAND_FOREGROUND,
true, "Exit");
- screen.buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1),
+ screen.buttonPrint(Common::Point(Scalpel::INVENTORY_POINTS[1][2], CONTROLS_Y1),
_invMode == INVMODE_LOOK ? COMMAND_HIGHLIGHTED :COMMAND_FOREGROUND,
true, "Look");
- screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1),
+ screen.buttonPrint(Common::Point(Scalpel::INVENTORY_POINTS[2][2], CONTROLS_Y1),
_invMode == INVMODE_USE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
true, "Use");
- screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1),
+ screen.buttonPrint(Common::Point(Scalpel::INVENTORY_POINTS[3][2], CONTROLS_Y1),
_invMode == INVMODE_GIVE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
true, "Give");
- screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1),
+ screen.print(Common::Point(Scalpel::INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1),
_invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND,
"^^");
- screen.print(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1 + 1),
+ screen.print(Common::Point(Scalpel::INVENTORY_POINTS[5][2], CONTROLS_Y1 + 1),
_invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND,
"^");
- screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1),
+ screen.print(Common::Point(Scalpel::INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1),
(_holdings - _invIndex <= 6) ? COMMAND_NULL : COMMAND_FOREGROUND,
"_");
- screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1),
+ screen.print(Common::Point(Scalpel::INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1),
(_holdings - _invIndex <= 6) ? COMMAND_NULL : COMMAND_FOREGROUND,
"__");
if (_invMode != INVMODE_LOOK)
ui.clearInfo();
} else {
- screen.buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1),
+ screen.buttonPrint(Common::Point(Scalpel::INVENTORY_POINTS[0][2], CONTROLS_Y1),
_invMode == INVMODE_EXIT ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
false, "Exit");
- screen.buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1),
+ screen.buttonPrint(Common::Point(Scalpel::INVENTORY_POINTS[1][2], CONTROLS_Y1),
_invMode == INVMODE_LOOK ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
false, "Look");
- screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1),
+ screen.buttonPrint(Common::Point(Scalpel::INVENTORY_POINTS[2][2], CONTROLS_Y1),
_invMode == INVMODE_USE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
false, "Use");
- screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1),
+ screen.buttonPrint(Common::Point(Scalpel::INVENTORY_POINTS[3][2], CONTROLS_Y1),
_invMode == INVMODE_GIVE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
false, "Give");
- screen.gPrint(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1),
+ screen.gPrint(Common::Point(Scalpel::INVENTORY_POINTS[4][2], CONTROLS_Y1),
_invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND,
"^^");
- screen.gPrint(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1),
+ screen.gPrint(Common::Point(Scalpel::INVENTORY_POINTS[5][2], CONTROLS_Y1),
_invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND,
"^");
- screen.gPrint(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1),
+ screen.gPrint(Common::Point(Scalpel::INVENTORY_POINTS[6][2], CONTROLS_Y1),
(_holdings - _invIndex < 7) ? COMMAND_NULL : COMMAND_FOREGROUND,
"_");
- screen.gPrint(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1),
+ screen.gPrint(Common::Point(Scalpel::INVENTORY_POINTS[7][2], CONTROLS_Y1),
(_holdings - _invIndex < 7) ? COMMAND_NULL : COMMAND_FOREGROUND,
"__");
}
diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk
index 2ded999..cee48ae 100644
--- a/engines/sherlock/module.mk
+++ b/engines/sherlock/module.mk
@@ -3,7 +3,12 @@ MODULE := engines/sherlock
MODULE_OBJS = \
scalpel/darts.o \
scalpel/scalpel.o \
+ scalpel/scalpel_scene.o \
+ scalpel/scalpel_user_interface.o \
+ scalpel/settings.o \
tattoo/tattoo.o \
+ tattoo/tattoo_scene.o \
+ tattoo/tattoo_user_interface.o \
animation.o \
debugger.o \
detection.o \
@@ -17,7 +22,6 @@ MODULE_OBJS = \
saveload.o \
scene.o \
screen.o \
- settings.o \
sherlock.o \
sound.o \
surface.o \
diff --git a/engines/sherlock/scalpel/scalpel_scene.cpp b/engines/sherlock/scalpel/scalpel_scene.cpp
new file mode 100644
index 0000000..b6a4241
--- /dev/null
+++ b/engines/sherlock/scalpel/scalpel_scene.cpp
@@ -0,0 +1,381 @@
+/* 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/scalpel/scalpel_scene.h"
+#include "sherlock/scalpel/scalpel.h"
+#include "sherlock/events.h"
+#include "sherlock/people.h"
+#include "sherlock/screen.h"
+
+namespace Sherlock {
+
+namespace Scalpel {
+
+void ScalpelScene::checkBgShapes() {
+ People &people = *_vm->_people;
+ Person &holmes = people._player;
+ Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
+
+ // Call the base scene method to handle bg shapes
+ Scene::checkBgShapes();
+
+ // Iterate through the canim list
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ Object &obj = _canimShapes[idx];
+ if (obj._type == STATIC_BG_SHAPE || obj._type == ACTIVE_BG_SHAPE) {
+ if ((obj._flags & 5) == 1) {
+ obj._misc = (pt.y < (obj._position.y + obj._imageFrame->_frame.h - 1)) ?
+ NORMAL_FORWARD : NORMAL_BEHIND;
+ } else if (!(obj._flags & 1)) {
+ obj._misc = BEHIND;
+ } else if (obj._flags & 4) {
+ obj._misc = FORWARD;
+ }
+ }
+ }
+}
+
+void ScalpelScene::doBgAnimCheckCursor() {
+ Inventory &inv = *_vm->_inventory;
+ Events &events = *_vm->_events;
+ Sound &sound = *_vm->_sound;
+ UserInterface &ui = *_vm->_ui;
+ Common::Point mousePos = events.mousePos();
+
+ if (ui._menuMode == LOOK_MODE) {
+ if (mousePos.y > CONTROLS_Y1)
+ events.setCursor(ARROW);
+ else if (mousePos.y < CONTROLS_Y)
+ events.setCursor(MAGNIFY);
+ }
+
+ // Check for setting magnifying glass cursor
+ if (ui._menuMode == INV_MODE || ui._menuMode == USE_MODE || ui._menuMode == GIVE_MODE) {
+ if (inv._invMode == INVMODE_LOOK) {
+ // Only show Magnifying glass cursor if it's not on the inventory command line
+ if (mousePos.y < CONTROLS_Y || mousePos.y >(CONTROLS_Y1 + 13))
+ events.setCursor(MAGNIFY);
+ else
+ events.setCursor(ARROW);
+ } else {
+ events.setCursor(ARROW);
+ }
+ }
+
+ if (sound._diskSoundPlaying && !*sound._soundIsOn) {
+ // Loaded sound just finished playing
+ sound.freeDigiSound();
+ }
+}
+
+void ScalpelScene::doBgAnim() {
+ ScalpelEngine &vm = *((ScalpelEngine *)_vm);
+ Events &events = *_vm->_events;
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
+ Talk &talk = *_vm->_talk;
+
+ screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
+ talk._talkToAbort = false;
+
+ if (_restoreFlag) {
+ for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
+ if (people[idx]._type == CHARACTER)
+ people[idx].checkSprite();
+ }
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE)
+ _bgShapes[idx].checkObject();
+ }
+
+ if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE)
+ people._portrait.checkObject();
+
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ if (_canimShapes[idx]._type != INVALID && _canimShapes[idx]._type != REMOVE)
+ _canimShapes[idx].checkObject();
+ }
+
+ if (_currentScene == 12)
+ vm.eraseMirror12();
+
+ // Restore the back buffer from the back buffer 2 in the changed area
+ Common::Rect bounds(people[AL]._oldPosition.x, people[AL]._oldPosition.y,
+ people[AL]._oldPosition.x + people[AL]._oldSize.x,
+ people[AL]._oldPosition.y + people[AL]._oldSize.y);
+ Common::Point pt(bounds.left, bounds.top);
+
+ if (people[AL]._type == CHARACTER)
+ screen.restoreBackground(bounds);
+ else if (people[AL]._type == REMOVE)
+ screen._backBuffer->blitFrom(screen._backBuffer2, pt, bounds);
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if (o._type == ACTIVE_BG_SHAPE || o._type == HIDE_SHAPE || o._type == REMOVE)
+ screen.restoreBackground(o.getOldBounds());
+ }
+
+ if (people._portraitLoaded)
+ screen.restoreBackground(Common::Rect(
+ people._portrait._oldPosition.x, people._portrait._oldPosition.y,
+ people._portrait._oldPosition.x + people._portrait._oldSize.x,
+ people._portrait._oldPosition.y + people._portrait._oldSize.y
+ ));
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if (o._type == NO_SHAPE && ((o._flags & OBJ_BEHIND) == 0)) {
+ // Restore screen area
+ screen._backBuffer->blitFrom(screen._backBuffer2, o._position,
+ Common::Rect(o._position.x, o._position.y,
+ o._position.x + o._noShapeSize.x, o._position.y + o._noShapeSize.y));
+
+ o._oldPosition = o._position;
+ o._oldSize = o._noShapeSize;
+ }
+ }
+
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ Object &o = _canimShapes[idx];
+ if (o._type == ACTIVE_BG_SHAPE || o._type == HIDE_SHAPE || o._type == REMOVE)
+ screen.restoreBackground(Common::Rect(o._oldPosition.x, o._oldPosition.y,
+ o._oldPosition.x + o._oldSize.x, o._oldPosition.y + o._oldSize.y));
+ }
+ }
+
+ //
+ // Update the background objects and canimations
+ //
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if (o._type == ACTIVE_BG_SHAPE || o._type == NO_SHAPE)
+ o.adjustObject();
+ }
+
+ if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE)
+ people._portrait.adjustObject();
+
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ if (_canimShapes[idx]._type != INVALID)
+ _canimShapes[idx].adjustObject();
+ }
+
+ if (people[AL]._type == CHARACTER && people._holmesOn)
+ people[AL].adjustSprite();
+
+ // Flag the bg shapes which need to be redrawn
+ checkBgShapes();
+
+ if (_currentScene == 12)
+ vm.doMirror12();
+
+ // Draw all active shapes which are behind the person
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND)
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ }
+
+ // Draw all canimations which are behind the person
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ Object &o = _canimShapes[idx];
+ if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND) {
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ }
+ }
+
+ // Draw all active shapes which are HAPPEN and behind the person
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND)
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ }
+
+ // Draw all canimations which are NORMAL and behind the person
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ Object &o = _canimShapes[idx];
+ if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND) {
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ }
+ }
+
+ // Draw the person if not animating
+ if (people[AL]._type == CHARACTER && people[AL]._walkLoaded) {
+ // If Holmes is too far to the right, move him back so he's on-screen
+ int xRight = SHERLOCK_SCREEN_WIDTH - 2 - people[AL]._imageFrame->_frame.w;
+ int tempX = MIN(people[AL]._position.x / FIXED_INT_MULTIPLIER, xRight);
+
+ bool flipped = people[AL]._sequenceNumber == WALK_LEFT || people[AL]._sequenceNumber == STOP_LEFT ||
+ people[AL]._sequenceNumber == WALK_UPLEFT || people[AL]._sequenceNumber == STOP_UPLEFT ||
+ people[AL]._sequenceNumber == WALK_DOWNRIGHT || people[AL]._sequenceNumber == STOP_DOWNRIGHT;
+ screen._backBuffer->transBlitFrom(*people[AL]._imageFrame,
+ Common::Point(tempX, people[AL]._position.y / FIXED_INT_MULTIPLIER - people[AL]._imageFrame->_frame.h), flipped);
+ }
+
+ // Draw all static and active shapes are NORMAL and are in front of the person
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD)
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ }
+
+ // Draw all static and active canimations that are NORMAL and are in front of the person
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ Object &o = _canimShapes[idx];
+ if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD) {
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ }
+ }
+
+ // Draw all static and active shapes that are in front of the person
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD)
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ }
+
+ // Draw any active portrait
+ if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE)
+ screen._backBuffer->transBlitFrom(*people._portrait._imageFrame,
+ people._portrait._position, people._portrait._flags & OBJ_FLIPPED);
+
+ // Draw all static and active canimations that are in front of the person
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ Object &o = _canimShapes[idx];
+ if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD) {
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ }
+ }
+
+ // Draw all NO_SHAPE shapes which have flag bit 0 clear
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if (o._type == NO_SHAPE && (o._flags & OBJ_BEHIND) == 0)
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+ }
+
+ // Bring the newly built picture to the screen
+ if (_animating == 2) {
+ _animating = 0;
+ screen.slamRect(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
+ } else {
+ if (people[AL]._type != INVALID && ((_goToScene == -1 || _canimShapes.empty()))) {
+ if (people[AL]._type == REMOVE) {
+ screen.slamRect(Common::Rect(
+ people[AL]._oldPosition.x, people[AL]._oldPosition.y,
+ people[AL]._oldPosition.x + people[AL]._oldSize.x,
+ people[AL]._oldPosition.y + people[AL]._oldSize.y
+ ));
+ people[AL]._type = INVALID;
+ } else {
+ screen.flushImage(people[AL]._imageFrame,
+ Common::Point(people[AL]._position.x / FIXED_INT_MULTIPLIER,
+ people[AL]._position.y / FIXED_INT_MULTIPLIER - people[AL].frameHeight()),
+ &people[AL]._oldPosition.x, &people[AL]._oldPosition.y,
+ &people[AL]._oldSize.x, &people[AL]._oldSize.y);
+ }
+ }
+
+ if (_currentScene == 12)
+ vm.flushMirror12();
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if ((o._type == ACTIVE_BG_SHAPE || o._type == REMOVE) && _goToScene == -1) {
+ screen.flushImage(o._imageFrame, o._position,
+ &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y);
+ }
+ }
+
+ if (people._portraitLoaded) {
+ if (people._portrait._type == REMOVE)
+ screen.slamRect(Common::Rect(
+ people._portrait._position.x, people._portrait._position.y,
+ people._portrait._position.x + people._portrait._delta.x,
+ people._portrait._position.y + people._portrait._delta.y
+ ));
+ else
+ screen.flushImage(people._portrait._imageFrame, people._portrait._position,
+ &people._portrait._oldPosition.x, &people._portrait._oldPosition.y,
+ &people._portrait._oldSize.x, &people._portrait._oldSize.y);
+
+ if (people._portrait._type == REMOVE)
+ people._portrait._type = INVALID;
+ }
+
+ if (_goToScene == -1) {
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &o = _bgShapes[idx];
+ if (o._type == NO_SHAPE && (o._flags & OBJ_BEHIND) == 0) {
+ screen.slamArea(o._position.x, o._position.y, o._oldSize.x, o._oldSize.y);
+ screen.slamArea(o._oldPosition.x, o._oldPosition.y, o._oldSize.x, o._oldSize.y);
+ } else if (o._type == HIDE_SHAPE) {
+ // Hiding shape, so flush it out and mark it as hidden
+ screen.flushImage(o._imageFrame, o._position,
+ &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y);
+ o._type = HIDDEN;
+ }
+ }
+ }
+
+ for (int idx = _canimShapes.size() - 1; idx >= 0; --idx) {
+ Object &o = _canimShapes[idx];
+
+ if (o._type == INVALID) {
+ // Anim shape was invalidated by checkEndOfSequence, so at this point we can remove it
+ _canimShapes.remove_at(idx);
+ } else if (o._type == REMOVE) {
+ if (_goToScene == -1)
+ screen.slamArea(o._position.x, o._position.y, o._delta.x, o._delta.y);
+
+ // Shape for an animation is no longer needed, so remove it completely
+ _canimShapes.remove_at(idx);
+ } else if (o._type == ACTIVE_BG_SHAPE) {
+ screen.flushImage(o._imageFrame, o._position,
+ &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y);
+ }
+ }
+ }
+
+ _restoreFlag = true;
+ _doBgAnimDone = true;
+
+ events.wait(3);
+ screen.resetDisplayBounds();
+
+ // Check if the method was called for calling a portrait, and a talk was
+ // interrupting it. This talk file would not have been executed at the time,
+ // since we needed to finish the 'doBgAnim' to finish clearing the portrait
+ if (people._clearingThePortrait && talk._scriptMoreFlag == 3) {
+ // Reset the flags and call to talk
+ people._clearingThePortrait = false;
+ talk._scriptMoreFlag = 0;
+ talk.talkTo(talk._scriptName);
+ }
+}
+
+} // End of namespace Scalpel
+
+} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel_scene.h b/engines/sherlock/scalpel/scalpel_scene.h
new file mode 100644
index 0000000..e5a442f
--- /dev/null
+++ b/engines/sherlock/scalpel/scalpel_scene.h
@@ -0,0 +1,61 @@
+/* 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.
+ *
+ */
+
+#ifndef SHERLOCK_SCALPEL_SCENE_H
+#define SHERLOCK_SCALPEL_SCENE_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/serializer.h"
+#include "sherlock/objects.h"
+#include "sherlock/scene.h"
+#include "sherlock/screen.h"
+
+namespace Sherlock {
+
+namespace Scalpel {
+
+class ScalpelScene : public Scene {
+private:
+ void doBgAnimCheckCursor();
+protected:
+ /**
+ * Checks all the background shapes. If a background shape is animating,
+ * it will flag it as needing to be drawn. If a non-animating shape is
+ * colliding with another shape, it will also flag it as needing drawing
+ */
+ virtual void checkBgShapes();
+public:
+ ScalpelScene(SherlockEngine *vm) : Scene(vm) {}
+
+ /**
+ * Draw all objects and characters.
+ */
+ virtual void doBgAnim();
+};
+
+} // End of namespace Scalpel
+
+} // End of namespace Sherlock
+
+#endif
diff --git a/engines/sherlock/scalpel/scalpel_user_interface.cpp b/engines/sherlock/scalpel/scalpel_user_interface.cpp
new file mode 100644
index 0000000..f9ec8bb
--- /dev/null
+++ b/engines/sherlock/scalpel/scalpel_user_interface.cpp
@@ -0,0 +1,2276 @@
+/* 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/scalpel/scalpel_user_interface.h"
+#include "sherlock/sherlock.h"
+#include "sherlock/scalpel/settings.h"
+
+namespace Sherlock {
+
+namespace Scalpel {
+
+// Main user interface menu control locations
+const int MENU_POINTS[12][4] = {
+ { 13, 153, 72, 165 },
+ { 13, 169, 72, 181 },
+ { 13, 185, 72, 197 },
+ { 88, 153, 152, 165 },
+ { 88, 169, 152, 181 },
+ { 88, 185, 152, 197 },
+ { 165, 153, 232, 165 },
+ { 165, 169, 232, 181 },
+ { 165, 185, 233, 197 },
+ { 249, 153, 305, 165 },
+ { 249, 169, 305, 181 },
+ { 249, 185, 305, 197 }
+};
+
+// Inventory control locations */
+const int INVENTORY_POINTS[8][3] = {
+ { 4, 50, 29 },
+ { 52, 99, 77 },
+ { 101, 140, 123 },
+ { 142, 187, 166 },
+ { 189, 219, 198 },
+ { 221, 251, 234 },
+ { 253, 283, 266 },
+ { 285, 315, 294 }
+};
+
+const char COMMANDS[13] = "LMTPOCIUGJFS";
+const char INVENTORY_COMMANDS[9] = { "ELUG-+,." };
+const char *const PRESS_KEY_FOR_MORE = "Press any Key for More.";
+const char *const PRESS_KEY_TO_CONTINUE = "Press any Key to Continue.";
+
+const char *const MOPEN[] = {
+ "This cannot be opened", "It is already open", "It is locked", "Wait for Watson", " ", "."
+};
+const char *const MCLOSE[] = {
+ "This cannot be closed", "It is already closed", "The safe door is in the way"
+};
+const char *const MMOVE[] = {
+ "This cannot be moved", "It is bolted to the floor", "It is too heavy", "The other crate is in the way"
+};
+const char *const MPICK[] = {
+ "Nothing of interest here", "It is bolted down", "It is too big to carry", "It is too heavy",
+ "I think a girl would be more your type", "Those flowers belong to Penny", "She's far too young for you!",
+ "I think a girl would be more your type!", "Government property for official use only"
+};
+const char *const MUSE[] = {
+ "You can't do that", "It had no effect", "You can't reach it", "OK, the door looks bigger! Happy?",
+ "Doors don't smoke"
+};
+
+/*----------------------------------------------------------------*/
+
+
+ScalpelUserInterface::ScalpelUserInterface(SherlockEngine *vm): UserInterface(vm) {
+ _controls = new ImageFile("menu.all");
+ _controlPanel = new ImageFile("controls.vgs");
+ _keyPress = '\0';
+ _lookHelp = 0;
+ _bgFound = 0;
+ _oldBgFound = -1;
+ _help = _oldHelp = 0;
+ _key = _oldKey = '\0';
+ _temp = _oldTemp = 0;
+ _oldLook = 0;
+ _keyboardInput = false;
+ _pause = false;
+ _cNum = 0;
+ _find = 0;
+ _oldUse = 0;
+}
+
+ScalpelUserInterface::~ScalpelUserInterface() {
+ delete _controls;
+ delete _controlPanel;
+}
+
+void ScalpelUserInterface::reset() {
+ _oldKey = -1;
+ _help = _oldHelp = -1;
+ _oldTemp = _temp = -1;
+}
+
+void ScalpelUserInterface::drawInterface(int bufferNum) {
+ Screen &screen = *_vm->_screen;
+
+ if (bufferNum & 1)
+ screen._backBuffer1.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y));
+ if (bufferNum & 2)
+ screen._backBuffer2.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y));
+ if (bufferNum == 3)
+ screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK);
+}
+
+void ScalpelUserInterface::handleInput() {
+ Events &events = *_vm->_events;
+ Inventory &inv = *_vm->_inventory;
+ People &people = *_vm->_people;
+ Scene &scene = *_vm->_scene;
+ Screen &screen = *_vm->_screen;
+ Talk &talk = *_vm->_talk;
+
+ if (_menuCounter)
+ whileMenuCounter();
+
+ Common::Point pt = events.mousePos();
+ _bgFound = scene.findBgShape(Common::Rect(pt.x, pt.y, pt.x + 1, pt.y + 1));
+ _keyPress = '\0';
+
+ // Check kbd and set the mouse released flag if Enter or space is pressed.
+ // Otherwise, the pressed _key is stored for later use
+ if (events.kbHit()) {
+ Common::KeyState keyState = events.getKey();
+ _keyPress = keyState.ascii;
+
+ if (keyState.keycode == Common::KEYCODE_x && keyState.flags & Common::KBD_ALT) {
+ _vm->quitGame();
+ events.pollEvents();
+ return;
+ }
+ }
+
+ // Do button highlighting check
+ if (!talk._scriptMoreFlag) { // Don't if scripts are running
+ if (((events._rightPressed || events._rightReleased) && _helpStyle) ||
+ (!_helpStyle && !_menuCounter)) {
+ // Handle any default commands if we're in STD_MODE
+ if (_menuMode == STD_MODE) {
+ if (pt.y < CONTROLS_Y &&
+ (events._rightPressed || (!_helpStyle && !events._released)) &&
+ (_bgFound != -1) && (_bgFound < 1000) &&
+ (scene._bgShapes[_bgFound]._defaultCommand ||
+ !scene._bgShapes[_bgFound]._description.empty())) {
+ // If there is no default command, so set it to Look
+ if (scene._bgShapes[_bgFound]._defaultCommand)
+ _help = scene._bgShapes[_bgFound]._defaultCommand - 1;
+ else
+ _help = 0;
+
+ // Reset 'help' if it is an invalid command
+ if (_help > 5)
+ _help = -1;
+ } else if (pt.y < CONTROLS_Y &&
+ ((events._rightReleased && _helpStyle) || (events._released && !_helpStyle)) &&
+ (_bgFound != -1 && _bgFound < 1000) &&
+ (scene._bgShapes[_bgFound]._defaultCommand ||
+ !scene._bgShapes[_bgFound]._description.empty())) {
+ // If there is no default command, set it to Look
+ if (scene._bgShapes[_bgFound]._defaultCommand)
+ _menuMode = (MenuMode)scene._bgShapes[_bgFound]._defaultCommand;
+ else
+ _menuMode = LOOK_MODE;
+ events._released = true;
+ events._pressed = events._oldButtons = false;
+ _help = _oldHelp = -1;
+
+ if (_menuMode == LOOK_MODE) {
+ // Set the flag to tell the game that this was a right-click
+ // call to look and should exit without the look button being pressed
+ _lookHelp = true;
+ }
+ } else {
+ _help = -1;
+ }
+
+ // Check if highlighting a different button than last time
+ if (_help != _oldHelp) {
+ // If another button was highlighted previously, restore it
+ if (_oldHelp != -1)
+ restoreButton(_oldHelp);
+
+ // If we're highlighting a new button, then draw it pressed
+ if (_help != -1)
+ depressButton(_help);
+
+ _oldHelp = _help;
+ }
+
+ if (_bgFound != _oldBgFound || _oldBgFound == -1) {
+ _infoFlag = true;
+ clearInfo();
+
+ if (_help != -1 && !scene._bgShapes[_bgFound]._description.empty()
+ && scene._bgShapes[_bgFound]._description[0] != ' ')
+ screen.print(Common::Point(0, INFO_LINE + 1),
+ INFO_FOREGROUND, "%s", scene._bgShapes[_bgFound]._description.c_str());
+
+ _oldBgFound = _bgFound;
+ }
+ } else {
+ // We're not in STD_MODE
+ // If there isn't a window open, then revert back to STD_MODE
+ if (!_windowOpen && events._rightReleased) {
+ // Restore all buttons
+ for (int idx = 0; idx < 12; ++idx)
+ restoreButton(idx);
+
+ _menuMode = STD_MODE;
+ _key = _oldKey = -1;
+ _temp = _oldTemp = _lookHelp = _invLookFlag = 0;
+ events.clearEvents();
+ }
+ }
+ }
+ }
+
+ // Reset the old bgshape number if the mouse button is released, so that
+ // it can e re-highlighted when we come back here
+ if ((events._rightReleased && _helpStyle) || (events._released && !_helpStyle))
+ _oldBgFound = -1;
+
+ // Do routines that should be done before input processing
+ switch (_menuMode) {
+ case LOOK_MODE:
+ if (!_windowOpen) {
+ if (events._released && _bgFound >= 0 && _bgFound < 1000) {
+ if (!scene._bgShapes[_bgFound]._examine.empty())
+ examine();
+ } else {
+ lookScreen(pt);
+ }
+ }
+ break;
+
+ case MOVE_MODE:
+ case OPEN_MODE:
+ case CLOSE_MODE:
+ case PICKUP_MODE:
+ lookScreen(pt);
+ break;
+
+ case TALK_MODE:
+ if (!_windowOpen) {
+ bool personFound;
+
+ if (_bgFound >= 1000) {
+ personFound = false;
+ if (!events._released)
+ lookScreen(pt);
+ } else {
+ personFound = _bgFound != -1 && scene._bgShapes[_bgFound]._aType == PERSON;
+ }
+
+ if (events._released && personFound)
+ talk.talk(_bgFound);
+ else if (personFound)
+ lookScreen(pt);
+ else if (_bgFound < 1000)
+ clearInfo();
+ }
+ break;
+
+ case USE_MODE:
+ case GIVE_MODE:
+ case INV_MODE:
+ if (inv._invMode == INVMODE_LOOK || inv._invMode == INVMODE_USE || inv._invMode == INVMODE_GIVE) {
+ if (pt.y > CONTROLS_Y)
+ lookInv();
+ else
+ lookScreen(pt);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ //
+ // Do input processing
+ //
+ if (events._pressed || events._released || events._rightPressed || _keyPress || _pause) {
+ if (((events._released && (_helpStyle || _help == -1)) || (events._rightReleased && !_helpStyle)) &&
+ (pt.y <= CONTROLS_Y) && (_menuMode == STD_MODE)) {
+ // The mouse was clicked in the playing area with no action buttons down.
+ // Check if the mouse was clicked in a script zone. If it was,
+ // then execute the script. Otherwise, walk to the given position
+ if (scene.checkForZones(pt, SCRIPT_ZONE) != 0 ||
+ scene.checkForZones(pt, NOWALK_ZONE) != 0) {
+ // Mouse clicked in script zone
+ events._pressed = events._released = false;
+ } else {
+ people._walkDest = pt;
+ people._allowWalkAbort = false;
+ people.goAllTheWay();
+ }
+
+ if (_oldKey != -1) {
+ restoreButton(_oldTemp);
+ _oldKey = -1;
+ }
+ }
+
+ // Handle action depending on selected mode
+ switch (_menuMode) {
+ case LOOK_MODE:
+ if (_windowOpen)
+ doLookControl();
+ break;
+
+ case MOVE_MODE:
+ doMiscControl(ALLOW_MOVE);
+ break;
+
+ case TALK_MODE:
+ if (_windowOpen)
+ doTalkControl();
+ break;
+
+ case OPEN_MODE:
+ doMiscControl(ALLOW_OPEN);
+ break;
+
+ case CLOSE_MODE:
+ doMiscControl(ALLOW_CLOSE);
+ break;
+
+ case PICKUP_MODE:
+ doPickControl();
+ break;
+
+ case USE_MODE:
+ case GIVE_MODE:
+ case INV_MODE:
+ doInvControl();
+ break;
+
+ case FILES_MODE:
+ doEnvControl();
+ break;
+
+ default:
+ break;
+ }
+
+ // As long as there isn't an open window, do main input processing.
+ // Windows are opened when in TALK, USE, INV, and GIVE modes
+ if ((!_windowOpen && !_menuCounter && pt.y > CONTROLS_Y) ||
+ _keyPress) {
+ if (events._pressed || events._released || _pause || _keyPress)
+ doMainControl();
+ }
+
+ if (pt.y < CONTROLS_Y && events._pressed && _oldTemp != (int)(_menuMode - 1) && _oldKey != -1)
+ restoreButton(_oldTemp);
+ }
+}
+
+void ScalpelUserInterface::depressButton(int num) {
+ Screen &screen = *_vm->_screen;
+ Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]);
+
+ ImageFrame &frame = (*_controls)[num];
+ screen._backBuffer1.transBlitFrom(frame, pt);
+ screen.slamArea(pt.x, pt.y, pt.x + frame._width, pt.y + frame._height);
+}
+
+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;
+
+ screen._backBuffer1.blitFrom(screen._backBuffer2, pt,
+ Common::Rect(pt.x, pt.y, pt.x + 90, pt.y + 19));
+ screen.slamArea(pt.x, pt.y, pt.x + frame.w, pt.y + frame.h);
+
+ if (!_menuCounter) {
+ _infoFlag = true;
+ clearInfo();
+ }
+}
+
+void ScalpelUserInterface::pushButton(int num) {
+ Events &events = *_vm->_events;
+ _oldKey = -1;
+
+ if (!events._released) {
+ if (_oldHelp != -1)
+ restoreButton(_oldHelp);
+ if (_help != -1)
+ restoreButton(_help);
+
+ depressButton(num);
+ events.wait(6);
+ }
+
+ restoreButton(num);
+}
+
+void ScalpelUserInterface::toggleButton(int num) {
+ Screen &screen = *_vm->_screen;
+
+ if (_menuMode != (MenuMode)(num + 1)) {
+ _menuMode = (MenuMode)(num + 1);
+ _oldKey = COMMANDS[num];
+ _oldTemp = num;
+
+ if (_keyboardInput) {
+ if (_oldHelp != -1 && _oldHelp != num)
+ restoreButton(_oldHelp);
+ if (_help != -1 && _help != num)
+ restoreButton(_help);
+
+ _keyboardInput = false;
+
+ ImageFrame &frame = (*_controls)[num];
+ Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]);
+ screen._backBuffer1.transBlitFrom(frame, pt);
+ screen.slamArea(pt.x, pt.y, pt.x + frame._width, pt.y + frame._height);
+ }
+ } else {
+ _menuMode = STD_MODE;
+ _oldKey = -1;
+ restoreButton(num);
+ }
+}
+
+void ScalpelUserInterface::clearInfo() {
+ if (_infoFlag) {
+ _vm->_screen->vgaBar(Common::Rect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 19,
+ INFO_LINE + 10), INFO_BLACK);
+ _infoFlag = false;
+ _oldLook = -1;
+ }
+}
+
+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 ScalpelUserInterface::whileMenuCounter() {
+ if (!(--_menuCounter) || _vm->_events->checkInput()) {
+ _menuCounter = 0;
+ _infoFlag = true;
+ clearInfo();
+ }
+}
+
+void ScalpelUserInterface::examine() {
+ Events &events = *_vm->_events;
+ Inventory &inv = *_vm->_inventory;
+ People &people = *_vm->_people;
+ Scene &scene = *_vm->_scene;
+ Talk &talk = *_vm->_talk;
+ Common::Point pt = events.mousePos();
+
+ if (pt.y < (CONTROLS_Y + 9)) {
+ Object &obj = scene._bgShapes[_bgFound];
+
+ if (obj._lookcAnim != 0) {
+ int canimSpeed = ((obj._lookcAnim & 0xe0) >> 5) + 1;
+ scene._cAnimFramePause = obj._lookFrames;
+ _cAnimStr = obj._examine;
+ _cNum = (obj._lookcAnim & 0x1f) - 1;
+
+ scene.startCAnim(_cNum, canimSpeed);
+ } else if (obj._lookPosition.y != 0) {
+ // Need to walk to the object to be examined
+ people.walkToCoords(Common::Point(obj._lookPosition.x, obj._lookPosition.y * 100), obj._lookFacing);
+ }
+
+ if (!talk._talkToAbort) {
+ _cAnimStr = obj._examine;
+ if (obj._lookFlag)
+ _vm->setFlags(obj._lookFlag);
+ }
+ } else {
+ // Looking at an inventory item
+ _cAnimStr = inv[_selector]._examine;
+ if (inv[_selector]._lookFlag)
+ _vm->setFlags(inv[_selector]._lookFlag);
+ }
+
+ if (_invLookFlag) {
+ // Don't close the inventory window when starting an examine display, since its
+ // window will slide up to replace the inventory display
+ _windowOpen = false;
+ _menuMode = LOOK_MODE;
+ }
+
+ if (!talk._talkToAbort) {
+ if (!scene._cAnimFramePause)
+ printObjectDesc(_cAnimStr, true);
+ else
+ // description was already printed in startCAnimation
+ scene._cAnimFramePause = 0;
+ }
+}
+
+void ScalpelUserInterface::lookScreen(const Common::Point &pt) {
+ Events &events = *_vm->_events;
+ Inventory &inv = *_vm->_inventory;
+ Scene &scene = *_vm->_scene;
+ Screen &screen = *_vm->_screen;
+ Common::Point mousePos = events.mousePos();
+ int temp;
+ Common::String tempStr;
+
+ // Don't display anything for right button command
+ if ((events._rightPressed || events._rightPressed) && !events._pressed)
+ return;
+
+ if (mousePos.y < CONTROLS_Y && (temp = _bgFound) != -1) {
+ if (temp != _oldLook) {
+ _infoFlag = true;
+ clearInfo();
+
+ if (temp < 1000)
+ tempStr = scene._bgShapes[temp]._description;
+ else
+ tempStr = scene._bgShapes[temp - 1000]._description;
+
+ _infoFlag = true;
+ clearInfo();
+
+ // Only print description if there is one
+ if (!tempStr.empty() && tempStr[0] != ' ') {
+ // If inventory is active and an item is selected for a Use or Give action
+ if ((_menuMode == INV_MODE || _menuMode == USE_MODE || _menuMode == GIVE_MODE) &&
+ (inv._invMode == INVMODE_USE || inv._invMode == INVMODE_GIVE)) {
+ int width1 = 0, width2 = 0;
+ int x, width;
+ if (inv._invMode == INVMODE_USE) {
+ // Using an object
+ x = width = screen.stringWidth("Use ");
+
+ if (temp < 1000 && scene._bgShapes[temp]._aType != PERSON)
+ // It's not a person, so make it lowercase
+ tempStr.setChar(tolower(tempStr[0]), 0);
+
+ x += screen.stringWidth(tempStr);
+
+ // If we're using an inventory object, add in the width
+ // of the object name and the " on "
+ if (_selector != -1) {
+ width1 = screen.stringWidth(inv[_selector]._name);
+ x += width1;
+ width2 = screen.stringWidth(" on ");
+ x += width2;
+ }
+
+ // If the line will be too long, keep cutting off characters
+ // until the string will fit
+ while (x > 280) {
+ x -= screen.charWidth(tempStr.lastChar());
+ tempStr.deleteLastChar();
+ }
+
+ int xStart = (SHERLOCK_SCREEN_WIDTH - x) / 2;
+ screen.print(Common::Point(xStart, INFO_LINE + 1),
+ INFO_FOREGROUND, "Use ");
+
+ if (_selector != -1) {
+ screen.print(Common::Point(xStart + width, INFO_LINE + 1),
+ TALK_FOREGROUND, "%s", inv[_selector]._name.c_str());
+ screen.print(Common::Point(xStart + width + width1, INFO_LINE + 1),
+ INFO_FOREGROUND, " on ");
+ screen.print(Common::Point(xStart + width + width1 + width2, INFO_LINE + 1),
+ INFO_FOREGROUND, "%s", tempStr.c_str());
+ } else {
+ screen.print(Common::Point(xStart + width, INFO_LINE + 1),
+ INFO_FOREGROUND, "%s", tempStr.c_str());
+ }
+ } else if (temp >= 0 && temp < 1000 && _selector != -1 &&
+ scene._bgShapes[temp]._aType == PERSON) {
+ // Giving an object to a person
+ width1 = screen.stringWidth(inv[_selector]._name);
+ x = width = screen.stringWidth("Give ");
+ x += width1;
+ width2 = screen.stringWidth(" to ");
+ x += width2;
+ x += screen.stringWidth(tempStr);
+
+ // Ensure string will fit on-screen
+ while (x > 280) {
+ x -= screen.charWidth(tempStr.lastChar());
+ tempStr.deleteLastChar();
+ }
+
+ int xStart = (SHERLOCK_SCREEN_WIDTH - x) / 2;
+ screen.print(Common::Point(xStart, INFO_LINE + 1),
+ INFO_FOREGROUND, "Give ");
+ screen.print(Common::Point(xStart + width, INFO_LINE + 1),
+ TALK_FOREGROUND, "%s", inv[_selector]._name.c_str());
+ screen.print(Common::Point(xStart + width + width1, INFO_LINE + 1),
+ INFO_FOREGROUND, " to ");
+ screen.print(Common::Point(xStart + width + width1 + width2, INFO_LINE + 1),
+ INFO_FOREGROUND, "%s", tempStr.c_str());
+ }
+ } else {
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", tempStr.c_str());
+ }
+
+ _infoFlag = true;
+ _oldLook = temp;
+ }
+ }
+ } else {
+ clearInfo();
+ }
+}
+
+void ScalpelUserInterface::lookInv() {
+ Events &events = *_vm->_events;
+ Inventory &inv = *_vm->_inventory;
+ Screen &screen = *_vm->_screen;
+ Common::Point mousePos = events.mousePos();
+
+ if (mousePos.x > 15 && mousePos.x < 314 && mousePos.y > (CONTROLS_Y1 + 11)
+ && mousePos.y < (SHERLOCK_SCREEN_HEIGHT - 2)) {
+ int temp = (mousePos.x - 6) / 52 + inv._invIndex;
+ if (temp < inv._holdings) {
+ if (temp < inv._holdings) {
+ clearInfo();
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND,
+ "%s", inv[temp]._description.c_str());
+ _infoFlag = true;
+ _oldLook = temp;
+ }
+ } else {
+ clearInfo();
+ }
+ } else {
+ clearInfo();
+ }
+}
+
+void ScalpelUserInterface::doEnvControl() {
+ Events &events = *_vm->_events;
+ SaveManager &saves = *_vm->_saves;
+ Scene &scene = *_vm->_scene;
+ Screen &screen = *_vm->_screen;
+ Talk &talk = *_vm->_talk;
+ Common::Point mousePos = events.mousePos();
+ static const char ENV_COMMANDS[7] = "ELSUDQ";
+
+ byte color;
+
+ _key = _oldKey = -1;
+ _keyboardInput = false;
+ int found = saves.getHighlightedButton();
+
+ if (events._pressed || events._released) {
+ events.clearKeyboard();
+
+ // Check for a filename entry being highlighted
+ if ((events._pressed || events._released) && mousePos.y > (CONTROLS_Y + 10)) {
+ int found1 = 0;
+ for (_selector = 0; (_selector < ONSCREEN_FILES_COUNT) && !found1; ++_selector)
+ if (mousePos.y > (CONTROLS_Y + 11 + _selector * 10) && mousePos.y < (CONTROLS_Y + 21 + _selector * 10))
+ found1 = 1;
+
+ if (_selector + saves._savegameIndex - 1 < MAX_SAVEGAME_SLOTS + (saves._envMode != SAVEMODE_LOAD))
+ _selector = _selector + saves._savegameIndex - 1;
+ else
+ _selector = -1;
+
+ if (!found1)
+ _selector = -1;
+ }
+
+ // Handle selecting buttons, if any
+ saves.highlightButtons(found);
+
+ if (found == 0 || found == 5)
+ saves._envMode = SAVEMODE_NONE;
+ }
+
+ if (_keyPress) {
+ _key = toupper(_keyPress);
+
+ // Escape _key will close the dialog
+ if (_key == Common::KEYCODE_ESCAPE)
+ _key = 'E';
+
+ if (_key == 'E' || _key == 'L' || _key == 'S' || _key == 'U' || _key == 'D' || _key == 'Q') {
+ const char *chP = strchr(ENV_COMMANDS, _key);
+ int btnIndex = !chP ? -1 : chP - ENV_COMMANDS;
+ saves.highlightButtons(btnIndex);
+ _keyboardInput = true;
+
+ if (_key == 'E' || _key == 'Q') {
+ saves._envMode = SAVEMODE_NONE;
+ } else if (_key >= '1' && _key <= '9') {
+ _keyboardInput = true;
+ _selector = _key - '1';
+ if (_selector >= MAX_SAVEGAME_SLOTS + (saves._envMode == SAVEMODE_LOAD ? 0 : 1))
+ _selector = -1;
+
+ if (saves.checkGameOnScreen(_selector))
+ _oldSelector = _selector;
+ } else {
+ _selector = -1;
+ }
+ }
+ }
+
+ if (_selector != _oldSelector) {
+ if (_oldSelector != -1 && _oldSelector >= saves._savegameIndex && _oldSelector < (saves._savegameIndex + ONSCREEN_FILES_COUNT)) {
+ screen.print(Common::Point(6, CONTROLS_Y + 12 + (_oldSelector - saves._savegameIndex) * 10),
+ INV_FOREGROUND, "%d.", _oldSelector + 1);
+ screen.print(Common::Point(24, CONTROLS_Y + 12 + (_oldSelector - saves._savegameIndex) * 10),
+ INV_FOREGROUND, "%s", saves._savegames[_oldSelector].c_str());
+ }
+
+ if (_selector != -1) {
+ screen.print(Common::Point(6, CONTROLS_Y + 12 + (_selector - saves._savegameIndex) * 10),
+ TALK_FOREGROUND, "%d.", _selector + 1);
+ screen.print(Common::Point(24, CONTROLS_Y + 12 + (_selector - saves._savegameIndex) * 10),
+ TALK_FOREGROUND, "%s", saves._savegames[_selector].c_str());
+ }
+
+ _oldSelector = _selector;
+ }
+
+ if (events._released || _keyboardInput) {
+ if ((found == 0 && events._released) || _key == 'E') {
+ banishWindow();
+ _windowBounds.top = CONTROLS_Y1;
+
+ events._pressed = events._released = _keyboardInput = false;
+ _keyPress = '\0';
+ } else if ((found == 1 && events._released) || _key == 'L') {
+ saves._envMode = SAVEMODE_LOAD;
+ if (_selector != -1) {
+ saves.loadGame(_selector + 1);
+ }
+ } else if ((found == 2 && events._released) || _key == 'S') {
+ saves._envMode = SAVEMODE_SAVE;
+ if (_selector != -1) {
+ if (saves.checkGameOnScreen(_selector))
+ _oldSelector = _selector;
+
+ if (saves.promptForDescription(_selector)) {
+ saves.saveGame(_selector + 1, saves._savegames[_selector]);
+
+ banishWindow(1);
+ _windowBounds.top = CONTROLS_Y1;
+ _key = _oldKey = -1;
+ _keyPress = '\0';
+ _keyboardInput = false;
+ } else {
+ if (!talk._talkToAbort) {
+ screen._backBuffer1.fillRect(Common::Rect(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10,
+ SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y + 20 + (_selector - saves._savegameIndex) * 10), INV_BACKGROUND);
+ screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10), INV_FOREGROUND,
+ "%d.", _selector + 1);
+ screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10), INV_FOREGROUND,
+ "%s", saves._savegames[_selector].c_str());
+
+ screen.slamArea(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10, 311, 10);
+ _selector = _oldSelector = -1;
+ }
+ }
+ }
+ } else if (((found == 3 && events._released) || _key == 'U') && saves._savegameIndex) {
+ bool moreKeys;
+ do {
+ saves._savegameIndex--;
+ screen._backBuffer1.fillRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2,
+ SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND);
+
+ for (int idx = saves._savegameIndex; idx < (saves._savegameIndex + ONSCREEN_FILES_COUNT); ++idx) {
+ color = INV_FOREGROUND;
+ if (idx == _selector && idx >= saves._savegameIndex && idx < (saves._savegameIndex + ONSCREEN_FILES_COUNT))
+ color = TALK_FOREGROUND;
+
+ screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color, "%d.", idx + 1);
+ screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color, "%s", saves._savegames[idx].c_str());
+ }
+
+ screen.slamRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, SHERLOCK_SCREEN_HEIGHT));
+
+ color = !saves._savegameIndex ? COMMAND_NULL : COMMAND_FOREGROUND;
+ screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), color, true, "Up");
+ color = (saves._savegameIndex == MAX_SAVEGAME_SLOTS - ONSCREEN_FILES_COUNT) ? COMMAND_NULL : COMMAND_FOREGROUND;
+ screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), color, true, "Down");
+
+ // Check whether there are more pending U keys pressed
+ moreKeys = false;
+ if (events.kbHit()) {
+ Common::KeyState keyState = events.getKey();
+
+ _key = toupper(keyState.keycode);
+ moreKeys = _key == 'U';
+ }
+ } while ((saves._savegameIndex) && moreKeys);
+ } else if (((found == 4 && events._released) || _key == 'D') && saves._savegameIndex < (MAX_SAVEGAME_SLOTS - ONSCREEN_FILES_COUNT)) {
+ bool moreKeys;
+ do {
+ saves._savegameIndex++;
+ screen._backBuffer1.fillRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2,
+ SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND);
+
+ for (int idx = saves._savegameIndex; idx < (saves._savegameIndex + ONSCREEN_FILES_COUNT); ++idx) {
+ if (idx == _selector && idx >= saves._savegameIndex && idx < (saves._savegameIndex + ONSCREEN_FILES_COUNT))
+ color = TALK_FOREGROUND;
+ else
+ color = INV_FOREGROUND;
+
+ screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color,
+ "%d.", idx + 1);
+ screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color,
+ "%s", saves._savegames[idx].c_str());
+ }
+
+ screen.slamRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, SHERLOCK_SCREEN_HEIGHT));
+
+ color = (!saves._savegameIndex) ? COMMAND_NULL : COMMAND_FOREGROUND;
+ screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), color, true, "Up");
+
+ color = (saves._savegameIndex == MAX_SAVEGAME_SLOTS - ONSCREEN_FILES_COUNT) ? COMMAND_NULL : COMMAND_FOREGROUND;
+ screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), color, true, "Down");
+
+ // Check whether there are more pending D keys pressed
+ moreKeys = false;
+ if (events.kbHit()) {
+ Common::KeyState keyState;
+ _key = toupper(keyState.keycode);
+
+ moreKeys = _key == 'D';
+ }
+ } while (saves._savegameIndex < (MAX_SAVEGAME_SLOTS - ONSCREEN_FILES_COUNT) && moreKeys);
+ } else if ((found == 5 && events._released) || _key == 'Q') {
+ clearWindow();
+ screen.print(Common::Point(0, CONTROLS_Y + 20), INV_FOREGROUND, "Are you sure you wish to Quit ?");
+ screen.vgaBar(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y + 10), BORDER_COLOR);
+
+ screen.makeButton(Common::Rect(112, CONTROLS_Y, 160, CONTROLS_Y + 10), 136 - screen.stringWidth("Yes") / 2, "Yes");
+ screen.makeButton(Common::Rect(161, CONTROLS_Y, 209, CONTROLS_Y + 10), 184 - screen.stringWidth("No") / 2, "No");
+ screen.slamArea(112, CONTROLS_Y, 97, 10);
+
+ do {
+ scene.doBgAnim();
+
+ if (talk._talkToAbort)
+ return;
+
+ events.pollEventsAndWait();
+ events.setButtonState();
+ mousePos = events.mousePos();
+
+ if (events.kbHit()) {
+ Common::KeyState keyState = events.getKey();
+ _key = toupper(keyState.keycode);
+
+ if (_key == 'X' && (keyState.flags & Common::KBD_ALT) != 0) {
+ _vm->quitGame();
+ events.pollEvents();
+ return;
+ }
+
+ if (_key == Common::KEYCODE_ESCAPE)
+ _key = 'N';
+
+ if (_key == Common::KEYCODE_RETURN || _key == ' ') {
+ events._pressed = false;
+ events._released = true;
+ events._oldButtons = 0;
+ _keyPress = '\0';
+ }
+ }
+
+ if (events._pressed || events._released) {
+ if (mousePos.x > 112 && mousePos.x < 159 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 9))
+ color = COMMAND_HIGHLIGHTED;
+ else
+ color = COMMAND_FOREGROUND;
+ screen.buttonPrint(Common::Point(136, CONTROLS_Y), color, true, "Yes");
+
+ if (mousePos.x > 161 && mousePos.x < 208 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 9))
+ color = COMMAND_HIGHLIGHTED;
+ else
+ color = COMMAND_FOREGROUND;
+ screen.buttonPrint(Common::Point(184, CONTROLS_Y), color, true, "No");
+ }
+
+ if (mousePos.x > 112 && mousePos.x < 159 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 9) && events._released)
+ _key = 'Y';
+
+ if (mousePos.x > 161 && mousePos.x < 208 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 9) && events._released)
+ _key = 'N';
+ } while (!_vm->shouldQuit() && _key != 'Y' && _key != 'N');
+
+ if (_key == 'Y') {
+ _vm->quitGame();
+ events.pollEvents();
+ return;
+ } else {
+ screen.buttonPrint(Common::Point(184, CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "No");
+ banishWindow(1);
+ _windowBounds.top = CONTROLS_Y1;
+ _key = -1;
+ }
+ } else {
+ if (_selector != -1) {
+ // Are we already in Load mode?
+ if (saves._envMode == SAVEMODE_LOAD) {
+ saves.loadGame(_selector + 1);
+ } else if (saves._envMode == SAVEMODE_SAVE || saves.isSlotEmpty(_selector)) {
+ // We're already in save mode, or pointing to an empty save slot
+ if (saves.checkGameOnScreen(_selector))
+ _oldSelector = _selector;
+
+ if (saves.promptForDescription(_selector)) {
+ saves.saveGame(_selector + 1, saves._savegames[_selector]);
+ banishWindow();
+ _windowBounds.top = CONTROLS_Y1;
+ _key = _oldKey = -1;
+ _keyPress = '\0';
+ _keyboardInput = false;
+ } else {
+ if (!talk._talkToAbort) {
+ screen._backBuffer1.fillRect(Common::Rect(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10,
+ 317, CONTROLS_Y + 20 + (_selector - saves._savegameIndex) * 10), INV_BACKGROUND);
+ screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10),
+ INV_FOREGROUND, "%d.", _selector + 1);
+ screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10),
+ INV_FOREGROUND, "%s", saves._savegames[_selector].c_str());
+ screen.slamArea(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10, 311, 10);
+ _selector = _oldSelector = -1;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void ScalpelUserInterface::doInvControl() {
+ Events &events = *_vm->_events;
+ Inventory &inv = *_vm->_inventory;
+ Scene &scene = *_vm->_scene;
+ Screen &screen = *_vm->_screen;
+ Talk &talk = *_vm->_talk;
+ int colors[8];
+ Common::Point mousePos = events.mousePos();
+
+ _key = _oldKey = -1;
+ _keyboardInput = false;
+
+ // Check whether any inventory slot is highlighted
+ int found = -1;
+ Common::fill(&colors[0], &colors[8], (int)COMMAND_FOREGROUND);
+ for (int idx = 0; idx < 8; ++idx) {
+ Common::Rect r(INVENTORY_POINTS[idx][0], CONTROLS_Y1,
+ INVENTORY_POINTS[idx][1], CONTROLS_Y1 + 10);
+ if (r.contains(mousePos)) {
+ found = idx;
+ break;
+ }
+ }
+
+ if (events._pressed || events._released) {
+ events.clearKeyboard();
+
+ if (found != -1)
+ // If a slot highlighted, set its color
+ colors[found] = COMMAND_HIGHLIGHTED;
+ screen.buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1), colors[0], true, "Exit");
+
+ if (found >= 0 && found <= 3) {
+ screen.buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1), colors[1], true, "Look");
+ screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1), colors[2], true, "Use");
+ screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1), colors[3], true, "Give");
+ inv._invMode = (InvMode)found;
+ _selector = -1;
+ }
+
+ if (inv._invIndex) {
+ screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), colors[4], "^^");
+ screen.print(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1 + 1), colors[5], "^");
+ }
+
+ if ((inv._holdings - inv._invIndex) > 6) {
+ screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), colors[6], "_");
+ screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1), colors[7], "__");
+ }
+
+ bool flag = false;
+ if (inv._invMode == INVMODE_LOOK || inv._invMode == INVMODE_USE || inv._invMode == INVMODE_GIVE) {
+ Common::Rect r(15, CONTROLS_Y1 + 11, 314, SHERLOCK_SCREEN_HEIGHT - 2);
+ if (r.contains(mousePos)) {
+ _selector = (mousePos.x - 6) / 52 + inv._invIndex;
+ if (_selector < inv._holdings)
+ flag = true;
+ }
+ }
+
+ if (!flag && mousePos.y >(CONTROLS_Y1 + 11))
+ _selector = -1;
+ }
+
+ if (_keyPress) {
+ _key = toupper(_keyPress);
+
+ if (_key == Common::KEYCODE_ESCAPE)
+ // Escape will also 'E'xit out of inventory display
+ _key = 'E';
+
+ if (_key == 'E' || _key == 'L' || _key == 'U' || _key == 'G'
+ || _key == '-' || _key == '+') {
+ InvMode temp = inv._invMode;
+
+ const char *chP = strchr(INVENTORY_COMMANDS, _key);
+ inv._invMode = !chP ? INVMODE_INVALID : (InvMode)(chP - INVENTORY_COMMANDS);
+ inv.invCommands(true);
+
+ inv._invMode = temp;
+ _keyboardInput = true;
+ if (_key == 'E')
+ inv._invMode = INVMODE_EXIT;
+ _selector = -1;
+ } else {
+ _selector = -1;
+ }
+ }
+
+ if (_selector != _oldSelector) {
+ if (_oldSelector != -1) {
+ // Un-highlight
+ if (_oldSelector >= inv._invIndex && _oldSelector < (inv._invIndex + 6))
+ inv.highlight(_oldSelector, BUTTON_MIDDLE);
+ }
+
+ if (_selector != -1)
+ inv.highlight(_selector, 235);
+
+ _oldSelector = _selector;
+ }
+
+ if (events._released || _keyboardInput) {
+ if ((found == 0 && events._released) || _key == 'E') {
+ inv.freeInv();
+ _infoFlag = true;
+ clearInfo();
+ banishWindow(false);
+ _key = -1;
+ events.clearEvents();
+ events.setCursor(ARROW);
+ } else if ((found == 1 && events._released) || (_key == 'L')) {
+ inv._invMode = INVMODE_LOOK;
+ } else if ((found == 2 && events._released) || (_key == 'U')) {
+ inv._invMode = INVMODE_USE;
+ } else if ((found == 3 && events._released) || (_key == 'G')) {
+ inv._invMode = INVMODE_GIVE;
+ } else if (((found == 4 && events._released) || _key == ',') && inv._invIndex) {
+ if (inv._invIndex >= 6)
+ inv._invIndex -= 6;
+ else
+ inv._invIndex = 0;
+
+ screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1),
+ COMMAND_HIGHLIGHTED, "^^");
+ inv.freeGraphics();
+ inv.loadGraphics();
+ inv.putInv(SLAM_DISPLAY);
+ inv.invCommands(true);
+ } else if (((found == 5 && events._released) || _key == '-') && inv._invIndex > 0) {
+ --inv._invIndex;
+ screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), COMMAND_HIGHLIGHTED, "^");
+ inv.freeGraphics();
+ inv.loadGraphics();
+ inv.putInv(SLAM_DISPLAY);
+ inv.invCommands(true);
+ } else if (((found == 6 && events._released) || _key == '+') && (inv._holdings - inv._invIndex) > 6) {
+ ++inv._invIndex;
+ screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), COMMAND_HIGHLIGHTED, "_");
+ inv.freeGraphics();
+ inv.loadGraphics();
+ inv.putInv(SLAM_DISPLAY);
+ inv.invCommands(true);
+ } else if (((found == 7 && events._released) || _key == '.') && (inv._holdings - inv._invIndex) > 6) {
+ inv._invIndex += 6;
+ if ((inv._holdings - 6) < inv._invIndex)
+ inv._invIndex = inv._holdings - 6;
+
+ screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1), COMMAND_HIGHLIGHTED, "_");
+ inv.freeGraphics();
+ inv.loadGraphics();
+ inv.putInv(SLAM_DISPLAY);
+ inv.invCommands(true);
+ } else {
+ // If something is being given, make sure it's being given to a person
+ if (inv._invMode == INVMODE_GIVE) {
+ if (_bgFound != -1 && scene._bgShapes[_bgFound]._aType == PERSON)
+ _find = _bgFound;
+ else
+ _find = -1;
+ } else {
+ _find = _bgFound;
+ }
+
+ if ((mousePos.y < CONTROLS_Y1) && (inv._invMode == INVMODE_LOOK) && (_find >= 0) && (_find < 1000)) {
+ if (!scene._bgShapes[_find]._examine.empty() &&
+ scene._bgShapes[_find]._examine[0] >= ' ')
+ inv.refreshInv();
+ } else if (_selector != -1 || _find >= 0) {
+ // Selector is the inventory object that was clicked on, or selected.
+ // If it's -1, then no inventory item is highlighted yet. Otherwise,
+ // an object in the scene has been clicked.
+
+ if (_selector != -1 && inv._invMode == INVMODE_LOOK
+ && mousePos.y >(CONTROLS_Y1 + 11))
+ inv.refreshInv();
+
+ if (talk._talkToAbort)
+ return;
+
+ // Now check for the Use and Give actions. If inv_mode is INVMODE_GIVE,
+ // that means GIVE is in effect, _selector is the object being
+ // given, and _find is the target.
+ // The same applies to USE, except if _selector is -1, then USE
+ // is being tried on an object in the scene without an inventory
+ // object being highlighted first.
+
+ if ((inv._invMode == INVMODE_USE || (_selector != -1 && inv._invMode == INVMODE_GIVE)) && _find >= 0) {
+ events._pressed = events._released = false;
+ _infoFlag = true;
+ clearInfo();
+
+ int tempSel = _selector; // Save the selector
+ _selector = -1;
+
+ inv.putInv(SLAM_DISPLAY);
+ _selector = tempSel; // Restore it
+ InvMode tempMode = inv._invMode;
+ inv._invMode = INVMODE_USE55;
+ inv.invCommands(true);
+
+ _infoFlag = true;
+ clearInfo();
+ banishWindow(false);
+ _key = -1;
+
+ inv.freeInv();
+
+ bool giveFl = (tempMode >= INVMODE_GIVE);
+ if (_selector >= 0)
+ // Use/Give inv object with scene object
+ checkUseAction(&scene._bgShapes[_find]._use[0], inv[_selector]._name, MUSE, _find, giveFl);
+ else
+ // Now inv object has been highlighted
+ checkUseAction(&scene._bgShapes[_find]._use[0], "*SELF*", MUSE, _find, giveFl);
+
+ _selector = _oldSelector = -1;
+ }
+ }
+ }
+ }
+}
+
+void ScalpelUserInterface::doLookControl() {
+ Events &events = *_vm->_events;
+ Inventory &inv = *_vm->_inventory;
+ Screen &screen = *_vm->_screen;
+
+ _key = _oldKey = -1;
+ _keyboardInput = (_keyPress != '\0');
+
+ if (events._released || events._rightReleased || _keyboardInput) {
+ // Is an inventory object being looked at?
+ if (!_invLookFlag) {
+ // Is there any remaining text to display?
+ if (!_descStr.empty()) {
+ printObjectDesc(_descStr, false);
+ } else if (!_lookHelp) {
+ // Need to close the window and depress the Look button
+ Common::Point pt(MENU_POINTS[0][0], MENU_POINTS[0][1]);
+ screen._backBuffer2.blitFrom((*_controls)[0], pt);
+ banishWindow(true);
+
+ _windowBounds.top = CONTROLS_Y1;
+ _key = _oldKey = COMMANDS[LOOK_MODE - 1];
+ _temp = _oldTemp = 0;
+ _menuMode = LOOK_MODE;
+ events.clearEvents();
+
+ // Restore UI
+ drawInterface();
+ } else {
+ events.setCursor(ARROW);
+ banishWindow(true);
+ _windowBounds.top = CONTROLS_Y1;
+ _key = _oldKey = -1;
+ _temp = _oldTemp = 0;
+ _menuMode = STD_MODE;
+ events.clearEvents();
+ }
+ } else {
+ // Looking at an inventory object
+ // Backup the user interface
+ Surface tempSurface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y1);
+ tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0),
+ Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+
+ inv.drawInventory(INVENTORY_DONT_DISPLAY);
+ banishWindow(true);
+
+ // Restore the ui
+ screen._backBuffer2.blitFrom(tempSurface, Common::Point(0, CONTROLS_Y1));
+
+ _windowBounds.top = CONTROLS_Y1;
+ _key = _oldKey = COMMANDS[LOOK_MODE - 1];
+ _temp = _oldTemp = 0;
+ events.clearEvents();
+ _invLookFlag = false;
+ _menuMode = INV_MODE;
+ _windowOpen = true;
+ }
+ }
+}
+
+void ScalpelUserInterface::doMainControl() {
+ Events &events = *_vm->_events;
+ Inventory &inv = *_vm->_inventory;
+ SaveManager &saves = *_vm->_saves;
+ Common::Point pt = events.mousePos();
+
+ if ((events._pressed || events._released) && pt.y > CONTROLS_Y) {
+ events.clearKeyboard();
+ _key = -1;
+
+ // Check whether the mouse is in any of the command areas
+ for (_temp = 0; (_temp < 12) && (_key == -1); ++_temp) {
+ Common::Rect r(MENU_POINTS[_temp][0], MENU_POINTS[_temp][1],
+ MENU_POINTS[_temp][2], MENU_POINTS[_temp][3]);
+ if (r.contains(pt))
+ _key = COMMANDS[_temp];
+ }
+ --_temp;
+ } else if (_keyPress) {
+ // Keyboard control
+ _keyboardInput = true;
+
+ if (_keyPress >= 'A' && _keyPress <= 'Z') {
+ const char *c = strchr(COMMANDS, _keyPress);
+ _temp = !c ? 12 : c - COMMANDS;
+ } else {
+ _temp = 12;
+ }
+
+ if (_temp == 12)
+ _key = -1;
+
+ if (events._rightPressed) {
+ _temp = 12;
+ _key = -1;
+ }
+ } else if (!events._released) {
+ _key = -1;
+ }
+
+ // Check if the button being pointed to has changed
+ if (_oldKey != _key && !_windowOpen) {
+ // Clear the info line
+ _infoFlag = true;
+ clearInfo();
+
+ // If there was an old button selected, restore it
+ if (_oldKey != -1) {
+ _menuMode = STD_MODE;
+ restoreButton(_oldTemp);
+ }
+
+ // If a new button is being pointed to, highlight it
+ if (_key != -1 && _temp < 12 && !_keyboardInput)
+ depressButton(_temp);
+
+ // Save the new button selection
+ _oldKey = _key;
+ _oldTemp = _temp;
+ }
+
+ if (!events._pressed && !_windowOpen) {
+ switch (_key) {
+ case 'L':
+ toggleButton(0);
+ break;
+ case 'M':
+ toggleButton(1);
+ break;
+ case 'T':
+ toggleButton(2);
+ break;
+ case 'P':
+ toggleButton(3);
+ break;
+ case 'O':
+ toggleButton(4);
+ break;
+ case 'C':
+ toggleButton(5);
+ break;
+ case 'I':
+ pushButton(6);
+ _selector = _oldSelector = -1;
+ _menuMode = INV_MODE;
+ inv.drawInventory(PLAIN_INVENTORY);
+ break;
+ case 'U':
+ pushButton(7);
+ _selector = _oldSelector = -1;
+ _menuMode = USE_MODE;
+ inv.drawInventory(USE_INVENTORY_MODE);
+ break;
+ case 'G':
+ pushButton(8);
+ _selector = _oldSelector = -1;
+ _menuMode = GIVE_MODE;
+ inv.drawInventory(GIVE_INVENTORY_MODE);
+ break;
+ case 'J':
+ pushButton(9);
+ _menuMode = JOURNAL_MODE;
+ journalControl();
+ break;
+ case 'F':
+ pushButton(10);
+
+ // Create a thumbnail of the current screen before the files dialog is shown, in case
+ // the user saves the game
+ saves.createThumbnail();
+
+ _selector = _oldSelector = -1;
+
+ if (_vm->_showOriginalSavesDialog) {
+ // Show the original dialog
+ _menuMode = FILES_MODE;
+ saves.drawInterface();
+ _windowOpen = true;
+ } else {
+ // Show the ScummVM GMM instead
+ _vm->_canLoadSave = true;
+ _vm->openMainMenuDialog();
+ _vm->_canLoadSave = false;
+ }
+ break;
+ case 'S':
+ pushButton(11);
+ _menuMode = SETUP_MODE;
+ Settings::show(_vm);
+ break;
+ default:
+ break;
+ }
+
+ _help = _oldHelp = _oldBgFound = -1;
+ }
+}
+
+void ScalpelUserInterface::doMiscControl(int allowed) {
+ Events &events = *_vm->_events;
+ Scene &scene = *_vm->_scene;
+ Talk &talk = *_vm->_talk;
+
+ if (events._released) {
+ _temp = _bgFound;
+ if (_bgFound != -1) {
+ // Only allow pointing to objects, not people
+ if (_bgFound < 1000) {
+ events.clearEvents();
+ Object &obj = scene._bgShapes[_bgFound];
+
+ switch (allowed) {
+ case ALLOW_OPEN:
+ checkAction(obj._aOpen, MOPEN, _temp);
+ if (_menuMode != TALK_MODE && !talk._talkToAbort) {
+ _menuMode = STD_MODE;
+ restoreButton(OPEN_MODE - 1);
+ _key = _oldKey = -1;
+ }
+ break;
+
+ case ALLOW_CLOSE:
+ checkAction(obj._aClose, MCLOSE, _temp);
+ if (_menuMode != TALK_MODE && !talk._talkToAbort) {
+ _menuMode = STD_MODE;
+ restoreButton(CLOSE_MODE - 1);
+ _key = _oldKey = -1;
+ }
+ break;
+
+ case ALLOW_MOVE:
+ checkAction(obj._aMove, MMOVE, _temp);
+ if (_menuMode != TALK_MODE && !talk._talkToAbort) {
+ _menuMode = STD_MODE;
+ restoreButton(MOVE_MODE - 1);
+ _key = _oldKey = -1;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+}
+
+void ScalpelUserInterface::doPickControl() {
+ Events &events = *_vm->_events;
+ Scene &scene = *_vm->_scene;
+ Talk &talk = *_vm->_talk;
+
+ if (events._released) {
+ if ((_temp = _bgFound) != -1) {
+ events.clearEvents();
+
+ // Don't allow characters to be picked up
+ if (_bgFound < 1000) {
+ scene._bgShapes[_bgFound].pickUpObject(MPICK);
+
+ if (!talk._talkToAbort && _menuMode != TALK_MODE) {
+ _key = _oldKey = -1;
+ _menuMode = STD_MODE;
+ restoreButton(PICKUP_MODE - 1);
+ }
+ }
+ }
+ }
+}
+
+void ScalpelUserInterface::doTalkControl() {
+ Events &events = *_vm->_events;
+ Journal &journal = *_vm->_journal;
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
+ Sound &sound = *_vm->_sound;
+ Talk &talk = *_vm->_talk;
+ Common::Point mousePos = events.mousePos();
+
+ _key = _oldKey = -1;
+ _keyboardInput = false;
+
+ if (events._pressed || events._released) {
+ events.clearKeyboard();
+
+ // Handle button printing
+ if (mousePos.x > 99 && mousePos.x < 138 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) && !_endKeyActive)
+ screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Exit");
+ else if (_endKeyActive)
+ screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_FOREGROUND, true, "Exit");
+
+ if (mousePos.x > 140 && mousePos.x < 170 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) && talk._moreTalkUp)
+ screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Up");
+ else if (talk._moreTalkUp)
+ screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_FOREGROUND, true, "Up");
+
+ if (mousePos.x > 181&& mousePos.x < 220 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) && talk._moreTalkDown)
+ screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Down");
+ else if (talk._moreTalkDown)
+ screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_FOREGROUND, true, "Down");
+
+ bool found = false;
+ for (_selector = talk._talkIndex; _selector < (int)talk._statements.size() && !found; ++_selector) {
+ if (mousePos.y > talk._statements[_selector]._talkPos.top &&
+ mousePos.y < talk._statements[_selector]._talkPos.bottom)
+ found = true;
+ }
+ --_selector;
+ if (!found)
+ _selector = -1;
+ }
+
+ if (_keyPress) {
+ _key = toupper(_keyPress);
+ if (_key == Common::KEYCODE_ESCAPE)
+ _key = 'E';
+
+ // Check for number press indicating reply line
+ if (_key >= '1' && _key <= ('1' + (int)talk._statements.size() - 1)) {
+ for (uint idx = 0; idx < talk._statements.size(); ++idx) {
+ if (talk._statements[idx]._talkMap == (_key - '1')) {
+ // Found the given statement
+ _selector = idx;
+ _key = -1;
+ _keyboardInput = true;
+ break;
+ }
+ }
+ } else if (_key == 'E' || _key == 'U' || _key == 'D') {
+ _keyboardInput = true;
+ } else {
+ _selector = -1;
+ }
+ }
+
+ if (_selector != _oldSelector) {
+ // Remove highlighting from previous line, if any
+ if (_oldSelector != -1) {
+ if (!((talk._talkHistory[talk._converseNum][_oldSelector] >> (_oldSelector & 7)) & 1))
+ talk.talkLine(_oldSelector, talk._statements[_oldSelector]._talkMap, INV_FOREGROUND,
+ talk._statements[_oldSelector]._talkPos.top, true);
+ else
+ talk.talkLine(_oldSelector, talk._statements[_oldSelector]._talkMap, TALK_NULL,
+ talk._statements[_oldSelector]._talkPos.top, true);
+ }
+
+ // Add highlighting to new line, if any
+ if (_selector != -1)
+ talk.talkLine(_selector, talk._statements[_selector]._talkMap, TALK_FOREGROUND,
+ talk._statements[_selector]._talkPos.top, true);
+
+ _oldSelector = _selector;
+ }
+
+ if (events._released || _keyboardInput) {
+ if (((Common::Rect(99, CONTROLS_Y, 138, CONTROLS_Y + 10).contains(mousePos) && events._released)
+ || _key == 'E') && _endKeyActive) {
+ talk.freeTalkVars();
+ talk.pullSequence();
+ banishWindow();
+ _windowBounds.top = CONTROLS_Y1;
+ } else if (((Common::Rect(140, CONTROLS_Y, 179, CONTROLS_Y + 10).contains(mousePos) && events._released)
+ || _key == 'U') && talk._moreTalkUp) {
+ while (talk._statements[--talk._talkIndex]._talkMap == -1)
+ ;
+ screen._backBuffer1.fillRect(Common::Rect(5, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2,
+ SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND);
+ talk.displayTalk(false);
+
+ screen.slamRect(Common::Rect(5, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH - 5, SHERLOCK_SCREEN_HEIGHT - 2));
+ } else if (((Common::Rect(181, CONTROLS_Y, 220, CONTROLS_Y + 10).contains(mousePos) && events._released)
+ || _key == 'D') && talk._moreTalkDown) {
+ do {
+ ++talk._talkIndex;
+ } while (talk._talkIndex < (int)talk._statements.size() && talk._statements[talk._talkIndex]._talkMap == -1);
+
+ screen._backBuffer1.fillRect(Common::Rect(5, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2,
+ SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND);
+ talk.displayTalk(false);
+
+ screen.slamRect(Common::Rect(5, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH - 5, SHERLOCK_SCREEN_HEIGHT - 2));
+ } else if (_selector != -1) {
+ screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_NULL, true, "Exit");
+ screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, true, "Up");
+ screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, true, "Down");
+
+ // If the reply is new, add it to the journal
+ if (!talk._talkHistory[talk._converseNum][_selector]) {
+ journal.record(talk._converseNum, _selector);
+
+ // Add any Holmes point to Holmes' total, if any
+ if (talk._statements[_selector]._quotient)
+ people._holmesQuotient += talk._statements[_selector]._quotient;
+ }
+
+ // Flag the response as having been used
+ talk._talkHistory[talk._converseNum][_selector] = true;
+
+ clearWindow();
+ screen.print(Common::Point(16, CONTROLS_Y + 12), TALK_FOREGROUND, "Sherlock Holmes");
+ talk.talkLine(_selector + 128, talk._statements[_selector]._talkMap, COMMAND_FOREGROUND, CONTROLS_Y + 21, true);
+
+ switch (talk._statements[_selector]._portraitSide & 3) {
+ case 0:
+ case 1:
+ people._portraitSide = 20;
+ break;
+ case 2:
+ people._portraitSide = 220;
+ break;
+ case 3:
+ people._portraitSide = 120;
+ break;
+ }
+
+ // Check for flipping Holmes
+ if (talk._statements[_selector]._portraitSide & REVERSE_DIRECTION)
+ people._holmesFlip = true;
+
+ talk._speaker = 0;
+ people.setTalking(0);
+
+ if (!talk._statements[_selector]._voiceFile.empty() && sound._voices) {
+ sound.playSound(talk._statements[_selector]._voiceFile, WAIT_RETURN_IMMEDIATELY);
+
+ // Set voices as an indicator for waiting
+ sound._voices = 2;
+ sound._speechOn = *sound._soundIsOn;
+ } else {
+ sound._speechOn = false;
+ }
+
+ talk.waitForMore(talk._statements[_selector]._statement.size());
+ if (talk._talkToAbort)
+ return;
+
+ people.clearTalking();
+ if (talk._talkToAbort)
+ return;
+
+ while (!_vm->shouldQuit()) {
+ talk._scriptSelect = _selector;
+ talk._speaker = talk._talkTo;
+ talk.doScript(talk._statements[_selector]._reply);
+
+ if (!talk._talkToAbort) {
+ if (!talk._talkStealth)
+ clearWindow();
+
+ if (!talk._statements[_selector]._modified.empty()) {
+ for (uint idx = 0; idx < talk._statements[_selector]._modified.size(); ++idx) {
+ _vm->setFlags(talk._statements[_selector]._modified[idx]);
+ }
+
+ talk.setTalkMap();
+ }
+
+ // Check for another linked talk file
+ Common::String linkFilename = talk._statements[_selector]._linkFile;
+ if (!linkFilename.empty() && !talk._scriptMoreFlag) {
+ talk.freeTalkVars();
+ talk.loadTalkFile(linkFilename);
+
+ // Find the first new statement
+ int select = _selector = _oldSelector = -1;
+ for (uint idx = 0; idx < talk._statements.size() && select == -1; ++idx) {
+ if (!talk._statements[idx]._talkMap)
+ select = talk._talkIndex = idx;
+ }
+
+ // See if the new statement is a stealth reply
+ talk._talkStealth = talk._statements[select]._statement.hasPrefix("^") ? 2 : 0;
+
+ // Is the new talk file a standard file, reply first file, or a stealth file
+ if (!talk._statements[select]._statement.hasPrefix("*") &&
+ !talk._statements[select]._statement.hasPrefix("^")) {
+ // Not a reply first file, so display the new selections
+ if (_endKeyActive)
+ screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_FOREGROUND, true, "Exit");
+ else
+ screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_NULL, true, "Exit");
+
+ talk.displayTalk(true);
+ events.setCursor(ARROW);
+ break;
+ } else {
+ _selector = select;
+
+ if (!talk._talkHistory[talk._converseNum][_selector])
+ journal.record(talk._converseNum, _selector);
+
+ talk._talkHistory[talk._converseNum][_selector] = true;
+ }
+ } else {
+ talk.freeTalkVars();
+ talk.pullSequence();
+ banishWindow();
+ _windowBounds.top = CONTROLS_Y1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ events._pressed = events._released = false;
+ events._oldButtons = 0;
+ talk._talkStealth = 0;
+
+ // If a script was pushed onto the script stack, restore it
+ if (!talk._scriptStack.empty()) {
+ ScriptStackEntry stackEntry = talk._scriptStack.pop();
+ talk._scriptName = stackEntry._name;
+ talk._scriptSaveIndex = stackEntry._currentIndex;
+ talk._scriptSelect = stackEntry._select;
+ }
+ }
+ }
+}
+
+void ScalpelUserInterface::journalControl() {
+ Events &events = *_vm->_events;
+ Journal &journal = *_vm->_journal;
+ Scene &scene = *_vm->_scene;
+ Screen &screen = *_vm->_screen;
+ bool doneFlag = false;
+
+ // Draw the journal screen
+ journal.drawInterface();
+
+ // Handle journal events
+ do {
+ _key = -1;
+ events.setButtonState();
+
+ // Handle keypresses
+ if (events.kbHit()) {
+ Common::KeyState keyState = events.getKey();
+ if (keyState.keycode == Common::KEYCODE_x && (keyState.flags & Common::KBD_ALT)) {
+ _vm->quitGame();
+ return;
+ } else if (keyState.keycode == Common::KEYCODE_e || keyState.keycode == Common::KEYCODE_ESCAPE) {
+ doneFlag = true;
+ } else {
+ _key = toupper(keyState.keycode);
+ }
+ }
+
+ if (!doneFlag)
+ doneFlag = journal.handleEvents(_key);
+ } while (!_vm->shouldQuit() && !doneFlag);
+
+ // Finish up
+ _infoFlag = _keyboardInput = false;
+ _keyPress = '\0';
+ _windowOpen = false;
+ _windowBounds.top = CONTROLS_Y1;
+ _key = -1;
+ _menuMode = STD_MODE;
+
+ // Reset the palette
+ screen.setPalette(screen._cMap);
+
+ screen._backBuffer1.blitFrom(screen._backBuffer2);
+ scene.updateBackground();
+ screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
+}
+
+void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool firstTime) {
+ Events &events = *_vm->_events;
+ Inventory &inv = *_vm->_inventory;
+ Screen &screen = *_vm->_screen;
+ Talk &talk = *_vm->_talk;
+
+ if (str.hasPrefix("_")) {
+ _lookScriptFlag = true;
+ events.setCursor(MAGNIFY);
+ int savedSelector = _selector;
+ talk.talkTo(str.c_str() + 1);
+ _lookScriptFlag = false;
+
+ if (talk._talkToAbort) {
+ events.setCursor(ARROW);
+ return;
+ }
+
+ // Check if looking at an inventory object
+ if (!_invLookFlag) {
+ // See if this look was called by a right button click or not
+ if (!_lookHelp) {
+ // If it wasn't a right button click, then we need depress
+ // the look button before we close the window. So save a copy of the
+ // menu area, and draw the controls onto it
+ Surface tempSurface((*_controls)[0]._frame.w, (*_controls)[0]._frame.h);
+ Common::Point pt(MENU_POINTS[0][0], MENU_POINTS[0][1]);
+
+ tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0),
+ Common::Rect(pt.x, pt.y, pt.x + tempSurface.w(), pt.y + tempSurface.h()));
+ screen._backBuffer2.transBlitFrom((*_controls)[0], pt);
+
+ banishWindow(1);
+ events.setCursor(MAGNIFY);
+ _windowBounds.top = CONTROLS_Y1;
+ _key = _oldKey = COMMANDS[LOOK_MODE - 1];
+ _temp = _oldTemp = 0;
+ _menuMode = LOOK_MODE;
+ events.clearEvents();
+
+ screen._backBuffer2.blitFrom(tempSurface, pt);
+ } else {
+ events.setCursor(ARROW);
+ banishWindow(true);
+ _windowBounds.top = CONTROLS_Y1;
+ _key = _oldKey = -1;
+ _temp = _oldTemp = 0;
+ _menuMode = STD_MODE;
+ _lookHelp = 0;
+ events.clearEvents();
+ }
+ } else {
+ // Looking at an inventory object
+ _selector = _oldSelector = savedSelector;
+
+ // Reload the inventory graphics and draw the inventory
+ inv.loadInv();
+ inv.putInv(SLAM_SECONDARY_BUFFER);
+ inv.freeInv();
+ banishWindow(1);
+
+ _windowBounds.top = CONTROLS_Y1;
+ _key = _oldKey = COMMANDS[INV_MODE - 1];
+ _temp = _oldTemp = 0;
+ events.clearEvents();
+
+ _invLookFlag = 0;
+ _menuMode = INV_MODE;
+ _windowOpen = true;
+ }
+
+ return;
+ }
+
+ Surface &bb = *screen._backBuffer;
+ if (firstTime) {
+ // Only draw the border on the first call
+ _infoFlag = true;
+ clearInfo();
+
+ bb.fillRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH,
+ CONTROLS_Y1 + 10), BORDER_COLOR);
+ bb.fillRect(Common::Rect(0, CONTROLS_Y + 10, 1, SHERLOCK_SCREEN_HEIGHT - 1),
+ BORDER_COLOR);
+ bb.fillRect(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y + 10,
+ SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR);
+ bb.fillRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 1, SHERLOCK_SCREEN_WIDTH,
+ SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR);
+ }
+
+ // Clear background
+ bb.fillRect(Common::Rect(2, CONTROLS_Y + 10, SHERLOCK_SCREEN_WIDTH - 2,
+ SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND);
+
+ _windowBounds.top = CONTROLS_Y;
+ events.clearEvents();
+
+ // Loop through displaying up to five lines
+ bool endOfStr = false;
+ const char *msgP = str.c_str();
+ for (int lineNum = 0; lineNum < ONSCREEN_FILES_COUNT && !endOfStr; ++lineNum) {
+ int width = 0;
+ const char *lineStartP = msgP;
+
+ // Determine how much can be displayed on the line
+ do {
+ width += screen.charWidth(*msgP++);
+ } while (width < 300 && *msgP);
+
+ if (*msgP)
+ --msgP;
+ else
+ endOfStr = true;
+
+ // If the line needs to be wrapped, scan backwards to find
+ // the end of the previous word as a splitting point
+ if (width >= 300) {
+ while (*msgP != ' ')
+ --msgP;
+ endOfStr = false;
+ }
+
+ // Print out the line
+ Common::String line(lineStartP, msgP);
+ screen.gPrint(Common::Point(16, CONTROLS_Y + 12 + lineNum * 9),
+ INV_FOREGROUND, "%s", line.c_str());
+
+ if (!endOfStr)
+ // Start next line at start of the nxet word after space
+ ++msgP;
+ }
+
+ // Handle display depending on whether all the message was shown
+ if (!endOfStr) {
+ screen.makeButton(Common::Rect(46, CONTROLS_Y, 272, CONTROLS_Y + 10),
+ (SHERLOCK_SCREEN_WIDTH - screen.stringWidth(PRESS_KEY_FOR_MORE)) / 2,
+ PRESS_KEY_FOR_MORE);
+ screen.gPrint(Common::Point((SHERLOCK_SCREEN_WIDTH -
+ screen.stringWidth(PRESS_KEY_FOR_MORE)) / 2, CONTROLS_Y),
+ COMMAND_FOREGROUND, "P");
+ _descStr = msgP;
+ } else {
+ screen.makeButton(Common::Rect(46, CONTROLS_Y, 272, CONTROLS_Y + 10),
+ (SHERLOCK_SCREEN_WIDTH - screen.stringWidth(PRESS_KEY_TO_CONTINUE)) / 2,
+ PRESS_KEY_TO_CONTINUE);
+ screen.gPrint(Common::Point((SHERLOCK_SCREEN_WIDTH -
+ screen.stringWidth(PRESS_KEY_TO_CONTINUE)) / 2, CONTROLS_Y),
+ COMMAND_FOREGROUND, "P");
+ _descStr = "";
+ }
+
+ if (firstTime) {
+ if (!_slideWindows) {
+ screen.slamRect(Common::Rect(0, CONTROLS_Y,
+ SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+ } else {
+ // Display the window
+ summonWindow();
+ }
+
+ _selector = _oldSelector = -1;
+ _windowOpen = true;
+ } else {
+ screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH,
+ SHERLOCK_SCREEN_HEIGHT));
+ }
+}
+
+void ScalpelUserInterface::printObjectDesc() {
+ printObjectDesc(_cAnimStr, true);
+}
+
+void ScalpelUserInterface::summonWindow(const Surface &bgSurface, bool slideUp) {
+ Events &events = *_vm->_events;
+ Screen &screen = *_vm->_screen;
+
+ if (_windowOpen)
+ // A window is already open, so can't open another one
+ return;
+
+ if (slideUp) {
+ // Gradually slide up the display of the window
+ for (int idx = 1; idx <= bgSurface.h(); idx += 2) {
+ screen._backBuffer->blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - idx),
+ Common::Rect(0, 0, bgSurface.w(), idx));
+ screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - idx,
+ SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+
+ events.delay(10);
+ }
+ } else {
+ // Gradually slide down the display of the window
+ for (int idx = 1; idx <= bgSurface.h(); idx += 2) {
+ screen._backBuffer->blitFrom(bgSurface,
+ Common::Point(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h()),
+ Common::Rect(0, bgSurface.h() - idx, bgSurface.w(), bgSurface.h()));
+ screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h(),
+ SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - bgSurface.h() + idx));
+
+ events.delay(10);
+ }
+ }
+
+ // Final display of the entire window
+ screen._backBuffer->blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h()),
+ Common::Rect(0, 0, bgSurface.w(), bgSurface.h()));
+ screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h(), bgSurface.w(), bgSurface.h());
+
+ _windowOpen = true;
+}
+
+void ScalpelUserInterface::summonWindow(bool slideUp, int height) {
+ Screen &screen = *_vm->_screen;
+
+ // Extract the window that's been drawn on the back buffer
+ Surface tempSurface(SHERLOCK_SCREEN_WIDTH,
+ (SHERLOCK_SCREEN_HEIGHT - height));
+ Common::Rect r(0, height, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
+ tempSurface.blitFrom(screen._backBuffer1, Common::Point(0, 0), r);
+
+ // Remove drawn window with original user interface
+ screen._backBuffer1.blitFrom(screen._backBuffer2,
+ Common::Point(0, height), r);
+
+ // Display the window gradually on-screen
+ summonWindow(tempSurface, slideUp);
+}
+
+void ScalpelUserInterface::banishWindow(bool slideUp) {
+ Events &events = *_vm->_events;
+ Screen &screen = *_vm->_screen;
+
+ if (_windowOpen) {
+ if (slideUp || !_slideWindows) {
+ // Slide window down
+ // Only slide the window if the window style allows it
+ if (_slideWindows) {
+ for (int idx = 2; idx < (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y); idx += 2) {
+ // Shift the window down by 2 lines
+ byte *pSrc = (byte *)screen._backBuffer1.getBasePtr(0, CONTROLS_Y + idx - 2);
+ byte *pSrcEnd = (byte *)screen._backBuffer1.getBasePtr(0, SHERLOCK_SCREEN_HEIGHT - 2);
+ byte *pDest = (byte *)screen._backBuffer1.getBasePtr(0, SHERLOCK_SCREEN_HEIGHT);
+ Common::copy_backward(pSrc, pSrcEnd, pDest);
+
+ // Restore lines from the ui in the secondary back buffer
+ screen._backBuffer1.blitFrom(screen._backBuffer2,
+ Common::Point(0, CONTROLS_Y),
+ Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y + idx));
+
+ screen.slamArea(0, CONTROLS_Y + idx - 2, SHERLOCK_SCREEN_WIDTH,
+ SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y - idx + 2);
+ events.delay(10);
+ }
+
+ // Restore final two old lines
+ screen._backBuffer1.blitFrom(screen._backBuffer2,
+ Common::Point(0, SHERLOCK_SCREEN_HEIGHT - 2),
+ Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 2,
+ SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+ screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - 2, SHERLOCK_SCREEN_WIDTH, 2);
+ } else {
+ // Restore old area to completely erase window
+ screen._backBuffer1.blitFrom(screen._backBuffer2,
+ Common::Point(0, CONTROLS_Y),
+ Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+ screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH,
+ SHERLOCK_SCREEN_HEIGHT));
+ }
+ } else {
+ // Slide the original user interface up to cover the dialog
+ for (int idx = 1; idx < (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y1); idx += 2) {
+ byte *pSrc = (byte *)screen._backBuffer2.getBasePtr(0, CONTROLS_Y1);
+ byte *pSrcEnd = (byte *)screen._backBuffer2.getBasePtr(0, CONTROLS_Y1 + idx);
+ byte *pDest = (byte *)screen._backBuffer1.getBasePtr(0, SHERLOCK_SCREEN_HEIGHT - idx);
+ Common::copy(pSrc, pSrcEnd, pDest);
+
+ screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - idx, SHERLOCK_SCREEN_WIDTH,
+ SHERLOCK_SCREEN_HEIGHT);
+ events.delay(10);
+ }
+
+ // Show entire final area
+ screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(0, CONTROLS_Y1),
+ Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+ screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+ }
+
+ _infoFlag = false;
+ _windowOpen = false;
+ }
+
+ _menuMode = STD_MODE;
+}
+
+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;
+ Scene &scene = *_vm->_scene;
+ Screen &screen = *_vm->_screen;
+ Talk &talk = *_vm->_talk;
+ bool printed = messages == nullptr;
+
+ if (objNum >= 1000) {
+ // Holmes was specified, so do nothing
+ _infoFlag = true;
+ clearInfo();
+ _infoFlag = true;
+
+ // Display error message
+ _menuCounter = 30;
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "You can't do that to yourself.");
+ return;
+ }
+
+ // Scan for target item
+ int targetNum = -1;
+ if (giveMode) {
+ for (int idx = 0; idx < USE_COUNT && targetNum == -1; ++idx) {
+ if ((use[idx]._target.equalsIgnoreCase("*GIVE*") || use[idx]._target.equalsIgnoreCase("*GIVEP*"))
+ && use[idx]._names[0].equalsIgnoreCase(invName)) {
+ // Found a match
+ targetNum = idx;
+ if (use[idx]._target.equalsIgnoreCase("*GIVE*"))
+ inv.deleteItemFromInventory(invName);
+ }
+ }
+ } else {
+ for (int idx = 0; idx < USE_COUNT && targetNum == -1; ++idx) {
+ if (use[idx]._target.equalsIgnoreCase(invName))
+ targetNum = idx;
+ }
+ }
+
+ if (targetNum != -1) {
+ // Found a target, so do the action
+ const UseType &action = use[targetNum];
+
+ events.setCursor(WAIT);
+
+ if (action._useFlag)
+ _vm->setFlags(action._useFlag);
+
+ if (action._cAnimNum != 99) {
+ if (action._cAnimNum == 0)
+ scene.startCAnim(9, action._cAnimSpeed);
+ else
+ scene.startCAnim(action._cAnimNum - 1, action._cAnimSpeed);
+ }
+
+ if (!talk._talkToAbort) {
+ Object &obj = scene._bgShapes[objNum];
+ for (int idx = 0; idx < NAMES_COUNT && !talk._talkToAbort; ++idx) {
+ if (obj.checkNameForCodes(action._names[idx], messages)) {
+ if (!talk._talkToAbort)
+ printed = true;
+ }
+ }
+
+ // Print "Done..." as an ending, unless flagged for leaving scene or otherwise flagged
+ if (scene._goToScene != 1 && !printed && !talk._talkToAbort) {
+ _infoFlag = true;
+ clearInfo();
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "Done...");
+ _menuCounter = 25;
+ }
+ }
+ } else {
+ // Couldn't find target, so print error
+ _infoFlag = true;
+ clearInfo();
+
+ if (giveMode) {
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "No, thank you.");
+ } else if (messages == nullptr) {
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "You can't do that.");
+ } else {
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", messages[0]);
+ }
+
+ _infoFlag = true;
+ _menuCounter = 30;
+ }
+
+ events.setCursor(ARROW);
+}
+
+void ScalpelUserInterface::checkAction(ActionType &action, const char *const messages[], int objNum) {
+ Events &events = *_vm->_events;
+ People &people = *_vm->_people;
+ Scene &scene = *_vm->_scene;
+ Screen &screen = *_vm->_screen;
+ Talk &talk = *_vm->_talk;
+ Common::Point pt(-1, -1);
+
+ if (objNum >= 1000)
+ // Ignore actions done on characters
+ return;
+
+ if (!action._cAnimSpeed) {
+ // Invalid action, to print error message
+ _infoFlag = true;
+ clearInfo();
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", messages[action._cAnimNum]);
+ _infoFlag = true;
+
+ // Set how long to show the message
+ _menuCounter = 30;
+ } else {
+ Object &obj = scene._bgShapes[objNum];
+
+ int cAnimNum;
+ if (action._cAnimNum == 0)
+ // Really a 10
+ cAnimNum = 9;
+ else
+ cAnimNum = action._cAnimNum - 1;
+
+ int dir = -1;
+ if (action._cAnimNum != 99) {
+ CAnim &anim = scene._cAnim[cAnimNum];
+
+ if (action._cAnimNum != 99) {
+ if (action._cAnimSpeed & REVERSE_DIRECTION) {
+ pt = anim._teleportPos;
+ dir = anim._teleportDir;
+ } else {
+ pt = anim._goto;
+ dir = anim._gotoDir;
+ }
+ }
+ } else {
+ pt = Common::Point(-1, -1);
+ dir = -1;
+ }
+
+ // Has a value, so do action
+ // Show wait cursor whilst walking to object and doing action
+ events.setCursor(WAIT);
+ bool printed = false;
+
+ for (int nameIdx = 0; nameIdx < NAMES_COUNT; ++nameIdx) {
+ if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2
+ && toupper(action._names[nameIdx][1]) == 'W') {
+ if (obj.checkNameForCodes(Common::String(action._names[nameIdx].c_str() + 2), messages)) {
+ if (!talk._talkToAbort)
+ printed = true;
+ }
+ }
+ }
+
+ bool doCAnim = true;
+ for (int nameIdx = 0; nameIdx < NAMES_COUNT; ++nameIdx) {
+ if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2) {
+ char ch = toupper(action._names[nameIdx][1]);
+
+ if (ch == 'T' || ch == 'B') {
+ printed = true;
+ if (pt.x != -1)
+ // Holmes needs to walk to object before the action is done
+ people.walkToCoords(pt, dir);
+
+ if (!talk._talkToAbort) {
+ // Ensure Holmes is on the exact intended location
+ people[AL]._position = pt;
+ people[AL]._sequenceNumber = dir;
+ people.gotoStand(people[AL]);
+
+ talk.talkTo(action._names[nameIdx].c_str() + 2);
+ if (ch == 'T')
+ doCAnim = false;
+ }
+ }
+ }
+ }
+
+ if (doCAnim && !talk._talkToAbort) {
+ if (pt.x != -1)
+ // Holmes needs to walk to object before the action is done
+ people.walkToCoords(pt, dir);
+ }
+
+ for (int nameIdx = 0; nameIdx < NAMES_COUNT; ++nameIdx) {
+ if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2
+ && toupper(action._names[nameIdx][1]) == 'F') {
+ if (obj.checkNameForCodes(action._names[nameIdx].c_str() + 2, messages)) {
+ if (!talk._talkToAbort)
+ printed = true;
+ }
+ }
+ }
+
+ if (doCAnim && !talk._talkToAbort && action._cAnimNum != 99)
+ scene.startCAnim(cAnimNum, action._cAnimSpeed);
+
+ if (!talk._talkToAbort) {
+ for (int nameIdx = 0; nameIdx < NAMES_COUNT && !talk._talkToAbort; ++nameIdx) {
+ if (obj.checkNameForCodes(action._names[nameIdx], messages)) {
+ if (!talk._talkToAbort)
+ printed = true;
+ }
+ }
+
+ // Unless we're leaving the scene, print a "Done" message unless the printed flag has been set
+ if (scene._goToScene != 1 && !printed && !talk._talkToAbort) {
+ _infoFlag = true;
+ clearInfo();
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "Done...");
+
+ // Set how long to show the message
+ _menuCounter = 30;
+ }
+ }
+ }
+
+ // Reset cursor back to arrow
+ events.setCursor(ARROW);
+}
+
+} // End of namespace Scalpel
+
+} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel_user_interface.h b/engines/sherlock/scalpel/scalpel_user_interface.h
new file mode 100644
index 0000000..8ed69ac8
--- /dev/null
+++ b/engines/sherlock/scalpel/scalpel_user_interface.h
@@ -0,0 +1,227 @@
+/* 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.
+ *
+ */
+
+#ifndef SHERLOCK_SCALPEL_UI_H
+#define SHERLOCK_SCALPEL_UI_H
+
+#include "common/scummsys.h"
+#include "sherlock/user_interface.h"
+
+namespace Sherlock {
+
+class Inventory;
+class Talk;
+
+namespace Scalpel {
+
+extern const char COMMANDS[13];
+extern const int MENU_POINTS[12][4];
+
+extern const int INVENTORY_POINTS[8][3];
+extern const char INVENTORY_COMMANDS[9];
+extern const char *const PRESS_KEY_FOR_MORE;
+extern const char *const PRESS_KEY_TO_CONTINUE;
+
+class Settings;
+
+class ScalpelUserInterface: public UserInterface {
+ friend class Inventory;
+ friend class Settings;
+ friend class Talk;
+private:
+ ImageFile *_controlPanel;
+ ImageFile *_controls;
+ char _keyPress;
+ int _lookHelp;
+ int _bgFound, _oldBgFound;
+ int _help, _oldHelp;
+ char _key, _oldKey;
+ int _temp, _oldTemp;
+ int _oldLook;
+ bool _keyboardInput;
+ bool _pause;
+ int _cNum;
+ Common::String _cAnimStr;
+ Common::String _descStr;
+ int _find;
+ int _oldUse;
+private:
+ /**
+ * Draws the image for a user interface button in the down/pressed state.
+ */
+ void depressButton(int num);
+
+ /**
+ * If he mouse button is pressed, then calls depressButton to draw the button
+ * as pressed; if not, it will show it as released with a call to "restoreButton".
+ */
+ void pushButton(int num);
+
+ /**
+ * By the time this method has been called, the graphics for the button change
+ * have already been drawn. This simply takes care of switching the mode around
+ * accordingly
+ */
+ void toggleButton(int num);
+
+ /**
+ * Creates a text window and uses it to display the in-depth description
+ * of the highlighted object
+ */
+ void examine();
+
+ /**
+ * Print the name of an object in the scene
+ */
+ void lookScreen(const Common::Point &pt);
+
+ /**
+ * Gets the item in the inventory the mouse is on and display's it's description
+ */
+ void lookInv();
+
+ /**
+ * Handles input when the file list window is being displayed
+ */
+ void doEnvControl();
+
+ /**
+ * Handle input whilst the inventory is active
+ */
+ void doInvControl();
+
+ /**
+ * Handles waiting whilst an object's description window is open.
+ */
+ void doLookControl();
+
+ /**
+ * Handles input until one of the user interface buttons/commands is selected
+ */
+ void doMainControl();
+
+ /**
+ * Handles the input for the MOVE, OPEN, and CLOSE commands
+ */
+ void doMiscControl(int allowed);
+
+ /**
+ * Handles input for picking up items
+ */
+ void doPickControl();
+
+ /**
+ * Handles input when in talk mode. It highlights the buttons and available statements,
+ * and handles allowing the user to click on them
+ */
+ void doTalkControl();
+
+ /**
+ * Handles events when the Journal is active.
+ * @remarks Whilst this would in theory be better in the Journal class, since it displays in
+ * the user interface, it uses so many internal UI fields, that it sort of made some sense
+ * to put it in the UserInterface class.
+ */
+ void journalControl();
+
+ /**
+ * Checks to see whether a USE action is valid on the given object
+ */
+ void checkUseAction(const UseType *use, const Common::String &invName, const char *const messages[],
+ int objNum, bool giveMode);
+
+ /**
+ * Called for OPEN, CLOSE, and MOVE actions are being done
+ */
+ void checkAction(ActionType &action, const char *const messages[], int objNum);
+
+ /**
+ * Print the previously selected object's decription
+ */
+ void printObjectDesc(const Common::String &str, bool firstTime);
+public:
+ ScalpelUserInterface(SherlockEngine *vm);
+ virtual ~ScalpelUserInterface();
+
+ /**
+ * Handles counting down whilst checking for input, then clears the info line.
+ */
+ void whileMenuCounter();
+
+ /**
+ * Draws the image for the given user interface button in the up
+ * (not selected) position
+ */
+ void restoreButton(int num);
+public:
+ /**
+ * Resets the user interface
+ */
+ virtual void reset();
+
+ /**
+ * Main input handler for the user interface
+ */
+ virtual void handleInput();
+
+ /**
+ * Draw the user interface onto the screen's back buffers
+ */
+ virtual void drawInterface(int bufferNum = 3);
+
+ /**
+ * 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();
+};
+
+} // End of namespace Scalpel
+
+} // End of namespace Sherlock
+
+#endif
diff --git a/engines/sherlock/scalpel/settings.cpp b/engines/sherlock/scalpel/settings.cpp
new file mode 100644
index 0000000..4459786
--- /dev/null
+++ b/engines/sherlock/scalpel/settings.cpp
@@ -0,0 +1,341 @@
+/* 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/sherlock.h"
+#include "sherlock/scalpel/settings.h"
+#include "sherlock/scalpel/scalpel_user_interface.h"
+
+namespace Sherlock {
+
+namespace Scalpel {
+
+static const int SETUP_POINTS[12][4] = {
+ { 4, 154, 101, 53 }, // Exit
+ { 4, 165, 101, 53 }, // Music Toggle
+ { 219, 165, 316, 268 }, // Voice Toggle
+ { 103, 165, 217, 160 }, // Sound Effects Toggle
+ { 219, 154, 316, 268 }, // Help Button Left/Right
+ { 103, 154, 217, 160 }, // New Font Style
+ { 4, 187, 101, 53 }, // Joystick Toggle
+ { 103, 187, 217, 160 }, // Calibrate Joystick
+ { 219, 176, 316, 268 }, // Fade Style
+ { 103, 176, 217, 160 }, // Window Open Style
+ { 4, 176, 101, 53 }, // Portraits Toggle
+ { 219, 187, 316, 268 } // _key Pad Accel. Toggle
+};
+
+static const char *const SETUP_STRS0[2] = { "off", "on" };
+static const char *const SETUP_STRS1[2] = { "Directly", "by Pixel" };
+static const char *const SETUP_STRS2[2] = { "Left", "Right" };
+static const char *const SETUP_STRS3[2] = { "Appear", "Slide" };
+static const char *const SETUP_STRS5[2] = { "Left", "Right" };
+static const char *const SETUP_NAMES[12] = {
+ "Exit", "M", "V", "S", "B", "New Font Style", "J", "Calibrate Joystick", "F", "W", "P", "K"
+};
+
+/*----------------------------------------------------------------*/
+
+void Settings::drawInteface(bool flag) {
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
+ Sound &sound = *_vm->_sound;
+ UserInterface &ui = *_vm->_ui;
+ Common::String tempStr;
+
+ if (!flag) {
+ screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y1 + 1), BORDER_COLOR);
+ screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y1 + 1, 2, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR);
+ screen._backBuffer1.fillRect(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y1 + 1, SHERLOCK_SCREEN_WIDTH,
+ SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR);
+ screen._backBuffer1.hLine(0, SHERLOCK_SCREEN_HEIGHT - 1, SHERLOCK_SCREEN_WIDTH - 1, BORDER_COLOR);
+ screen._backBuffer1.fillRect(Common::Rect(2, CONTROLS_Y1 + 1, SHERLOCK_SCREEN_WIDTH - 2,
+ SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND);
+ }
+
+ screen.makeButton(Common::Rect(SETUP_POINTS[0][0], SETUP_POINTS[0][1], SETUP_POINTS[0][2], SETUP_POINTS[0][1] + 10),
+ SETUP_POINTS[0][3] - screen.stringWidth("Exit") / 2, "Exit");
+
+ tempStr = Common::String::format("Music %s", SETUP_STRS0[sound._music]);
+ screen.makeButton(Common::Rect(SETUP_POINTS[1][0], SETUP_POINTS[1][1], SETUP_POINTS[1][2], SETUP_POINTS[1][1] + 10),
+ SETUP_POINTS[1][3] - screen.stringWidth(tempStr) / 2, tempStr);
+
+ tempStr = Common::String::format("Voices %s", SETUP_STRS0[sound._voices]);
+ screen.makeButton(Common::Rect(SETUP_POINTS[2][0], SETUP_POINTS[2][1], SETUP_POINTS[2][2], SETUP_POINTS[2][1] + 10),
+ SETUP_POINTS[2][3] - screen.stringWidth(tempStr) / 2, tempStr);
+
+ tempStr = Common::String::format("Sound Effects %s", SETUP_STRS0[sound._digitized]);
+ screen.makeButton(Common::Rect(SETUP_POINTS[3][0], SETUP_POINTS[3][1], SETUP_POINTS[3][2], SETUP_POINTS[3][1] + 10),
+ SETUP_POINTS[3][3] - screen.stringWidth(tempStr) / 2, tempStr);
+
+ tempStr = Common::String::format("Auto Help %s", SETUP_STRS5[ui._helpStyle]);
+ screen.makeButton(Common::Rect(SETUP_POINTS[4][0], SETUP_POINTS[4][1], SETUP_POINTS[4][2], SETUP_POINTS[4][1] + 10),
+ SETUP_POINTS[4][3] - screen.stringWidth(tempStr) / 2, tempStr);
+ screen.makeButton(Common::Rect(SETUP_POINTS[5][0], SETUP_POINTS[5][1], SETUP_POINTS[5][2], SETUP_POINTS[5][1] + 10),
+ SETUP_POINTS[5][3] - screen.stringWidth("New Font Style") / 2, "New Font Style");
+
+ // WORKAROUND: We don't support the joystick in ScummVM, so draw the next two buttons as disabled
+ tempStr = "Joystick Off";
+ screen.makeButton(Common::Rect(SETUP_POINTS[6][0], SETUP_POINTS[6][1], SETUP_POINTS[6][2], SETUP_POINTS[6][1] + 10),
+ SETUP_POINTS[6][3] - screen.stringWidth(tempStr) / 2, tempStr);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[6][3], SETUP_POINTS[6][1]), COMMAND_NULL, false, tempStr);
+
+ tempStr = "Calibrate Joystick";
+ screen.makeButton(Common::Rect(SETUP_POINTS[7][0], SETUP_POINTS[7][1], SETUP_POINTS[7][2], SETUP_POINTS[7][1] + 10),
+ SETUP_POINTS[7][3] - screen.stringWidth(tempStr) / 2, tempStr);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[7][3], SETUP_POINTS[7][1]), COMMAND_NULL, false, tempStr);
+
+ tempStr = Common::String::format("Fade %s", screen._fadeStyle ? "by Pixel" : "Directly");
+ screen.makeButton(Common::Rect(SETUP_POINTS[8][0], SETUP_POINTS[8][1], SETUP_POINTS[8][2], SETUP_POINTS[8][1] + 10),
+ SETUP_POINTS[8][3] - screen.stringWidth(tempStr) / 2, tempStr);
+
+ tempStr = Common::String::format("Windows %s", ui._slideWindows ? "Slide" : "Appear");
+ screen.makeButton(Common::Rect(SETUP_POINTS[9][0], SETUP_POINTS[9][1], SETUP_POINTS[9][2], SETUP_POINTS[9][1] + 10),
+ SETUP_POINTS[9][3] - screen.stringWidth(tempStr) / 2, tempStr);
+
+ tempStr = Common::String::format("Portraits %s", SETUP_STRS0[people._portraitsOn]);
+ screen.makeButton(Common::Rect(SETUP_POINTS[10][0], SETUP_POINTS[10][1], SETUP_POINTS[10][2], SETUP_POINTS[10][1] + 10),
+ SETUP_POINTS[10][3] - screen.stringWidth(tempStr) / 2, tempStr);
+
+ tempStr = "Key Pad Slow";
+ screen.makeButton(Common::Rect(SETUP_POINTS[11][0], SETUP_POINTS[11][1], SETUP_POINTS[11][2], SETUP_POINTS[11][1] + 10),
+ SETUP_POINTS[11][3] - screen.stringWidth(tempStr) / 2, tempStr);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[11][3], SETUP_POINTS[11][1]), COMMAND_NULL, false, tempStr);
+
+ // Show the window immediately, or slide it on-screen
+ if (!flag) {
+ if (!ui._slideWindows) {
+ screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+ } else {
+ ui.summonWindow(true, CONTROLS_Y1);
+ }
+
+ ui._windowOpen = true;
+ } else {
+ screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+ }
+}
+
+int Settings::drawButtons(const Common::Point &pt, int _key) {
+ Events &events = *_vm->_events;
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
+ Sound &sound = *_vm->_sound;
+ UserInterface &ui = *_vm->_ui;
+ int found = -1;
+ byte color;
+ Common::String tempStr;
+
+ for (int idx = 0; idx < 12; ++idx) {
+ if ((pt.x > SETUP_POINTS[idx][0] && pt.x < SETUP_POINTS[idx][2] && pt.y > SETUP_POINTS[idx][1]
+ && pt.y < (SETUP_POINTS[idx][1] + 10) && (events._pressed || events._released))
+ || (_key == SETUP_NAMES[idx][0])) {
+ found = idx;
+ color = COMMAND_HIGHLIGHTED;
+ } else {
+ color = COMMAND_FOREGROUND;
+ }
+
+ // Print the button text
+ switch (idx) {
+ case 1:
+ tempStr = Common::String::format("Music %s", SETUP_STRS0[sound._music]);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
+ break;
+ case 2:
+ tempStr = Common::String::format("Voices %s", SETUP_STRS0[sound._voices]);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
+ break;
+ case 3:
+ tempStr = Common::String::format("Sound Effects %s", SETUP_STRS0[sound._digitized]);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
+ break;
+ case 4:
+ tempStr = Common::String::format("Auto Help %s", SETUP_STRS2[ui._helpStyle]);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
+ break;
+ case 6:
+ tempStr = "Joystick Off";
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), COMMAND_NULL, true, tempStr);
+ break;
+ case 7:
+ tempStr = "Calibrate Joystick";
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), COMMAND_NULL, true, tempStr);
+ break;
+ case 8:
+ tempStr = Common::String::format("Fade %s", SETUP_STRS1[screen._fadeStyle]);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
+ break;
+ case 9:
+ tempStr = Common::String::format("Windows %s", SETUP_STRS3[ui._slideWindows]);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
+ break;
+ case 10:
+ tempStr = Common::String::format("Portraits %s", SETUP_STRS0[people._portraitsOn]);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
+ break;
+ case 11:
+ tempStr = "Key Pad Slow";
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), COMMAND_NULL, true, tempStr);
+ break;
+ default:
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, SETUP_NAMES[idx]);
+ break;
+ }
+ }
+
+ return found;
+}
+
+void Settings::show(SherlockEngine *vm) {
+ Events &events = *vm->_events;
+ People &people = *vm->_people;
+ Scene &scene = *vm->_scene;
+ Screen &screen = *vm->_screen;
+ Sound &sound = *vm->_sound;
+ Talk &talk = *vm->_talk;
+ ScalpelUserInterface &ui = *(ScalpelUserInterface *)vm->_ui;
+ bool updateConfig = false;
+
+ assert(vm->getGameID() == GType_SerratedScalpel);
+ Settings settings(vm);
+ settings.drawInteface(false);
+
+ do {
+ if (ui._menuCounter)
+ ui.whileMenuCounter();
+
+ int found = -1;
+ ui._key = -1;
+
+ scene.doBgAnim();
+ if (talk._talkToAbort)
+ return;
+
+ events.setButtonState();
+ Common::Point pt = events.mousePos();
+
+ if (events._pressed || events._released || events.kbHit()) {
+ ui.clearInfo();
+ ui._key = -1;
+
+ if (events.kbHit()) {
+ Common::KeyState keyState = events.getKey();
+ ui._key = toupper(keyState.keycode);
+
+ if (ui._key == Common::KEYCODE_RETURN || ui._key == Common::KEYCODE_SPACE) {
+ events._pressed = false;
+ events._oldButtons = 0;
+ ui._keyPress = '\0';
+ events._released = true;
+ }
+ }
+
+ // Handle highlighting button under mouse
+ found = settings.drawButtons(pt, ui._key);
+ }
+
+ if ((found == 0 && events._released) || (ui._key == 'E' || ui._key == Common::KEYCODE_ESCAPE))
+ // Exit
+ break;
+
+ if ((found == 1 && events._released) || ui._key == 'M') {
+ // Toggle music
+ if (sound._music) {
+ sound.stopSound();
+ sound._music = false;
+ }
+ else {
+ sound._music = true;
+ sound.startSong();
+ }
+
+ updateConfig = true;
+ settings.drawInteface(true);
+ }
+
+ if ((found == 2 && events._released) || ui._key == 'V') {
+ sound._voices = !sound._voices;
+ updateConfig = true;
+ settings.drawInteface(true);
+ }
+
+ if ((found == 3 && events._released) || ui._key == 'S') {
+ // Toggle sound effects
+ sound._digitized = !sound._digitized;
+ updateConfig = true;
+ settings.drawInteface(true);
+ }
+
+ if ((found == 4 && events._released) || ui._key == 'A') {
+ // Help button style
+ ui._helpStyle = !ui._helpStyle;
+ updateConfig = true;
+ settings.drawInteface(true);
+ }
+
+ if ((found == 5 && events._released) || ui._key == 'N') {
+ // New font style
+ int fontNum = screen.fontNumber() + 1;
+ if (fontNum == 3)
+ fontNum = 0;
+
+ screen.setFont(fontNum);
+ updateConfig = true;
+ settings.drawInteface(true);
+ }
+
+ if ((found == 8 && events._released) || ui._key == 'F') {
+ // Toggle fade style
+ screen._fadeStyle = !screen._fadeStyle;
+ updateConfig = true;
+ settings.drawInteface(true);
+ }
+
+ if ((found == 9 && events._released) || ui._key == 'W') {
+ // Window style
+ ui._slideWindows = !ui._slideWindows;
+ updateConfig = true;
+ settings.drawInteface(true);
+ }
+
+ if ((found == 10 && events._released) || ui._key == 'P') {
+ // Toggle portraits being shown
+ people._portraitsOn = !people._portraitsOn;
+ updateConfig = true;
+ settings.drawInteface(true);
+ }
+ } while (!vm->shouldQuit());
+
+ ui.banishWindow();
+
+ if (updateConfig)
+ vm->saveConfig();
+
+ ui._keyPress = '\0';
+ ui._keyboardInput = false;
+ ui._windowBounds.top = CONTROLS_Y1;
+ ui._key = -1;
+}
+
+} // End of namespace Scalpel
+
+} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/settings.h b/engines/sherlock/scalpel/settings.h
new file mode 100644
index 0000000..ff2e647
--- /dev/null
+++ b/engines/sherlock/scalpel/settings.h
@@ -0,0 +1,63 @@
+/* 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.
+ *
+ */
+
+#ifndef SHERLOCK_SETTINGS_H
+#define SHERLOCK_SETTINGS_H
+
+#include "common/scummsys.h"
+
+namespace Sherlock {
+
+class SherlockEngine;
+
+namespace Scalpel {
+
+class Settings {
+private:
+ SherlockEngine *_vm;
+
+ Settings(SherlockEngine *vm) : _vm(vm) {}
+
+ /**
+ * Draws the interface for the settings window
+ */
+ void drawInteface(bool flag);
+
+ /**
+ * Draws the buttons for the settings dialog
+ */
+ int drawButtons(const Common::Point &pt, int key);
+public:
+ /**
+ * Handles input when the settings window is being shown
+ * @remarks Whilst this would in theory be better in the Journal class, since it displays in
+ * the user interface, it uses so many internal UI fields, that it sort of made some sense
+ * to put it in the UserInterface class.
+ */
+ static void show(SherlockEngine *vm);
+};
+
+} // End of namespace Scalpel
+
+} // End of namespace Sherlock
+
+#endif
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 06bbabf..0f0187e 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -23,8 +23,10 @@
#include "sherlock/scene.h"
#include "sherlock/sherlock.h"
#include "sherlock/scalpel/scalpel.h"
+#include "sherlock/scalpel/scalpel_scene.h"
#include "sherlock/screen.h"
#include "sherlock/tattoo/tattoo.h"
+#include "sherlock/tattoo/tattoo_scene.h"
namespace Sherlock {
@@ -1325,554 +1327,4 @@ void Scene::checkBgShapes() {
}
}
-/*----------------------------------------------------------------*/
-
-namespace Scalpel {
-
-void ScalpelScene::checkBgShapes() {
- People &people = *_vm->_people;
- Person &holmes = people._player;
- Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
-
- // Call the base scene method to handle bg shapes
- Scene::checkBgShapes();
-
- // Iterate through the canim list
- for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- Object &obj = _canimShapes[idx];
- if (obj._type == STATIC_BG_SHAPE || obj._type == ACTIVE_BG_SHAPE) {
- if ((obj._flags & 5) == 1) {
- obj._misc = (pt.y < (obj._position.y + obj._imageFrame->_frame.h - 1)) ?
- NORMAL_FORWARD : NORMAL_BEHIND;
- } else if (!(obj._flags & 1)) {
- obj._misc = BEHIND;
- } else if (obj._flags & 4) {
- obj._misc = FORWARD;
- }
- }
- }
-}
-
-void ScalpelScene::doBgAnimCheckCursor() {
- Inventory &inv = *_vm->_inventory;
- Events &events = *_vm->_events;
- Sound &sound = *_vm->_sound;
- UserInterface &ui = *_vm->_ui;
- Common::Point mousePos = events.mousePos();
-
- if (ui._menuMode == LOOK_MODE) {
- if (mousePos.y > CONTROLS_Y1)
- events.setCursor(ARROW);
- else if (mousePos.y < CONTROLS_Y)
- events.setCursor(MAGNIFY);
- }
-
- // Check for setting magnifying glass cursor
- if (ui._menuMode == INV_MODE || ui._menuMode == USE_MODE || ui._menuMode == GIVE_MODE) {
- if (inv._invMode == INVMODE_LOOK) {
- // Only show Magnifying glass cursor if it's not on the inventory command line
- if (mousePos.y < CONTROLS_Y || mousePos.y >(CONTROLS_Y1 + 13))
- events.setCursor(MAGNIFY);
- else
- events.setCursor(ARROW);
- } else {
- events.setCursor(ARROW);
- }
- }
-
- if (sound._diskSoundPlaying && !*sound._soundIsOn) {
- // Loaded sound just finished playing
- sound.freeDigiSound();
- }
-}
-
-void ScalpelScene::doBgAnim() {
- Scalpel::ScalpelEngine &vm = *((Scalpel::ScalpelEngine *)_vm);
- Events &events = *_vm->_events;
- People &people = *_vm->_people;
- Screen &screen = *_vm->_screen;
- Talk &talk = *_vm->_talk;
-
- screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
- talk._talkToAbort = false;
-
- if (_restoreFlag) {
- for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
- if (people[idx]._type == CHARACTER)
- people[idx].checkSprite();
- }
-
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE)
- _bgShapes[idx].checkObject();
- }
-
- if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE)
- people._portrait.checkObject();
-
- for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- if (_canimShapes[idx]._type != INVALID && _canimShapes[idx]._type != REMOVE)
- _canimShapes[idx].checkObject();
- }
-
- if (_currentScene == 12)
- vm.eraseMirror12();
-
- // Restore the back buffer from the back buffer 2 in the changed area
- Common::Rect bounds(people[AL]._oldPosition.x, people[AL]._oldPosition.y,
- people[AL]._oldPosition.x + people[AL]._oldSize.x,
- people[AL]._oldPosition.y + people[AL]._oldSize.y);
- Common::Point pt(bounds.left, bounds.top);
-
- if (people[AL]._type == CHARACTER)
- screen.restoreBackground(bounds);
- else if (people[AL]._type == REMOVE)
- screen._backBuffer->blitFrom(screen._backBuffer2, pt, bounds);
-
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &o = _bgShapes[idx];
- if (o._type == ACTIVE_BG_SHAPE || o._type == HIDE_SHAPE || o._type == REMOVE)
- screen.restoreBackground(o.getOldBounds());
- }
-
- if (people._portraitLoaded)
- screen.restoreBackground(Common::Rect(
- people._portrait._oldPosition.x, people._portrait._oldPosition.y,
- people._portrait._oldPosition.x + people._portrait._oldSize.x,
- people._portrait._oldPosition.y + people._portrait._oldSize.y
- ));
-
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &o = _bgShapes[idx];
- if (o._type == NO_SHAPE && ((o._flags & OBJ_BEHIND) == 0)) {
- // Restore screen area
- screen._backBuffer->blitFrom(screen._backBuffer2, o._position,
- Common::Rect(o._position.x, o._position.y,
- o._position.x + o._noShapeSize.x, o._position.y + o._noShapeSize.y));
-
- o._oldPosition = o._position;
- o._oldSize = o._noShapeSize;
- }
- }
-
- for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- Object &o = _canimShapes[idx];
- if (o._type == ACTIVE_BG_SHAPE || o._type == HIDE_SHAPE || o._type == REMOVE)
- screen.restoreBackground(Common::Rect(o._oldPosition.x, o._oldPosition.y,
- o._oldPosition.x + o._oldSize.x, o._oldPosition.y + o._oldSize.y));
- }
- }
-
- //
- // Update the background objects and canimations
- //
-
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &o = _bgShapes[idx];
- if (o._type == ACTIVE_BG_SHAPE || o._type == NO_SHAPE)
- o.adjustObject();
- }
-
- if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE)
- people._portrait.adjustObject();
-
- for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- if (_canimShapes[idx]._type != INVALID)
- _canimShapes[idx].adjustObject();
- }
-
- if (people[AL]._type == CHARACTER && people._holmesOn)
- people[AL].adjustSprite();
-
- // Flag the bg shapes which need to be redrawn
- checkBgShapes();
-
- if (_currentScene == 12)
- vm.doMirror12();
-
- // Draw all active shapes which are behind the person
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &o = _bgShapes[idx];
- if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND)
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
- }
-
- // Draw all canimations which are behind the person
- for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- Object &o = _canimShapes[idx];
- if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND) {
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
- }
- }
-
- // Draw all active shapes which are HAPPEN and behind the person
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &o = _bgShapes[idx];
- if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND)
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
- }
-
- // Draw all canimations which are NORMAL and behind the person
- for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- Object &o = _canimShapes[idx];
- if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND) {
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
- }
- }
-
- // Draw the person if not animating
- if (people[AL]._type == CHARACTER && people[AL]._walkLoaded) {
- // If Holmes is too far to the right, move him back so he's on-screen
- int xRight = SHERLOCK_SCREEN_WIDTH - 2 - people[AL]._imageFrame->_frame.w;
- int tempX = MIN(people[AL]._position.x / FIXED_INT_MULTIPLIER, xRight);
-
- bool flipped = people[AL]._sequenceNumber == WALK_LEFT || people[AL]._sequenceNumber == STOP_LEFT ||
- people[AL]._sequenceNumber == WALK_UPLEFT || people[AL]._sequenceNumber == STOP_UPLEFT ||
- people[AL]._sequenceNumber == WALK_DOWNRIGHT || people[AL]._sequenceNumber == STOP_DOWNRIGHT;
- screen._backBuffer->transBlitFrom(*people[AL]._imageFrame,
- Common::Point(tempX, people[AL]._position.y / FIXED_INT_MULTIPLIER - people[AL]._imageFrame->_frame.h), flipped);
- }
-
- // Draw all static and active shapes are NORMAL and are in front of the person
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &o = _bgShapes[idx];
- if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD)
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
- }
-
- // Draw all static and active canimations that are NORMAL and are in front of the person
- for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- Object &o = _canimShapes[idx];
- if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD) {
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
- }
- }
-
- // Draw all static and active shapes that are in front of the person
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &o = _bgShapes[idx];
- if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD)
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
- }
-
- // Draw any active portrait
- if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE)
- screen._backBuffer->transBlitFrom(*people._portrait._imageFrame,
- people._portrait._position, people._portrait._flags & OBJ_FLIPPED);
-
- // Draw all static and active canimations that are in front of the person
- for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- Object &o = _canimShapes[idx];
- if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD) {
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
- }
- }
-
- // Draw all NO_SHAPE shapes which have flag bit 0 clear
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &o = _bgShapes[idx];
- if (o._type == NO_SHAPE && (o._flags & OBJ_BEHIND) == 0)
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
- }
-
- // Bring the newly built picture to the screen
- if (_animating == 2) {
- _animating = 0;
- screen.slamRect(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
- } else {
- if (people[AL]._type != INVALID && ((_goToScene == -1 || _canimShapes.empty()))) {
- if (people[AL]._type == REMOVE) {
- screen.slamRect(Common::Rect(
- people[AL]._oldPosition.x, people[AL]._oldPosition.y,
- people[AL]._oldPosition.x + people[AL]._oldSize.x,
- people[AL]._oldPosition.y + people[AL]._oldSize.y
- ));
- people[AL]._type = INVALID;
- } else {
- screen.flushImage(people[AL]._imageFrame,
- Common::Point(people[AL]._position.x / FIXED_INT_MULTIPLIER,
- people[AL]._position.y / FIXED_INT_MULTIPLIER - people[AL].frameHeight()),
- &people[AL]._oldPosition.x, &people[AL]._oldPosition.y,
- &people[AL]._oldSize.x, &people[AL]._oldSize.y);
- }
- }
-
- if (_currentScene == 12)
- vm.flushMirror12();
-
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &o = _bgShapes[idx];
- if ((o._type == ACTIVE_BG_SHAPE || o._type == REMOVE) && _goToScene == -1) {
- screen.flushImage(o._imageFrame, o._position,
- &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y);
- }
- }
-
- if (people._portraitLoaded) {
- if (people._portrait._type == REMOVE)
- screen.slamRect(Common::Rect(
- people._portrait._position.x, people._portrait._position.y,
- people._portrait._position.x + people._portrait._delta.x,
- people._portrait._position.y + people._portrait._delta.y
- ));
- else
- screen.flushImage(people._portrait._imageFrame, people._portrait._position,
- &people._portrait._oldPosition.x, &people._portrait._oldPosition.y,
- &people._portrait._oldSize.x, &people._portrait._oldSize.y);
-
- if (people._portrait._type == REMOVE)
- people._portrait._type = INVALID;
- }
-
- if (_goToScene == -1) {
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &o = _bgShapes[idx];
- if (o._type == NO_SHAPE && (o._flags & OBJ_BEHIND) == 0) {
- screen.slamArea(o._position.x, o._position.y, o._oldSize.x, o._oldSize.y);
- screen.slamArea(o._oldPosition.x, o._oldPosition.y, o._oldSize.x, o._oldSize.y);
- } else if (o._type == HIDE_SHAPE) {
- // Hiding shape, so flush it out and mark it as hidden
- screen.flushImage(o._imageFrame, o._position,
- &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y);
- o._type = HIDDEN;
- }
- }
- }
-
- for (int idx = _canimShapes.size() - 1; idx >= 0; --idx) {
- Object &o = _canimShapes[idx];
-
- if (o._type == INVALID) {
- // Anim shape was invalidated by checkEndOfSequence, so at this point we can remove it
- _canimShapes.remove_at(idx);
- } else if (o._type == REMOVE) {
- if (_goToScene == -1)
- screen.slamArea(o._position.x, o._position.y, o._delta.x, o._delta.y);
-
- // Shape for an animation is no longer needed, so remove it completely
- _canimShapes.remove_at(idx);
- } else if (o._type == ACTIVE_BG_SHAPE) {
- screen.flushImage(o._imageFrame, o._position,
- &o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y);
- }
- }
- }
-
- _restoreFlag = true;
- _doBgAnimDone = true;
-
- events.wait(3);
- screen.resetDisplayBounds();
-
- // Check if the method was called for calling a portrait, and a talk was
- // interrupting it. This talk file would not have been executed at the time,
- // since we needed to finish the 'doBgAnim' to finish clearing the portrait
- if (people._clearingThePortrait && talk._scriptMoreFlag == 3) {
- // Reset the flags and call to talk
- people._clearingThePortrait = false;
- talk._scriptMoreFlag = 0;
- talk.talkTo(talk._scriptName);
- }
-}
-
-} // End of namespace Scalpel
-
-/*----------------------------------------------------------------*/
-
-namespace Tattoo {
-
-TattooScene::TattooScene(SherlockEngine *vm) : Scene(vm) {
- _arrowZone = -1;
- _mask = _mask1 = nullptr;
- _maskCounter = 0;
-}
-
-void TattooScene::checkBgShapes() {
- People &people = *_vm->_people;
- Person &holmes = people._player;
- Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
-
- // Call the base scene method to handle bg shapes
- Scene::checkBgShapes();
-
- // Check for any active playing animation
- if (_activeCAnim._images && _activeCAnim._zPlacement != REMOVE) {
- switch (_activeCAnim._flags & 3) {
- case 0:
- _activeCAnim._zPlacement = BEHIND;
- break;
- case 1:
- _activeCAnim._zPlacement = ((_activeCAnim._position.y + _activeCAnim._imageFrame->_frame.h - 1)) ?
- NORMAL_FORWARD : NORMAL_BEHIND;
- break;
- case 2:
- _activeCAnim._zPlacement = FORWARD;
- break;
- default:
- break;
- }
- }
-}
-
-void TattooScene::doBgAnimCheckCursor() {
- Events &events = *_vm->_events;
- UserInterface &ui = *_vm->_ui;
- Common::Point mousePos = events.mousePos();
-
- // If we're in Look Mode, make sure the cursor is the magnifying glass
- if (ui._menuMode == LOOK_MODE && events.getCursor() != MAGNIFY)
- events.setCursor(MAGNIFY);
-
- // See if the mouse is over any of the arrow zones, and if so, change the cursor to the correct
- // arrow cursor indicating the direcetion of the exit
- if (events.getCursor() == ARROW || events.getCursor() >= EXIT_ZONES_START) {
- CursorId cursorId = ARROW;
-
- if (ui._menuMode == STD_MODE && _arrowZone != -1 && _currentScene != 90) {
- for (uint idx = 0; idx < _exits.size(); ++idx) {
- Exit &exit = _exits[idx];
- if (exit.contains(mousePos))
- cursorId = (CursorId)(exit._image + EXIT_ZONES_START);
- }
- }
-
- events.setCursor(cursorId);
- }
-}
-
-void TattooScene::doBgAnimEraseBackground() {
- TattooEngine &vm = *((TattooEngine *)_vm);
- People &people = *_vm->_people;
- Screen &screen = *_vm->_screen;
- TattooUserInterface &ui = *((TattooUserInterface *)_vm->_ui);
-
- static const int16 OFFSETS[16] = { -1, -2, -3, -3, -2, -1, -1, 0, 1, 2, 3, 3, 2, 1, 0, 0 };
-
- if (_mask != nullptr) {
- if (screen._backBuffer1.w() > screen.w())
- screen.blitFrom(screen._backBuffer1, Common::Point(0, 0), Common::Rect(screen._currentScroll, 0,
- screen._currentScroll + screen.w(), screen.h()));
- else
- screen.blitFrom(screen._backBuffer1);
-
- switch (_currentScene) {
- case 7:
- if (++_maskCounter == 2) {
- _maskCounter = 0;
- if (--_maskOffset.x < 0)
- _maskOffset.x = SHERLOCK_SCREEN_WIDTH - 1;
- }
- break;
-
- case 8:
- _maskOffset.x += 2;
- if (_maskOffset.x >= SHERLOCK_SCREEN_WIDTH)
- _maskOffset.x = 0;
- break;
-
- case 18:
- case 68:
- ++_maskCounter;
- if (_maskCounter / 4 >= 16)
- _maskCounter = 0;
-
- _maskOffset.x = OFFSETS[_maskCounter / 4];
- break;
-
- case 53:
- if (++_maskCounter == 2) {
- _maskCounter = 0;
- if (++_maskOffset.x == screen._backBuffer1.w())
- _maskOffset.x = 0;
- }
- break;
-
- default:
- break;
- }
- } else {
- // Standard scene without mask, so call user interface to erase any UI elements as necessary
- ui.doBgAnimRestoreUI();
-
- // Restore background for any areas covered by characters and shapes
- for (uint idx = 0; idx < MAX_CHARACTERS; ++idx)
- screen.restoreBackground(Common::Rect(people[idx]._oldPosition.x, people[idx]._oldPosition.y,
- people[idx]._oldPosition.x + people[idx]._oldSize.x, people[idx]._oldPosition.y + people[idx]._oldSize.y));
-
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &obj = _bgShapes[idx];
-
- if ((obj._type == ACTIVE_BG_SHAPE && (obj._maxFrames > 1 || obj._delta.x != 0 || obj._delta.y != 0)) ||
- obj._type == HIDE_SHAPE || obj._type == REMOVE)
- screen._backBuffer1.blitFrom(*obj._imageFrame, obj._oldPosition,
- Common::Rect(obj._oldPosition.x, obj._oldPosition.y, obj._oldPosition.x + obj._oldSize.x,
- obj._oldPosition.y + obj._oldSize.y));
- }
-
- // If credits are active, erase the area they cover
- if (vm._creditsActive)
- vm.eraseCredits();
- }
-
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- Object &obj = _bgShapes[idx];
-
- if (obj._type == NO_SHAPE && (obj._flags & 1) == 0) {
- screen._backBuffer1.blitFrom(screen._backBuffer2, obj._position, obj.getNoShapeBounds());
-
- obj._oldPosition = obj._position;
- obj._oldSize = obj._noShapeSize;
- }
- }
-
- // Adjust the Target Scroll if needed
- if ((people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER - screen._currentScroll) <
- (SHERLOCK_SCREEN_WIDTH / 8) && people[people._walkControl]._delta.x < 0) {
-
- screen._targetScroll = (short)(people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER -
- SHERLOCK_SCREEN_WIDTH / 8 - 250);
- if (screen._targetScroll < 0)
- screen._targetScroll = 0;
- }
-
- if ((people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER - screen._currentScroll) > (SHERLOCK_SCREEN_WIDTH / 4 * 3)
- && people[people._walkControl]._delta.x > 0)
- screen._targetScroll = (short)(people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER -
- SHERLOCK_SCREEN_WIDTH / 4 * 3 + 250);
-
- if (screen._targetScroll > screen._scrollSize)
- screen._targetScroll = screen._scrollSize;
-
- ui.doScroll();
-}
-
-void TattooScene::doBgAnim() {
- doBgAnimCheckCursor();
-
-// Events &events = *_vm->_events;
- People &people = *_vm->_people;
-// Scene &scene = *_vm->_scene;
- Screen &screen = *_vm->_screen;
- Talk &talk = *_vm->_talk;
-
- screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
- talk._talkToAbort = false;
-
- // Check the characters and sprites for updates
- for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
- if (people[idx]._type == CHARACTER)
- people[idx].checkSprite();
- }
-
- for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE)
- _bgShapes[idx].checkObject();
- }
-
- // Erase any affected background areas
- doBgAnimEraseBackground();
-}
-
-} // End of namespace Tattoo
-
} // End of namespace Sherlock
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index ce07850..b5e27ff 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -318,61 +318,6 @@ public:
void setNPCPath(int npc);
};
-namespace Scalpel {
-
-class ScalpelScene : public Scene {
-private:
- void doBgAnimCheckCursor();
-protected:
- /**
- * Checks all the background shapes. If a background shape is animating,
- * it will flag it as needing to be drawn. If a non-animating shape is
- * colliding with another shape, it will also flag it as needing drawing
- */
- virtual void checkBgShapes();
-public:
- ScalpelScene(SherlockEngine *vm) : Scene(vm) {}
-
- /**
- * Draw all objects and characters.
- */
- virtual void doBgAnim();
-};
-
-} // End of namespace Scalpel
-
-namespace Tattoo {
-
-class TattooScene : public Scene {
-private:
- int _arrowZone;
- int _maskCounter;
- Common::Point _maskOffset;
-private:
- void doBgAnimCheckCursor();
-
- void doBgAnimEraseBackground();
-protected:
- /**
- * Checks all the background shapes. If a background shape is animating,
- * it will flag it as needing to be drawn. If a non-animating shape is
- * colliding with another shape, it will also flag it as needing drawing
- */
- virtual void checkBgShapes();
-public:
- ImageFile *_mask, *_mask1;
- CAnimStream _activeCAnim;
-public:
- TattooScene(SherlockEngine *vm);
-
- /**
- * Draw all objects and characters.
- */
- virtual void doBgAnim();
-};
-
-} // End of namespace Tattoo
-
} // End of namespace Sherlock
#endif
diff --git a/engines/sherlock/settings.cpp b/engines/sherlock/settings.cpp
deleted file mode 100644
index 98a13a3..0000000
--- a/engines/sherlock/settings.cpp
+++ /dev/null
@@ -1,340 +0,0 @@
-/* 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/sherlock.h"
-#include "sherlock/settings.h"
-
-namespace Sherlock {
-
-namespace Scalpel {
-
-static const int SETUP_POINTS[12][4] = {
- { 4, 154, 101, 53 }, // Exit
- { 4, 165, 101, 53 }, // Music Toggle
- { 219, 165, 316, 268 }, // Voice Toggle
- { 103, 165, 217, 160 }, // Sound Effects Toggle
- { 219, 154, 316, 268 }, // Help Button Left/Right
- { 103, 154, 217, 160 }, // New Font Style
- { 4, 187, 101, 53 }, // Joystick Toggle
- { 103, 187, 217, 160 }, // Calibrate Joystick
- { 219, 176, 316, 268 }, // Fade Style
- { 103, 176, 217, 160 }, // Window Open Style
- { 4, 176, 101, 53 }, // Portraits Toggle
- { 219, 187, 316, 268 } // _key Pad Accel. Toggle
-};
-
-static const char *const SETUP_STRS0[2] = { "off", "on" };
-static const char *const SETUP_STRS1[2] = { "Directly", "by Pixel" };
-static const char *const SETUP_STRS2[2] = { "Left", "Right" };
-static const char *const SETUP_STRS3[2] = { "Appear", "Slide" };
-static const char *const SETUP_STRS5[2] = { "Left", "Right" };
-static const char *const SETUP_NAMES[12] = {
- "Exit", "M", "V", "S", "B", "New Font Style", "J", "Calibrate Joystick", "F", "W", "P", "K"
-};
-
-/*----------------------------------------------------------------*/
-
-void Settings::drawInteface(bool flag) {
- People &people = *_vm->_people;
- Screen &screen = *_vm->_screen;
- Sound &sound = *_vm->_sound;
- UserInterface &ui = *_vm->_ui;
- Common::String tempStr;
-
- if (!flag) {
- screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y1 + 1), BORDER_COLOR);
- screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y1 + 1, 2, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR);
- screen._backBuffer1.fillRect(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y1 + 1, SHERLOCK_SCREEN_WIDTH,
- SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR);
- screen._backBuffer1.hLine(0, SHERLOCK_SCREEN_HEIGHT - 1, SHERLOCK_SCREEN_WIDTH - 1, BORDER_COLOR);
- screen._backBuffer1.fillRect(Common::Rect(2, CONTROLS_Y1 + 1, SHERLOCK_SCREEN_WIDTH - 2,
- SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND);
- }
-
- screen.makeButton(Common::Rect(SETUP_POINTS[0][0], SETUP_POINTS[0][1], SETUP_POINTS[0][2], SETUP_POINTS[0][1] + 10),
- SETUP_POINTS[0][3] - screen.stringWidth("Exit") / 2, "Exit");
-
- tempStr = Common::String::format("Music %s", SETUP_STRS0[sound._music]);
- screen.makeButton(Common::Rect(SETUP_POINTS[1][0], SETUP_POINTS[1][1], SETUP_POINTS[1][2], SETUP_POINTS[1][1] + 10),
- SETUP_POINTS[1][3] - screen.stringWidth(tempStr) / 2, tempStr);
-
- tempStr = Common::String::format("Voices %s", SETUP_STRS0[sound._voices]);
- screen.makeButton(Common::Rect(SETUP_POINTS[2][0], SETUP_POINTS[2][1], SETUP_POINTS[2][2], SETUP_POINTS[2][1] + 10),
- SETUP_POINTS[2][3] - screen.stringWidth(tempStr) / 2, tempStr);
-
- tempStr = Common::String::format("Sound Effects %s", SETUP_STRS0[sound._digitized]);
- screen.makeButton(Common::Rect(SETUP_POINTS[3][0], SETUP_POINTS[3][1], SETUP_POINTS[3][2], SETUP_POINTS[3][1] + 10),
- SETUP_POINTS[3][3] - screen.stringWidth(tempStr) / 2, tempStr);
-
- tempStr = Common::String::format("Auto Help %s", SETUP_STRS5[ui._helpStyle]);
- screen.makeButton(Common::Rect(SETUP_POINTS[4][0], SETUP_POINTS[4][1], SETUP_POINTS[4][2], SETUP_POINTS[4][1] + 10),
- SETUP_POINTS[4][3] - screen.stringWidth(tempStr) / 2, tempStr);
- screen.makeButton(Common::Rect(SETUP_POINTS[5][0], SETUP_POINTS[5][1], SETUP_POINTS[5][2], SETUP_POINTS[5][1] + 10),
- SETUP_POINTS[5][3] - screen.stringWidth("New Font Style") / 2, "New Font Style");
-
- // WORKAROUND: We don't support the joystick in ScummVM, so draw the next two buttons as disabled
- tempStr = "Joystick Off";
- screen.makeButton(Common::Rect(SETUP_POINTS[6][0], SETUP_POINTS[6][1], SETUP_POINTS[6][2], SETUP_POINTS[6][1] + 10),
- SETUP_POINTS[6][3] - screen.stringWidth(tempStr) / 2, tempStr);
- screen.buttonPrint(Common::Point(SETUP_POINTS[6][3], SETUP_POINTS[6][1]), COMMAND_NULL, false, tempStr);
-
- tempStr = "Calibrate Joystick";
- screen.makeButton(Common::Rect(SETUP_POINTS[7][0], SETUP_POINTS[7][1], SETUP_POINTS[7][2], SETUP_POINTS[7][1] + 10),
- SETUP_POINTS[7][3] - screen.stringWidth(tempStr) / 2, tempStr);
- screen.buttonPrint(Common::Point(SETUP_POINTS[7][3], SETUP_POINTS[7][1]), COMMAND_NULL, false, tempStr);
-
- tempStr = Common::String::format("Fade %s", screen._fadeStyle ? "by Pixel" : "Directly");
- screen.makeButton(Common::Rect(SETUP_POINTS[8][0], SETUP_POINTS[8][1], SETUP_POINTS[8][2], SETUP_POINTS[8][1] + 10),
- SETUP_POINTS[8][3] - screen.stringWidth(tempStr) / 2, tempStr);
-
- tempStr = Common::String::format("Windows %s", ui._slideWindows ? "Slide" : "Appear");
- screen.makeButton(Common::Rect(SETUP_POINTS[9][0], SETUP_POINTS[9][1], SETUP_POINTS[9][2], SETUP_POINTS[9][1] + 10),
- SETUP_POINTS[9][3] - screen.stringWidth(tempStr) / 2, tempStr);
-
- tempStr = Common::String::format("Portraits %s", SETUP_STRS0[people._portraitsOn]);
- screen.makeButton(Common::Rect(SETUP_POINTS[10][0], SETUP_POINTS[10][1], SETUP_POINTS[10][2], SETUP_POINTS[10][1] + 10),
- SETUP_POINTS[10][3] - screen.stringWidth(tempStr) / 2, tempStr);
-
- tempStr = "Key Pad Slow";
- screen.makeButton(Common::Rect(SETUP_POINTS[11][0], SETUP_POINTS[11][1], SETUP_POINTS[11][2], SETUP_POINTS[11][1] + 10),
- SETUP_POINTS[11][3] - screen.stringWidth(tempStr) / 2, tempStr);
- screen.buttonPrint(Common::Point(SETUP_POINTS[11][3], SETUP_POINTS[11][1]), COMMAND_NULL, false, tempStr);
-
- // Show the window immediately, or slide it on-screen
- if (!flag) {
- if (!ui._slideWindows) {
- screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
- } else {
- ui.summonWindow(true, CONTROLS_Y1);
- }
-
- ui._windowOpen = true;
- } else {
- screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
- }
-}
-
-int Settings::drawButtons(const Common::Point &pt, int _key) {
- Events &events = *_vm->_events;
- People &people = *_vm->_people;
- Screen &screen = *_vm->_screen;
- Sound &sound = *_vm->_sound;
- UserInterface &ui = *_vm->_ui;
- int found = -1;
- byte color;
- Common::String tempStr;
-
- for (int idx = 0; idx < 12; ++idx) {
- if ((pt.x > SETUP_POINTS[idx][0] && pt.x < SETUP_POINTS[idx][2] && pt.y > SETUP_POINTS[idx][1]
- && pt.y < (SETUP_POINTS[idx][1] + 10) && (events._pressed || events._released))
- || (_key == SETUP_NAMES[idx][0])) {
- found = idx;
- color = COMMAND_HIGHLIGHTED;
- } else {
- color = COMMAND_FOREGROUND;
- }
-
- // Print the button text
- switch (idx) {
- case 1:
- tempStr = Common::String::format("Music %s", SETUP_STRS0[sound._music]);
- screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
- break;
- case 2:
- tempStr = Common::String::format("Voices %s", SETUP_STRS0[sound._voices]);
- screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
- break;
- case 3:
- tempStr = Common::String::format("Sound Effects %s", SETUP_STRS0[sound._digitized]);
- screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
- break;
- case 4:
- tempStr = Common::String::format("Auto Help %s", SETUP_STRS2[ui._helpStyle]);
- screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
- break;
- case 6:
- tempStr = "Joystick Off";
- screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), COMMAND_NULL, true, tempStr);
- break;
- case 7:
- tempStr = "Calibrate Joystick";
- screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), COMMAND_NULL, true, tempStr);
- break;
- case 8:
- tempStr = Common::String::format("Fade %s", SETUP_STRS1[screen._fadeStyle]);
- screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
- break;
- case 9:
- tempStr = Common::String::format("Windows %s", SETUP_STRS3[ui._slideWindows]);
- screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
- break;
- case 10:
- tempStr = Common::String::format("Portraits %s", SETUP_STRS0[people._portraitsOn]);
- screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
- break;
- case 11:
- tempStr = "Key Pad Slow";
- screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), COMMAND_NULL, true, tempStr);
- break;
- default:
- screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, SETUP_NAMES[idx]);
- break;
- }
- }
-
- return found;
-}
-
-void Settings::show(SherlockEngine *vm) {
- Events &events = *vm->_events;
- People &people = *vm->_people;
- Scene &scene = *vm->_scene;
- Screen &screen = *vm->_screen;
- Sound &sound = *vm->_sound;
- Talk &talk = *vm->_talk;
- ScalpelUserInterface &ui = *(ScalpelUserInterface *)vm->_ui;
- bool updateConfig = false;
-
- assert(vm->getGameID() == GType_SerratedScalpel);
- Settings settings(vm);
- settings.drawInteface(false);
-
- do {
- if (ui._menuCounter)
- ui.whileMenuCounter();
-
- int found = -1;
- ui._key = -1;
-
- scene.doBgAnim();
- if (talk._talkToAbort)
- return;
-
- events.setButtonState();
- Common::Point pt = events.mousePos();
-
- if (events._pressed || events._released || events.kbHit()) {
- ui.clearInfo();
- ui._key = -1;
-
- if (events.kbHit()) {
- Common::KeyState keyState = events.getKey();
- ui._key = toupper(keyState.keycode);
-
- if (ui._key == Common::KEYCODE_RETURN || ui._key == Common::KEYCODE_SPACE) {
- events._pressed = false;
- events._oldButtons = 0;
- ui._keyPress = '\0';
- events._released = true;
- }
- }
-
- // Handle highlighting button under mouse
- found = settings.drawButtons(pt, ui._key);
- }
-
- if ((found == 0 && events._released) || (ui._key == 'E' || ui._key == Common::KEYCODE_ESCAPE))
- // Exit
- break;
-
- if ((found == 1 && events._released) || ui._key == 'M') {
- // Toggle music
- if (sound._music) {
- sound.stopSound();
- sound._music = false;
- }
- else {
- sound._music = true;
- sound.startSong();
- }
-
- updateConfig = true;
- settings.drawInteface(true);
- }
-
- if ((found == 2 && events._released) || ui._key == 'V') {
- sound._voices = !sound._voices;
- updateConfig = true;
- settings.drawInteface(true);
- }
-
- if ((found == 3 && events._released) || ui._key == 'S') {
- // Toggle sound effects
- sound._digitized = !sound._digitized;
- updateConfig = true;
- settings.drawInteface(true);
- }
-
- if ((found == 4 && events._released) || ui._key == 'A') {
- // Help button style
- ui._helpStyle = !ui._helpStyle;
- updateConfig = true;
- settings.drawInteface(true);
- }
-
- if ((found == 5 && events._released) || ui._key == 'N') {
- // New font style
- int fontNum = screen.fontNumber() + 1;
- if (fontNum == 3)
- fontNum = 0;
-
- screen.setFont(fontNum);
- updateConfig = true;
- settings.drawInteface(true);
- }
-
- if ((found == 8 && events._released) || ui._key == 'F') {
- // Toggle fade style
- screen._fadeStyle = !screen._fadeStyle;
- updateConfig = true;
- settings.drawInteface(true);
- }
-
- if ((found == 9 && events._released) || ui._key == 'W') {
- // Window style
- ui._slideWindows = !ui._slideWindows;
- updateConfig = true;
- settings.drawInteface(true);
- }
-
- if ((found == 10 && events._released) || ui._key == 'P') {
- // Toggle portraits being shown
- people._portraitsOn = !people._portraitsOn;
- updateConfig = true;
- settings.drawInteface(true);
- }
- } while (!vm->shouldQuit());
-
- ui.banishWindow();
-
- if (updateConfig)
- vm->saveConfig();
-
- ui._keyPress = '\0';
- ui._keyboardInput = false;
- ui._windowBounds.top = CONTROLS_Y1;
- ui._key = -1;
-}
-
-} // End of namespace Scalpel
-
-} // End of namespace Sherlock
diff --git a/engines/sherlock/settings.h b/engines/sherlock/settings.h
deleted file mode 100644
index ff2e647..0000000
--- a/engines/sherlock/settings.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* 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.
- *
- */
-
-#ifndef SHERLOCK_SETTINGS_H
-#define SHERLOCK_SETTINGS_H
-
-#include "common/scummsys.h"
-
-namespace Sherlock {
-
-class SherlockEngine;
-
-namespace Scalpel {
-
-class Settings {
-private:
- SherlockEngine *_vm;
-
- Settings(SherlockEngine *vm) : _vm(vm) {}
-
- /**
- * Draws the interface for the settings window
- */
- void drawInteface(bool flag);
-
- /**
- * Draws the buttons for the settings dialog
- */
- int drawButtons(const Common::Point &pt, int key);
-public:
- /**
- * Handles input when the settings window is being shown
- * @remarks Whilst this would in theory be better in the Journal class, since it displays in
- * the user interface, it uses so many internal UI fields, that it sort of made some sense
- * to put it in the UserInterface class.
- */
- static void show(SherlockEngine *vm);
-};
-
-} // End of namespace Scalpel
-
-} // End of namespace Sherlock
-
-#endif
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index 5e9cb02..dd6e776 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -23,6 +23,7 @@
#include "sherlock/talk.h"
#include "sherlock/sherlock.h"
#include "sherlock/screen.h"
+#include "sherlock/scalpel/scalpel_user_interface.h"
namespace Sherlock {
@@ -547,7 +548,7 @@ void Talk::talkTo(const Common::String &filename) {
}
- ui._key = ui._oldKey = COMMANDS[TALK_MODE - 1];
+ ui._key = ui._oldKey = Scalpel::COMMANDS[TALK_MODE - 1];
ui._temp = ui._oldTemp = 0;
ui._menuMode = TALK_MODE;
_talkToFlag = 2;
@@ -784,9 +785,9 @@ void Talk::drawInterface() {
screen.makeButton(Common::Rect(181, CONTROLS_Y, 221, CONTROLS_Y + 10),
200 - screen.stringWidth("Down") / 2, "Down");
} else {
- int strWidth = screen.stringWidth(PRESS_KEY_TO_CONTINUE);
+ int strWidth = screen.stringWidth(Scalpel::PRESS_KEY_TO_CONTINUE);
screen.makeButton(Common::Rect(46, CONTROLS_Y, 273, CONTROLS_Y + 10),
- 160 - strWidth / 2, PRESS_KEY_TO_CONTINUE);
+ 160 - strWidth / 2, Scalpel::PRESS_KEY_TO_CONTINUE);
screen.gPrint(Common::Point(160 - strWidth / 2, CONTROLS_Y), COMMAND_FOREGROUND, "P");
}
}
diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp
new file mode 100644
index 0000000..f03e791
--- /dev/null
+++ b/engines/sherlock/tattoo/tattoo_scene.cpp
@@ -0,0 +1,227 @@
+/* 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/tattoo/tattoo_scene.h"
+#include "sherlock/tattoo/tattoo.h"
+#include "sherlock/tattoo/tattoo_user_interface.h"
+#include "sherlock/events.h"
+#include "sherlock/people.h"
+
+namespace Sherlock {
+
+namespace Tattoo {
+
+TattooScene::TattooScene(SherlockEngine *vm) : Scene(vm) {
+ _arrowZone = -1;
+ _mask = _mask1 = nullptr;
+ _maskCounter = 0;
+}
+
+void TattooScene::checkBgShapes() {
+ People &people = *_vm->_people;
+ Person &holmes = people._player;
+ Common::Point pt(holmes._position.x / FIXED_INT_MULTIPLIER, holmes._position.y / FIXED_INT_MULTIPLIER);
+
+ // Call the base scene method to handle bg shapes
+ Scene::checkBgShapes();
+
+ // Check for any active playing animation
+ if (_activeCAnim._images && _activeCAnim._zPlacement != REMOVE) {
+ switch (_activeCAnim._flags & 3) {
+ case 0:
+ _activeCAnim._zPlacement = BEHIND;
+ break;
+ case 1:
+ _activeCAnim._zPlacement = ((_activeCAnim._position.y + _activeCAnim._imageFrame->_frame.h - 1)) ?
+ NORMAL_FORWARD : NORMAL_BEHIND;
+ break;
+ case 2:
+ _activeCAnim._zPlacement = FORWARD;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void TattooScene::doBgAnimCheckCursor() {
+ Events &events = *_vm->_events;
+ UserInterface &ui = *_vm->_ui;
+ Common::Point mousePos = events.mousePos();
+
+ // If we're in Look Mode, make sure the cursor is the magnifying glass
+ if (ui._menuMode == LOOK_MODE && events.getCursor() != MAGNIFY)
+ events.setCursor(MAGNIFY);
+
+ // See if the mouse is over any of the arrow zones, and if so, change the cursor to the correct
+ // arrow cursor indicating the direcetion of the exit
+ if (events.getCursor() == ARROW || events.getCursor() >= EXIT_ZONES_START) {
+ CursorId cursorId = ARROW;
+
+ if (ui._menuMode == STD_MODE && _arrowZone != -1 && _currentScene != 90) {
+ for (uint idx = 0; idx < _exits.size(); ++idx) {
+ Exit &exit = _exits[idx];
+ if (exit.contains(mousePos))
+ cursorId = (CursorId)(exit._image + EXIT_ZONES_START);
+ }
+ }
+
+ events.setCursor(cursorId);
+ }
+}
+
+void TattooScene::doBgAnimEraseBackground() {
+ TattooEngine &vm = *((TattooEngine *)_vm);
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
+ TattooUserInterface &ui = *((TattooUserInterface *)_vm->_ui);
+
+ static const int16 OFFSETS[16] = { -1, -2, -3, -3, -2, -1, -1, 0, 1, 2, 3, 3, 2, 1, 0, 0 };
+
+ if (_mask != nullptr) {
+ if (screen._backBuffer1.w() > screen.w())
+ screen.blitFrom(screen._backBuffer1, Common::Point(0, 0), Common::Rect(screen._currentScroll, 0,
+ screen._currentScroll + screen.w(), screen.h()));
+ else
+ screen.blitFrom(screen._backBuffer1);
+
+ switch (_currentScene) {
+ case 7:
+ if (++_maskCounter == 2) {
+ _maskCounter = 0;
+ if (--_maskOffset.x < 0)
+ _maskOffset.x = SHERLOCK_SCREEN_WIDTH - 1;
+ }
+ break;
+
+ case 8:
+ _maskOffset.x += 2;
+ if (_maskOffset.x >= SHERLOCK_SCREEN_WIDTH)
+ _maskOffset.x = 0;
+ break;
+
+ case 18:
+ case 68:
+ ++_maskCounter;
+ if (_maskCounter / 4 >= 16)
+ _maskCounter = 0;
+
+ _maskOffset.x = OFFSETS[_maskCounter / 4];
+ break;
+
+ case 53:
+ if (++_maskCounter == 2) {
+ _maskCounter = 0;
+ if (++_maskOffset.x == screen._backBuffer1.w())
+ _maskOffset.x = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else {
+ // Standard scene without mask, so call user interface to erase any UI elements as necessary
+ ui.doBgAnimRestoreUI();
+
+ // Restore background for any areas covered by characters and shapes
+ for (uint idx = 0; idx < MAX_CHARACTERS; ++idx)
+ screen.restoreBackground(Common::Rect(people[idx]._oldPosition.x, people[idx]._oldPosition.y,
+ people[idx]._oldPosition.x + people[idx]._oldSize.x, people[idx]._oldPosition.y + people[idx]._oldSize.y));
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &obj = _bgShapes[idx];
+
+ if ((obj._type == ACTIVE_BG_SHAPE && (obj._maxFrames > 1 || obj._delta.x != 0 || obj._delta.y != 0)) ||
+ obj._type == HIDE_SHAPE || obj._type == REMOVE)
+ screen._backBuffer1.blitFrom(*obj._imageFrame, obj._oldPosition,
+ Common::Rect(obj._oldPosition.x, obj._oldPosition.y, obj._oldPosition.x + obj._oldSize.x,
+ obj._oldPosition.y + obj._oldSize.y));
+ }
+
+ // If credits are active, erase the area they cover
+ if (vm._creditsActive)
+ vm.eraseCredits();
+ }
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &obj = _bgShapes[idx];
+
+ if (obj._type == NO_SHAPE && (obj._flags & 1) == 0) {
+ screen._backBuffer1.blitFrom(screen._backBuffer2, obj._position, obj.getNoShapeBounds());
+
+ obj._oldPosition = obj._position;
+ obj._oldSize = obj._noShapeSize;
+ }
+ }
+
+ // Adjust the Target Scroll if needed
+ if ((people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER - screen._currentScroll) <
+ (SHERLOCK_SCREEN_WIDTH / 8) && people[people._walkControl]._delta.x < 0) {
+
+ screen._targetScroll = (short)(people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER -
+ SHERLOCK_SCREEN_WIDTH / 8 - 250);
+ if (screen._targetScroll < 0)
+ screen._targetScroll = 0;
+ }
+
+ if ((people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER - screen._currentScroll) > (SHERLOCK_SCREEN_WIDTH / 4 * 3)
+ && people[people._walkControl]._delta.x > 0)
+ screen._targetScroll = (short)(people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER -
+ SHERLOCK_SCREEN_WIDTH / 4 * 3 + 250);
+
+ if (screen._targetScroll > screen._scrollSize)
+ screen._targetScroll = screen._scrollSize;
+
+ ui.doScroll();
+}
+
+void TattooScene::doBgAnim() {
+ doBgAnimCheckCursor();
+
+// Events &events = *_vm->_events;
+ People &people = *_vm->_people;
+// Scene &scene = *_vm->_scene;
+ Screen &screen = *_vm->_screen;
+ Talk &talk = *_vm->_talk;
+
+ screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
+ talk._talkToAbort = false;
+
+ // Check the characters and sprites for updates
+ for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
+ if (people[idx]._type == CHARACTER)
+ people[idx].checkSprite();
+ }
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE)
+ _bgShapes[idx].checkObject();
+ }
+
+ // Erase any affected background areas
+ doBgAnimEraseBackground();
+}
+
+} // End of namespace Tattoo
+
+} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_scene.h b/engines/sherlock/tattoo/tattoo_scene.h
new file mode 100644
index 0000000..34e87f4
--- /dev/null
+++ b/engines/sherlock/tattoo/tattoo_scene.h
@@ -0,0 +1,65 @@
+/* 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.
+ *
+ */
+
+#ifndef SHERLOCK_TATTOO_SCENE_H
+#define SHERLOCK_TATTOO_SCENE_H
+
+#include "common/scummsys.h"
+#include "sherlock/scene.h"
+
+namespace Sherlock {
+
+namespace Tattoo {
+
+class TattooScene : public Scene {
+private:
+ int _arrowZone;
+ int _maskCounter;
+ Common::Point _maskOffset;
+private:
+ void doBgAnimCheckCursor();
+
+ void doBgAnimEraseBackground();
+protected:
+ /**
+ * Checks all the background shapes. If a background shape is animating,
+ * it will flag it as needing to be drawn. If a non-animating shape is
+ * colliding with another shape, it will also flag it as needing drawing
+ */
+ virtual void checkBgShapes();
+public:
+ ImageFile *_mask, *_mask1;
+ CAnimStream _activeCAnim;
+public:
+ TattooScene(SherlockEngine *vm);
+
+ /**
+ * Draw all objects and characters.
+ */
+ virtual void doBgAnim();
+};
+
+} // End of namespace Tattoo
+
+} // End of namespace Sherlock
+
+#endif
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp
new file mode 100644
index 0000000..98ec34d
--- /dev/null
+++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp
@@ -0,0 +1,106 @@
+/* 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/tattoo/tattoo_user_interface.h"
+#include "sherlock/tattoo/tattoo_scene.h"
+#include "sherlock/sherlock.h"
+
+namespace Sherlock {
+
+namespace Tattoo {
+
+TattooUserInterface::TattooUserInterface(SherlockEngine *vm): UserInterface(vm) {
+ _menuBuffer = nullptr;
+ _invMenuBuffer = nullptr;
+}
+
+void TattooUserInterface::handleInput() {
+ // TODO
+ _vm->_events->pollEventsAndWait();
+}
+
+void TattooUserInterface::doBgAnimRestoreUI() {
+ TattooScene &scene = *((TattooScene *)_vm->_scene);
+ Screen &screen = *_vm->_screen;
+
+ // If _oldMenuBounds was set, then either a new menu has been opened or the current menu has been closed.
+ // Either way, we need to restore the area where the menu was displayed
+ if (_oldMenuBounds.width() > 0)
+ screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldMenuBounds.left, _oldMenuBounds.top),
+ _oldMenuBounds);
+
+ if (_oldInvMenuBounds.width() > 0)
+ screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldInvMenuBounds.left, _oldInvMenuBounds.top),
+ _oldInvMenuBounds);
+
+ if (_menuBuffer != nullptr)
+ screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_menuBounds.left, _menuBounds.top), _menuBounds);
+ if (_invMenuBuffer != nullptr)
+ screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_invMenuBounds.left, _invMenuBounds.top), _invMenuBounds);
+
+ // If there is a Text Tag being display, restore the area underneath it
+ if (_oldTagBounds.width() > 0)
+ screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldTagBounds.left, _oldTagBounds.top),
+ _oldTagBounds);
+
+ // If there is an Inventory being shown, restore the graphics underneath it
+ if (_oldInvGraphicBounds.width() > 0)
+ screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldInvGraphicBounds.left, _oldInvGraphicBounds.top),
+ _oldInvGraphicBounds);
+
+ // If a canimation is active, restore the graphics underneath it
+ if (scene._activeCAnim._images != nullptr)
+ screen.restoreBackground(scene._activeCAnim._oldBounds);
+
+ // If a canimation just ended, remove it's graphics from the backbuffer
+ if (scene._activeCAnim._removeBounds.width() > 0)
+ screen.restoreBackground(scene._activeCAnim._removeBounds);
+}
+
+void TattooUserInterface::doScroll() {
+ Screen &screen = *_vm->_screen;
+ int oldScroll = screen._currentScroll;
+
+ // If we're already at the target scroll position, nothing needs to be done
+ if (screen._targetScroll == screen._currentScroll)
+ return;
+
+ screen._flushScreen = true;
+ if (screen._targetScroll > screen._currentScroll) {
+ screen._currentScroll += screen._scrollSpeed;
+ if (screen._currentScroll > screen._targetScroll)
+ screen._currentScroll = screen._targetScroll;
+ } else if (screen._targetScroll < screen._currentScroll) {
+ screen._currentScroll -= screen._scrollSpeed;
+ if (screen._currentScroll < screen._targetScroll)
+ screen._currentScroll = screen._targetScroll;
+ }
+
+ if (_menuBuffer != nullptr)
+ _menuBounds.translate(screen._currentScroll - oldScroll, 0);
+ if (_invMenuBuffer != nullptr)
+ _invMenuBounds.translate(screen._currentScroll - oldScroll, 0);
+}
+
+} // End of namespace Tattoo
+
+} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.h b/engines/sherlock/tattoo/tattoo_user_interface.h
new file mode 100644
index 0000000..c7a4c4c
--- /dev/null
+++ b/engines/sherlock/tattoo/tattoo_user_interface.h
@@ -0,0 +1,68 @@
+/* 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.
+ *
+ */
+
+#ifndef SHERLOCK_TATTOO_UI_H
+#define SHERLOCK_TATTOO_UI_H
+
+#include "common/scummsys.h"
+#include "sherlock/user_interface.h"
+
+namespace Sherlock {
+
+namespace Tattoo {
+
+class TattooUserInterface : public UserInterface {
+private:
+ Common::Rect _menuBounds;
+ Common::Rect _oldMenuBounds;
+ Common::Rect _invMenuBounds;
+ Common::Rect _oldInvMenuBounds;
+ Common::Rect _oldTagBounds;
+ Common::Rect _oldInvGraphicBounds;
+ Surface *_menuBuffer;
+ Surface *_invMenuBuffer;
+public:
+ TattooUserInterface(SherlockEngine *vm);
+
+ /**
+ * Handles restoring any areas of the back buffer that were/are covered by UI elements
+ */
+ void doBgAnimRestoreUI();
+
+ /**
+ * Checks to see if the screen needs to be scrolled. If so, scrolls it towards the target position
+ */
+ void doScroll();
+public:
+ virtual ~TattooUserInterface() {}
+
+ /**
+ * Main input handler for the user interface
+ */
+ virtual void handleInput();
+};
+
+} // End of namespace Tattoo
+
+} // End of namespace Sherlock
+
+#endif
diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp
index 5858daf..9fff7cc 100644
--- a/engines/sherlock/user_interface.cpp
+++ b/engines/sherlock/user_interface.cpp
@@ -22,64 +22,11 @@
#include "sherlock/user_interface.h"
#include "sherlock/sherlock.h"
-#include "sherlock/settings.h"
+#include "sherlock/scalpel/scalpel_user_interface.h"
+#include "sherlock/tattoo/tattoo_user_interface.h"
namespace Sherlock {
-// Main user interface menu control locations
-const int MENU_POINTS[12][4] = {
- { 13, 153, 72, 165 },
- { 13, 169, 72, 181 },
- { 13, 185, 72, 197 },
- { 88, 153, 152, 165 },
- { 88, 169, 152, 181 },
- { 88, 185, 152, 197 },
- { 165, 153, 232, 165 },
- { 165, 169, 232, 181 },
- { 165, 185, 233, 197 },
- { 249, 153, 305, 165 },
- { 249, 169, 305, 181 },
- { 249, 185, 305, 197 }
-};
-
-// Inventory control locations */
-const int INVENTORY_POINTS[8][3] = {
- { 4, 50, 29 },
- { 52, 99, 77 },
- { 101, 140, 123 },
- { 142, 187, 166 },
- { 189, 219, 198 },
- { 221, 251, 234 },
- { 253, 283, 266 },
- { 285, 315, 294 }
-};
-
-const char COMMANDS[13] = "LMTPOCIUGJFS";
-const char INVENTORY_COMMANDS[9] = { "ELUG-+,." };
-const char *const PRESS_KEY_FOR_MORE = "Press any Key for More.";
-const char *const PRESS_KEY_TO_CONTINUE = "Press any Key to Continue.";
-
-const char *const MOPEN[] = {
- "This cannot be opened", "It is already open", "It is locked", "Wait for Watson", " ", "."
-};
-const char *const MCLOSE[] = {
- "This cannot be closed", "It is already closed", "The safe door is in the way"
-};
-const char *const MMOVE[] = {
- "This cannot be moved", "It is bolted to the floor", "It is too heavy", "The other crate is in the way"
-};
-const char *const MPICK[] = {
- "Nothing of interest here", "It is bolted down", "It is too big to carry", "It is too heavy",
- "I think a girl would be more your type", "Those flowers belong to Penny", "She's far too young for you!",
- "I think a girl would be more your type!", "Government property for official use only"
-};
-const char *const MUSE[] = {
- "You can't do that", "It had no effect", "You can't reach it", "OK, the door looks bigger! Happy?",
- "Doors don't smoke"
-};
-
-
-
UserInterface *UserInterface::init(SherlockEngine *vm) {
if (vm->getGameID() == GType_SerratedScalpel)
return new Scalpel::ScalpelUserInterface(vm);
@@ -106,2277 +53,4 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) {
_lookHelp = 0;
}
-/*----------------------------------------------------------------*/
-
-namespace Scalpel {
-
-ScalpelUserInterface::ScalpelUserInterface(SherlockEngine *vm): UserInterface(vm) {
- _controls = new ImageFile("menu.all");
- _controlPanel = new ImageFile("controls.vgs");
- _keyPress = '\0';
- _lookHelp = 0;
- _bgFound = 0;
- _oldBgFound = -1;
- _help = _oldHelp = 0;
- _key = _oldKey = '\0';
- _temp = _oldTemp = 0;
- _oldLook = 0;
- _keyboardInput = false;
- _pause = false;
- _cNum = 0;
- _find = 0;
- _oldUse = 0;
-}
-
-ScalpelUserInterface::~ScalpelUserInterface() {
- delete _controls;
- delete _controlPanel;
-}
-
-void ScalpelUserInterface::reset() {
- _oldKey = -1;
- _help = _oldHelp = -1;
- _oldTemp = _temp = -1;
-}
-
-void ScalpelUserInterface::drawInterface(int bufferNum) {
- Screen &screen = *_vm->_screen;
-
- if (bufferNum & 1)
- screen._backBuffer1.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y));
- if (bufferNum & 2)
- screen._backBuffer2.transBlitFrom((*_controlPanel)[0], Common::Point(0, CONTROLS_Y));
- if (bufferNum == 3)
- screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK);
-}
-
-void ScalpelUserInterface::handleInput() {
- Events &events = *_vm->_events;
- Inventory &inv = *_vm->_inventory;
- People &people = *_vm->_people;
- Scene &scene = *_vm->_scene;
- Screen &screen = *_vm->_screen;
- Talk &talk = *_vm->_talk;
-
- if (_menuCounter)
- whileMenuCounter();
-
- Common::Point pt = events.mousePos();
- _bgFound = scene.findBgShape(Common::Rect(pt.x, pt.y, pt.x + 1, pt.y + 1));
- _keyPress = '\0';
-
- // Check kbd and set the mouse released flag if Enter or space is pressed.
- // Otherwise, the pressed _key is stored for later use
- if (events.kbHit()) {
- Common::KeyState keyState = events.getKey();
- _keyPress = keyState.ascii;
-
- if (keyState.keycode == Common::KEYCODE_x && keyState.flags & Common::KBD_ALT) {
- _vm->quitGame();
- events.pollEvents();
- return;
- }
- }
-
- // Do button highlighting check
- if (!talk._scriptMoreFlag) { // Don't if scripts are running
- if (((events._rightPressed || events._rightReleased) && _helpStyle) ||
- (!_helpStyle && !_menuCounter)) {
- // Handle any default commands if we're in STD_MODE
- if (_menuMode == STD_MODE) {
- if (pt.y < CONTROLS_Y &&
- (events._rightPressed || (!_helpStyle && !events._released)) &&
- (_bgFound != -1) && (_bgFound < 1000) &&
- (scene._bgShapes[_bgFound]._defaultCommand ||
- !scene._bgShapes[_bgFound]._description.empty())) {
- // If there is no default command, so set it to Look
- if (scene._bgShapes[_bgFound]._defaultCommand)
- _help = scene._bgShapes[_bgFound]._defaultCommand - 1;
- else
- _help = 0;
-
- // Reset 'help' if it is an invalid command
- if (_help > 5)
- _help = -1;
- } else if (pt.y < CONTROLS_Y &&
- ((events._rightReleased && _helpStyle) || (events._released && !_helpStyle)) &&
- (_bgFound != -1 && _bgFound < 1000) &&
- (scene._bgShapes[_bgFound]._defaultCommand ||
- !scene._bgShapes[_bgFound]._description.empty())) {
- // If there is no default command, set it to Look
- if (scene._bgShapes[_bgFound]._defaultCommand)
- _menuMode = (MenuMode)scene._bgShapes[_bgFound]._defaultCommand;
- else
- _menuMode = LOOK_MODE;
- events._released = true;
- events._pressed = events._oldButtons = false;
- _help = _oldHelp = -1;
-
- if (_menuMode == LOOK_MODE) {
- // Set the flag to tell the game that this was a right-click
- // call to look and should exit without the look button being pressed
- _lookHelp = true;
- }
- } else {
- _help = -1;
- }
-
- // Check if highlighting a different button than last time
- if (_help != _oldHelp) {
- // If another button was highlighted previously, restore it
- if (_oldHelp != -1)
- restoreButton(_oldHelp);
-
- // If we're highlighting a new button, then draw it pressed
- if (_help != -1)
- depressButton(_help);
-
- _oldHelp = _help;
- }
-
- if (_bgFound != _oldBgFound || _oldBgFound == -1) {
- _infoFlag = true;
- clearInfo();
-
- if (_help != -1 && !scene._bgShapes[_bgFound]._description.empty()
- && scene._bgShapes[_bgFound]._description[0] != ' ')
- screen.print(Common::Point(0, INFO_LINE + 1),
- INFO_FOREGROUND, "%s", scene._bgShapes[_bgFound]._description.c_str());
-
- _oldBgFound = _bgFound;
- }
- } else {
- // We're not in STD_MODE
- // If there isn't a window open, then revert back to STD_MODE
- if (!_windowOpen && events._rightReleased) {
- // Restore all buttons
- for (int idx = 0; idx < 12; ++idx)
- restoreButton(idx);
-
- _menuMode = STD_MODE;
- _key = _oldKey = -1;
- _temp = _oldTemp = _lookHelp = _invLookFlag = 0;
- events.clearEvents();
- }
- }
- }
- }
-
- // Reset the old bgshape number if the mouse button is released, so that
- // it can e re-highlighted when we come back here
- if ((events._rightReleased && _helpStyle) || (events._released && !_helpStyle))
- _oldBgFound = -1;
-
- // Do routines that should be done before input processing
- switch (_menuMode) {
- case LOOK_MODE:
- if (!_windowOpen) {
- if (events._released && _bgFound >= 0 && _bgFound < 1000) {
- if (!scene._bgShapes[_bgFound]._examine.empty())
- examine();
- } else {
- lookScreen(pt);
- }
- }
- break;
-
- case MOVE_MODE:
- case OPEN_MODE:
- case CLOSE_MODE:
- case PICKUP_MODE:
- lookScreen(pt);
- break;
-
- case TALK_MODE:
- if (!_windowOpen) {
- bool personFound;
-
- if (_bgFound >= 1000) {
- personFound = false;
- if (!events._released)
- lookScreen(pt);
- } else {
- personFound = _bgFound != -1 && scene._bgShapes[_bgFound]._aType == PERSON;
- }
-
- if (events._released && personFound)
- talk.talk(_bgFound);
- else if (personFound)
- lookScreen(pt);
- else if (_bgFound < 1000)
- clearInfo();
- }
- break;
-
- case USE_MODE:
- case GIVE_MODE:
- case INV_MODE:
- if (inv._invMode == INVMODE_LOOK || inv._invMode == INVMODE_USE || inv._invMode == INVMODE_GIVE) {
- if (pt.y > CONTROLS_Y)
- lookInv();
- else
- lookScreen(pt);
- }
- break;
-
- default:
- break;
- }
-
- //
- // Do input processing
- //
- if (events._pressed || events._released || events._rightPressed || _keyPress || _pause) {
- if (((events._released && (_helpStyle || _help == -1)) || (events._rightReleased && !_helpStyle)) &&
- (pt.y <= CONTROLS_Y) && (_menuMode == STD_MODE)) {
- // The mouse was clicked in the playing area with no action buttons down.
- // Check if the mouse was clicked in a script zone. If it was,
- // then execute the script. Otherwise, walk to the given position
- if (scene.checkForZones(pt, SCRIPT_ZONE) != 0 ||
- scene.checkForZones(pt, NOWALK_ZONE) != 0) {
- // Mouse clicked in script zone
- events._pressed = events._released = false;
- } else {
- people._walkDest = pt;
- people._allowWalkAbort = false;
- people.goAllTheWay();
- }
-
- if (_oldKey != -1) {
- restoreButton(_oldTemp);
- _oldKey = -1;
- }
- }
-
- // Handle action depending on selected mode
- switch (_menuMode) {
- case LOOK_MODE:
- if (_windowOpen)
- doLookControl();
- break;
-
- case MOVE_MODE:
- doMiscControl(ALLOW_MOVE);
- break;
-
- case TALK_MODE:
- if (_windowOpen)
- doTalkControl();
- break;
-
- case OPEN_MODE:
- doMiscControl(ALLOW_OPEN);
- break;
-
- case CLOSE_MODE:
- doMiscControl(ALLOW_CLOSE);
- break;
-
- case PICKUP_MODE:
- doPickControl();
- break;
-
- case USE_MODE:
- case GIVE_MODE:
- case INV_MODE:
- doInvControl();
- break;
-
- case FILES_MODE:
- doEnvControl();
- break;
-
- default:
- break;
- }
-
- // As long as there isn't an open window, do main input processing.
- // Windows are opened when in TALK, USE, INV, and GIVE modes
- if ((!_windowOpen && !_menuCounter && pt.y > CONTROLS_Y) ||
- _keyPress) {
- if (events._pressed || events._released || _pause || _keyPress)
- doMainControl();
- }
-
- if (pt.y < CONTROLS_Y && events._pressed && _oldTemp != (int)(_menuMode - 1) && _oldKey != -1)
- restoreButton(_oldTemp);
- }
-}
-
-void ScalpelUserInterface::depressButton(int num) {
- Screen &screen = *_vm->_screen;
- Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]);
-
- ImageFrame &frame = (*_controls)[num];
- screen._backBuffer1.transBlitFrom(frame, pt);
- screen.slamArea(pt.x, pt.y, pt.x + frame._width, pt.y + frame._height);
-}
-
-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;
-
- screen._backBuffer1.blitFrom(screen._backBuffer2, pt,
- Common::Rect(pt.x, pt.y, pt.x + 90, pt.y + 19));
- screen.slamArea(pt.x, pt.y, pt.x + frame.w, pt.y + frame.h);
-
- if (!_menuCounter) {
- _infoFlag = true;
- clearInfo();
- }
-}
-
-void ScalpelUserInterface::pushButton(int num) {
- Events &events = *_vm->_events;
- _oldKey = -1;
-
- if (!events._released) {
- if (_oldHelp != -1)
- restoreButton(_oldHelp);
- if (_help != -1)
- restoreButton(_help);
-
- depressButton(num);
- events.wait(6);
- }
-
- restoreButton(num);
-}
-
-void ScalpelUserInterface::toggleButton(int num) {
- Screen &screen = *_vm->_screen;
-
- if (_menuMode != (MenuMode)(num + 1)) {
- _menuMode = (MenuMode)(num + 1);
- _oldKey = COMMANDS[num];
- _oldTemp = num;
-
- if (_keyboardInput) {
- if (_oldHelp != -1 && _oldHelp != num)
- restoreButton(_oldHelp);
- if (_help != -1 && _help != num)
- restoreButton(_help);
-
- _keyboardInput = false;
-
- ImageFrame &frame = (*_controls)[num];
- Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]);
- screen._backBuffer1.transBlitFrom(frame, pt);
- screen.slamArea(pt.x, pt.y, pt.x + frame._width, pt.y + frame._height);
- }
- } else {
- _menuMode = STD_MODE;
- _oldKey = -1;
- restoreButton(num);
- }
-}
-
-void ScalpelUserInterface::clearInfo() {
- if (_infoFlag) {
- _vm->_screen->vgaBar(Common::Rect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 19,
- INFO_LINE + 10), INFO_BLACK);
- _infoFlag = false;
- _oldLook = -1;
- }
-}
-
-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 ScalpelUserInterface::whileMenuCounter() {
- if (!(--_menuCounter) || _vm->_events->checkInput()) {
- _menuCounter = 0;
- _infoFlag = true;
- clearInfo();
- }
-}
-
-void ScalpelUserInterface::examine() {
- Events &events = *_vm->_events;
- Inventory &inv = *_vm->_inventory;
- People &people = *_vm->_people;
- Scene &scene = *_vm->_scene;
- Talk &talk = *_vm->_talk;
- Common::Point pt = events.mousePos();
-
- if (pt.y < (CONTROLS_Y + 9)) {
- Object &obj = scene._bgShapes[_bgFound];
-
- if (obj._lookcAnim != 0) {
- int canimSpeed = ((obj._lookcAnim & 0xe0) >> 5) + 1;
- scene._cAnimFramePause = obj._lookFrames;
- _cAnimStr = obj._examine;
- _cNum = (obj._lookcAnim & 0x1f) - 1;
-
- scene.startCAnim(_cNum, canimSpeed);
- } else if (obj._lookPosition.y != 0) {
- // Need to walk to the object to be examined
- people.walkToCoords(Common::Point(obj._lookPosition.x, obj._lookPosition.y * 100), obj._lookFacing);
- }
-
- if (!talk._talkToAbort) {
- _cAnimStr = obj._examine;
- if (obj._lookFlag)
- _vm->setFlags(obj._lookFlag);
- }
- } else {
- // Looking at an inventory item
- _cAnimStr = inv[_selector]._examine;
- if (inv[_selector]._lookFlag)
- _vm->setFlags(inv[_selector]._lookFlag);
- }
-
- if (_invLookFlag) {
- // Don't close the inventory window when starting an examine display, since its
- // window will slide up to replace the inventory display
- _windowOpen = false;
- _menuMode = LOOK_MODE;
- }
-
- if (!talk._talkToAbort) {
- if (!scene._cAnimFramePause)
- printObjectDesc(_cAnimStr, true);
- else
- // description was already printed in startCAnimation
- scene._cAnimFramePause = 0;
- }
-}
-
-void ScalpelUserInterface::lookScreen(const Common::Point &pt) {
- Events &events = *_vm->_events;
- Inventory &inv = *_vm->_inventory;
- Scene &scene = *_vm->_scene;
- Screen &screen = *_vm->_screen;
- Common::Point mousePos = events.mousePos();
- int temp;
- Common::String tempStr;
-
- // Don't display anything for right button command
- if ((events._rightPressed || events._rightPressed) && !events._pressed)
- return;
-
- if (mousePos.y < CONTROLS_Y && (temp = _bgFound) != -1) {
- if (temp != _oldLook) {
- _infoFlag = true;
- clearInfo();
-
- if (temp < 1000)
- tempStr = scene._bgShapes[temp]._description;
- else
- tempStr = scene._bgShapes[temp - 1000]._description;
-
- _infoFlag = true;
- clearInfo();
-
- // Only print description if there is one
- if (!tempStr.empty() && tempStr[0] != ' ') {
- // If inventory is active and an item is selected for a Use or Give action
- if ((_menuMode == INV_MODE || _menuMode == USE_MODE || _menuMode == GIVE_MODE) &&
- (inv._invMode == INVMODE_USE || inv._invMode == INVMODE_GIVE)) {
- int width1 = 0, width2 = 0;
- int x, width;
- if (inv._invMode == INVMODE_USE) {
- // Using an object
- x = width = screen.stringWidth("Use ");
-
- if (temp < 1000 && scene._bgShapes[temp]._aType != PERSON)
- // It's not a person, so make it lowercase
- tempStr.setChar(tolower(tempStr[0]), 0);
-
- x += screen.stringWidth(tempStr);
-
- // If we're using an inventory object, add in the width
- // of the object name and the " on "
- if (_selector != -1) {
- width1 = screen.stringWidth(inv[_selector]._name);
- x += width1;
- width2 = screen.stringWidth(" on ");
- x += width2;
- }
-
- // If the line will be too long, keep cutting off characters
- // until the string will fit
- while (x > 280) {
- x -= screen.charWidth(tempStr.lastChar());
- tempStr.deleteLastChar();
- }
-
- int xStart = (SHERLOCK_SCREEN_WIDTH - x) / 2;
- screen.print(Common::Point(xStart, INFO_LINE + 1),
- INFO_FOREGROUND, "Use ");
-
- if (_selector != -1) {
- screen.print(Common::Point(xStart + width, INFO_LINE + 1),
- TALK_FOREGROUND, "%s", inv[_selector]._name.c_str());
- screen.print(Common::Point(xStart + width + width1, INFO_LINE + 1),
- INFO_FOREGROUND, " on ");
- screen.print(Common::Point(xStart + width + width1 + width2, INFO_LINE + 1),
- INFO_FOREGROUND, "%s", tempStr.c_str());
- } else {
- screen.print(Common::Point(xStart + width, INFO_LINE + 1),
- INFO_FOREGROUND, "%s", tempStr.c_str());
- }
- } else if (temp >= 0 && temp < 1000 && _selector != -1 &&
- scene._bgShapes[temp]._aType == PERSON) {
- // Giving an object to a person
- width1 = screen.stringWidth(inv[_selector]._name);
- x = width = screen.stringWidth("Give ");
- x += width1;
- width2 = screen.stringWidth(" to ");
- x += width2;
- x += screen.stringWidth(tempStr);
-
- // Ensure string will fit on-screen
- while (x > 280) {
- x -= screen.charWidth(tempStr.lastChar());
- tempStr.deleteLastChar();
- }
-
- int xStart = (SHERLOCK_SCREEN_WIDTH - x) / 2;
- screen.print(Common::Point(xStart, INFO_LINE + 1),
- INFO_FOREGROUND, "Give ");
- screen.print(Common::Point(xStart + width, INFO_LINE + 1),
- TALK_FOREGROUND, "%s", inv[_selector]._name.c_str());
- screen.print(Common::Point(xStart + width + width1, INFO_LINE + 1),
- INFO_FOREGROUND, " to ");
- screen.print(Common::Point(xStart + width + width1 + width2, INFO_LINE + 1),
- INFO_FOREGROUND, "%s", tempStr.c_str());
- }
- } else {
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", tempStr.c_str());
- }
-
- _infoFlag = true;
- _oldLook = temp;
- }
- }
- } else {
- clearInfo();
- }
-}
-
-void ScalpelUserInterface::lookInv() {
- Events &events = *_vm->_events;
- Inventory &inv = *_vm->_inventory;
- Screen &screen = *_vm->_screen;
- Common::Point mousePos = events.mousePos();
-
- if (mousePos.x > 15 && mousePos.x < 314 && mousePos.y > (CONTROLS_Y1 + 11)
- && mousePos.y < (SHERLOCK_SCREEN_HEIGHT - 2)) {
- int temp = (mousePos.x - 6) / 52 + inv._invIndex;
- if (temp < inv._holdings) {
- if (temp < inv._holdings) {
- clearInfo();
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND,
- "%s", inv[temp]._description.c_str());
- _infoFlag = true;
- _oldLook = temp;
- }
- } else {
- clearInfo();
- }
- } else {
- clearInfo();
- }
-}
-
-void ScalpelUserInterface::doEnvControl() {
- Events &events = *_vm->_events;
- SaveManager &saves = *_vm->_saves;
- Scene &scene = *_vm->_scene;
- Screen &screen = *_vm->_screen;
- Talk &talk = *_vm->_talk;
- Common::Point mousePos = events.mousePos();
- static const char ENV_COMMANDS[7] = "ELSUDQ";
-
- byte color;
-
- _key = _oldKey = -1;
- _keyboardInput = false;
- int found = saves.getHighlightedButton();
-
- if (events._pressed || events._released) {
- events.clearKeyboard();
-
- // Check for a filename entry being highlighted
- if ((events._pressed || events._released) && mousePos.y > (CONTROLS_Y + 10)) {
- int found1 = 0;
- for (_selector = 0; (_selector < ONSCREEN_FILES_COUNT) && !found1; ++_selector)
- if (mousePos.y > (CONTROLS_Y + 11 + _selector * 10) && mousePos.y < (CONTROLS_Y + 21 + _selector * 10))
- found1 = 1;
-
- if (_selector + saves._savegameIndex - 1 < MAX_SAVEGAME_SLOTS + (saves._envMode != SAVEMODE_LOAD))
- _selector = _selector + saves._savegameIndex - 1;
- else
- _selector = -1;
-
- if (!found1)
- _selector = -1;
- }
-
- // Handle selecting buttons, if any
- saves.highlightButtons(found);
-
- if (found == 0 || found == 5)
- saves._envMode = SAVEMODE_NONE;
- }
-
- if (_keyPress) {
- _key = toupper(_keyPress);
-
- // Escape _key will close the dialog
- if (_key == Common::KEYCODE_ESCAPE)
- _key = 'E';
-
- if (_key == 'E' || _key == 'L' || _key == 'S' || _key == 'U' || _key == 'D' || _key == 'Q') {
- const char *chP = strchr(ENV_COMMANDS, _key);
- int btnIndex = !chP ? -1 : chP - ENV_COMMANDS;
- saves.highlightButtons(btnIndex);
- _keyboardInput = true;
-
- if (_key == 'E' || _key == 'Q') {
- saves._envMode = SAVEMODE_NONE;
- } else if (_key >= '1' && _key <= '9') {
- _keyboardInput = true;
- _selector = _key - '1';
- if (_selector >= MAX_SAVEGAME_SLOTS + (saves._envMode == SAVEMODE_LOAD ? 0 : 1))
- _selector = -1;
-
- if (saves.checkGameOnScreen(_selector))
- _oldSelector = _selector;
- } else {
- _selector = -1;
- }
- }
- }
-
- if (_selector != _oldSelector) {
- if (_oldSelector != -1 && _oldSelector >= saves._savegameIndex && _oldSelector < (saves._savegameIndex + ONSCREEN_FILES_COUNT)) {
- screen.print(Common::Point(6, CONTROLS_Y + 12 + (_oldSelector - saves._savegameIndex) * 10),
- INV_FOREGROUND, "%d.", _oldSelector + 1);
- screen.print(Common::Point(24, CONTROLS_Y + 12 + (_oldSelector - saves._savegameIndex) * 10),
- INV_FOREGROUND, "%s", saves._savegames[_oldSelector].c_str());
- }
-
- if (_selector != -1) {
- screen.print(Common::Point(6, CONTROLS_Y + 12 + (_selector - saves._savegameIndex) * 10),
- TALK_FOREGROUND, "%d.", _selector + 1);
- screen.print(Common::Point(24, CONTROLS_Y + 12 + (_selector - saves._savegameIndex) * 10),
- TALK_FOREGROUND, "%s", saves._savegames[_selector].c_str());
- }
-
- _oldSelector = _selector;
- }
-
- if (events._released || _keyboardInput) {
- if ((found == 0 && events._released) || _key == 'E') {
- banishWindow();
- _windowBounds.top = CONTROLS_Y1;
-
- events._pressed = events._released = _keyboardInput = false;
- _keyPress = '\0';
- } else if ((found == 1 && events._released) || _key == 'L') {
- saves._envMode = SAVEMODE_LOAD;
- if (_selector != -1) {
- saves.loadGame(_selector + 1);
- }
- } else if ((found == 2 && events._released) || _key == 'S') {
- saves._envMode = SAVEMODE_SAVE;
- if (_selector != -1) {
- if (saves.checkGameOnScreen(_selector))
- _oldSelector = _selector;
-
- if (saves.promptForDescription(_selector)) {
- saves.saveGame(_selector + 1, saves._savegames[_selector]);
-
- banishWindow(1);
- _windowBounds.top = CONTROLS_Y1;
- _key = _oldKey = -1;
- _keyPress = '\0';
- _keyboardInput = false;
- } else {
- if (!talk._talkToAbort) {
- screen._backBuffer1.fillRect(Common::Rect(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10,
- SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y + 20 + (_selector - saves._savegameIndex) * 10), INV_BACKGROUND);
- screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10), INV_FOREGROUND,
- "%d.", _selector + 1);
- screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10), INV_FOREGROUND,
- "%s", saves._savegames[_selector].c_str());
-
- screen.slamArea(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10, 311, 10);
- _selector = _oldSelector = -1;
- }
- }
- }
- } else if (((found == 3 && events._released) || _key == 'U') && saves._savegameIndex) {
- bool moreKeys;
- do {
- saves._savegameIndex--;
- screen._backBuffer1.fillRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2,
- SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND);
-
- for (int idx = saves._savegameIndex; idx < (saves._savegameIndex + ONSCREEN_FILES_COUNT); ++idx) {
- color = INV_FOREGROUND;
- if (idx == _selector && idx >= saves._savegameIndex && idx < (saves._savegameIndex + ONSCREEN_FILES_COUNT))
- color = TALK_FOREGROUND;
-
- screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color, "%d.", idx + 1);
- screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color, "%s", saves._savegames[idx].c_str());
- }
-
- screen.slamRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, SHERLOCK_SCREEN_HEIGHT));
-
- color = !saves._savegameIndex ? COMMAND_NULL : COMMAND_FOREGROUND;
- screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), color, true, "Up");
- color = (saves._savegameIndex == MAX_SAVEGAME_SLOTS - ONSCREEN_FILES_COUNT) ? COMMAND_NULL : COMMAND_FOREGROUND;
- screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), color, true, "Down");
-
- // Check whether there are more pending U keys pressed
- moreKeys = false;
- if (events.kbHit()) {
- Common::KeyState keyState = events.getKey();
-
- _key = toupper(keyState.keycode);
- moreKeys = _key == 'U';
- }
- } while ((saves._savegameIndex) && moreKeys);
- } else if (((found == 4 && events._released) || _key == 'D') && saves._savegameIndex < (MAX_SAVEGAME_SLOTS - ONSCREEN_FILES_COUNT)) {
- bool moreKeys;
- do {
- saves._savegameIndex++;
- screen._backBuffer1.fillRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2,
- SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND);
-
- for (int idx = saves._savegameIndex; idx < (saves._savegameIndex + ONSCREEN_FILES_COUNT); ++idx) {
- if (idx == _selector && idx >= saves._savegameIndex && idx < (saves._savegameIndex + ONSCREEN_FILES_COUNT))
- color = TALK_FOREGROUND;
- else
- color = INV_FOREGROUND;
-
- screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color,
- "%d.", idx + 1);
- screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color,
- "%s", saves._savegames[idx].c_str());
- }
-
- screen.slamRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2, SHERLOCK_SCREEN_HEIGHT));
-
- color = (!saves._savegameIndex) ? COMMAND_NULL : COMMAND_FOREGROUND;
- screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), color, true, "Up");
-
- color = (saves._savegameIndex == MAX_SAVEGAME_SLOTS - ONSCREEN_FILES_COUNT) ? COMMAND_NULL : COMMAND_FOREGROUND;
- screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), color, true, "Down");
-
- // Check whether there are more pending D keys pressed
- moreKeys = false;
- if (events.kbHit()) {
- Common::KeyState keyState;
- _key = toupper(keyState.keycode);
-
- moreKeys = _key == 'D';
- }
- } while (saves._savegameIndex < (MAX_SAVEGAME_SLOTS - ONSCREEN_FILES_COUNT) && moreKeys);
- } else if ((found == 5 && events._released) || _key == 'Q') {
- clearWindow();
- screen.print(Common::Point(0, CONTROLS_Y + 20), INV_FOREGROUND, "Are you sure you wish to Quit ?");
- screen.vgaBar(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y + 10), BORDER_COLOR);
-
- screen.makeButton(Common::Rect(112, CONTROLS_Y, 160, CONTROLS_Y + 10), 136 - screen.stringWidth("Yes") / 2, "Yes");
- screen.makeButton(Common::Rect(161, CONTROLS_Y, 209, CONTROLS_Y + 10), 184 - screen.stringWidth("No") / 2, "No");
- screen.slamArea(112, CONTROLS_Y, 97, 10);
-
- do {
- scene.doBgAnim();
-
- if (talk._talkToAbort)
- return;
-
- events.pollEventsAndWait();
- events.setButtonState();
- mousePos = events.mousePos();
-
- if (events.kbHit()) {
- Common::KeyState keyState = events.getKey();
- _key = toupper(keyState.keycode);
-
- if (_key == 'X' && (keyState.flags & Common::KBD_ALT) != 0) {
- _vm->quitGame();
- events.pollEvents();
- return;
- }
-
- if (_key == Common::KEYCODE_ESCAPE)
- _key = 'N';
-
- if (_key == Common::KEYCODE_RETURN || _key == ' ') {
- events._pressed = false;
- events._released = true;
- events._oldButtons = 0;
- _keyPress = '\0';
- }
- }
-
- if (events._pressed || events._released) {
- if (mousePos.x > 112 && mousePos.x < 159 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 9))
- color = COMMAND_HIGHLIGHTED;
- else
- color = COMMAND_FOREGROUND;
- screen.buttonPrint(Common::Point(136, CONTROLS_Y), color, true, "Yes");
-
- if (mousePos.x > 161 && mousePos.x < 208 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 9))
- color = COMMAND_HIGHLIGHTED;
- else
- color = COMMAND_FOREGROUND;
- screen.buttonPrint(Common::Point(184, CONTROLS_Y), color, true, "No");
- }
-
- if (mousePos.x > 112 && mousePos.x < 159 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 9) && events._released)
- _key = 'Y';
-
- if (mousePos.x > 161 && mousePos.x < 208 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 9) && events._released)
- _key = 'N';
- } while (!_vm->shouldQuit() && _key != 'Y' && _key != 'N');
-
- if (_key == 'Y') {
- _vm->quitGame();
- events.pollEvents();
- return;
- } else {
- screen.buttonPrint(Common::Point(184, CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "No");
- banishWindow(1);
- _windowBounds.top = CONTROLS_Y1;
- _key = -1;
- }
- } else {
- if (_selector != -1) {
- // Are we already in Load mode?
- if (saves._envMode == SAVEMODE_LOAD) {
- saves.loadGame(_selector + 1);
- } else if (saves._envMode == SAVEMODE_SAVE || saves.isSlotEmpty(_selector)) {
- // We're already in save mode, or pointing to an empty save slot
- if (saves.checkGameOnScreen(_selector))
- _oldSelector = _selector;
-
- if (saves.promptForDescription(_selector)) {
- saves.saveGame(_selector + 1, saves._savegames[_selector]);
- banishWindow();
- _windowBounds.top = CONTROLS_Y1;
- _key = _oldKey = -1;
- _keyPress = '\0';
- _keyboardInput = false;
- } else {
- if (!talk._talkToAbort) {
- screen._backBuffer1.fillRect(Common::Rect(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10,
- 317, CONTROLS_Y + 20 + (_selector - saves._savegameIndex) * 10), INV_BACKGROUND);
- screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10),
- INV_FOREGROUND, "%d.", _selector + 1);
- screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10),
- INV_FOREGROUND, "%s", saves._savegames[_selector].c_str());
- screen.slamArea(6, CONTROLS_Y + 11 + (_selector - saves._savegameIndex) * 10, 311, 10);
- _selector = _oldSelector = -1;
- }
- }
- }
- }
- }
- }
-}
-
-void ScalpelUserInterface::doInvControl() {
- Events &events = *_vm->_events;
- Inventory &inv = *_vm->_inventory;
- Scene &scene = *_vm->_scene;
- Screen &screen = *_vm->_screen;
- Talk &talk = *_vm->_talk;
- int colors[8];
- Common::Point mousePos = events.mousePos();
-
- _key = _oldKey = -1;
- _keyboardInput = false;
-
- // Check whether any inventory slot is highlighted
- int found = -1;
- Common::fill(&colors[0], &colors[8], (int)COMMAND_FOREGROUND);
- for (int idx = 0; idx < 8; ++idx) {
- Common::Rect r(INVENTORY_POINTS[idx][0], CONTROLS_Y1,
- INVENTORY_POINTS[idx][1], CONTROLS_Y1 + 10);
- if (r.contains(mousePos)) {
- found = idx;
- break;
- }
- }
-
- if (events._pressed || events._released) {
- events.clearKeyboard();
-
- if (found != -1)
- // If a slot highlighted, set its color
- colors[found] = COMMAND_HIGHLIGHTED;
- screen.buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1), colors[0], true, "Exit");
-
- if (found >= 0 && found <= 3) {
- screen.buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1), colors[1], true, "Look");
- screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1), colors[2], true, "Use");
- screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1), colors[3], true, "Give");
- inv._invMode = (InvMode)found;
- _selector = -1;
- }
-
- if (inv._invIndex) {
- screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), colors[4], "^^");
- screen.print(Common::Point(INVENTORY_POINTS[5][2], CONTROLS_Y1 + 1), colors[5], "^");
- }
-
- if ((inv._holdings - inv._invIndex) > 6) {
- screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), colors[6], "_");
- screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1), colors[7], "__");
- }
-
- bool flag = false;
- if (inv._invMode == INVMODE_LOOK || inv._invMode == INVMODE_USE || inv._invMode == INVMODE_GIVE) {
- Common::Rect r(15, CONTROLS_Y1 + 11, 314, SHERLOCK_SCREEN_HEIGHT - 2);
- if (r.contains(mousePos)) {
- _selector = (mousePos.x - 6) / 52 + inv._invIndex;
- if (_selector < inv._holdings)
- flag = true;
- }
- }
-
- if (!flag && mousePos.y >(CONTROLS_Y1 + 11))
- _selector = -1;
- }
-
- if (_keyPress) {
- _key = toupper(_keyPress);
-
- if (_key == Common::KEYCODE_ESCAPE)
- // Escape will also 'E'xit out of inventory display
- _key = 'E';
-
- if (_key == 'E' || _key == 'L' || _key == 'U' || _key == 'G'
- || _key == '-' || _key == '+') {
- InvMode temp = inv._invMode;
-
- const char *chP = strchr(INVENTORY_COMMANDS, _key);
- inv._invMode = !chP ? INVMODE_INVALID : (InvMode)(chP - INVENTORY_COMMANDS);
- inv.invCommands(true);
-
- inv._invMode = temp;
- _keyboardInput = true;
- if (_key == 'E')
- inv._invMode = INVMODE_EXIT;
- _selector = -1;
- } else {
- _selector = -1;
- }
- }
-
- if (_selector != _oldSelector) {
- if (_oldSelector != -1) {
- // Un-highlight
- if (_oldSelector >= inv._invIndex && _oldSelector < (inv._invIndex + 6))
- inv.highlight(_oldSelector, BUTTON_MIDDLE);
- }
-
- if (_selector != -1)
- inv.highlight(_selector, 235);
-
- _oldSelector = _selector;
- }
-
- if (events._released || _keyboardInput) {
- if ((found == 0 && events._released) || _key == 'E') {
- inv.freeInv();
- _infoFlag = true;
- clearInfo();
- banishWindow(false);
- _key = -1;
- events.clearEvents();
- events.setCursor(ARROW);
- } else if ((found == 1 && events._released) || (_key == 'L')) {
- inv._invMode = INVMODE_LOOK;
- } else if ((found == 2 && events._released) || (_key == 'U')) {
- inv._invMode = INVMODE_USE;
- } else if ((found == 3 && events._released) || (_key == 'G')) {
- inv._invMode = INVMODE_GIVE;
- } else if (((found == 4 && events._released) || _key == ',') && inv._invIndex) {
- if (inv._invIndex >= 6)
- inv._invIndex -= 6;
- else
- inv._invIndex = 0;
-
- screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1),
- COMMAND_HIGHLIGHTED, "^^");
- inv.freeGraphics();
- inv.loadGraphics();
- inv.putInv(SLAM_DISPLAY);
- inv.invCommands(true);
- } else if (((found == 5 && events._released) || _key == '-') && inv._invIndex > 0) {
- --inv._invIndex;
- screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), COMMAND_HIGHLIGHTED, "^");
- inv.freeGraphics();
- inv.loadGraphics();
- inv.putInv(SLAM_DISPLAY);
- inv.invCommands(true);
- } else if (((found == 6 && events._released) || _key == '+') && (inv._holdings - inv._invIndex) > 6) {
- ++inv._invIndex;
- screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), COMMAND_HIGHLIGHTED, "_");
- inv.freeGraphics();
- inv.loadGraphics();
- inv.putInv(SLAM_DISPLAY);
- inv.invCommands(true);
- } else if (((found == 7 && events._released) || _key == '.') && (inv._holdings - inv._invIndex) > 6) {
- inv._invIndex += 6;
- if ((inv._holdings - 6) < inv._invIndex)
- inv._invIndex = inv._holdings - 6;
-
- screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1), COMMAND_HIGHLIGHTED, "_");
- inv.freeGraphics();
- inv.loadGraphics();
- inv.putInv(SLAM_DISPLAY);
- inv.invCommands(true);
- } else {
- // If something is being given, make sure it's being given to a person
- if (inv._invMode == INVMODE_GIVE) {
- if (_bgFound != -1 && scene._bgShapes[_bgFound]._aType == PERSON)
- _find = _bgFound;
- else
- _find = -1;
- } else {
- _find = _bgFound;
- }
-
- if ((mousePos.y < CONTROLS_Y1) && (inv._invMode == INVMODE_LOOK) && (_find >= 0) && (_find < 1000)) {
- if (!scene._bgShapes[_find]._examine.empty() &&
- scene._bgShapes[_find]._examine[0] >= ' ')
- inv.refreshInv();
- } else if (_selector != -1 || _find >= 0) {
- // Selector is the inventory object that was clicked on, or selected.
- // If it's -1, then no inventory item is highlighted yet. Otherwise,
- // an object in the scene has been clicked.
-
- if (_selector != -1 && inv._invMode == INVMODE_LOOK
- && mousePos.y >(CONTROLS_Y1 + 11))
- inv.refreshInv();
-
- if (talk._talkToAbort)
- return;
-
- // Now check for the Use and Give actions. If inv_mode is INVMODE_GIVE,
- // that means GIVE is in effect, _selector is the object being
- // given, and _find is the target.
- // The same applies to USE, except if _selector is -1, then USE
- // is being tried on an object in the scene without an inventory
- // object being highlighted first.
-
- if ((inv._invMode == INVMODE_USE || (_selector != -1 && inv._invMode == INVMODE_GIVE)) && _find >= 0) {
- events._pressed = events._released = false;
- _infoFlag = true;
- clearInfo();
-
- int tempSel = _selector; // Save the selector
- _selector = -1;
-
- inv.putInv(SLAM_DISPLAY);
- _selector = tempSel; // Restore it
- InvMode tempMode = inv._invMode;
- inv._invMode = INVMODE_USE55;
- inv.invCommands(true);
-
- _infoFlag = true;
- clearInfo();
- banishWindow(false);
- _key = -1;
-
- inv.freeInv();
-
- bool giveFl = (tempMode >= INVMODE_GIVE);
- if (_selector >= 0)
- // Use/Give inv object with scene object
- checkUseAction(&scene._bgShapes[_find]._use[0], inv[_selector]._name, MUSE, _find, giveFl);
- else
- // Now inv object has been highlighted
- checkUseAction(&scene._bgShapes[_find]._use[0], "*SELF*", MUSE, _find, giveFl);
-
- _selector = _oldSelector = -1;
- }
- }
- }
- }
-}
-
-void ScalpelUserInterface::doLookControl() {
- Events &events = *_vm->_events;
- Inventory &inv = *_vm->_inventory;
- Screen &screen = *_vm->_screen;
-
- _key = _oldKey = -1;
- _keyboardInput = (_keyPress != '\0');
-
- if (events._released || events._rightReleased || _keyboardInput) {
- // Is an inventory object being looked at?
- if (!_invLookFlag) {
- // Is there any remaining text to display?
- if (!_descStr.empty()) {
- printObjectDesc(_descStr, false);
- } else if (!_lookHelp) {
- // Need to close the window and depress the Look button
- Common::Point pt(MENU_POINTS[0][0], MENU_POINTS[0][1]);
- screen._backBuffer2.blitFrom((*_controls)[0], pt);
- banishWindow(true);
-
- _windowBounds.top = CONTROLS_Y1;
- _key = _oldKey = COMMANDS[LOOK_MODE - 1];
- _temp = _oldTemp = 0;
- _menuMode = LOOK_MODE;
- events.clearEvents();
-
- // Restore UI
- drawInterface();
- } else {
- events.setCursor(ARROW);
- banishWindow(true);
- _windowBounds.top = CONTROLS_Y1;
- _key = _oldKey = -1;
- _temp = _oldTemp = 0;
- _menuMode = STD_MODE;
- events.clearEvents();
- }
- } else {
- // Looking at an inventory object
- // Backup the user interface
- Surface tempSurface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y1);
- tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0),
- Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
-
- inv.drawInventory(INVENTORY_DONT_DISPLAY);
- banishWindow(true);
-
- // Restore the ui
- screen._backBuffer2.blitFrom(tempSurface, Common::Point(0, CONTROLS_Y1));
-
- _windowBounds.top = CONTROLS_Y1;
- _key = _oldKey = COMMANDS[LOOK_MODE - 1];
- _temp = _oldTemp = 0;
- events.clearEvents();
- _invLookFlag = false;
- _menuMode = INV_MODE;
- _windowOpen = true;
- }
- }
-}
-
-void ScalpelUserInterface::doMainControl() {
- Events &events = *_vm->_events;
- Inventory &inv = *_vm->_inventory;
- SaveManager &saves = *_vm->_saves;
- Common::Point pt = events.mousePos();
-
- if ((events._pressed || events._released) && pt.y > CONTROLS_Y) {
- events.clearKeyboard();
- _key = -1;
-
- // Check whether the mouse is in any of the command areas
- for (_temp = 0; (_temp < 12) && (_key == -1); ++_temp) {
- Common::Rect r(MENU_POINTS[_temp][0], MENU_POINTS[_temp][1],
- MENU_POINTS[_temp][2], MENU_POINTS[_temp][3]);
- if (r.contains(pt))
- _key = COMMANDS[_temp];
- }
- --_temp;
- } else if (_keyPress) {
- // Keyboard control
- _keyboardInput = true;
-
- if (_keyPress >= 'A' && _keyPress <= 'Z') {
- const char *c = strchr(COMMANDS, _keyPress);
- _temp = !c ? 12 : c - COMMANDS;
- } else {
- _temp = 12;
- }
-
- if (_temp == 12)
- _key = -1;
-
- if (events._rightPressed) {
- _temp = 12;
- _key = -1;
- }
- } else if (!events._released) {
- _key = -1;
- }
-
- // Check if the button being pointed to has changed
- if (_oldKey != _key && !_windowOpen) {
- // Clear the info line
- _infoFlag = true;
- clearInfo();
-
- // If there was an old button selected, restore it
- if (_oldKey != -1) {
- _menuMode = STD_MODE;
- restoreButton(_oldTemp);
- }
-
- // If a new button is being pointed to, highlight it
- if (_key != -1 && _temp < 12 && !_keyboardInput)
- depressButton(_temp);
-
- // Save the new button selection
- _oldKey = _key;
- _oldTemp = _temp;
- }
-
- if (!events._pressed && !_windowOpen) {
- switch (_key) {
- case 'L':
- toggleButton(0);
- break;
- case 'M':
- toggleButton(1);
- break;
- case 'T':
- toggleButton(2);
- break;
- case 'P':
- toggleButton(3);
- break;
- case 'O':
- toggleButton(4);
- break;
- case 'C':
- toggleButton(5);
- break;
- case 'I':
- pushButton(6);
- _selector = _oldSelector = -1;
- _menuMode = INV_MODE;
- inv.drawInventory(PLAIN_INVENTORY);
- break;
- case 'U':
- pushButton(7);
- _selector = _oldSelector = -1;
- _menuMode = USE_MODE;
- inv.drawInventory(USE_INVENTORY_MODE);
- break;
- case 'G':
- pushButton(8);
- _selector = _oldSelector = -1;
- _menuMode = GIVE_MODE;
- inv.drawInventory(GIVE_INVENTORY_MODE);
- break;
- case 'J':
- pushButton(9);
- _menuMode = JOURNAL_MODE;
- journalControl();
- break;
- case 'F':
- pushButton(10);
-
- // Create a thumbnail of the current screen before the files dialog is shown, in case
- // the user saves the game
- saves.createThumbnail();
-
- _selector = _oldSelector = -1;
-
- if (_vm->_showOriginalSavesDialog) {
- // Show the original dialog
- _menuMode = FILES_MODE;
- saves.drawInterface();
- _windowOpen = true;
- } else {
- // Show the ScummVM GMM instead
- _vm->_canLoadSave = true;
- _vm->openMainMenuDialog();
- _vm->_canLoadSave = false;
- }
- break;
- case 'S':
- pushButton(11);
- _menuMode = SETUP_MODE;
- Settings::show(_vm);
- break;
- default:
- break;
- }
-
- _help = _oldHelp = _oldBgFound = -1;
- }
-}
-
-void ScalpelUserInterface::doMiscControl(int allowed) {
- Events &events = *_vm->_events;
- Scene &scene = *_vm->_scene;
- Talk &talk = *_vm->_talk;
-
- if (events._released) {
- _temp = _bgFound;
- if (_bgFound != -1) {
- // Only allow pointing to objects, not people
- if (_bgFound < 1000) {
- events.clearEvents();
- Object &obj = scene._bgShapes[_bgFound];
-
- switch (allowed) {
- case ALLOW_OPEN:
- checkAction(obj._aOpen, MOPEN, _temp);
- if (_menuMode != TALK_MODE && !talk._talkToAbort) {
- _menuMode = STD_MODE;
- restoreButton(OPEN_MODE - 1);
- _key = _oldKey = -1;
- }
- break;
-
- case ALLOW_CLOSE:
- checkAction(obj._aClose, MCLOSE, _temp);
- if (_menuMode != TALK_MODE && !talk._talkToAbort) {
- _menuMode = STD_MODE;
- restoreButton(CLOSE_MODE - 1);
- _key = _oldKey = -1;
- }
- break;
-
- case ALLOW_MOVE:
- checkAction(obj._aMove, MMOVE, _temp);
- if (_menuMode != TALK_MODE && !talk._talkToAbort) {
- _menuMode = STD_MODE;
- restoreButton(MOVE_MODE - 1);
- _key = _oldKey = -1;
- }
- break;
-
- default:
- break;
- }
- }
- }
- }
-}
-
-void ScalpelUserInterface::doPickControl() {
- Events &events = *_vm->_events;
- Scene &scene = *_vm->_scene;
- Talk &talk = *_vm->_talk;
-
- if (events._released) {
- if ((_temp = _bgFound) != -1) {
- events.clearEvents();
-
- // Don't allow characters to be picked up
- if (_bgFound < 1000) {
- scene._bgShapes[_bgFound].pickUpObject(MPICK);
-
- if (!talk._talkToAbort && _menuMode != TALK_MODE) {
- _key = _oldKey = -1;
- _menuMode = STD_MODE;
- restoreButton(PICKUP_MODE - 1);
- }
- }
- }
- }
-}
-
-void ScalpelUserInterface::doTalkControl() {
- Events &events = *_vm->_events;
- Journal &journal = *_vm->_journal;
- People &people = *_vm->_people;
- Screen &screen = *_vm->_screen;
- Sound &sound = *_vm->_sound;
- Talk &talk = *_vm->_talk;
- Common::Point mousePos = events.mousePos();
-
- _key = _oldKey = -1;
- _keyboardInput = false;
-
- if (events._pressed || events._released) {
- events.clearKeyboard();
-
- // Handle button printing
- if (mousePos.x > 99 && mousePos.x < 138 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) && !_endKeyActive)
- screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Exit");
- else if (_endKeyActive)
- screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_FOREGROUND, true, "Exit");
-
- if (mousePos.x > 140 && mousePos.x < 170 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) && talk._moreTalkUp)
- screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Up");
- else if (talk._moreTalkUp)
- screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_FOREGROUND, true, "Up");
-
- if (mousePos.x > 181&& mousePos.x < 220 && mousePos.y > CONTROLS_Y && mousePos.y < (CONTROLS_Y + 10) && talk._moreTalkDown)
- screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Down");
- else if (talk._moreTalkDown)
- screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_FOREGROUND, true, "Down");
-
- bool found = false;
- for (_selector = talk._talkIndex; _selector < (int)talk._statements.size() && !found; ++_selector) {
- if (mousePos.y > talk._statements[_selector]._talkPos.top &&
- mousePos.y < talk._statements[_selector]._talkPos.bottom)
- found = true;
- }
- --_selector;
- if (!found)
- _selector = -1;
- }
-
- if (_keyPress) {
- _key = toupper(_keyPress);
- if (_key == Common::KEYCODE_ESCAPE)
- _key = 'E';
-
- // Check for number press indicating reply line
- if (_key >= '1' && _key <= ('1' + (int)talk._statements.size() - 1)) {
- for (uint idx = 0; idx < talk._statements.size(); ++idx) {
- if (talk._statements[idx]._talkMap == (_key - '1')) {
- // Found the given statement
- _selector = idx;
- _key = -1;
- _keyboardInput = true;
- break;
- }
- }
- } else if (_key == 'E' || _key == 'U' || _key == 'D') {
- _keyboardInput = true;
- } else {
- _selector = -1;
- }
- }
-
- if (_selector != _oldSelector) {
- // Remove highlighting from previous line, if any
- if (_oldSelector != -1) {
- if (!((talk._talkHistory[talk._converseNum][_oldSelector] >> (_oldSelector & 7)) & 1))
- talk.talkLine(_oldSelector, talk._statements[_oldSelector]._talkMap, INV_FOREGROUND,
- talk._statements[_oldSelector]._talkPos.top, true);
- else
- talk.talkLine(_oldSelector, talk._statements[_oldSelector]._talkMap, TALK_NULL,
- talk._statements[_oldSelector]._talkPos.top, true);
- }
-
- // Add highlighting to new line, if any
- if (_selector != -1)
- talk.talkLine(_selector, talk._statements[_selector]._talkMap, TALK_FOREGROUND,
- talk._statements[_selector]._talkPos.top, true);
-
- _oldSelector = _selector;
- }
-
- if (events._released || _keyboardInput) {
- if (((Common::Rect(99, CONTROLS_Y, 138, CONTROLS_Y + 10).contains(mousePos) && events._released)
- || _key == 'E') && _endKeyActive) {
- talk.freeTalkVars();
- talk.pullSequence();
- banishWindow();
- _windowBounds.top = CONTROLS_Y1;
- } else if (((Common::Rect(140, CONTROLS_Y, 179, CONTROLS_Y + 10).contains(mousePos) && events._released)
- || _key == 'U') && talk._moreTalkUp) {
- while (talk._statements[--talk._talkIndex]._talkMap == -1)
- ;
- screen._backBuffer1.fillRect(Common::Rect(5, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2,
- SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND);
- talk.displayTalk(false);
-
- screen.slamRect(Common::Rect(5, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH - 5, SHERLOCK_SCREEN_HEIGHT - 2));
- } else if (((Common::Rect(181, CONTROLS_Y, 220, CONTROLS_Y + 10).contains(mousePos) && events._released)
- || _key == 'D') && talk._moreTalkDown) {
- do {
- ++talk._talkIndex;
- } while (talk._talkIndex < (int)talk._statements.size() && talk._statements[talk._talkIndex]._talkMap == -1);
-
- screen._backBuffer1.fillRect(Common::Rect(5, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2,
- SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND);
- talk.displayTalk(false);
-
- screen.slamRect(Common::Rect(5, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH - 5, SHERLOCK_SCREEN_HEIGHT - 2));
- } else if (_selector != -1) {
- screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_NULL, true, "Exit");
- screen.buttonPrint(Common::Point(159, CONTROLS_Y), COMMAND_NULL, true, "Up");
- screen.buttonPrint(Common::Point(200, CONTROLS_Y), COMMAND_NULL, true, "Down");
-
- // If the reply is new, add it to the journal
- if (!talk._talkHistory[talk._converseNum][_selector]) {
- journal.record(talk._converseNum, _selector);
-
- // Add any Holmes point to Holmes' total, if any
- if (talk._statements[_selector]._quotient)
- people._holmesQuotient += talk._statements[_selector]._quotient;
- }
-
- // Flag the response as having been used
- talk._talkHistory[talk._converseNum][_selector] = true;
-
- clearWindow();
- screen.print(Common::Point(16, CONTROLS_Y + 12), TALK_FOREGROUND, "Sherlock Holmes");
- talk.talkLine(_selector + 128, talk._statements[_selector]._talkMap, COMMAND_FOREGROUND, CONTROLS_Y + 21, true);
-
- switch (talk._statements[_selector]._portraitSide & 3) {
- case 0:
- case 1:
- people._portraitSide = 20;
- break;
- case 2:
- people._portraitSide = 220;
- break;
- case 3:
- people._portraitSide = 120;
- break;
- }
-
- // Check for flipping Holmes
- if (talk._statements[_selector]._portraitSide & REVERSE_DIRECTION)
- people._holmesFlip = true;
-
- talk._speaker = 0;
- people.setTalking(0);
-
- if (!talk._statements[_selector]._voiceFile.empty() && sound._voices) {
- sound.playSound(talk._statements[_selector]._voiceFile, WAIT_RETURN_IMMEDIATELY);
-
- // Set voices as an indicator for waiting
- sound._voices = 2;
- sound._speechOn = *sound._soundIsOn;
- } else {
- sound._speechOn = false;
- }
-
- talk.waitForMore(talk._statements[_selector]._statement.size());
- if (talk._talkToAbort)
- return;
-
- people.clearTalking();
- if (talk._talkToAbort)
- return;
-
- while (!_vm->shouldQuit()) {
- talk._scriptSelect = _selector;
- talk._speaker = talk._talkTo;
- talk.doScript(talk._statements[_selector]._reply);
-
- if (!talk._talkToAbort) {
- if (!talk._talkStealth)
- clearWindow();
-
- if (!talk._statements[_selector]._modified.empty()) {
- for (uint idx = 0; idx < talk._statements[_selector]._modified.size(); ++idx) {
- _vm->setFlags(talk._statements[_selector]._modified[idx]);
- }
-
- talk.setTalkMap();
- }
-
- // Check for another linked talk file
- Common::String linkFilename = talk._statements[_selector]._linkFile;
- if (!linkFilename.empty() && !talk._scriptMoreFlag) {
- talk.freeTalkVars();
- talk.loadTalkFile(linkFilename);
-
- // Find the first new statement
- int select = _selector = _oldSelector = -1;
- for (uint idx = 0; idx < talk._statements.size() && select == -1; ++idx) {
- if (!talk._statements[idx]._talkMap)
- select = talk._talkIndex = idx;
- }
-
- // See if the new statement is a stealth reply
- talk._talkStealth = talk._statements[select]._statement.hasPrefix("^") ? 2 : 0;
-
- // Is the new talk file a standard file, reply first file, or a stealth file
- if (!talk._statements[select]._statement.hasPrefix("*") &&
- !talk._statements[select]._statement.hasPrefix("^")) {
- // Not a reply first file, so display the new selections
- if (_endKeyActive)
- screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_FOREGROUND, true, "Exit");
- else
- screen.buttonPrint(Common::Point(119, CONTROLS_Y), COMMAND_NULL, true, "Exit");
-
- talk.displayTalk(true);
- events.setCursor(ARROW);
- break;
- } else {
- _selector = select;
-
- if (!talk._talkHistory[talk._converseNum][_selector])
- journal.record(talk._converseNum, _selector);
-
- talk._talkHistory[talk._converseNum][_selector] = true;
- }
- } else {
- talk.freeTalkVars();
- talk.pullSequence();
- banishWindow();
- _windowBounds.top = CONTROLS_Y1;
- break;
- }
- } else {
- break;
- }
- }
-
- events._pressed = events._released = false;
- events._oldButtons = 0;
- talk._talkStealth = 0;
-
- // If a script was pushed onto the script stack, restore it
- if (!talk._scriptStack.empty()) {
- ScriptStackEntry stackEntry = talk._scriptStack.pop();
- talk._scriptName = stackEntry._name;
- talk._scriptSaveIndex = stackEntry._currentIndex;
- talk._scriptSelect = stackEntry._select;
- }
- }
- }
-}
-
-void ScalpelUserInterface::journalControl() {
- Events &events = *_vm->_events;
- Journal &journal = *_vm->_journal;
- Scene &scene = *_vm->_scene;
- Screen &screen = *_vm->_screen;
- bool doneFlag = false;
-
- // Draw the journal screen
- journal.drawInterface();
-
- // Handle journal events
- do {
- _key = -1;
- events.setButtonState();
-
- // Handle keypresses
- if (events.kbHit()) {
- Common::KeyState keyState = events.getKey();
- if (keyState.keycode == Common::KEYCODE_x && (keyState.flags & Common::KBD_ALT)) {
- _vm->quitGame();
- return;
- } else if (keyState.keycode == Common::KEYCODE_e || keyState.keycode == Common::KEYCODE_ESCAPE) {
- doneFlag = true;
- } else {
- _key = toupper(keyState.keycode);
- }
- }
-
- if (!doneFlag)
- doneFlag = journal.handleEvents(_key);
- } while (!_vm->shouldQuit() && !doneFlag);
-
- // Finish up
- _infoFlag = _keyboardInput = false;
- _keyPress = '\0';
- _windowOpen = false;
- _windowBounds.top = CONTROLS_Y1;
- _key = -1;
- _menuMode = STD_MODE;
-
- // Reset the palette
- screen.setPalette(screen._cMap);
-
- screen._backBuffer1.blitFrom(screen._backBuffer2);
- scene.updateBackground();
- screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
-}
-
-void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool firstTime) {
- Events &events = *_vm->_events;
- Inventory &inv = *_vm->_inventory;
- Screen &screen = *_vm->_screen;
- Talk &talk = *_vm->_talk;
-
- if (str.hasPrefix("_")) {
- _lookScriptFlag = true;
- events.setCursor(MAGNIFY);
- int savedSelector = _selector;
- talk.talkTo(str.c_str() + 1);
- _lookScriptFlag = false;
-
- if (talk._talkToAbort) {
- events.setCursor(ARROW);
- return;
- }
-
- // Check if looking at an inventory object
- if (!_invLookFlag) {
- // See if this look was called by a right button click or not
- if (!_lookHelp) {
- // If it wasn't a right button click, then we need depress
- // the look button before we close the window. So save a copy of the
- // menu area, and draw the controls onto it
- Surface tempSurface((*_controls)[0]._frame.w, (*_controls)[0]._frame.h);
- Common::Point pt(MENU_POINTS[0][0], MENU_POINTS[0][1]);
-
- tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0),
- Common::Rect(pt.x, pt.y, pt.x + tempSurface.w(), pt.y + tempSurface.h()));
- screen._backBuffer2.transBlitFrom((*_controls)[0], pt);
-
- banishWindow(1);
- events.setCursor(MAGNIFY);
- _windowBounds.top = CONTROLS_Y1;
- _key = _oldKey = COMMANDS[LOOK_MODE - 1];
- _temp = _oldTemp = 0;
- _menuMode = LOOK_MODE;
- events.clearEvents();
-
- screen._backBuffer2.blitFrom(tempSurface, pt);
- } else {
- events.setCursor(ARROW);
- banishWindow(true);
- _windowBounds.top = CONTROLS_Y1;
- _key = _oldKey = -1;
- _temp = _oldTemp = 0;
- _menuMode = STD_MODE;
- _lookHelp = 0;
- events.clearEvents();
- }
- } else {
- // Looking at an inventory object
- _selector = _oldSelector = savedSelector;
-
- // Reload the inventory graphics and draw the inventory
- inv.loadInv();
- inv.putInv(SLAM_SECONDARY_BUFFER);
- inv.freeInv();
- banishWindow(1);
-
- _windowBounds.top = CONTROLS_Y1;
- _key = _oldKey = COMMANDS[INV_MODE - 1];
- _temp = _oldTemp = 0;
- events.clearEvents();
-
- _invLookFlag = 0;
- _menuMode = INV_MODE;
- _windowOpen = true;
- }
-
- return;
- }
-
- Surface &bb = *screen._backBuffer;
- if (firstTime) {
- // Only draw the border on the first call
- _infoFlag = true;
- clearInfo();
-
- bb.fillRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH,
- CONTROLS_Y1 + 10), BORDER_COLOR);
- bb.fillRect(Common::Rect(0, CONTROLS_Y + 10, 1, SHERLOCK_SCREEN_HEIGHT - 1),
- BORDER_COLOR);
- bb.fillRect(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y + 10,
- SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR);
- bb.fillRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 1, SHERLOCK_SCREEN_WIDTH,
- SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR);
- }
-
- // Clear background
- bb.fillRect(Common::Rect(2, CONTROLS_Y + 10, SHERLOCK_SCREEN_WIDTH - 2,
- SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND);
-
- _windowBounds.top = CONTROLS_Y;
- events.clearEvents();
-
- // Loop through displaying up to five lines
- bool endOfStr = false;
- const char *msgP = str.c_str();
- for (int lineNum = 0; lineNum < ONSCREEN_FILES_COUNT && !endOfStr; ++lineNum) {
- int width = 0;
- const char *lineStartP = msgP;
-
- // Determine how much can be displayed on the line
- do {
- width += screen.charWidth(*msgP++);
- } while (width < 300 && *msgP);
-
- if (*msgP)
- --msgP;
- else
- endOfStr = true;
-
- // If the line needs to be wrapped, scan backwards to find
- // the end of the previous word as a splitting point
- if (width >= 300) {
- while (*msgP != ' ')
- --msgP;
- endOfStr = false;
- }
-
- // Print out the line
- Common::String line(lineStartP, msgP);
- screen.gPrint(Common::Point(16, CONTROLS_Y + 12 + lineNum * 9),
- INV_FOREGROUND, "%s", line.c_str());
-
- if (!endOfStr)
- // Start next line at start of the nxet word after space
- ++msgP;
- }
-
- // Handle display depending on whether all the message was shown
- if (!endOfStr) {
- screen.makeButton(Common::Rect(46, CONTROLS_Y, 272, CONTROLS_Y + 10),
- (SHERLOCK_SCREEN_WIDTH - screen.stringWidth(PRESS_KEY_FOR_MORE)) / 2,
- PRESS_KEY_FOR_MORE);
- screen.gPrint(Common::Point((SHERLOCK_SCREEN_WIDTH -
- screen.stringWidth(PRESS_KEY_FOR_MORE)) / 2, CONTROLS_Y),
- COMMAND_FOREGROUND, "P");
- _descStr = msgP;
- } else {
- screen.makeButton(Common::Rect(46, CONTROLS_Y, 272, CONTROLS_Y + 10),
- (SHERLOCK_SCREEN_WIDTH - screen.stringWidth(PRESS_KEY_TO_CONTINUE)) / 2,
- PRESS_KEY_TO_CONTINUE);
- screen.gPrint(Common::Point((SHERLOCK_SCREEN_WIDTH -
- screen.stringWidth(PRESS_KEY_TO_CONTINUE)) / 2, CONTROLS_Y),
- COMMAND_FOREGROUND, "P");
- _descStr = "";
- }
-
- if (firstTime) {
- if (!_slideWindows) {
- screen.slamRect(Common::Rect(0, CONTROLS_Y,
- SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
- } else {
- // Display the window
- summonWindow();
- }
-
- _selector = _oldSelector = -1;
- _windowOpen = true;
- } else {
- screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH,
- SHERLOCK_SCREEN_HEIGHT));
- }
-}
-
-void ScalpelUserInterface::printObjectDesc() {
- printObjectDesc(_cAnimStr, true);
-}
-
-void ScalpelUserInterface::summonWindow(const Surface &bgSurface, bool slideUp) {
- Events &events = *_vm->_events;
- Screen &screen = *_vm->_screen;
-
- if (_windowOpen)
- // A window is already open, so can't open another one
- return;
-
- if (slideUp) {
- // Gradually slide up the display of the window
- for (int idx = 1; idx <= bgSurface.h(); idx += 2) {
- screen._backBuffer->blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - idx),
- Common::Rect(0, 0, bgSurface.w(), idx));
- screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - idx,
- SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
-
- events.delay(10);
- }
- } else {
- // Gradually slide down the display of the window
- for (int idx = 1; idx <= bgSurface.h(); idx += 2) {
- screen._backBuffer->blitFrom(bgSurface,
- Common::Point(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h()),
- Common::Rect(0, bgSurface.h() - idx, bgSurface.w(), bgSurface.h()));
- screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h(),
- SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - bgSurface.h() + idx));
-
- events.delay(10);
- }
- }
-
- // Final display of the entire window
- screen._backBuffer->blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h()),
- Common::Rect(0, 0, bgSurface.w(), bgSurface.h()));
- screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h(), bgSurface.w(), bgSurface.h());
-
- _windowOpen = true;
-}
-
-void ScalpelUserInterface::summonWindow(bool slideUp, int height) {
- Screen &screen = *_vm->_screen;
-
- // Extract the window that's been drawn on the back buffer
- Surface tempSurface(SHERLOCK_SCREEN_WIDTH,
- (SHERLOCK_SCREEN_HEIGHT - height));
- Common::Rect r(0, height, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
- tempSurface.blitFrom(screen._backBuffer1, Common::Point(0, 0), r);
-
- // Remove drawn window with original user interface
- screen._backBuffer1.blitFrom(screen._backBuffer2,
- Common::Point(0, height), r);
-
- // Display the window gradually on-screen
- summonWindow(tempSurface, slideUp);
-}
-
-void ScalpelUserInterface::banishWindow(bool slideUp) {
- Events &events = *_vm->_events;
- Screen &screen = *_vm->_screen;
-
- if (_windowOpen) {
- if (slideUp || !_slideWindows) {
- // Slide window down
- // Only slide the window if the window style allows it
- if (_slideWindows) {
- for (int idx = 2; idx < (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y); idx += 2) {
- // Shift the window down by 2 lines
- byte *pSrc = (byte *)screen._backBuffer1.getBasePtr(0, CONTROLS_Y + idx - 2);
- byte *pSrcEnd = (byte *)screen._backBuffer1.getBasePtr(0, SHERLOCK_SCREEN_HEIGHT - 2);
- byte *pDest = (byte *)screen._backBuffer1.getBasePtr(0, SHERLOCK_SCREEN_HEIGHT);
- Common::copy_backward(pSrc, pSrcEnd, pDest);
-
- // Restore lines from the ui in the secondary back buffer
- screen._backBuffer1.blitFrom(screen._backBuffer2,
- Common::Point(0, CONTROLS_Y),
- Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y + idx));
-
- screen.slamArea(0, CONTROLS_Y + idx - 2, SHERLOCK_SCREEN_WIDTH,
- SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y - idx + 2);
- events.delay(10);
- }
-
- // Restore final two old lines
- screen._backBuffer1.blitFrom(screen._backBuffer2,
- Common::Point(0, SHERLOCK_SCREEN_HEIGHT - 2),
- Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 2,
- SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
- screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - 2, SHERLOCK_SCREEN_WIDTH, 2);
- } else {
- // Restore old area to completely erase window
- screen._backBuffer1.blitFrom(screen._backBuffer2,
- Common::Point(0, CONTROLS_Y),
- Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
- screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH,
- SHERLOCK_SCREEN_HEIGHT));
- }
- } else {
- // Slide the original user interface up to cover the dialog
- for (int idx = 1; idx < (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y1); idx += 2) {
- byte *pSrc = (byte *)screen._backBuffer2.getBasePtr(0, CONTROLS_Y1);
- byte *pSrcEnd = (byte *)screen._backBuffer2.getBasePtr(0, CONTROLS_Y1 + idx);
- byte *pDest = (byte *)screen._backBuffer1.getBasePtr(0, SHERLOCK_SCREEN_HEIGHT - idx);
- Common::copy(pSrc, pSrcEnd, pDest);
-
- screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - idx, SHERLOCK_SCREEN_WIDTH,
- SHERLOCK_SCREEN_HEIGHT);
- events.delay(10);
- }
-
- // Show entire final area
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(0, CONTROLS_Y1),
- Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
- screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
- }
-
- _infoFlag = false;
- _windowOpen = false;
- }
-
- _menuMode = STD_MODE;
-}
-
-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;
- Scene &scene = *_vm->_scene;
- Screen &screen = *_vm->_screen;
- Talk &talk = *_vm->_talk;
- bool printed = messages == nullptr;
-
- if (objNum >= 1000) {
- // Holmes was specified, so do nothing
- _infoFlag = true;
- clearInfo();
- _infoFlag = true;
-
- // Display error message
- _menuCounter = 30;
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "You can't do that to yourself.");
- return;
- }
-
- // Scan for target item
- int targetNum = -1;
- if (giveMode) {
- for (int idx = 0; idx < USE_COUNT && targetNum == -1; ++idx) {
- if ((use[idx]._target.equalsIgnoreCase("*GIVE*") || use[idx]._target.equalsIgnoreCase("*GIVEP*"))
- && use[idx]._names[0].equalsIgnoreCase(invName)) {
- // Found a match
- targetNum = idx;
- if (use[idx]._target.equalsIgnoreCase("*GIVE*"))
- inv.deleteItemFromInventory(invName);
- }
- }
- } else {
- for (int idx = 0; idx < USE_COUNT && targetNum == -1; ++idx) {
- if (use[idx]._target.equalsIgnoreCase(invName))
- targetNum = idx;
- }
- }
-
- if (targetNum != -1) {
- // Found a target, so do the action
- const UseType &action = use[targetNum];
-
- events.setCursor(WAIT);
-
- if (action._useFlag)
- _vm->setFlags(action._useFlag);
-
- if (action._cAnimNum != 99) {
- if (action._cAnimNum == 0)
- scene.startCAnim(9, action._cAnimSpeed);
- else
- scene.startCAnim(action._cAnimNum - 1, action._cAnimSpeed);
- }
-
- if (!talk._talkToAbort) {
- Object &obj = scene._bgShapes[objNum];
- for (int idx = 0; idx < NAMES_COUNT && !talk._talkToAbort; ++idx) {
- if (obj.checkNameForCodes(action._names[idx], messages)) {
- if (!talk._talkToAbort)
- printed = true;
- }
- }
-
- // Print "Done..." as an ending, unless flagged for leaving scene or otherwise flagged
- if (scene._goToScene != 1 && !printed && !talk._talkToAbort) {
- _infoFlag = true;
- clearInfo();
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "Done...");
- _menuCounter = 25;
- }
- }
- } else {
- // Couldn't find target, so print error
- _infoFlag = true;
- clearInfo();
-
- if (giveMode) {
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "No, thank you.");
- } else if (messages == nullptr) {
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "You can't do that.");
- } else {
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", messages[0]);
- }
-
- _infoFlag = true;
- _menuCounter = 30;
- }
-
- events.setCursor(ARROW);
-}
-
-void ScalpelUserInterface::checkAction(ActionType &action, const char *const messages[], int objNum) {
- Events &events = *_vm->_events;
- People &people = *_vm->_people;
- Scene &scene = *_vm->_scene;
- Screen &screen = *_vm->_screen;
- Talk &talk = *_vm->_talk;
- Common::Point pt(-1, -1);
-
- if (objNum >= 1000)
- // Ignore actions done on characters
- return;
-
- if (!action._cAnimSpeed) {
- // Invalid action, to print error message
- _infoFlag = true;
- clearInfo();
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", messages[action._cAnimNum]);
- _infoFlag = true;
-
- // Set how long to show the message
- _menuCounter = 30;
- } else {
- Object &obj = scene._bgShapes[objNum];
-
- int cAnimNum;
- if (action._cAnimNum == 0)
- // Really a 10
- cAnimNum = 9;
- else
- cAnimNum = action._cAnimNum - 1;
-
- int dir = -1;
- if (action._cAnimNum != 99) {
- CAnim &anim = scene._cAnim[cAnimNum];
-
- if (action._cAnimNum != 99) {
- if (action._cAnimSpeed & REVERSE_DIRECTION) {
- pt = anim._teleportPos;
- dir = anim._teleportDir;
- } else {
- pt = anim._goto;
- dir = anim._gotoDir;
- }
- }
- } else {
- pt = Common::Point(-1, -1);
- dir = -1;
- }
-
- // Has a value, so do action
- // Show wait cursor whilst walking to object and doing action
- events.setCursor(WAIT);
- bool printed = false;
-
- for (int nameIdx = 0; nameIdx < NAMES_COUNT; ++nameIdx) {
- if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2
- && toupper(action._names[nameIdx][1]) == 'W') {
- if (obj.checkNameForCodes(Common::String(action._names[nameIdx].c_str() + 2), messages)) {
- if (!talk._talkToAbort)
- printed = true;
- }
- }
- }
-
- bool doCAnim = true;
- for (int nameIdx = 0; nameIdx < NAMES_COUNT; ++nameIdx) {
- if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2) {
- char ch = toupper(action._names[nameIdx][1]);
-
- if (ch == 'T' || ch == 'B') {
- printed = true;
- if (pt.x != -1)
- // Holmes needs to walk to object before the action is done
- people.walkToCoords(pt, dir);
-
- if (!talk._talkToAbort) {
- // Ensure Holmes is on the exact intended location
- people[AL]._position = pt;
- people[AL]._sequenceNumber = dir;
- people.gotoStand(people[AL]);
-
- talk.talkTo(action._names[nameIdx].c_str() + 2);
- if (ch == 'T')
- doCAnim = false;
- }
- }
- }
- }
-
- if (doCAnim && !talk._talkToAbort) {
- if (pt.x != -1)
- // Holmes needs to walk to object before the action is done
- people.walkToCoords(pt, dir);
- }
-
- for (int nameIdx = 0; nameIdx < NAMES_COUNT; ++nameIdx) {
- if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2
- && toupper(action._names[nameIdx][1]) == 'F') {
- if (obj.checkNameForCodes(action._names[nameIdx].c_str() + 2, messages)) {
- if (!talk._talkToAbort)
- printed = true;
- }
- }
- }
-
- if (doCAnim && !talk._talkToAbort && action._cAnimNum != 99)
- scene.startCAnim(cAnimNum, action._cAnimSpeed);
-
- if (!talk._talkToAbort) {
- for (int nameIdx = 0; nameIdx < NAMES_COUNT && !talk._talkToAbort; ++nameIdx) {
- if (obj.checkNameForCodes(action._names[nameIdx], messages)) {
- if (!talk._talkToAbort)
- printed = true;
- }
- }
-
- // Unless we're leaving the scene, print a "Done" message unless the printed flag has been set
- if (scene._goToScene != 1 && !printed && !talk._talkToAbort) {
- _infoFlag = true;
- clearInfo();
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "Done...");
-
- // Set how long to show the message
- _menuCounter = 30;
- }
- }
- }
-
- // Reset cursor back to arrow
- events.setCursor(ARROW);
-}
-
-}
-
-/*----------------------------------------------------------------*/
-
-namespace Tattoo {
-
-TattooUserInterface::TattooUserInterface(SherlockEngine *vm): UserInterface(vm) {
- _menuBuffer = nullptr;
- _invMenuBuffer = nullptr;
-}
-
-void TattooUserInterface::handleInput() {
- // TODO
- _vm->_events->pollEventsAndWait();
-}
-
-void TattooUserInterface::doBgAnimRestoreUI() {
- TattooScene &scene = *((TattooScene *)_vm->_scene);
- Screen &screen = *_vm->_screen;
-
- // If _oldMenuBounds was set, then either a new menu has been opened or the current menu has been closed.
- // Either way, we need to restore the area where the menu was displayed
- if (_oldMenuBounds.width() > 0)
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldMenuBounds.left, _oldMenuBounds.top),
- _oldMenuBounds);
-
- if (_oldInvMenuBounds.width() > 0)
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldInvMenuBounds.left, _oldInvMenuBounds.top),
- _oldInvMenuBounds);
-
- if (_menuBuffer != nullptr)
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_menuBounds.left, _menuBounds.top), _menuBounds);
- if (_invMenuBuffer != nullptr)
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_invMenuBounds.left, _invMenuBounds.top), _invMenuBounds);
-
- // If there is a Text Tag being display, restore the area underneath it
- if (_oldTagBounds.width() > 0)
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldTagBounds.left, _oldTagBounds.top),
- _oldTagBounds);
-
- // If there is an Inventory being shown, restore the graphics underneath it
- if (_oldInvGraphicBounds.width() > 0)
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldInvGraphicBounds.left, _oldInvGraphicBounds.top),
- _oldInvGraphicBounds);
-
- // If a canimation is active, restore the graphics underneath it
- if (scene._activeCAnim._images != nullptr)
- screen.restoreBackground(scene._activeCAnim._oldBounds);
-
- // If a canimation just ended, remove it's graphics from the backbuffer
- if (scene._activeCAnim._removeBounds.width() > 0)
- screen.restoreBackground(scene._activeCAnim._removeBounds);
-}
-
-void TattooUserInterface::doScroll() {
- Screen &screen = *_vm->_screen;
- int oldScroll = screen._currentScroll;
-
- // If we're already at the target scroll position, nothing needs to be done
- if (screen._targetScroll == screen._currentScroll)
- return;
-
- screen._flushScreen = true;
- if (screen._targetScroll > screen._currentScroll) {
- screen._currentScroll += screen._scrollSpeed;
- if (screen._currentScroll > screen._targetScroll)
- screen._currentScroll = screen._targetScroll;
- } else if (screen._targetScroll < screen._currentScroll) {
- screen._currentScroll -= screen._scrollSpeed;
- if (screen._currentScroll < screen._targetScroll)
- screen._currentScroll = screen._targetScroll;
- }
-
- if (_menuBuffer != nullptr)
- _menuBounds.translate(screen._currentScroll - oldScroll, 0);
- if (_invMenuBuffer != nullptr)
- _invMenuBounds.translate(screen._currentScroll - oldScroll, 0);
-}
-
-} // End of namespace Tattoo
-
} // End of namespace Sherlock
diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h
index dfd6d02..042997a 100644
--- a/engines/sherlock/user_interface.h
+++ b/engines/sherlock/user_interface.h
@@ -50,18 +50,6 @@ enum MenuMode {
SETUP_MODE = 12
};
-extern const char COMMANDS[13];
-extern const int MENU_POINTS[12][4];
-
-extern const int INVENTORY_POINTS[8][3];
-extern const char INVENTORY_COMMANDS[9];
-extern const char *const PRESS_KEY_FOR_MORE;
-extern const char *const PRESS_KEY_TO_CONTINUE;
-
-class SherlockEngine;
-class Inventory;
-class Talk;
-
class UserInterface {
protected:
SherlockEngine *_vm;
@@ -137,222 +125,6 @@ public:
virtual void printObjectDesc() {}
};
-namespace Scalpel {
-
-class ScalpelUserInterface: public UserInterface {
- friend class Inventory;
- friend class Settings;
- friend class Talk;
-private:
- ImageFile *_controlPanel;
- ImageFile *_controls;
- char _keyPress;
- int _lookHelp;
- int _bgFound, _oldBgFound;
- int _help, _oldHelp;
- char _key, _oldKey;
- int _temp, _oldTemp;
- int _oldLook;
- bool _keyboardInput;
- bool _pause;
- int _cNum;
- Common::String _cAnimStr;
- Common::String _descStr;
- int _find;
- int _oldUse;
-private:
- /**
- * Draws the image for a user interface button in the down/pressed state.
- */
- void depressButton(int num);
-
- /**
- * If he mouse button is pressed, then calls depressButton to draw the button
- * as pressed; if not, it will show it as released with a call to "restoreButton".
- */
- void pushButton(int num);
-
- /**
- * By the time this method has been called, the graphics for the button change
- * have already been drawn. This simply takes care of switching the mode around
- * accordingly
- */
- void toggleButton(int num);
-
- /**
- * Creates a text window and uses it to display the in-depth description
- * of the highlighted object
- */
- void examine();
-
- /**
- * Print the name of an object in the scene
- */
- void lookScreen(const Common::Point &pt);
-
- /**
- * Gets the item in the inventory the mouse is on and display's it's description
- */
- void lookInv();
-
- /**
- * Handles input when the file list window is being displayed
- */
- void doEnvControl();
-
- /**
- * Handle input whilst the inventory is active
- */
- void doInvControl();
-
- /**
- * Handles waiting whilst an object's description window is open.
- */
- void doLookControl();
-
- /**
- * Handles input until one of the user interface buttons/commands is selected
- */
- void doMainControl();
-
- /**
- * Handles the input for the MOVE, OPEN, and CLOSE commands
- */
- void doMiscControl(int allowed);
-
- /**
- * Handles input for picking up items
- */
- void doPickControl();
-
- /**
- * Handles input when in talk mode. It highlights the buttons and available statements,
- * and handles allowing the user to click on them
- */
- void doTalkControl();
-
- /**
- * Handles events when the Journal is active.
- * @remarks Whilst this would in theory be better in the Journal class, since it displays in
- * the user interface, it uses so many internal UI fields, that it sort of made some sense
- * to put it in the UserInterface class.
- */
- void journalControl();
-
- /**
- * Checks to see whether a USE action is valid on the given object
- */
- void checkUseAction(const UseType *use, const Common::String &invName, const char *const messages[],
- int objNum, bool giveMode);
-
- /**
- * Called for OPEN, CLOSE, and MOVE actions are being done
- */
- void checkAction(ActionType &action, const char *const messages[], int objNum);
-
- /**
- * Print the previously selected object's decription
- */
- void printObjectDesc(const Common::String &str, bool firstTime);
-public:
- ScalpelUserInterface(SherlockEngine *vm);
- virtual ~ScalpelUserInterface();
-
- /**
- * Handles counting down whilst checking for input, then clears the info line.
- */
- void whileMenuCounter();
-
- /**
- * Draws the image for the given user interface button in the up
- * (not selected) position
- */
- void restoreButton(int num);
-public:
- /**
- * Resets the user interface
- */
- virtual void reset();
-
- /**
- * Main input handler for the user interface
- */
- virtual void handleInput();
-
- /**
- * Draw the user interface onto the screen's back buffers
- */
- virtual void drawInterface(int bufferNum = 3);
-
- /**
- * 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();
-};
-
-} // End of namespace Scalpel
-
-namespace Tattoo {
-
-class TattooUserInterface : public UserInterface {
-private:
- Common::Rect _menuBounds;
- Common::Rect _oldMenuBounds;
- Common::Rect _invMenuBounds;
- Common::Rect _oldInvMenuBounds;
- Common::Rect _oldTagBounds;
- Common::Rect _oldInvGraphicBounds;
- Surface *_menuBuffer;
- Surface *_invMenuBuffer;
-public:
- TattooUserInterface(SherlockEngine *vm);
-
- /**
- * Handles restoring any areas of the back buffer that were/are covered by UI elements
- */
- void doBgAnimRestoreUI();
-
- /**
- * Checks to see if the screen needs to be scrolled. If so, scrolls it towards the target position
- */
- void doScroll();
-public:
- virtual ~TattooUserInterface() {}
-
- /**
- * Main input handler for the user interface
- */
- virtual void handleInput();
-};
-
-} // End of namespace Tattoo
-
} // End of namespace Sherlock
#endif
Commit: 88d245814314b9e452d02ce8ce8e2aa89bc3ecea
https://github.com/scummvm/scummvm/commit/88d245814314b9e452d02ce8ce8e2aa89bc3ecea
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-28T19:59:03-04:00
Commit Message:
SHERLOCK: Implement additions to updateBackground, some method stubs
Changed paths:
engines/sherlock/people.cpp
engines/sherlock/people.h
engines/sherlock/resources.cpp
engines/sherlock/resources.h
engines/sherlock/scene.h
engines/sherlock/screen.cpp
engines/sherlock/screen.h
engines/sherlock/surface.cpp
engines/sherlock/surface.h
engines/sherlock/tattoo/tattoo_scene.cpp
engines/sherlock/tattoo/tattoo_scene.h
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp
index f8dd8e2..0ef49ff 100644
--- a/engines/sherlock/people.cpp
+++ b/engines/sherlock/people.cpp
@@ -70,6 +70,7 @@ const char *const WALK_LIB_NAMES[10] = {
Person::Person() : Sprite(), _walkLoaded(false), _npcIndex(0), _npcStack(0), _npcPause(false) {
Common::fill(&_npcPath[0], &_npcPath[MAX_NPC_PATH], 0);
+ _tempX = _tempScaleVal = 0;
}
void Person::clearNPC() {
diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h
index f4aba5a..013727d 100644
--- a/engines/sherlock/people.h
+++ b/engines/sherlock/people.h
@@ -74,6 +74,8 @@ public:
bool _npcPause;
byte _npcPath[MAX_NPC_PATH];
Common::String _npcName;
+ int _tempX;
+ int _tempScaleVal;
// Rose Tattoo fields
Common::String _walkVGSName; // Name of walk library person is using
diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp
index 4e10ba9..961286f 100644
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@ -466,4 +466,14 @@ void ImageFile::decompressFrame(ImageFrame &frame, const byte *src) {
}
}
+/*----------------------------------------------------------------*/
+
+int ImageFrame::sDrawXSize(int scaleVal) const {
+ error("TODO: sDrawXSize");
+}
+
+int ImageFrame::sDrawYSize(int scaleVal) const {
+ error("TODO: sDrawYSize");
+}
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h
index 659ecf0..c5b76ac 100644
--- a/engines/sherlock/resources.h
+++ b/engines/sherlock/resources.h
@@ -173,6 +173,10 @@ struct ImageFrame {
Common::Point _offset;
byte _rleMarker;
Graphics::Surface _frame;
+
+ int sDrawXSize(int scaleVal) const;
+
+ int sDrawYSize(int scaleVal) const;
};
class ImageFile : public Common::Array<ImageFrame> {
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index b5e27ff..624e4d3 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -273,11 +273,6 @@ public:
int toggleObject(const Common::String &name);
/**
- * Draw all objects and characters.
- */
- virtual void doBgAnim() = 0;
-
- /**
* Attempts to find a background shape within the passed bounds. If found,
* it will return the shape number, or -1 on failure.
*/
@@ -300,12 +295,6 @@ public:
int closestZone(const Common::Point &pt);
/**
- * Update the screen back buffer with all of the scene objects which need
- * to be drawn
- */
- void updateBackground();
-
- /**
* Synchronize the data for a savegame
*/
void synchronize(Common::Serializer &s);
@@ -316,6 +305,17 @@ public:
* the scene number being entered
*/
void setNPCPath(int npc);
+public:
+ /**
+ * Draw all objects and characters.
+ */
+ virtual void doBgAnim() = 0;
+
+ /**
+ * Update the screen back buffer with all of the scene objects which need
+ * to be drawn
+ */
+ virtual void updateBackground();
};
} // End of namespace Sherlock
diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp
index 350341f..e826a10 100644
--- a/engines/sherlock/screen.cpp
+++ b/engines/sherlock/screen.cpp
@@ -253,24 +253,26 @@ void Screen::slamRect(const Common::Rect &r) {
}
}
-void Screen::flushImage(ImageFrame *frame, const Common::Point &pt,
- int16 *xp, int16 *yp, int16 *width, int16 *height) {
+void Screen::flushImage(ImageFrame *frame, const Common::Point &pt, int16 *xp, int16 *yp,
+ int16 *width, int16 *height) {
Common::Point imgPos = pt + frame->_offset;
Common::Rect newBounds(imgPos.x, imgPos.y, imgPos.x + frame->_frame.w, imgPos.y + frame->_frame.h);
Common::Rect oldBounds(*xp, *yp, *xp + *width, *yp + *height);
- // See if the areas of the old and new overlap, and if so combine the areas
- if (newBounds.intersects(oldBounds)) {
- Common::Rect mergedBounds = newBounds;
- mergedBounds.extend(oldBounds);
- mergedBounds.right += 1;
- mergedBounds.bottom += 1;
+ if (!_flushScreen) {
+ // See if the areas of the old and new overlap, and if so combine the areas
+ if (newBounds.intersects(oldBounds)) {
+ Common::Rect mergedBounds = newBounds;
+ mergedBounds.extend(oldBounds);
+ mergedBounds.right += 1;
+ mergedBounds.bottom += 1;
- slamRect(mergedBounds);
- } else {
- // The two areas are independent, so copy them both
- slamRect(newBounds);
- slamRect(oldBounds);
+ slamRect(mergedBounds);
+ } else {
+ // The two areas are independent, so copy them both
+ slamRect(newBounds);
+ slamRect(oldBounds);
+ }
}
*xp = newBounds.left;
@@ -279,6 +281,11 @@ void Screen::flushImage(ImageFrame *frame, const Common::Point &pt,
*height = newBounds.height();
}
+void Screen::flushScaleImage(ImageFrame *frame, const Common::Point &pt, int16 *xp, int16 *yp,
+ int16 *width, int16 *height, int scaleVal) {
+ error("TODO");
+}
+
void Screen::print(const Common::Point &pt, byte color, const char *formatStr, ...) {
// Create the string to display
va_list args;
diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h
index ae368cf..949f9de 100644
--- a/engines/sherlock/screen.h
+++ b/engines/sherlock/screen.h
@@ -184,6 +184,9 @@ public:
void flushImage(ImageFrame *frame, const Common::Point &pt,
int16 *xp, int16 *yp, int16 *width, int16 *height);
+ void flushScaleImage(ImageFrame *frame, const Common::Point &pt,
+ int16 *xp, int16 *yp, int16 *width, int16 *height, int scaleVal);
+
/**
* Returns the width of a string in pixels
*/
diff --git a/engines/sherlock/surface.cpp b/engines/sherlock/surface.cpp
index 80495a3..6cf479c 100644
--- a/engines/sherlock/surface.cpp
+++ b/engines/sherlock/surface.cpp
@@ -186,4 +186,10 @@ void Surface::setPixels(byte *pixels, int width, int height) {
_surface.setPixels(pixels);
}
+void Surface::maskArea(const ImageFrame &src, const Common::Point &pt, int scrollX) {
+ // TODO
+ error("TODO: maskArea");
+}
+
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/surface.h b/engines/sherlock/surface.h
index ccabf02..663f87f 100644
--- a/engines/sherlock/surface.h
+++ b/engines/sherlock/surface.h
@@ -126,6 +126,8 @@ public:
*/
void fillRect(const Common::Rect &r, byte color);
+ void maskArea(const ImageFrame &src, const Common::Point &pt, int scrollX);
+
/**
* Clear the screen
*/
diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp
index f03e791..1effd60 100644
--- a/engines/sherlock/tattoo/tattoo_scene.cpp
+++ b/engines/sherlock/tattoo/tattoo_scene.cpp
@@ -222,6 +222,114 @@ void TattooScene::doBgAnim() {
doBgAnimEraseBackground();
}
+void TattooScene::updateBackground() {
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
+
+ Scene::updateBackground();
+
+ if (_mask != nullptr) {
+ switch (_currentScene) {
+ case 7:
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 110), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 110), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x + SHERLOCK_SCREEN_WIDTH, 110), screen._currentScroll);
+ break;
+
+ case 8:
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 180), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 180), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x + SHERLOCK_SCREEN_WIDTH, 180), screen._currentScroll);
+ if (!_vm->readFlags(880))
+ screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(940, 300), screen._currentScroll);
+ break;
+
+ case 18:
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(0, 203), screen._currentScroll);
+ if (!_vm->readFlags(189))
+ screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(124, 239), screen._currentScroll);
+ break;
+
+ case 53:
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 110), screen._currentScroll);
+ break;
+
+ case 68:
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(0, 203), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(124, 239), screen._currentScroll);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ screen._flushScreen = true;
+
+ for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
+ Person &p = people[idx];
+
+ if (p._type != INVALID) {
+ if (_goToScene == -1 || _cAnim.size() == 0) {
+ if (p._type == REMOVE) {
+ screen.slamArea(p._oldPosition.x, p._oldPosition.y, p._oldSize.x, p._oldSize.y);
+ p._type = INVALID;
+ } else {
+ if (p._tempScaleVal == 256) {
+ screen.flushImage(p._imageFrame, Common::Point(p._tempX, p._position.y / FIXED_INT_MULTIPLIER
+ - p._imageFrame->_width), &p._oldPosition.x, &p._oldPosition.y, &p._oldSize.x, &p._oldSize.y);
+ } else {
+ int ts = p._imageFrame->sDrawYSize(p._tempScaleVal);
+ int ty = p._position.y / FIXED_INT_MULTIPLIER - ts;
+ screen.flushScaleImage(p._imageFrame, Common::Point(p._tempX, ty),
+ &p._oldPosition.x, &p._oldPosition.y, &p._oldSize.x, &p._oldSize.y, p._tempScaleVal);
+ }
+ }
+ }
+ }
+ }
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &obj = _bgShapes[idx];
+
+ if (obj._type == ACTIVE_BG_SHAPE || obj._type == REMOVE) {
+ if (_goToScene == -1) {
+ if (obj._scaleVal == 256)
+ screen.flushImage(obj._imageFrame, obj._position, &obj._oldPosition.x, &obj._oldPosition.y,
+ &obj._oldSize.x, &obj._oldSize.y);
+ else
+ screen.flushScaleImage(obj._imageFrame, obj._position, &obj._oldPosition.x, &obj._oldPosition.y,
+ &obj._oldSize.x, &obj._oldSize.y, obj._scaleVal);
+
+ if (obj._type == REMOVE)
+ obj._type = INVALID;
+ }
+ }
+ }
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &obj = _bgShapes[idx];
+
+ if (_goToScene == -1) {
+ if (obj._type == NO_SHAPE && (obj._flags & 1) == 0) {
+ screen.slamRect(obj.getNoShapeBounds());
+ screen.slamRect(obj.getOldBounds());
+ } else if (obj._type == HIDE_SHAPE) {
+ if (obj._scaleVal == 256)
+ screen.flushImage(obj._imageFrame, obj._position, &obj._oldPosition.x, &obj._oldPosition.y,
+ &obj._oldSize.x, &obj._oldSize.y);
+ else
+ screen.flushScaleImage(obj._imageFrame, obj._position, &obj._oldPosition.x, &obj._oldPosition.y,
+ &obj._oldSize.x, &obj._oldSize.y, obj._scaleVal);
+ obj._type = HIDDEN;
+ }
+ }
+ }
+
+ screen._flushScreen = false;
+}
+
+
} // End of namespace Tattoo
} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_scene.h b/engines/sherlock/tattoo/tattoo_scene.h
index 34e87f4..5e26eaa 100644
--- a/engines/sherlock/tattoo/tattoo_scene.h
+++ b/engines/sherlock/tattoo/tattoo_scene.h
@@ -56,6 +56,13 @@ public:
* Draw all objects and characters.
*/
virtual void doBgAnim();
+
+ /**
+ * Update the screen back buffer with all of the scene objects which need
+ * to be drawn
+ */
+ virtual void updateBackground();
+
};
} // End of namespace Tattoo
Commit: a6607ff2d60e7951594a6a2ad8fd319fb776e35b
https://github.com/scummvm/scummvm/commit/a6607ff2d60e7951594a6a2ad8fd319fb776e35b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-28T21:47:52-04:00
Commit Message:
SHERLOCK: Implemented flushScaleImage and scale calculations
Changed paths:
engines/sherlock/resources.cpp
engines/sherlock/resources.h
engines/sherlock/screen.cpp
engines/sherlock/screen.h
diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp
index 961286f..f1c705b 100644
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@ -469,11 +469,31 @@ void ImageFile::decompressFrame(ImageFrame &frame, const byte *src) {
/*----------------------------------------------------------------*/
int ImageFrame::sDrawXSize(int scaleVal) const {
- error("TODO: sDrawXSize");
+ int width = _width;
+ int scale = scaleVal == 0 ? 1 : scaleVal;
+
+ if (scaleVal >= 256)
+ --width;
+
+ int result = width * 256 / scale;
+ if (scaleVal >= 256)
+ ++result;
+
+ return result;
}
int ImageFrame::sDrawYSize(int scaleVal) const {
- error("TODO: sDrawYSize");
+ int height = _height;
+ int scale = scaleVal == 0 ? 1 : scaleVal;
+
+ if (scaleVal >= 256)
+ --height;
+
+ int result = height * 256 / scale;
+ if (scaleVal >= 256)
+ ++result;
+
+ return result;
}
} // End of namespace Sherlock
diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h
index c5b76ac..5c071e3 100644
--- a/engines/sherlock/resources.h
+++ b/engines/sherlock/resources.h
@@ -174,8 +174,14 @@ struct ImageFrame {
byte _rleMarker;
Graphics::Surface _frame;
+ /**
+ * Return the frame width adjusted by a specified scale amount
+ */
int sDrawXSize(int scaleVal) const;
+ /**
+ * Return the frame height adjusted by a specified scale amount
+ */
int sDrawYSize(int scaleVal) const;
};
diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp
index e826a10..a3af555 100644
--- a/engines/sherlock/screen.cpp
+++ b/engines/sherlock/screen.cpp
@@ -283,7 +283,31 @@ void Screen::flushImage(ImageFrame *frame, const Common::Point &pt, int16 *xp, i
void Screen::flushScaleImage(ImageFrame *frame, const Common::Point &pt, int16 *xp, int16 *yp,
int16 *width, int16 *height, int scaleVal) {
- error("TODO");
+ Common::Point imgPos = pt + frame->_offset;
+ Common::Rect newBounds(imgPos.x, imgPos.y, imgPos.x + frame->sDrawXSize(scaleVal),
+ imgPos.y + frame->sDrawYSize(scaleVal));
+ Common::Rect oldBounds(*xp, *yp, *xp + *width, *yp + *height);
+
+ if (!_flushScreen) {
+ // See if the areas of the old and new overlap, and if so combine the areas
+ if (newBounds.intersects(oldBounds)) {
+ Common::Rect mergedBounds = newBounds;
+ mergedBounds.extend(oldBounds);
+ mergedBounds.right += 1;
+ mergedBounds.bottom += 1;
+
+ slamRect(mergedBounds);
+ } else {
+ // The two areas are independent, so copy them both
+ slamRect(newBounds);
+ slamRect(oldBounds);
+ }
+ }
+
+ *xp = newBounds.left;
+ *yp = newBounds.top;
+ *width = newBounds.width();
+ *height = newBounds.height();
}
void Screen::print(const Common::Point &pt, byte color, const char *formatStr, ...) {
diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h
index 949f9de..8fda9cb 100644
--- a/engines/sherlock/screen.h
+++ b/engines/sherlock/screen.h
@@ -181,11 +181,15 @@ public:
* Copy an image from the back buffer to the screen, taking care of both the
* new area covered by the shape as well as the old area, which must be restored
*/
- void flushImage(ImageFrame *frame, const Common::Point &pt,
- int16 *xp, int16 *yp, int16 *width, int16 *height);
+ void flushImage(ImageFrame *frame, const Common::Point &pt, int16 *xp, int16 *yp,
+ int16 *width, int16 *height);
- void flushScaleImage(ImageFrame *frame, const Common::Point &pt,
- int16 *xp, int16 *yp, int16 *width, int16 *height, int scaleVal);
+ /**
+ * Similar to flushImage, this method takes in an extra parameter for the scale proporation,
+ * which affects the calculated bounds accordingly
+ */
+ void flushScaleImage(ImageFrame *frame, const Common::Point &pt, int16 *xp, int16 *yp,
+ int16 *width, int16 *height, int scaleVal);
/**
* Returns the width of a string in pixels
Commit: 895189e3ffd1931ca01991731f98bbf74796e05d
https://github.com/scummvm/scummvm/commit/895189e3ffd1931ca01991731f98bbf74796e05d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-29T22:56:34-04:00
Commit Message:
SHERLOCK: More RT doBgAnim code, interface draw
Changed paths:
engines/sherlock/objects.cpp
engines/sherlock/objects.h
engines/sherlock/scene.h
engines/sherlock/surface.cpp
engines/sherlock/tattoo/tattoo.cpp
engines/sherlock/tattoo/tattoo.h
engines/sherlock/tattoo/tattoo_scene.cpp
engines/sherlock/tattoo/tattoo_scene.h
engines/sherlock/tattoo/tattoo_user_interface.cpp
engines/sherlock/tattoo/tattoo_user_interface.h
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index 3e8838c..8818f80 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -1151,6 +1151,10 @@ CAnimStream::CAnimStream() {
_zPlacement = 0;
}
+void CAnimStream::getNextFrame() {
+ // TODO
+}
+
/*----------------------------------------------------------------*/
SceneImage::SceneImage() {
diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h
index ec5c2e7..d671066 100644
--- a/engines/sherlock/objects.h
+++ b/engines/sherlock/objects.h
@@ -429,6 +429,8 @@ struct CAnimStream {
int _zPlacement; // Used by doBgAnim for determining Z order
CAnimStream();
+
+ void getNextFrame();
};
struct SceneImage {
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index 624e4d3..37a1b32 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -183,11 +183,6 @@ private:
* will remain the same on future visits to the scene
*/
void saveSceneStatus();
-
- /**
- * Draw all the shapes, people and NPCs in the correct order
- */
- void drawAllShapes();
protected:
SherlockEngine *_vm;
@@ -198,6 +193,11 @@ protected:
*/
virtual void checkBgShapes();
+ /**
+ * Draw all the shapes, people and NPCs in the correct order
+ */
+ void drawAllShapes();
+
Scene(SherlockEngine *vm);
public:
int _currentScene;
diff --git a/engines/sherlock/surface.cpp b/engines/sherlock/surface.cpp
index 6cf479c..5a9e59e 100644
--- a/engines/sherlock/surface.cpp
+++ b/engines/sherlock/surface.cpp
@@ -96,6 +96,12 @@ void Surface::transBlitFrom(const ImageFrame &src, const Common::Point &pt,
transBlitFrom(src._frame, pt + src._offset, flipped, overrideColor);
}
+void Surface::transBlitFrom(const Surface &src, const Common::Point &pt,
+ bool flipped, int overrideColor) {
+ const Graphics::Surface &s = src._surface;
+ transBlitFrom(s, pt, flipped, overrideColor);
+}
+
void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &pt,
bool flipped, int overrideColor) {
Common::Rect drawRect(0, 0, src.w, src.h);
diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp
index 6d90416..368b24b 100644
--- a/engines/sherlock/tattoo/tattoo.cpp
+++ b/engines/sherlock/tattoo/tattoo.cpp
@@ -68,6 +68,10 @@ void TattooEngine::loadInitialPalette() {
delete stream;
}
+void TattooEngine::drawCredits() {
+ // TODO
+}
+
void TattooEngine::eraseCredits() {
// TODO
}
diff --git a/engines/sherlock/tattoo/tattoo.h b/engines/sherlock/tattoo/tattoo.h
index b6a8510..bb6310d 100644
--- a/engines/sherlock/tattoo/tattoo.h
+++ b/engines/sherlock/tattoo/tattoo.h
@@ -54,6 +54,11 @@ public:
virtual ~TattooEngine() {}
/**
+ * Draw credits on the screen
+ */
+ void drawCredits();
+
+ /**
* Erase any area of the screen covered by credits
*/
void eraseCredits();
diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp
index 1effd60..dd96f33 100644
--- a/engines/sherlock/tattoo/tattoo_scene.cpp
+++ b/engines/sherlock/tattoo/tattoo_scene.cpp
@@ -196,6 +196,8 @@ void TattooScene::doBgAnimEraseBackground() {
}
void TattooScene::doBgAnim() {
+ TattooUserInterface &ui = *((TattooUserInterface *)_vm->_ui);
+
doBgAnimCheckCursor();
// Events &events = *_vm->_events;
@@ -208,7 +210,7 @@ void TattooScene::doBgAnim() {
talk._talkToAbort = false;
// Check the characters and sprites for updates
- for (int idx = 0; idx < MAX_CHARACTERS; ++idx) {
+ for (uint idx = 0; idx < MAX_CHARACTERS; ++idx) {
if (people[idx]._type == CHARACTER)
people[idx].checkSprite();
}
@@ -220,8 +222,73 @@ void TattooScene::doBgAnim() {
// Erase any affected background areas
doBgAnimEraseBackground();
+
+ doBgAnimUpdateBgObjectsAndAnim();
+
+ ui.drawInterface();
+}
+
+void TattooScene::doBgAnimUpdateBgObjectsAndAnim() {
+ TattooEngine &vm = *((TattooEngine *)_vm);
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &obj = _bgShapes[idx];
+ if (obj._type == ACTIVE_BG_SHAPE || obj._type == NO_SHAPE)
+ obj.adjustObject();
+ }
+
+ for (uint idx = 0; idx < MAX_CHARACTERS; ++idx) {
+ if (people[idx]._type == CHARACTER)
+ people[idx].adjustSprite();
+ }
+
+ if (_activeCAnim._images != nullptr != _activeCAnim._zPlacement != REMOVE) {
+ _activeCAnim.getNextFrame();
+ }
+
+ // Flag the bg shapes which need to be redrawn
+ checkBgShapes();
+ drawAllShapes();
+
+
+ if (_mask != nullptr) {
+ switch (_currentScene) {
+ case 7:
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 110), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 110), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x + SHERLOCK_SCREEN_WIDTH, 110), screen._currentScroll);
+ break;
+
+ case 8:
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 180), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 180), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x + SHERLOCK_SCREEN_WIDTH, 180), screen._currentScroll);
+ if (!_vm->readFlags(880))
+ screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(940, 300), screen._currentScroll);
+ break;
+
+ case 18:
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 203), screen._currentScroll);
+ if (!_vm->readFlags(189))
+ screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(124 + _maskOffset.x, 239), screen._currentScroll);
+ break;
+
+ case 53:
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 110), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 110), screen._currentScroll);
+ break;
+
+ case 68:
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 203), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(124 + _maskOffset.x, 239), screen._currentScroll);
+ break;
+ }
+ }
}
+
void TattooScene::updateBackground() {
People &people = *_vm->_people;
Screen &screen = *_vm->_screen;
diff --git a/engines/sherlock/tattoo/tattoo_scene.h b/engines/sherlock/tattoo/tattoo_scene.h
index 5e26eaa..de28306 100644
--- a/engines/sherlock/tattoo/tattoo_scene.h
+++ b/engines/sherlock/tattoo/tattoo_scene.h
@@ -39,6 +39,11 @@ private:
void doBgAnimCheckCursor();
void doBgAnimEraseBackground();
+
+ /**
+ * Update the background objects and canimations as part of doBgAnim
+ */
+ void doBgAnimUpdateBgObjectsAndAnim();
protected:
/**
* Checks all the background shapes. If a background shape is animating,
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp
index 98ec34d..e763228 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.cpp
+++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp
@@ -22,7 +22,7 @@
#include "sherlock/tattoo/tattoo_user_interface.h"
#include "sherlock/tattoo/tattoo_scene.h"
-#include "sherlock/sherlock.h"
+#include "sherlock/tattoo/tattoo.h"
namespace Sherlock {
@@ -31,6 +31,8 @@ namespace Tattoo {
TattooUserInterface::TattooUserInterface(SherlockEngine *vm): UserInterface(vm) {
_menuBuffer = nullptr;
_invMenuBuffer = nullptr;
+ _tagBuffer = nullptr;
+ _invGraphic = nullptr;
}
void TattooUserInterface::handleInput() {
@@ -38,6 +40,44 @@ void TattooUserInterface::handleInput() {
_vm->_events->pollEventsAndWait();
}
+void TattooUserInterface::drawInterface(int bufferNum) {
+ Screen &screen = *_vm->_screen;
+ TattooEngine &vm = *((TattooEngine *)_vm);
+
+ if (_invMenuBuffer != nullptr) {
+ Common::Rect r = _invMenuBounds;
+ r.grow(-3);
+ r.translate(-screen._currentScroll, 0);
+ _grayAreas.clear();
+ _grayAreas.push_back(r);
+
+ drawGrayAreas();
+ screen._backBuffer1.transBlitFrom(*_invMenuBuffer, Common::Point(_invMenuBounds.left, _invMenuBounds.top));
+ }
+
+ if (_menuBuffer != nullptr) {
+ Common::Rect r = _menuBounds;
+ r.grow(-3);
+ r.translate(-screen._currentScroll, 0);
+ _grayAreas.clear();
+ _grayAreas.push_back(r);
+
+ drawGrayAreas();
+ screen._backBuffer1.transBlitFrom(*_menuBuffer, Common::Point(_invMenuBounds.left, _invMenuBounds.top));
+ }
+
+ // See if we need to draw a Text Tag floating with the cursor
+ if (_tagBuffer != nullptr)
+ screen._backBuffer1.transBlitFrom(*_tagBuffer, Common::Point(_tagBounds.left, _tagBounds.top));
+
+ // See if we need to draw an Inventory Item Graphic floating with the cursor
+ if (_invGraphic != nullptr)
+ screen._backBuffer1.transBlitFrom(*_invGraphic, Common::Point(_invGraphicBounds.left, _invGraphicBounds.top));
+
+ if (vm._creditsActive)
+ vm.drawCredits();
+}
+
void TattooUserInterface::doBgAnimRestoreUI() {
TattooScene &scene = *((TattooScene *)_vm->_scene);
Screen &screen = *_vm->_screen;
@@ -101,6 +141,10 @@ void TattooUserInterface::doScroll() {
_invMenuBounds.translate(screen._currentScroll - oldScroll, 0);
}
+void TattooUserInterface::drawGrayAreas() {
+ // TODO
+}
+
} // End of namespace Tattoo
} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.h b/engines/sherlock/tattoo/tattoo_user_interface.h
index c7a4c4c..2125f1b 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.h
+++ b/engines/sherlock/tattoo/tattoo_user_interface.h
@@ -36,10 +36,20 @@ private:
Common::Rect _oldMenuBounds;
Common::Rect _invMenuBounds;
Common::Rect _oldInvMenuBounds;
+ Common::Rect _tagBounds;
Common::Rect _oldTagBounds;
+ Common::Rect _invGraphicBounds;
Common::Rect _oldInvGraphicBounds;
Surface *_menuBuffer;
Surface *_invMenuBuffer;
+ Surface *_tagBuffer;
+ Surface *_invGraphic;
+ Common::Array<Common::Rect> _grayAreas;
+private:
+ /**
+ * Draws designated areas of the screen that are meant to be grayed out using grayscale colors
+ */
+ void drawGrayAreas();
public:
TattooUserInterface(SherlockEngine *vm);
@@ -59,6 +69,11 @@ public:
* Main input handler for the user interface
*/
virtual void handleInput();
+
+ /**
+ * Draw the user interface onto the screen's back buffers
+ */
+ virtual void drawInterface(int bufferNum = 3);
};
} // End of namespace Tattoo
Commit: 6b95fc6b1132cf5ce6edc4216368bd38eddc939b
https://github.com/scummvm/scummvm/commit/6b95fc6b1132cf5ce6edc4216368bd38eddc939b
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-30T10:46:19-04:00
Commit Message:
Merge branch 'sherlock2'
Changed paths:
A engines/sherlock/decompress.cpp
A engines/sherlock/scalpel/scalpel_scene.cpp
A engines/sherlock/scalpel/scalpel_scene.h
A engines/sherlock/scalpel/scalpel_user_interface.cpp
A engines/sherlock/scalpel/scalpel_user_interface.h
A engines/sherlock/scalpel/settings.cpp
A engines/sherlock/scalpel/settings.h
A engines/sherlock/tattoo/tattoo_scene.cpp
A engines/sherlock/tattoo/tattoo_scene.h
A engines/sherlock/tattoo/tattoo_user_interface.cpp
A engines/sherlock/tattoo/tattoo_user_interface.h
R engines/sherlock/settings.cpp
R engines/sherlock/settings.h
engines/sherlock/events.cpp
engines/sherlock/events.h
engines/sherlock/inventory.cpp
engines/sherlock/journal.cpp
engines/sherlock/map.cpp
engines/sherlock/map.h
engines/sherlock/module.mk
engines/sherlock/music.cpp
engines/sherlock/music.h
engines/sherlock/objects.cpp
engines/sherlock/objects.h
engines/sherlock/people.cpp
engines/sherlock/people.h
engines/sherlock/resources.cpp
engines/sherlock/resources.h
engines/sherlock/scalpel/scalpel.cpp
engines/sherlock/scene.cpp
engines/sherlock/scene.h
engines/sherlock/screen.cpp
engines/sherlock/screen.h
engines/sherlock/sherlock.cpp
engines/sherlock/sherlock.h
engines/sherlock/sound.cpp
engines/sherlock/sound.h
engines/sherlock/surface.cpp
engines/sherlock/surface.h
engines/sherlock/talk.cpp
engines/sherlock/talk.h
engines/sherlock/tattoo/tattoo.cpp
engines/sherlock/tattoo/tattoo.h
engines/sherlock/user_interface.cpp
engines/sherlock/user_interface.h
diff --cc engines/sherlock/module.mk
index d8c1d78,cee48ae..9ebe416
--- a/engines/sherlock/module.mk
+++ b/engines/sherlock/module.mk
@@@ -3,8 -3,12 +3,13 @@@ MODULE := engines/sherloc
MODULE_OBJS = \
scalpel/darts.o \
scalpel/scalpel.o \
+ scalpel/drivers/adlib.o \
+ scalpel/scalpel_scene.o \
+ scalpel/scalpel_user_interface.o \
+ scalpel/settings.o \
tattoo/tattoo.o \
+ tattoo/tattoo_scene.o \
+ tattoo/tattoo_user_interface.o \
animation.o \
debugger.o \
detection.o \
diff --cc engines/sherlock/music.cpp
index ed047f6,0000000..3e31bcc
mode 100644,000000..100644
--- a/engines/sherlock/music.cpp
+++ b/engines/sherlock/music.cpp
@@@ -1,358 -1,0 +1,363 @@@
+/* 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 "common/config-manager.h"
+#include "sherlock/sherlock.h"
+#include "sherlock/music.h"
+#include "sherlock/scalpel/drivers/mididriver.h"
+
+namespace Sherlock {
+
+#define NUM_SONGS 45
+
+#define USE_SCI_MIDI_PLAYER 1
+
+/* This tells which song to play in each room, 0 = no song played */
+static const char ROOM_SONG[62] = {
+ 0, 20, 43, 6, 11, 2, 8, 15, 6, 28,
+ 6, 38, 7, 32, 16, 5, 8, 41, 9, 22,
+ 10, 23, 4, 39, 19, 24, 13, 27, 0, 30,
+ 3, 21, 26, 25, 16, 29, 1, 1, 18, 12,
+ 1, 17, 17, 31, 17, 34, 36, 7, 20, 20,
+ 33, 8, 44, 40, 42, 35, 0, 0, 0, 12,
+ 12
+};
+
+static const char *const SONG_NAMES[NUM_SONGS] = {
+ "SINGERF", "CHEMIST", "TOBAC", "EQUEST", "MORTUARY", "DOCKS", "LSTUDY",
+ "LORD", "BOY", "PERFUM1", "BAKER1", "BAKER2", "OPERA1", "HOLMES",
+ "FFLAT", "OP1FLAT", "ZOO", "SROOM", "FLOWERS", "YARD", "TAXID",
+ "PUB1", "VICTIM", "RUGBY", "DORM", "SHERMAN", "LAWYER", "THEATRE",
+ "DETECT", "OPERA4", "POOL", "SOOTH", "ANNA1", "ANNA2", "PROLOG3",
+ "PAWNSHOP", "MUSICBOX", "MOZART1", "ROBHUNT", "PANCRAS1", "PANCRAS2", "LORDKILL",
+ "BLACKWEL", "RESCUE", "MAP"
+};
+
+MidiParser_SH::MidiParser_SH() {
+ _ppqn = 1;
+ setTempo(16667);
+ _data = nullptr;
+ _beats = 0;
+ _lastEvent = 0;
+ _trackEnd = nullptr;
+}
+
+void MidiParser_SH::parseNextEvent(EventInfo &info) {
+// warning("parseNextEvent");
+
+ // An attempt to remap MT32 instruments to GMIDI. Only partially successful, it still
+ // does not sound even close to the real MT32. Oddly enough, on the actual hardware MT32
+ // and SB sound very differently.
+ static const byte mt32Map[128] = {
+ 0, 1, 0, 2, 4, 4, 5, 3, /* 0-7 */
+ 16, 17, 18, 16, 16, 19, 20, 21, /* 8-15 */
+ 6, 6, 6, 7, 7, 7, 8, 112, /* 16-23 */
+ 62, 62, 63, 63 , 38, 38, 39, 39, /* 24-31 */
+ 88, 95, 52, 98, 97, 99, 14, 54, /* 32-39 */
+ 102, 96, 53, 102, 81, 100, 14, 80, /* 40-47 */
+ 48, 48, 49, 45, 41, 40, 42, 42, /* 48-55 */
+ 43, 46, 45, 24, 25, 28, 27, 104, /* 56-63 */
+ 32, 32, 34, 33, 36, 37, 35, 35, /* 64-71 */
+ 79, 73, 72, 72, 74, 75, 64, 65, /* 72-79 */
+ 66, 67, 71, 71, 68, 69, 70, 22, /* 80-87 */
+ 56, 59, 57, 57, 60, 60, 58, 61, /* 88-95 */
+ 61, 11, 11, 98, 14, 9, 14, 13, /* 96-103 */
+ 12, 107, 107, 77, 78, 78, 76, 76, /* 104-111 */
+ 47, 117, 127, 118, 118, 116, 115, 119, /* 112-119 */
+ 115, 112, 55, 124, 123, 0, 14, 117 /* 120-127 */
+ };
+
+
+ info.start = _position._playPos;
+ info.delta = 0;
+
+ info.event = *_position._playPos++;
+ //warning("Event %x", info.event);
+ _position._runningStatus = info.event;
+
+ switch (info.command()) {
+ case 0xC: { // program change
+ int idx = *_position._playPos++;
+ info.basic.param1 = idx & 0x7f;
+ // don't do this here, it breaks adlib
+ //info.basic.param1 = mt32Map[idx & 0x7f]; // remap MT32 to GM
+ info.basic.param2 = 0;
+ }
+ break;
+ case 0xD:
+ info.basic.param1 = *_position._playPos++;
+ info.basic.param2 = 0;
+ break;
+
+ case 0xB:
+ info.basic.param1 = *_position._playPos++;
+ info.basic.param2 = *_position._playPos++;
+ info.length = 0;
+ break;
+
+ case 0x8:
+ case 0x9:
+ case 0xA:
+ case 0xE:
+ info.basic.param1 = *(_position._playPos++);
+ info.basic.param2 = *(_position._playPos++);
+ if (info.command() == 0x9 && info.basic.param2 == 0) {
+ // NoteOn with param2==0 is a NoteOff
+ info.event = info.channel() | 0x80;
+ }
+ info.length = 0;
+ break;
+ case 0xF:
+ if (info.event == 0xFF) {
+ byte type = *(_position._playPos++);
+ switch(type) {
+ case 0x2F:
+ // End of Track
+ allNotesOff();
+ stopPlaying();
+ unloadMusic();
+ return;
+ case 0x51:
+ warning("TODO: 0xFF / 0x51");
+ return;
+ default:
+ warning("TODO: 0xFF / %x Unknown", type);
+ break;
+ }
+ } else if (info.event == 0xFC) {
+ allNotesOff();
+ stopPlaying();
+ unloadMusic();
+ return;
+ } else {
+ warning("TODO: %x / Unknown", info.event);
+ break;
+ }
+ break;
+ default:
+ warning("MidiParser_SH::parseNextEvent: Unsupported event code %x", info.event);
+ break;
+ }// switch (info.command())
+
+ info.delta = *(_position._playPos++);
+}
+
+bool MidiParser_SH::loadMusic(byte *data, uint32 size) {
+ warning("loadMusic");
+ unloadMusic();
+
+ byte *headerPtr = data;
+ byte *pos = data;
+ uint16 headerSize = READ_LE_UINT16(headerPtr);
+ assert(headerSize == 0x7F);
+
+ // Skip over header
+ pos += headerSize;
+
+ _lastEvent = 0;
+ _trackEnd = data + size;
+
+ _numTracks = 1;
+ _tracks[0] = pos;
+
+ _ppqn = 1;
+ setTempo(16667);
+ setTrack(0);
+
+ return true;
+}
+
+/*----------------------------------------------------------------*/
+
+Music::Music(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
+ if (_vm->_interactiveFl)
+ _vm->_res->addToCache("MUSIC.LIB");
+
+ MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
+
+ _musicType = MidiDriver::getMusicType(dev);
+
+#if USE_SCI_MIDI_PLAYER
+ _pMidiDrv = NULL;
+#endif
+ _driver = NULL;
+
+ switch (_musicType) {
+ case MT_ADLIB:
+#if USE_SCI_MIDI_PLAYER
+ _pMidiDrv = MidiPlayer_AdLib_create();
+#else
+ _driver = MidiDriver_AdLib_create();
+#endif
+ break;
+ default:
+ _driver = MidiDriver::createMidi(dev);
+ break;
+ }
+#if USE_SCI_MIDI_PLAYER
+ if (_pMidiDrv) {
+ assert(_pMidiDrv);
+ int ret = _pMidiDrv->open();
+ if (ret == 0) {
+ _pMidiDrv->setTimerCallback(&_midiParser, &_midiParser.timerCallback);
+ }
+ _midiParser.setMidiDriver(_pMidiDrv);
+ _midiParser.setTimerRate(_pMidiDrv->getBaseTempo());
+ }
+#endif
+
+ if (_driver) {
+ assert(_driver);
+
+ int ret = _driver->open();
+ if (ret == 0) {
+ _driver->sendGMReset();
+ _driver->setTimerCallback(&_midiParser, &_midiParser.timerCallback);
+ }
+ _midiParser.setMidiDriver(_driver);
+ _midiParser.setTimerRate(_driver->getBaseTempo());
+ }
+
+ _musicPlaying = false;
+ _musicOn = true;
+}
+
+bool Music::loadSong(int songNumber) {
+ warning("loadSong");
+
+ if(songNumber == 100)
+ songNumber = 55;
+ else if(songNumber == 70)
+ songNumber = 54;
+
+ if((songNumber > 60) || (songNumber < 1))
+ return false;
+
+ songNumber = ROOM_SONG[songNumber];
+
+ if(songNumber == 0)
+ songNumber = 12;
+
+ if((songNumber > NUM_SONGS) || (songNumber < 1))
+ return false;
+
+ Common::String songName = Common::String(SONG_NAMES[songNumber - 1]) + ".MUS";
+
+ freeSong(); // free any song that is currently loaded
+
+ if (!playMusic(songName))
+ return false;
+
+ stopMusic();
+ startSong();
+ return true;
+}
+
++bool Music::loadSong(const Common::String &songName) {
++ warning("TODO: Music::loadSong");
++ return false;
++}
++
+void Music::syncMusicSettings() {
+ _musicOn = !ConfMan.getBool("mute") && !ConfMan.getBool("music_mute");
+}
+
+bool Music::playMusic(const Common::String &name) {
+ if (!_musicOn)
+ return false;
+
+ warning("Sound::playMusic %s", name.c_str());
+ Common::SeekableReadStream *stream = _vm->_res->load(name, "MUSIC.LIB");
+
+ byte *data = new byte[stream->size()];
+ int32 dataSize = stream->size();
+ assert(data);
+
+ stream->read(data, dataSize);
+
+ // for dumping the music tracks
+#if 0
+ Common::DumpFile outFile;
+ outFile.open(name + ".RAW");
+ outFile.write(data, stream->size());
+ outFile.flush();
+ outFile.close();
+#endif
+
+ if (dataSize < 14) {
+ warning("not enough data in music file");
+ return false;
+ }
+
+ byte *dataPos = data;
+ if (memcmp(" ", dataPos, 12)) {
+ warning("Expected header not found in music file");
+ return false;
+ }
+ dataPos += 12;
+ dataSize -= 12;
+
+ uint16 headerSize = READ_LE_UINT16(dataPos);
+ if (headerSize != 0x7F) {
+ warning("music header is not as expected");
+ return false;
+ }
+
+ if (_musicType == MT_ADLIB) {
+ if (_driver)
+ MidiDriver_AdLib_newMusicData(_driver, dataPos, dataSize);
+#if USE_SCI_MIDI_PLAYER
+ if (_pMidiDrv)
+ MidiPlayer_AdLib_newMusicData(_pMidiDrv, dataPos, dataSize);
+#endif
+ }
+
+ _midiParser.loadMusic(dataPos, dataSize);
+ return true;
+}
+
+void Music::stopMusic() {
+ // TODO
+ warning("TODO: Sound::stopMusic");
+
+ _musicPlaying = false;
+}
+
+void Music::startSong() {
+ if (!_musicOn)
+ return;
+
+ // TODO
+ warning("TODO: Sound::startSong");
+ _musicPlaying = true;
+}
+
+void Music::freeSong() {
+ // TODO
+ warning("TODO: Sound::freeSong");
+}
+
+void Music::waitTimerRoland(uint time) {
+ // TODO
+ warning("TODO: Sound::waitTimerRoland");
+}} // End of namespace Sherlock
+
diff --cc engines/sherlock/music.h
index a195b26,0000000..c371060
mode 100644,000000..100644
--- a/engines/sherlock/music.h
+++ b/engines/sherlock/music.h
@@@ -1,102 -1,0 +1,107 @@@
+/* 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.
+ *
+ */
+
+#ifndef SHERLOCK_MUSIC_H
+#define SHERLOCK_MUSIC_H
+
+#include "audio/midiplayer.h"
+#include "audio/midiparser.h"
+//#include "audio/mididrv.h"
+#include "sherlock/scalpel/drivers/mididriver.h"
+
+namespace Sherlock {
+
+class SherlockEngine;
+
+class MidiParser_SH : public MidiParser {
+protected:
+ virtual void parseNextEvent(EventInfo &info);
+
+ uint8 _beats;
+ uint8 _lastEvent;
+ byte *_data;
+ byte *_trackEnd;
+public:
+ MidiParser_SH();
+ virtual bool loadMusic(byte *data, uint32 size);
+};
+
+class Music {
+private:
+ SherlockEngine *_vm;
+ Audio::Mixer *_mixer;
+ MidiParser_SH _midiParser;
+ MidiPlayer *_pMidiDrv;
+ MidiDriver *_driver;
+
+public:
+ bool _musicPlaying;
+ bool _musicOn;
+
+private:
+ MusicType _musicType;
+
+public:
+ Music(SherlockEngine *vm, Audio::Mixer *mixer);
+
+ /**
+ * Saves sound-related settings
+ */
+ void syncMusicSettings();
+
+ /**
+ * Load a specified song
+ */
+ bool loadSong(int songNumber);
+
+ /**
++ * Load a specified song
++ */
++ bool loadSong(const Common::String &songName);
++
++ /**
+ * Start playing a song
+ */
+ void startSong();
+
+ /**
+ * Free any currently loaded song
+ */
+ void freeSong();
+
+ /**
+ * Play the specified music resource
+ */
+ bool playMusic(const Common::String &name);
+
+ /**
+ * Stop playing the music
+ */
+ void stopMusic();
+
+ void waitTimerRoland(uint time);
+};
+
+} // End of namespace Sherlock
+
+#endif
+
diff --cc engines/sherlock/scalpel/scalpel.cpp
index bee44bf,6b72188..304445d
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@@ -22,8 -22,8 +22,9 @@@
#include "sherlock/scalpel/scalpel.h"
#include "sherlock/sherlock.h"
+#include "sherlock/music.h"
#include "sherlock/animation.h"
+ #include "engines/util.h"
namespace Sherlock {
diff --cc engines/sherlock/scalpel/settings.cpp
index 0000000,4459786..aa8033d
mode 000000,100644..100644
--- a/engines/sherlock/scalpel/settings.cpp
+++ b/engines/sherlock/scalpel/settings.cpp
@@@ -1,0 -1,341 +1,341 @@@
+ /* 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/sherlock.h"
+ #include "sherlock/scalpel/settings.h"
+ #include "sherlock/scalpel/scalpel_user_interface.h"
+
+ namespace Sherlock {
+
+ namespace Scalpel {
+
+ static const int SETUP_POINTS[12][4] = {
+ { 4, 154, 101, 53 }, // Exit
+ { 4, 165, 101, 53 }, // Music Toggle
+ { 219, 165, 316, 268 }, // Voice Toggle
+ { 103, 165, 217, 160 }, // Sound Effects Toggle
+ { 219, 154, 316, 268 }, // Help Button Left/Right
+ { 103, 154, 217, 160 }, // New Font Style
+ { 4, 187, 101, 53 }, // Joystick Toggle
+ { 103, 187, 217, 160 }, // Calibrate Joystick
+ { 219, 176, 316, 268 }, // Fade Style
+ { 103, 176, 217, 160 }, // Window Open Style
+ { 4, 176, 101, 53 }, // Portraits Toggle
+ { 219, 187, 316, 268 } // _key Pad Accel. Toggle
+ };
+
+ static const char *const SETUP_STRS0[2] = { "off", "on" };
+ static const char *const SETUP_STRS1[2] = { "Directly", "by Pixel" };
+ static const char *const SETUP_STRS2[2] = { "Left", "Right" };
+ static const char *const SETUP_STRS3[2] = { "Appear", "Slide" };
+ static const char *const SETUP_STRS5[2] = { "Left", "Right" };
+ static const char *const SETUP_NAMES[12] = {
+ "Exit", "M", "V", "S", "B", "New Font Style", "J", "Calibrate Joystick", "F", "W", "P", "K"
+ };
+
+ /*----------------------------------------------------------------*/
+
+ void Settings::drawInteface(bool flag) {
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
+ Sound &sound = *_vm->_sound;
++ Music &music = *_vm->_music;
+ UserInterface &ui = *_vm->_ui;
+ Common::String tempStr;
+
+ if (!flag) {
+ screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y1 + 1), BORDER_COLOR);
+ screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y1 + 1, 2, SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR);
+ screen._backBuffer1.fillRect(Common::Rect(SHERLOCK_SCREEN_WIDTH - 2, CONTROLS_Y1 + 1, SHERLOCK_SCREEN_WIDTH,
+ SHERLOCK_SCREEN_HEIGHT), BORDER_COLOR);
+ screen._backBuffer1.hLine(0, SHERLOCK_SCREEN_HEIGHT - 1, SHERLOCK_SCREEN_WIDTH - 1, BORDER_COLOR);
+ screen._backBuffer1.fillRect(Common::Rect(2, CONTROLS_Y1 + 1, SHERLOCK_SCREEN_WIDTH - 2,
+ SHERLOCK_SCREEN_HEIGHT - 2), INV_BACKGROUND);
+ }
+
+ screen.makeButton(Common::Rect(SETUP_POINTS[0][0], SETUP_POINTS[0][1], SETUP_POINTS[0][2], SETUP_POINTS[0][1] + 10),
+ SETUP_POINTS[0][3] - screen.stringWidth("Exit") / 2, "Exit");
+
- tempStr = Common::String::format("Music %s", SETUP_STRS0[sound._music]);
++ tempStr = Common::String::format("Music %s", SETUP_STRS0[music._musicOn]);
+ screen.makeButton(Common::Rect(SETUP_POINTS[1][0], SETUP_POINTS[1][1], SETUP_POINTS[1][2], SETUP_POINTS[1][1] + 10),
+ SETUP_POINTS[1][3] - screen.stringWidth(tempStr) / 2, tempStr);
+
+ tempStr = Common::String::format("Voices %s", SETUP_STRS0[sound._voices]);
+ screen.makeButton(Common::Rect(SETUP_POINTS[2][0], SETUP_POINTS[2][1], SETUP_POINTS[2][2], SETUP_POINTS[2][1] + 10),
+ SETUP_POINTS[2][3] - screen.stringWidth(tempStr) / 2, tempStr);
+
+ tempStr = Common::String::format("Sound Effects %s", SETUP_STRS0[sound._digitized]);
+ screen.makeButton(Common::Rect(SETUP_POINTS[3][0], SETUP_POINTS[3][1], SETUP_POINTS[3][2], SETUP_POINTS[3][1] + 10),
+ SETUP_POINTS[3][3] - screen.stringWidth(tempStr) / 2, tempStr);
+
+ tempStr = Common::String::format("Auto Help %s", SETUP_STRS5[ui._helpStyle]);
+ screen.makeButton(Common::Rect(SETUP_POINTS[4][0], SETUP_POINTS[4][1], SETUP_POINTS[4][2], SETUP_POINTS[4][1] + 10),
+ SETUP_POINTS[4][3] - screen.stringWidth(tempStr) / 2, tempStr);
+ screen.makeButton(Common::Rect(SETUP_POINTS[5][0], SETUP_POINTS[5][1], SETUP_POINTS[5][2], SETUP_POINTS[5][1] + 10),
+ SETUP_POINTS[5][3] - screen.stringWidth("New Font Style") / 2, "New Font Style");
+
+ // WORKAROUND: We don't support the joystick in ScummVM, so draw the next two buttons as disabled
+ tempStr = "Joystick Off";
+ screen.makeButton(Common::Rect(SETUP_POINTS[6][0], SETUP_POINTS[6][1], SETUP_POINTS[6][2], SETUP_POINTS[6][1] + 10),
+ SETUP_POINTS[6][3] - screen.stringWidth(tempStr) / 2, tempStr);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[6][3], SETUP_POINTS[6][1]), COMMAND_NULL, false, tempStr);
+
+ tempStr = "Calibrate Joystick";
+ screen.makeButton(Common::Rect(SETUP_POINTS[7][0], SETUP_POINTS[7][1], SETUP_POINTS[7][2], SETUP_POINTS[7][1] + 10),
+ SETUP_POINTS[7][3] - screen.stringWidth(tempStr) / 2, tempStr);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[7][3], SETUP_POINTS[7][1]), COMMAND_NULL, false, tempStr);
+
+ tempStr = Common::String::format("Fade %s", screen._fadeStyle ? "by Pixel" : "Directly");
+ screen.makeButton(Common::Rect(SETUP_POINTS[8][0], SETUP_POINTS[8][1], SETUP_POINTS[8][2], SETUP_POINTS[8][1] + 10),
+ SETUP_POINTS[8][3] - screen.stringWidth(tempStr) / 2, tempStr);
+
+ tempStr = Common::String::format("Windows %s", ui._slideWindows ? "Slide" : "Appear");
+ screen.makeButton(Common::Rect(SETUP_POINTS[9][0], SETUP_POINTS[9][1], SETUP_POINTS[9][2], SETUP_POINTS[9][1] + 10),
+ SETUP_POINTS[9][3] - screen.stringWidth(tempStr) / 2, tempStr);
+
+ tempStr = Common::String::format("Portraits %s", SETUP_STRS0[people._portraitsOn]);
+ screen.makeButton(Common::Rect(SETUP_POINTS[10][0], SETUP_POINTS[10][1], SETUP_POINTS[10][2], SETUP_POINTS[10][1] + 10),
+ SETUP_POINTS[10][3] - screen.stringWidth(tempStr) / 2, tempStr);
+
+ tempStr = "Key Pad Slow";
+ screen.makeButton(Common::Rect(SETUP_POINTS[11][0], SETUP_POINTS[11][1], SETUP_POINTS[11][2], SETUP_POINTS[11][1] + 10),
+ SETUP_POINTS[11][3] - screen.stringWidth(tempStr) / 2, tempStr);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[11][3], SETUP_POINTS[11][1]), COMMAND_NULL, false, tempStr);
+
+ // Show the window immediately, or slide it on-screen
+ if (!flag) {
+ if (!ui._slideWindows) {
+ screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+ } else {
+ ui.summonWindow(true, CONTROLS_Y1);
+ }
+
+ ui._windowOpen = true;
+ } else {
+ screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+ }
+ }
+
+ int Settings::drawButtons(const Common::Point &pt, int _key) {
+ Events &events = *_vm->_events;
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
++ Music &music = *_vm->_music;
+ Sound &sound = *_vm->_sound;
+ UserInterface &ui = *_vm->_ui;
+ int found = -1;
+ byte color;
+ Common::String tempStr;
+
+ for (int idx = 0; idx < 12; ++idx) {
+ if ((pt.x > SETUP_POINTS[idx][0] && pt.x < SETUP_POINTS[idx][2] && pt.y > SETUP_POINTS[idx][1]
+ && pt.y < (SETUP_POINTS[idx][1] + 10) && (events._pressed || events._released))
+ || (_key == SETUP_NAMES[idx][0])) {
+ found = idx;
+ color = COMMAND_HIGHLIGHTED;
+ } else {
+ color = COMMAND_FOREGROUND;
+ }
+
+ // Print the button text
+ switch (idx) {
+ case 1:
- tempStr = Common::String::format("Music %s", SETUP_STRS0[sound._music]);
++ tempStr = Common::String::format("Music %s", SETUP_STRS0[music._musicOn]);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
+ break;
+ case 2:
+ tempStr = Common::String::format("Voices %s", SETUP_STRS0[sound._voices]);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
+ break;
+ case 3:
+ tempStr = Common::String::format("Sound Effects %s", SETUP_STRS0[sound._digitized]);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
+ break;
+ case 4:
+ tempStr = Common::String::format("Auto Help %s", SETUP_STRS2[ui._helpStyle]);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
+ break;
+ case 6:
+ tempStr = "Joystick Off";
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), COMMAND_NULL, true, tempStr);
+ break;
+ case 7:
+ tempStr = "Calibrate Joystick";
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), COMMAND_NULL, true, tempStr);
+ break;
+ case 8:
+ tempStr = Common::String::format("Fade %s", SETUP_STRS1[screen._fadeStyle]);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
+ break;
+ case 9:
+ tempStr = Common::String::format("Windows %s", SETUP_STRS3[ui._slideWindows]);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
+ break;
+ case 10:
+ tempStr = Common::String::format("Portraits %s", SETUP_STRS0[people._portraitsOn]);
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
+ break;
+ case 11:
+ tempStr = "Key Pad Slow";
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), COMMAND_NULL, true, tempStr);
+ break;
+ default:
+ screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, SETUP_NAMES[idx]);
+ break;
+ }
+ }
+
+ return found;
+ }
+
+ void Settings::show(SherlockEngine *vm) {
+ Events &events = *vm->_events;
+ People &people = *vm->_people;
+ Scene &scene = *vm->_scene;
+ Screen &screen = *vm->_screen;
+ Sound &sound = *vm->_sound;
++ Music &music = *vm->_music;
+ Talk &talk = *vm->_talk;
+ ScalpelUserInterface &ui = *(ScalpelUserInterface *)vm->_ui;
+ bool updateConfig = false;
+
+ assert(vm->getGameID() == GType_SerratedScalpel);
+ Settings settings(vm);
+ settings.drawInteface(false);
+
+ do {
+ if (ui._menuCounter)
+ ui.whileMenuCounter();
+
+ int found = -1;
+ ui._key = -1;
+
+ scene.doBgAnim();
+ if (talk._talkToAbort)
+ return;
+
+ events.setButtonState();
+ Common::Point pt = events.mousePos();
+
+ if (events._pressed || events._released || events.kbHit()) {
+ ui.clearInfo();
+ ui._key = -1;
+
+ if (events.kbHit()) {
+ Common::KeyState keyState = events.getKey();
+ ui._key = toupper(keyState.keycode);
+
+ if (ui._key == Common::KEYCODE_RETURN || ui._key == Common::KEYCODE_SPACE) {
+ events._pressed = false;
+ events._oldButtons = 0;
+ ui._keyPress = '\0';
+ events._released = true;
+ }
+ }
+
+ // Handle highlighting button under mouse
+ found = settings.drawButtons(pt, ui._key);
+ }
+
+ if ((found == 0 && events._released) || (ui._key == 'E' || ui._key == Common::KEYCODE_ESCAPE))
+ // Exit
+ break;
+
+ if ((found == 1 && events._released) || ui._key == 'M') {
+ // Toggle music
- if (sound._music) {
- sound.stopSound();
- sound._music = false;
- }
- else {
- sound._music = true;
- sound.startSong();
- }
++ music._musicOn = !music._musicOn;
++ if (!music._musicOn)
++ music.stopMusic();
++ else
++ music.startSong();
+
+ updateConfig = true;
+ settings.drawInteface(true);
+ }
+
+ if ((found == 2 && events._released) || ui._key == 'V') {
+ sound._voices = !sound._voices;
+ updateConfig = true;
+ settings.drawInteface(true);
+ }
+
+ if ((found == 3 && events._released) || ui._key == 'S') {
+ // Toggle sound effects
+ sound._digitized = !sound._digitized;
+ updateConfig = true;
+ settings.drawInteface(true);
+ }
+
+ if ((found == 4 && events._released) || ui._key == 'A') {
+ // Help button style
+ ui._helpStyle = !ui._helpStyle;
+ updateConfig = true;
+ settings.drawInteface(true);
+ }
+
+ if ((found == 5 && events._released) || ui._key == 'N') {
+ // New font style
+ int fontNum = screen.fontNumber() + 1;
+ if (fontNum == 3)
+ fontNum = 0;
+
+ screen.setFont(fontNum);
+ updateConfig = true;
+ settings.drawInteface(true);
+ }
+
+ if ((found == 8 && events._released) || ui._key == 'F') {
+ // Toggle fade style
+ screen._fadeStyle = !screen._fadeStyle;
+ updateConfig = true;
+ settings.drawInteface(true);
+ }
+
+ if ((found == 9 && events._released) || ui._key == 'W') {
+ // Window style
+ ui._slideWindows = !ui._slideWindows;
+ updateConfig = true;
+ settings.drawInteface(true);
+ }
+
+ if ((found == 10 && events._released) || ui._key == 'P') {
+ // Toggle portraits being shown
+ people._portraitsOn = !people._portraitsOn;
+ updateConfig = true;
+ settings.drawInteface(true);
+ }
+ } while (!vm->shouldQuit());
+
+ ui.banishWindow();
+
+ if (updateConfig)
+ vm->saveConfig();
+
+ ui._keyPress = '\0';
+ ui._keyboardInput = false;
+ ui._windowBounds.top = CONTROLS_Y1;
+ ui._key = -1;
+ }
+
+ } // End of namespace Scalpel
+
+ } // End of namespace Sherlock
diff --cc engines/sherlock/scene.cpp
index 781e596,0f0187e..76fb7ae
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@@ -193,7 -254,8 +254,9 @@@ void Scene::freeScene()
bool Scene::loadScene(const Common::String &filename) {
Events &events = *_vm->_events;
Map &map = *_vm->_map;
++ Music &music = *_vm->_music;
People &people = *_vm->_people;
+ Resources &res = *_vm->_res;
SaveManager &saves = *_vm->_saves;
Screen &screen = *_vm->_screen;
Sound &sound = *_vm->_sound;
@@@ -213,8 -275,38 +276,38 @@@
_cAnim.clear();
_sequenceBuffer.clear();
+ // Check if it's a scene we need to keep trakc track of how many times we've visited
+ for (int idx = (int)_sceneTripCounters.size() - 1; idx >= 0; --idx) {
+ if (_sceneTripCounters[idx]._sceneNumber == _currentScene) {
+ if (--_sceneTripCounters[idx]._numTimes == 0) {
+ _vm->setFlags(_sceneTripCounters[idx]._flag);
+ _sceneTripCounters.remove_at(idx);
+ }
+ }
+ }
+
+ if (IS_ROSE_TATTOO) {
+ // Set the NPC paths for the scene
+ setNPCPath(0);
+
+ // Handle loading music for the scene
+ if (sound._midiDrvLoaded) {
+ if (talk._scriptMoreFlag != 1 && talk._scriptMoreFlag != 3)
+ sound._nextSongName = Common::String::format("res%02d", _currentScene);
+
+ // If it's a new song, then start it up
+ if (sound._currentSongName.compareToIgnoreCase(sound._nextSongName)) {
- if (sound.loadSong(sound._nextSongName)) {
++ if (music.loadSong(sound._nextSongName)) {
+ sound.setMIDIVolume(sound._musicVolume);
- if (sound._musicOn)
- sound.startSong();
++ if (music._musicOn)
++ music.startSong();
+ }
+ }
+ }
+ }
+
//
- // Load background shapes from <filename>.rrm
+ // Load the room resource file for the scene
//
Common::String rrmFile = filename + ".rrm";
@@@ -447,8 -608,10 +609,8 @@@
checkInventory();
// Handle starting any music for the scene
- if (music._musicOn && music.loadSong(_currentScene))
- if (IS_SERRATED_SCALPEL && sound._musicOn && sound.loadSong(_currentScene)) {
- if (sound._music)
- sound.startSong();
- }
++ if (IS_SERRATED_SCALPEL && music._musicOn && music.loadSong(_currentScene))
+ music.startSong();
// Load walking images if not already loaded
people.loadWalk();
diff --cc engines/sherlock/sound.cpp
index a923cf9,279dd44..e7f4fe8
--- a/engines/sherlock/sound.cpp
+++ b/engines/sherlock/sound.cpp
@@@ -57,11 -58,14 +57,14 @@@ Sound::Sound(SherlockEngine *vm, Audio:
_soundPlaying = false;
_soundIsOn = &_soundPlaying;
_curPriority = 0;
+ _digiBuf = nullptr;
+ _midiDrvLoaded = false;
+ _musicVolume = 0;
_soundOn = true;
- _musicOn = true;
_speechOn = true;
+ _vm->_res->addToCache("MUSIC.LIB");
if (!_vm->_interactiveFl)
_vm->_res->addToCache("TITLE.SND");
else {
diff --cc engines/sherlock/sound.h
index 2351beb,06450ff..e1c0777
--- a/engines/sherlock/sound.h
+++ b/engines/sherlock/sound.h
@@@ -89,8 -94,36 +92,9 @@@ public
*/
void stopSound();
- /**
- * Load a specified song
- */
- bool loadSong(int songNumber);
- bool loadSong(const Common::String &name);
-
- /**
- * Start playing a song
- */
- void startSong();
-
- /**
- * Free any currently loaded song
- */
- void freeSong();
-
- /**
- * Play the specified music resource
- */
- void playMusic(const Common::String &name);
-
- /**
- * Stop playing the music
- */
- void stopMusic();
-
void stopSndFuncPtr(int v1, int v2);
- void waitTimerRoland(uint time);
void freeDigiSound();
+ void setMIDIVolume(int volume);
};
} // End of namespace Sherlock
Commit: 9c09f243ea4db7b002b9cec9b348812c22404409
https://github.com/scummvm/scummvm/commit/9c09f243ea4db7b002b9cec9b348812c22404409
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-30T10:47:47-04:00
Commit Message:
Merge branch 'master' of https://github.com/scummvm/scummvm
Changed paths:
engines/sherlock/scalpel/drivers/adlib.cpp
Commit: 4e404416146c43d8a3aa2175b33e95f84a348eff
https://github.com/scummvm/scummvm/commit/4e404416146c43d8a3aa2175b33e95f84a348eff
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-30T11:17:07-04:00
Commit Message:
TSAGE: Fix incorrectly named header defines
Changed paths:
engines/tsage/graphics.h
engines/tsage/resources.h
diff --git a/engines/tsage/graphics.h b/engines/tsage/graphics.h
index d65d0bc..25f7aea 100644
--- a/engines/tsage/graphics.h
+++ b/engines/tsage/graphics.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef RING_GRAPHICS_H
-#define RING_GRAPHICS_H
+#ifndef TSAGE_GRAPHICS_H
+#define TSAGE_GRAPHICS_H
#include "tsage/events.h"
#include "tsage/saveload.h"
diff --git a/engines/tsage/resources.h b/engines/tsage/resources.h
index a7536a3..7aa0c49 100644
--- a/engines/tsage/resources.h
+++ b/engines/tsage/resources.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef RING_RESOURCES_H
-#define RING_RESOURCES_H
+#ifndef TSAGE_RESOURCES_H
+#define TSAGE_RESOURCES_H
#include "common/scummsys.h"
#include "common/array.h"
Commit: 0cc5313689d980fc9855eba6bbdc973c7a9d9e96
https://github.com/scummvm/scummvm/commit/0cc5313689d980fc9855eba6bbdc973c7a9d9e96
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-05-30T17:42:36+02:00
Commit Message:
SHERLOCK: midi parser delta reading changed
Changed paths:
engines/sherlock/music.cpp
diff --git a/engines/sherlock/music.cpp b/engines/sherlock/music.cpp
index 3e31bcc..884fbd6 100644
--- a/engines/sherlock/music.cpp
+++ b/engines/sherlock/music.cpp
@@ -86,9 +86,15 @@ void MidiParser_SH::parseNextEvent(EventInfo &info) {
115, 112, 55, 124, 123, 0, 14, 117 /* 120-127 */
};
+ // there is no delta right at the start of the music data
+ // this order is essential, otherwise notes will get delayed or even go missing
+ if (_position._playPos != _tracks[0]) {
+ info.delta = *(_position._playPos++);
+ } else {
+ info.delta = 0;
+ }
info.start = _position._playPos;
- info.delta = 0;
info.event = *_position._playPos++;
//warning("Event %x", info.event);
@@ -157,8 +163,6 @@ void MidiParser_SH::parseNextEvent(EventInfo &info) {
warning("MidiParser_SH::parseNextEvent: Unsupported event code %x", info.event);
break;
}// switch (info.command())
-
- info.delta = *(_position._playPos++);
}
bool MidiParser_SH::loadMusic(byte *data, uint32 size) {
Commit: 17aeb5264921ca55f77d190d6ff146e9a54ee5b6
https://github.com/scummvm/scummvm/commit/17aeb5264921ca55f77d190d6ff146e9a54ee5b6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-30T11:42:21-04:00
Commit Message:
SHERLOCK: Fix non-interactive Scalpel demo
Changed paths:
engines/sherlock/events.cpp
engines/sherlock/scalpel/scalpel_user_interface.cpp
diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp
index a02a06c..b238605 100644
--- a/engines/sherlock/events.cpp
+++ b/engines/sherlock/events.cpp
@@ -32,8 +32,7 @@ namespace Sherlock {
enum ButtonFlag { LEFT_BUTTON = 1, RIGHT_BUTTON = 2 };
-Events::Events(SherlockEngine *vm) {
- _vm = vm;
+Events::Events(SherlockEngine *vm): _vm(vm) {
_cursorImages = nullptr;
_cursorId = INVALID_CURSOR;
_frameCounter = 1;
@@ -43,7 +42,8 @@ Events::Events(SherlockEngine *vm) {
_rightPressed = _rightReleased = false;
_oldButtons = _oldRightButton = false;
- loadCursors("rmouse.vgs");
+ if (_vm->_interactiveFl)
+ loadCursors("rmouse.vgs");
}
Events::~Events() {
diff --git a/engines/sherlock/scalpel/scalpel_user_interface.cpp b/engines/sherlock/scalpel/scalpel_user_interface.cpp
index f9ec8bb..69ab6ec 100644
--- a/engines/sherlock/scalpel/scalpel_user_interface.cpp
+++ b/engines/sherlock/scalpel/scalpel_user_interface.cpp
@@ -84,8 +84,14 @@ const char *const MUSE[] = {
ScalpelUserInterface::ScalpelUserInterface(SherlockEngine *vm): UserInterface(vm) {
- _controls = new ImageFile("menu.all");
- _controlPanel = new ImageFile("controls.vgs");
+ if (_vm->_interactiveFl) {
+ _controls = new ImageFile("menu.all");
+ _controlPanel = new ImageFile("controls.vgs");
+ } else {
+ _controls = nullptr;
+ _controlPanel = nullptr;
+ }
+
_keyPress = '\0';
_lookHelp = 0;
_bgFound = 0;
Commit: a7f9e4c317aecc179bca6b698922c3b835ca02cc
https://github.com/scummvm/scummvm/commit/a7f9e4c317aecc179bca6b698922c3b835ca02cc
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2015-05-30T17:45:39+02:00
Commit Message:
SHERLOCK: Fix compilation with GCC
Changed paths:
engines/sherlock/scalpel/scalpel_user_interface.h
diff --git a/engines/sherlock/scalpel/scalpel_user_interface.h b/engines/sherlock/scalpel/scalpel_user_interface.h
index 8ed69ac8..262cd29 100644
--- a/engines/sherlock/scalpel/scalpel_user_interface.h
+++ b/engines/sherlock/scalpel/scalpel_user_interface.h
@@ -44,7 +44,7 @@ extern const char *const PRESS_KEY_TO_CONTINUE;
class Settings;
class ScalpelUserInterface: public UserInterface {
- friend class Inventory;
+ friend class Sherlock::Inventory;
friend class Settings;
friend class Talk;
private:
Commit: 560bc65fc4e70dfc8f2df3affe2c6ab31afc5a74
https://github.com/scummvm/scummvm/commit/560bc65fc4e70dfc8f2df3affe2c6ab31afc5a74
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2015-05-30T17:46:35+02:00
Commit Message:
SHERLOCK: Silence GCC warning.
Changed paths:
engines/sherlock/talk.h
diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h
index a5f81f3..ebfe8f1 100644
--- a/engines/sherlock/talk.h
+++ b/engines/sherlock/talk.h
@@ -109,7 +109,7 @@ enum OpcodeReturn { RET_EXIT = -1, RET_SUCCESS = 0, RET_CONTINUE = 1 };
class SherlockEngine;
class Talk;
-namespace Scalpel { class ScalpelUserInterface; };
+namespace Scalpel { class ScalpelUserInterface; }
typedef OpcodeReturn(Talk::*OpcodeMethod)(const byte *&str);
Commit: 25551111491e216ac4b46741beea13cbaa511b66
https://github.com/scummvm/scummvm/commit/25551111491e216ac4b46741beea13cbaa511b66
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-30T11:49:34-04:00
Commit Message:
SHERLOCK: Fix incorrect if statement
Changed paths:
engines/sherlock/tattoo/tattoo_scene.cpp
diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp
index dd96f33..66a66ba 100644
--- a/engines/sherlock/tattoo/tattoo_scene.cpp
+++ b/engines/sherlock/tattoo/tattoo_scene.cpp
@@ -244,7 +244,7 @@ void TattooScene::doBgAnimUpdateBgObjectsAndAnim() {
people[idx].adjustSprite();
}
- if (_activeCAnim._images != nullptr != _activeCAnim._zPlacement != REMOVE) {
+ if (_activeCAnim._images != nullptr && _activeCAnim._zPlacement != REMOVE) {
_activeCAnim.getNextFrame();
}
Commit: 442fb847683aa789ae75dcf990040a13691293b6
https://github.com/scummvm/scummvm/commit/442fb847683aa789ae75dcf990040a13691293b6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-30T12:56:07-04:00
Commit Message:
SHERLOCK: Make some of the scalpel user interface fields public
Changed paths:
engines/sherlock/scalpel/scalpel_user_interface.h
diff --git a/engines/sherlock/scalpel/scalpel_user_interface.h b/engines/sherlock/scalpel/scalpel_user_interface.h
index 262cd29..dbc3945 100644
--- a/engines/sherlock/scalpel/scalpel_user_interface.h
+++ b/engines/sherlock/scalpel/scalpel_user_interface.h
@@ -44,12 +44,9 @@ extern const char *const PRESS_KEY_TO_CONTINUE;
class Settings;
class ScalpelUserInterface: public UserInterface {
- friend class Sherlock::Inventory;
friend class Settings;
friend class Talk;
private:
- ImageFile *_controlPanel;
- ImageFile *_controls;
char _keyPress;
int _lookHelp;
int _bgFound, _oldBgFound;
@@ -63,7 +60,6 @@ private:
Common::String _cAnimStr;
Common::String _descStr;
int _find;
- int _oldUse;
private:
/**
* Draws the image for a user interface button in the down/pressed state.
@@ -159,6 +155,10 @@ private:
*/
void printObjectDesc(const Common::String &str, bool firstTime);
public:
+ ImageFile *_controlPanel;
+ ImageFile *_controls;
+ int _oldUse;
+public:
ScalpelUserInterface(SherlockEngine *vm);
virtual ~ScalpelUserInterface();
Commit: 1f7555c2ca753c4b68c3a53c651dead981e7b81d
https://github.com/scummvm/scummvm/commit/1f7555c2ca753c4b68c3a53c651dead981e7b81d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-30T13:04:22-04:00
Commit Message:
SHERLOCK: Further compilation fixes
Changed paths:
engines/sherlock/scalpel/drivers/adlib.cpp
engines/sherlock/scalpel/scalpel_user_interface.h
engines/sherlock/tattoo/tattoo_scene.cpp
diff --git a/engines/sherlock/scalpel/drivers/adlib.cpp b/engines/sherlock/scalpel/drivers/adlib.cpp
index 5786a33..2a56d6a 100644
--- a/engines/sherlock/scalpel/drivers/adlib.cpp
+++ b/engines/sherlock/scalpel/drivers/adlib.cpp
@@ -405,7 +405,7 @@ void MidiDriver_AdLib::send(uint32 b) {
pitchBendChange(channel, op1, op2);
break;
case 0xf0: // SysEx
- warning("SysEx: %lx", b);
+ warning("SysEx: %x", b);
break;
default:
warning("ADLIB: Unknown event %02x", command);
diff --git a/engines/sherlock/scalpel/scalpel_user_interface.h b/engines/sherlock/scalpel/scalpel_user_interface.h
index dbc3945..552bcf0 100644
--- a/engines/sherlock/scalpel/scalpel_user_interface.h
+++ b/engines/sherlock/scalpel/scalpel_user_interface.h
@@ -80,12 +80,6 @@ private:
void toggleButton(int num);
/**
- * Creates a text window and uses it to display the in-depth description
- * of the highlighted object
- */
- void examine();
-
- /**
* Print the name of an object in the scene
*/
void lookScreen(const Common::Point &pt);
@@ -172,6 +166,12 @@ public:
* (not selected) position
*/
void restoreButton(int num);
+
+ /**
+ * Creates a text window and uses it to display the in-depth description
+ * of the highlighted object
+ */
+ void examine();
public:
/**
* Resets the user interface
diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp
index 66a66ba..2a13b2a 100644
--- a/engines/sherlock/tattoo/tattoo_scene.cpp
+++ b/engines/sherlock/tattoo/tattoo_scene.cpp
@@ -229,7 +229,6 @@ void TattooScene::doBgAnim() {
}
void TattooScene::doBgAnimUpdateBgObjectsAndAnim() {
- TattooEngine &vm = *((TattooEngine *)_vm);
People &people = *_vm->_people;
Screen &screen = *_vm->_screen;
@@ -244,7 +243,7 @@ void TattooScene::doBgAnimUpdateBgObjectsAndAnim() {
people[idx].adjustSprite();
}
- if (_activeCAnim._images != nullptr && _activeCAnim._zPlacement != REMOVE) {
+ if ((_activeCAnim._images != nullptr) && (_activeCAnim._zPlacement != REMOVE)) {
_activeCAnim.getNextFrame();
}
Commit: a3008e8f010704207f39a857641be3d4c564ccb1
https://github.com/scummvm/scummvm/commit/a3008e8f010704207f39a857641be3d4c564ccb1
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2015-05-30T19:18:29+02:00
Commit Message:
FMOPL: Fix confusing "opl_driver" behavior
The way I've configured ScummVM, the default is to use FluidSynth
for MIDI, and any game where I want AdLib overrides that setting.
I have set the DOSBox OPL emulator as the default.
However, this causes the game's "opl_driver" setting to be "auto",
which overrides the default setting, and usually picks the MAME
OPL emulator. To counter this, if it sees that "opl_driver" is
"auto", it will check the default setting.
In other words, only use "auto" if "opl_driver" isn't set on any
level. I think this is the behaviour that should cause the least
amount of astonishment.
Changed paths:
audio/fmopl.cpp
diff --git a/audio/fmopl.cpp b/audio/fmopl.cpp
index c18e544..30229ea 100644
--- a/audio/fmopl.cpp
+++ b/audio/fmopl.cpp
@@ -80,6 +80,12 @@ Config::DriverId Config::detect(OplType type) {
}
DriverId drv = parse(ConfMan.get("opl_driver"));
+ if (drv == kAuto) {
+ // Since the "auto" can be explicitly set for a game, and this
+ // driver shows up in the GUI as "<default>", check if there is
+ // a global setting for it before resorting to auto-detection.
+ drv = parse(ConfMan.get("opl_driver", Common::ConfigManager::kApplicationDomain));
+ }
// When a valid driver is selected, check whether it supports
// the requested OPL chip.
Commit: 8b9de5cdc9e59e1eee634f636c0c415044361c7a
https://github.com/scummvm/scummvm/commit/8b9de5cdc9e59e1eee634f636c0c415044361c7a
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-05-30T20:15:20+02:00
Commit Message:
SHERLOCK: implement SysEx 0xFC loop/not loop
Changed paths:
engines/sherlock/music.cpp
diff --git a/engines/sherlock/music.cpp b/engines/sherlock/music.cpp
index 884fbd6..cc66f4c 100644
--- a/engines/sherlock/music.cpp
+++ b/engines/sherlock/music.cpp
@@ -134,6 +134,8 @@ void MidiParser_SH::parseNextEvent(EventInfo &info) {
break;
case 0xF:
if (info.event == 0xFF) {
+ warning("SysEx 0xFF");
+
byte type = *(_position._playPos++);
switch(type) {
case 0x2F:
@@ -150,10 +152,24 @@ void MidiParser_SH::parseNextEvent(EventInfo &info) {
break;
}
} else if (info.event == 0xFC) {
- allNotesOff();
- stopPlaying();
- unloadMusic();
- return;
+ // Official End-Of-Track signal
+ warning("SysEx 0xFC");
+
+ byte type = *(_position._playPos++);
+ switch (type) {
+ case 0x80: // end of track, triggers looping
+ warning("SysEx triggered looping");
+ jumpToTick(0, true, true, false);
+ break;
+ case 0x81: // end of track, stop playing
+ warning("SysEx triggered music stop");
+ stopPlaying();
+ unloadMusic();
+ break;
+ default:
+ error("MidiParser_SH::parseNextEvent: Unknown SysEx 0xFC type %x", type);
+ break;
+ }
} else {
warning("TODO: %x / Unknown", info.event);
break;
Commit: 3dd81bfb355542f27a589ec1267fc495588e3734
https://github.com/scummvm/scummvm/commit/3dd81bfb355542f27a589ec1267fc495588e3734
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-05-30T20:26:03+02:00
Commit Message:
SHERLOCK: renamed SysEx to System META event
Changed paths:
engines/sherlock/music.cpp
diff --git a/engines/sherlock/music.cpp b/engines/sherlock/music.cpp
index cc66f4c..3c85f63 100644
--- a/engines/sherlock/music.cpp
+++ b/engines/sherlock/music.cpp
@@ -153,21 +153,21 @@ void MidiParser_SH::parseNextEvent(EventInfo &info) {
}
} else if (info.event == 0xFC) {
// Official End-Of-Track signal
- warning("SysEx 0xFC");
+ warning("System META event 0xFC");
byte type = *(_position._playPos++);
switch (type) {
case 0x80: // end of track, triggers looping
- warning("SysEx triggered looping");
+ warning("META event triggered looping");
jumpToTick(0, true, true, false);
break;
case 0x81: // end of track, stop playing
- warning("SysEx triggered music stop");
+ warning("META event triggered music stop");
stopPlaying();
unloadMusic();
break;
default:
- error("MidiParser_SH::parseNextEvent: Unknown SysEx 0xFC type %x", type);
+ error("MidiParser_SH::parseNextEvent: Unknown META event 0xFC type %x", type);
break;
}
} else {
Commit: f3d1ffdaaf74b3ca1b01da16ec85d44d054e2f92
https://github.com/scummvm/scummvm/commit/f3d1ffdaaf74b3ca1b01da16ec85d44d054e2f92
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-05-30T21:01:59+02:00
Commit Message:
SHERLOCK: adlib: add support for percussion
Changed paths:
engines/sherlock/scalpel/drivers/adlib.cpp
diff --git a/engines/sherlock/scalpel/drivers/adlib.cpp b/engines/sherlock/scalpel/drivers/adlib.cpp
index 2a56d6a..ca11012 100644
--- a/engines/sherlock/scalpel/drivers/adlib.cpp
+++ b/engines/sherlock/scalpel/drivers/adlib.cpp
@@ -45,6 +45,24 @@ byte adlib_Operator2Register[SHERLOCK_ADLIB_VOICES_COUNT] = {
0x03, 0x04, 0x05, 0x0B, 0x0C, 0x0D, 0x13, 0x14, 0x15
};
+struct adlib_percussionChannelEntry {
+ byte requiredNote;
+ byte replacementNote;
+};
+
+// hardcoded, dumped from ADHOM.DRV
+const adlib_percussionChannelEntry adlib_percussionChannelTable[SHERLOCK_ADLIB_VOICES_COUNT] = {
+ { 0x00, 0x00 },
+ { 0x00, 0x00 },
+ { 0x00, 0x00 },
+ { 0x00, 0x00 },
+ { 0x00, 0x00 },
+ { 0x00, 0x00 },
+ { 0x24, 0x0C },
+ { 0x38, 0x01 },
+ { 0x26, 0x1E }
+};
+
struct adlib_InstrumentEntry {
byte reg20op1;
byte reg40op1;
@@ -433,8 +451,24 @@ void MidiDriver_AdLib::noteOn(byte MIDIchannel, byte note, byte velocity) {
}
}
}
+ warning("MIDI channel not mapped/all FM voice channels busy %d", MIDIchannel);
+ } else {
+ // Percussion channel
+ warning("percussion!");
+ for (byte FMvoiceChannel = 0; FMvoiceChannel < SHERLOCK_ADLIB_VOICES_COUNT; FMvoiceChannel++) {
+ if (_voiceChannelMapping[FMvoiceChannel] == MIDIchannel) {
+ if (note == adlib_percussionChannelTable[FMvoiceChannel].requiredNote) {
+ _channels[FMvoiceChannel].inUse = true;
+ _channels[FMvoiceChannel].currentNote = note;
+
+ voiceOnOff(FMvoiceChannel, true, adlib_percussionChannelTable[FMvoiceChannel].replacementNote, velocity);
+ return;
+ }
+ }
+ }
+ // TODO: driver does some extra things in case no channel is found
+ warning("percussion MIDI channel not mapped/all FM voice channels busy");
}
- warning("MIDI channel not mapped/all FM voice channels busy %d", MIDIchannel);
}
void MidiDriver_AdLib::noteOff(byte MIDIchannel, byte note) {
@@ -444,7 +478,12 @@ void MidiDriver_AdLib::noteOff(byte MIDIchannel, byte note) {
_channels[FMvoiceChannel].inUse = false;
_channels[FMvoiceChannel].currentNote = 0;
- voiceOnOff(FMvoiceChannel, false, note, 0);
+ if (MIDIchannel != 9) {
+ // not-percussion
+ voiceOnOff(FMvoiceChannel, false, note, 0);
+ } else {
+ voiceOnOff(FMvoiceChannel, false, adlib_percussionChannelTable[FMvoiceChannel].replacementNote, 0);
+ }
return;
}
}
Commit: 52ca97fe63aa1032d32fefab4397df34b825e63b
https://github.com/scummvm/scummvm/commit/52ca97fe63aa1032d32fefab4397df34b825e63b
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-05-30T22:56:13+02:00
Commit Message:
SHERLOCK: midiparser block META event 0xFF for now
Changed paths:
engines/sherlock/music.cpp
diff --git a/engines/sherlock/music.cpp b/engines/sherlock/music.cpp
index 3c85f63..c793b4a 100644
--- a/engines/sherlock/music.cpp
+++ b/engines/sherlock/music.cpp
@@ -134,7 +134,7 @@ void MidiParser_SH::parseNextEvent(EventInfo &info) {
break;
case 0xF:
if (info.event == 0xFF) {
- warning("SysEx 0xFF");
+ error("SysEx META event 0xFF");
byte type = *(_position._playPos++);
switch(type) {
Commit: fd33a100a12f4cb5256e5060a231012f17284261
https://github.com/scummvm/scummvm/commit/fd33a100a12f4cb5256e5060a231012f17284261
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-30T17:55:22-04:00
Commit Message:
SHERLOCK: Beginnings of Scalpel logo display
Changed paths:
A engines/sherlock/scalpel/tsage/logo.cpp
A engines/sherlock/scalpel/tsage/logo.h
A engines/sherlock/scalpel/tsage/resources.cpp
A engines/sherlock/scalpel/tsage/resources.h
engines/sherlock/module.mk
engines/sherlock/resources.cpp
engines/sherlock/scalpel/scalpel.cpp
diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk
index 9ebe416..1a38d56 100644
--- a/engines/sherlock/module.mk
+++ b/engines/sherlock/module.mk
@@ -4,6 +4,8 @@ MODULE_OBJS = \
scalpel/darts.o \
scalpel/scalpel.o \
scalpel/drivers/adlib.o \
+ scalpel/tsage/logo.o \
+ scalpel/tsage/resources.o \
scalpel/scalpel_scene.o \
scalpel/scalpel_user_interface.o \
scalpel/settings.o \
diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp
index f1c705b..2e6a0c2 100644
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@ -255,7 +255,7 @@ Common::SeekableReadStream *Resources::decompress(Common::SeekableReadStream &so
}
Common::SeekableReadStream *Resources::decompress(Common::SeekableReadStream &source, uint32 outSize) {
- int inSize = (_vm->getGameID() == GType_RoseTattoo) ? source.readUint32LE() : -1;
+ int inSize = (_vm->getGameID() == GType_RoseTattoo) ? source.readSint32LE() : -1;
byte *outBuffer = (byte *)malloc(outSize);
Common::MemoryReadStream *outStream = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
@@ -265,7 +265,7 @@ Common::SeekableReadStream *Resources::decompress(Common::SeekableReadStream &so
}
void Resources::decompress(Common::SeekableReadStream &source, byte *buffer, uint32 outSize) {
- int inputSize = (_vm->getGameID() == GType_RoseTattoo) ? source.readUint32LE() : -1;
+ int inputSize = (_vm->getGameID() == GType_RoseTattoo) ? source.readSint32LE() : -1;
decompressLZ(source, buffer, outSize, inputSize);
}
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index 304445d..43b6906 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -20,11 +20,12 @@
*
*/
+#include "engines/util.h"
#include "sherlock/scalpel/scalpel.h"
+#include "sherlock/scalpel/tsage/logo.h"
#include "sherlock/sherlock.h"
#include "sherlock/music.h"
#include "sherlock/animation.h"
-#include "engines/util.h"
namespace Sherlock {
@@ -423,6 +424,8 @@ void ScalpelEngine::showOpening() {
if (isDemo() && _interactiveFl)
return;
+ if (!TsAGE::Logo::show(this))
+ return;
if (!showCityCutscene())
return;
if (!showAlleyCutscene())
diff --git a/engines/sherlock/scalpel/tsage/logo.cpp b/engines/sherlock/scalpel/tsage/logo.cpp
new file mode 100644
index 0000000..fb85662
--- /dev/null
+++ b/engines/sherlock/scalpel/tsage/logo.cpp
@@ -0,0 +1,139 @@
+/* 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 "common/scummsys.h"
+#include "sherlock/scalpel/tsage/logo.h"
+#include "sherlock/scalpel/scalpel.h"
+
+namespace Sherlock {
+namespace Scalpel {
+namespace TsAGE {
+
+bool Logo::show(ScalpelEngine *vm) {
+ Events &events = *vm->_events;
+ Logo *logo = new Logo(vm);
+ bool interrupted = false;
+
+ while (!logo->finished()) {
+ logo->nextFrame();
+
+ events.wait(2);
+ events.setButtonState();
+
+ interrupted = vm->shouldQuit() || events.kbHit() || events._pressed;
+ if (interrupted) {
+ events.clearEvents();
+ break;
+ }
+ }
+
+ delete logo;
+ return !interrupted;
+}
+
+Logo::Logo(ScalpelEngine *vm) : _vm(vm), _lib("sf3.rlb"), _surface(vm->_screen->w(), vm->_screen->h()) {
+ // Initialize frame counter
+ _counter = 0;
+
+ // Set up the palettes
+ Common::fill(&_palette1[0], &_palette1[PALETTE_SIZE], 0);
+ Common::fill(&_palette1[0], &_palette2[PALETTE_SIZE], 0);
+ Common::fill(&_palette1[0], &_palette3[PALETTE_SIZE], 0);
+
+ _lib.getPalette(_palette1, 1111);
+ _lib.getPalette(_palette1, 10);
+ _lib.getPalette(_palette2, 1111);
+ _lib.getPalette(_palette2, 1);
+ _lib.getPalette(_palette3, 1111);
+ _lib.getPalette(_palette3, 14);
+}
+
+bool Logo::finished() const {
+ return false;
+}
+
+void Logo::nextFrame() {
+
+ switch (_counter++) {
+ case 0:
+ loadBackground();
+ fade(_palette1);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void Logo::loadBackground() {
+ Screen &screen = *_vm->_screen;
+
+ for (int idx = 0; idx < 4; ++idx) {
+ // Get the portion of the screen
+ Common::SeekableReadStream *stream = _lib.getResource(RES_BITMAP, 10, idx);
+
+ // Load it onto the surface
+ Common::Point pt((idx / 2) * (_surface.w() / 2), (idx % 2) * (_surface.h() / 2));
+ for (int y = 0; y < (_surface.h() / 2); ++y, ++pt.y) {
+ byte *pDest = (byte *)_surface.getBasePtr(pt.x, pt.y);
+ stream->read(pDest, _surface.w() / 2);
+ }
+
+ // _backgroundBounds = Rect(0, 0, READ_LE_UINT16(data), READ_LE_UINT16(data + 2));
+ delete stream;
+ }
+
+ // Default to a blank palette
+ byte palette[PALETTE_SIZE];
+ Common::fill(&palette[0], &palette[PALETTE_SIZE], 0);
+ screen.setPalette(palette);
+
+ // Copy the surface to the screen
+ screen.blitFrom(_surface);
+}
+
+void Logo::fade(const byte palette[PALETTE_SIZE]) {
+ Events &events = *_vm->_events;
+ Screen &screen = *_vm->_screen;
+ byte tempPalette[PALETTE_SIZE];
+
+ for (int percent = 0; percent < 100; percent += 6) {
+ for (int palIndex = 0; palIndex < 256; ++palIndex) {
+ const byte *palP = (const byte *)&palette[palIndex * 3];
+ byte *destP = &tempPalette[palIndex * 3];
+
+ for (int rgbIndex = 0; rgbIndex < 3; ++rgbIndex, ++palP, ++destP) {
+ *destP = (int)*palP * percent / 100;
+ }
+ }
+
+ screen.setPalette(tempPalette);
+ events.wait(1);
+ }
+
+ // Set final palette
+ screen.setPalette(palette);
+}
+
+} // end of namespace TsAGE
+} // end of namespace Scalpel
+} // end of namespace Sherlock
diff --git a/engines/sherlock/scalpel/tsage/logo.h b/engines/sherlock/scalpel/tsage/logo.h
new file mode 100644
index 0000000..4adbe95
--- /dev/null
+++ b/engines/sherlock/scalpel/tsage/logo.h
@@ -0,0 +1,77 @@
+/* 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.
+ *
+ */
+
+#ifndef SHERLOCK_SCALPEL_TSAGE_LOGO_H
+#define SHERLOCK_SCALPEL_TSAGE_LOGO_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/file.h"
+#include "common/list.h"
+#include "common/str.h"
+#include "common/str-array.h"
+#include "common/util.h"
+#include "graphics/surface.h"
+#include "sherlock/scalpel/tsage/resources.h"
+#include "sherlock/screen.h"
+
+namespace Sherlock {
+namespace Scalpel {
+
+class ScalpelEngine;
+
+namespace TsAGE {
+
+class Logo {
+private:
+ ScalpelEngine *_vm;
+ TLib _lib;
+ Surface _surface;
+ int _counter;
+ byte _palette1[PALETTE_SIZE];
+ byte _palette2[PALETTE_SIZE];
+ byte _palette3[PALETTE_SIZE];
+
+ Logo(ScalpelEngine *vm);
+
+ void nextFrame();
+
+ bool finished() const;
+
+ /**
+ * Load the background for the scene
+ */
+ void loadBackground();
+
+ /**
+ * Fade from the current palette to a new one
+ */
+ void fade(const byte palette[PALETTE_SIZE]);
+public:
+ static bool show(ScalpelEngine *vm);
+};
+
+} // end of namespace TsAGE
+} // end of namespace Scalpel
+} // end of namespace Sherlock
+
+#endif
diff --git a/engines/sherlock/scalpel/tsage/resources.cpp b/engines/sherlock/scalpel/tsage/resources.cpp
new file mode 100644
index 0000000..56b7021
--- /dev/null
+++ b/engines/sherlock/scalpel/tsage/resources.cpp
@@ -0,0 +1,373 @@
+/* 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 "common/scummsys.h"
+#include "common/memstream.h"
+#include "common/stack.h"
+#include "sherlock/scalpel/tsage/resources.h"
+
+namespace Sherlock {
+namespace Scalpel {
+namespace TsAGE {
+
+static uint16 bitMasks[4] = {0x1ff, 0x3ff, 0x7ff, 0xfff};
+
+uint16 BitReader::readToken() {
+ assert((numBits >= 9) && (numBits <= 12));
+ uint16 result = _remainder;
+ int bitsLeft = numBits - _bitsLeft;
+ int bitOffset = _bitsLeft;
+ _bitsLeft = 0;
+
+ while (bitsLeft >= 0) {
+ _remainder = readByte();
+ result |= _remainder << bitOffset;
+ bitsLeft -= 8;
+ bitOffset += 8;
+ }
+
+ _bitsLeft = -bitsLeft;
+ _remainder >>= 8 - _bitsLeft;
+ return result & bitMasks[numBits - 9];
+}
+
+/*-------------------------------------------------------------------------*/
+
+TLib::TLib(const Common::String &filename) : _filename(filename) {
+
+ // If the resource strings list isn't yet loaded, load them
+ if (_resStrings.size() == 0) {
+ Common::File f;
+ if (f.open("tsage.cfg")) {
+ while (!f.eos()) {
+ _resStrings.push_back(f.readLine());
+ }
+ f.close();
+ }
+ }
+
+ if (!_file.open(filename))
+ error("Missing file %s", filename.c_str());
+
+ loadIndex();
+}
+
+TLib::~TLib() {
+ _resStrings.clear();
+}
+
+/**
+ * Load a section index from the given position in the file
+ */
+void TLib::loadSection(uint32 fileOffset) {
+ _resources.clear();
+ _file.seek(fileOffset);
+ _sections.fileOffset = fileOffset;
+
+ loadSection(_file, _resources);
+}
+
+struct DecodeReference {
+ uint16 vWord;
+ uint8 vByte;
+};
+
+/**
+ * Gets a resource from the currently loaded section
+ */
+Common::SeekableReadStream *TLib::getResource(uint16 id, bool suppressErrors) {
+ // Scan for an entry for the given Id
+ ResourceEntry *re = nullptr;
+ ResourceList::iterator iter;
+ for (iter = _resources.begin(); iter != _resources.end(); ++iter) {
+ if ((*iter).id == id) {
+ re = &(*iter);
+ break;
+ }
+ }
+ if (!re) {
+ if (suppressErrors)
+ return nullptr;
+ error("Could not find resource Id #%d", id);
+ }
+
+ if (!re->isCompressed) {
+ // Read in the resource data and return it
+ byte *dataP = (byte *)malloc(re->size);
+ _file.seek(_sections.fileOffset + re->fileOffset);
+ _file.read(dataP, re->size);
+
+ return new Common::MemoryReadStream(dataP, re->size, DisposeAfterUse::YES);
+ }
+
+ /*
+ * Decompress the data block
+ */
+
+ _file.seek(_sections.fileOffset + re->fileOffset);
+ Common::ReadStream *compStream = _file.readStream(re->size);
+ BitReader bitReader(*compStream);
+
+ byte *dataOut = (byte *)malloc(re->uncompressedSize);
+ byte *destP = dataOut;
+ uint bytesWritten = 0;
+
+ uint16 ctrCurrent = 0x102, ctrMax = 0x200;
+ uint16 word_48050 = 0, currentToken = 0, word_48054 =0;
+ byte byte_49068 = 0, byte_49069 = 0;
+
+ const uint tableSize = 0x1000;
+ DecodeReference *table = (DecodeReference *)malloc(tableSize * sizeof(DecodeReference));
+ if (!table)
+ error("[TLib::getResource] Cannot allocate table buffer");
+
+ for (uint i = 0; i < tableSize; ++i) {
+ table[i].vByte = table[i].vWord = 0;
+ }
+ Common::Stack<uint16> tokenList;
+
+ for (;;) {
+ // Get the next decode token
+ uint16 token = bitReader.readToken();
+
+ // Handle the token
+ if (token == 0x101) {
+ // End of compressed stream
+ break;
+ } else if (token == 0x100) {
+ // Reset bit-rate
+ bitReader.numBits = 9;
+ ctrMax = 0x200;
+ ctrCurrent = 0x102;
+
+ // Set variables with next token
+ currentToken = word_48050 = bitReader.readToken();
+ byte_49069 = byte_49068 = (byte)currentToken;
+
+ ++bytesWritten;
+ assert(bytesWritten <= re->uncompressedSize);
+ *destP++ = byte_49069;
+ } else {
+ word_48054 = word_48050 = token;
+
+ if (token >= ctrCurrent) {
+ word_48050 = currentToken;
+ tokenList.push(byte_49068);
+ }
+
+ while (word_48050 >= 0x100) {
+ assert(word_48050 < 0x1000);
+ tokenList.push(table[word_48050].vByte);
+ word_48050 = table[word_48050].vWord;
+ }
+
+ byte_49069 = byte_49068 = (byte)word_48050;
+ tokenList.push(word_48050);
+
+ // Write out any cached tokens
+ while (!tokenList.empty()) {
+ ++bytesWritten;
+ assert(bytesWritten <= re->uncompressedSize);
+ *destP++ = tokenList.pop();
+ }
+
+ assert(ctrCurrent < 0x1000);
+ table[ctrCurrent].vByte = byte_49069;
+ table[ctrCurrent].vWord = currentToken;
+ ++ctrCurrent;
+
+ currentToken = word_48054;
+ if ((ctrCurrent >= ctrMax) && (bitReader.numBits != 12)) {
+ // Move to the next higher bit-rate
+ ++bitReader.numBits;
+ ctrMax <<= 1;
+ }
+ }
+ }
+
+ free(table);
+
+ assert(bytesWritten == re->uncompressedSize);
+ delete compStream;
+ return new Common::MemoryReadStream(dataOut, re->uncompressedSize, DisposeAfterUse::YES);
+}
+
+/**
+ * Finds the correct section and loads the specified resource within it
+ */
+Common::SeekableReadStream *TLib::getResource(ResourceType resType, uint16 resNum, uint16 rlbNum, bool suppressErrors) {
+ SectionList::iterator i = _sections.begin();
+ while ((i != _sections.end()) && ((*i).resType != resType || (*i).resNum != resNum))
+ ++i;
+ if (i == _sections.end()) {
+ if (suppressErrors)
+ return nullptr;
+ error("Unknown resource type %d num %d", resType, resNum);
+ }
+
+ loadSection((*i).fileOffset);
+
+ return getResource(rlbNum, suppressErrors);
+}
+
+/**
+ * Gets the offset of the start of a resource in the resource file
+ */
+uint32 TLib::getResourceStart(ResourceType resType, uint16 resNum, uint16 rlbNum, ResourceEntry &entry) {
+ // Find the correct section
+ SectionList::iterator i = _sections.begin();
+ while ((i != _sections.end()) && ((*i).resType != resType || (*i).resNum != resNum))
+ ++i;
+ if (i == _sections.end()) {
+ error("Unknown resource type %d num %d", resType, resNum);
+ }
+
+ // Load in the section index
+ loadSection((*i).fileOffset);
+
+ // Scan for an entry for the given Id
+ ResourceEntry *re = nullptr;
+ ResourceList::iterator iter;
+ for (iter = _resources.begin(); iter != _resources.end(); ++iter) {
+ if ((*iter).id == rlbNum) {
+ re = &(*iter);
+ break;
+ }
+ }
+
+ // Throw an error if no resource was found, or the resource is compressed
+ if (!re || re->isCompressed)
+ error("Invalid resource Id #%d", rlbNum);
+
+ // Return the resource entry as well as the file offset
+ entry = *re;
+ return _sections.fileOffset + entry.fileOffset;
+}
+
+void TLib::loadIndex() {
+ uint16 resNum, configId, fileOffset;
+
+ // Load the root resources section
+ loadSection(0);
+
+ // Get the single resource from it
+ Common::SeekableReadStream *stream = getResource(0);
+
+ _sections.clear();
+
+ // Loop through reading the entries
+ while ((resNum = stream->readUint16LE()) != 0xffff) {
+ configId = stream->readUint16LE();
+ fileOffset = stream->readUint16LE();
+
+ SectionEntry se;
+ se.resNum = resNum;
+ se.resType = (ResourceType)(configId & 0x1f);
+ se.fileOffset = (((configId >> 5) & 0x7ff) << 16) | fileOffset;
+
+ _sections.push_back(se);
+ }
+
+ delete stream;
+}
+
+/**
+ * Retrieves the specified palette resource and returns it's data
+ *
+ * @paletteNum Specefies the palette number
+ */
+void TLib::getPalette(byte palette[PALETTE_SIZE], int paletteNum) {
+ // Get the specified palette
+ Common::SeekableReadStream *stream = getResource(RES_PALETTE, paletteNum, 0, true);
+ if (!stream)
+ return;
+
+ int startNum = stream->readUint16LE();
+ int numEntries = stream->readUint16LE();
+ assert((startNum < 256) && ((startNum + numEntries) <= 256));
+ stream->skip(2);
+
+ // Copy over the data
+ stream->read(&palette[startNum * 3], numEntries * 3);
+
+ delete stream;
+}
+
+/**
+ * Open up the given resource file using a passed file object. If the desired entry is found
+ * in the index, return the index entry for it, and move the file to the start of the resource
+ */
+bool TLib::scanIndex(Common::File &f, ResourceType resType, int rlbNum, int resNum,
+ ResourceEntry &resEntry) {
+ // Load the root section index
+ ResourceList resList;
+ loadSection(f, resList);
+
+ // Loop through the index for the desired entry
+ ResourceList::iterator iter;
+ for (iter = resList.begin(); iter != resList.end(); ++iter) {
+ ResourceEntry &re = *iter;
+ if (re.id == resNum) {
+ // Found it, so exit
+ resEntry = re;
+ f.seek(re.fileOffset);
+ return true;
+ }
+ }
+
+ // No matching entry found
+ return false;
+}
+
+/**
+ * Inner logic for decoding a section index into a passed resource list object
+ */
+void TLib::loadSection(Common::File &f, ResourceList &resources) {
+ if (f.readUint32BE() != 0x544D492D)
+ error("Data block is not valid Rlb data");
+
+ /*uint8 unknown1 = */f.readByte();
+ uint16 numEntries = f.readByte();
+
+ for (uint i = 0; i < numEntries; ++i) {
+ uint16 id = f.readUint16LE();
+ uint16 size = f.readUint16LE();
+ uint16 uncSize = f.readUint16LE();
+ uint8 sizeHi = f.readByte();
+ uint8 type = f.readByte() >> 5;
+ assert(type <= 1);
+ uint32 offset = f.readUint32LE();
+
+ ResourceEntry re;
+ re.id = id;
+ re.fileOffset = offset;
+ re.isCompressed = type != 0;
+ re.size = ((sizeHi & 0xF) << 16) | size;
+ re.uncompressedSize = ((sizeHi & 0xF0) << 12) | uncSize;
+
+ resources.push_back(re);
+ }
+}
+
+} // end of namespace TsAGE
+} // end of namespace Scalpel
+} // end of namespace Sherlock
diff --git a/engines/sherlock/scalpel/tsage/resources.h b/engines/sherlock/scalpel/tsage/resources.h
new file mode 100644
index 0000000..3e09b6b
--- /dev/null
+++ b/engines/sherlock/scalpel/tsage/resources.h
@@ -0,0 +1,139 @@
+/* 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.
+ *
+ */
+
+#ifndef SHERLOCK_SCALPEL_TSAGE_RESOURCES_H
+#define SHERLOCK_SCALPEL_TSAGE_RESOURCES_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/file.h"
+#include "common/list.h"
+#include "common/str.h"
+#include "common/str-array.h"
+#include "common/util.h"
+#include "graphics/surface.h"
+#include "sherlock/screen.h"
+
+namespace Sherlock {
+namespace Scalpel {
+namespace TsAGE {
+
+// Magic number used by original game to identify valid memory blocks
+const uint32 MEMORY_ENTRY_ID = 0xE11DA722;
+
+const int MEMORY_POOL_SIZE = 1000;
+
+enum ResourceType { RES_LIBRARY, RES_STRIP, RES_IMAGE, RES_PALETTE, RES_VISAGE, RES_SOUND, RES_MESSAGE,
+ RES_FONT, RES_POINTER, RES_BANK, RES_SND_DRIVER, RES_PRIORITY, RES_CONTROL, RES_WALKRGNS,
+ RES_BITMAP, RES_SAVE, RES_SEQUENCE,
+ // Return to Ringworld specific resource types
+ RT17, RT18, RT19, RT20, RT21, RT22, RT23, RT24, RT25, RT26, RT27, RT28, RT29, RT30, RT31
+};
+
+class SectionEntry {
+public:
+ ResourceType resType;
+ uint16 resNum;
+ uint32 fileOffset;
+
+ SectionEntry() {
+ resType = RES_LIBRARY;
+ resNum = 0;
+ fileOffset = 0;
+ }
+};
+
+class ResourceEntry {
+public:
+ uint16 id;
+ bool isCompressed;
+ uint32 fileOffset;
+ uint32 size;
+ uint32 uncompressedSize;
+
+ ResourceEntry() {
+ id = 0;
+ isCompressed = false;
+ fileOffset = 0;
+ size = 0;
+ uncompressedSize = 0;
+ }
+};
+
+typedef Common::List<ResourceEntry> ResourceList;
+
+class SectionList : public Common::List<SectionEntry> {
+public:
+ uint32 fileOffset;
+
+ SectionList() {
+ fileOffset = 0;
+ }
+};
+
+class BitReader {
+private:
+ Common::ReadStream &_stream;
+ uint8 _remainder, _bitsLeft;
+ byte readByte() { return _stream.eos() ? 0 : _stream.readByte(); }
+public:
+ BitReader(Common::ReadStream &s) : _stream(s) {
+ numBits = 9;
+ _remainder = 0;
+ _bitsLeft = 0;
+ }
+ uint16 readToken();
+
+ int numBits;
+};
+
+class TLib {
+private:
+ Common::StringArray _resStrings;
+private:
+ Common::File _file;
+ Common::String _filename;
+ ResourceList _resources;
+ SectionList _sections;
+
+ void loadSection(uint32 fileOffset);
+ void loadIndex();
+
+ static bool scanIndex(Common::File &f, ResourceType resType, int rlbNum, int resNum, ResourceEntry &resEntry);
+ static void loadSection(Common::File &f, ResourceList &resources);
+public:
+ TLib(const Common::String &filename);
+ ~TLib();
+
+ const Common::String &getFilename() { return _filename; }
+ const SectionList &getSections() { return _sections; }
+ Common::SeekableReadStream *getResource(uint16 id, bool suppressErrors = false);
+ Common::SeekableReadStream *getResource(ResourceType resType, uint16 resNum, uint16 rlbNum, bool suppressErrors = false);
+ uint32 getResourceStart(ResourceType resType, uint16 resNum, uint16 rlbNum, ResourceEntry &entry);
+ void getPalette(byte palette[PALETTE_SIZE], int paletteNum);
+};
+
+} // end of namespace TsAGE
+} // end of namespace Scalpel
+} // end of namespace Sherlock
+
+#endif
Commit: 9da6a9071398711b05790c9a5c3b3cdbe125032c
https://github.com/scummvm/scummvm/commit/9da6a9071398711b05790c9a5c3b3cdbe125032c
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-05-31T00:34:29+02:00
Commit Message:
SHERLOCK: adlib: implement in-use-channel usage
Changed paths:
engines/sherlock/scalpel/drivers/adlib.cpp
diff --git a/engines/sherlock/scalpel/drivers/adlib.cpp b/engines/sherlock/scalpel/drivers/adlib.cpp
index ca11012..c1dbddb 100644
--- a/engines/sherlock/scalpel/drivers/adlib.cpp
+++ b/engines/sherlock/scalpel/drivers/adlib.cpp
@@ -221,7 +221,7 @@ uint16 adlib_FrequencyLookUpTable[SHERLOCK_ADLIB_NOTES_COUNT] = {
class MidiDriver_AdLib : public MidiDriver_Emulated {
public:
MidiDriver_AdLib(Audio::Mixer *mixer)
- : MidiDriver_Emulated(mixer), _masterVolume(15), _rhythmKeyMap(0), _opl(0) {
+ : MidiDriver_Emulated(mixer), _masterVolume(15), _opl(0) {
memset(_voiceChannelMapping, 0, sizeof(_voiceChannelMapping));
}
virtual ~MidiDriver_AdLib() { }
@@ -245,25 +245,23 @@ public:
void setVolume(byte volume);
virtual uint32 property(int prop, uint32 param);
- bool useRhythmChannel() const { return _rhythmKeyMap != NULL; }
-
void newMusicData(byte *musicData, int32 musicDataSize);
private:
struct adlib_ChannelEntry {
- bool inUse;
- const adlib_InstrumentEntry *currentInstrumentPtr;
- byte currentNote;
- byte currentA0hReg;
- byte currentB0hReg;
-
- adlib_ChannelEntry() : inUse(false), currentInstrumentPtr(NULL), currentNote(0),
+ bool inUse;
+ uint16 inUseTimer;
+ const adlib_InstrumentEntry *currentInstrumentPtr;
+ byte currentNote;
+ byte currentA0hReg;
+ byte currentB0hReg;
+
+ adlib_ChannelEntry() : inUse(false), inUseTimer(0), currentInstrumentPtr(NULL), currentNote(0),
currentA0hReg(0), currentB0hReg(0) { }
};
OPL::OPL *_opl;
int _masterVolume;
- byte *_rhythmKeyMap;
// points to a MIDI channel for each of the new voice channels
byte _voiceChannelMapping[SHERLOCK_ADLIB_VOICES_COUNT];
@@ -271,6 +269,8 @@ private:
// stores information about all FM voice channels
adlib_ChannelEntry _channels[SHERLOCK_ADLIB_VOICES_COUNT];
+ void updateChannelInUseTimers();
+
void resetAdLib();
void resetAdLib_OperatorRegisters(byte baseRegister, byte value);
void resetAdLib_FMVoiceChannelRegisters(byte baseRegister, byte value);
@@ -330,7 +330,6 @@ void MidiDriver_AdLib::close() {
_mixer->stopHandle(_mixerSoundHandle);
delete _opl;
- delete[] _rhythmKeyMap;
}
void MidiDriver_AdLib::setVolume(byte volume) {
@@ -338,6 +337,17 @@ void MidiDriver_AdLib::setVolume(byte volume) {
//renewNotes(-1, true);
}
+// this should normally get called per tick
+// but calling it per send() shouldn't be a problem
+// TODO: maybe change inUseTimer to a 32-bit integer to make sure there are no overruns?!?!
+void MidiDriver_AdLib::updateChannelInUseTimers() {
+ for (byte FMvoiceChannel = 0; FMvoiceChannel < SHERLOCK_ADLIB_VOICES_COUNT; FMvoiceChannel++) {
+ if (_channels[FMvoiceChannel].inUse) {
+ _channels[FMvoiceChannel].inUseTimer++;
+ }
+ }
+}
+
// Called when a music track got loaded into memory
void MidiDriver_AdLib::newMusicData(byte *musicData, int32 musicDataSize) {
assert(musicDataSize >= 0x7F);
@@ -401,6 +411,8 @@ void MidiDriver_AdLib::send(uint32 b) {
byte op1 = (b >> 8) & 0xff;
byte op2 = (b >> 16) & 0xff;
+ updateChannelInUseTimers();
+
switch (command) {
case 0x80:
noteOff(channel, op1);
@@ -435,6 +447,9 @@ void MidiDriver_AdLib::generateSamples(int16 *data, int len) {
}
void MidiDriver_AdLib::noteOn(byte MIDIchannel, byte note, byte velocity) {
+ int16 oldestInUseChannel = -1;
+ uint16 oldestInUseTimer = 0;
+
if (velocity == 0)
return noteOff(MIDIchannel, note);
@@ -451,7 +466,29 @@ void MidiDriver_AdLib::noteOn(byte MIDIchannel, byte note, byte velocity) {
}
}
}
+
+ // Look for oldest in-use channel
+ for (byte FMvoiceChannel = 0; FMvoiceChannel < SHERLOCK_ADLIB_VOICES_COUNT; FMvoiceChannel++) {
+ if (_voiceChannelMapping[FMvoiceChannel] == MIDIchannel) {
+ if (_channels[FMvoiceChannel].inUseTimer > oldestInUseTimer) {
+ oldestInUseTimer = _channels[FMvoiceChannel].inUseTimer;
+ oldestInUseChannel = FMvoiceChannel;
+ }
+ }
+ }
+ if (oldestInUseChannel >= 0) {
+ // channel found
+ warning("used In-Use channel");
+ voiceOnOff(oldestInUseChannel, false, 0, 0);
+
+ _channels[oldestInUseChannel].inUse = true;
+ _channels[oldestInUseChannel].inUseTimer = 0; // safety, original driver also did this
+ _channels[oldestInUseChannel].currentNote = note;
+ voiceOnOff(oldestInUseChannel, true, note, velocity);
+ return;
+ }
warning("MIDI channel not mapped/all FM voice channels busy %d", MIDIchannel);
+
} else {
// Percussion channel
warning("percussion!");
@@ -466,7 +503,6 @@ void MidiDriver_AdLib::noteOn(byte MIDIchannel, byte note, byte velocity) {
}
}
}
- // TODO: driver does some extra things in case no channel is found
warning("percussion MIDI channel not mapped/all FM voice channels busy");
}
}
@@ -476,6 +512,7 @@ void MidiDriver_AdLib::noteOff(byte MIDIchannel, byte note) {
if (_voiceChannelMapping[FMvoiceChannel] == MIDIchannel) {
if (_channels[FMvoiceChannel].currentNote == note) {
_channels[FMvoiceChannel].inUse = false;
+ _channels[FMvoiceChannel].inUseTimer = 0;
_channels[FMvoiceChannel].currentNote = 0;
if (MIDIchannel != 9) {
Commit: ec56344ed706f81df3701b0b18f7194c319fde6c
https://github.com/scummvm/scummvm/commit/ec56344ed706f81df3701b0b18f7194c319fde6c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-30T18:44:48-04:00
Commit Message:
SHERLOCK: Free memory leaks from unreleased sound resources
Changed paths:
engines/sherlock/music.cpp
engines/sherlock/sound.cpp
diff --git a/engines/sherlock/music.cpp b/engines/sherlock/music.cpp
index c793b4a..a97e55d 100644
--- a/engines/sherlock/music.cpp
+++ b/engines/sherlock/music.cpp
@@ -313,6 +313,7 @@ bool Music::playMusic(const Common::String &name) {
assert(data);
stream->read(data, dataSize);
+ delete stream;
// for dumping the music tracks
#if 0
diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp
index e7f4fe8..390576e 100644
--- a/engines/sherlock/sound.cpp
+++ b/engines/sherlock/sound.cpp
@@ -135,6 +135,7 @@ bool Sound::playSound(const Common::String &name, WaitType waitType, int priorit
byte *data = (byte *)malloc(size);
byte *ptr = data;
stream->read(ptr, size);
+ delete stream;
assert(size > 2);
Commit: 6ce9be24046b1cfd886d020758f083155a930155
https://github.com/scummvm/scummvm/commit/6ce9be24046b1cfd886d020758f083155a930155
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-05-31T00:58:49+02:00
Commit Message:
SHERLOCK: adlib: in-use timer, thx LordHoto
Changed paths:
engines/sherlock/scalpel/drivers/adlib.cpp
diff --git a/engines/sherlock/scalpel/drivers/adlib.cpp b/engines/sherlock/scalpel/drivers/adlib.cpp
index c1dbddb..8dee501 100644
--- a/engines/sherlock/scalpel/drivers/adlib.cpp
+++ b/engines/sherlock/scalpel/drivers/adlib.cpp
@@ -269,8 +269,10 @@ private:
// stores information about all FM voice channels
adlib_ChannelEntry _channels[SHERLOCK_ADLIB_VOICES_COUNT];
- void updateChannelInUseTimers();
+protected:
+ void onTimer();
+private:
void resetAdLib();
void resetAdLib_OperatorRegisters(byte baseRegister, byte value);
void resetAdLib_FMVoiceChannelRegisters(byte baseRegister, byte value);
@@ -337,10 +339,10 @@ void MidiDriver_AdLib::setVolume(byte volume) {
//renewNotes(-1, true);
}
-// this should normally get called per tick
-// but calling it per send() shouldn't be a problem
-// TODO: maybe change inUseTimer to a 32-bit integer to make sure there are no overruns?!?!
-void MidiDriver_AdLib::updateChannelInUseTimers() {
+// this should/must get called per tick
+// original driver did this before MIDI data processing on each tick
+// we do it atm after MIDI data processing
+void MidiDriver_AdLib::onTimer() {
for (byte FMvoiceChannel = 0; FMvoiceChannel < SHERLOCK_ADLIB_VOICES_COUNT; FMvoiceChannel++) {
if (_channels[FMvoiceChannel].inUse) {
_channels[FMvoiceChannel].inUseTimer++;
@@ -411,8 +413,6 @@ void MidiDriver_AdLib::send(uint32 b) {
byte op1 = (b >> 8) & 0xff;
byte op2 = (b >> 16) & 0xff;
- updateChannelInUseTimers();
-
switch (command) {
case 0x80:
noteOff(channel, op1);
Commit: 4942571e63589919dada0de3d225e78e60e6dcb6
https://github.com/scummvm/scummvm/commit/4942571e63589919dada0de3d225e78e60e6dcb6
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-05-31T01:04:24+02:00
Commit Message:
SHERLOCK: adlib: fix "in-use" usage voiceOnOff()
Changed paths:
engines/sherlock/scalpel/drivers/adlib.cpp
diff --git a/engines/sherlock/scalpel/drivers/adlib.cpp b/engines/sherlock/scalpel/drivers/adlib.cpp
index 8dee501..29ca1ba 100644
--- a/engines/sherlock/scalpel/drivers/adlib.cpp
+++ b/engines/sherlock/scalpel/drivers/adlib.cpp
@@ -479,7 +479,9 @@ void MidiDriver_AdLib::noteOn(byte MIDIchannel, byte note, byte velocity) {
if (oldestInUseChannel >= 0) {
// channel found
warning("used In-Use channel");
- voiceOnOff(oldestInUseChannel, false, 0, 0);
+ // original driver used note 0, we use the current note
+ // because using note 0 could create a bad note (out of index) and we check that. Original driver didn't.
+ voiceOnOff(oldestInUseChannel, false, _channels[oldestInUseChannel].currentNote, 0);
_channels[oldestInUseChannel].inUse = true;
_channels[oldestInUseChannel].inUseTimer = 0; // safety, original driver also did this
@@ -542,7 +544,8 @@ void MidiDriver_AdLib::voiceOnOff(byte FMvoiceChannel, bool keyOn, byte note, by
frequencyOffset = note;
}
if (frequencyOffset >= SHERLOCK_ADLIB_NOTES_COUNT) {
- error("bad note!");
+ warning("CRITICAL - bad note!!!");
+ return;
}
frequency = adlib_FrequencyLookUpTable[frequencyOffset];
Commit: 6796444f0861d0a689a0076cb9d7b43ed976ca74
https://github.com/scummvm/scummvm/commit/6796444f0861d0a689a0076cb9d7b43ed976ca74
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-30T20:14:38-04:00
Commit Message:
SHERLOCK: Fix restoring info line when talk window closes
Changed paths:
engines/sherlock/scalpel/scalpel_user_interface.cpp
engines/sherlock/talk.cpp
diff --git a/engines/sherlock/scalpel/scalpel_user_interface.cpp b/engines/sherlock/scalpel/scalpel_user_interface.cpp
index 69ab6ec..295cddb 100644
--- a/engines/sherlock/scalpel/scalpel_user_interface.cpp
+++ b/engines/sherlock/scalpel/scalpel_user_interface.cpp
@@ -1549,6 +1549,8 @@ void ScalpelUserInterface::doTalkControl() {
|| _key == 'E') && _endKeyActive) {
talk.freeTalkVars();
talk.pullSequence();
+
+ drawInterface(2);
banishWindow();
_windowBounds.top = CONTROLS_Y1;
} else if (((Common::Rect(140, CONTROLS_Y, 179, CONTROLS_Y + 10).contains(mousePos) && events._released)
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index dd6e776..96e4d0d 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -556,6 +556,7 @@ void Talk::talkTo(const Common::String &filename) {
freeTalkVars();
if (!ui._lookScriptFlag) {
+ ui.drawInterface(2);
ui.banishWindow();
ui._windowBounds.top = CONTROLS_Y1;
ui._menuMode = STD_MODE;
Commit: 59d81c0aa1595fed6de169d89f44fbab8fcf068c
https://github.com/scummvm/scummvm/commit/59d81c0aa1595fed6de169d89f44fbab8fcf068c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-30T22:33:40-04:00
Commit Message:
SHERLOCK: Added lightweight TsAGE object for handling logo animations
Changed paths:
engines/sherlock/scalpel/tsage/logo.cpp
engines/sherlock/scalpel/tsage/logo.h
diff --git a/engines/sherlock/scalpel/tsage/logo.cpp b/engines/sherlock/scalpel/tsage/logo.cpp
index fb85662..bf1c0f5 100644
--- a/engines/sherlock/scalpel/tsage/logo.cpp
+++ b/engines/sherlock/scalpel/tsage/logo.cpp
@@ -28,6 +28,216 @@ namespace Sherlock {
namespace Scalpel {
namespace TsAGE {
+TLib *Visage::_tLib;
+
+Visage::Visage() {
+ _resNum = -1;
+ _rlbNum = -1;
+ _stream = nullptr;
+}
+
+void Visage::setVisage(int resNum, int rlbNum) {
+ if ((_resNum != resNum) || (_rlbNum != rlbNum)) {
+ _resNum = resNum;
+ _rlbNum = rlbNum;
+ delete _stream;
+
+ // Games after Ringworld have an extra indirection via the visage index file
+ Common::SeekableReadStream *stream = _tLib->getResource(RES_VISAGE, resNum, 9999);
+ if (rlbNum == 0)
+ rlbNum = 1;
+
+ // Check how many slots there are
+ uint16 count = stream->readUint16LE();
+ if (rlbNum > count)
+ rlbNum = count;
+
+ // Get the flags/rlbNum to use
+ stream->seek((rlbNum - 1) * 4 + 2);
+ uint32 v = stream->readUint32LE();
+ int flags = v >> 30;
+
+ if (flags & 3) {
+ rlbNum = (int)(v & 0xff);
+ }
+ assert((flags & 3) == 0);
+ delete stream;
+
+ _stream = _tLib->getResource(RES_VISAGE, resNum, rlbNum);
+ }
+}
+
+Visage::~Visage() {
+ delete _stream;
+}
+
+void Visage::getFrame(ObjectSurface &s, int frameNum) {
+ _stream->seek(0);
+ int numFrames = _stream->readUint16LE();
+ if (frameNum > numFrames)
+ frameNum = numFrames;
+ if (frameNum > 0)
+ --frameNum;
+
+ _stream->seek(frameNum * 4 + 2);
+ int offset = _stream->readUint32LE();
+ _stream->seek(offset);
+
+ surfaceFromRes(s);
+}
+
+int Visage::getFrameCount() const {
+ _stream->seek(0);
+ return _stream->readUint16LE();
+}
+
+bool Visage::isLoaded() const {
+ return _stream != nullptr;
+}
+
+void Visage::surfaceFromRes(ObjectSurface &s) {
+ int frameWidth = _stream->readUint16LE();
+ int frameHeight = _stream->readUint16LE();
+ Common::Rect r(0, 0, frameWidth, frameHeight);
+ s.create(r.width(), r.height());
+
+ s._centroid.x = _stream->readSint16LE();
+ s._centroid.y = _stream->readSint16LE();
+
+ _stream->skip(1);
+ byte flags = _stream->readByte();
+ bool rleEncoded = (flags & 2) != 0;
+
+ byte *destP = (byte *)s.getPixels();
+
+ if (!rleEncoded) {
+ _stream->read(destP, r.width() * r.height());
+ } else {
+ Common::fill(destP, destP + (r.width() * r.height()), 0xff);
+
+ for (int yp = 0; yp < r.height(); ++yp) {
+ int width = r.width();
+ destP = (byte *)s.getBasePtr(0, yp);
+
+ while (width > 0) {
+ uint8 controlVal = _stream->readByte();
+ if ((controlVal & 0x80) == 0) {
+ // Copy specified number of bytes
+ _stream->read(destP, controlVal);
+ width -= controlVal;
+ destP += controlVal;
+ } else if ((controlVal & 0x40) == 0) {
+ // Skip a specified number of output pixels
+ destP += controlVal & 0x3f;
+ width -= controlVal & 0x3f;
+ } else {
+ // Copy a specified pixel a given number of times
+ controlVal &= 0x3f;
+ int pixel = _stream->readByte();
+
+ Common::fill(destP, destP + controlVal, pixel);
+ destP += controlVal;
+ width -= controlVal;
+ }
+ }
+ assert(width == 0);
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+ScalpelEngine *Object::_vm;
+
+Object::Object() {
+ _vm = nullptr;
+ _animMode = ANIM_MODE_NONE;
+ _frame = 0;
+ _numFrames = 0;
+ _frameChange = 0;
+}
+
+void Object::setVisage(int visage, int strip) {
+ _visage.setVisage(visage, strip);
+}
+
+void Object::setAnimMode(AnimationMode mode) {
+ _animMode = mode;
+ _finished = false;
+
+ _updateStartFrame = _vm->_events->getFrameCounter();
+ if (_numFrames)
+ _updateStartFrame += 60 / _numFrames;
+ _frameChange = 1;
+}
+
+void Object::update() {
+ Screen &screen = *_vm->_screen;
+
+ if (_visage.isLoaded()) {
+ switch (_animMode) {
+ case ANIM_MODE_5:
+ if (_frame < _visage.getFrameCount())
+ _frame = changeFrame();
+ else
+ _finished = true;
+ break;
+
+ default:
+ break;
+ }
+
+ // Erase previous frame, if any
+ if (!_oldBounds.isEmpty())
+ screen.blitFrom(screen._backBuffer1, Common::Point(_oldBounds.left, _oldBounds.top), _oldBounds);
+
+ // Get the new frame
+ ObjectSurface s;
+ _visage.getFrame(s, _frame);
+
+ // Display the frame
+ _oldBounds = Common::Rect(_position.x, _position.y, _position.x + s.w(), _position.y + s.h());
+ _oldBounds.translate(-s._centroid.x, -s._centroid.y);
+ screen.transBlitFrom(s, Common::Point(_oldBounds.left, _oldBounds.top));
+ }
+}
+
+int Object::changeFrame() {
+ int frameNum = _frame;
+ uint32 currentFrame = _vm->_events->getFrameCounter();
+
+ if (_updateStartFrame <= currentFrame) {
+ if (_numFrames > 0) {
+ int v = 60 / _numFrames;
+ _updateStartFrame = currentFrame + v;
+
+ frameNum = getNewFrame();
+ }
+ }
+
+ return frameNum;
+}
+
+int Object::getNewFrame() {
+ int frameNum = _frame + _frameChange;
+
+ if (_frameChange > 0) {
+ if (frameNum > _visage.getFrameCount()) {
+ frameNum = 1;
+ }
+ } else if (frameNum < 1) {
+ frameNum = _visage.getFrameCount();
+ }
+
+ return frameNum;
+}
+
+bool Object::isAnimEnded() const {
+ return _finished;
+}
+
+/*----------------------------------------------------------------*/
+
bool Logo::show(ScalpelEngine *vm) {
Events &events = *vm->_events;
Logo *logo = new Logo(vm);
@@ -39,6 +249,9 @@ bool Logo::show(ScalpelEngine *vm) {
events.wait(2);
events.setButtonState();
+ for (int idx = 0; idx < 4; ++idx)
+ logo->_objects[idx].update();
+
interrupted = vm->shouldQuit() || events.kbHit() || events._pressed;
if (interrupted) {
events.clearEvents();
@@ -50,10 +263,16 @@ bool Logo::show(ScalpelEngine *vm) {
return !interrupted;
}
-Logo::Logo(ScalpelEngine *vm) : _vm(vm), _lib("sf3.rlb"), _surface(vm->_screen->w(), vm->_screen->h()) {
- // Initialize frame counter
+Logo::Logo(ScalpelEngine *vm) : _vm(vm), _lib("sf3.rlb") {
+ Object::_vm = vm;
+ Visage::_tLib = &_lib;
+
+ // Initialize counter
_counter = 0;
+ // Save a copy of the original palette
+ _vm->_screen->getPalette(_originalPalette);
+
// Set up the palettes
Common::fill(&_palette1[0], &_palette1[PALETTE_SIZE], 0);
Common::fill(&_palette1[0], &_palette2[PALETTE_SIZE], 0);
@@ -67,18 +286,42 @@ Logo::Logo(ScalpelEngine *vm) : _vm(vm), _lib("sf3.rlb"), _surface(vm->_screen->
_lib.getPalette(_palette3, 14);
}
+Logo::~Logo() {
+ // Restore the original palette
+ _vm->_screen->setPalette(_originalPalette);
+}
+
bool Logo::finished() const {
- return false;
+ return _counter >= 4;
}
void Logo::nextFrame() {
-
switch (_counter++) {
case 0:
+ // Load the background and fade it in
loadBackground();
fade(_palette1);
break;
+ case 1:
+ // First half of square, circle, and triangle arranging themselves
+ _objects[0].setVisage(16, 1);
+ _objects[0]._frame = 1;
+ _objects[0]._position = Common::Point(169, 107);
+ _objects[0]._numFrames = 7;
+ _objects[0].setAnimMode(ANIM_MODE_5);
+ break;
+
+ case 2:
+ // Keep waiting until first animation ends
+ if (!_objects[0].isAnimEnded())
+ --_counter;
+ break;
+
+ case 3:
+ // Keep waiting until second animation of shapes ordering themselves ends
+ return;
+
default:
break;
}
@@ -92,10 +335,10 @@ void Logo::loadBackground() {
Common::SeekableReadStream *stream = _lib.getResource(RES_BITMAP, 10, idx);
// Load it onto the surface
- Common::Point pt((idx / 2) * (_surface.w() / 2), (idx % 2) * (_surface.h() / 2));
- for (int y = 0; y < (_surface.h() / 2); ++y, ++pt.y) {
- byte *pDest = (byte *)_surface.getBasePtr(pt.x, pt.y);
- stream->read(pDest, _surface.w() / 2);
+ Common::Point pt((idx / 2) * (SHERLOCK_SCREEN_WIDTH / 2), (idx % 2) * (SHERLOCK_SCREEN_HEIGHT / 2));
+ for (int y = 0; y < (SHERLOCK_SCREEN_HEIGHT / 2); ++y, ++pt.y) {
+ byte *pDest = (byte *)screen._backBuffer1.getBasePtr(pt.x, pt.y);
+ stream->read(pDest, SHERLOCK_SCREEN_WIDTH / 2);
}
// _backgroundBounds = Rect(0, 0, READ_LE_UINT16(data), READ_LE_UINT16(data + 2));
@@ -108,7 +351,7 @@ void Logo::loadBackground() {
screen.setPalette(palette);
// Copy the surface to the screen
- screen.blitFrom(_surface);
+ screen.blitFrom(screen._backBuffer1);
}
void Logo::fade(const byte palette[PALETTE_SIZE]) {
diff --git a/engines/sherlock/scalpel/tsage/logo.h b/engines/sherlock/scalpel/tsage/logo.h
index 4adbe95..0b1f0a0 100644
--- a/engines/sherlock/scalpel/tsage/logo.h
+++ b/engines/sherlock/scalpel/tsage/logo.h
@@ -41,17 +41,113 @@ class ScalpelEngine;
namespace TsAGE {
+enum AnimationMode { ANIM_MODE_NONE = 0, ANIM_MODE_4 = 4, ANIM_MODE_5 = 5 };
+
+class ObjectSurface : public Surface {
+public:
+ Common::Point _centroid;
+public:
+ ObjectSurface() : Surface() {}
+ virtual ~ObjectSurface() {}
+};
+
+class Visage {
+private:
+ Common::SeekableReadStream *_stream;
+
+ /**
+ * Translates a raw image resource into a graphics surface
+ */
+ void surfaceFromRes(ObjectSurface &s);
+public:
+ static TLib *_tLib;
+ int _resNum;
+ int _rlbNum;
+public:
+ Visage();
+ ~Visage();
+
+ /**
+ * Set the visage number
+ */
+ void setVisage(int resNum, int rlbNum = 9999);
+
+ /**
+ * Get a frame from the visage
+ */
+ void getFrame(ObjectSurface &s, int frameNum);
+
+ /**
+ * Return the number of frames
+ */
+ int getFrameCount() const;
+
+ /**
+ * Returns whether the visage is loaded
+ */
+ bool isLoaded() const;
+};
+
+class Object {
+private:
+ Visage _visage;
+ uint32 _updateStartFrame;
+ int _animMode;
+ bool _finished;
+
+ /**
+ * Return the next frame when the object is animating
+ */
+ int changeFrame();
+
+ /**
+ * Gets the next frame in the sequence
+ */
+ int getNewFrame();
+public:
+ static ScalpelEngine *_vm;
+ Common::Point _position;
+ Common::Rect _oldBounds;
+ int _frame;
+ int _numFrames;
+ int _frameChange;
+public:
+ Object();
+
+ /**
+ * Load the data for the object
+ */
+ void setVisage(int visage, int strip);
+
+ /**
+ * Sets the animation mode
+ */
+ void setAnimMode(AnimationMode mode);
+
+ /**
+ * Returns true if an animation is ended
+ */
+ bool isAnimEnded() const;
+
+ /**
+ * Update the frame
+ */
+ void update();
+};
+
class Logo {
private:
ScalpelEngine *_vm;
TLib _lib;
- Surface _surface;
int _counter;
+ byte _originalPalette[PALETTE_SIZE];
byte _palette1[PALETTE_SIZE];
byte _palette2[PALETTE_SIZE];
byte _palette3[PALETTE_SIZE];
+ Object _objects[4];
Logo(ScalpelEngine *vm);
+ ~Logo();
void nextFrame();
Commit: 40f5d26c92b524e50f33be57d8fff929cc225705
https://github.com/scummvm/scummvm/commit/40f5d26c92b524e50f33be57d8fff929cc225705
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2015-05-31T09:18:30+02:00
Commit Message:
TSAGE: Fix typo in comment
Changed paths:
engines/tsage/core.cpp
diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp
index c1c4c27..d4068c2 100644
--- a/engines/tsage/core.cpp
+++ b/engines/tsage/core.cpp
@@ -1465,7 +1465,7 @@ void ScenePalette::fade(const byte *adjustData, bool fullAdjust, int percent) {
adjustData += 3;
}
- // Set the altered pale4tte
+ // Set the altered palette
g_system->getPaletteManager()->setPalette((const byte *)&tempPalette[0], 0, 256);
GLOBALS._screenSurface.updateScreen();
}
Commit: 3c9a5f02d2555dec0b2e2192a6ae96a224f05d50
https://github.com/scummvm/scummvm/commit/3c9a5f02d2555dec0b2e2192a6ae96a224f05d50
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2015-05-31T09:21:23+02:00
Commit Message:
MADS: Remove unnecessary semicolon
Changed paths:
engines/mads/palette.cpp
diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp
index 36c9e56..7651fe8 100644
--- a/engines/mads/palette.cpp
+++ b/engines/mads/palette.cpp
@@ -497,7 +497,7 @@ void Fader::fadeIn(byte palette[PALETTE_SIZE], byte destPalette[PALETTE_SIZE],
int baseColor, int numColors, int baseGrey, int numGreys,
int tickDelay, int steps) {
GreyEntry map[PALETTE_COUNT];
- byte tempPal[PALETTE_SIZE];;
+ byte tempPal[PALETTE_SIZE];
int8 signs[PALETTE_COUNT][3];
byte palIndex[PALETTE_COUNT][3];
int intensity;
Commit: 742b04cc49b499397e8b8e7e426e4d313ffcdc98
https://github.com/scummvm/scummvm/commit/742b04cc49b499397e8b8e7e426e4d313ffcdc98
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2015-05-31T09:21:47+02:00
Commit Message:
VOYEUR: Remove unnecessary semicolon
Changed paths:
engines/voyeur/events.cpp
diff --git a/engines/voyeur/events.cpp b/engines/voyeur/events.cpp
index 320c922..34ef507 100644
--- a/engines/voyeur/events.cpp
+++ b/engines/voyeur/events.cpp
@@ -76,7 +76,7 @@ EventsManager::EventsManager(VoyeurEngine *vm) : _intPtr(_gameData),
_leftClick = _rightClick = false;
_mouseClicked = _newMouseClicked = false;
- _newLeftClick = _newRightClick = false;;
+ _newLeftClick = _newRightClick = false;
_videoDead = 0;
Commit: 35fe594133e3b68f5f77db9416d4a73f5924ba3e
https://github.com/scummvm/scummvm/commit/35fe594133e3b68f5f77db9416d4a73f5924ba3e
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-05-31T12:16:30+02:00
Commit Message:
SHERLOCK: clean up adlib driver
Changed paths:
engines/sherlock/music.cpp
engines/sherlock/music.h
engines/sherlock/scalpel/drivers/adlib.cpp
engines/sherlock/scalpel/drivers/mididriver.h
diff --git a/engines/sherlock/music.cpp b/engines/sherlock/music.cpp
index a97e55d..0735f41 100644
--- a/engines/sherlock/music.cpp
+++ b/engines/sherlock/music.cpp
@@ -29,8 +29,6 @@ namespace Sherlock {
#define NUM_SONGS 45
-#define USE_SCI_MIDI_PLAYER 1
-
/* This tells which song to play in each room, 0 = no song played */
static const char ROOM_SONG[62] = {
0, 20, 43, 6, 11, 2, 8, 15, 6, 28,
@@ -216,34 +214,16 @@ Music::Music(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
_musicType = MidiDriver::getMusicType(dev);
-#if USE_SCI_MIDI_PLAYER
- _pMidiDrv = NULL;
-#endif
_driver = NULL;
switch (_musicType) {
case MT_ADLIB:
-#if USE_SCI_MIDI_PLAYER
- _pMidiDrv = MidiPlayer_AdLib_create();
-#else
_driver = MidiDriver_AdLib_create();
-#endif
break;
default:
_driver = MidiDriver::createMidi(dev);
break;
}
-#if USE_SCI_MIDI_PLAYER
- if (_pMidiDrv) {
- assert(_pMidiDrv);
- int ret = _pMidiDrv->open();
- if (ret == 0) {
- _pMidiDrv->setTimerCallback(&_midiParser, &_midiParser.timerCallback);
- }
- _midiParser.setMidiDriver(_pMidiDrv);
- _midiParser.setTimerRate(_pMidiDrv->getBaseTempo());
- }
-#endif
if (_driver) {
assert(_driver);
@@ -346,10 +326,6 @@ bool Music::playMusic(const Common::String &name) {
if (_musicType == MT_ADLIB) {
if (_driver)
MidiDriver_AdLib_newMusicData(_driver, dataPos, dataSize);
-#if USE_SCI_MIDI_PLAYER
- if (_pMidiDrv)
- MidiPlayer_AdLib_newMusicData(_pMidiDrv, dataPos, dataSize);
-#endif
}
_midiParser.loadMusic(dataPos, dataSize);
diff --git a/engines/sherlock/music.h b/engines/sherlock/music.h
index c371060..0ebc3e9 100644
--- a/engines/sherlock/music.h
+++ b/engines/sherlock/music.h
@@ -50,7 +50,6 @@ private:
SherlockEngine *_vm;
Audio::Mixer *_mixer;
MidiParser_SH _midiParser;
- MidiPlayer *_pMidiDrv;
MidiDriver *_driver;
public:
diff --git a/engines/sherlock/scalpel/drivers/adlib.cpp b/engines/sherlock/scalpel/drivers/adlib.cpp
index 29ca1ba..db1151c 100644
--- a/engines/sherlock/scalpel/drivers/adlib.cpp
+++ b/engines/sherlock/scalpel/drivers/adlib.cpp
@@ -32,8 +32,6 @@
namespace Sherlock {
-#define USE_SCI_MIDI_PLAYER 1
-
#define SHERLOCK_ADLIB_VOICES_COUNT 9
#define SHERLOCK_ADLIB_NOTES_COUNT 96
@@ -286,29 +284,6 @@ private:
void pitchBendChange(byte MIDIchannel, byte parameter1, byte parameter2);
};
-#if USE_SCI_MIDI_PLAYER
-class MidiPlayer_AdLib : public MidiPlayer {
-public:
- MidiPlayer_AdLib() : MidiPlayer() { _driver = new MidiDriver_AdLib(g_system->getMixer()); }
- ~MidiPlayer_AdLib() {
- delete _driver;
- _driver = 0;
- }
-
- int open();
- void close();
-
- byte getPlayId() const;
- int getPolyphony() const { return SHERLOCK_ADLIB_VOICES_COUNT; }
- bool hasRhythmChannel() const { return false; }
- void setVolume(byte volume) { static_cast<MidiDriver_AdLib *>(_driver)->setVolume(volume); }
-
- //int getLastChannel() const { return (static_cast<const MidiDriver_AdLib *>(_driver)->useRhythmChannel() ? 8 : 15); }
-
- void newMusicData(byte *musicData, int32 musicDataSize) { static_cast<MidiDriver_AdLib *>(_driver)->newMusicData(musicData, musicDataSize); }
-};
-#endif
-
int MidiDriver_AdLib::open() {
int rate = _mixer->getOutputRate();
@@ -650,43 +625,9 @@ void MidiDriver_AdLib::setRegister(int reg, int value) {
}
uint32 MidiDriver_AdLib::property(int prop, uint32 param) {
-#if 0
- switch(prop) {
- case MIDI_PROP_MASTER_VOLUME:
- if (param != 0xffff)
- _masterVolume = param;
- return _masterVolume;
- default:
- break;
- }
-#endif
return 0;
}
-#if USE_SCI_MIDI_PLAYER
-int MidiPlayer_AdLib::open() {
- return static_cast<MidiDriver_AdLib *>(_driver)->open();
-}
-
-void MidiPlayer_AdLib::close() {
- if (_driver) {
- _driver->close();
- }
-}
-
-byte MidiPlayer_AdLib::getPlayId() const {
- return 0x00;
-}
-
-MidiPlayer *MidiPlayer_AdLib_create() {
- return new MidiPlayer_AdLib();
-}
-
-void MidiPlayer_AdLib_newMusicData(MidiPlayer *driver, byte *musicData, int32 musicDataSize) {
- static_cast<MidiPlayer_AdLib *>(driver)->newMusicData(musicData, musicDataSize);
-}
-#endif
-
MidiDriver *MidiDriver_AdLib_create() {
return new MidiDriver_AdLib(g_system->getMixer());
}
diff --git a/engines/sherlock/scalpel/drivers/mididriver.h b/engines/sherlock/scalpel/drivers/mididriver.h
index f1366f8..6421331 100644
--- a/engines/sherlock/scalpel/drivers/mididriver.h
+++ b/engines/sherlock/scalpel/drivers/mididriver.h
@@ -24,65 +24,11 @@
#define SHERLOCK_SOFTSEQ_MIDIDRIVER_H
#include "sherlock/sherlock.h"
-//#include "audio/mididrv.h"
+#include "audio/mididrv.h"
#include "common/error.h"
namespace Sherlock {
-#define USE_SCI_MIDIPLAYER 1
-
-#if USE_SCI_MIDIPLAYER
-enum {
- MIDI_CHANNELS = 16,
- MIDI_PROP_MASTER_VOLUME = 0
-};
-
-#define MIDI_RHYTHM_CHANNEL 9
-
-class MidiPlayer : public MidiDriver_BASE {
-protected:
- MidiDriver *_driver;
- int8 _reverb;
-
-public:
- MidiPlayer() : _driver(0), _reverb(-1) { }
-
- virtual int open() { return _driver->open(); }
- virtual void close() { _driver->close(); }
- virtual void send(uint32 b) { _driver->send(b); }
- virtual uint32 getBaseTempo() { return _driver->getBaseTempo(); }
- virtual bool hasRhythmChannel() const = 0;
- virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) { _driver->setTimerCallback(timer_param, timer_proc); }
-
- virtual byte getPlayId() const = 0;
- virtual int getPolyphony() const = 0;
- virtual int getFirstChannel() const { return 0; }
- //virtual int getLastChannel() const { return 15; }
-
- virtual void setVolume(byte volume) {
- if(_driver)
- _driver->property(MIDI_PROP_MASTER_VOLUME, volume);
- }
-
- virtual int getVolume() {
- return _driver ? _driver->property(MIDI_PROP_MASTER_VOLUME, 0xffff) : 0;
- }
-
- // Returns the current reverb, or -1 when no reverb is active
- int8 getReverb() const { return _reverb; }
- // Sets the current reverb, used mainly in MT-32
- virtual void setReverb(int8 reverb) { _reverb = reverb; }
-
- // Special stuff for Sherlock Holmes
-// virtual void newMusicData(byte *musicData, int32 musicDataSize);
-
-//protected:
-};
-
-extern MidiPlayer *MidiPlayer_AdLib_create();
-extern void MidiPlayer_AdLib_newMusicData(MidiPlayer *driver, byte *musicData, int32 musicDataSize);
-#endif
-
extern MidiDriver *MidiDriver_AdLib_create();
extern void MidiDriver_AdLib_newMusicData(MidiDriver *driver, byte *musicData, int32 musicDataSize);
Commit: 2826a06bc56386f845fd6551ba422f1baf5e3ecd
https://github.com/scummvm/scummvm/commit/2826a06bc56386f845fd6551ba422f1baf5e3ecd
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2015-05-31T16:05:31+02:00
Commit Message:
SHERLOCK: Fix regression in conversations
This causes replies to once again be shown in their entirety,
instead of one line at a time.
There were two errors: First of all, _wait was always set to 1,
because one of the conditions was "|| _opcodes[OP_IF_STATEMENT]"
instead of "|| v == _opcodes[OP_IF_STATEMENT]".
Secondly, judging by the older version, this part of the code
should only be allowed to set _wait to 1, never to 0, because we
may have already set it to 1 for other reasons.
Changed paths:
engines/sherlock/talk.cpp
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index 96e4d0d..59897e2 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -1270,9 +1270,12 @@ void Talk::doScript(const Common::String &script) {
}
byte v = (str >= _scriptEnd ? 0 : str[0]);
- _wait = v == _opcodes[OP_SWITCH_SPEAKER] || v == _opcodes[OP_ASSIGN_PORTRAIT_LOCATION] ||
- v == _opcodes[OP_BANISH_WINDOW] || _opcodes[OP_IF_STATEMENT] || v == _opcodes[OP_ELSE_STATEMENT] ||
- v == _opcodes[OP_END_IF_STATEMENT] || v == _opcodes[OP_GOTO_SCENE] || v == _opcodes[OP_CALL_TALK_FILE];
+ if (v == _opcodes[OP_SWITCH_SPEAKER] || v == _opcodes[OP_ASSIGN_PORTRAIT_LOCATION] ||
+ v == _opcodes[OP_BANISH_WINDOW] || v == _opcodes[OP_IF_STATEMENT] ||
+ v == _opcodes[OP_ELSE_STATEMENT] || v == _opcodes[OP_END_IF_STATEMENT] ||
+ v == _opcodes[OP_GOTO_SCENE] || v == _opcodes[OP_CALL_TALK_FILE]) {
+ _wait = 1;
+ }
}
// Open window if it wasn't already open, and text has already been printed
Commit: 656906da4276bdb0783f58be6e84164b2bf0ecbb
https://github.com/scummvm/scummvm/commit/656906da4276bdb0783f58be6e84164b2bf0ecbb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-31T10:29:13-04:00
Commit Message:
SHERLOCK: More of the Scalpel logo implemented
Changed paths:
engines/sherlock/scalpel/tsage/logo.cpp
engines/sherlock/scalpel/tsage/logo.h
diff --git a/engines/sherlock/scalpel/tsage/logo.cpp b/engines/sherlock/scalpel/tsage/logo.cpp
index bf1c0f5..0fa8bf8 100644
--- a/engines/sherlock/scalpel/tsage/logo.cpp
+++ b/engines/sherlock/scalpel/tsage/logo.cpp
@@ -67,6 +67,11 @@ void Visage::setVisage(int resNum, int rlbNum) {
}
}
+void Visage::clear() {
+ delete _stream;
+ _stream = nullptr;
+}
+
Visage::~Visage() {
delete _stream;
}
@@ -151,7 +156,7 @@ ScalpelEngine *Object::_vm;
Object::Object() {
_vm = nullptr;
- _animMode = ANIM_MODE_NONE;
+ _isAnimating = false;
_frame = 0;
_numFrames = 0;
_frameChange = 0;
@@ -161,8 +166,8 @@ void Object::setVisage(int visage, int strip) {
_visage.setVisage(visage, strip);
}
-void Object::setAnimMode(AnimationMode mode) {
- _animMode = mode;
+void Object::setAnimMode(bool isAnimating) {
+ _isAnimating = isAnimating;
_finished = false;
_updateStartFrame = _vm->_events->getFrameCounter();
@@ -171,26 +176,24 @@ void Object::setAnimMode(AnimationMode mode) {
_frameChange = 1;
}
+void Object::erase() {
+ Screen &screen = *_vm->_screen;
+
+ if (_visage.isLoaded() && !_oldBounds.isEmpty())
+ screen.blitFrom(screen._backBuffer1, Common::Point(_oldBounds.left, _oldBounds.top), _oldBounds);
+}
+
void Object::update() {
Screen &screen = *_vm->_screen;
if (_visage.isLoaded()) {
- switch (_animMode) {
- case ANIM_MODE_5:
+ if (_isAnimating) {
if (_frame < _visage.getFrameCount())
_frame = changeFrame();
else
_finished = true;
- break;
-
- default:
- break;
}
- // Erase previous frame, if any
- if (!_oldBounds.isEmpty())
- screen.blitFrom(screen._backBuffer1, Common::Point(_oldBounds.left, _oldBounds.top), _oldBounds);
-
// Get the new frame
ObjectSurface s;
_visage.getFrame(s, _frame);
@@ -236,6 +239,10 @@ bool Object::isAnimEnded() const {
return _finished;
}
+bool Object::isMoving() const {
+ return (_destination.x != 0) && (_destination != _position);
+}
+
/*----------------------------------------------------------------*/
bool Logo::show(ScalpelEngine *vm) {
@@ -249,11 +256,15 @@ bool Logo::show(ScalpelEngine *vm) {
events.wait(2);
events.setButtonState();
+ // Erase areas from previous frame, and update and re-draw objects
+ for (int idx = 0; idx < 4; ++idx)
+ logo->_objects[idx].erase();
for (int idx = 0; idx < 4; ++idx)
logo->_objects[idx].update();
interrupted = vm->shouldQuit() || events.kbHit() || events._pressed;
if (interrupted) {
+ // Keyboard or mouse button pressed, so break out of logo display
events.clearEvents();
break;
}
@@ -292,10 +303,12 @@ Logo::~Logo() {
}
bool Logo::finished() const {
- return _counter >= 4;
+ return _counter >= 442;
}
void Logo::nextFrame() {
+ Screen &screen = *_vm->_screen;
+
switch (_counter++) {
case 0:
// Load the background and fade it in
@@ -309,18 +322,179 @@ void Logo::nextFrame() {
_objects[0]._frame = 1;
_objects[0]._position = Common::Point(169, 107);
_objects[0]._numFrames = 7;
- _objects[0].setAnimMode(ANIM_MODE_5);
+ _objects[0].setAnimMode(true);
break;
case 2:
// Keep waiting until first animation ends
- if (!_objects[0].isAnimEnded())
+ if (!_objects[0].isAnimEnded()) {
--_counter;
+ } else {
+ // Start second half of the shapes animation
+ _objects[0].setVisage(16, 2);
+ _objects[0]._frame = 1;
+ _objects[0]._numFrames = 11;
+ _objects[0].setAnimMode(true);
+ }
break;
case 3:
// Keep waiting until second animation of shapes ordering themselves ends
- return;
+ if (!_objects[0].isAnimEnded()) {
+ --_counter;
+ } else {
+ // Fade out the background but keep the shapes visible
+ fade(_palette2);
+ screen._backBuffer1.clear();
+ screen.clear();
+ }
+ break;
+
+ case 13: {
+ // Load the new palette
+ byte palette[PALETTE_SIZE];
+ _lib.getPalette(palette, 12);
+ screen.setPalette(palette);
+ break;
+ }
+
+ case 14:
+ _objects[0].setVisage(12, 1);
+ _objects[0]._frame = 1;
+ _objects[0]._numFrames = 7;
+ _objects[0]._position = Common::Point(170, 142);
+ _objects[0].setDestination(Common::Point(158, 71));
+ break;
+
+ case 15:
+ // Wait until the logo has expanded upwards to form EA logo
+ if (_objects[0].isMoving())
+ --_counter;
+ break;
+
+ case 16:
+ fade(_palette3, 40);
+ break;
+
+ case 20:
+ // Show the 'Electronic Arts' company name
+ _objects[1].setVisage(14, 1);
+ _objects[1]._frame = 1;
+ _objects[1]._position = Common::Point(152, 98);
+ break;
+
+ case 140:
+ // Start sequence of positioning and size hand cursor in an arc
+ _objects[2].setVisage(18, 1);
+ _objects[2]._frame = 1;
+ _objects[2]._position = Common::Point(33, 91);
+ break;
+
+ case 145:
+ _objects[2]._frame = 2;
+ _objects[2]._position = Common::Point(44, 124);
+ break;
+
+ case 150:
+ _objects[2]._frame = 3;
+ _objects[2]._position = Common::Point(64, 153);
+ break;
+
+ case 155:
+ _objects[2]._frame = 4;
+ _objects[2]._position = Common::Point(87, 174);
+ break;
+
+ case 160:
+ _objects[2]._frame = 5;
+ _objects[2]._position = Common::Point(114, 191);
+ break;
+
+ case 165:
+ _objects[2]._frame = 6;
+ _objects[2]._position = Common::Point(125, 184);
+ break;
+
+ case 170:
+ _objects[2]._frame = 7;
+ _objects[2]._position = Common::Point(154, 187);
+ break;
+
+ case 175:
+ _objects[2]._frame = 8;
+ _objects[2]._position = Common::Point(181, 182);
+ break;
+
+ case 180:
+ _objects[2]._frame = 9;
+ _objects[2]._position = Common::Point(191, 167);
+ break;
+
+ case 185:
+ _objects[2]._frame = 10;
+ _objects[2]._position = Common::Point(190, 150);
+ break;
+
+ case 190:
+ _objects[2]._frame = 11;
+ _objects[2]._position = Common::Point(182, 139);
+ break;
+
+ case 195:
+ _objects[2]._frame = 11;
+ _objects[2]._position = Common::Point(170, 130);
+ break;
+
+ case 200:
+ _objects[2]._frame = 11;
+ _objects[2]._position = Common::Point(158, 121);
+ break;
+
+ case 205:
+ // Show a highlighting of the company name
+ _objects[2].remove();
+ _objects[3].setVisage(19, 1);
+ _objects[3]._position = Common::Point(155, 94);
+ break;
+
+ case 213:
+ _objects[3]._frame = 2;
+ _objects[3]._position = Common::Point(155, 94);
+ break;
+
+ case 221:
+ _objects[1].remove();
+ break;
+
+ case 222:
+ _objects[3]._frame = 3;
+ _objects[3]._position = Common::Point(155, 94);
+ break;
+
+ case 230:
+ _objects[3]._frame = 4;
+ _objects[3]._position = Common::Point(155, 94);
+ break;
+
+ case 238:
+ _objects[3]._frame = 5;
+ _objects[3]._position = Common::Point(155, 94);
+ break;
+
+ case 246:
+ _objects[3]._frame = 6;
+ _objects[3]._position = Common::Point(155, 94);
+ break;
+
+ case 254:
+ _objects[3]._frame = 7;
+ _objects[3]._position = Common::Point(155, 94);
+ break;
+
+ case 262:
+ _objects[3]._frame = 8;
+ _objects[3]._position = Common::Point(155, 94);
+ break;
default:
break;
@@ -354,18 +528,22 @@ void Logo::loadBackground() {
screen.blitFrom(screen._backBuffer1);
}
-void Logo::fade(const byte palette[PALETTE_SIZE]) {
+void Logo::fade(const byte palette[PALETTE_SIZE], int step) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
+ byte startPalette[PALETTE_SIZE];
byte tempPalette[PALETTE_SIZE];
- for (int percent = 0; percent < 100; percent += 6) {
+ screen.getPalette(startPalette);
+
+ for (int percent = 0; percent < 100; percent += step) {
for (int palIndex = 0; palIndex < 256; ++palIndex) {
- const byte *palP = (const byte *)&palette[palIndex * 3];
+ const byte *pal1P = (const byte *)&startPalette[palIndex * 3];
+ const byte *pal2P = (const byte *)&palette[palIndex * 3];
byte *destP = &tempPalette[palIndex * 3];
- for (int rgbIndex = 0; rgbIndex < 3; ++rgbIndex, ++palP, ++destP) {
- *destP = (int)*palP * percent / 100;
+ for (int rgbIndex = 0; rgbIndex < 3; ++rgbIndex, ++pal1P, ++pal2P, ++destP) {
+ *destP = (int)*pal1P + ((int)*pal2P - (int)*pal1P) * percent / 100;
}
}
diff --git a/engines/sherlock/scalpel/tsage/logo.h b/engines/sherlock/scalpel/tsage/logo.h
index 0b1f0a0..0dcd35e 100644
--- a/engines/sherlock/scalpel/tsage/logo.h
+++ b/engines/sherlock/scalpel/tsage/logo.h
@@ -41,8 +41,6 @@ class ScalpelEngine;
namespace TsAGE {
-enum AnimationMode { ANIM_MODE_NONE = 0, ANIM_MODE_4 = 4, ANIM_MODE_5 = 5 };
-
class ObjectSurface : public Surface {
public:
Common::Point _centroid;
@@ -73,6 +71,11 @@ public:
void setVisage(int resNum, int rlbNum = 9999);
/**
+ * Clear the visage
+ */
+ void clear();
+
+ /**
* Get a frame from the visage
*/
void getFrame(ObjectSurface &s, int frameNum);
@@ -92,7 +95,7 @@ class Object {
private:
Visage _visage;
uint32 _updateStartFrame;
- int _animMode;
+ bool _isAnimating;
bool _finished;
/**
@@ -107,6 +110,7 @@ private:
public:
static ScalpelEngine *_vm;
Common::Point _position;
+ Common::Point _destination;
Common::Rect _oldBounds;
int _frame;
int _numFrames;
@@ -120,9 +124,14 @@ public:
void setVisage(int visage, int strip);
/**
- * Sets the animation mode
+ * Sets whether the object is animating
*/
- void setAnimMode(AnimationMode mode);
+ void setAnimMode(bool isAnimating);
+
+ /**
+ * Starts an object moving to a given destination
+ */
+ void setDestination(const Common::Point &pt) { _destination = pt; }
/**
* Returns true if an animation is ended
@@ -130,9 +139,24 @@ public:
bool isAnimEnded() const;
/**
+ * Return true if object is moving
+ */
+ bool isMoving() const;
+
+ /**
+ * Erase the area the object was previously drawn at, by restoring the background
+ */
+ void erase();
+
+ /**
* Update the frame
*/
void update();
+
+ /**
+ * Remove an object from being displayed
+ */
+ void remove() { _visage.clear(); }
};
class Logo {
@@ -161,7 +185,7 @@ private:
/**
* Fade from the current palette to a new one
*/
- void fade(const byte palette[PALETTE_SIZE]);
+ void fade(const byte palette[PALETTE_SIZE], int step = 6);
public:
static bool show(ScalpelEngine *vm);
};
Commit: 53f6e1903b9f4247b231955b16dc49cb7d40d3e9
https://github.com/scummvm/scummvm/commit/53f6e1903b9f4247b231955b16dc49cb7d40d3e9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-31T11:49:06-04:00
Commit Message:
SHERLOCK: Implement TsAGE object mover code for Scalpel logo display
Changed paths:
engines/sherlock/scalpel/tsage/logo.cpp
engines/sherlock/scalpel/tsage/logo.h
diff --git a/engines/sherlock/scalpel/tsage/logo.cpp b/engines/sherlock/scalpel/tsage/logo.cpp
index 0fa8bf8..3fc9973 100644
--- a/engines/sherlock/scalpel/tsage/logo.cpp
+++ b/engines/sherlock/scalpel/tsage/logo.cpp
@@ -160,6 +160,7 @@ Object::Object() {
_frame = 0;
_numFrames = 0;
_frameChange = 0;
+ _angle = _changeCtr = 0;
}
void Object::setVisage(int visage, int strip) {
@@ -176,6 +177,39 @@ void Object::setAnimMode(bool isAnimating) {
_frameChange = 1;
}
+void Object::setDestination(const Common::Point &pt) {
+ _destination = pt;
+
+ int moveRate = 10;
+ _walkStartFrame = _vm->_events->getFrameCounter();
+ _walkStartFrame += 60 / moveRate;
+
+ calculateMoveAngle();
+
+ // Get the difference
+ int diffX = _destination.x - _position.x;
+ int diffY = _destination.y - _position.y;
+ int xSign = (diffX < 0) ? -1 : (diffX > 0 ? 1 : 0);
+ int ySign = (diffY < 0) ? -1 : (diffY > 0 ? 1 : 0);
+ diffX = ABS(diffX);
+ diffY = ABS(diffY);
+
+ if (diffX < diffY) {
+ _minorDiff = diffX / 2;
+ _majorDiff = diffY;
+ } else {
+ _minorDiff = diffY / 2;
+ _majorDiff = diffX;
+ }
+
+ // Set the destination position
+ _moveDelta = Common::Point(diffX, diffY);
+ _moveSign = Common::Point(xSign, ySign);
+ _changeCtr = 0;
+
+ assert(diffX || diffY);
+}
+
void Object::erase() {
Screen &screen = *_vm->_screen;
@@ -187,6 +221,9 @@ void Object::update() {
Screen &screen = *_vm->_screen;
if (_visage.isLoaded()) {
+ if (isMoving())
+ move();
+
if (_isAnimating) {
if (_frame < _visage.getFrameCount())
_frame = changeFrame();
@@ -235,6 +272,27 @@ int Object::getNewFrame() {
return frameNum;
}
+void Object::calculateMoveAngle() {
+ int xDiff = _destination.x - _position.x, yDiff = _position.y - _destination.y;
+
+ if (!xDiff && !yDiff)
+ _angle = 0;
+ else if (!xDiff)
+ _angle = (_destination.y >= _position.y) ? 180 : 0;
+ else if (!yDiff)
+ _angle = (_destination.x >= _position.x) ? 90 : 270;
+ else {
+ int result = (((xDiff * 100) / ((abs(xDiff) + abs(yDiff))) * 90) / 100);
+
+ if (yDiff < 0)
+ result = 180 - result;
+ else if (xDiff < 0)
+ result += 360;
+
+ _angle = result;
+ }
+}
+
bool Object::isAnimEnded() const {
return _finished;
}
@@ -243,6 +301,82 @@ bool Object::isMoving() const {
return (_destination.x != 0) && (_destination != _position);
}
+void Object::move() {
+ Common::Point currPos = _position;
+ Common::Point moveDiff(5, 3);
+ int yDiff = 0;
+ int percent = 100;
+
+ if (dontMove())
+ return;
+
+ if (_moveDelta.x >= _moveDelta.y) {
+ int xAmount = _moveSign.x * moveDiff.x * percent / 100;
+ if (!xAmount)
+ xAmount = _moveSign.x;
+ currPos.x += xAmount;
+
+ int yAmount = ABS(_destination.y - currPos.y);
+ int yChange = _majorDiff / ABS(xAmount);
+ int ySign;
+
+ if (!yChange)
+ ySign = _moveSign.y;
+ else {
+ int v = yAmount / yChange;
+ _changeCtr += yAmount % yChange;
+ if (_changeCtr >= yChange) {
+ ++v;
+ _changeCtr -= yChange;
+ }
+
+ ySign = _moveSign.y * v;
+ }
+
+ currPos.y += ySign;
+ _majorDiff -= ABS(xAmount);
+
+ }
+ else {
+ int yAmount = _moveSign.y * moveDiff.y * percent / 100;
+ if (!yAmount)
+ yAmount = _moveSign.y;
+ currPos.y += yAmount;
+
+ int xAmount = ABS(_destination.x - currPos.x);
+ int xChange = _majorDiff / ABS(yAmount);
+ int xSign;
+
+ if (!xChange)
+ xSign = _moveSign.x;
+ else {
+ int v = xAmount / xChange;
+ _changeCtr += xAmount % xChange;
+ if (_changeCtr >= xChange) {
+ ++v;
+ _changeCtr -= xChange;
+ }
+
+ xSign = _moveSign.x * v;
+ }
+
+ currPos.x += xSign;
+ _majorDiff -= ABS(yAmount);
+ }
+
+ _position = currPos;
+ if (dontMove())
+ _position = _destination;
+}
+
+bool Object::dontMove() const {
+ return (_majorDiff <= 0);
+}
+
+void Object::endMove() {
+ _position = _destination;
+}
+
/*----------------------------------------------------------------*/
bool Logo::show(ScalpelEngine *vm) {
diff --git a/engines/sherlock/scalpel/tsage/logo.h b/engines/sherlock/scalpel/tsage/logo.h
index 0dcd35e..68b7353 100644
--- a/engines/sherlock/scalpel/tsage/logo.h
+++ b/engines/sherlock/scalpel/tsage/logo.h
@@ -97,6 +97,12 @@ private:
uint32 _updateStartFrame;
bool _isAnimating;
bool _finished;
+ uint32 _walkStartFrame;
+ int _angle;
+ int _changeCtr;
+ int _majorDiff, _minorDiff;
+ Common::Point _moveDelta;
+ Common::Point _moveSign;
/**
* Return the next frame when the object is animating
@@ -107,6 +113,26 @@ private:
* Gets the next frame in the sequence
*/
int getNewFrame();
+
+ /**
+ * Calculate the angle between the current position and a designated destination
+ */
+ void calculateMoveAngle();
+
+ /**
+ * Handle any object movement
+ */
+ void move();
+
+ /**
+ * Returns whether not to make any movement
+ */
+ bool dontMove() const;
+
+ /**
+ * Ends any current movement
+ */
+ void endMove();
public:
static ScalpelEngine *_vm;
Common::Point _position;
@@ -131,7 +157,7 @@ public:
/**
* Starts an object moving to a given destination
*/
- void setDestination(const Common::Point &pt) { _destination = pt; }
+ void setDestination(const Common::Point &pt);
/**
* Returns true if an animation is ended
Commit: 141ff4d08dc24b6bb17098bd71801e2a58e6a38f
https://github.com/scummvm/scummvm/commit/141ff4d08dc24b6bb17098bd71801e2a58e6a38f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-31T11:58:07-04:00
Commit Message:
SHERLOCK: Fix white screen on Sclapel logo
Changed paths:
engines/sherlock/scalpel/tsage/logo.cpp
diff --git a/engines/sherlock/scalpel/tsage/logo.cpp b/engines/sherlock/scalpel/tsage/logo.cpp
index 3fc9973..239543b 100644
--- a/engines/sherlock/scalpel/tsage/logo.cpp
+++ b/engines/sherlock/scalpel/tsage/logo.cpp
@@ -487,6 +487,7 @@ void Logo::nextFrame() {
case 13: {
// Load the new palette
byte palette[PALETTE_SIZE];
+ Common::copy(&_palette2[0], &_palette2[PALETTE_SIZE], &palette[0]);
_lib.getPalette(palette, 12);
screen.setPalette(palette);
break;
Commit: b1cae872512a7dff969201b7c7b7633100b39415
https://github.com/scummvm/scummvm/commit/b1cae872512a7dff969201b7c7b7633100b39415
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2015-05-31T20:27:41+02:00
Commit Message:
SHERLOCK: Fix brief black screen in EA logo intro
There used to be a slight delay between clearing the screen and
starting the "morph into EA logo" animation. Now those two things
are done in the same stage of the intro.
Changed paths:
engines/sherlock/scalpel/tsage/logo.cpp
diff --git a/engines/sherlock/scalpel/tsage/logo.cpp b/engines/sherlock/scalpel/tsage/logo.cpp
index 239543b..3ae6476 100644
--- a/engines/sherlock/scalpel/tsage/logo.cpp
+++ b/engines/sherlock/scalpel/tsage/logo.cpp
@@ -480,20 +480,18 @@ void Logo::nextFrame() {
// Fade out the background but keep the shapes visible
fade(_palette2);
screen._backBuffer1.clear();
- screen.clear();
}
break;
- case 13: {
+ case 14:
// Load the new palette
byte palette[PALETTE_SIZE];
Common::copy(&_palette2[0], &_palette2[PALETTE_SIZE], &palette[0]);
_lib.getPalette(palette, 12);
+ screen.clear();
screen.setPalette(palette);
- break;
- }
- case 14:
+ // Morph into the EA logo
_objects[0].setVisage(12, 1);
_objects[0]._frame = 1;
_objects[0]._numFrames = 7;
Commit: b01dee457a6adc2a9871e7a6007289fb7193903f
https://github.com/scummvm/scummvm/commit/b01dee457a6adc2a9871e7a6007289fb7193903f
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2015-05-31T20:45:40+02:00
Commit Message:
SHERLOCK: Added missing setAnimMode() call
It doesn't seem to make any difference, but surely it should be
called here when it's called for earlier animations?
Changed paths:
engines/sherlock/scalpel/tsage/logo.cpp
diff --git a/engines/sherlock/scalpel/tsage/logo.cpp b/engines/sherlock/scalpel/tsage/logo.cpp
index 3ae6476..8cc5f99 100644
--- a/engines/sherlock/scalpel/tsage/logo.cpp
+++ b/engines/sherlock/scalpel/tsage/logo.cpp
@@ -495,6 +495,7 @@ void Logo::nextFrame() {
_objects[0].setVisage(12, 1);
_objects[0]._frame = 1;
_objects[0]._numFrames = 7;
+ _objects[0].setAnimMode(true);
_objects[0]._position = Common::Point(170, 142);
_objects[0].setDestination(Common::Point(158, 71));
break;
Commit: c822e849de786f1b1be2dfbcdd3364d0b33c7297
https://github.com/scummvm/scummvm/commit/c822e849de786f1b1be2dfbcdd3364d0b33c7297
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-31T16:28:41-04:00
Commit Message:
SHERLOCK: Move scroll variables from Screen to TattooUserInterface
Changed paths:
engines/sherlock/scene.cpp
engines/sherlock/screen.cpp
engines/sherlock/screen.h
engines/sherlock/tattoo/tattoo_scene.cpp
engines/sherlock/tattoo/tattoo_user_interface.cpp
engines/sherlock/tattoo/tattoo_user_interface.h
engines/sherlock/user_interface.h
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 76fb7ae..5b2cd9c 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -336,7 +336,7 @@ bool Scene::loadScene(const Common::String &filename) {
screen.translatePalette(screen._cMap);
screen.setupBGArea(screen._cMap);
- screen.initScrollVars();
+ ui.initScrollVars();
// Read in background
if (_lzwMode) {
diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp
index a3af555..708493c 100644
--- a/engines/sherlock/screen.cpp
+++ b/engines/sherlock/screen.cpp
@@ -44,10 +44,6 @@ Screen::Screen(SherlockEngine *vm) : Surface(g_system->getWidth(), g_system->get
// Rose Tattoo specific fields
_fadeBytesRead = _fadeBytesToRead = 0;
_oldFadePercent = 0;
- _scrollSize = 0;
- _scrollSpeed = 0;
- _currentScroll = 0;
- _targetScroll = 0;
_flushScreen = false;
}
@@ -310,6 +306,16 @@ void Screen::flushScaleImage(ImageFrame *frame, const Common::Point &pt, int16 *
*height = newBounds.height();
}
+void Screen::blockMove(const Common::Rect &r, const Common::Point &scrollPos) {
+ Common::Rect bounds = r;
+ bounds.translate(scrollPos.x, scrollPos.y);
+ slamRect(bounds);
+}
+
+void Screen::blockMove(const Common::Point &scrollPos) {
+ blockMove(Common::Rect(0, 0, w(), h()), scrollPos);
+}
+
void Screen::print(const Common::Point &pt, byte color, const char *formatStr, ...) {
// Create the string to display
va_list args;
@@ -491,15 +497,6 @@ void Screen::setupBGArea(const byte cMap[PALETTE_SIZE]) {
warning("TODO");
}
-/**
- * Initializes scroll variables
- */
-void Screen::initScrollVars() {
- _scrollSize = 0;
- _currentScroll = 0;
- _targetScroll = 0;
-}
-
void Screen::translatePalette(byte palette[PALETTE_SIZE]) {
for (int idx = 0; idx < PALETTE_SIZE; ++idx)
palette[idx] = VGA_COLOR_TRANS(palette[idx]);
diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h
index 8fda9cb..2774673 100644
--- a/engines/sherlock/screen.h
+++ b/engines/sherlock/screen.h
@@ -99,8 +99,6 @@ public:
byte _cMap[PALETTE_SIZE];
byte _sMap[PALETTE_SIZE];
byte _tMap[PALETTE_SIZE];
- int _currentScroll, _targetScroll;
- int _scrollSize, _scrollSpeed;
bool _flushScreen;
public:
Screen(SherlockEngine *vm);
@@ -192,6 +190,16 @@ public:
int16 *width, int16 *height, int scaleVal);
/**
+ * Copies data from the back buffer to the screen, taking into account scrolling position
+ */
+ void blockMove(const Common::Rect &r, const Common::Point &scrollPos);
+
+ /**
+ * Copies the entire screen from the back buffer, taking into account scrolling position
+ */
+ void blockMove(const Common::Point &scorllPos);
+
+ /**
* Returns the width of a string in pixels
*/
int stringWidth(const Common::String &str);
@@ -257,8 +265,6 @@ public:
void setupBGArea(const byte cMap[PALETTE_SIZE]);
- void initScrollVars();
-
/**
* Translate a palette from 6-bit RGB values to full 8-bit values suitable for passing
* to the underlying palette manager
diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp
index 2a13b2a..cd86a58 100644
--- a/engines/sherlock/tattoo/tattoo_scene.cpp
+++ b/engines/sherlock/tattoo/tattoo_scene.cpp
@@ -99,8 +99,8 @@ void TattooScene::doBgAnimEraseBackground() {
if (_mask != nullptr) {
if (screen._backBuffer1.w() > screen.w())
- screen.blitFrom(screen._backBuffer1, Common::Point(0, 0), Common::Rect(screen._currentScroll, 0,
- screen._currentScroll + screen.w(), screen.h()));
+ screen.blitFrom(screen._backBuffer1, Common::Point(0, 0), Common::Rect(ui._currentScroll.x, 0,
+ ui._currentScroll.x + screen.w(), screen.h()));
else
screen.blitFrom(screen._backBuffer1);
@@ -175,22 +175,22 @@ void TattooScene::doBgAnimEraseBackground() {
}
// Adjust the Target Scroll if needed
- if ((people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER - screen._currentScroll) <
+ if ((people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER - ui._currentScroll.x) <
(SHERLOCK_SCREEN_WIDTH / 8) && people[people._walkControl]._delta.x < 0) {
- screen._targetScroll = (short)(people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER -
+ ui._targetScroll.x = (short)(people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER -
SHERLOCK_SCREEN_WIDTH / 8 - 250);
- if (screen._targetScroll < 0)
- screen._targetScroll = 0;
+ if (ui._targetScroll.x < 0)
+ ui._targetScroll.x = 0;
}
- if ((people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER - screen._currentScroll) > (SHERLOCK_SCREEN_WIDTH / 4 * 3)
+ if ((people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER - ui._currentScroll.x) > (SHERLOCK_SCREEN_WIDTH / 4 * 3)
&& people[people._walkControl]._delta.x > 0)
- screen._targetScroll = (short)(people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER -
+ ui._targetScroll.x = (short)(people[people._walkControl]._position.x / FIXED_INT_MULTIPLIER -
SHERLOCK_SCREEN_WIDTH / 4 * 3 + 250);
- if (screen._targetScroll > screen._scrollSize)
- screen._targetScroll = screen._scrollSize;
+ if (ui._targetScroll.x > ui._scrollSize)
+ ui._targetScroll.x = ui._scrollSize;
ui.doScroll();
}
@@ -231,6 +231,7 @@ void TattooScene::doBgAnim() {
void TattooScene::doBgAnimUpdateBgObjectsAndAnim() {
People &people = *_vm->_people;
Screen &screen = *_vm->_screen;
+ TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &obj = _bgShapes[idx];
@@ -255,33 +256,33 @@ void TattooScene::doBgAnimUpdateBgObjectsAndAnim() {
if (_mask != nullptr) {
switch (_currentScene) {
case 7:
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 110), screen._currentScroll);
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 110), screen._currentScroll);
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x + SHERLOCK_SCREEN_WIDTH, 110), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 110), ui._currentScroll.x);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 110), ui._currentScroll.x);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x + SHERLOCK_SCREEN_WIDTH, 110), ui._currentScroll.x);
break;
case 8:
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 180), screen._currentScroll);
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 180), screen._currentScroll);
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x + SHERLOCK_SCREEN_WIDTH, 180), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 180), ui._currentScroll.x);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 180), ui._currentScroll.x);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x + SHERLOCK_SCREEN_WIDTH, 180), ui._currentScroll.x);
if (!_vm->readFlags(880))
- screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(940, 300), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(940, 300), ui._currentScroll.x);
break;
case 18:
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 203), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 203), ui._currentScroll.x);
if (!_vm->readFlags(189))
- screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(124 + _maskOffset.x, 239), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(124 + _maskOffset.x, 239), ui._currentScroll.x);
break;
case 53:
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 110), screen._currentScroll);
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 110), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 110), ui._currentScroll.x);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 110), ui._currentScroll.x);
break;
case 68:
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 203), screen._currentScroll);
- screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(124 + _maskOffset.x, 239), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 203), ui._currentScroll.x);
+ screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(124 + _maskOffset.x, 239), ui._currentScroll.x);
break;
}
}
@@ -291,38 +292,39 @@ void TattooScene::doBgAnimUpdateBgObjectsAndAnim() {
void TattooScene::updateBackground() {
People &people = *_vm->_people;
Screen &screen = *_vm->_screen;
+ TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
Scene::updateBackground();
if (_mask != nullptr) {
switch (_currentScene) {
case 7:
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 110), screen._currentScroll);
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 110), screen._currentScroll);
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x + SHERLOCK_SCREEN_WIDTH, 110), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 110), ui._currentScroll.x);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 110), ui._currentScroll.x);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x + SHERLOCK_SCREEN_WIDTH, 110), ui._currentScroll.x);
break;
case 8:
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 180), screen._currentScroll);
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 180), screen._currentScroll);
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x + SHERLOCK_SCREEN_WIDTH, 180), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x - SHERLOCK_SCREEN_WIDTH, 180), ui._currentScroll.x);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 180), ui._currentScroll.x);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x + SHERLOCK_SCREEN_WIDTH, 180), ui._currentScroll.x);
if (!_vm->readFlags(880))
- screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(940, 300), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(940, 300), ui._currentScroll.x);
break;
case 18:
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(0, 203), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(0, 203), ui._currentScroll.x);
if (!_vm->readFlags(189))
- screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(124, 239), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(124, 239), ui._currentScroll.x);
break;
case 53:
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 110), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(_maskOffset.x, 110), ui._currentScroll.x);
break;
case 68:
- screen._backBuffer1.maskArea((*_mask)[0], Common::Point(0, 203), screen._currentScroll);
- screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(124, 239), screen._currentScroll);
+ screen._backBuffer1.maskArea((*_mask)[0], Common::Point(0, 203), ui._currentScroll.x);
+ screen._backBuffer1.maskArea((*_mask1)[0], Common::Point(124, 239), ui._currentScroll.x);
break;
default:
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp
index e763228..a97b6f7 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.cpp
+++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp
@@ -33,6 +33,13 @@ TattooUserInterface::TattooUserInterface(SherlockEngine *vm): UserInterface(vm)
_invMenuBuffer = nullptr;
_tagBuffer = nullptr;
_invGraphic = nullptr;
+ _scrollSize = _scrollSpeed = 0;
+}
+
+void TattooUserInterface::initScrollVars() {
+ _scrollSize = 0;
+ _currentScroll.x = _currentScroll.y = 0;
+ _targetScroll.x = _targetScroll.y = 0;
}
void TattooUserInterface::handleInput() {
@@ -41,13 +48,14 @@ void TattooUserInterface::handleInput() {
}
void TattooUserInterface::drawInterface(int bufferNum) {
+ TattooScene &scene = *(TattooScene *)_vm->_scene;
Screen &screen = *_vm->_screen;
- TattooEngine &vm = *((TattooEngine *)_vm);
+ TattooEngine &vm = *(TattooEngine *)_vm;
if (_invMenuBuffer != nullptr) {
Common::Rect r = _invMenuBounds;
r.grow(-3);
- r.translate(-screen._currentScroll, 0);
+ r.translate(-_currentScroll.x, 0);
_grayAreas.clear();
_grayAreas.push_back(r);
@@ -58,7 +66,7 @@ void TattooUserInterface::drawInterface(int bufferNum) {
if (_menuBuffer != nullptr) {
Common::Rect r = _menuBounds;
r.grow(-3);
- r.translate(-screen._currentScroll, 0);
+ r.translate(-_currentScroll.x, 0);
_grayAreas.clear();
_grayAreas.push_back(r);
@@ -76,6 +84,14 @@ void TattooUserInterface::drawInterface(int bufferNum) {
if (vm._creditsActive)
vm.drawCredits();
+
+ // Bring the widgets to the screen
+ if (scene._mask != nullptr)
+ screen._flushScreen = true;
+
+ //if (screen._flushScreen)
+ // screen.blockMove(_currentScroll.x);
+
}
void TattooUserInterface::doBgAnimRestoreUI() {
@@ -118,27 +134,27 @@ void TattooUserInterface::doBgAnimRestoreUI() {
void TattooUserInterface::doScroll() {
Screen &screen = *_vm->_screen;
- int oldScroll = screen._currentScroll;
+ int oldScroll = _currentScroll.x;
// If we're already at the target scroll position, nothing needs to be done
- if (screen._targetScroll == screen._currentScroll)
+ if (_targetScroll.x == _currentScroll.x)
return;
screen._flushScreen = true;
- if (screen._targetScroll > screen._currentScroll) {
- screen._currentScroll += screen._scrollSpeed;
- if (screen._currentScroll > screen._targetScroll)
- screen._currentScroll = screen._targetScroll;
- } else if (screen._targetScroll < screen._currentScroll) {
- screen._currentScroll -= screen._scrollSpeed;
- if (screen._currentScroll < screen._targetScroll)
- screen._currentScroll = screen._targetScroll;
+ if (_targetScroll.x > _currentScroll.x) {
+ _currentScroll.x += _scrollSpeed;
+ if (_currentScroll.x > _targetScroll.x)
+ _currentScroll.x = _targetScroll.x;
+ } else if (_targetScroll.x < _currentScroll.x) {
+ _currentScroll.x -= _scrollSpeed;
+ if (_currentScroll.x < _targetScroll.x)
+ _currentScroll.x = _targetScroll.x;
}
if (_menuBuffer != nullptr)
- _menuBounds.translate(screen._currentScroll - oldScroll, 0);
+ _menuBounds.translate(_currentScroll.x - oldScroll, 0);
if (_invMenuBuffer != nullptr)
- _invMenuBounds.translate(screen._currentScroll - oldScroll, 0);
+ _invMenuBounds.translate(_currentScroll.x - oldScroll, 0);
}
void TattooUserInterface::drawGrayAreas() {
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.h b/engines/sherlock/tattoo/tattoo_user_interface.h
index 2125f1b..fea9ca8 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.h
+++ b/engines/sherlock/tattoo/tattoo_user_interface.h
@@ -51,6 +51,9 @@ private:
*/
void drawGrayAreas();
public:
+ Common::Point _currentScroll, _targetScroll;
+ int _scrollSize, _scrollSpeed;
+public:
TattooUserInterface(SherlockEngine *vm);
/**
@@ -74,6 +77,11 @@ public:
* Draw the user interface onto the screen's back buffers
*/
virtual void drawInterface(int bufferNum = 3);
+
+ /**
+ * Initializes scroll variables
+ */
+ virtual void initScrollVars();
};
} // End of namespace Tattoo
diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h
index 042997a..c7a3987 100644
--- a/engines/sherlock/user_interface.h
+++ b/engines/sherlock/user_interface.h
@@ -123,6 +123,11 @@ public:
* Print the previously selected object's decription
*/
virtual void printObjectDesc() {}
+
+ /**
+ * Initializes scroll variables
+ */
+ virtual void initScrollVars() {}
};
} // End of namespace Sherlock
Commit: f2bced65aca1e98bc75e4e2e6a5fd12eba95fcf3
https://github.com/scummvm/scummvm/commit/f2bced65aca1e98bc75e4e2e6a5fd12eba95fcf3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-31T16:56:48-04:00
Commit Message:
SHERLOCK: Implemented Tattoo UI drawInterface
Changed paths:
engines/sherlock/tattoo/tattoo_user_interface.cpp
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp
index a97b6f7..e1568b4 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.cpp
+++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp
@@ -89,9 +89,53 @@ void TattooUserInterface::drawInterface(int bufferNum) {
if (scene._mask != nullptr)
screen._flushScreen = true;
- //if (screen._flushScreen)
- // screen.blockMove(_currentScroll.x);
+ if (screen._flushScreen)
+ screen.blockMove(_currentScroll);
+ // If there are UI widgets open, slam the areas they were drawn on to the physical screen
+ if (_menuBuffer != nullptr)
+ screen.slamArea(_menuBounds.left - _currentScroll.x, _menuBounds.top, _menuBounds.width(), _menuBounds.height());
+
+ if (_invMenuBuffer != nullptr)
+ screen.slamArea(_invMenuBounds.left - _currentScroll.x, _invMenuBounds.top, _invMenuBounds.width(), _invMenuBounds.height());
+
+ // If therea re widgets being cleared, then restore that area of the screen
+ if (_oldMenuBounds.right) {
+ screen.slamArea(_oldMenuBounds.left - _currentScroll.x, _oldMenuBounds.top, _oldMenuBounds.width(), _oldMenuBounds.height());
+ _oldMenuBounds.left = _oldMenuBounds.top = _oldMenuBounds.right = _oldMenuBounds.bottom = 0;
+ }
+
+ if (_oldInvMenuBounds.left) {
+ screen.slamArea(_oldInvMenuBounds.left - _currentScroll.x, _oldInvMenuBounds.top, _oldInvMenuBounds.width(), _oldInvMenuBounds.height());
+ _oldInvMenuBounds.left = _oldInvMenuBounds.top = _oldInvMenuBounds.right = _oldInvMenuBounds.bottom = 0;
+ }
+
+ // See if need to clear any tags
+ if (_oldTagBounds.right) {
+ screen.slamArea(_oldTagBounds.left - _currentScroll.x, _oldTagBounds.top, _oldTagBounds.width(), _oldTagBounds.height());
+
+ // If there's no tag actually being displayed, then reset bounds so we don't keep restoring the area
+ if (_tagBuffer == nullptr) {
+ _tagBounds.left = _tagBounds.top = _tagBounds.right = _tagBounds.bottom = 0;
+ _oldTagBounds.left = _oldTagBounds.top = _oldTagBounds.right = _oldTagBounds.bottom = 0;
+ }
+ }
+ if (_tagBuffer != nullptr)
+ screen.slamArea(_tagBounds.left - _currentScroll.x, _tagBounds.top, _tagBounds.width(), _tagBounds.height());
+
+ // See if we need to flush areas assocaited with the inventory graphic
+ if (_oldInvGraphicBounds.right) {
+ screen.slamArea(_oldInvGraphicBounds.left - _currentScroll.x, _oldInvGraphicBounds.top,
+ _oldInvGraphicBounds.width(), _oldInvGraphicBounds.height());
+
+ // If there's no graphic actually being displayed, then reset bounds so we don't keep restoring the area
+ if (_invGraphic == nullptr) {
+ _invGraphicBounds.left = _invGraphicBounds.top = _invGraphicBounds.right = _invGraphicBounds.bottom = 0;
+ _oldInvGraphicBounds.left = _oldInvGraphicBounds.top = _oldInvGraphicBounds.right = _oldInvGraphicBounds.bottom = 0;
+ }
+ }
+ if (_invGraphic != nullptr)
+ screen.slamArea(_invGraphicBounds.left - _currentScroll.x, _invGraphicBounds.top, _invGraphicBounds.width(), _invGraphicBounds.height());
}
void TattooUserInterface::doBgAnimRestoreUI() {
Commit: 90be81b284d1263bb8ebbd4dbf8f0ae41dec4ddc
https://github.com/scummvm/scummvm/commit/90be81b284d1263bb8ebbd4dbf8f0ae41dec4ddc
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-05-31T23:28:28+02:00
Commit Message:
SHERLOCK: debug levels for AdLib & Music
Changed paths:
engines/sherlock/music.cpp
engines/sherlock/scalpel/drivers/adlib.cpp
engines/sherlock/sherlock.cpp
engines/sherlock/sherlock.h
diff --git a/engines/sherlock/music.cpp b/engines/sherlock/music.cpp
index 0735f41..ebfdc26 100644
--- a/engines/sherlock/music.cpp
+++ b/engines/sherlock/music.cpp
@@ -151,16 +151,16 @@ void MidiParser_SH::parseNextEvent(EventInfo &info) {
}
} else if (info.event == 0xFC) {
// Official End-Of-Track signal
- warning("System META event 0xFC");
+ debugC(kDebugLevelMusic, "Music: System META event 0xFC");
byte type = *(_position._playPos++);
switch (type) {
case 0x80: // end of track, triggers looping
- warning("META event triggered looping");
+ debugC(kDebugLevelMusic, "Music: META event triggered looping");
jumpToTick(0, true, true, false);
break;
case 0x81: // end of track, stop playing
- warning("META event triggered music stop");
+ debugC(kDebugLevelMusic, "Music: META event triggered music stop");
stopPlaying();
unloadMusic();
break;
@@ -180,7 +180,7 @@ void MidiParser_SH::parseNextEvent(EventInfo &info) {
}
bool MidiParser_SH::loadMusic(byte *data, uint32 size) {
- warning("loadMusic");
+ debugC(kDebugLevelMusic, "Music: loadMusic()");
unloadMusic();
byte *headerPtr = data;
@@ -242,7 +242,7 @@ Music::Music(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
}
bool Music::loadSong(int songNumber) {
- warning("loadSong");
+ debugC(kDebugLevelMusic, "Music: loadSong()");
if(songNumber == 100)
songNumber = 55;
@@ -285,7 +285,7 @@ bool Music::playMusic(const Common::String &name) {
if (!_musicOn)
return false;
- warning("Sound::playMusic %s", name.c_str());
+ debugC(kDebugLevelMusic, "Music: playMusic('%s')", name.c_str());
Common::SeekableReadStream *stream = _vm->_res->load(name, "MUSIC.LIB");
byte *data = new byte[stream->size()];
@@ -305,13 +305,13 @@ bool Music::playMusic(const Common::String &name) {
#endif
if (dataSize < 14) {
- warning("not enough data in music file");
+ warning("Music: not enough data in music file");
return false;
}
byte *dataPos = data;
if (memcmp(" ", dataPos, 12)) {
- warning("Expected header not found in music file");
+ warning("Music: expected header not found in music file");
return false;
}
dataPos += 12;
@@ -319,7 +319,7 @@ bool Music::playMusic(const Common::String &name) {
uint16 headerSize = READ_LE_UINT16(dataPos);
if (headerSize != 0x7F) {
- warning("music header is not as expected");
+ warning("Music: header is not as expected");
return false;
}
diff --git a/engines/sherlock/scalpel/drivers/adlib.cpp b/engines/sherlock/scalpel/drivers/adlib.cpp
index db1151c..5411c74 100644
--- a/engines/sherlock/scalpel/drivers/adlib.cpp
+++ b/engines/sherlock/scalpel/drivers/adlib.cpp
@@ -287,7 +287,7 @@ private:
int MidiDriver_AdLib::open() {
int rate = _mixer->getOutputRate();
- debug(3, "ADLIB: Starting driver");
+ debugC(kDebugLevelAdLibDriver, "AdLib: starting driver");
_opl = OPL::Config::create(OPL::Config::kOpl2);
@@ -406,11 +406,11 @@ void MidiDriver_AdLib::send(uint32 b) {
// Aftertouch doesn't seem to be implemented in the Sherlock Holmes adlib driver
break;
case 0xe0:
- warning("pitch bend change");
+ debugC(kDebugLevelAdLibDriver, "AdLib: pitch bend change");
pitchBendChange(channel, op1, op2);
break;
case 0xf0: // SysEx
- warning("SysEx: %x", b);
+ warning("ADLIB: SysEx: %x", b);
break;
default:
warning("ADLIB: Unknown event %02x", command);
@@ -453,7 +453,7 @@ void MidiDriver_AdLib::noteOn(byte MIDIchannel, byte note, byte velocity) {
}
if (oldestInUseChannel >= 0) {
// channel found
- warning("used In-Use channel");
+ debugC(kDebugLevelAdLibDriver, "AdLib: used In-Use channel");
// original driver used note 0, we use the current note
// because using note 0 could create a bad note (out of index) and we check that. Original driver didn't.
voiceOnOff(oldestInUseChannel, false, _channels[oldestInUseChannel].currentNote, 0);
@@ -464,11 +464,10 @@ void MidiDriver_AdLib::noteOn(byte MIDIchannel, byte note, byte velocity) {
voiceOnOff(oldestInUseChannel, true, note, velocity);
return;
}
- warning("MIDI channel not mapped/all FM voice channels busy %d", MIDIchannel);
+ debugC(kDebugLevelAdLibDriver, "AdLib: MIDI channel not mapped/all FM voice channels busy %d", MIDIchannel);
} else {
// Percussion channel
- warning("percussion!");
for (byte FMvoiceChannel = 0; FMvoiceChannel < SHERLOCK_ADLIB_VOICES_COUNT; FMvoiceChannel++) {
if (_voiceChannelMapping[FMvoiceChannel] == MIDIchannel) {
if (note == adlib_percussionChannelTable[FMvoiceChannel].requiredNote) {
@@ -480,7 +479,7 @@ void MidiDriver_AdLib::noteOn(byte MIDIchannel, byte note, byte velocity) {
}
}
}
- warning("percussion MIDI channel not mapped/all FM voice channels busy");
+ debugC(kDebugLevelAdLibDriver, "AdLib: percussion MIDI channel not mapped/all FM voice channels busy");
}
}
@@ -519,7 +518,7 @@ void MidiDriver_AdLib::voiceOnOff(byte FMvoiceChannel, bool keyOn, byte note, by
frequencyOffset = note;
}
if (frequencyOffset >= SHERLOCK_ADLIB_NOTES_COUNT) {
- warning("CRITICAL - bad note!!!");
+ warning("CRITICAL - AdLib driver: bad note!!!");
return;
}
frequency = adlib_FrequencyLookUpTable[frequencyOffset];
diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp
index d3a409a..5ebf9e5 100644
--- a/engines/sherlock/sherlock.cpp
+++ b/engines/sherlock/sherlock.cpp
@@ -71,7 +71,9 @@ SherlockEngine::~SherlockEngine() {
}
void SherlockEngine::initialize() {
- DebugMan.addDebugChannel(kDebugScript, "scripts", "Script debug level");
+ DebugMan.addDebugChannel(kDebugLevelScript, "scripts", "Script debug level");
+ DebugMan.addDebugChannel(kDebugLevelAdLibDriver, "AdLib", "AdLib driver debugging");
+ DebugMan.addDebugChannel(kDebugLevelMusic, "Music", "Music debugging");
ImageFile::setVm(this);
Object::setVm(this);
diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h
index e71c729..078e9ea 100644
--- a/engines/sherlock/sherlock.h
+++ b/engines/sherlock/sherlock.h
@@ -51,7 +51,9 @@
namespace Sherlock {
enum {
- kDebugScript = 1 << 0
+ kDebugLevelScript = 1 << 0,
+ kDebugLevelAdLibDriver = 2 << 0,
+ kDebugLevelMusic = 3 << 0,
};
enum GameType {
Commit: c79b0d1db9d9ce6529674e2c982e76bb68d93eb6
https://github.com/scummvm/scummvm/commit/c79b0d1db9d9ce6529674e2c982e76bb68d93eb6
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2015-05-31T23:29:54+02:00
Commit Message:
SHERLOCK: Silence GCC warning
Changed paths:
engines/sherlock/sherlock.h
diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h
index 078e9ea..16dacd3 100644
--- a/engines/sherlock/sherlock.h
+++ b/engines/sherlock/sherlock.h
@@ -53,7 +53,7 @@ namespace Sherlock {
enum {
kDebugLevelScript = 1 << 0,
kDebugLevelAdLibDriver = 2 << 0,
- kDebugLevelMusic = 3 << 0,
+ kDebugLevelMusic = 3 << 0
};
enum GameType {
Commit: 6b8452538fb9fa608394f407123a1c622ebf1ba6
https://github.com/scummvm/scummvm/commit/6b8452538fb9fa608394f407123a1c622ebf1ba6
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-31T17:55:56-04:00
Commit Message:
SHERLOCK: Implement remainder of RT doBgAnim
Changed paths:
engines/sherlock/objects.cpp
engines/sherlock/objects.h
engines/sherlock/people.cpp
engines/sherlock/people.h
engines/sherlock/screen.cpp
engines/sherlock/screen.h
engines/sherlock/sherlock.cpp
engines/sherlock/sherlock.h
engines/sherlock/tattoo/tattoo.cpp
engines/sherlock/tattoo/tattoo.h
engines/sherlock/tattoo/tattoo_scene.cpp
engines/sherlock/tattoo/tattoo_scene.h
engines/sherlock/tattoo/tattoo_user_interface.cpp
engines/sherlock/tattoo/tattoo_user_interface.h
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index 8818f80..4527c4e 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -364,6 +364,10 @@ void Sprite::checkSprite() {
}
}
+const Common::Rect Sprite::getOldBounds() const {
+ return Common::Rect(_oldPosition.x, _oldPosition.y, _oldPosition.x + _oldSize.x, _oldPosition.y + _oldSize.y);
+}
+
/*----------------------------------------------------------------*/
void WalkSequence::load(Common::SeekableReadStream &s) {
diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h
index d671066..54cea69 100644
--- a/engines/sherlock/objects.h
+++ b/engines/sherlock/objects.h
@@ -242,6 +242,11 @@ public:
* Return frame height
*/
int frameHeight() const { return _imageFrame ? _imageFrame->_frame.h : 0; }
+
+ /**
+ * Returns the old bounsd for the sprite from the previous frame
+ */
+ const Common::Rect getOldBounds() const;
};
enum { OBJ_BEHIND = 1, OBJ_FLIPPED = 2, OBJ_FORWARD = 4, TURNON_OBJ = 0x20, TURNOFF_OBJ = 0x40 };
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp
index 0ef49ff..7686d52 100644
--- a/engines/sherlock/people.cpp
+++ b/engines/sherlock/people.cpp
@@ -79,6 +79,10 @@ void Person::clearNPC() {
_npcName = "";
}
+void Person::updateNPC() {
+ // TODO
+}
+
/*----------------------------------------------------------------*/
People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) {
diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h
index 013727d..32faee5 100644
--- a/engines/sherlock/people.h
+++ b/engines/sherlock/people.h
@@ -76,6 +76,7 @@ public:
Common::String _npcName;
int _tempX;
int _tempScaleVal;
+ bool _updateNPCPath;
// Rose Tattoo fields
Common::String _walkVGSName; // Name of walk library person is using
@@ -86,6 +87,11 @@ public:
* Clear the NPC related data
*/
void clearNPC();
+
+ /**
+ * Update the NPC
+ */
+ void updateNPC();
};
class SherlockEngine;
diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp
index 708493c..6c59c3b 100644
--- a/engines/sherlock/screen.cpp
+++ b/engines/sherlock/screen.cpp
@@ -306,6 +306,18 @@ void Screen::flushScaleImage(ImageFrame *frame, const Common::Point &pt, int16 *
*height = newBounds.height();
}
+void Screen::flushImage(ImageFrame *frame, const Common::Point &pt, Common::Rect &newBounds, int scaleVal) {
+ Common::Point newPos, newSize;
+
+ if (scaleVal == 256)
+ flushImage(frame, pt, &newPos.x, &newPos.y, &newSize.x, &newSize.y);
+ else
+ flushScaleImage(frame, pt, &newPos.x, &newPos.y, &newSize.x, &newSize.y, scaleVal);
+
+ // Transfer the pos and size amounts into a single bounds rect
+ newBounds = Common::Rect(newPos.x, newPos.y, newPos.x + newSize.x, newPos.y + newSize.y);
+}
+
void Screen::blockMove(const Common::Rect &r, const Common::Point &scrollPos) {
Common::Rect bounds = r;
bounds.translate(scrollPos.x, scrollPos.y);
diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h
index 2774673..7d49c52 100644
--- a/engines/sherlock/screen.h
+++ b/engines/sherlock/screen.h
@@ -190,6 +190,11 @@ public:
int16 *width, int16 *height, int scaleVal);
/**
+ * Variation of flushImage/flushScaleImage that takes in and updates a rect
+ */
+ void flushImage(ImageFrame *frame, const Common::Point &pt, Common::Rect &newBounds, int scaleVal);
+
+ /**
* Copies data from the back buffer to the screen, taking into account scrolling position
*/
void blockMove(const Common::Rect &r, const Common::Point &scrollPos);
diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp
index 5ebf9e5..67a1552 100644
--- a/engines/sherlock/sherlock.cpp
+++ b/engines/sherlock/sherlock.cpp
@@ -50,6 +50,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam
_canLoadSave = false;
_showOriginalSavesDialog = false;
_interactiveFl = true;
+ _fastMode = false;
}
SherlockEngine::~SherlockEngine() {
diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h
index 16dacd3..c233373 100644
--- a/engines/sherlock/sherlock.h
+++ b/engines/sherlock/sherlock.h
@@ -123,6 +123,7 @@ public:
bool _canLoadSave;
bool _showOriginalSavesDialog;
bool _interactiveFl;
+ bool _fastMode;
public:
SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc);
virtual ~SherlockEngine();
diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp
index 368b24b..765016b 100644
--- a/engines/sherlock/tattoo/tattoo.cpp
+++ b/engines/sherlock/tattoo/tattoo.cpp
@@ -72,6 +72,10 @@ void TattooEngine::drawCredits() {
// TODO
}
+void TattooEngine::blitCredits() {
+ // TODO
+}
+
void TattooEngine::eraseCredits() {
// TODO
}
diff --git a/engines/sherlock/tattoo/tattoo.h b/engines/sherlock/tattoo/tattoo.h
index bb6310d..28fa77f 100644
--- a/engines/sherlock/tattoo/tattoo.h
+++ b/engines/sherlock/tattoo/tattoo.h
@@ -59,6 +59,11 @@ public:
void drawCredits();
/**
+ * Blit the drawn credits to the screen
+ */
+ void blitCredits();
+
+ /**
* Erase any area of the screen covered by credits
*/
void eraseCredits();
diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp
index cd86a58..8a3c586 100644
--- a/engines/sherlock/tattoo/tattoo_scene.cpp
+++ b/engines/sherlock/tattoo/tattoo_scene.cpp
@@ -196,15 +196,15 @@ void TattooScene::doBgAnimEraseBackground() {
}
void TattooScene::doBgAnim() {
+ TattooEngine &vm = *(TattooEngine *)_vm;
+ Events &events = *_vm->_events;
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
+ Talk &talk = *_vm->_talk;
TattooUserInterface &ui = *((TattooUserInterface *)_vm->_ui);
doBgAnimCheckCursor();
-// Events &events = *_vm->_events;
- People &people = *_vm->_people;
-// Scene &scene = *_vm->_scene;
- Screen &screen = *_vm->_screen;
- Talk &talk = *_vm->_talk;
screen.setDisplayBounds(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
talk._talkToAbort = false;
@@ -226,6 +226,23 @@ void TattooScene::doBgAnim() {
doBgAnimUpdateBgObjectsAndAnim();
ui.drawInterface();
+
+ doBgAnimDrawSprites();
+
+ if (vm._creditsActive)
+ vm.blitCredits();
+
+ if (!vm._fastMode)
+ events.wait(3);
+
+ screen._flushScreen = false;
+ _doBgAnimDone = false;
+ ui._drawMenu = false;
+
+ for (uint idx = 1; idx < MAX_CHARACTERS; ++idx) {
+ if (people[idx]._updateNPCPath)
+ people[idx].updateNPC();
+ }
}
void TattooScene::doBgAnimUpdateBgObjectsAndAnim() {
@@ -288,7 +305,6 @@ void TattooScene::doBgAnimUpdateBgObjectsAndAnim() {
}
}
-
void TattooScene::updateBackground() {
People &people = *_vm->_people;
Screen &screen = *_vm->_screen;
@@ -397,6 +413,83 @@ void TattooScene::updateBackground() {
screen._flushScreen = false;
}
+void TattooScene::doBgAnimDrawSprites() {
+ People &people = *_vm->_people;
+ Screen &screen = *_vm->_screen;
+ TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
+
+ for (uint idx = 0; idx < MAX_CHARACTERS; ++idx) {
+ Person &person = people[idx];
+
+ if (person._type != INVALID) {
+ if (_goToScene == -1 || _cAnim.size() == 0) {
+ if (person._type == REMOVE) {
+ screen.slamRect(person.getOldBounds());
+ person._type = INVALID;
+ } else {
+ if (person._tempScaleVal == 256) {
+ screen.flushImage(person._imageFrame, Common::Point(person._tempX, person._position.y / FIXED_INT_MULTIPLIER
+ - person.frameHeight()), &person._oldPosition.x, &person._oldPosition.y, &person._oldSize.x, &person._oldSize.y);
+ } else {
+ int ts = person._imageFrame->sDrawYSize(person._tempScaleVal);
+ int ty = person._position.y / FIXED_INT_MULTIPLIER - ts;
+ screen.flushScaleImage(person._imageFrame, Common::Point(person._tempX, ty),
+ &person._oldPosition.x, &person._oldPosition.y, &person._oldSize.x, &person._oldSize.y, person._tempScaleVal);
+ }
+ }
+ }
+ }
+ }
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &obj = _bgShapes[idx];
+
+ if (obj._type == ACTIVE_BG_SHAPE || obj._type == REMOVE) {
+ if (_goToScene == -1) {
+ if (obj._scaleVal == 256)
+ screen.flushImage(obj._imageFrame, obj._position, &obj._oldPosition.x, &obj._oldPosition.y,
+ &obj._oldSize.x, &obj._oldSize.y);
+ else
+ screen.flushScaleImage(obj._imageFrame, obj._position, &obj._oldPosition.x, &obj._oldPosition.y,
+ &obj._oldSize.x, &obj._oldSize.y, obj._scaleVal);
+
+ if (obj._type == REMOVE)
+ obj._type = INVALID;
+ }
+ }
+ }
+
+ for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
+ Object &obj = _bgShapes[idx];
+
+ if (_goToScene == -1) {
+ if (obj._type == NO_SHAPE && (obj._flags & 1) == 0) {
+ screen.slamRect(obj.getNoShapeBounds());
+ screen.slamRect(obj.getOldBounds());
+ } else if (obj._type == HIDE_SHAPE) {
+ if (obj._scaleVal == 256)
+ screen.flushImage(obj._imageFrame, obj._position, &obj._oldPosition.x, &obj._oldPosition.y,
+ &obj._oldSize.x, &obj._oldSize.y);
+ else
+ screen.flushScaleImage(obj._imageFrame, obj._position, &obj._oldPosition.x, &obj._oldPosition.y,
+ &obj._oldSize.x, &obj._oldSize.y, obj._scaleVal);
+ obj._type = HIDDEN;
+ }
+ }
+ }
+
+ if (_activeCAnim._images != nullptr || _activeCAnim._zPlacement == REMOVE) {
+ if (_activeCAnim._zPlacement != REMOVE) {
+ screen.flushImage(_activeCAnim._imageFrame, _activeCAnim._position, _activeCAnim._oldBounds, _activeCAnim._scaleVal);
+ } else {
+ screen.slamArea(_activeCAnim._removeBounds.left - ui._currentScroll.x, _activeCAnim._removeBounds.top,
+ _activeCAnim._removeBounds.width(), _activeCAnim._removeBounds.height());
+ _activeCAnim._removeBounds.left = _activeCAnim._removeBounds.top = 0;
+ _activeCAnim._removeBounds.right = _activeCAnim._removeBounds.bottom = 0;
+ _activeCAnim._zPlacement = -1; // Reset _zPlacement so we don't REMOVE again
+ }
+ }
+}
} // End of namespace Tattoo
diff --git a/engines/sherlock/tattoo/tattoo_scene.h b/engines/sherlock/tattoo/tattoo_scene.h
index de28306..91e7ad4 100644
--- a/engines/sherlock/tattoo/tattoo_scene.h
+++ b/engines/sherlock/tattoo/tattoo_scene.h
@@ -44,6 +44,8 @@ private:
* Update the background objects and canimations as part of doBgAnim
*/
void doBgAnimUpdateBgObjectsAndAnim();
+
+ void doBgAnimDrawSprites();
protected:
/**
* Checks all the background shapes. If a background shape is animating,
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp
index e1568b4..6779cc4 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.cpp
+++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp
@@ -34,6 +34,7 @@ TattooUserInterface::TattooUserInterface(SherlockEngine *vm): UserInterface(vm)
_tagBuffer = nullptr;
_invGraphic = nullptr;
_scrollSize = _scrollSpeed = 0;
+ _drawMenu = false;
}
void TattooUserInterface::initScrollVars() {
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.h b/engines/sherlock/tattoo/tattoo_user_interface.h
index fea9ca8..db6a04f 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.h
+++ b/engines/sherlock/tattoo/tattoo_user_interface.h
@@ -53,6 +53,7 @@ private:
public:
Common::Point _currentScroll, _targetScroll;
int _scrollSize, _scrollSpeed;
+ bool _drawMenu;
public:
TattooUserInterface(SherlockEngine *vm);
Commit: 79bf0a05eeba502943a178fc7098a1876ad9244c
https://github.com/scummvm/scummvm/commit/79bf0a05eeba502943a178fc7098a1876ad9244c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-31T17:57:20-04:00
Commit Message:
SHERLOCK: Remove unused variable
Changed paths:
engines/sherlock/scalpel/tsage/logo.cpp
diff --git a/engines/sherlock/scalpel/tsage/logo.cpp b/engines/sherlock/scalpel/tsage/logo.cpp
index 8cc5f99..76fa653 100644
--- a/engines/sherlock/scalpel/tsage/logo.cpp
+++ b/engines/sherlock/scalpel/tsage/logo.cpp
@@ -304,7 +304,6 @@ bool Object::isMoving() const {
void Object::move() {
Common::Point currPos = _position;
Common::Point moveDiff(5, 3);
- int yDiff = 0;
int percent = 100;
if (dontMove())
Commit: 171117677de3663f636cafb8acf0397a879d4ccc
https://github.com/scummvm/scummvm/commit/171117677de3663f636cafb8acf0397a879d4ccc
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-06-01T00:12:00+02:00
Commit Message:
SHERLOCK: implement 2 palette faes for the intro
Changed paths:
engines/sherlock/scalpel/scalpel.cpp
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index 43b6906..113c4ee 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -440,8 +440,13 @@ void ScalpelEngine::showOpening() {
}
bool ScalpelEngine::showCityCutscene() {
+ byte greyPalette[PALETTE_SIZE];
byte palette[PALETTE_SIZE];
+ // Demo fades from black into grey and then fades from grey into the scene
+ Common::fill(&greyPalette[0], &greyPalette[PALETTE_SIZE], 142);
+ _screen->fadeIn((const byte *)greyPalette, 3);
+
_music->playMusic("prolog1.mus");
_animation->_gfxLibraryFilename = "title.lib";
_animation->_soundLibraryFilename = "title.snd";
@@ -569,7 +574,10 @@ bool ScalpelEngine::scrollCredits() {
// Load the images for displaying credit text
Common::SeekableReadStream *stream = _res->load("credits.vgs", "title.lib");
ImageFile creditsImages(*stream);
- _screen->setPalette(creditsImages._palette);
+
+ // Demo fades slowly from the scene into credits palette
+ _screen->fadeIn(creditsImages._palette, 3);
+
delete stream;
// Save a copy of the screen background for use in drawing each credit frame
Commit: d52aa528d5b0f135792b63cf6730c186e137a434
https://github.com/scummvm/scummvm/commit/d52aa528d5b0f135792b63cf6730c186e137a434
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-05-31T18:16:47-04:00
Commit Message:
SHERLOCK: Formatting fix
Changed paths:
engines/sherlock/scalpel/tsage/logo.cpp
diff --git a/engines/sherlock/scalpel/tsage/logo.cpp b/engines/sherlock/scalpel/tsage/logo.cpp
index 76fa653..ca4903e 100644
--- a/engines/sherlock/scalpel/tsage/logo.cpp
+++ b/engines/sherlock/scalpel/tsage/logo.cpp
@@ -334,9 +334,7 @@ void Object::move() {
currPos.y += ySign;
_majorDiff -= ABS(xAmount);
-
- }
- else {
+ } else {
int yAmount = _moveSign.y * moveDiff.y * percent / 100;
if (!yAmount)
yAmount = _moveSign.y;
Commit: e028eb442500fa457a8d8bf84105abd0e6f2e883
https://github.com/scummvm/scummvm/commit/e028eb442500fa457a8d8bf84105abd0e6f2e883
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-06-01T00:35:24+02:00
Commit Message:
SHERLOCK: intro changes
- shortened delay during "in the alley" text,
so that music track change occurs correctly
- added fade to black during alley cutscene
Changed paths:
engines/sherlock/scalpel/scalpel.cpp
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index 113c4ee..ca3befb 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -507,7 +507,7 @@ bool ScalpelEngine::showCityCutscene() {
// In the alley...
_screen->transBlitFrom(titleImages[3], Common::Point(72, 51));
_screen->fadeIn(palette, 3);
- finished = _events->delay(3000, true);
+ finished = _events->delay(2500, true);
}
}
@@ -524,8 +524,16 @@ bool ScalpelEngine::showAlleyCutscene() {
_animation->_soundLibraryFilename = "TITLE.SND";
bool finished = _animation->play("27PRO1", 1, 3, true, 2);
- if (finished)
+ if (finished) {
+ _screen->getPalette(palette);
+ _screen->fadeToBlack(2);
+ finished = _events->delay(500);
+ }
+
+ if (finished) {
+ _screen->setPalette(palette);
finished = _animation->play("27PRO2", 1, 0, false, 2);
+ }
if (finished) {
showLBV("scream.lbv");
Commit: 3b2c04521270709176a41c7dc84d7b2a76f0d2f3
https://github.com/scummvm/scummvm/commit/3b2c04521270709176a41c7dc84d7b2a76f0d2f3
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2015-06-01T03:47:33+03:00
Commit Message:
SHERLOCK: Fix bug when opening the journal
Changed paths:
engines/sherlock/journal.cpp
diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp
index b4b05da..a3c12a6 100644
--- a/engines/sherlock/journal.cpp
+++ b/engines/sherlock/journal.cpp
@@ -154,7 +154,7 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
// Find the person being referred to
talk._talkTo = -1;
for (int idx = 0; idx < (int)people._characters.size(); ++idx) {
- Common::String portrait = people[idx]._portrait;
+ Common::String portrait = people._characters[idx]._portrait;
Common::String numStr(portrait.c_str(), portrait.c_str() + 4);
if (locStr == numStr) {
Commit: 621ed75677a6f51369a9a77c05637fb3d31eb835
https://github.com/scummvm/scummvm/commit/621ed75677a6f51369a9a77c05637fb3d31eb835
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2015-06-01T04:16:48+03:00
Commit Message:
SHERLOCK: Clean up the static people data arrays
Changed paths:
engines/sherlock/scalpel/scalpel.cpp
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index ca3befb..15678c1 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -92,280 +92,80 @@ static const byte MAP_SEQUENCES[3][MAX_FRAME] = {
#define MAX_PEOPLE 66
-const char PEOPLE_PORTRAITS[MAX_PEOPLE][5] = {
- { "HOLM" }, // Sherlock Holmes
- { "WATS" }, // Dr. Watson
- { "LEST" }, // Inspector Lestrade
- { "CON1" }, // Constable O'Brien
- { "CON2" }, // Constable Lewis
- { "SHEI" }, // Sheila Parker
- { "HENR" }, // Henry Carruthers
- { "LESL" }, // Lesley (flower girl)
- { "USH1" }, // Usher #1
- { "USH2" }, // Usher #2
- { "FRED" }, // Fredrick Epstein
- { "WORT" }, // Mrs. Worthington
- { "COAC" }, // Coach
- { "PLAY" }, // Player
- { "WBOY" }, // Tim (Waterboy)
- { "JAME" }, // James Sanders
- { "BELL" }, // Belle (perfumerie)
- { "GIRL" }, // Cleaning Girl (perfumerie)
- { "EPST" }, // Epstien in the Opera Balcony
- { "WIGG" }, // Wiggins
- { "PAUL" }, // Paul (Brumwell / Carroway)
- { "BART" }, // Bartender
- { "DIRT" }, // Dirty Drunk
- { "SHOU" }, // Shouting Drunk
- { "STAG" }, // Staggering Drunk
- { "BOUN" }, // Bouncer
- { "SAND" }, // James Sanders - At Home
- { "CORO" }, // The Coroner
- { "EQUE" }, // The Equestrian Shop Keeper
- { "GEOR" }, // George Blackwood
- { "LARS" }, // Lars
- { "PARK" }, // Sheila Parker (happy)
- { "CHEM" }, // Chemist
- { "GREG" }, // Inspector Gregson
- { "LAWY" }, // Jacob Farthington Lawyer
- { "MYCR" }, // Mycroft
- { "SHER" }, // Old Sherman
- { "CHMB" }, // Richard Chemist Stock boy
- { "BARM" }, // Barman
- { "DAND" }, // Dandy Player
- { "ROUG" }, // Rough-looking Player
- { "SPEC" }, // Spectator
- { "HUNT" }, // Robert Hunt
- { "VIOL" }, // Violet Secretary
- { "PETT" }, // Pettigrew
- { "APPL" }, // Augie (apple seller)
- { "ANNA" }, // Anna Carroway
- { "GUAR" }, // Guard
- { "ANTO" }, // Antonio Caruso
- { "TOBY" }, // Toby the Dog
- { "KING" }, // Simon Kingsley
- { "ALFR" }, // Alfred Tobacco Clerk
- { "LADY" }, // Lady Brumwell
- { "ROSA" }, // Madame Rosa
- { "LADB" }, // Lady Brumwell
- { "MOOR" }, // Joseph Moorehead
- { "BEAL" }, // Mrs. Beale
- { "LION" }, // Felix the Lion
- { "HOLL" }, // Hollingston
- { "CALL" }, // Constable Callaghan
- { "JERE" }, // Sergeant Jeremy Duncan
- { "LORD" }, // Lord Brumwell
- { "NIGE" }, // Nigel Jameson
- { "JONA" }, // Jonas (newspaper seller)
- { "DUGA" }, // Constable Dugan
- { "INSP" } // Inspector Lestrade (Scotland Yard)
+struct PeopleData {
+ const char *portrait;
+ const char *name;
+ byte stillSequences[MAX_TALK_SEQUENCES];
+ byte talkSequences[MAX_TALK_SEQUENCES];
};
-const char *const PEOPLE_NAMES[MAX_PEOPLE] = {
- "Sherlock Holmes",
- "Dr. Watson",
- "Inspector Lestrade",
- "Constable O'Brien",
- "Constable Lewis",
- "Sheila Parker",
- "Henry Carruthers",
- "Lesley",
- "An Usher",
- "An Usher",
- "Fredrick Epstein",
- "Mrs. Worthington",
- "The Coach",
- "A Player",
- "Tim",
- "James Sanders",
- "Belle",
- "Cleaning Girl",
- "Fredrick Epstein",
- "Wiggins",
- "Paul",
- "The Bartender",
- "A Dirty Drunk",
- "A Shouting Drunk",
- "A Staggering Drunk",
- "The Bouncer",
- "James Sanders",
- "The Coroner",
- "Reginald Snipes",
- "George Blackwood",
- "Lars",
- "Sheila Parker",
- "The Chemist",
- "Inspector Gregson",
- "Jacob Farthington",
- "Mycroft",
- "Old Sherman",
- "Richard",
- "The Barman",
- "A Dandy Player",
- "A Rough-looking Player",
- "A Spectator",
- "Robert Hunt",
- "Violet",
- "Pettigrew",
- "Augie",
- "Anna Carroway",
- "A Guard",
- "Antonio Caruso",
- "Toby the Dog",
- "Simon Kingsley",
- "Alfred",
- "Lady Brumwell",
- "Madame Rosa",
- "Lady Brumwell",
- "Joseph Moorehead",
- "Mrs. Beale",
- "Felix",
- "Hollingston",
- "Constable Callaghan",
- "Sergeant Duncan",
- "Lord Brumwell",
- "Nigel Jaimeson",
- "Jonas",
- "Constable Dugan",
- "Inspector Lestrade"
-};
-
-static const byte PEOPLE_STILL_SEQUENCES[MAX_PEOPLE][MAX_TALK_SEQUENCES] = {
- { 1, 0, 0 }, // Sherlock Holmes
- { 6, 0, 0 }, // Dr. Watson
- { 4, 0, 0 }, // Inspector Lestrade
- { 2, 0, 0 }, // Constable #1
- { 2, 0, 0 }, // Constable #2
- { 2, 0, 0 }, // Sheila Parker
- { 3, 0, 0 }, // Henry Carruthers
- { 9, 0, 0 }, // Lesly (flower girl)
- { 13, 0, 0 }, // Usher #1
- { 2, 0, 0 }, // Usher #2
- { 4, 0, 0 }, // Fredrick Epstein
- { 9, 0, 0 }, // Mrs.Worthington
- { 2, 0, 0 }, // Coach
- { 8, 0, 0 }, // Player
- { 13, 0, 0 }, // Waterboy
- { 6, 0, 0 }, // James Sanders
- { 1, 0, 0 }, // Belle (perfumerie)
- { 20, 0, 0 }, // Cleaning Girl (perfumerie)
- { 17, 0, 0 }, // Epstien in the Opera Balcony
- { 3, 0, 0 }, // Wiggins
- { 2, 0, 0 }, // Paul (Brumwell/Carroway)
- { 1, 0, 0 }, // Bartender
- { 1, 0, 0 }, // Dirty Drunk
- { 1, 0, 0 }, // Shouting Drunk
- { 1, 0, 0 }, // Staggering Drunk
- { 1, 0, 0 }, // Bouncer
- { 6, 0, 0 }, // James Sanders - At Home
- { 6, 0, 0 }, // The Coroner
- { 1, 0, 0 }, // The Equestrian Shop Keeper
- { 1, 0, 0 }, // George Blackwood
- { 7, 0, 0 }, // Lars
- { 1, 0, 0 }, // Sheila Parker
- { 8, 0, 0 }, // Chemist
- { 6, 0, 0 }, // Inspector Gregson
- { 1, 0, 0 }, // Lawyer
- { 1, 0, 0 }, // Mycroft
- { 7, 0, 0 }, // Old Sherman
- { 1, 0, 0 }, // Stock Boy in Chemist Shop
- { 1, 0, 0 }, // Barman
- { 1, 0, 0 }, // Dandy Player
- { 1, 0, 0 }, // Rough-looking Player
- { 1, 0, 0 }, // Spectator
- { 1, 0, 0 }, // Robert Hunt
- { 3, 0, 0 }, // Violet Secretary
- { 1, 0, 0 }, // Pettigrew
- { 8, 0, 0 }, // Augie (apple seller)
- { 16, 0, 0 }, // Anna Carroway
- { 1, 0, 0 }, // Guard
- { 8, 0, 0 }, // Antonio Caruso
- { 1, 0, 0 }, // Toby the Dog
- { 13, 0, 0 }, // Simon Kingsley
- { 2, 0, 0 }, // Alfred Tobacco Clerk
- { 1, 0, 0 }, // Lady Brumwell
- { 1, 0, 0 }, // Madame Rosa
- { 1, 0, 0 }, // Lady Brumwell
- { 1, 0, 0 }, // Joseph Moorehead
- { 5, 0, 0 }, // Mrs. Beale
- { 1, 0, 0 }, // Felix the Lion
- { 1, 0, 0 }, // Hollingston
- { 1, 0, 0 }, // Constable Callaghan
- { 2, 0, 0 }, // Sergeant Jeremy Duncan
- { 1, 0, 0 }, // Lord Brumwell
- { 1, 0, 0 }, // Nigel Jameson
- { 1, 0, 0 }, // Jonas (newspaper seller)
- { 1, 0, 0 }, // Constable Dugan
- { 4, 0, 0 } // Inspector Lestrade (Yard)
-};
-
-static const byte PEOPLE_TALK_SEQUENCES[MAX_PEOPLE][MAX_TALK_SEQUENCES] = {
- { 1, 0, 0 }, // Sherlock Holmes
- { 5, 5, 6, 7, 8, 7, 8, 6, 0, 0 }, // Dr. Watson
- { 2, 0, 0 }, // Inspector Lestrade
- { 1, 0, 0 }, // Constable #1
- { 1, 0, 0 }, // Constable #2
- { 2, 3, 0, 0 }, // Sheila Parker
- { 3, 0, 0 }, // Henry Carruthers
- { 1, 2, 3, 2, 1, 2, 3, 0, 0 }, // Lesly (flower girl)
- { 13, 14, 0, 0 }, // Usher #1
- { 2, 0, 0 }, // Usher #2
- { 1, 2, 3, 4, 3, 4, 3, 2, 0, 0 }, // Fredrick Epstein
- { 8, 0, 0 }, // Mrs.Worthington
- { 1, 2, 3, 4, 5, 4, 3, 2, 0, 0 }, // Coach
- { 7, 8, 0, 0 }, // Player
- { 12, 13, 0, 0 }, // Waterboy
- { 3, 4, 0, 0 }, // James Sanders
- { 4, 5, 0, 0 }, // Belle (perfumerie)
- { 14, 15, 16, 17, 18, 19, 20, 20, 20, 0, 0 }, // Cleaning Girl (perfumerie)
- { 16, 17, 18, 18, 18, 17, 17, 0, 0 }, // Epstien in the Opera Balcony
- { 2, 3, 0, 0 }, // Wiggins
- { 1, 2, 0, 0 }, // Paul (Brumwell/Carroway)
- { 1, 0, 0 }, // Bartender
- { 1, 0, 0 }, // Dirty Drunk
- { 1, 0, 0 }, // Shouting Drunk
- { 1, 0, 0 }, // Staggering Drunk
- { 1, 0, 0 }, // Bouncer
- { 5, 6, 0, 0 }, // James Sanders - At Home
- { 4, 5, 0, 0 }, // The Coroner
- { 1, 0, 0 }, // The Equestrian Shop Keeper
- { 1, 0, 0 }, // George Blackwood
- { 5, 6, 0, 0 }, // Lars
- { 1, 0, 0 }, // Sheila Parker
- { 8, 9, 0, 0 }, // Chemist
- { 5, 6, 0, 0 }, // Inspector Gregson
- { 1, 0, 0 }, // Lawyer
- { 1, 0, 0 }, // Mycroft
- { 7, 8, 0, 0 }, // Old Sherman
- { 1, 0, 0 }, // Stock Boy in Chemist Shop
- { 1, 0, 0 }, // Barman
- { 1, 0, 0 }, // Dandy Player
- { 1, 0, 0 }, // Rough-looking Player
- { 1, 0, 0 }, // Spectator
- { 1, 0, 0 }, // Robert Hunt
- { 3, 4, 0, 0 }, // Violet Secretary
- { 1, 0, 0 }, // Pettigrew
- { 14, 15, 0, 0 }, // Augie (apple seller)
- { 3, 4, 5, 6, 0, 0 }, // Anna Carroway
- { 4, 5, 6, 0, 0 }, // Guard
- { 7, 8, 0, 0 }, // Antonio Caruso
- { 1, 0, 0 }, // Toby the Dog
- { 13, 14, 0, 0 }, // Simon Kingsley
- { 2, 3, 0, 0 }, // Alfred Tobacco Clerk
- { 3, 4, 0, 0 }, // Lady Brumwell
- { 1, 30, 0, 0 }, // Madame Rosa
- { 3, 4, 0, 0 }, // Lady Brumwell
- { 1, 0, 0 }, // Joseph Moorehead
- { 14, 15, 16, 17, 18, 19, 20, 0, 0 }, // Mrs. Beale
- { 1, 0, 0 }, // Felix the Lion
- { 1, 0, 0 }, // Hollingston
- { 1, 0, 0 }, // Constable Callaghan
- { 1, 1, 2, 2, 0, 0 }, // Sergeant Jeremy Duncan
- { 9, 10, 0, 0 }, // Lord Brumwell
- { 1, 2, 0, 138, 3, 4, 0, 138, 0, 0 }, // Nigel Jameson
- { 1, 8, 0, 0 }, // Jonas (newspaper seller)
- { 1, 0, 0 }, // Constable Dugan
- { 2, 0, 0 } // Inspector Lestrade (Yard)
+const PeopleData PEOPLE_DATA[MAX_PEOPLE] = {
+ { "HOLM", "Sherlock Holmes", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "WATS", "Dr. Watson", { 6, 0, 0 }, { 5, 5, 6, 7, 8, 7, 8, 6, 0, 0 } },
+ { "LEST", "Inspector Lestrade", { 4, 0, 0 }, { 2, 0, 0 } },
+ { "CON1", "Constable O'Brien", { 2, 0, 0 }, { 1, 0, 0 } },
+ { "CON2", "Constable Lewis", { 2, 0, 0 }, { 1, 0, 0 } },
+ { "SHEI", "Sheila Parker", { 2, 0, 0 }, { 2, 3, 0, 0 } },
+ { "HENR", "Henry Carruthers", { 3, 0, 0 }, { 3, 0, 0 } },
+ { "LESL", "Lesley", { 9, 0, 0 }, { 1, 2, 3, 2, 1, 2, 3, 0, 0 } },
+ { "USH1", "An Usher", { 13, 0, 0 }, { 13, 14, 0, 0 } },
+ { "USH2", "An Usher", { 2, 0, 0 }, { 2, 0, 0 } },
+ { "FRED", "Fredrick Epstein", { 4, 0, 0 }, { 1, 2, 3, 4, 3, 4, 3, 2, 0, 0 } },
+ { "WORT", "Mrs. Worthington", { 9, 0, 0 }, { 8, 0, 0 } },
+ { "COAC", "The Coach", { 2, 0, 0 }, { 1, 2, 3, 4, 5, 4, 3, 2, 0, 0 } },
+ { "PLAY", "A Player", { 8, 0, 0 }, { 7, 8, 0, 0 } },
+ { "WBOY", "Tim", { 13, 0, 0 }, { 12, 13, 0, 0 } },
+ { "JAME", "James Sanders", { 6, 0, 0 }, { 3, 4, 0, 0 } },
+ { "BELL", "Belle", { 1, 0, 0 }, { 4, 5, 0, 0 } },
+ { "GIRL", "Cleaning Girl", { 20, 0, 0 }, { 14, 15, 16, 17, 18, 19, 20, 20, 20, 0, 0 } },
+ { "EPST", "Fredrick Epstein", { 17, 0, 0 }, { 16, 17, 18, 18, 18, 17, 17, 0, 0 } },
+ { "WIGG", "Wiggins", { 3, 0, 0 }, { 2, 3, 0, 0 } },
+ { "PAUL", "Paul", { 2, 0, 0 }, { 1, 2, 0, 0 } },
+ { "BART", "The Bartender", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "DIRT", "A Dirty Drunk", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "SHOU", "A Shouting Drunk", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "STAG", "A Staggering Drunk", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "BOUN", "The Bouncer", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "SAND", "James Sanders", { 6, 0, 0 }, { 5, 6, 0, 0 } },
+ { "CORO", "The Coroner", { 6, 0, 0 }, { 4, 5, 0, 0 } },
+ { "EQUE", "Reginald Snipes", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "GEOR", "George Blackwood", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "LARS", "Lars", { 7, 0, 0 }, { 5, 6, 0, 0 } },
+ { "PARK", "Sheila Parker", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "CHEM", "The Chemist", { 8, 0, 0 }, { 8, 9, 0, 0 } },
+ { "GREG", "Inspector Gregson", { 6, 0, 0 }, { 5, 6, 0, 0 } },
+ { "LAWY", "Jacob Farthington", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "MYCR", "Mycroft", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "SHER", "Old Sherman", { 7, 0, 0 }, { 7, 8, 0, 0 } },
+ { "CHMB", "Richard", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "BARM", "The Barman", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "DAND", "A Dandy Player", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "ROUG", "A Rough-looking Player", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "SPEC", "A Spectator", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "HUNT", "Robert Hunt", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "VIOL", "Violet", { 3, 0, 0 }, { 3, 4, 0, 0 } },
+ { "PETT", "Pettigrew", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "APPL", "Augie", { 8, 0, 0 }, { 14, 15, 0, 0 } },
+ { "ANNA", "Anna Carroway", { 16, 0, 0 }, { 3, 4, 5, 6, 0, 0 } },
+ { "GUAR", "A Guard", { 1, 0, 0 }, { 4, 5, 6, 0, 0 } },
+ { "ANTO", "Antonio Caruso", { 8, 0, 0 }, { 7, 8, 0, 0 } },
+ { "TOBY", "Toby the Dog", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "KING", "Simon Kingsley", { 13, 0, 0 }, { 13, 14, 0, 0 } },
+ { "ALFR", "Alfred", { 2, 0, 0 }, { 2, 3, 0, 0 } },
+ { "LADY", "Lady Brumwell", { 1, 0, 0 }, { 3, 4, 0, 0 } },
+ { "ROSA", "Madame Rosa", { 1, 0, 0 }, { 1, 30, 0, 0 } },
+ { "LADB", "Lady Brumwell", { 1, 0, 0 }, { 3, 4, 0, 0 } },
+ { "MOOR", "Joseph Moorehead", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "BEAL", "Mrs. Beale", { 5, 0, 0 }, { 14, 15, 16, 17, 18, 19, 20, 0, 0 } },
+ { "LION", "Felix", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "HOLL", "Hollingston", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "CALL", "Constable Callaghan", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "JERE", "Sergeant Duncan", { 2, 0, 0 }, { 1, 1, 2, 2, 0, 0 } },
+ { "LORD", "Lord Brumwell", { 1, 0, 0 }, { 9, 10, 0, 0 } },
+ { "NIGE", "Nigel Jaimeson", { 1, 0, 0 }, { 1, 2, 0, 138, 3, 4, 0, 138, 0, 0 } },
+ { "JONA", "Jonas", { 1, 0, 0 }, { 1, 8, 0, 0 } },
+ { "DUGA", "Constable Dugan", { 1, 0, 0 }, { 1, 0, 0 } },
+ { "INSP", "Inspector Lestrade", { 4, 0, 0 }, { 2, 0, 0 } }
};
/*----------------------------------------------------------------*/
@@ -404,8 +204,8 @@ void ScalpelEngine::initialize() {
// Set up list of people
for (int idx = 0; idx < MAX_PEOPLE; ++idx)
- _people->_characters.push_back(PersonData(PEOPLE_NAMES[idx], PEOPLE_PORTRAITS[idx],
- PEOPLE_STILL_SEQUENCES[idx], PEOPLE_TALK_SEQUENCES[idx]));
+ _people->_characters.push_back(PersonData(PEOPLE_DATA[idx].name, PEOPLE_DATA[idx].portrait,
+ PEOPLE_DATA[idx].stillSequences, PEOPLE_DATA[idx].talkSequences));
_animation->setPrologueNames(&PROLOGUE_NAMES[0], PROLOGUE_NAMES_COUNT);
_animation->setPrologueFrames(&PROLOGUE_FRAMES[0][0], 6, 9);
Commit: bf12f04c451589789a1823b8a1aa9111b340aee2
https://github.com/scummvm/scummvm/commit/bf12f04c451589789a1823b8a1aa9111b340aee2
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2015-06-01T04:19:54+03:00
Commit Message:
SHERLOCK: Fix closing namespace comments
Changed paths:
engines/sherlock/scalpel/darts.cpp
engines/sherlock/scalpel/scalpel.cpp
engines/sherlock/tattoo/tattoo.cpp
diff --git a/engines/sherlock/scalpel/darts.cpp b/engines/sherlock/scalpel/darts.cpp
index 8d78335..cdd3915 100644
--- a/engines/sherlock/scalpel/darts.cpp
+++ b/engines/sherlock/scalpel/darts.cpp
@@ -554,4 +554,4 @@ void Darts::setFlagsForDarts(int flagNum) {
} // End of namespace Scalpel
-} // End of namespace Scalpel
+} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index 15678c1..854f968 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -733,4 +733,4 @@ void ScalpelEngine::flushMirror12() {
} // End of namespace Scalpel
-} // End of namespace Scalpel
+} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp
index 765016b..abafc7b 100644
--- a/engines/sherlock/tattoo/tattoo.cpp
+++ b/engines/sherlock/tattoo/tattoo.cpp
@@ -82,4 +82,4 @@ void TattooEngine::eraseCredits() {
} // End of namespace Tattoo
-} // End of namespace Scalpel
+} // End of namespace Sherlock
Commit: 2143ade072d44065a13a378b040b686adfbdacad
https://github.com/scummvm/scummvm/commit/2143ade072d44065a13a378b040b686adfbdacad
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2015-06-01T08:04:49+02:00
Commit Message:
SHERLOCK: Erase the hand cursor when that part of the intro is done
Changed paths:
engines/sherlock/scalpel/tsage/logo.cpp
diff --git a/engines/sherlock/scalpel/tsage/logo.cpp b/engines/sherlock/scalpel/tsage/logo.cpp
index ca4903e..32a68c1 100644
--- a/engines/sherlock/scalpel/tsage/logo.cpp
+++ b/engines/sherlock/scalpel/tsage/logo.cpp
@@ -583,6 +583,7 @@ void Logo::nextFrame() {
case 205:
// Show a highlighting of the company name
+ _objects[2].erase();
_objects[2].remove();
_objects[3].setVisage(19, 1);
_objects[3]._position = Common::Point(155, 94);
Commit: 049ca42bb231080c97c9afc2c778fc375787870c
https://github.com/scummvm/scummvm/commit/049ca42bb231080c97c9afc2c778fc375787870c
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-06-01T12:10:20+02:00
Commit Message:
SHERLOCK: intro timing + fixes
Changed paths:
engines/sherlock/music.cpp
engines/sherlock/music.h
engines/sherlock/scalpel/scalpel.cpp
diff --git a/engines/sherlock/music.cpp b/engines/sherlock/music.cpp
index ebfdc26..b72e4d4 100644
--- a/engines/sherlock/music.cpp
+++ b/engines/sherlock/music.cpp
@@ -356,5 +356,39 @@ void Music::freeSong() {
void Music::waitTimerRoland(uint time) {
// TODO
warning("TODO: Sound::waitTimerRoland");
-}} // End of namespace Sherlock
+}
+
+bool Music::waitUntilTick(uint32 tick, uint32 maxTick, uint32 additionalDelay, uint32 noMusicDelay) {
+ uint32 currentTick = 0;
+
+ if (!_midiParser.isPlaying()) {
+ return _vm->_events->delay(noMusicDelay, true);
+ }
+ while (1) {
+ if (!_midiParser.isPlaying()) { // Music has stopped playing -> we are done
+ if (additionalDelay > 0) {
+ if (!_vm->_events->delay(additionalDelay, true))
+ return false;
+ }
+ return true;
+ }
+
+ currentTick = _midiParser.getTick();
+ //warning("waitUntilTick: %lx", currentTick);
+
+ if (currentTick <= maxTick) {
+ if (currentTick >= tick) {
+ if (additionalDelay > 0) {
+ if (!_vm->_events->delay(additionalDelay, true))
+ return false;
+ }
+ return true;
+ }
+ }
+ if (!_vm->_events->delay(10, true))
+ return false;
+ }
+}
+
+} // End of namespace Sherlock
diff --git a/engines/sherlock/music.h b/engines/sherlock/music.h
index 0ebc3e9..e651dd7 100644
--- a/engines/sherlock/music.h
+++ b/engines/sherlock/music.h
@@ -98,6 +98,8 @@ public:
void stopMusic();
void waitTimerRoland(uint time);
+
+ bool waitUntilTick(uint32 tick, uint32 maxTick, uint32 additionalDelay, uint32 noMusicDelay);
};
} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index 854f968..e3aa424 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -307,7 +307,9 @@ bool ScalpelEngine::showCityCutscene() {
// In the alley...
_screen->transBlitFrom(titleImages[3], Common::Point(72, 51));
_screen->fadeIn(palette, 3);
- finished = _events->delay(2500, true);
+
+ // Wait until the track got looped and the first few notes were played
+ finished = _music->waitUntilTick(0x104, 0x500, 0, 2500);
}
}
@@ -323,11 +325,16 @@ bool ScalpelEngine::showAlleyCutscene() {
_animation->_gfxLibraryFilename = "TITLE.LIB";
_animation->_soundLibraryFilename = "TITLE.SND";
+ // Fade "In The Alley..." text to black
+ _screen->fadeToBlack(2);
+
bool finished = _animation->play("27PRO1", 1, 3, true, 2);
if (finished) {
_screen->getPalette(palette);
_screen->fadeToBlack(2);
- finished = _events->delay(500);
+
+ // wait until second lower main note
+ finished = _music->waitUntilTick(0x64a, 0xFFFF, 0, 1000); // 652
}
if (finished) {
@@ -337,7 +344,17 @@ bool ScalpelEngine::showAlleyCutscene() {
if (finished) {
showLBV("scream.lbv");
- finished = _events->delay(6000);
+
+ // wait until first "scream" in music happened
+ finished = _music->waitUntilTick(0xabe, 0xFFFF, 0, 6000);
+ }
+
+ if (finished) {
+ // quick fade out
+ _screen->fadeToBlack(1);
+
+ // wait until after third "scream" in music happened
+ finished = _music->waitUntilTick(0xb80, 0xFFFF, 0, 2000);
}
if (finished)
@@ -351,9 +368,13 @@ bool ScalpelEngine::showAlleyCutscene() {
if (finished) {
ImageFile titleImages("title3.vgs", true);
// "Early the following morning on Baker Street..."
- _screen->_backBuffer1.transBlitFrom(titleImages[0], Common::Point(35, 51), false, 0);
- _screen->fadeIn(palette, 3);
- finished = _events->delay(1000);
+ _screen->transBlitFrom(titleImages[0], Common::Point(35, 51));
+
+ // fast fade-in
+ _screen->fadeIn(palette, 1);
+
+ // wait for music to end and wait an additional 2.5 seconds
+ finished = _music->waitUntilTick(0xFFFF, 0xFFFF, 2500, 3000);
}
_animation->_gfxLibraryFilename = "";
@@ -367,7 +388,18 @@ bool ScalpelEngine::showStreetCutscene() {
_music->playMusic("PROLOG3.MUS");
- bool finished = _animation->play("14KICK", 1, 3, true, 2);
+ // wait a bit
+ bool finished = _events->delay(500);
+
+ if (finished) {
+ // fade out "Early the following morning..."
+ _screen->fadeToBlack(2);
+
+ // wait for music a bit
+ finished = _music->waitUntilTick(0xE4, 0xFFFF, 0, 1000);
+ }
+
+ finished = _animation->play("14KICK", 1, 3, true, 2);
if (finished)
finished = _animation->play("14NOTE", 1, 0, false, 2);
Commit: 3025a44157a75ead6c36298179eb6b92f9796c3f
https://github.com/scummvm/scummvm/commit/3025a44157a75ead6c36298179eb6b92f9796c3f
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-06-01T13:00:29+02:00
Commit Message:
SHERLOCK: fix flicker during EA logo intro
Changed paths:
engines/sherlock/scalpel/tsage/logo.cpp
diff --git a/engines/sherlock/scalpel/tsage/logo.cpp b/engines/sherlock/scalpel/tsage/logo.cpp
index 32a68c1..769f58c 100644
--- a/engines/sherlock/scalpel/tsage/logo.cpp
+++ b/engines/sherlock/scalpel/tsage/logo.cpp
@@ -384,15 +384,15 @@ bool Logo::show(ScalpelEngine *vm) {
while (!logo->finished()) {
logo->nextFrame();
- events.wait(2);
- events.setButtonState();
-
// Erase areas from previous frame, and update and re-draw objects
for (int idx = 0; idx < 4; ++idx)
logo->_objects[idx].erase();
for (int idx = 0; idx < 4; ++idx)
logo->_objects[idx].update();
+ events.wait(2);
+ events.setButtonState();
+
interrupted = vm->shouldQuit() || events.kbHit() || events._pressed;
if (interrupted) {
// Keyboard or mouse button pressed, so break out of logo display
Commit: de837f2719d1960372a79db4404b9c36e38a159f
https://github.com/scummvm/scummvm/commit/de837f2719d1960372a79db4404b9c36e38a159f
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-06-01T13:07:48+02:00
Commit Message:
SHERLOCK: add fade out to street scene intro
Changed paths:
engines/sherlock/scalpel/scalpel.cpp
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index e3aa424..275380e 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -404,6 +404,10 @@ bool ScalpelEngine::showStreetCutscene() {
if (finished)
finished = _animation->play("14NOTE", 1, 0, false, 2);
+ // Fade to black
+ if (finished)
+ _screen->fadeToBlack(1);
+
_animation->_gfxLibraryFilename = "";
_animation->_soundLibraryFilename = "";
return finished;
Commit: c20fbeaf6f99714c9b62f619915f0b7275089e90
https://github.com/scummvm/scummvm/commit/c20fbeaf6f99714c9b62f619915f0b7275089e90
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-06-01T13:26:34+02:00
Commit Message:
SHERLOCK: add comments about waitUntilTick()
Changed paths:
engines/sherlock/music.cpp
diff --git a/engines/sherlock/music.cpp b/engines/sherlock/music.cpp
index b72e4d4..a6f1e5b 100644
--- a/engines/sherlock/music.cpp
+++ b/engines/sherlock/music.cpp
@@ -358,6 +358,9 @@ void Music::waitTimerRoland(uint time) {
warning("TODO: Sound::waitTimerRoland");
}
+// This is used to wait for the music in certain situations like especially the intro
+// Note: the original game didn't do this, instead it just waited for certain amounts of time
+// We do this, so that the intro graphics + music work together even on faster/slower hardware.
bool Music::waitUntilTick(uint32 tick, uint32 maxTick, uint32 additionalDelay, uint32 noMusicDelay) {
uint32 currentTick = 0;
Commit: b752c1f5bb1e9e1db83ed6f4368bfe6f6e2f151e
https://github.com/scummvm/scummvm/commit/b752c1f5bb1e9e1db83ed6f4368bfe6f6e2f151e
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-06-01T13:40:00+02:00
Commit Message:
SHERLOCK: intro: play constable anim slower
Changed paths:
engines/sherlock/scalpel/scalpel.cpp
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index 275380e..20e53e9 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -224,12 +224,14 @@ void ScalpelEngine::showOpening() {
if (isDemo() && _interactiveFl)
return;
+#if 0
if (!TsAGE::Logo::show(this))
return;
if (!showCityCutscene())
return;
if (!showAlleyCutscene())
return;
+#endif
if (!showStreetCutscene())
return;
if (!showOfficeCutscene())
@@ -401,8 +403,10 @@ bool ScalpelEngine::showStreetCutscene() {
finished = _animation->play("14KICK", 1, 3, true, 2);
+ // Constable animation plays slower than speed 2
+ // If we play it with speed 2, music gets obviously out of sync
if (finished)
- finished = _animation->play("14NOTE", 1, 0, false, 2);
+ finished = _animation->play("14NOTE", 1, 0, false, 3);
// Fade to black
if (finished)
Commit: 0500dc2408f27d4cd93a2631ac64bdbd80e30336
https://github.com/scummvm/scummvm/commit/0500dc2408f27d4cd93a2631ac64bdbd80e30336
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-06-01T13:40:44+02:00
Commit Message:
SHERLOCK: remove debug #ifs
Changed paths:
engines/sherlock/scalpel/scalpel.cpp
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index 20e53e9..3483828 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -224,14 +224,12 @@ void ScalpelEngine::showOpening() {
if (isDemo() && _interactiveFl)
return;
-#if 0
if (!TsAGE::Logo::show(this))
return;
if (!showCityCutscene())
return;
if (!showAlleyCutscene())
return;
-#endif
if (!showStreetCutscene())
return;
if (!showOfficeCutscene())
Commit: d0a0f85fc524fc6e744c2a73c5c2413d411b4041
https://github.com/scummvm/scummvm/commit/d0a0f85fc524fc6e744c2a73c5c2413d411b4041
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2015-06-01T22:55:35+02:00
Commit Message:
SHERLOCK: Remove unnecessary object positioning
The final piece of the logo animation doesn't move, so we only need
to set its position once. Obviously this could be further simplified.
Changed paths:
engines/sherlock/scalpel/tsage/logo.cpp
diff --git a/engines/sherlock/scalpel/tsage/logo.cpp b/engines/sherlock/scalpel/tsage/logo.cpp
index 769f58c..50021dd 100644
--- a/engines/sherlock/scalpel/tsage/logo.cpp
+++ b/engines/sherlock/scalpel/tsage/logo.cpp
@@ -591,7 +591,6 @@ void Logo::nextFrame() {
case 213:
_objects[3]._frame = 2;
- _objects[3]._position = Common::Point(155, 94);
break;
case 221:
@@ -600,32 +599,26 @@ void Logo::nextFrame() {
case 222:
_objects[3]._frame = 3;
- _objects[3]._position = Common::Point(155, 94);
break;
case 230:
_objects[3]._frame = 4;
- _objects[3]._position = Common::Point(155, 94);
break;
case 238:
_objects[3]._frame = 5;
- _objects[3]._position = Common::Point(155, 94);
break;
case 246:
_objects[3]._frame = 6;
- _objects[3]._position = Common::Point(155, 94);
break;
case 254:
_objects[3]._frame = 7;
- _objects[3]._position = Common::Point(155, 94);
break;
case 262:
_objects[3]._frame = 8;
- _objects[3]._position = Common::Point(155, 94);
break;
default:
More information about the Scummvm-git-logs
mailing list