diff --git a/engines/plumbers/configure.engine b/engines/plumbers/configure.engine new file mode 100644 index 000000000000..948a0e74a88e --- /dev/null +++ b/engines/plumbers/configure.engine @@ -0,0 +1,3 @@ +# This file is included from the main "configure" script +# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] +add_engine plumbers "Plumbers Don't Wear Ties" no "" "" "" diff --git a/engines/plumbers/console.cpp b/engines/plumbers/console.cpp new file mode 100644 index 000000000000..f005b60769c6 --- /dev/null +++ b/engines/plumbers/console.cpp @@ -0,0 +1,47 @@ +/* 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 "gui/debugger.h" + +#include "plumbers/plumbers.h" +#include "plumbers/console.h" + +namespace Plumbers { + +Console::Console(Plumbers::PlumbersGame *vm) : _vm(vm) { + _allowSkip = false; + registerCmd("allowSkip", WRAP_METHOD(Console, Cmd_allowSkip)); +} + +bool Console::Cmd_allowSkip(int argc, const char** argv) { + if (argc != 1) { + debugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Enables/Disables the possibility to skip screen delays\n"); + return true; + } + + _allowSkip ^= true; + debugPrintf("Skipping delay is now %s\n", _allowSkip ? "Enabled" : "Disabled"); + return true; +} + +} // End of namespace Plumbers diff --git a/engines/plumbers/console.h b/engines/plumbers/console.h new file mode 100644 index 000000000000..c849678419d6 --- /dev/null +++ b/engines/plumbers/console.h @@ -0,0 +1,46 @@ +/* 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 PLUMBERS_CONSOLE_H +#define PLUMBERS_CONSOLE_H + +#include "gui/debugger.h" + +namespace Plumbers { + +class PlumbersGame; + +class Console : public GUI::Debugger { +private: + PlumbersGame *_vm; + +public: + bool _allowSkip; + + explicit Console(Plumbers::PlumbersGame *vm); + virtual ~Console(void) {} + + bool Cmd_allowSkip(int argc, const char** argv); +}; +} + +#endif diff --git a/engines/plumbers/detection.cpp b/engines/plumbers/detection.cpp new file mode 100644 index 000000000000..9c1fe49aa8ba --- /dev/null +++ b/engines/plumbers/detection.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 "base/plugins.h" + +#include "engines/advancedDetector.h" +#include "common/file.h" + +#include "plumbers/plumbers.h" + + +namespace Plumbers { +const char *PlumbersGame::getGameId() const { return _gameDescription->gameId; } +Common::Platform PlumbersGame::getPlatform() const { return _gameDescription->platform; } +} + +static const PlainGameDescriptor plumbersGames[] = { + {"plumbers", "Plumbers Don't Wear Ties!"}, + {0, 0} +}; + +namespace Plumbers { + +static const ADGameDescription gameDescriptions[] = { + // Plumbers PC version + { + "plumbers", + 0, + AD_ENTRY1s("GAME.BIN", 0, 41622), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO1(GUIO_NONE) + }, + + /* + // Plumbers 3DO version + { + "plumbers", + 0, + AD_ENTRY1s("launchme", 0, 143300), + Common::EN_ANY, + Common::kPlatform3DO, + ADGF_UNSTABLE, + GUIO1(GUIO_NONE) + }, + */ + + AD_TABLE_END_MARKER +}; + +} // End of namespace Plumbers + +class PlumbersMetaEngine : public AdvancedMetaEngine { +public: + PlumbersMetaEngine() : AdvancedMetaEngine(Plumbers::gameDescriptions, sizeof(ADGameDescription), plumbersGames) { + _singleId = "plumbers"; + } + + virtual const char *getName() const { + return "Plumbers Don't Wear Ties' Engine"; + } + + virtual const char *getOriginalCopyright() const { + return "Plumbers Don't Wear Ties (C) 1993-94 Kirin Entertainment"; + } + + virtual bool hasFeature(MetaEngineFeature f) const; + virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; +}; + +bool PlumbersMetaEngine::hasFeature(MetaEngineFeature f) const { + return false; +} + +bool PlumbersMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { + if (desc) + *engine = new Plumbers::PlumbersGame(syst, desc); + + return desc != nullptr; +} + +#if PLUGIN_ENABLED_DYNAMIC(PLUMBERS) +REGISTER_PLUGIN_DYNAMIC(PLUMBERS, PLUGIN_TYPE_ENGINE, PlumbersMetaEngine); +#else +REGISTER_PLUGIN_STATIC(PLUMBERS, PLUGIN_TYPE_ENGINE, PlumbersMetaEngine); +#endif diff --git a/engines/plumbers/module.mk b/engines/plumbers/module.mk new file mode 100644 index 000000000000..a8b246548a1b --- /dev/null +++ b/engines/plumbers/module.mk @@ -0,0 +1,14 @@ +MODULE := engines/plumbers + +MODULE_OBJS = \ + plumbers.o \ + console.o \ + detection.o + +# This module can be built as a plugin +ifeq ($(ENABLE_PLUMBERS), DYNAMIC_PLUGIN) +PLUGIN := 1 +endif + +# Include common rules +include $(srcdir)/rules.mk diff --git a/engines/plumbers/plumbers.cpp b/engines/plumbers/plumbers.cpp new file mode 100644 index 000000000000..4d4ed0c1f354 --- /dev/null +++ b/engines/plumbers/plumbers.cpp @@ -0,0 +1,368 @@ +/* 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/config-manager.h" +#include "common/error.h" +#include "graphics/cursorman.h" +#include "graphics/surface.h" +#include "graphics/screen.h" +#include "graphics/palette.h" +#include "graphics/font.h" +#include "graphics/fontman.h" +#include "common/system.h" +#include "engines/util.h" +#include "common/debug.h" +#include "common/debug-channels.h" + +#include "plumbers/plumbers.h" + +namespace Plumbers { + +PlumbersGame::PlumbersGame(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) { + _image = nullptr; + _console = nullptr; + _timerInstalled = false; + DebugMan.addDebugChannel(kDebugGeneral, "general", "General debug level"); +} + +PlumbersGame::~PlumbersGame() { + delete _image; + delete _console; +} + +static const byte MOUSECURSOR_SCI[] = { + 1,1,0,0,0,0,0,0,0,0,0, + 1,2,1,0,0,0,0,0,0,0,0, + 1,2,2,1,0,0,0,0,0,0,0, + 1,2,2,2,1,0,0,0,0,0,0, + 1,2,2,2,2,1,0,0,0,0,0, + 1,2,2,2,2,2,1,0,0,0,0, + 1,2,2,2,2,2,2,1,0,0,0, + 1,2,2,2,2,2,2,2,1,0,0, + 1,2,2,2,2,2,2,2,2,1,0, + 1,2,2,2,2,2,2,2,2,2,1, + 1,2,2,2,2,2,1,0,0,0,0, + 1,2,1,0,1,2,2,1,0,0,0, + 1,1,0,0,1,2,2,1,0,0,0, + 0,0,0,0,0,1,2,2,1,0,0, + 0,0,0,0,0,1,2,2,1,0,0, + 0,0,0,0,0,0,1,2,2,1,0 +}; + +static const byte cursorPalette[] = { + 0, 0, 0, // Black / Transparent + 0x80, 0x80, 0x80, // Gray + 0xff, 0xff, 0xff // White +}; + +Common::Error PlumbersGame::run() { + initGraphics(640, 480, true); + _console = new Console(this); + + CursorMan.replaceCursor(MOUSECURSOR_SCI, 11, 16, 0, 0, 0); + CursorMan.replaceCursorPalette(cursorPalette, 0, 3); + CursorMan.showMouse(true); + + readTables("game.bin"); + + _showScoreFl = false; + _leftButtonDownFl = false; + _endGameFl = false; + _totScore = 0; + _curSceneIdx = _prvSceneIdx = 0; + _curChoice = 0; + _actions.clear(); + _actions.push(ShowScene); + + bool quit = false; + + while (!quit && !_endGameFl) { + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_QUIT: + case Common::EVENT_RTL: + quit = true; + break; + + case Common::EVENT_LBUTTONDOWN: + if (_leftButtonDownFl) { + Common::Point mousePos = g_system->getEventManager()->getMousePos(); + for (_curChoice = 0; _curChoice < _scenes[_curSceneIdx]._decisionChoices; _curChoice++) { + if (_scenes[_curSceneIdx]._choices[_curChoice]._region.contains(mousePos)) + break; + } + if (_curChoice < kMaxChoice) { + debugC(5, kDebugGeneral, "Accepting mouse click at %d : %d , choice = %d", mousePos.x, mousePos.y, _curChoice); + _totScore += _scenes[_curSceneIdx]._choices[_curChoice]._points; + _actions.push(ChangeScene); + _leftButtonDownFl = false; + } + } else if (_console->_allowSkip && _timerInstalled) { + // Allows to skip speech by skipping wait delay + onTimer(this); + } + break; + case Common::EVENT_KEYDOWN: + if (event.kbd.keycode == Common::KEYCODE_d && event.kbd.hasFlags(Common::KBD_CTRL)) + _console->attach(); + + break; + default: + break; + } + } + + while (!_actions.empty()) { + switch (_actions.pop()) { + case Redraw: + drawScreen(); + break; + case ShowScene: + showScene(); + break; + case UpdateScene: + updateScene(); + break; + case ChangeScene: + changeScene(); + break; + case PlaySound: + playSound(); + break; + } + } + + g_system->updateScreen(); + g_system->delayMillis(10); + } + + g_system->getTimerManager()->removeTimerProc(onTimer); + stopSound(); + + return Common::kNoError; +} + +void PlumbersGame::loadImage(const Common::String &dirname, const Common::String &filename) { + Common::String name = dirname + "/" + filename; + debugC(1, kDebugGeneral, "%s : %s", __FUNCTION__, name.c_str()); + Common::File *file = new Common::File(); + if (!file->open(name)) + error("unable to load image %s", name.c_str()); + + if (_image) + delete _image; + + _image = new Image::BitmapDecoder(); + _image->loadStream(*file); + file->close(); + delete file; +} + +void PlumbersGame::drawScreen() { + debugC(1, kDebugGeneral, "%s : %s", __FUNCTION__, _image ? "YES" : "NO"); + if (_image) { + if (_setDurationFl) { + g_system->getTimerManager()->removeTimerProc(onTimer); + g_system->getTimerManager()->installTimerProc(onTimer, _bitmaps[_curBitmapIdx]._duration * 100 * 1000, this, "timer"); + _timerInstalled = true; + _actions.push(UpdateScene); + } + + Graphics::Surface *screen = g_system->lockScreen(); + screen->fillRect(Common::Rect(0, 0, g_system->getWidth(), g_system->getHeight()), 0); + + const Graphics::Surface *surface = _image->getSurface(); + + int w = CLIP(surface->w, 0, 640); + int h = CLIP(surface->h, 0, 480); + + int x = (640 - w) / 2; + int y = (480 - h) / 2; + + screen->copyRectToSurface(*surface, x, y, Common::Rect(0, 0, w, h)); + + if (_showScoreFl) { + Common::String score = Common::String::format("Your Score is: %ld", _totScore); + const Graphics::Font &font(*FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont)); + Common::Rect rect(10, 440, 200, 440 + font.getFontHeight()); + screen->fillRect(rect, 0); + font.drawString(screen, score, rect.left, rect.top, 190, 255, Graphics::kTextAlignCenter); + _showScoreFl = false; + } + + g_system->unlockScreen(); + g_system->getPaletteManager()->setPalette(_image->getPalette(), 0, 256); + g_system->updateScreen(); + } + + _console->onFrame(); +} + +void PlumbersGame::playSound() { + Common::String name = _scenes[_curSceneIdx]._sceneName + "/" + _scenes[_curSceneIdx]._waveFilename; + debugC(3, kDebugGeneral, "%s : %s", __FUNCTION__, name.c_str()); + Common::File *file = new Common::File(); + if (!file->open(name)) + error("unable to load sound %s", name.c_str()); + + Audio::RewindableAudioStream *audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES); + Audio::AudioStream *stream = audioStream; + stopSound(); + _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream, -1, Audio::Mixer::kMaxChannelVolume); +} + +void PlumbersGame::stopSound() { + debugC(3, kDebugGeneral, "%s", __FUNCTION__); + if (_mixer->isSoundHandleActive(_soundHandle)) + _mixer->stopHandle(_soundHandle); +} + +void PlumbersGame::showScene() { + debugC(1, kDebugGeneral, "%s : %d", __FUNCTION__, _curSceneIdx); + _curBitmapIdx = _scenes[_curSceneIdx]._startBitmap; + loadImage(_scenes[_curSceneIdx]._sceneName, _bitmaps[_curBitmapIdx]._filename); + _actions.push(Redraw); + _setDurationFl = true; + _actions.push(PlaySound); +} + +void PlumbersGame::updateScene() { + debugC(2, kDebugGeneral, "%s : %d", __FUNCTION__, _curBitmapIdx); + _curBitmapIdx++; + if (_curBitmapIdx >= _scenes[_curSceneIdx]._startBitmap + _scenes[_curSceneIdx]._bitmapNum) { + if (_scenes[_curSceneIdx]._decisionChoices == 1) { + _curChoice = 0; + _actions.push(ChangeScene); + } else { + _showScoreFl = true; + _leftButtonDownFl = true; + _setDurationFl = false; + loadImage(_scenes[_curSceneIdx]._sceneName, _scenes[_curSceneIdx]._decisionBitmap); + } + } else { + loadImage(_scenes[_curSceneIdx]._sceneName, _bitmaps[_curBitmapIdx]._filename); + _setDurationFl = true; + } +} + +void PlumbersGame::changeScene() { + debugC(1, kDebugGeneral, "%s : %d", __FUNCTION__, _curChoice); + if (_scenes[_curSceneIdx]._choices[_curChoice]._sceneIdx == -1) { + _curSceneIdx = _prvSceneIdx; + _curBitmapIdx = 9999; + _actions.push(UpdateScene); + _actions.push(Redraw); + } else if (_scenes[_curSceneIdx]._choices[_curChoice]._sceneIdx == 32767) { + _endGameFl = true; + } else { + if (_scenes[_curSceneIdx]._decisionChoices > 1) + _prvSceneIdx = _curSceneIdx; + if (_scenes[_curSceneIdx]._choices[_curChoice]._skipScene) { + _curSceneIdx = getSceneNumb(_scenes[_curSceneIdx]._choices[_curChoice]._sceneIdx); + _curBitmapIdx = 9999; + _actions.push(UpdateScene); + _actions.push(Redraw); + g_system->getTimerManager()->removeTimerProc(onTimer); + _timerInstalled = false; + } else { + _curSceneIdx = getSceneNumb(_scenes[_curSceneIdx]._choices[_curChoice]._sceneIdx); + _actions.push(ShowScene); + } + } +} + +void PlumbersGame::processTimer() { + debugC(7, kDebugGeneral, "%s", __FUNCTION__); + _timerInstalled = false; + if (!_endGameFl) + _actions.push(Redraw); +} + +void PlumbersGame::onTimer(void *arg) { + g_system->getTimerManager()->removeTimerProc(onTimer); + ((PlumbersGame*)arg)->processTimer(); +} + +void PlumbersGame::initTables() { + memset(_scenes, 0, sizeof(_scenes)); + memset(_bitmaps, 0, sizeof(_bitmaps)); +} + +void PlumbersGame::readTables(const Common::String &fileName) { + Common::File file; + if (!file.open(fileName)) + error("sReadTables(): Error reading BIN file"); + + initTables(); + + _totScore = file.readSint32LE(); + file.skip(10); + _totScene = file.readSint16LE(); + file.skip(6); + + char buf[kMaxName]; + for (int i = 0; i < kMaxScene; i++) { + _scenes[i]._bitmapNum = file.readSint16LE(); + _scenes[i]._startBitmap = file.readSint16LE(); + _scenes[i]._decisionChoices = file.readSint16LE(); + file.read(buf, kMaxName); + _scenes[i]._sceneName = Common::String(buf); + file.read(buf, kMaxName); + _scenes[i]._waveFilename = Common::String(buf); + file.read(buf, kMaxName); + _scenes[i]._decisionBitmap = Common::String(buf); + + for (int j = 0; j < kMaxChoice; j++) { + _scenes[i]._choices[j]._points = file.readSint32LE(); + _scenes[i]._choices[j]._sceneIdx = file.readSint16LE(); + _scenes[i]._choices[j]._skipScene = file.readSint16LE(); + int left = file.readSint16LE(); + int top = file.readSint16LE(); + int right = file.readSint16LE(); + int bottom = file.readSint16LE(); + _scenes[i]._choices[j]._region = Common::Rect(left, top, right, bottom); + } + } + + for (int i = 0; i < kMaxBitmaps; i++) { + _bitmaps[i]._duration = file.readSint16LE(); + file.read(buf, kMaxName); + _bitmaps[i]._filename = Common::String(buf); + } + file.close(); +} + +int PlumbersGame::getSceneNumb(int sNo) { + debugC(1, kDebugGeneral, "%s : %d", __FUNCTION__, sNo); + Common::String testString = Common::String::format("SC%02d", sNo); + + for (int sCurScene = 0; sCurScene < _totScene; sCurScene++) { + if (testString == _scenes[sCurScene]._sceneName) + return sCurScene; + } + return 0; +} + +} // End of namespace Plumbers diff --git a/engines/plumbers/plumbers.h b/engines/plumbers/plumbers.h new file mode 100644 index 000000000000..56b27fb7451d --- /dev/null +++ b/engines/plumbers/plumbers.h @@ -0,0 +1,135 @@ +/* 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 PLUMBERS_PLUMBERS_H +#define PLUMBERS_PLUMBERS_H + +#include "common/scummsys.h" +#include "common/config-manager.h" +#include "engines/advancedDetector.h" +#include "common/error.h" +#include "engines/engine.h" + +#include "audio/audiostream.h" +#include "audio/decoders/wave.h" +#include "audio/mixer.h" +#include "common/events.h" +#include "common/file.h" +#include "common/queue.h" +#include "common/system.h" +#include "common/timer.h" +#include "graphics/palette.h" +#include "graphics/screen.h" +#include "graphics/surface.h" +#include "image/bmp.h" + +#include "plumbers/console.h" + +namespace Plumbers { +enum PlumbersDebugChannels { + kDebugGeneral = 1 << 0 +}; + +class PlumbersGame : public Engine { +public: + PlumbersGame(OSystem *syst, const ADGameDescription *gameDesc); + ~PlumbersGame(); + + virtual Common::Error run(); + + // Detection related functions + const ADGameDescription *_gameDescription; + const char *getGameId() const; + Common::Platform getPlatform() const; + +private: + static const int kMaxName = 13 + 1; + static const int kMaxBitmaps = 2000; + static const int kMaxChoice = 3; + static const int kMaxScene = 100; + + struct { + int _duration; + Common::String _filename; + } _bitmaps[kMaxBitmaps]; + + struct { + int _bitmapNum; + int _startBitmap; + int _decisionChoices; + Common::String _sceneName; + Common::String _waveFilename; + Common::String _decisionBitmap; + struct { + long _points; + int _sceneIdx; + int _skipScene; + Common::Rect _region; + } _choices[kMaxChoice]; + } _scenes[kMaxScene]; + + Image::ImageDecoder *_image; + Console *_console; + + bool _showScoreFl; + bool _setDurationFl; + bool _leftButtonDownFl; + bool _endGameFl; + bool _timerInstalled; + int _curSceneIdx, _prvSceneIdx; + int _curBitmapIdx; + int _curChoice; + int _totScene; + long _totScore; + + enum Action { + Redraw, + ShowScene, + UpdateScene, + ChangeScene, + PlaySound + }; + + Common::Queue _actions; + + void loadImage(const Common::String &dirname, const Common::String &filename); + void drawScreen(); + + Audio::SoundHandle _soundHandle; + + void playSound(); + void stopSound(); + + void showScene(); + void updateScene(); + void changeScene(); + + void processTimer(); + static void onTimer(void *arg); + + void initTables(); + void readTables(const Common::String &fileName); + int getSceneNumb(int sNo); +}; +} // End of namespace Plumbers + +#endif