diff options
-rw-r--r-- | engines/sherlock/events.cpp | 24 | ||||
-rw-r--r-- | engines/sherlock/events.h | 10 | ||||
-rw-r--r-- | engines/sherlock/resources.cpp | 57 | ||||
-rw-r--r-- | engines/sherlock/resources.h | 3 | ||||
-rw-r--r-- | engines/sherlock/room.cpp | 2 | ||||
-rw-r--r-- | engines/sherlock/room.h | 3 | ||||
-rw-r--r-- | engines/sherlock/scalpel/scalpel.cpp | 177 | ||||
-rw-r--r-- | engines/sherlock/scalpel/scalpel.h | 12 | ||||
-rw-r--r-- | engines/sherlock/screen.cpp | 1 | ||||
-rw-r--r-- | engines/sherlock/screen.h | 1 | ||||
-rw-r--r-- | engines/sherlock/sherlock.cpp | 16 | ||||
-rw-r--r-- | engines/sherlock/sherlock.h | 4 | ||||
-rw-r--r-- | engines/sherlock/sound.cpp | 14 | ||||
-rw-r--r-- | engines/sherlock/sound.h | 4 |
14 files changed, 297 insertions, 31 deletions
diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index b2d9fc65e8..1a882eedea 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -32,7 +32,8 @@ namespace Sherlock { EventsManager::EventsManager(SherlockEngine *vm) { _vm = vm; - _cursorId = CURSOR_NONE; + _cursorSprites = nullptr; + _cursorIndex = -1; _frameCounter = 1; _priorFrameTime = 0; _mouseClicked = false; @@ -40,15 +41,30 @@ EventsManager::EventsManager(SherlockEngine *vm) { } EventsManager::~EventsManager() { + delete _cursorSprites; +} + +/** + * Load a set of cursors from the specified file + */ +void EventsManager::loadCursors(const Common::String &filename) { + hideCursor(); + delete _cursorSprites; + + _cursorSprites = new Sprite(filename); } /** * Set the cursor to show */ -void EventsManager::setCursor(CursorType cursorId) { - _cursorId = cursorId; +void EventsManager::changeCursor(int cursorIndex) { + _cursorIndex = cursorIndex; + + // Set the cursor data + Graphics::Surface &s = (*_cursorSprites)[cursorIndex]; + CursorMan.replaceCursor(s.getPixels(), s.w, s.h, s.w / 2, s.h / 2, 0xff); - // TODO: Cursor handling + showCursor(); } /** diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h index 4493fcdc65..1f7352eeb5 100644 --- a/engines/sherlock/events.h +++ b/engines/sherlock/events.h @@ -26,11 +26,10 @@ #include "common/scummsys.h" #include "common/events.h" #include "common/stack.h" +#include "sherlock/sprite.h" namespace Sherlock { -enum CursorType { CURSOR_NONE = 0 }; - #define GAME_FRAME_RATE 60 #define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE) @@ -42,10 +41,11 @@ private: uint32 _frameCounter; uint32 _priorFrameTime; Common::Point _mousePos; + Sprite *_cursorSprites; bool checkForNextFrameCounter(); public: - CursorType _cursorId; + int _cursorIndex; byte _mouseButtons; bool _mouseClicked; Common::Stack<Common::KeyState> _pendingKeys; @@ -53,7 +53,9 @@ public: EventsManager(SherlockEngine *vm); ~EventsManager(); - void setCursor(CursorType cursorId); + void loadCursors(const Common::String &filename); + + void changeCursor(int cursorIndex); void showCursor(); diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp index 47e2046084..6636ca5be8 100644 --- a/engines/sherlock/resources.cpp +++ b/engines/sherlock/resources.cpp @@ -41,43 +41,57 @@ bool Cache::isCached(const Common::String &filename) const { * If the file is LZW compressed, automatically decompresses it and loads * the uncompressed version into memory */ -void Cache::load(const Common::String &filename) { +void Cache::load(const Common::String &name) { // First check if the entry already exists - if (_resources.contains(filename)) + if (_resources.contains(name)) return; - // Allocate a new cache entry - _resources[filename] = CacheEntry(); - CacheEntry &cacheEntry = _resources[filename]; - // Open the file for reading Common::File f; - if (!f.open(filename)) - error("Could not read file - %s", filename.c_str()); + if (!f.open(name)) + error("Could not read file - %s", name.c_str()); + + load(name, f); + + f.close(); +} + +/** + * Load a cache entry based on a passed stream + */ +void Cache::load(const Common::String &name, Common::SeekableReadStream &stream) { + // First check if the entry already exists + if (_resources.contains(name)) + return; // Check whether the file is compressed const char LZW_HEADER[5] = { "LZV\x1a" }; char header[5]; - f.read(header, 5); + stream.read(header, 5); bool isCompressed = !strncmp(header, LZW_HEADER, 5); - f.seek(0); + stream.seek(0); + + // Allocate a new cache entry + _resources[name] = CacheEntry(); + CacheEntry &cacheEntry = _resources[name]; if (isCompressed) { // It's compressed, so decompress the file and store it's data in the cache entry - Common::SeekableReadStream *decompressed = decompressLZ(f); + Common::SeekableReadStream *decompressed = decompressLZ(stream); cacheEntry.resize(decompressed->size()); decompressed->read(&cacheEntry[0], decompressed->size()); delete decompressed; } else { // It's not, so read the raw data of the file into the cache entry - cacheEntry.resize(f.size()); - f.read(&cacheEntry[0], f.size()); + cacheEntry.resize(stream.size()); + stream.read(&cacheEntry[0], stream.size()); } - - f.close(); } +/** + * Get a file from the cache + */ Common::SeekableReadStream *Cache::get(const Common::String &filename) const { // Return a memory stream that encapsulates the data const CacheEntry &cacheEntry = _resources[filename]; @@ -96,7 +110,6 @@ Resources::Resources() { addToCache("portrait.lib"); } - /** * Adds the specified file to the cache. If it's a library file, takes care of * loading it's index for future use @@ -113,6 +126,18 @@ void Resources::addToCache(const Common::String &filename) { delete stream; } +/** + * Adds a resource from a library file tot he cache + */ +void Resources::addToCache(const Common::String &filename, const Common::String &libFilename) { + // Get the resource + Common::SeekableReadStream *stream = load(filename, libFilename); + + _cache.load(filename, *stream); + + delete stream; +} + Common::SeekableReadStream *Resources::load(const Common::String &filename) { // First check if the file is directly in the cache if (_cache.isCached(filename)) diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h index edb9bd8ba0..cd6e60c325 100644 --- a/engines/sherlock/resources.h +++ b/engines/sherlock/resources.h @@ -57,6 +57,7 @@ public: bool isCached(const Common::String &filename) const; void load(const Common::String &name); + void load(const Common::String &name, Common::SeekableReadStream &stream); Common::SeekableReadStream *get(const Common::String &filename) const; }; @@ -72,6 +73,8 @@ public: Resources(); void addToCache(const Common::String &filename); + void addToCache(const Common::String &filename, const Common::String &libFilename); + bool isInCache(const Common::String &filename) const { return _cache.isCached(filename); } Common::SeekableReadStream *load(const Common::String &filename); diff --git a/engines/sherlock/room.cpp b/engines/sherlock/room.cpp index 9926899953..c06d707b40 100644 --- a/engines/sherlock/room.cpp +++ b/engines/sherlock/room.cpp @@ -27,8 +27,8 @@ namespace Sherlock { Rooms::Rooms() { for (int roomNum = 0; roomNum < ROOMS_COUNT; ++roomNum) Common::fill(&_stats[roomNum][0], &_stats[roomNum][9], false); - _goToRoom = -1; + _oldCharPoint = 0; } } // End of namespace Sherlock diff --git a/engines/sherlock/room.h b/engines/sherlock/room.h index 75800b623a..0f2bc56a45 100644 --- a/engines/sherlock/room.h +++ b/engines/sherlock/room.h @@ -94,6 +94,9 @@ public: bool _stats[ROOMS_COUNT][9]; bool _savedStats[ROOMS_COUNT][9]; int _goToRoom; + Common::Point _bigPos; + Common::Point _overPos; + int _oldCharPoint; public: Rooms(); }; diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp index 0e5a3bec34..d691bbd8bb 100644 --- a/engines/sherlock/scalpel/scalpel.cpp +++ b/engines/sherlock/scalpel/scalpel.cpp @@ -27,6 +27,12 @@ namespace Sherlock { namespace Scalpel { +ScalpelEngine::ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : + SherlockEngine(syst, gameDesc) { + _tempFadeStyle = 0; + _chessResult = 0; +} + /** * Game initialization */ @@ -131,17 +137,188 @@ bool ScalpelEngine::showCityCutscene() { } bool ScalpelEngine::showAlleyCutscene() { + // TODO return true; } bool ScalpelEngine::showStreetCutscene() { + // TODO return true; } bool ScalpelEngine::showOfficeCutscene() { + // TODO return true; } +int ScalpelEngine::doChessBoard() { + // TODO + return 0; +} + +void ScalpelEngine::playDarts() { + // TODO +} + +/** + * Starting a scene within the game + */ +void ScalpelEngine::startScene() { + if (_rooms->_goToRoom == 100 || _rooms->_goToRoom == 98) { + // Chessboard selection + if (_sound->_musicEnabled) { + if (_sound->loadSong(100)) { + if (_sound->_music) + _sound->startSong(); + } + } + + _rooms->_goToRoom = doChessBoard(); + + _sound->freeSong(); + _hsavedPos = Common::Point(-1, -1); + _hsavedFs = -1; + } + + // Some rooms are prologue cutscenes, rather than normal game scenes. These are: + // 2: Blackwood's capture + // 52: Rescuing Anna + // 53: Moorehead's death / subway train + // 55: Fade out and exit + // 70: Brumwell suicide + switch (_rooms->_goToRoom) { + case 2: + case 52: + case 53: + case 70: + if (_sound->_musicEnabled && _sound->loadSong(_rooms->_goToRoom)) { + if (_sound->_music) + _sound->startSong(); + } + + switch (_rooms->_goToRoom) { + case 2: + // Blackwood's capture + _res->addToCache("final2.vda", "epilogue.lib"); + _res->addToCache("final2.vdx", "epilogue.lib"); + _animation->playPrologue("final1", 1, 3, true, 4); + _animation->playPrologue("final22", 1, 0, false, 4); + break; + + case 52: + // Rescuing Anna + _res->addToCache("finalr2.vda", "epilogue.lib"); + _res->addToCache("finalr2.vdx", "epilogue.lib"); + _res->addToCache("finale1.vda", "epilogue.lib"); + _res->addToCache("finale1.vdx", "epilogue.lib"); + _res->addToCache("finale2.vda", "epilogue.lib"); + _res->addToCache("finale2.vdx", "epilogue.lib"); + _res->addToCache("finale3.vda", "epilogue.lib"); + _res->addToCache("finale3.vdx", "epilogue.lib"); + _res->addToCache("finale4.vda", "EPILOG2.lib"); + _res->addToCache("finale4.vdx", "EPILOG2.lib"); + + _animation->playPrologue("finalr1", 1, 3, true, 4); + _animation->playPrologue("finalr2", 1, 0, false, 4); + + if (!_res->isInCache("finale2.vda")) { + // Finale file isn't cached + _res->addToCache("finale2.vda", "epilogue.lib"); + _res->addToCache("finale2.vdx", "epilogue.lib"); + _res->addToCache("finale3.vda", "epilogue.lib"); + _res->addToCache("finale3.vdx", "epilogue.lib"); + _res->addToCache("finale4.vda", "EPILOG2.lib"); + _res->addToCache("finale4.vdx", "EPILOG2.lib"); + } + + _animation->playPrologue("finale1", 1, 0, false, 4); + _animation->playPrologue("finale2", 1, 0, false, 4); + _animation->playPrologue("finale3", 1, 0, false, 4); + + _useEpilogue2 = true; + _animation->playPrologue("finale4", 1, 0, false, 4); + _useEpilogue2 = false; + break; + + case 53: + // Moorehead's death / subway train + _res->addToCache("SUBWAY2.vda", "epilogue.lib"); + _res->addToCache("SUBWAY2.vdx", "epilogue.lib"); + _res->addToCache("SUBWAY3.vda", "epilogue.lib"); + _res->addToCache("SUBWAY3.vdx", "epilogue.lib"); + + _animation->playPrologue("SUBWAY1", 1, 3, true, 4); + _animation->playPrologue("SUBWAY2", 1, 0, false, 4); + _animation->playPrologue("SUBWAY3", 1, 0, false, 4); + + // Set fading to direct fade temporary so the transition goes quickly. + _tempFadeStyle = _screen->_fadeStyle ? 257 : 256; + _screen->_fadeStyle = false; + break; + + case 70: + // Brumwell suicide + _animation->playPrologue("suicid", 1, 3, true, 4); + break; + default: + break; + } + + // Except for the Moorehead Murder scene, fade to black first + if (_rooms->_goToRoom != 53) { + _events->wait(40); + _screen->fadeToBlack(3); + } + + switch (_rooms->_goToRoom) { + case 52: + _rooms->_goToRoom = 27; // Go to the Lawyer's Office + _rooms->_bigPos = Common::Point(0, 0); // Overland scroll position + _rooms->_overPos = Common::Point(22900 - 600, 9400 + 900); // Overland position + _rooms->_oldCharPoint = 27; + break; + + case 53: + _rooms->_goToRoom = 17; // Go to St. Pancras Station + _rooms->_bigPos = Common::Point(0, 0); // Overland scroll position + _rooms->_overPos = Common::Point(32500 - 600, 3000 + 900); // Overland position + _rooms->_oldCharPoint = 17; + break; + + default: + _rooms->_goToRoom = 4; // Back to Baker st. + _rooms->_bigPos = Common::Point(0, 0); // Overland scroll position + _rooms->_overPos = Common::Point(14500 - 600, 8400 + 900); // Overland position + _rooms->_oldCharPoint = 4; + break; + } + + // Free any song from the previous scene + _sound->freeSong(); + break; + + case 55: + // Exit game + _screen->fadeToBlack(3); + quitGame(); + return; + + default: + break; + } + + _events->loadCursors("rmouse.vgs"); + _events->changeCursor(0); + + if (_rooms->_goToRoom == 99) { + // Chess Board + playDarts(); + _chessResult = _rooms->_goToRoom = 19; // Go back to the bar + } + + _chessResult = _rooms->_goToRoom; +} + } // End of namespace Scalpel } // End of namespace Scalpel diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h index 584bd78a20..83510064fa 100644 --- a/engines/sherlock/scalpel/scalpel.h +++ b/engines/sherlock/scalpel/scalpel.h @@ -31,17 +31,25 @@ namespace Scalpel { class ScalpelEngine : public SherlockEngine { private: + int _tempFadeStyle; + int _chessResult; + bool showCityCutscene(); bool showAlleyCutscene(); bool showStreetCutscene(); bool showOfficeCutscene(); + + int doChessBoard(); + + void playDarts(); protected: virtual void initialize(); virtual void showOpening(); + + virtual void startScene(); public: - ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc) : - SherlockEngine(syst, gameDesc) {} + ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~ScalpelEngine() {} }; diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp index 7a4d4863ac..0ec5df9c4c 100644 --- a/engines/sherlock/screen.cpp +++ b/engines/sherlock/screen.cpp @@ -31,6 +31,7 @@ Screen::Screen(SherlockEngine *vm) : Surface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCR _backBuffer(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), _backBuffer2(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT) { _transitionSeed = 1; + _fadeStyle = false; setFont(1); } diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h index 78ccffc575..05fd80a8b7 100644 --- a/engines/sherlock/screen.h +++ b/engines/sherlock/screen.h @@ -51,6 +51,7 @@ protected: virtual void addDirtyRect(const Common::Rect &r); public: Surface _backBuffer, _backBuffer2; + bool _fadeStyle; public: Screen(SherlockEngine *vm); diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index add24cba9f..907f0a5a16 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -40,9 +40,10 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _sound = nullptr; _talk = nullptr; _useEpilogue2 = false; + _hsavedPos = Common::Point(-1, -1); + _hsavedFs = -1; } - SherlockEngine::~SherlockEngine() { delete _animation; delete _debugger; @@ -73,11 +74,11 @@ void SherlockEngine::initialize() { _midi->setNativeMT32(native_mt32); */ + _res = new Resources(); _animation = new Animation(this); _debugger = new Debugger(this); _events = new EventsManager(this); _journal = new Journal(); - _res = new Resources(); _rooms = new Rooms(); _screen = new Screen(this); _sound = new Sound(this); @@ -90,8 +91,15 @@ Common::Error SherlockEngine::run() { showOpening(); - // TODO: Rest of game - + while (!shouldQuit()) { + // Prepare for scene, and handle any game-specific scenes + startScene(); + + // TODO: Implement game and remove this dummy loop + while (!shouldQuit()) + _events->pollEventsAndWait(); + } + return Common::kNoError; } diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index cedc57a9f8..7906417d7e 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -69,6 +69,8 @@ protected: virtual void initialize(); virtual void showOpening() = 0; + + virtual void startScene() {} public: const SherlockGameDescription *_gameDescription; Animation *_animation; @@ -85,6 +87,8 @@ public: Common::String _soundOverride; Common::String _titleOverride; bool _useEpilogue2; + Common::Point _hsavedPos; + int _hsavedFs; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp index 0957315a35..efc1965637 100644 --- a/engines/sherlock/sound.cpp +++ b/engines/sherlock/sound.cpp @@ -29,6 +29,7 @@ Sound::Sound(SherlockEngine *vm): _vm(vm) { _musicEnabled = true; _voicesEnabled = true; _playingEpilogue = false; + _music = false; } void Sound::playSound(const Common::String &name, WaitType waitType) { @@ -59,5 +60,18 @@ void Sound::stopMusic() { // TODO } +int Sound::loadSong(int songNumber) { + // TODO + return 0; +} + +void Sound::startSong() { + // TODO +} + +void Sound::freeSong() { + // TODO +} + } // End of namespace Sherlock diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h index 7775016c94..442e908838 100644 --- a/engines/sherlock/sound.h +++ b/engines/sherlock/sound.h @@ -42,6 +42,7 @@ public: bool _musicEnabled; bool _voicesEnabled; bool _playingEpilogue; + bool _music; public: Sound(SherlockEngine *vm); @@ -50,6 +51,9 @@ public: void playCachedSound(int index); void clearCache(); void stopSound(); + int loadSong(int songNumber); + void startSong(); + void freeSong(); void playMusic(const Common::String &name); void stopMusic(); |