diff --git a/engines/sherlock/decompress.h b/engines/sherlock/decompress.h deleted file mode 100644 index 694f56aa6553..000000000000 --- a/engines/sherlock/decompress.h +++ /dev/null @@ -1,36 +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_DECOMPRESS_H -#define SHERLOCK_DECOMPRESS_H - -#include "common/memstream.h" - -namespace Sherlock { - -#include "common/stream.h" - -Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source, int32 outSize = -1); - -} // namespace Sherlock - -#endif diff --git a/engines/sherlock/detection.cpp b/engines/sherlock/detection.cpp index 78ab33bfd031..2804ec1d31f3 100644 --- a/engines/sherlock/detection.cpp +++ b/engines/sherlock/detection.cpp @@ -25,6 +25,7 @@ #include "sherlock/scalpel/scalpel.h" #include "sherlock/tattoo/tattoo.h" #include "common/system.h" +#include "common/translation.h" #include "engines/advancedDetector.h" namespace Sherlock { @@ -57,11 +58,29 @@ static const PlainGameDescriptor sherlockGames[] = { {0, 0} }; + +#define GAMEOPTION_ORIGINAL_SAVES GUIO_GAMEOPTIONS1 + +static const ADExtraGuiOptionsMap optionsList[] = { + { + GAMEOPTION_ORIGINAL_SAVES, + { + _s("Use original savegame dialog"), + _s("Files button in-game shows original savegame dialog rather than ScummVM menu"), + "originalsaveload", + false + } + }, + + AD_EXTRA_GUI_OPTIONS_TERMINATOR +}; + #include "sherlock/detection_tables.h" class SherlockMetaEngine : public AdvancedMetaEngine { public: - SherlockMetaEngine() : AdvancedMetaEngine(Sherlock::gameDescriptions, sizeof(Sherlock::SherlockGameDescription), sherlockGames) {} + SherlockMetaEngine() : AdvancedMetaEngine(Sherlock::gameDescriptions, sizeof(Sherlock::SherlockGameDescription), + sherlockGames, optionsList) {} virtual const char *getName() const { return "Sherlock Engine"; diff --git a/engines/sherlock/detection_tables.h b/engines/sherlock/detection_tables.h index 975b7323ec00..8300a0ffcf7b 100644 --- a/engines/sherlock/detection_tables.h +++ b/engines/sherlock/detection_tables.h @@ -33,7 +33,7 @@ static const SherlockGameDescription gameDescriptions[] = { Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE | ADGF_NO_FLAGS, - GUIO1(GUIO_NOSPEECH) + GUIO2(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVES) }, GType_SerratedScalpel, }, diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp index d8c0104e6ccd..1997807d1573 100644 --- a/engines/sherlock/inventory.cpp +++ b/engines/sherlock/inventory.cpp @@ -49,8 +49,6 @@ Inventory::Inventory(SherlockEngine *vm) : Common::Array(), _vm(v _invGraphicsLoaded = false; _invIndex = 0; _holdings = 0; - _oldFlag = 0; - _invFlag = 0; _invMode = INVMODE_EXIT; } @@ -215,7 +213,6 @@ void Inventory::drawInventory(int flag) { UserInterface &ui = *_vm->_ui; int tempFlag = flag; - _oldFlag = 7; loadInv(); if (flag == 128) { @@ -257,10 +254,8 @@ void Inventory::drawInventory(int flag) { if (flag) { ui._oldKey = INVENTORY_COMMANDS[flag]; - _oldFlag = flag; } else { ui._oldKey = -1; - _invFlag = 6; } invCommands(0); diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h index f4cea7729a16..eb5aebdd7cb9 100644 --- a/engines/sherlock/inventory.h +++ b/engines/sherlock/inventory.h @@ -75,8 +75,6 @@ class Inventory : public Common::Array { int _holdings; // Used to hold number of visible items in active inventory. // Since Inventory array also contains some special hidden items void freeGraphics(); - int _oldFlag; - int _invFlag; public: Inventory(SherlockEngine *vm); ~Inventory(); diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index c2eedd46ee10..46e233bf7a89 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -146,6 +146,10 @@ int Map::show() { int oldFont = screen.fontNumber(); screen.setFont(0); + // Initial screen clear + screen._backBuffer1.clear(); + screen.clear(); + // Load the entire map ImageFile bigMap("bigmap.vgs"); screen.setPalette(bigMap._palette); diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h index 4432ec8553dc..4a418138b25b 100644 --- a/engines/sherlock/map.h +++ b/engines/sherlock/map.h @@ -29,7 +29,7 @@ #include "common/serializer.h" #include "common/str.h" #include "common/str-array.h" -#include "sherlock/graphics.h" +#include "sherlock/surface.h" #include "sherlock/objects.h" namespace Sherlock { diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk index babd0c49a0a3..2ded999ed17f 100644 --- a/engines/sherlock/module.mk +++ b/engines/sherlock/module.mk @@ -5,11 +5,9 @@ MODULE_OBJS = \ scalpel/scalpel.o \ tattoo/tattoo.o \ animation.o \ - decompress.o \ debugger.o \ detection.o \ events.o \ - graphics.o \ inventory.o \ journal.o \ map.o \ @@ -22,6 +20,7 @@ MODULE_OBJS = \ settings.o \ sherlock.o \ sound.o \ + surface.o \ talk.o \ user_interface.o diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index 9f2704ac62a0..bff80c234754 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -21,14 +21,14 @@ */ #include "sherlock/resources.h" -#include "sherlock/decompress.h" #include "sherlock/screen.h" #include "sherlock/sherlock.h" #include "common/debug.h" +#include "common/memstream.h" namespace Sherlock { -Cache::Cache() { +Cache::Cache(SherlockEngine *vm): _vm(vm) { } /** @@ -66,20 +66,17 @@ void Cache::load(const Common::String &name, Common::SeekableReadStream &stream) if (_resources.contains(name)) return; - // Check whether the file is compressed - const char LZW_HEADER[5] = { "LZV\x1a" }; - char header[5]; - stream.read(header, 5); - bool isCompressed = !strncmp(header, LZW_HEADER, 5); + int32 signature = stream.readUint32BE(); stream.seek(0); // Allocate a new cache entry _resources[name] = CacheEntry(); CacheEntry &cacheEntry = _resources[name]; - if (isCompressed) { + // 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 = decompressLZ(stream); + Common::SeekableReadStream *decompressed = _vm->_res->decompressLZ(stream); cacheEntry.resize(decompressed->size()); decompressed->read(&cacheEntry[0], decompressed->size()); @@ -102,7 +99,7 @@ Common::SeekableReadStream *Cache::get(const Common::String &filename) const { /*----------------------------------------------------------------*/ -Resources::Resources() { +Resources::Resources(SherlockEngine *vm): _vm(vm), _cache(vm) { _resourceIndex = -1; addToCache("vgs.lib"); @@ -169,8 +166,19 @@ Common::SeekableReadStream *Resources::load(const Common::String &filename) { stream->seek(entry._offset); Common::SeekableReadStream *resStream = stream->readStream(entry._size); - delete stream; - return resStream; + // Check whether the file is compressed + 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); + delete stream; + delete resStream; + return decompressed; + } else { + resStream->seek(0); + delete stream; + return resStream; + } } } @@ -402,4 +410,62 @@ 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)); + } + + uint32 size = source.readUint32LE(); + return decompressLZ(source, size); +} + +/** + * Decompresses an LZW block of data with a specified output size + */ +Common::SeekableReadStream *Resources::decompressLZ(Common::SeekableReadStream &source, uint32 outSize) { + 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); + + memset(lzWindow, 0xFF, 0xFEE); + lzWindowPos = 0xFEE; + cmd = 0; + + do { + cmd >>= 1; + if (!(cmd & 0x100)) + cmd = source.readByte() | 0xFF00; + + if (cmd & 1) { + byte literal = source.readByte(); + *outBuffer++ = literal; + lzWindow[lzWindowPos] = literal; + lzWindowPos = (lzWindowPos + 1) & 0x0FFF; + } else { + int copyPos, copyLen; + copyPos = source.readByte(); + copyLen = source.readByte(); + copyPos = copyPos | ((copyLen & 0xF0) << 4); + copyLen = (copyLen & 0x0F) + 3; + while (copyLen--) { + byte literal = lzWindow[copyPos]; + copyPos = (copyPos + 1) & 0x0FFF; + *outBuffer++ = literal; + lzWindow[lzWindowPos] = literal; + lzWindowPos = (lzWindowPos + 1) & 0x0FFF; + } + } + } while (outBuffer < outBufferEnd); + + return outS; +} + } // End of namespace Sherlock diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h index bbaac60a33fb..041f1c64a9bb 100644 --- a/engines/sherlock/resources.h +++ b/engines/sherlock/resources.h @@ -52,9 +52,10 @@ class SherlockEngine; class Cache { private: + SherlockEngine *_vm; CacheHash _resources; public: - Cache(); + Cache(SherlockEngine *_vm); bool isCached(const Common::String &filename) const; @@ -66,6 +67,7 @@ class Cache { class Resources { private: + SherlockEngine *_vm; Cache _cache; LibraryIndexes _indexes; int _resourceIndex; @@ -73,7 +75,7 @@ class Resources { 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); @@ -87,6 +89,9 @@ class Resources { bool exists(const Common::String &filename) const; int resourceIndex() const; + + static Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source, uint32 outSize); + Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source); }; struct ImageFrame { diff --git a/engines/sherlock/saveload.cpp b/engines/sherlock/saveload.cpp index a78b89b00cb6..b9ac3e79d68f 100644 --- a/engines/sherlock/saveload.cpp +++ b/engines/sherlock/saveload.cpp @@ -21,7 +21,7 @@ */ #include "sherlock/saveload.h" -#include "sherlock/graphics.h" +#include "sherlock/surface.h" #include "sherlock/sherlock.h" #include "common/system.h" #include "graphics/scaler.h" diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index b9820797147d..521aeb338b14 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -255,8 +255,9 @@ void ScalpelEngine::initialize() { _flags[39] = true; // Turn on Baker Street // 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]); diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index d4662ed55944..0a25d3dd0f57 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -23,7 +23,6 @@ #include "sherlock/scene.h" #include "sherlock/sherlock.h" #include "sherlock/scalpel/scalpel.h" -#include "sherlock/decompress.h" #include "sherlock/screen.h" namespace Sherlock { @@ -64,7 +63,10 @@ void BgFileHeader::synchronize(Common::SeekableReadStream &s, bool isRoseTattoo) /*----------------------------------------------------------------*/ -void BgfileheaderInfo::synchronize(Common::SeekableReadStream &s) { +/** + * Load the data for the object + */ +void BgfileheaderInfo::load(Common::SeekableReadStream &s) { _filesize = s.readUint32LE(); _maxFrames = s.readByte(); @@ -75,7 +77,10 @@ void BgfileheaderInfo::synchronize(Common::SeekableReadStream &s) { /*----------------------------------------------------------------*/ -void Exit::synchronize(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(); @@ -91,14 +96,20 @@ void Exit::synchronize(Common::SeekableReadStream &s) { /*----------------------------------------------------------------*/ -void SceneEntry::synchronize(Common::SeekableReadStream &s) { +/** + * Load the data for the object + */ +void SceneEntry::load(Common::SeekableReadStream &s) { _startPosition.x = s.readSint16LE(); _startPosition.y = s.readSint16LE(); _startDir = s.readByte(); _allow = s.readByte(); } -void SceneSound::synchronize(Common::SeekableReadStream &s) { +/** + * Load the data for the object + */ +void SceneSound::load(Common::SeekableReadStream &s) { char buffer[9]; s.read(buffer, 8); buffer[8] = '\0'; @@ -109,6 +120,9 @@ void SceneSound::synchronize(Common::SeekableReadStream &s) { /*----------------------------------------------------------------*/ +/** + * Retuurn the index of the passed object in the array + */ int ObjectArray::indexOf(const Object &obj) const { for (uint idx = 0; idx < size(); ++idx) { if (&(*this)[idx] == &obj) @@ -236,6 +250,7 @@ bool Scene::loadScene(const Common::String &filename) { Events &events = *_vm->_events; Map &map = *_vm->_map; People &people = *_vm->_people; + Resources &res = *_vm->_res; SaveManager &saves = *_vm->_saves; Screen &screen = *_vm->_screen; Sound &sound = *_vm->_sound; @@ -288,7 +303,7 @@ bool Scene::loadScene(const Common::String &filename) { // 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 { @@ -300,12 +315,12 @@ bool Scene::loadScene(const Common::String &filename) { 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 * shapeSize + bgHeader._descSize + bgHeader._seqSize); _bgShapes.resize(bgHeader._numStructs); @@ -333,7 +348,7 @@ bool Scene::loadScene(const Common::String &filename) { // Read in the image data Common::SeekableReadStream *imageStream = _lzwMode ? - decompressLZ(*rrmStream, bgInfo[idx]._filesize) : + Resources::decompressLZ(*rrmStream, bgInfo[idx]._filesize) : rrmStream->readStream(bgInfo[idx]._filesize); _images[idx + 1]._images = new ImageFile(*imageStream); @@ -362,7 +377,7 @@ bool Scene::loadScene(const Common::String &filename) { _cAnim.clear(); if (bgHeader._numcAnimations) { Common::SeekableReadStream *canimStream = _lzwMode ? - decompressLZ(*rrmStream, 65 * bgHeader._numcAnimations) : + Resources::decompressLZ(*rrmStream, 65 * bgHeader._numcAnimations) : rrmStream->readStream(65 * bgHeader._numcAnimations); _cAnim.resize(bgHeader._numcAnimations); @@ -375,7 +390,7 @@ bool Scene::loadScene(const Common::String &filename) { // Read in the room bounding areas int size = rrmStream->readUint16LE(); Common::SeekableReadStream *boundsStream = !_lzwMode ? rrmStream : - decompressLZ(*rrmStream, size); + Resources::decompressLZ(*rrmStream, size); _zones.resize(size / 10); for (uint idx = 0; idx < _zones.size(); ++idx) { @@ -402,7 +417,7 @@ bool Scene::loadScene(const Common::String &filename) { // Read in the walk data size = rrmStream->readUint16LE(); Common::SeekableReadStream *walkStream = !_lzwMode ? rrmStream : - decompressLZ(*rrmStream, size); + Resources::decompressLZ(*rrmStream, size); _walkData.resize(size); walkStream->read(&_walkData[0], size); @@ -415,17 +430,17 @@ bool Scene::loadScene(const Common::String &filename) { _exits.resize(numExits); for (int idx = 0; idx < numExits; ++idx) - _exits[idx].synchronize(*rrmStream); + _exits[idx].load(*rrmStream); // Read in the entrance - _entrance.synchronize(*rrmStream); + _entrance.load(*rrmStream); // Initialize sound list int numSounds = rrmStream->readByte(); _sounds.resize(numSounds); for (int idx = 0; idx < numSounds; ++idx) - _sounds[idx].synchronize(*rrmStream); + _sounds[idx].load(*rrmStream); for (int idx = 0; idx < numSounds; ++idx) sound.loadSound(_sounds[idx]._name, _sounds[idx]._priority); @@ -439,7 +454,7 @@ bool Scene::loadScene(const Common::String &filename) { // Read in the background Common::SeekableReadStream *bgStream = !_lzwMode ? rrmStream : - decompressLZ(*rrmStream, SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT); + Resources::decompressLZ(*rrmStream, SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT); bgStream->read(screen._backBuffer1.getPixels(), SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT); @@ -1013,7 +1028,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) { // Load the canimation into the cache Common::SeekableReadStream *imgStream = !_lzwMode ? rrmStream->readStream(cAnim._size) : - decompressLZ(*rrmStream, cAnim._size); + Resources::decompressLZ(*rrmStream, cAnim._size); res.addToCache(fname, *imgStream); delete imgStream; diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index b4b88fa0a17b..86b1e3d06387 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -65,7 +65,7 @@ struct BgfileheaderInfo { int _maxFrames; // How many unique frames in object Common::String _filename; // Filename of object - void synchronize(Common::SeekableReadStream &s); + void load(Common::SeekableReadStream &s); }; struct Exit { @@ -76,7 +76,7 @@ struct Exit { Common::Point _people; int _peopleDir; - void synchronize(Common::SeekableReadStream &s); + void load(Common::SeekableReadStream &s); }; struct SceneEntry { @@ -84,14 +84,14 @@ struct SceneEntry { int _startDir; int _allow; - void synchronize(Common::SeekableReadStream &s); + void load(Common::SeekableReadStream &s); }; struct SceneSound { Common::String _name; int _priority; - void synchronize(Common::SeekableReadStream &s); + void load(Common::SeekableReadStream &s); }; class ObjectArray: public Common::Array { diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 0ca10b4a4a7f..349bf4d024a2 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -149,6 +149,7 @@ void Screen::fadeToBlack(int speed) { } setPalette(tempPalette); + fillRect(Common::Rect(0, 0, this->w, this->h), 0); } /** @@ -169,7 +170,7 @@ void Screen::fadeIn(const byte palette[PALETTE_SIZE], int speed) { */ void Screen::addDirtyRect(const Common::Rect &r) { _dirtyRects.push_back(r); - assert(r.isValidRect() && r.width() > 0 && r.height() > 0); + assert(r.width() > 0 && r.height() > 0); } /** @@ -224,7 +225,7 @@ void Screen::randomTransition() { 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 --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 25389166d0c9..8a8eca13fc62 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -26,8 +26,7 @@ #include "common/list.h" #include "common/rect.h" #include "common/serializer.h" -#include "graphics/surface.h" -#include "sherlock/graphics.h" +#include "sherlock/surface.h" #include "sherlock/resources.h" namespace Sherlock { diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 318267bb8fdf..eea3dcb8679d 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -21,7 +21,7 @@ */ #include "sherlock/sherlock.h" -#include "sherlock/graphics.h" +#include "sherlock/surface.h" #include "common/scummsys.h" #include "common/config-manager.h" #include "common/debug-channels.h" @@ -47,6 +47,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _useEpilogue2 = false; _loadGameSlot = -1; _canLoadSave = false; + _showOriginalSavesDialog = false; } SherlockEngine::~SherlockEngine() { @@ -75,7 +76,7 @@ void SherlockEngine::initialize() { ImageFile::setVm(this); Object::setVm(this); Sprite::setVm(this); - _res = new Resources(); + _res = new Resources(this); _animation = new Animation(this); _debugger = new Debugger(this); _events = new Events(this); @@ -101,6 +102,9 @@ Common::Error SherlockEngine::run() { // Initialize the engine initialize(); + // Flag for whether to show original saves dialog rather than the ScummVM GMM + _showOriginalSavesDialog = ConfMan.getBool("originalsaveload"); + // If requested, load a savegame instead of showing the intro if (ConfMan.hasKey("save_slot")) { int saveSlot = ConfMan.getInt("save_slot"); @@ -122,6 +126,9 @@ Common::Error SherlockEngine::run() { if (shouldQuit()) break; + // Clear the screen + _screen->clear(); + // Reset UI flags _ui->reset(); @@ -207,26 +214,27 @@ void SherlockEngine::loadConfig() { // Load sound settings syncSoundSettings(); - // Load other settings - if (ConfMan.hasKey("font")) - _screen->setFont(ConfMan.getInt("font")); - if (ConfMan.hasKey("fade_style")) - _screen->_fadeStyle = ConfMan.getBool("fade_style"); - if (ConfMan.hasKey("help_style")) - _ui->_helpStyle = ConfMan.getBool("help_style"); - if (ConfMan.hasKey("window_style")) - _ui->_windowStyle = ConfMan.getInt("window_style"); - if (ConfMan.hasKey("portraits_on")) - _people->_portraitsOn = ConfMan.getBool("portraits_on"); + ConfMan.registerDefault("font", 1); + ConfMan.registerDefault("fade_style", true); + ConfMan.registerDefault("help_style", false); + ConfMan.registerDefault("window_style", 1); + ConfMan.registerDefault("portraits_on", true); + ConfMan.registerDefault("originalsaveload", false); + + _screen->setFont(ConfMan.getInt("font")); + _screen->_fadeStyle = ConfMan.getBool("fade_style"); + _ui->_helpStyle = ConfMan.getBool("help_style"); + _ui->_windowStyle = ConfMan.getInt("window_style"); + _people->_portraitsOn = ConfMan.getBool("portraits_on"); } /** * Saves game configuration information */ void SherlockEngine::saveConfig() { - ConfMan.setBool("mute", _sound->_digitized); - ConfMan.setBool("music_mute", _sound->_music); - ConfMan.setBool("speech_mute", _sound->_voices); + ConfMan.setBool("mute", !_sound->_digitized); + ConfMan.setBool("music_mute", !_sound->_music); + ConfMan.setBool("speech_mute", !_sound->_voices); ConfMan.setInt("font", _screen->fontNumber()); ConfMan.setBool("fade_style", _screen->_fadeStyle); diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index e21ac8c6d640..9261ad5b0532 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -108,6 +108,7 @@ class SherlockEngine : public Engine { bool _useEpilogue2; int _loadGameSlot; bool _canLoadSave; + bool _showOriginalSavesDialog; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index 70451a68da22..001907917f9b 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -45,7 +45,8 @@ Sound::Sound(SherlockEngine *vm, Audio::Mixer *mixer): _vm(vm), _mixer(mixer) { _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"); } /** @@ -92,7 +93,11 @@ bool Sound::playSound(const Common::String &name, WaitType waitType, int priorit Common::String filename = name; if (!filename.contains('.')) filename += ".SND"; - Common::SeekableReadStream *stream = _vm->_res->load(filename, "TITLE.SND"); + + Common::SeekableReadStream *stream = _vm->_res->load(filename); + + if (!stream) + error("Unable to find sound file '%s'", filename.c_str()); stream->skip(2); int size = stream->readUint32BE(); @@ -115,6 +120,15 @@ bool Sound::playSound(const Common::String &name, WaitType waitType, int priorit free(data); +#if 0 + // Debug : used to dump files + Common::DumpFile outFile; + outFile.open(filename); + outFile.write(decoded, (size - 2) * 2); + outFile.flush(); + outFile.close(); +#endif + Audio::AudioStream *audioStream = Audio::makeRawStream(decoded, (size - 2) * 2, rate, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES); _mixer->playStream(Audio::Mixer::kPlainSoundType, &_effectsHandle, audioStream, -1, Audio::Mixer::kMaxChannelVolume); _soundPlaying = true; @@ -138,14 +152,6 @@ bool Sound::playSound(const Common::String &name, WaitType waitType, int priorit _soundPlaying = false; _mixer->stopHandle(_effectsHandle); -#if 0 - // Debug : used to dump files - Common::DumpFile outFile; - outFile.open(filename); - outFile.write(decoded, (size - 2) * 2); - outFile.flush(); - outFile.close(); -#endif return retval; } diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/surface.cpp similarity index 88% rename from engines/sherlock/graphics.cpp rename to engines/sherlock/surface.cpp index 234928156af5..36e625794c61 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/surface.cpp @@ -20,7 +20,7 @@ * */ -#include "sherlock/graphics.h" +#include "sherlock/surface.h" #include "sherlock/sherlock.h" #include "common/system.h" #include "graphics/palette.h" @@ -62,28 +62,7 @@ void Surface::blitFrom(const Graphics::Surface &src) { * Draws a surface at a given position within this surface */ void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt) { - Common::Rect drawRect(0, 0, src.w, src.h); - Common::Point destPt = pt; - - if (destPt.x < 0) { - drawRect.left += -destPt.x; - destPt.x = 0; - } - if (destPt.y < 0) { - drawRect.top += -destPt.y; - destPt.y = 0; - } - int right = destPt.x + src.w; - if (right > this->w) { - drawRect.right -= (right - this->w); - } - int bottom = destPt.y + src.h; - if (bottom > this->h) { - drawRect.bottom -= (bottom - this->h); - } - - if (drawRect.isValidRect()) - blitFrom(src, destPt, drawRect); + blitFrom(src, pt, Common::Rect(0, 0, src.w, src.h)); } /** @@ -91,11 +70,10 @@ void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt) { */ void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds) { - Common::Rect destRect(pt.x, pt.y, pt.x + srcBounds.width(), - pt.y + srcBounds.height()); Common::Rect srcRect = srcBounds; + Common::Rect destRect(pt.x, pt.y, pt.x + srcRect.width(), pt.y + srcRect.height()); - if (clip(srcRect, destRect)) { + if (srcRect.isValidRect() && clip(srcRect, destRect)) { // Surface is at least partially or completely on-screen addDirtyRect(destRect); copyRectToSurface(src, destRect.left, destRect.top, srcRect); @@ -194,4 +172,11 @@ bool Surface::clip(Common::Rect &srcBounds, Common::Rect &destBounds) { return true; } +/** + * Clear the screen + */ +void Surface::clear() { + fillRect(Common::Rect(0, 0, this->w, this->h), 0); +} + } // End of namespace Sherlock diff --git a/engines/sherlock/graphics.h b/engines/sherlock/surface.h similarity index 99% rename from engines/sherlock/graphics.h rename to engines/sherlock/surface.h index d4a1584968db..b2a759aa8df9 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/surface.h @@ -53,6 +53,8 @@ class Surface : public Graphics::Surface { void fillRect(int x1, int y1, int x2, int y2, byte color); void fillRect(const Common::Rect &r, byte color); + + void clear(); }; } // End of namespace Sherlock diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index 61f0004fd697..d65643182390 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -104,7 +104,6 @@ Talk::Talk(SherlockEngine *vm): _vm(vm) { _moreTalkDown = _moreTalkUp = false; _scriptMoreFlag = 0; _scriptSaveIndex = -1; - _scriptCurrentIndex = -1; } /** @@ -1082,10 +1081,6 @@ void Talk::doScript(const Common::String &script) { // Handle control code switch (c) { case SWITCH_SPEAKER: - // Save the current point in the script, since it might be intterupted by - // doing bg anims in the next call, so we need to know where to return to - _scriptCurrentIndex = str - scriptStart; - if (!(_speaker & 128)) people.clearTalking(); if (_talkToAbort) @@ -1103,10 +1098,7 @@ void Talk::doScript(const Common::String &script) { break; case RUN_CANIMATION: - // Save the current point in the script, since it might be intterupted by - // doing bg anims in the next call, so we need to know where to return to ++str; - _scriptCurrentIndex = (str + 1) - scriptStart; scene.startCAnim((str[0] - 1) & 127, (str[0] & 128) ? -1 : 1); if (_talkToAbort) return; @@ -1143,10 +1135,6 @@ void Talk::doScript(const Common::String &script) { break; case REMOVE_PORTRAIT: - // Save the current point in the script, since it might be intterupted by - // doing bg anims in the next call, so we need to know where to return to - _scriptCurrentIndex = str - scriptStart; - if (_speaker >= 0 && _speaker < 128) people.clearTalking(); pullSequence(); @@ -1203,10 +1191,7 @@ void Talk::doScript(const Common::String &script) { } case WALK_TO_COORDS: - // Save the current point in the script, since it might be interrupted by - // doing bg anims in the next call, so we need to know where to return to ++str; - _scriptCurrentIndex = str - scriptStart; people.walkToCoords(Common::Point(((str[0] - 1) * 256 + str[1] - 1) * 100, str[2] * 100), str[3] - 1); @@ -1217,10 +1202,7 @@ void Talk::doScript(const Common::String &script) { break; case PAUSE_WITHOUT_CONTROL: - // Save the current point in the script, since it might be intterupted by - // doing bg anims in the next call, so we need to know where to return to ++str; - _scriptCurrentIndex = str - scriptStart; for (int idx = 0; idx < (str[0] - 1); ++idx) { scene.doBgAnim(); @@ -1234,10 +1216,6 @@ void Talk::doScript(const Common::String &script) { break; case BANISH_WINDOW: - // Save the current point in the script, since it might be intterupted by - // doing bg anims in the next call, so we need to know where to return to - _scriptCurrentIndex = str - scriptStart; - if (!(_speaker & 128)) people.clearTalking(); pullSequence(); @@ -1403,19 +1381,19 @@ void Talk::doScript(const Common::String &script) { break; } - case CALL_TALK_FILE: + case CALL_TALK_FILE: { ++str; for (int idx = 0; idx < 8 && str[idx] != '~'; ++idx) tempString += str[idx]; str += 8; - _scriptCurrentIndex = str - scriptStart; + 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._currentIndex = scriptCurrentIndex; rec1._select = _scriptSelect; _scriptStack.push(rec1); @@ -1433,12 +1411,10 @@ void Talk::doScript(const Common::String &script) { endStr = true; wait = 0; break; + } case MOVE_MOUSE: - // Save the current point in the script, since it might be intterupted by - // doing bg anims in the next call, so we need to know where to return to ++str; - _scriptCurrentIndex = str - scriptStart; events.moveMouse(Common::Point((str[0] - 1) * 256 + str[1] - 1, str[2])); if (_talkToAbort) return; @@ -1464,10 +1440,6 @@ void Talk::doScript(const Common::String &script) { ++str; CAnim &animation = scene._cAnim[str[0] - 1]; - // Save the current point in the script, since it might be interrupted by - // doing bg anims in the next call, so we need to know where to return to - _scriptCurrentIndex = (str + 1) - scriptStart; - people.walkToCoords(animation._goto, animation._gotoDir); if (_talkToAbort) return; @@ -1614,10 +1586,6 @@ void Talk::doScript(const Common::String &script) { } if (wait) { - // Save the current point in the script, since it might be intterupted by - // doing bg anims in the next call, so we need to know where to return to - _scriptCurrentIndex = str - scriptStart; - // Handling pausing if (!pauseFlag && charCount < 160) charCount = 160; diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h index d81586228faa..b1a735827cc3 100644 --- a/engines/sherlock/talk.h +++ b/engines/sherlock/talk.h @@ -140,7 +140,6 @@ class Talk { int _talkStealth; int _talkToFlag; int _scriptSaveIndex; - int _scriptCurrentIndex; private: void stripVoiceCommands(); void setTalkMap(); diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp index 9039e3f9d47b..3c684ff3ee9a 100644 --- a/engines/sherlock/tattoo/tattoo.cpp +++ b/engines/sherlock/tattoo/tattoo.cpp @@ -44,6 +44,7 @@ void TattooEngine::initialize() { // Add some more files to the cache _res->addToCache("walk.lib"); + _res->addToCache("sound.lib"); // Starting scene _scene->_goToScene = 91; diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 8e7254026b2e..1ab8fe729473 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -172,11 +172,6 @@ void UserInterface::handleInput() { _vm->quitGame(); events.pollEvents(); return; - } else if (keyState.keycode == Common::KEYCODE_SPACE || - keyState.keycode == Common::KEYCODE_RETURN) { - events._pressed = false; - events._oldButtons = 0; - _keycode = Common::KEYCODE_INVALID; } } @@ -929,7 +924,7 @@ void UserInterface::doEnvControl() { 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, 150, CONTROLS_Y + 10), 136 - screen.stringWidth("Yes") / 2, "Yes"); + 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); @@ -1430,17 +1425,24 @@ void UserInterface::doMainControl() { break; case 'F': pushButton(10); - _menuMode = FILES_MODE; // Create a thumbnail of the current screen before the files dialog is shown, in case // the user saves the game saves.createThumbnail(); - // Display the dialog - saves.drawInterface(); - _selector = _oldSelector = -1; - _windowOpen = true; + + 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); @@ -1699,9 +1701,6 @@ void UserInterface::doTalkControl() { sound._speechOn = false; } - // Set the _scriptCurrentIndex so if the statement is irrupted, the entire - // reply will be shown when it's restarted - talk._scriptCurrentIndex = 0; talk.waitForMore(talk._statements[_selector]._statement.size()); if (talk._talkToAbort) return; diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index 79382a19fe4b..2ff60715e3c8 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -25,7 +25,7 @@ #include "common/scummsys.h" #include "common/events.h" -#include "sherlock/graphics.h" +#include "sherlock/surface.h" #include "sherlock/objects.h" #include "sherlock/resources.h"