aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/access/configure.engine2
-rw-r--r--engines/bbvs/bbvs.cpp8
-rw-r--r--engines/bbvs/bbvs.h9
-rw-r--r--engines/bbvs/configure.engine2
-rw-r--r--engines/bbvs/detection.cpp17
-rw-r--r--engines/bbvs/dialogs.cpp30
-rw-r--r--engines/bbvs/minigames/bbairguitar.cpp25
-rw-r--r--engines/bbvs/minigames/bbtennis.cpp2
-rw-r--r--engines/bbvs/videoplayer.cpp11
-rw-r--r--engines/cine/cine.cpp52
-rw-r--r--engines/cine/cine.h1
-rw-r--r--engines/cine/main_loop.cpp4
-rw-r--r--engines/cine/saveload.cpp9
-rw-r--r--engines/cine/script_fw.cpp6
-rw-r--r--engines/cine/sound.cpp88
-rw-r--r--engines/cine/sound.h5
-rw-r--r--engines/fullpipe/gameloader.cpp2
-rw-r--r--engines/fullpipe/interaction.cpp2
-rw-r--r--engines/fullpipe/lift.cpp2
-rw-r--r--engines/fullpipe/messagehandlers.cpp2
-rw-r--r--engines/fullpipe/motion.cpp189
-rw-r--r--engines/fullpipe/motion.h93
-rw-r--r--engines/fullpipe/scenes.cpp4
-rw-r--r--engines/fullpipe/scenes/scene04.cpp14
-rw-r--r--engines/fullpipe/scenes/scene06.cpp8
-rw-r--r--engines/fullpipe/scenes/scene08.cpp4
-rw-r--r--engines/fullpipe/scenes/scene09.cpp6
-rw-r--r--engines/fullpipe/scenes/scene10.cpp2
-rw-r--r--engines/fullpipe/scenes/scene11.cpp8
-rw-r--r--engines/fullpipe/scenes/scene14.cpp10
-rw-r--r--engines/fullpipe/scenes/scene16.cpp2
-rw-r--r--engines/fullpipe/scenes/scene18and19.cpp2
-rw-r--r--engines/fullpipe/scenes/scene22.cpp8
-rw-r--r--engines/fullpipe/scenes/scene23.cpp6
-rw-r--r--engines/fullpipe/scenes/scene25.cpp2
-rw-r--r--engines/fullpipe/scenes/scene26.cpp2
-rw-r--r--engines/fullpipe/scenes/scene27.cpp8
-rw-r--r--engines/fullpipe/scenes/scene28.cpp2
-rw-r--r--engines/fullpipe/scenes/scene29.cpp14
-rw-r--r--engines/fullpipe/scenes/scene32.cpp8
-rw-r--r--engines/fullpipe/scenes/scene34.cpp12
-rw-r--r--engines/fullpipe/scenes/sceneFinal.cpp2
-rw-r--r--engines/gob/sound/cdrom.cpp5
-rw-r--r--engines/groovie/music.cpp8
-rw-r--r--engines/hopkins/computer.cpp8
-rw-r--r--engines/kyra/sound_intern.h2
-rw-r--r--engines/kyra/sound_towns.cpp100
-rw-r--r--engines/kyra/staticres.cpp2
-rw-r--r--engines/lastexpress/data/snd.cpp8
-rw-r--r--engines/lastexpress/data/snd.h6
-rw-r--r--engines/lure/res.cpp4
-rw-r--r--engines/lure/res_struct.cpp21
-rw-r--r--engines/lure/res_struct.h14
-rw-r--r--engines/mads/configure.engine2
-rw-r--r--engines/mads/detection_tables.h4
-rw-r--r--engines/mads/nebular/game_nebular.cpp4
-rw-r--r--engines/mads/nebular/menu_nebular.cpp26
-rw-r--r--engines/mads/nebular/menu_nebular.h15
-rw-r--r--engines/mads/nebular/nebular_scenes1.cpp2
-rw-r--r--engines/mads/nebular/sound_nebular.cpp6
-rw-r--r--engines/mads/resources.cpp4
-rw-r--r--engines/mohawk/sound.cpp30
-rw-r--r--engines/mohawk/sound.h6
-rw-r--r--engines/mortevielle/detection_tables.h2
-rw-r--r--engines/mortevielle/menu.cpp11
-rw-r--r--engines/mortevielle/sound.cpp44
-rw-r--r--engines/mortevielle/utils.cpp8
-rw-r--r--engines/neverhood/menumodule.cpp6
-rw-r--r--engines/neverhood/menumodule.h1
-rw-r--r--engines/neverhood/modules/module2700.cpp12
-rw-r--r--engines/neverhood/modules/module2700.h4
-rw-r--r--engines/sci/detection_tables.h11
-rw-r--r--engines/scumm/POTFILES1
-rw-r--r--engines/scumm/imuse_digi/dimuse.cpp3
-rw-r--r--engines/scumm/imuse_digi/dimuse_track.cpp9
-rw-r--r--engines/scumm/input.cpp9
-rw-r--r--engines/scumm/players/player_towns.cpp69
-rw-r--r--engines/scumm/players/player_towns.h4
-rw-r--r--engines/scumm/scumm-md5.h3
-rw-r--r--engines/sherlock/animation.cpp12
-rw-r--r--engines/sherlock/configure.engine2
-rw-r--r--engines/sherlock/debugger.cpp4
-rw-r--r--engines/sherlock/decompress.cpp128
-rw-r--r--engines/sherlock/detection_tables.h56
-rw-r--r--engines/sherlock/events.cpp41
-rw-r--r--engines/sherlock/events.h5
-rw-r--r--engines/sherlock/fonts.cpp68
-rw-r--r--engines/sherlock/image_file.cpp99
-rw-r--r--engines/sherlock/journal.cpp10
-rw-r--r--engines/sherlock/music.cpp12
-rw-r--r--engines/sherlock/music.h7
-rw-r--r--engines/sherlock/objects.cpp4
-rw-r--r--engines/sherlock/people.cpp5
-rw-r--r--engines/sherlock/scalpel/3do/movie_decoder.cpp43
-rw-r--r--engines/sherlock/scalpel/3do/movie_decoder.h3
-rw-r--r--engines/sherlock/scalpel/scalpel.cpp501
-rw-r--r--engines/sherlock/scalpel/scalpel.h53
-rw-r--r--engines/sherlock/scalpel/scalpel_fixed_text.cpp218
-rw-r--r--engines/sherlock/scalpel/scalpel_fixed_text.h68
-rw-r--r--engines/sherlock/scalpel/scalpel_journal.cpp19
-rw-r--r--engines/sherlock/scalpel/scalpel_map.cpp15
-rw-r--r--engines/sherlock/scalpel/scalpel_saveload.cpp3
-rw-r--r--engines/sherlock/scalpel/scalpel_scene.cpp146
-rw-r--r--engines/sherlock/scalpel/scalpel_scene.h2
-rw-r--r--engines/sherlock/scalpel/scalpel_screen.cpp251
-rw-r--r--engines/sherlock/scalpel/scalpel_screen.h40
-rw-r--r--engines/sherlock/scalpel/scalpel_talk.cpp116
-rw-r--r--engines/sherlock/scalpel/scalpel_talk.h26
-rw-r--r--engines/sherlock/scalpel/scalpel_user_interface.cpp113
-rw-r--r--engines/sherlock/scalpel/scalpel_user_interface.h3
-rw-r--r--engines/sherlock/scalpel/tsage/logo.cpp2
-rw-r--r--engines/sherlock/scene.cpp76
-rw-r--r--engines/sherlock/scene.h4
-rw-r--r--engines/sherlock/screen.cpp144
-rw-r--r--engines/sherlock/screen.h34
-rw-r--r--engines/sherlock/sherlock.cpp3
-rw-r--r--engines/sherlock/sherlock.h2
-rw-r--r--engines/sherlock/sound.cpp112
-rw-r--r--engines/sherlock/sound.h24
-rw-r--r--engines/sherlock/surface.cpp32
-rw-r--r--engines/sherlock/surface.h38
-rw-r--r--engines/sherlock/talk.cpp29
-rw-r--r--engines/sherlock/talk.h8
-rw-r--r--engines/sherlock/tattoo/tattoo.cpp9
-rw-r--r--engines/sherlock/tattoo/tattoo_darts.cpp115
-rw-r--r--engines/sherlock/tattoo/tattoo_fixed_text.cpp683
-rw-r--r--engines/sherlock/tattoo/tattoo_fixed_text.h120
-rw-r--r--engines/sherlock/tattoo/tattoo_inventory.cpp2
-rw-r--r--engines/sherlock/tattoo/tattoo_journal.cpp71
-rw-r--r--engines/sherlock/tattoo/tattoo_map.cpp17
-rw-r--r--engines/sherlock/tattoo/tattoo_people.cpp19
-rw-r--r--engines/sherlock/tattoo/tattoo_people.h2
-rw-r--r--engines/sherlock/tattoo/tattoo_resources.cpp394
-rw-r--r--engines/sherlock/tattoo/tattoo_resources.h9
-rw-r--r--engines/sherlock/tattoo/tattoo_scene.cpp36
-rw-r--r--engines/sherlock/tattoo/tattoo_talk.cpp4
-rw-r--r--engines/sherlock/tattoo/tattoo_user_interface.cpp23
-rw-r--r--engines/sherlock/tattoo/tattoo_user_interface.h3
-rw-r--r--engines/sherlock/tattoo/widget_base.cpp1
-rw-r--r--engines/sherlock/tattoo/widget_files.cpp23
-rw-r--r--engines/sherlock/tattoo/widget_inventory.cpp8
-rw-r--r--engines/sherlock/tattoo/widget_lab.cpp2
-rw-r--r--engines/sherlock/tattoo/widget_talk.cpp8
-rw-r--r--engines/sherlock/tattoo/widget_verbs.cpp5
-rw-r--r--engines/sword25/detection_tables.h13
-rw-r--r--engines/sword25/gfx/graphicengine.cpp36
-rw-r--r--engines/sword25/gfx/image/vectorimage.cpp11
-rw-r--r--engines/sword25/gfx/image/vectorimage.h1
-rw-r--r--engines/sword25/gfx/screenshot.cpp34
-rw-r--r--engines/sword25/gfx/staticbitmap.cpp4
-rw-r--r--engines/sword25/gfx/text.cpp36
-rw-r--r--engines/sword25/util/lua/scummvm_file.cpp4
-rw-r--r--engines/tinsel/music.cpp9
-rw-r--r--engines/tucker/staticres.cpp8
-rw-r--r--engines/tucker/tucker.h9
-rw-r--r--engines/wintermute/base/file/base_file.cpp2
-rw-r--r--engines/wintermute/base/gfx/base_surface.cpp5
-rw-r--r--engines/wintermute/detection_tables.h29
-rw-r--r--engines/wintermute/utils/convert_utf.cpp6
-rw-r--r--engines/wintermute/utils/convert_utf.h3
-rw-r--r--engines/zvision/POTFILES2
-rw-r--r--engines/zvision/video/zork_avi_decoder.cpp55
-rw-r--r--engines/zvision/video/zork_avi_decoder.h17
163 files changed, 3707 insertions, 1871 deletions
diff --git a/engines/access/configure.engine b/engines/access/configure.engine
index b1defce946..0082430062 100644
--- a/engines/access/configure.engine
+++ b/engines/access/configure.engine
@@ -1,3 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
-add_engine access "Access" no
+add_engine access "Access" yes
diff --git a/engines/bbvs/bbvs.cpp b/engines/bbvs/bbvs.cpp
index 11e4b6cea7..1d668f9c34 100644
--- a/engines/bbvs/bbvs.cpp
+++ b/engines/bbvs/bbvs.cpp
@@ -39,6 +39,8 @@
#include "common/error.h"
#include "common/fs.h"
#include "common/timer.h"
+#include "common/translation.h"
+#include "engines/advancedDetector.h"
#include "engines/util.h"
#include "graphics/cursorman.h"
#include "graphics/font.h"
@@ -116,9 +118,15 @@ BbvsEngine::BbvsEngine(OSystem *syst, const ADGameDescription *gd) :
Engine::syncSoundSettings();
+ _oldGUILanguage = TransMan.getCurrentLanguage();
+
+ if (gd->flags & GF_GUILANGSWITCH)
+ TransMan.setLanguage(getLanguageLocale(gd->language));
}
BbvsEngine::~BbvsEngine() {
+ if (TransMan.getCurrentLanguage() != _oldGUILanguage)
+ TransMan.setLanguage(_oldGUILanguage);
delete _random;
diff --git a/engines/bbvs/bbvs.h b/engines/bbvs/bbvs.h
index bbd8046a8b..d098aaf90b 100644
--- a/engines/bbvs/bbvs.h
+++ b/engines/bbvs/bbvs.h
@@ -63,6 +63,10 @@ class SoundMan;
#define BBVS_SAVEGAME_VERSION 0
enum {
+ GF_GUILANGSWITCH = (1 << 0) // If GUI language switch is required for menus
+};
+
+enum {
kVerbLook = 0,
kVerbUse = 1,
kVerbTalk = 2,
@@ -226,9 +230,12 @@ public:
void continueGameFromQuickSave();
void setNewSceneNum(int newSceneNum);
const Common::String getTargetName() { return _targetName; }
-private:
const ADGameDescription *_gameDescription;
+
+private:
Graphics::PixelFormat _pixelFormat;
+ Common::String _oldGUILanguage;
+
public:
Common::RandomSource *_random;
diff --git a/engines/bbvs/configure.engine b/engines/bbvs/configure.engine
index c1dc1ef924..8be3e078d9 100644
--- a/engines/bbvs/configure.engine
+++ b/engines/bbvs/configure.engine
@@ -1,3 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
-add_engine bbvs "Beavis and Butthead in Virtual Stupidity" no
+add_engine bbvs "Beavis and Butthead in Virtual Stupidity" yes
diff --git a/engines/bbvs/detection.cpp b/engines/bbvs/detection.cpp
index 3e247aad99..d2e3ab8e42 100644
--- a/engines/bbvs/detection.cpp
+++ b/engines/bbvs/detection.cpp
@@ -30,7 +30,7 @@
#include "graphics/thumbnail.h"
static const PlainGameDescriptor bbvsGames[] = {
- { "bbvs", "Beavis and Butthead in Virtual Stupidity" },
+ { "bbvs", "Beavis and Butt-head in Virtual Stupidity" },
{ 0, 0 }
};
@@ -40,10 +40,19 @@ static const ADGameDescription gameDescriptions[] = {
{
"bbvs",
0,
- AD_ENTRY1s("game0001.vnm", "637e5411751c7065bc385dd73d224561", 64004),
+ AD_ENTRY1s("vspr0001.vnm", "7ffe9b9e7ca322db1d48e86f5130578e", 1166628),
Common::EN_ANY,
Common::kPlatformWindows,
- ADGF_NO_FLAGS,
+ ADGF_NO_FLAGS | ADGF_TESTING,
+ GUIO0()
+ },
+ {
+ "bbvs",
+ 0,
+ AD_ENTRY1s("vspr0001.vnm", "91c76b1048f93208cd7b1a05ebccb408", 1176976),
+ Common::RU_RUS,
+ Common::kPlatformWindows,
+ GF_GUILANGSWITCH | ADGF_TESTING,
GUIO0()
},
@@ -66,7 +75,7 @@ public:
}
virtual const char *getName() const {
- return "MTV's Beavis and Butt-Head in Virtual Stupidity";
+ return "MTV's Beavis and Butt-head in Virtual Stupidity";
}
virtual const char *getOriginalCopyright() const {
diff --git a/engines/bbvs/dialogs.cpp b/engines/bbvs/dialogs.cpp
index af95f06c1e..ef7f3c9320 100644
--- a/engines/bbvs/dialogs.cpp
+++ b/engines/bbvs/dialogs.cpp
@@ -24,6 +24,7 @@
#include "common/events.h"
#include "gui/gui-manager.h"
#include "gui/ThemeEval.h"
+#include "engines/advancedDetector.h"
namespace Bbvs {
@@ -53,6 +54,27 @@ static const MenuButton kMenuButtons[] = {
{"Back ..", kCmdBack}
};
+static const MenuButton kMenuButtonsRu[] = {
+ // Main menu
+ {"\xBD\xDE\xD2\xD0\xEF \xD8\xD3\xE0\xD0", kCmdNewGame},
+ {"\xBF\xE0\xDE\xD4\xDE\xDB\xD6\xD8\xE2\xEC", kCmdContinue},
+ {"\xB5\xE9\xD5 ..", kCmdOptions},
+ {"\xBC\xD8\xDD\xD8 \xB8\xD3\xE0\xEB", kCmdMiniGames},
+ {"\xB2\xEB\xE5\xDE\xD4", kCmdQuit},
+ // Options
+ {"\xB4\xD5\xD8\xDD\xE1\xE2\xD0\xDB\xDB\xEF\xE6\xD8\xEF", kCmdUninstall},
+ {"\xB0\xD2\xE2\xDE\xE0\xEB", kCmdCredits},
+ {"\xBF\xE0\xDE\xDB\xDE\xD3", kCmdOpening},
+ {"\xC0\xD5\xDA\xDB\xD0\xDC\xD0", kCmdChicksNStuff},
+ {"\xBD\xD0\xD7\xD0\xD4 ..", kCmdBack},
+ // Minigames
+ {"\xC1\xDD\xD0\xD9\xDF\xD5\xE0", kCmdHockALoogie},
+ {"\xB6\xE3\xDA\xDE\xD6\xD0\xE0\xDA\xD0", kCmdBugJustice},
+ {"\xBF\xE2\xD5\xDD\xD8\xE1", kCmdCourtChaos},
+ {"\xB6\xD8\xD0\xDE\xD9 \xB7\xD2\xE3\xDA", kCmdAirGuitar},
+ {"\xBD\xD0\xD7\xD0\xD4 ..", kCmdBack}
+};
+
MainMenu::MainMenu(BbvsEngine *vm) : Dialog(0, 0, 1, 1), _vm(vm) {
init();
}
@@ -160,7 +182,13 @@ void MainMenu::handleCommand(GUI::CommandSender *sender, uint32 command, uint32
void MainMenu::gotoMenuScreen(int screen) {
for (int i = 0; i < 5; ++i) {
- const MenuButton *btn = &kMenuButtons[screen * 5 + i];
+ const MenuButton *btn;
+
+ if (_vm->_gameDescription->language == Common::RU_RUS) {
+ btn = &kMenuButtonsRu[screen * 5 + i];
+ } else {
+ btn = &kMenuButtons[screen * 5 + i];
+ }
_buttons[i]->setLabel(btn->label);
_buttons[i]->setCmd(btn->cmd);
_buttons[i]->setEnabled(btn->cmd != 0);
diff --git a/engines/bbvs/minigames/bbairguitar.cpp b/engines/bbvs/minigames/bbairguitar.cpp
index 26e27a966f..04175f7290 100644
--- a/engines/bbvs/minigames/bbairguitar.cpp
+++ b/engines/bbvs/minigames/bbairguitar.cpp
@@ -27,6 +27,7 @@
#include "gui/dialog.h"
#include "gui/message.h"
+#include "gui/filebrowser-dialog.h"
namespace Bbvs {
@@ -1204,15 +1205,25 @@ void MinigameBbAirGuitar::stopNote(int noteNum) {
}
bool MinigameBbAirGuitar::getLoadFilename(Common::String &filename) {
- // TODO Run dialog and return actual filename
- filename = "test.air";
- return true;
+ GUI::FileBrowserDialog browser(0, "air", GUI::kFBModeLoad);
+
+ if (browser.runModal() > 0) {
+ filename = browser.getResult();
+ return true;
+ }
+
+ return false;
}
bool MinigameBbAirGuitar::getSaveFilename(Common::String &filename) {
- // TODO Run dialog and return actual filename
- filename = "test.air";
- return true;
+ GUI::FileBrowserDialog browser(0, "air", GUI::kFBModeSave);
+
+ if (browser.runModal() > 0) {
+ filename = browser.getResult();
+ return true;
+ }
+
+ return false;
}
bool MinigameBbAirGuitar::querySaveModifiedDialog() {
@@ -1240,7 +1251,7 @@ bool MinigameBbAirGuitar::loadTracks() {
if (!querySaveModifiedTracks())
return false;
-
+
Common::String filename;
if (!getLoadFilename(filename))
return false;
diff --git a/engines/bbvs/minigames/bbtennis.cpp b/engines/bbvs/minigames/bbtennis.cpp
index 7763548330..6c7d8cbf31 100644
--- a/engines/bbvs/minigames/bbtennis.cpp
+++ b/engines/bbvs/minigames/bbtennis.cpp
@@ -516,7 +516,7 @@ void MinigameBbTennis::updateObjs() {
}
obj->blinkCtr = _vm->getRandom(64) + 60;
_tennisPlayerDelay = _vm->getRandom(128) + 400 - _playerDecrease;
- if (_vm->getRandom(10) == 1 && !isAnySoundPlaying(kAllSounds, 0x11))
+ if (_vm->getRandom(10) == 1 && !isAnySoundPlaying(kAllSounds, 11))
playSound(kYuppieEnteringCourtSounds[_vm->getRandom(2)]);
}
diff --git a/engines/bbvs/videoplayer.cpp b/engines/bbvs/videoplayer.cpp
index 9ea73ad10b..1b721c434f 100644
--- a/engines/bbvs/videoplayer.cpp
+++ b/engines/bbvs/videoplayer.cpp
@@ -43,6 +43,8 @@ void BbvsEngine::playVideo(int videoNum) {
return;
}
+ debug(0, "Screen format: %s", _system->getScreenFormat().toString().c_str());
+
Video::VideoDecoder *videoDecoder = new Video::AVIDecoder();
if (!videoDecoder->loadFile(videoFilename)) {
delete videoDecoder;
@@ -58,7 +60,14 @@ void BbvsEngine::playVideo(int videoNum) {
if (videoDecoder->needsUpdate()) {
const Graphics::Surface *frame = videoDecoder->decodeNextFrame();
if (frame) {
- _system->copyRectToScreen(frame->getPixels(), frame->pitch, 0, 0, frame->w, frame->h);
+ if (frame->format.bytesPerPixel > 1) {
+ Graphics::Surface *frame1 = frame->convertTo(_system->getScreenFormat());
+ _system->copyRectToScreen(frame1->getPixels(), frame1->pitch, 0, 0, frame1->w, frame1->h);
+ frame1->free();
+ delete frame1;
+ } else {
+ _system->copyRectToScreen(frame->getPixels(), frame->pitch, 0, 0, frame->w, frame->h);
+ }
_system->updateScreen();
}
}
diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp
index a4af8f2201..d2f088dcd8 100644
--- a/engines/cine/cine.cpp
+++ b/engines/cine/cine.cpp
@@ -22,10 +22,14 @@
#include "common/config-manager.h"
#include "common/debug-channels.h"
+#include "common/events.h"
#include "engines/util.h"
#include "graphics/cursorman.h"
+#include "graphics/palette.h"
+
+#include "image/iff.h"
#include "cine/cine.h"
#include "cine/bg_list.h"
@@ -89,9 +93,16 @@ void CineEngine::syncSoundSettings() {
}
Common::Error CineEngine::run() {
+ if (g_cine->getGameType() == GType_FW && (g_cine->getFeatures() & GF_CD)) {
+ showSplashScreen();
+ }
+
// Initialize backend
initGraphics(320, 200, false);
+ if (g_cine->getGameType() == GType_FW && (g_cine->getFeatures() & GF_CD))
+ checkCD();
+
if (getPlatform() == Common::kPlatformDOS) {
g_sound = new PCSound(_mixer, this);
} else {
@@ -236,4 +247,45 @@ void CineEngine::initialize() {
}
}
+void CineEngine::showSplashScreen() {
+ Common::File file;
+ if (!file.open("sony.lbm"))
+ return;
+
+ Image::IFFDecoder decoder;
+ if (!decoder.loadStream(file))
+ return;
+
+ const Graphics::Surface *surface = decoder.getSurface();
+ if (surface->w == 640 && surface->h == 480) {
+ initGraphics(640, 480, true);
+
+ const byte *palette = decoder.getPalette();
+ int paletteColorCount = decoder.getPaletteColorCount();
+ g_system->getPaletteManager()->setPalette(palette, 0, paletteColorCount);
+
+ g_system->copyRectToScreen(surface->getPixels(), 640, 0, 0, 640, 480);
+ g_system->updateScreen();
+
+ Common::EventManager *eventMan = g_system->getEventManager();
+
+ bool done = false;
+ uint32 now = g_system->getMillis();
+
+ while (!done && g_system->getMillis() - now < 2000) {
+ Common::Event event;
+ while (eventMan->pollEvent(event)) {
+ if (event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) {
+ done = true;
+ break;
+ }
+ if (shouldQuit())
+ done = true;
+ }
+ }
+ }
+
+ decoder.destroy();
+}
+
} // End of namespace Cine
diff --git a/engines/cine/cine.h b/engines/cine/cine.h
index e620d2ffa5..71a0c242b6 100644
--- a/engines/cine/cine.h
+++ b/engines/cine/cine.h
@@ -145,6 +145,7 @@ public:
private:
void initialize();
+ void showSplashScreen();
void resetEngine();
bool loadPlainSaveFW(Common::SeekableReadStream &in, CineSaveGameFormat saveGameFormat);
bool loadTempSaveOS(Common::SeekableReadStream &in);
diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp
index 9ce683445f..e52fc464d5 100644
--- a/engines/cine/main_loop.cpp
+++ b/engines/cine/main_loop.cpp
@@ -31,6 +31,8 @@
#include "cine/bg_list.h"
#include "cine/sound.h"
+#include "backends/audiocd/audiocd.h"
+
namespace Cine {
struct MouseStatusStruct {
@@ -219,6 +221,8 @@ void manageEvents() {
mouseData.left = mouseLeft;
mouseData.right = mouseRight;
+
+ g_system->getAudioCDManager()->updateCD();
}
void getMouseData(uint16 param, uint16 *pButton, uint16 *pX, uint16 *pY) {
diff --git a/engines/cine/saveload.cpp b/engines/cine/saveload.cpp
index c707c60695..907086a9a1 100644
--- a/engines/cine/saveload.cpp
+++ b/engines/cine/saveload.cpp
@@ -543,6 +543,15 @@ bool CineEngine::loadTempSaveOS(Common::SeekableReadStream &in) {
loadRel(currentRelName);
}
+ // Reset background music in CD version of Future Wars
+ if (getGameType() == GType_FW && (getFeatures() & GF_CD)) {
+ if (strlen(bgNames[0])) {
+ char buffer[20];
+ removeExtention(buffer, bgNames[0]);
+ g_sound->setBgMusic(atoi(buffer + 1));
+ }
+ }
+
// Load first background (Uses loadBg)
if (strlen(bgNames[0])) {
loadBg(bgNames[0]);
diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp
index c0b0c1f5da..6ad38f4433 100644
--- a/engines/cine/script_fw.cpp
+++ b/engines/cine/script_fw.cpp
@@ -1380,6 +1380,12 @@ int FWScript::o1_loadBg() {
debugC(5, kCineDebugScript, "Line: %d: loadBg(\"%s\")", _line, param);
+ if (g_cine->getGameType() == GType_FW && (g_cine->getFeatures() & GF_CD)) {
+ char buffer[20];
+ removeExtention(buffer, param);
+ g_sound->setBgMusic(atoi(buffer + 1));
+ }
+
loadBg(param);
g_cine->_bgIncrustList.clear();
bgVar0 = 0;
diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp
index 0c788b816c..7cab067371 100644
--- a/engines/cine/sound.cpp
+++ b/engines/cine/sound.cpp
@@ -32,6 +32,8 @@
#include "cine/cine.h"
#include "cine/sound.h"
+#include "backends/audiocd/audiocd.h"
+
#include "audio/audiostream.h"
#include "audio/fmopl.h"
#include "audio/mididrv.h"
@@ -907,6 +909,10 @@ void PCSoundFxPlayer::unload() {
PCSound::PCSound(Audio::Mixer *mixer, CineEngine *vm)
: Sound(mixer, vm), _soundDriver(0) {
+ _currentMusic = 0;
+ _currentMusicStatus = 0;
+ _currentBgSlot = 0;
+
const MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB);
const MusicType musicType = MidiDriver::getMusicType(dev);
if (musicType == MT_MT32 || musicType == MT_GM) {
@@ -940,23 +946,98 @@ PCSound::~PCSound() {
delete _soundDriver;
}
+static const char *const musicFileNames[11] = {
+ "DUGGER.DAT",
+ "SUITE21.DAT",
+ "FWARS.DAT",
+ "SUITE23.DAT",
+ "SUITE22.DAT",
+ "ESCAL",
+ "MOINES.DAT",
+ "MEDIAVAL.DAT",
+ "SFUTUR",
+ "ALIENS",
+ "TELESONG.DAT",
+};
+
+static uint8 musicCDTracks[11] = {
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, 22,
+};
+
void PCSound::loadMusic(const char *name) {
debugC(5, kCineDebugSound, "PCSound::loadMusic('%s')", name);
- _player->load(name);
+ if (_vm->getGameType() == GType_FW && (_vm->getFeatures() & GF_CD)) {
+ _currentMusic = 0;
+ _currentMusicStatus = 0;
+ for (int i = 0; i < 11; i++) {
+ if (!strcmp((const char *)name, musicFileNames[i])) {
+ _currentMusic = musicCDTracks[i];
+ _currentMusicStatus = musicCDTracks[i];
+ }
+ }
+ } else {
+ _player->load(name);
+ }
}
void PCSound::playMusic() {
debugC(5, kCineDebugSound, "PCSound::playMusic()");
- _player->play();
+ if (_vm->getGameType() == GType_FW && (_vm->getFeatures() & GF_CD)) {
+ g_system->getAudioCDManager()->stop();
+ g_system->getAudioCDManager()->play(_currentMusic - 1, -1, 0, 0);
+ } else {
+ _player->play();
+ }
+}
+
+static uint8 bgCDTracks[49] = {
+ 0, 21, 21, 23, 0, 29, 0, 0, 0, 0,
+ 0, 27, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 22, 22, 23, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+void PCSound::setBgMusic(int num) {
+ debugC(5, kCineDebugSound, "PCSound::setBgMusic(%d)", num);
+ _currentBgSlot = num;
+ if (!bgCDTracks[_currentBgSlot])
+ return;
+
+ if ((_currentBgSlot == 1) || (_currentMusicStatus == 0 && _currentMusic != bgCDTracks[_currentBgSlot])) {
+ _currentMusic = bgCDTracks[_currentBgSlot];
+ g_system->getAudioCDManager()->stop();
+ g_system->getAudioCDManager()->play(bgCDTracks[_currentBgSlot] - 1, -1, 0, 0);
+ }
}
void PCSound::stopMusic() {
debugC(5, kCineDebugSound, "PCSound::stopMusic()");
+
+ if (_vm->getGameType() == GType_FW && (_vm->getFeatures() & GF_CD)) {
+ if (_currentBgSlot != 1)
+ g_system->getAudioCDManager()->stop();
+ }
_player->stop();
}
void PCSound::fadeOutMusic() {
debugC(5, kCineDebugSound, "PCSound::fadeOutMusic()");
+
+ if (_vm->getGameType() == GType_FW && (_vm->getFeatures() & GF_CD)) {
+ if (_currentMusicStatus) {
+ if (_currentBgSlot == 1) {
+ _currentMusicStatus = 0;
+ } else {
+ _currentMusic = 0;
+ _currentMusicStatus = 0;
+ g_system->getAudioCDManager()->stop();
+ if (bgCDTracks[_currentBgSlot]) {
+ g_system->getAudioCDManager()->play(_currentBgSlot - 1, -1, 0, 0);
+ }
+ }
+ }
+ }
_player->fadeOut();
}
@@ -1056,6 +1137,9 @@ void PaulaSound::stopMusic() {
_mixer->stopHandle(_moduleHandle);
}
+void PaulaSound::setBgMusic(int num) {
+}
+
void PaulaSound::fadeOutMusic() {
debugC(5, kCineDebugSound, "PaulaSound::fadeOutMusic()");
Common::StackLock lock(_musicMutex);
diff --git a/engines/cine/sound.h b/engines/cine/sound.h
index efb3811f9a..0149071ed7 100644
--- a/engines/cine/sound.h
+++ b/engines/cine/sound.h
@@ -48,6 +48,7 @@ public:
virtual void playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) = 0;
virtual void stopSound(int channel) = 0;
+ virtual void setBgMusic(int num) = 0;
protected:
@@ -71,11 +72,14 @@ public:
virtual void playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat);
virtual void stopSound(int channel);
+ virtual void setBgMusic(int num);
protected:
PCSoundDriver *_soundDriver;
PCSoundFxPlayer *_player;
+
+ uint8 _currentMusic, _currentMusicStatus, _currentBgSlot;
};
class PaulaSound : public Sound {
@@ -91,6 +95,7 @@ public:
virtual void playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat);
virtual void stopSound(int channel);
+ virtual void setBgMusic(int num);
enum {
PAULA_FREQ = 3579545,
diff --git a/engines/fullpipe/gameloader.cpp b/engines/fullpipe/gameloader.cpp
index 7815475d37..68b63d398a 100644
--- a/engines/fullpipe/gameloader.cpp
+++ b/engines/fullpipe/gameloader.cpp
@@ -419,7 +419,7 @@ bool GameLoader::unloadScene(int sceneId) {
if (_sc2array[sceneTag]._isLoaded)
saveScenePicAniInfos(sceneId);
- _sc2array[sceneTag]._motionController->freeItems();
+ _sc2array[sceneTag]._motionController->detachAllObjects();
delete tag->_scene;
tag->_scene = 0;
diff --git a/engines/fullpipe/interaction.cpp b/engines/fullpipe/interaction.cpp
index 84e9688e30..4aac3485f4 100644
--- a/engines/fullpipe/interaction.cpp
+++ b/engines/fullpipe/interaction.cpp
@@ -311,7 +311,7 @@ LABEL_38:
if (abs(xpos - subj->_ox) > 1 || abs(ypos - subj->_oy) > 1
|| (inter->_staticsId2 != 0 && (subj->_statics == 0 || subj->_statics->_staticsId != inter->_staticsId2))) {
- mq = getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId)->method34(subj, xpos, ypos, 1, inter->_staticsId2);
+ mq = getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId)->startMove(subj, xpos, ypos, 1, inter->_staticsId2);
if (!mq)
return false;
diff --git a/engines/fullpipe/lift.cpp b/engines/fullpipe/lift.cpp
index 9a3d91540a..d066c89d4a 100644
--- a/engines/fullpipe/lift.cpp
+++ b/engines/fullpipe/lift.cpp
@@ -324,7 +324,7 @@ void FullpipeEngine::lift_walkAndGo() {
ExCommand *ex;
if (abs(_liftX - _aniMan->_ox) > 1 || abs(_liftY - _aniMan->_oy) > 1 || _aniMan->_movement || _aniMan->_statics->_staticsId != ST_MAN_UP) {
- mq = getCurrSceneSc2MotionController()->method34(_aniMan, _liftX, _liftY, 1, ST_MAN_UP);
+ mq = getCurrSceneSc2MotionController()->startMove(_aniMan, _liftX, _liftY, 1, ST_MAN_UP);
if (mq) {
ex = new ExCommand(0, 17, MSG_LIFT_CLICKBUTTON, 0, 0, 0, 1, 0, 0, 0);
diff --git a/engines/fullpipe/messagehandlers.cpp b/engines/fullpipe/messagehandlers.cpp
index d4f79d1dd8..94754ad22a 100644
--- a/engines/fullpipe/messagehandlers.cpp
+++ b/engines/fullpipe/messagehandlers.cpp
@@ -781,7 +781,7 @@ int MovGraph_messageHandler(ExCommand *cmd) {
int off = (node->_field_14 >> 16) & 0xFF;
double off2 = ((link->_movGraphNode2->_field_14 >> 8) & 0xff) - off;
- top = off + (int)(sqrt(sq) * off2 / link->_distance);
+ top = off + (int)(sqrt(sq) * off2 / link->_z);
} else {
top = (gr->calcOffset(ani->_ox, ani->_oy)->_field_14 >> 8) & 0xff;
}
diff --git a/engines/fullpipe/motion.cpp b/engines/fullpipe/motion.cpp
index 5845ad1501..1a61cb742a 100644
--- a/engines/fullpipe/motion.cpp
+++ b/engines/fullpipe/motion.cpp
@@ -88,7 +88,7 @@ bool MctlCompound::load(MfcArchive &file) {
for (int i = 0; i < count; i++) {
debug(6, "CompoundArray[%d]", i);
- MctlCompoundArrayItem *obj = new MctlCompoundArrayItem();
+ MctlItem *obj = new MctlItem();
obj->_motionControllerObj = (MotionController *)file.readClass();
@@ -114,14 +114,14 @@ bool MctlCompound::load(MfcArchive &file) {
return true;
}
-void MctlCompound::addObject(StaticANIObject *obj) {
+void MctlCompound::attachObject(StaticANIObject *obj) {
for (uint i = 0; i < _motionControllers.size(); i++)
- _motionControllers[i]->_motionControllerObj->addObject(obj);
+ _motionControllers[i]->_motionControllerObj->attachObject(obj);
}
-int MctlCompound::removeObject(StaticANIObject *obj) {
+int MctlCompound::detachObject(StaticANIObject *obj) {
for (uint i = 0; i < _motionControllers.size(); i++)
- _motionControllers[i]->_motionControllerObj->removeObject(obj);
+ _motionControllers[i]->_motionControllerObj->detachObject(obj);
return 1;
}
@@ -150,12 +150,12 @@ void MctlCompound::initMovGraph2() {
}
}
-void MctlCompound::freeItems() {
+void MctlCompound::detachAllObjects() {
for (uint i = 0; i < _motionControllers.size(); i++)
- _motionControllers[i]->_motionControllerObj->freeItems();
+ _motionControllers[i]->_motionControllerObj->detachAllObjects();
}
-MessageQueue *MctlCompound::method34(StaticANIObject *ani, int sourceX, int sourceY, int fuzzyMatch, int staticsId) {
+MessageQueue *MctlCompound::startMove(StaticANIObject *ani, int sourceX, int sourceY, int fuzzyMatch, int staticsId) {
int idx = -1;
int sourceIdx = -1;
@@ -187,7 +187,7 @@ MessageQueue *MctlCompound::method34(StaticANIObject *ani, int sourceX, int sour
return 0;
if (idx == sourceIdx)
- return _motionControllers[idx]->_motionControllerObj->method34(ani, sourceX, sourceY, fuzzyMatch, staticsId);
+ return _motionControllers[idx]->_motionControllerObj->startMove(ani, sourceX, sourceY, fuzzyMatch, staticsId);
double dist;
MctlConnectionPoint *cp = findClosestConnectionPoint(ani->_ox, ani->_oy, idx, sourceX, sourceY, sourceIdx, &dist);
@@ -195,7 +195,7 @@ MessageQueue *MctlCompound::method34(StaticANIObject *ani, int sourceX, int sour
if (!cp)
return 0;
- MessageQueue *mq = _motionControllers[idx]->_motionControllerObj->doWalkTo(ani, cp->_connectionX, cp->_connectionY, 1, cp->_field_14);
+ MessageQueue *mq = _motionControllers[idx]->_motionControllerObj->doWalkTo(ani, cp->_connectionX, cp->_connectionY, 1, cp->_mctlmirror);
if (!mq)
return 0;
@@ -264,7 +264,7 @@ MessageQueue *MctlCompound::doWalkTo(StaticANIObject *subj, int xpos, int ypos,
if (!closestP)
return 0;
- MessageQueue *mq = _motionControllers[match1]->_motionControllerObj->doWalkTo(subj, closestP->_connectionX, closestP->_connectionY, 1, closestP->_field_14);
+ MessageQueue *mq = _motionControllers[match1]->_motionControllerObj->doWalkTo(subj, closestP->_connectionX, closestP->_connectionY, 1, closestP->_mctlmirror);
ExCommand *ex;
@@ -287,7 +287,7 @@ MessageQueue *MctlCompound::doWalkTo(StaticANIObject *subj, int xpos, int ypos,
return mq;
}
-MctlCompoundArrayItem::~MctlCompoundArrayItem() {
+MctlItem::~MctlItem() {
delete _movGraphReactObj;
delete _motionControllerObj;
}
@@ -304,7 +304,7 @@ MctlLadder::MctlLadder() {
}
MctlLadder::~MctlLadder() {
- freeItems();
+ detachAllObjects();
}
int MctlLadder::collisionDetection(StaticANIObject *man) {
@@ -326,7 +326,7 @@ int MctlLadder::collisionDetection(StaticANIObject *man) {
return res;
}
-void MctlLadder::addObject(StaticANIObject *obj) {
+void MctlLadder::attachObject(StaticANIObject *obj) {
if (findObjectPos(obj) < 0) {
MctlLadderMovement *movement = new MctlLadderMovement;
@@ -391,7 +391,7 @@ bool MctlLadder::initMovement(StaticANIObject *ani, MctlLadderMovement *movement
return true;
}
-void MctlLadder::freeItems() {
+void MctlLadder::detachAllObjects() {
_mgm.clear();
for (uint i = 0; i < _ladmovements.size(); i++) {
@@ -402,7 +402,7 @@ void MctlLadder::freeItems() {
_ladmovements.clear();
}
-MessageQueue *MctlLadder::method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) {
+MessageQueue *MctlLadder::startMove(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) {
MessageQueue *mq = doWalkTo(subj, xpos, ypos, fuzzyMatch, staticsId);
if (mq) {
@@ -661,7 +661,7 @@ void MctlCompound::replaceNodeX(int from, int to) {
node->_x = to;
}
- gr->calcNodeDistancesAndAngles();
+ gr->recalcLinkParams();
}
}
}
@@ -669,10 +669,9 @@ void MctlCompound::replaceNodeX(int from, int to) {
MctlConnectionPoint::MctlConnectionPoint() {
_connectionX = 0;
_connectionY = 0;
- _field_C = 0;
- _field_10 = 0;
- _field_14 = 0;
- _field_16 = 0;
+ _mctlflags = 0;
+ _mctlstatic = 0;
+ _mctlmirror = 0;
_messageQueueObj = 0;
_motionControllerObj = 0;
}
@@ -779,7 +778,7 @@ bool MovGraph::load(MfcArchive &file) {
return true;
}
-void MovGraph::addObject(StaticANIObject *obj) {
+void MovGraph::attachObject(StaticANIObject *obj) {
_mgm.clear();
_mgm.addItem(obj->_id);
@@ -796,13 +795,13 @@ void MovGraph::addObject(StaticANIObject *obj) {
_mgm.addItem(obj->_id); // FIXME: Is it really needed?
}
-int MovGraph::removeObject(StaticANIObject *obj) {
- warning("STUB: MovGraph::removeObject()");
+int MovGraph::detachObject(StaticANIObject *obj) {
+ warning("STUB: MovGraph::detachObject()");
return 0;
}
-void MovGraph::freeItems() {
+void MovGraph::detachAllObjects() {
for (uint i = 0; i < _items.size(); i++) {
_items[i]->free();
@@ -812,7 +811,7 @@ void MovGraph::freeItems() {
_items.clear();
}
-Common::Array<MovItem *> *MovGraph::method28(StaticANIObject *ani, int x, int y, int flag1, int *rescount) {
+Common::Array<MovItem *> *MovGraph::getPaths(StaticANIObject *ani, int x, int y, int flag1, int *rescount) {
*rescount = 0;
if (_items.size() <= 0)
@@ -828,7 +827,7 @@ Common::Array<MovItem *> *MovGraph::method28(StaticANIObject *ani, int x, int y,
}
_items[idx]->free();
- calcNodeDistancesAndAngles();
+ recalcLinkParams();
_items[idx]->movarr._movSteps.clear();
@@ -838,7 +837,7 @@ Common::Array<MovItem *> *MovGraph::method28(StaticANIObject *ani, int x, int y,
point.y = ani->_oy;
if (!calcChunk(idx, ani->_ox, ani->_oy, &_items[idx]->movarr, 0))
- findClosestLink(idx, &point, &_items[idx]->movarr);
+ getNearestPoint(idx, &point, &_items[idx]->movarr);
_items[idx]->count = 0;
@@ -873,12 +872,12 @@ Common::Array<MovItem *> *MovGraph::method28(StaticANIObject *ani, int x, int y,
return 0;
}
-bool MovGraph::method2C(StaticANIObject *obj, int x, int y) {
+bool MovGraph::setPosImmediate(StaticANIObject *obj, int x, int y) {
obj->setOXY(x, y);
- return method3C(obj, 1);
+ return resetPosition(obj, 1);
}
-MessageQueue *MovGraph::method34(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) {
+MessageQueue *MovGraph::startMove(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) {
if (!ani) {
if (!_items.size())
return 0;
@@ -896,7 +895,7 @@ MessageQueue *MovGraph::method34(StaticANIObject *ani, int xpos, int ypos, int f
return 0;
int count;
- Common::Array<MovItem *> *movitems = method28(ani, xpos, ypos, fuzzyMatch, &count);
+ Common::Array<MovItem *> *movitems = getPaths(ani, xpos, ypos, fuzzyMatch, &count);
if (!movitems)
return 0;
@@ -941,9 +940,9 @@ MessageQueue *MovGraph::method34(StaticANIObject *ani, int xpos, int ypos, int f
int count2;
ani->setSomeDynamicPhaseIndex(ex->_field_14);
- method28(ani, xpos, ypos, fuzzyMatch, &count2);
+ getPaths(ani, xpos, ypos, fuzzyMatch, &count2);
- int idx = getItemIndexByStaticAni(ani);
+ int idx = getObjectIndex(ani);
count = _items[idx]->count;
movitems = _items[idx]->movitems;
}
@@ -951,12 +950,12 @@ MessageQueue *MovGraph::method34(StaticANIObject *ani, int xpos, int ypos, int f
return method50(ani, _callback1(ani, movitems, count), staticsId);
}
-void MovGraph::changeCallback(MovArr *(*callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter)) {
+void MovGraph::setSelFunc(MovArr *(*callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter)) {
_callback1 = callback1;
}
-bool MovGraph::method3C(StaticANIObject *ani, int flag) {
- int idx = getItemIndexByStaticAni(ani);
+bool MovGraph::resetPosition(StaticANIObject *ani, int flag) {
+ int idx = getObjectIndex(ani);
if (idx == -1)
return false;
@@ -967,7 +966,7 @@ bool MovGraph::method3C(StaticANIObject *ani, int flag) {
point.x = ani->_ox;
point.y = ani->_oy;
- findClosestLink(idx, &point, &movarr);
+ getNearestPoint(idx, &point, &movarr);
ani->setOXY(point.x, point.y);
if (flag) {
@@ -990,15 +989,15 @@ bool MovGraph::method3C(StaticANIObject *ani, int flag) {
return true;
}
-bool MovGraph::method44(StaticANIObject *ani, int x, int y) {
- int idx = getItemIndexByStaticAni(ani);
+bool MovGraph::canDropInventory(StaticANIObject *ani, int x, int y) {
+ int idx = getObjectIndex(ani);
MovArr m;
if (idx != -1) {
if (x != -1 || y != -1) {
int counter;
- Common::Array<MovItem *> *movitem = method28(ani, x, y, 0, &counter);
+ Common::Array<MovItem *> *movitem = getPaths(ani, x, y, 0, &counter);
if (movitem) {
MovArr *movarr = _callback1(ani, movitem, counter);
@@ -1021,13 +1020,13 @@ MessageQueue *MovGraph::doWalkTo(StaticANIObject *subj, int xpos, int ypos, int
PicAniInfo picAniInfo;
int ss;
- Common::Array<MovItem *> *movitem = method28(subj, xpos, ypos, fuzzyMatch, &ss);
+ Common::Array<MovItem *> *movitem = getPaths(subj, xpos, ypos, fuzzyMatch, &ss);
subj->getPicAniInfo(&picAniInfo);
if (movitem) {
MovArr *goal = _callback1(subj, movitem, ss);
- int idx = getItemIndexByStaticAni(subj);
+ int idx = getObjectIndex(subj);
for (int i = 0; i < _items[idx]->count; i++) {
if ((*_items[idx]->movitems)[i]->movarr == goal) {
@@ -1052,10 +1051,10 @@ MessageQueue *MovGraph::doWalkTo(StaticANIObject *subj, int xpos, int ypos, int
}
}
- movitem = method28(subj, xpos, ypos, fuzzyMatch, &ss);
+ movitem = getPaths(subj, xpos, ypos, fuzzyMatch, &ss);
if (movitem) {
MovArr *goal = _callback1(subj, movitem, ss);
- int idx = getItemIndexByStaticAni(subj);
+ int idx = getObjectIndex(subj);
if (_items[idx]->count > 0) {
int arridx = 0;
@@ -1106,7 +1105,7 @@ MessageQueue *MovGraph::sub1(StaticANIObject *ani, int x, int y, int stid, int x
int rescount;
- Common::Array<MovItem *> *movitems = method28(ani, x1, y1, flag1, &rescount);
+ Common::Array<MovItem *> *movitems = getPaths(ani, x1, y1, flag1, &rescount);
if (!movitems) {
ani->setPicAniInfo(&picinfo);
@@ -1117,7 +1116,7 @@ MessageQueue *MovGraph::sub1(StaticANIObject *ani, int x, int y, int stid, int x
MessageQueue *res = 0;
MovArr *goal = _callback1(ani, movitems, rescount);
- int idx = getItemIndexByStaticAni(ani);
+ int idx = getObjectIndex(ani);
MovGraphItem *movgitem = _items[idx];
int cnt = movgitem->count;
@@ -1177,16 +1176,16 @@ MessageQueue *MovGraph::fillMGMinfo(StaticANIObject *ani, MovArr *movarr, int st
if (i == movarr->_movStepCount - 1) {
nx = movarr->_point.x;
ny = movarr->_point.y;
- nd = st->link->_movGraphNode1->_distance;
+ nd = st->link->_movGraphNode1->_z;
} else {
if (st->sfield_0) {
nx = st->link->_movGraphNode1->_x;
ny = st->link->_movGraphNode1->_y;
- nd = st->link->_movGraphNode1->_distance;
+ nd = st->link->_movGraphNode1->_z;
} else {
nx = st->link->_movGraphNode2->_x;
ny = st->link->_movGraphNode2->_y;
- nd = st->link->_movGraphNode2->_distance;
+ nd = st->link->_movGraphNode2->_z;
}
}
@@ -1294,14 +1293,14 @@ double MovGraph::calcDistance(Common::Point *point, MovGraphLink *link, int fuzz
double dist2x = (double)(n2x - n1x);
double dist2y = (double)(n2y - n1y);
double dist1 = sqrt(dist1y * dist1y + dist1x * dist1x);
- double dist2 = ((double)(n1y - n2y) * dist1y + dist2x * dist1x) / link->_distance / dist1;
+ double dist2 = ((double)(n1y - n2y) * dist1y + dist2x * dist1x) / link->_z / dist1;
double distm = dist2 * dist1;
double res = sqrt(1.0 - dist2 * dist2) * dist1;
- if (dist2 <= 0.0 || distm >= link->_distance) {
+ if (dist2 <= 0.0 || distm >= link->_z) {
if (fuzzyMatch) {
if (dist2 > 0.0) {
- if (distm >= link->_distance) {
+ if (distm >= link->_z) {
point->x = n2x;
point->y = n2y;
}
@@ -1313,14 +1312,14 @@ double MovGraph::calcDistance(Common::Point *point, MovGraphLink *link, int fuzz
return -1.0;
}
} else {
- point->x = (int)(n1x + (dist2x * distm / link->_distance));
- point->y = (int)(n1y + (dist2y * distm / link->_distance));
+ point->x = (int)(n1x + (dist2x * distm / link->_z));
+ point->y = (int)(n1y + (dist2y * distm / link->_z));
}
return res;
}
-void MovGraph::calcNodeDistancesAndAngles() {
+void MovGraph::recalcLinkParams() {
for (ObList::iterator i = _links.begin(); i != _links.end(); ++i) {
assert(((CObject *)*i)->_objtype == kObjTypeMovGraphLink);
@@ -1328,11 +1327,11 @@ void MovGraph::calcNodeDistancesAndAngles() {
lnk->_flags &= 0x7FFFFFFF;
- lnk->calcNodeDistanceAndAngle();
+ lnk->recalcLength();
}
}
-bool MovGraph::findClosestLink(int unusedArg, Common::Point *p, MovArr *movarr) {
+bool MovGraph::getNearestPoint(int unusedArg, Common::Point *p, MovArr *movarr) {
MovGraphLink *link = 0;
double mindist = 1.0e20;
int resx = 0, resy = 0;
@@ -1348,7 +1347,7 @@ bool MovGraph::findClosestLink(int unusedArg, Common::Point *p, MovArr *movarr)
double dx3 = lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x;
double dy3 = lnk->_movGraphNode2->_y - lnk->_movGraphNode1->_y;
double sq1 = sqrt(dy1 * dy1 + dx1 * dx1);
- double sdist = (dy3 * dy1 + dx3 * dx1) / lnk->_distance / sq1;
+ double sdist = (dy3 * dy1 + dx3 * dx1) / lnk->_z / sq1;
double ldist = sdist * sq1;
double dist = sqrt(1.0 - sdist * sdist) * sq1;
@@ -1357,14 +1356,14 @@ bool MovGraph::findClosestLink(int unusedArg, Common::Point *p, MovArr *movarr)
dist = sqrt(dx1 * dx1 + dy1 * dy1);
}
- if (ldist > lnk->_distance) {
- ldist = lnk->_distance;
+ if (ldist > lnk->_z) {
+ ldist = lnk->_z;
dist = sqrt(dx2 * dx2 + dy2 * dy2);
}
- if (ldist >= 0.0 && ldist <= lnk->_distance && dist < mindist) {
- resx = lnk->_movGraphNode1->_x + (int)(dx3 * ldist / lnk->_distance);
- resy = lnk->_movGraphNode1->_y + (int)(dy3 * ldist / lnk->_distance);
+ if (ldist >= 0.0 && ldist <= lnk->_z && dist < mindist) {
+ resx = lnk->_movGraphNode1->_x + (int)(dx3 * ldist / lnk->_z);
+ resy = lnk->_movGraphNode1->_y + (int)(dy3 * ldist / lnk->_z);
mindist = dist;
link = lnk;
@@ -1387,7 +1386,7 @@ bool MovGraph::findClosestLink(int unusedArg, Common::Point *p, MovArr *movarr)
return false;
}
-int MovGraph::getItemIndexByStaticAni(StaticANIObject *ani) {
+int MovGraph::getObjectIndex(StaticANIObject *ani) {
for (uint i = 0; i < _items.size(); i++)
if (_items[i]->ani == ani)
return i;
@@ -1418,7 +1417,7 @@ Common::Array<MovArr *> *MovGraph::genMovArr(int x, int y, int *arrSize, int fla
movarr->_link = lnk;
movarr->_dist = ((double)(lnk->_movGraphNode1->_y - lnk->_movGraphNode2->_y) * (double)(lnk->_movGraphNode1->_y - point.y) +
(double)(lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x) * (double)(point.x - lnk->_movGraphNode1->_x)) /
- lnk->_distance / lnk->_distance;
+ lnk->_z / lnk->_z;
movarr->_point = point;
arr->push_back(movarr);
@@ -1447,7 +1446,7 @@ Common::Array<MovArr *> *MovGraph::genMovArr(int x, int y, int *arrSize, int fla
movarr->_link = lnk;
movarr->_dist = ((double)(lnk->_movGraphNode1->_y - lnk->_movGraphNode2->_y) * (double)(lnk->_movGraphNode1->_y - y) +
(double)(lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x) * (double)(x - lnk->_movGraphNode1->_x)) /
- lnk->_distance / lnk->_distance;
+ lnk->_z / lnk->_z;
movarr->_point.x = x;
movarr->_point.y = y;
@@ -1548,7 +1547,7 @@ bool MovGraph::calcChunk(int idx, int x, int y, MovArr *arr, int a6) {
Common::Array<MovArr *> *movarr = genMovArr(x, y, &arrSize, 0, 1);
if (!movarr)
- return findClosestLink(idx, 0, arr);
+ return getNearestPoint(idx, 0, arr);
bool res = false;
@@ -1777,8 +1776,8 @@ bool MovGraph2::initDirections(StaticANIObject *obj, MovGraph2Item *item) {
return true;
}
-void MovGraph2::addObject(StaticANIObject *obj) {
- MovGraph::addObject(obj);
+void MovGraph2::attachObject(StaticANIObject *obj) {
+ MovGraph::attachObject(obj);
int id = getItemIndexByGameObjectId(obj->_id);
@@ -2031,20 +2030,20 @@ MessageQueue *MovGraph2::buildMovInfo1MessageQueue(MovInfo1 *movInfo) {
return mq;
}
-int MovGraph2::removeObject(StaticANIObject *obj) {
- warning("STUB: MovGraph2::removeObject()");
+int MovGraph2::detachObject(StaticANIObject *obj) {
+ warning("STUB: MovGraph2::detachObject()");
return 0;
}
-void MovGraph2::freeItems() {
+void MovGraph2::detachAllObjects() {
for (uint i = 0; i < _items2.size(); i++)
delete _items2[i];
_items2.clear();
}
-MessageQueue *MovGraph2::method34(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) {
+MessageQueue *MovGraph2::startMove(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) {
if (!ani->isIdle())
return 0;
@@ -2240,9 +2239,9 @@ MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int
int dx2, dy2;
if (linkInfoSource.node)
- movInfo1.distance1 = linkInfoSource.node->_distance;
+ movInfo1.distance1 = linkInfoSource.node->_z;
else
- movInfo1.distance1 = linkInfoSource.link->_movGraphNode1->_distance;
+ movInfo1.distance1 = linkInfoSource.link->_movGraphNode1->_z;
if (linkInfoDest.node) {
dx2 = linkInfoDest.node->_x;
@@ -2251,16 +2250,16 @@ MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int
movInfo1.pt2.x = linkInfoDest.node->_x;
movInfo1.pt2.y = linkInfoDest.node->_y;
- movInfo1.distance2 = linkInfoDest.node->_distance;
+ movInfo1.distance2 = linkInfoDest.node->_z;
} else {
movInfo1.pt2.x = xpos;
movInfo1.pt2.y = ypos;
MovGraphNode *nod = linkInfoDest.link->_movGraphNode1;
double dst1 = sqrt((double)((ypos - nod->_y) * (ypos - nod->_y) + (xpos - nod->_x) * (xpos - nod->_x)));
- int dst = linkInfoDest.link->_movGraphNode2->_distance - nod->_distance;
+ int dst = linkInfoDest.link->_movGraphNode2->_z - nod->_z;
- movInfo1.distance2 = (int)(nod->_distance + (dst1 * (double)dst / linkInfoDest.link->_distance));
+ movInfo1.distance2 = (int)(nod->_z + (dst1 * (double)dst / linkInfoDest.link->_z));
calcDistance(&movInfo1.pt2, linkInfoDest.link, 1);
@@ -2397,8 +2396,8 @@ int MovGraph2::findLink(Common::Array<MovGraphLink *> *linkList, int idx, Common
rect->bottom = node2->_y;
}
if (point) {
- point->x = node3->_distance;
- point->y = node2->_distance;
+ point->x = node3->_z;
+ point->y = node2->_z;
}
if (abs(node3->_x - node2->_x) <= abs(node3->_y - node2->_y))
@@ -2659,7 +2658,7 @@ MovGraphLink *MovGraph2::findLink2(int x, int y) {
double n1dx = n1x - x;
double n1dy = n1y - y;
double dst1 = sqrt(n1dy * n1dy + n1dx * n1dx);
- double coeff1 = ((n1y - n2y) * n1dy + (n2x - n1x) * n1dx) / lnk->_distance / dst1;
+ double coeff1 = ((n1y - n2y) * n1dy + (n2x - n1x) * n1dx) / lnk->_z / dst1;
double dst3 = coeff1 * dst1;
double dst2 = sqrt(1.0 - coeff1 * coeff1) * dst1;
@@ -2667,11 +2666,11 @@ MovGraphLink *MovGraph2::findLink2(int x, int y) {
dst3 = 0.0;
dst2 = sqrt(n1dy * n1dy + n1dx * n1dx);
}
- if (dst3 > lnk->_distance) {
- dst3 = lnk->_distance;
+ if (dst3 > lnk->_z) {
+ dst3 = lnk->_z;
dst2 = sqrt((n2x - x) * (n2x - x) + (n2y - y) * (n2y - y));
}
- if (dst3 >= 0.0 && dst3 <= lnk->_distance && dst2 < mindist) {
+ if (dst3 >= 0.0 && dst3 <= lnk->_z && dst2 < mindist) {
mindist = dst2;
res = lnk;
}
@@ -2704,11 +2703,11 @@ double MovGraph2::findMinPath(LinkInfo *linkInfoSource, LinkInfo *linkInfoDest,
double newDistance = findMinPath(&linkInfoWorkSource, linkInfoDest, &tmpList);
- if (newDistance >= 0.0 && (minDistance < 0.0 || newDistance + lnk->_distance < minDistance)) {
+ if (newDistance >= 0.0 && (minDistance < 0.0 || newDistance + lnk->_z < minDistance)) {
listObj->clear();
listObj->push_back(tmpList);
- minDistance = newDistance + lnk->_distance;
+ minDistance = newDistance + lnk->_z;
}
lnk->_flags &= 0x7FFFFFFF;
@@ -2775,7 +2774,7 @@ MovGraphNode *MovGraph::calcOffset(int ox, int oy) {
}
MovGraphLink::MovGraphLink() {
- _distance = 0;
+ _z = 0;
_angle = 0;
_flags = 0x10000000;
_movGraphNode2 = 0;
@@ -2809,10 +2808,10 @@ bool MovGraphLink::load(MfcArchive &file) {
debug(8, "GraphNode2");
_movGraphNode2 = (MovGraphNode *)file.readClass();
- _distance = file.readDouble();
+ _z = file.readDouble();
_angle = file.readDouble();
- debug(8, "distance: %g, angle: %g", _distance, _angle);
+ debug(8, "distance: %g, angle: %g", _z, _angle);
_movGraphReact = (MovGraphReact *)file.readClass();
_name = file.readPascalString();
@@ -2820,12 +2819,12 @@ bool MovGraphLink::load(MfcArchive &file) {
return true;
}
-void MovGraphLink::calcNodeDistanceAndAngle() {
+void MovGraphLink::recalcLength() {
if (_movGraphNode1) {
double dx = _movGraphNode2->_x - _movGraphNode1->_x;
double dy = _movGraphNode2->_y - _movGraphNode1->_y;
- _distance = sqrt(dy * dy + dx * dx);
+ _z = sqrt(dy * dy + dx * dx);
_angle = atan2(dx, dy);
}
}
@@ -2836,7 +2835,7 @@ bool MovGraphNode::load(MfcArchive &file) {
_field_14 = file.readUint32LE();
_x = file.readUint32LE();
_y = file.readUint32LE();
- _distance = file.readUint32LE();
+ _z = file.readUint32LE();
return true;
}
@@ -3032,7 +3031,7 @@ int startWalkTo(int objId, int objKey, int x, int y, int fuzzyMatch) {
MctlCompound *mc = getCurrSceneSc2MotionController();
if (mc)
- return (mc->method34(g_fp->_currentScene->getStaticANIObject1ById(objId, objKey), x, y, fuzzyMatch, 0) != 0);
+ return (mc->startMove(g_fp->_currentScene->getStaticANIObject1ById(objId, objKey), x, y, fuzzyMatch, 0) != 0);
return 0;
}
@@ -3042,7 +3041,7 @@ bool doSomeAnimation(int objId, int objKey, int a3) {
MctlCompound *cmp = getCurrSceneSc2MotionController();
if (ani && cmp)
- return cmp->method3C(ani, a3);
+ return cmp->resetPosition(ani, a3);
return false;
}
diff --git a/engines/fullpipe/motion.h b/engines/fullpipe/motion.h
index c488039e22..a40d810ffa 100644
--- a/engines/fullpipe/motion.h
+++ b/engines/fullpipe/motion.h
@@ -48,19 +48,19 @@ public:
virtual bool load(MfcArchive &file);
virtual void methodC() {}
virtual void method10() {}
- virtual void clearEnabled() { _isEnabled = false; }
- virtual void setEnabled() { _isEnabled = true; }
- virtual void addObject(StaticANIObject *obj) {}
- virtual int removeObject(StaticANIObject *obj) { return 0; }
- virtual void freeItems() {}
- virtual Common::Array<MovItem *> *method28(StaticANIObject *ani, int x, int y, int flag1, int *rescount) { return 0; }
- virtual bool method2C(StaticANIObject *obj, int x, int y) { return false; }
+ virtual void deactivate() { _isEnabled = false; }
+ virtual void activate() { _isEnabled = true; }
+ virtual void attachObject(StaticANIObject *obj) {}
+ virtual int detachObject(StaticANIObject *obj) { return 0; }
+ virtual void detachAllObjects() {}
+ virtual Common::Array<MovItem *> *getPaths(StaticANIObject *ani, int x, int y, int flag1, int *rescount) { return 0; }
+ virtual bool setPosImmediate(StaticANIObject *obj, int x, int y) { return false; }
virtual int method30() { return 0; }
- virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { return 0; }
- virtual void changeCallback(MovArr *(*_callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter)) {}
- virtual bool method3C(StaticANIObject *ani, int flag) { return 0; }
+ virtual MessageQueue *startMove(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { return 0; }
+ virtual void setSelFunc(MovArr *(*_callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter)) {}
+ virtual bool resetPosition(StaticANIObject *ani, int flag) { return 0; }
virtual int method40() { return 0; }
- virtual bool method44(StaticANIObject *ani, int x, int y) { return false; }
+ virtual bool canDropInventory(StaticANIObject *ani, int x, int y) { return false; }
virtual int method48() { return -1; }
virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { return 0; }
@@ -82,7 +82,7 @@ public:
virtual bool pointInRegion(int x, int y);
};
-class MctlCompoundArrayItem : public CObject {
+class MctlItem : public CObject {
public:
MotionController *_motionControllerObj;
MovGraphReact *_movGraphReactObj;
@@ -92,11 +92,11 @@ public:
int _field_28;
public:
- MctlCompoundArrayItem() : _movGraphReactObj(0), _motionControllerObj(0), _field_20(0), _field_24(0), _field_28(0) {}
- ~MctlCompoundArrayItem();
+ MctlItem() : _movGraphReactObj(0), _motionControllerObj(0), _field_20(0), _field_24(0), _field_28(0) {}
+ ~MctlItem();
};
-class MctlCompoundArray : public Common::Array<MctlCompoundArrayItem *>, public CObject {
+class MctlCompoundArray : public Common::Array<MctlItem *>, public CObject {
public:
virtual bool load(MfcArchive &file);
};
@@ -109,10 +109,10 @@ public:
virtual bool load(MfcArchive &file);
- virtual void addObject(StaticANIObject *obj);
- virtual int removeObject(StaticANIObject *obj);
- virtual void freeItems();
- virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
+ virtual void attachObject(StaticANIObject *obj);
+ virtual int detachObject(StaticANIObject *obj);
+ virtual void detachAllObjects();
+ virtual MessageQueue *startMove(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
void initMovGraph2();
@@ -156,10 +156,10 @@ public:
virtual ~MctlLadder();
int collisionDetection(StaticANIObject *man);
- virtual void addObject(StaticANIObject *obj);
- virtual int removeObject(StaticANIObject *obj) { return 1; }
- virtual void freeItems();
- virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
+ virtual void attachObject(StaticANIObject *obj);
+ virtual int detachObject(StaticANIObject *obj) { return 1; }
+ virtual void detachAllObjects();
+ virtual MessageQueue *startMove(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
MessageQueue *controllerWalkTo(StaticANIObject *ani, int off);
@@ -173,12 +173,12 @@ class MovGraphNode : public CObject {
public:
int _x;
int _y;
- int _distance;
+ int _z;
int16 _field_10;
int _field_14;
public:
- MovGraphNode() : _x(0), _y(0), _distance(0), _field_10(0), _field_14(0) { _objtype = kObjTypeMovGraphNode; }
+ MovGraphNode() : _x(0), _y(0), _z(0), _field_10(0), _field_14(0) { _objtype = kObjTypeMovGraphNode; }
virtual bool load(MfcArchive &file);
};
@@ -225,7 +225,7 @@ class MovGraphLink : public CObject {
int _flags;
int _field_38;
int _field_3C;
- double _distance;
+ double _z;
double _angle;
MovGraphReact *_movGraphReact;
char *_name;
@@ -236,7 +236,7 @@ class MovGraphLink : public CObject {
virtual bool load(MfcArchive &file);
- void calcNodeDistanceAndAngle();
+ void recalcLength();
};
struct MovStep {
@@ -290,23 +290,23 @@ public:
virtual bool load(MfcArchive &file);
- virtual void addObject(StaticANIObject *obj);
- virtual int removeObject(StaticANIObject *obj);
- virtual void freeItems();
- virtual Common::Array<MovItem *> *method28(StaticANIObject *ani, int x, int y, int flag1, int *rescount);
- virtual bool method2C(StaticANIObject *obj, int x, int y);
- virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
- virtual void changeCallback(MovArr *(*_callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter));
- virtual bool method3C(StaticANIObject *ani, int flag);
- virtual bool method44(StaticANIObject *ani, int x, int y);
+ virtual void attachObject(StaticANIObject *obj);
+ virtual int detachObject(StaticANIObject *obj);
+ virtual void detachAllObjects();
+ virtual Common::Array<MovItem *> *getPaths(StaticANIObject *ani, int x, int y, int flag1, int *rescount);
+ virtual bool setPosImmediate(StaticANIObject *obj, int x, int y);
+ virtual MessageQueue *startMove(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
+ virtual void setSelFunc(MovArr *(*_callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter));
+ virtual bool resetPosition(StaticANIObject *ani, int flag);
+ virtual bool canDropInventory(StaticANIObject *ani, int x, int y);
virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
virtual MessageQueue *method50(StaticANIObject *ani, MovArr *movarr, int staticsId);
double calcDistance(Common::Point *point, MovGraphLink *link, int fuzzyMatch);
- void calcNodeDistancesAndAngles();
- bool findClosestLink(int unusedArg, Common::Point *p, MovArr *movarr);
+ void recalcLinkParams();
+ bool getNearestPoint(int unusedArg, Common::Point *p, MovArr *movarr);
MovGraphNode *calcOffset(int ox, int oy);
- int getItemIndexByStaticAni(StaticANIObject *ani);
+ int getObjectIndex(StaticANIObject *ani);
Common::Array<MovArr *> *genMovArr(int x, int y, int *arrSize, int flag1, int flag2);
void findAllPaths(MovGraphLink *lnk, MovGraphLink *lnk2, Common::Array<MovGraphLink *> &tempObList1, Common::Array<MovGraphLink *> &tempObList2);
Common::Array<MovItem *> *calcMovItems(MovArr *movarr1, MovArr *movarr2, int *listCount);
@@ -374,10 +374,10 @@ public:
Common::Array<MovGraph2Item *> _items2;
public:
- virtual void addObject(StaticANIObject *obj);
- virtual int removeObject(StaticANIObject *obj);
- virtual void freeItems();
- virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
+ virtual void attachObject(StaticANIObject *obj);
+ virtual int detachObject(StaticANIObject *obj);
+ virtual void detachAllObjects();
+ virtual MessageQueue *startMove(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId);
int getItemIndexByGameObjectId(int objectId);
@@ -404,10 +404,9 @@ class MctlConnectionPoint : public CObject {
public:
int _connectionX;
int _connectionY;
- int _field_C;
- int _field_10;
- int16 _field_14;
- int16 _field_16;
+ int _mctlflags;
+ int _mctlstatic;
+ int16 _mctlmirror;
MessageQueue *_messageQueueObj;
int _motionControllerObj;
diff --git a/engines/fullpipe/scenes.cpp b/engines/fullpipe/scenes.cpp
index 13c653ad09..32aa955a61 100644
--- a/engines/fullpipe/scenes.cpp
+++ b/engines/fullpipe/scenes.cpp
@@ -583,8 +583,8 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) {
_aniMan2 = _aniMan;
MctlCompound *cmp = getSc2MctlCompoundBySceneId(entrance->_sceneId);
cmp->initMovGraph2();
- cmp->addObject(_aniMan);
- cmp->setEnabled();
+ cmp->attachObject(_aniMan);
+ cmp->activate();
getGameLoaderInteractionController()->enableFlag24();
setInputDisabled(0);
diff --git a/engines/fullpipe/scenes/scene04.cpp b/engines/fullpipe/scenes/scene04.cpp
index 4a87ae5b87..c0f0960aba 100644
--- a/engines/fullpipe/scenes/scene04.cpp
+++ b/engines/fullpipe/scenes/scene04.cpp
@@ -275,7 +275,7 @@ void sceneHandler04_clickButton() {
}
void sceneHandler04_downLadder(int x, int y) {
- g_vars->scene04_ladder->method34(g_fp->_aniMan, x + g_vars->scene04_ladder->_ladder_field_20, y + g_vars->scene04_ladder->_ladder_field_24, 0, 0);
+ g_vars->scene04_ladder->startMove(g_fp->_aniMan, x + g_vars->scene04_ladder->_ladder_field_20, y + g_vars->scene04_ladder->_ladder_field_24, 0, 0);
}
void sceneHandler04_walkClimbLadder(ExCommand *ex) {
@@ -321,7 +321,7 @@ void sceneHandler04_walkClimbLadder(ExCommand *ex) {
g_vars->scene04_ladder->_ladder_field_20 = 0;
g_vars->scene04_ladder->_ladder_field_24 = -60;
- g_vars->scene04_ladder->addObject(g_fp->_aniMan);
+ g_vars->scene04_ladder->attachObject(g_fp->_aniMan);
if (g_vars->scene04_soundPlaying) {
g_vars->scene04_ladder->_ladmovements.front()->movVars->varUpStart = MV_MAN_STARTLADDER2;
@@ -337,7 +337,7 @@ void sceneHandler04_walkClimbLadder(ExCommand *ex) {
g_fp->_aniMan->_priority = 12;
- getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId)->clearEnabled();
+ getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId)->deactivate();
getGameLoaderInteractionController()->disableFlag24();
}
@@ -368,7 +368,7 @@ void sceneHandler04_clickLadder() {
} else {
if (g_fp->_aniMan->isIdle() && !(g_fp->_aniMan->_flags & 0x100)) {
if (abs(1095 - g_vars->scene04_dudePosX) > 1 || abs(434 - g_vars->scene04_dudePosY) > 1) {
- MessageQueue *mq = getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId)->method34(g_fp->_aniMan, 1095, 434, 1, ST_MAN_UP);
+ MessageQueue *mq = getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId)->startMove(g_fp->_aniMan, 1095, 434, 1, ST_MAN_UP);
if (mq) {
ExCommand *ex = new ExCommand(0, 17, MSG_SC4_CLICKLADDER, 0, 0, 0, 1, 0, 0, 0);
@@ -533,7 +533,7 @@ void sceneHandler04_manFromBottle() {
g_vars->scene04_ladder = 0;
- getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId)->setEnabled();
+ getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId)->activate();
getGameLoaderInteractionController()->enableFlag24();
}
@@ -1120,7 +1120,7 @@ void sceneHandler04_leaveLadder(ExCommand *ex) {
ex->_messageKind = 0;
- mc->setEnabled();
+ mc->activate();
getGameLoaderInteractionController()->enableFlag24();
} else {
delete mq;
@@ -1275,7 +1275,7 @@ void sceneHandler04_winArcade() {
g_vars->scene04_objectIsTaken = false;
g_vars->scene04_soundPlaying = false;
- getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId)->setEnabled();
+ getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId)->activate();
getGameLoaderInteractionController()->enableFlag24();
diff --git a/engines/fullpipe/scenes/scene06.cpp b/engines/fullpipe/scenes/scene06.cpp
index 06ec20dcb5..e9cecc42f0 100644
--- a/engines/fullpipe/scenes/scene06.cpp
+++ b/engines/fullpipe/scenes/scene06.cpp
@@ -118,7 +118,7 @@ void sceneHandler06_winArcade() {
sceneHandler06_setExits(g_fp->_currentScene);
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
getGameLoaderInteractionController()->enableFlag24();
}
@@ -300,7 +300,7 @@ void sceneHandler06_startAiming() {
if (getCurrSceneSc2MotionController()->_isEnabled)
g_fp->_updateScreenCallback = sceneHandler06_updateScreenCallback;
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
getGameLoaderInteractionController()->disableFlag24();
g_vars->scene06_ballDrop->queueMessageQueue(0);
@@ -313,7 +313,7 @@ void sceneHandler06_takeBall() {
|| abs(452 - g_fp->_aniMan->_oy) > 1
|| g_fp->_aniMan->_movement
|| g_fp->_aniMan->_statics->_staticsId != (0x4000 | ST_MAN_RIGHT)) {
- MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, 1158, 452, 1, (0x4000 | ST_MAN_RIGHT));
+ MessageQueue *mq = getCurrSceneSc2MotionController()->startMove(g_fp->_aniMan, 1158, 452, 1, (0x4000 | ST_MAN_RIGHT));
if (mq) {
ExCommand *ex = new ExCommand(0, 17, MSG_SC6_TAKEBALL, 0, 0, 0, 1, 0, 0, 0);
@@ -562,7 +562,7 @@ int sceneHandler06(ExCommand *ex) {
case MSG_SC6_RESTORESCROLL:
g_fp->_aniMan2 = g_fp->_aniMan;
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
getGameLoaderInteractionController()->enableFlag24();
sceneHandler06_setExits(g_fp->_currentScene);
break;
diff --git a/engines/fullpipe/scenes/scene08.cpp b/engines/fullpipe/scenes/scene08.cpp
index a5f5a8b389..d64df8688e 100644
--- a/engines/fullpipe/scenes/scene08.cpp
+++ b/engines/fullpipe/scenes/scene08.cpp
@@ -224,7 +224,7 @@ void sceneHandler08_startArcade() {
g_vars->scene08_onBelly = false;
getGameLoaderInteractionController()->disableFlag24();
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
g_vars->scene08_batuta->stopAnim_maybe();
@@ -276,7 +276,7 @@ void sceneHandler08_finishArcade() {
g_vars->scene08_inArcade = false;
getGameLoaderInteractionController()->enableFlag24();
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
}
void sceneHandler08_jumpOff(ExCommand *cmd) {
diff --git a/engines/fullpipe/scenes/scene09.cpp b/engines/fullpipe/scenes/scene09.cpp
index 99cf0b20fd..ffe8a1b2de 100644
--- a/engines/fullpipe/scenes/scene09.cpp
+++ b/engines/fullpipe/scenes/scene09.cpp
@@ -271,7 +271,7 @@ void sceneHandler09_spitterClick() {
g_vars->scene09_spitter->setPicAniInfo(&info);
if (ABS(x - g_fp->_aniMan->_ox) > 1 || ABS(y - g_fp->_aniMan->_oy) > 1) {
- MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, x, y, 1, ST_MAN_UP);
+ MessageQueue *mq = getCurrSceneSc2MotionController()->startMove(g_fp->_aniMan, x, y, 1, ST_MAN_UP);
if (mq) {
ExCommand *ex = new ExCommand(0, 17, MSG_SC9_PLVCLICK, 0, 0, 0, 1, 0, 0, 0);
@@ -602,14 +602,14 @@ int sceneHandler09(ExCommand *cmd) {
break;
case MSG_SC9_FROMLADDER:
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
getGameLoaderInteractionController()->enableFlag24();
g_vars->scene09_dudeIsOnLadder = false;
break;
case MSG_SC9_TOLADDER:
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
getGameLoaderInteractionController()->disableFlag24();
g_vars->scene09_dudeIsOnLadder = true;
diff --git a/engines/fullpipe/scenes/scene10.cpp b/engines/fullpipe/scenes/scene10.cpp
index 8c9e0b67d0..3e2a918b64 100644
--- a/engines/fullpipe/scenes/scene10.cpp
+++ b/engines/fullpipe/scenes/scene10.cpp
@@ -82,7 +82,7 @@ void sceneHandler10_clickGum() {
int y = g_vars->scene10_gum->_oy - 48;
if (abs(x - g_fp->_aniMan->_ox) > 1 || abs(y - g_fp->_aniMan->_oy) > 1) {
- MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, x, y, 1, ST_MAN_RIGHT);
+ MessageQueue *mq = getCurrSceneSc2MotionController()->startMove(g_fp->_aniMan, x, y, 1, ST_MAN_RIGHT);
if (mq) {
ExCommand *ex = new ExCommand(0, 17, MSG_SC10_CLICKGUM, 0, 0, 0, 1, 0, 0, 0);
ex->_excFlags = 2;
diff --git a/engines/fullpipe/scenes/scene11.cpp b/engines/fullpipe/scenes/scene11.cpp
index 0ce82f5d5f..1fa5cabc15 100644
--- a/engines/fullpipe/scenes/scene11.cpp
+++ b/engines/fullpipe/scenes/scene11.cpp
@@ -191,7 +191,7 @@ void sceneHandler11_restartMan() {
chainObjQueue(0, QU_SC11_RESTARTMAN, 1);
getGameLoaderInteractionController()->enableFlag24();
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
g_vars->scene11_scrollIsEnabled = false;
}
@@ -234,7 +234,7 @@ int sceneHandler11_updateScreenCallback() {
void sceneHandler11_manToSwing() {
g_vars->scene11_arcadeIsOn = true;
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
getGameLoaderInteractionController()->disableFlag24();
g_fp->_aniMan2->hide();
@@ -271,7 +271,7 @@ void sceneHandler11_putABoot() {
void sceneHandler11_putBoot() {
if (abs(353 - g_fp->_aniMan->_ox) > 1 || abs(498 - g_fp->_aniMan->_oy) > 1
|| g_fp->_aniMan->_movement || g_fp->_aniMan->_statics->_staticsId != ST_MAN_RIGHT) {
- MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, 353, 498, 1, ST_MAN_RIGHT);
+ MessageQueue *mq = getCurrSceneSc2MotionController()->startMove(g_fp->_aniMan, 353, 498, 1, ST_MAN_RIGHT);
if (mq) {
ExCommand *ex = new ExCommand(0, 17, MSG_SC11_PUTBOOT, 0, 0, 0, 1, 0, 0, 0);
@@ -299,7 +299,7 @@ void sceneHandler11_jumpFromSwing() {
g_vars->scene11_hint->_flags &= 0xFFFB;
g_vars->scene11_scrollIsEnabled = false;
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
getGameLoaderInteractionController()->enableFlag24();
g_vars->scene11_swingOldAngle = 0.0;
diff --git a/engines/fullpipe/scenes/scene14.cpp b/engines/fullpipe/scenes/scene14.cpp
index 446f477133..dc919c6d7f 100644
--- a/engines/fullpipe/scenes/scene14.cpp
+++ b/engines/fullpipe/scenes/scene14.cpp
@@ -174,7 +174,7 @@ void sceneHandler14_exitScene() {
chainQueue(QU_SC14_ENDARCADE, 0);
getGameLoaderInteractionController()->disableFlag24();
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
}
void sceneHandler14_showBallMan() {
@@ -284,7 +284,7 @@ void sceneHandler14_endArcade() {
setInputDisabled(0);
getGameLoaderInteractionController()->enableFlag24();
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
BehaviorEntryInfo *beh = g_fp->_behaviorManager->getBehaviorEntryInfoByMessageQueueDataId(g_vars->scene14_grandma, ST_GMA_SIT, QU_GMA_BLINK);
if (beh)
@@ -365,7 +365,7 @@ void sceneHandler14_startArcade() {
g_fp->_aniMan->_priority = 25;
}
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
getGameLoaderInteractionController()->disableFlag24();
g_fp->_aniMan2 = 0;
@@ -458,7 +458,7 @@ bool sceneHandler14_arcadeProcessClick(ExCommand *cmd) {
if (cmd->_sceneClickX > 1237)
return false;
- MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, 1237, 451, 1, 0);
+ MessageQueue *mq = getCurrSceneSc2MotionController()->startMove(g_fp->_aniMan, 1237, 451, 1, 0);
if (!mq)
return false;
@@ -473,7 +473,7 @@ bool sceneHandler14_arcadeProcessClick(ExCommand *cmd) {
cmd->_messageKind = 0;
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
getGameLoaderInteractionController()->disableFlag24();
return true;
}
diff --git a/engines/fullpipe/scenes/scene16.cpp b/engines/fullpipe/scenes/scene16.cpp
index df005950d2..5079863b4e 100644
--- a/engines/fullpipe/scenes/scene16.cpp
+++ b/engines/fullpipe/scenes/scene16.cpp
@@ -298,7 +298,7 @@ void sceneHandler16_drink() {
void sceneHandler16_mugClick() {
if (abs(310 - g_fp->_aniMan->_ox) >= 1 || abs(449 - g_fp->_aniMan->_oy) >= 1
|| g_fp->_aniMan->_movement || g_fp->_aniMan->_statics->_staticsId != ST_MAN_RIGHT) {
- MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, 310, 449, 1, ST_MAN_RIGHT);
+ MessageQueue *mq = getCurrSceneSc2MotionController()->startMove(g_fp->_aniMan, 310, 449, 1, ST_MAN_RIGHT);
if (mq) {
ExCommand *ex = new ExCommand(0, 17, MSG_SC16_MUGCLICK, 0, 0, 0, 1, 0, 0, 0);
diff --git a/engines/fullpipe/scenes/scene18and19.cpp b/engines/fullpipe/scenes/scene18and19.cpp
index 4f6677876b..5af7ef9043 100644
--- a/engines/fullpipe/scenes/scene18and19.cpp
+++ b/engines/fullpipe/scenes/scene18and19.cpp
@@ -379,7 +379,7 @@ int scene19_updateCursor() {
void sceneHandler18_clickBoard() {
if (ABS(967 - g_fp->_aniMan->_ox) > 1 || ABS(379 - g_fp->_aniMan->_oy) > 1 || g_fp->_aniMan->_statics->_staticsId != ST_MAN_RIGHT) {
- MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, 967, 379, 1, ST_MAN_RIGHT);
+ MessageQueue *mq = getCurrSceneSc2MotionController()->startMove(g_fp->_aniMan, 967, 379, 1, ST_MAN_RIGHT);
ExCommand *ex = new ExCommand(0, 17, MSG_SC18_MANREADY, 0, 0, 0, 1, 0, 0, 0);
ex->_excFlags = 2;
diff --git a/engines/fullpipe/scenes/scene22.cpp b/engines/fullpipe/scenes/scene22.cpp
index 542834b51a..f51469da69 100644
--- a/engines/fullpipe/scenes/scene22.cpp
+++ b/engines/fullpipe/scenes/scene22.cpp
@@ -191,7 +191,7 @@ void sceneHandler22_stoolLogic(ExCommand *cmd) {
xpos = 841;
manId = ST_MAN_RIGHT;
LABEL_31:
- mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, xpos, 449, 1, manId);
+ mq = getCurrSceneSc2MotionController()->startMove(g_fp->_aniMan, xpos, 449, 1, manId);
if (!mq)
return;
@@ -278,7 +278,7 @@ void sceneHandler22_stoolLogic(ExCommand *cmd) {
}
}
- mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, 1010, 443, 1, ST_MAN_UP);
+ mq = getCurrSceneSc2MotionController()->startMove(g_fp->_aniMan, 1010, 443, 1, ST_MAN_UP);
if (mq) {
mq->addExCommandToEnd(cmd->createClone());
@@ -318,13 +318,13 @@ int sceneHandler22(ExCommand *cmd) {
g_vars->scene22_dudeIsOnStool = false;
g_vars->scene22_interactionIsDisabled = false;
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 1);
break;
case MSG_SC22_ONSTOOL:
g_vars->scene22_dudeIsOnStool = true;
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 0);
break;
diff --git a/engines/fullpipe/scenes/scene23.cpp b/engines/fullpipe/scenes/scene23.cpp
index ded467e438..d6075c271b 100644
--- a/engines/fullpipe/scenes/scene23.cpp
+++ b/engines/fullpipe/scenes/scene23.cpp
@@ -296,7 +296,7 @@ void sceneHandler23_pushButton(ExCommand *cmd) {
if (g_fp->_msgX == 276 && g_fp->_msgY == 438 )
return;
- MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, 276, 438, 1, ST_MAN_RIGHT);
+ MessageQueue *mq = getCurrSceneSc2MotionController()->startMove(g_fp->_aniMan, 276, 438, 1, ST_MAN_RIGHT);
if (mq) {
mq->addExCommandToEnd(cmd->createClone());
@@ -424,7 +424,7 @@ int sceneHandler23(ExCommand *cmd) {
case MSG_SC23_FROMSTOOL:
g_vars->scene23_isOnStool = false;
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
getGameLoaderInteractionController()->enableFlag24();
g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 1);
@@ -438,7 +438,7 @@ int sceneHandler23(ExCommand *cmd) {
case MSG_SC23_ONSTOOL:
g_vars->scene23_isOnStool = true;
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
getGameLoaderInteractionController()->disableFlag24();
g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 0);
diff --git a/engines/fullpipe/scenes/scene25.cpp b/engines/fullpipe/scenes/scene25.cpp
index a07330f057..07eda73cf2 100644
--- a/engines/fullpipe/scenes/scene25.cpp
+++ b/engines/fullpipe/scenes/scene25.cpp
@@ -153,7 +153,7 @@ void sceneHandler25_enterMan() {
if (g_vars->scene25_waterIsPresent) {
chainQueue(QU_SC25_ENTERUP_WATER, 1);
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
} else {
chainQueue(QU_SC25_ENTERUP_FLOOR, 1);
}
diff --git a/engines/fullpipe/scenes/scene26.cpp b/engines/fullpipe/scenes/scene26.cpp
index b9d9161e7d..baed928d00 100644
--- a/engines/fullpipe/scenes/scene26.cpp
+++ b/engines/fullpipe/scenes/scene26.cpp
@@ -257,7 +257,7 @@ void sceneHandler26_clickVent(StaticANIObject *ani, ExCommand *cmd) {
int y = ani->_oy + 61;
if (abs(x - g_fp->_aniMan->_ox) > 1 || abs(y - g_fp->_aniMan->_oy) > 1 || g_fp->_aniMan->_movement || g_fp->_aniMan->_statics->_staticsId != ST_MAN_UP) {
- MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, x, y, 1, ST_MAN_UP);
+ MessageQueue *mq = getCurrSceneSc2MotionController()->startMove(g_fp->_aniMan, x, y, 1, ST_MAN_UP);
if (mq) {
ExCommand *ex = new ExCommand(0, 17, MSG_SC26_CLICKVENT, 0, 0, 0, 1, 0, 0, 0);
diff --git a/engines/fullpipe/scenes/scene27.cpp b/engines/fullpipe/scenes/scene27.cpp
index 8ec05caaff..9570d30913 100644
--- a/engines/fullpipe/scenes/scene27.cpp
+++ b/engines/fullpipe/scenes/scene27.cpp
@@ -159,7 +159,7 @@ void sceneHandler27_driverGiveVent() {
g_vars->scene27_driverHasVent = false;
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
getGameLoaderInteractionController()->enableFlag24();
g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 1);
@@ -226,7 +226,7 @@ void sceneHandler27_throwBat() {
g_fp->_aniMan->startAnim(MV_MAN27_THROWBET, 0, -1);
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
getGameLoaderInteractionController()->disableFlag24();
g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 0);
@@ -247,7 +247,7 @@ void sceneHandler27_clickBat(ExCommand *cmd) {
if (ABS(bx - g_fp->_aniMan->_ox) > 1 || ABS(by - g_fp->_aniMan->_oy) > 1
|| g_fp->_aniMan->_movement || g_fp->_aniMan->_statics->_staticsId != ST_MAN_RIGHT) {
- MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, bx, by, 1, ST_MAN_RIGHT);
+ MessageQueue *mq = getCurrSceneSc2MotionController()->startMove(g_fp->_aniMan, bx, by, 1, ST_MAN_RIGHT);
if (mq) {
mq->addExCommandToEnd(cmd->createClone());
@@ -501,7 +501,7 @@ void sceneHandler27_batLogic() {
default:
chainQueue(QU_SC27_RESTARTBETS, 1);
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
getGameLoaderInteractionController()->enableFlag24();
g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 1);
diff --git a/engines/fullpipe/scenes/scene28.cpp b/engines/fullpipe/scenes/scene28.cpp
index de5a96e70d..75ba2567b2 100644
--- a/engines/fullpipe/scenes/scene28.cpp
+++ b/engines/fullpipe/scenes/scene28.cpp
@@ -258,7 +258,7 @@ void sceneHandler28_clickLift(int keycode) {
if (abs(x - g_fp->_aniMan->_ox) > 1 || abs(472 - g_fp->_aniMan->_oy) > 1
|| g_fp->_aniMan->_movement
|| g_fp->_aniMan->_statics->_staticsId != ST_MAN_UP) {
- MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, x, 472, 1, ST_MAN_UP);
+ MessageQueue *mq = getCurrSceneSc2MotionController()->startMove(g_fp->_aniMan, x, 472, 1, ST_MAN_UP);
if (mq) {
ExCommand *ex = new ExCommand(0, 17, MSG_SC28_CLICKLIFT, 0, 0, 0, 1, 0, 0, 0);
ex->_excFlags |= 3;
diff --git a/engines/fullpipe/scenes/scene29.cpp b/engines/fullpipe/scenes/scene29.cpp
index 222a541554..a03671a4d0 100644
--- a/engines/fullpipe/scenes/scene29.cpp
+++ b/engines/fullpipe/scenes/scene29.cpp
@@ -687,7 +687,7 @@ void sceneHandler29_ballHitCheck() {
void sceneHandler29_manFromL() {
if (g_vars->scene29_manX < 497 && !g_vars->scene29_scrollingDisabled) {
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
getGameLoaderInteractionController()->enableFlag24();
g_fp->_aniMan->changeStatics2(ST_MAN_RIGHT | 0x4000);
@@ -700,7 +700,7 @@ void sceneHandler29_manFromL() {
}
void sceneHandler29_manFromR() {
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
getGameLoaderInteractionController()->enableFlag24();
chainQueue(QU_SC29_MANFROM_R, 1);
@@ -721,7 +721,7 @@ int sceneHandler29_updateScreenCallback() {
}
void sceneHandler29_manToL() {
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
getGameLoaderInteractionController()->disableFlag24();
chainQueue(QU_SC29_MANTO_L, 1);
@@ -737,7 +737,7 @@ void sceneHandler29_manToL() {
}
void sceneHandler29_manToR() {
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
getGameLoaderInteractionController()->disableFlag24();
chainQueue(QU_SC29_MANTO_R, 1);
@@ -763,7 +763,7 @@ void sceneHandler29_clickPorter(ExCommand *cmd) {
if (ABS(351 - g_vars->scene29_manX) > 1 || ABS(443 - g_vars->scene29_manY) > 1
|| g_fp->_aniMan->_movement || g_fp->_aniMan->_statics->_staticsId != ST_MAN_RIGHT) {
if (g_fp->_msgX != 351 || g_fp->_msgY != 443) {
- MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, 351, 443, 1, ST_MAN_RIGHT);
+ MessageQueue *mq = getCurrSceneSc2MotionController()->startMove(g_fp->_aniMan, 351, 443, 1, ST_MAN_RIGHT);
if (mq) {
mq->addExCommandToEnd(cmd->createClone());
@@ -781,7 +781,7 @@ void sceneHandler29_clickPorter(ExCommand *cmd) {
if (ABS(1582 - g_vars->scene29_manX) > 1 || ABS(445 - g_fp->_aniMan->_oy) > 1
|| g_fp->_aniMan->_movement || g_fp->_aniMan->_statics->_staticsId != (0x4000 | ST_MAN_RIGHT)) {
if (g_fp->_msgX != 1582 || g_fp->_msgY != 445) {
- MessageQueue *mq = getCurrSceneSc2MotionController()->method34(g_fp->_aniMan, 1582, 445, 1, (0x4000 | ST_MAN_RIGHT));
+ MessageQueue *mq = getCurrSceneSc2MotionController()->startMove(g_fp->_aniMan, 1582, 445, 1, (0x4000 | ST_MAN_RIGHT));
if (mq) {
mq->addExCommandToEnd(cmd->createClone());
@@ -1001,7 +1001,7 @@ int sceneHandler29(ExCommand *cmd) {
g_vars->scene29_reachedFarRight = false;
g_vars->scene29_rideBackEnabled = false;
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
getGameLoaderInteractionController()->enableFlag24();
break;
diff --git a/engines/fullpipe/scenes/scene32.cpp b/engines/fullpipe/scenes/scene32.cpp
index 9279db7513..05b78efb3d 100644
--- a/engines/fullpipe/scenes/scene32.cpp
+++ b/engines/fullpipe/scenes/scene32.cpp
@@ -189,7 +189,7 @@ void sceneHandler32_trySit(ExCommand *cmd) {
g_vars->scene32_dudeIsSitting = true;
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
getGameLoaderInteractionController()->disableFlag24();
}
}
@@ -236,7 +236,7 @@ void sceneHandler32_ladderLogic(ExCommand *cmd) {
g_vars->scene32_dudeOnLadder = false;
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
getGameLoaderInteractionController()->enableFlag24();
}
@@ -258,7 +258,7 @@ void sceneHandler32_potLogic(ExCommand *cmd) {
mq->setFlags(mq->getFlags() | 1);
mq->chain(0);
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
getGameLoaderInteractionController()->enableFlag24();
g_vars->scene32_dudeIsSitting = false;
@@ -330,7 +330,7 @@ int sceneHandler32(ExCommand *cmd) {
case MSG_SC32_ONLADDER:
g_vars->scene32_dudeOnLadder = true;
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
getGameLoaderInteractionController()->disableFlag24();
break;
diff --git a/engines/fullpipe/scenes/scene34.cpp b/engines/fullpipe/scenes/scene34.cpp
index 1c8c8b4855..32fb192756 100644
--- a/engines/fullpipe/scenes/scene34.cpp
+++ b/engines/fullpipe/scenes/scene34.cpp
@@ -115,7 +115,7 @@ int scene34_updateCursor() {
}
void sceneHandler34_leaveBoard() {
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
getGameLoaderInteractionController()->enableFlag24();
g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 1);
@@ -124,7 +124,7 @@ void sceneHandler34_leaveBoard() {
}
void sceneHandler34_onBoard() {
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
getGameLoaderInteractionController()->disableFlag24();
g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 0);
@@ -149,7 +149,7 @@ void sceneHandler34_hideStool() {
}
void sceneHandler34_climb() {
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
getGameLoaderInteractionController()->disableFlag24();
g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 0);
@@ -287,7 +287,7 @@ void sceneHandler34_showStool() {
}
void sceneHandler34_unclimb() {
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
getGameLoaderInteractionController()->enableFlag24();
g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 1);
@@ -323,7 +323,7 @@ int sceneHandler34(ExCommand *cmd) {
case MSG_SC34_FROMCACTUS:
g_vars->scene34_dudeOnCactus = false;
- getCurrSceneSc2MotionController()->setEnabled();
+ getCurrSceneSc2MotionController()->activate();
getGameLoaderInteractionController()->enableFlag24();
g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 1);
@@ -381,7 +381,7 @@ int sceneHandler34(ExCommand *cmd) {
case MSG_SC34_ONCACTUS:
g_vars->scene34_dudeOnCactus = true;
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
getGameLoaderInteractionController()->disableFlag24();
g_fp->_behaviorManager->setFlagByStaticAniObject(g_fp->_aniMan, 0);
diff --git a/engines/fullpipe/scenes/sceneFinal.cpp b/engines/fullpipe/scenes/sceneFinal.cpp
index d0040463ef..8b3ecb1025 100644
--- a/engines/fullpipe/scenes/sceneFinal.cpp
+++ b/engines/fullpipe/scenes/sceneFinal.cpp
@@ -97,7 +97,7 @@ void sceneHandlerFinal_goto2() {
void sceneHandlerFinal_startFinal() {
g_vars->sceneFinal_var01 = 1;
- getCurrSceneSc2MotionController()->clearEnabled();
+ getCurrSceneSc2MotionController()->deactivate();
getGameLoaderInteractionController()->disableFlag24();
g_fp->_aniMan2 = 0;
diff --git a/engines/gob/sound/cdrom.cpp b/engines/gob/sound/cdrom.cpp
index eca6ca4c9e..b862ca96fb 100644
--- a/engines/gob/sound/cdrom.cpp
+++ b/engines/gob/sound/cdrom.cpp
@@ -91,7 +91,10 @@ void CDROM::startTrack(const char *trackName) {
return;
}
- Common::strlcpy(_curTrack, trackName, 16);
+ Common::String curTrack(trackName);
+ curTrack.toUppercase();
+
+ Common::strlcpy(_curTrack, curTrack.c_str(), 16);
stopPlaying();
_curTrackBuffer = matchPtr;
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index c00290b155..cf65e012c8 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -934,16 +934,18 @@ bool MusicPlayerIOS::load(uint32 fileref, bool loop) {
}
// Create the audio stream
- Audio::AudioStream *audStream = Audio::SeekableAudioStream::openStreamFile(info.filename);
+ Audio::SeekableAudioStream *seekStream = Audio::SeekableAudioStream::openStreamFile(info.filename);
- if (!audStream) {
+ if (!seekStream) {
warning("Could not play audio file '%s'", info.filename.c_str());
return false;
}
+ Audio::AudioStream *audStream = seekStream;
+
// Loop if requested
if (loop)
- audStream = Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audStream, 0);
+ audStream = Audio::makeLoopingAudioStream(seekStream, 0);
// MIDI player handles volume reset on load, IOS player doesn't - force update here
updateVolume();
diff --git a/engines/hopkins/computer.cpp b/engines/hopkins/computer.cpp
index 18b16cb4c8..16977e0cb8 100644
--- a/engines/hopkins/computer.cpp
+++ b/engines/hopkins/computer.cpp
@@ -325,13 +325,13 @@ static const char _spanishText[] =
"% **** ORDENADOR DEL FBI NUMERO 4985 **** ORDENADOR J.HOPKINS *****\n"
"% **** ORDENADOR DEL FBI NUMERO 4998 **** ORDENADOR S.COLLINS *****\n"
"% *** ORDENADOR DEL FBI NUMERO 4997 *** ORDENADOR DE ACCESO LIBRE ***\n"
-"% LA CONTRASE\0245A ES: ALLFREE\n"
-"% ESCRIBE CONTRASE\0245A ACTUAL\n"
+"% LA CONTRASE\xA5" "A ES: ALLFREE\n"
+"% ESCRIBE CONTRASE\xA5" "A ACTUAL\n"
"% **** ACCESO DENEGADO ****\n"
"% 1) *** JUEGO ***\n"
"% 0) SALIR DEL ORDENADOR\n"
-"% 2) CADAVER EXTRA\0245O\n"
-"% 3) CADAVER EXTRA\0245O\n"
+"% 2) CADAVER EXTRA\xA5" "O\n"
+"% 3) CADAVER EXTRA\xA5" "O\n"
"% 4) SENADOR FERGUSSON\n"
"% 5) MATAPERROS\n"
"% 2) CIENTIFICO SECUESTRADO.\n"
diff --git a/engines/kyra/sound_intern.h b/engines/kyra/sound_intern.h
index 007ca3d3f5..4b77bf1351 100644
--- a/engines/kyra/sound_intern.h
+++ b/engines/kyra/sound_intern.h
@@ -151,7 +151,7 @@ private:
uint8 *_sfxFileData;
uint8 _sfxChannel;
- TownsEuphonyDriver *_driver;
+ EuphonyPlayer *_player;
bool _cdaPlaying;
diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp
index 725dedae3f..65ab4f31ef 100644
--- a/engines/kyra/sound_towns.cpp
+++ b/engines/kyra/sound_towns.cpp
@@ -37,13 +37,13 @@ SoundTowns::SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer)
: Sound(vm, mixer), _lastTrack(-1), _musicTrackData(0), _sfxFileData(0), _cdaPlaying(0),
_sfxFileIndex((uint)-1), _musicFadeTable(0), _sfxWDTable(0), _sfxBTTable(0), _sfxChannel(0x46), _currentResourceSet(0) {
memset(&_resInfo, 0, sizeof(_resInfo));
- _driver = new TownsEuphonyDriver(_mixer);
+ _player = new EuphonyPlayer(_mixer);
}
SoundTowns::~SoundTowns() {
g_system->getAudioCDManager()->stop();
haltTrack();
- delete _driver;
+ delete _player;
delete[] _musicTrackData;
delete[] _sfxFileData;
for (int i = 0; i < 3; i++)
@@ -58,15 +58,15 @@ bool SoundTowns::init() {
_sfxBTTable = _vm->staticres()->loadRawData(k1TownsSFXbtTable, unused);
_musicTrackData = new uint8[50570];
- if (!_driver->init())
+ if (!_player->init())
return false;
if (!loadInstruments())
return false;
- _driver->intf()->callback(68);
- _driver->intf()->callback(70, 0x33);
- _driver->setOutputVolume(1, 118, 118);
+ /*_player->driver()->intf()->callback(68);
+ _player->driver()->intf()->callback(70, 0x33);*/
+ _player->driver()->setOutputVolume(1, 118, 118);
return true;
}
@@ -93,7 +93,7 @@ void SoundTowns::playTrack(uint8 track) {
beginFadeOut();
if (_musicEnabled == 2 && trackNum != -1) {
- _driver->setOutputVolume(1, 118, 118);
+ _player->driver()->setOutputVolume(1, 118, 118);
g_system->getAudioCDManager()->play(trackNum + 1, loop ? -1 : 1, 0, 0);
g_system->getAudioCDManager()->updateCD();
_cdaPlaying = true;
@@ -112,12 +112,12 @@ void SoundTowns::haltTrack() {
_cdaPlaying = false;
for (int i = 0; i < 6; i++)
- _driver->chanVolume(i, 0);
+ _player->driver()->channelVolume(i, 0);
for (int i = 0x40; i < 0x46; i++)
- _driver->chanVolume(i, 0);
+ _player->driver()->channelVolume(i, 0);
for (int i = 0; i < 32; i++)
- _driver->configChan_enable(i, 0);
- _driver->stopParser();
+ _player->configPart_enable(i, 0);
+ _player->stop();
}
void SoundTowns::initAudioResourceInfo(int set, void *info) {
@@ -179,11 +179,11 @@ void SoundTowns::playSoundEffect(uint8 track, uint8) {
if (offset == -1)
return;
- if (!_driver->soundEffectIsPlaying(_sfxChannel ^ 1)) {
+ if (!_player->driver()->soundEffectIsPlaying(_sfxChannel ^ 1)) {
_sfxChannel ^= 1;
- } else if (_driver->soundEffectIsPlaying(_sfxChannel)) {
+ } else if (_player->driver()->soundEffectIsPlaying(_sfxChannel)) {
_sfxChannel ^= 1;
- _driver->stopSoundEffect(_sfxChannel);
+ _player->driver()->stopSoundEffect(_sfxChannel);
}
uint32 *sfxHeader = (uint32 *)(fileBody + offset);
@@ -221,57 +221,57 @@ void SoundTowns::playSoundEffect(uint8 track, uint8) {
}
}
- _driver->chanVolume(_sfxChannel, 127);
- _driver->chanPanPos(_sfxChannel, 0x40);
- _driver->chanPitch(_sfxChannel, 0);
- _driver->playSoundEffect(_sfxChannel, note, 127, sfxPlaybackBuffer);
+ _player->driver()->channelVolume(_sfxChannel, 127);
+ _player->driver()->channelPan(_sfxChannel, 0x40);
+ _player->driver()->channelPitch(_sfxChannel, 0);
+ _player->driver()->playSoundEffect(_sfxChannel, note, 127, sfxPlaybackBuffer);
delete[] sfxPlaybackBuffer;
}
void SoundTowns::updateVolumeSettings() {
- if (!_driver)
+ if (!_player)
return;
bool mute = false;
- _driver->setSoundEffectVolume(ConfMan.getInt("sfx_volume"));
+ _player->driver()->setSoundEffectVolume(ConfMan.getInt("sfx_volume"));
if (ConfMan.hasKey("mute"))
mute = ConfMan.getBool("mute");
- _driver->setMusicVolume((mute ? 0 : ConfMan.getInt("music_volume")));
- _driver->setSoundEffectVolume((mute ? 0 : ConfMan.getInt("sfx_volume")));
+ _player->driver()->setMusicVolume((mute ? 0 : ConfMan.getInt("music_volume")));
+ _player->driver()->setSoundEffectVolume((mute ? 0 : ConfMan.getInt("sfx_volume")));
}
void SoundTowns::stopAllSoundEffects() {
- _driver->chanVolume(0x46, 0);
- _driver->chanVolume(0x47, 0);
- _driver->stopSoundEffect(0x46);
- _driver->stopSoundEffect(0x47);
+ _player->driver()->channelVolume(0x46, 0);
+ _player->driver()->channelVolume(0x47, 0);
+ _player->driver()->stopSoundEffect(0x46);
+ _player->driver()->stopSoundEffect(0x47);
_sfxChannel = 0x46;
}
void SoundTowns::beginFadeOut() {
if (_cdaPlaying) {
for (int i = 118; i > 103; i--) {
- _driver->setOutputVolume(1, i, i);
+ _player->driver()->setOutputVolume(1, i, i);
_vm->delay(2 * _vm->tickLength());
}
for (int i = 103; i > 83; i -= 2) {
- _driver->setOutputVolume(1, i, i);
+ _player->driver()->setOutputVolume(1, i, i);
_vm->delay(2 * _vm->tickLength());
}
for (int i = 83; i > 58; i -= 2) {
- _driver->setOutputVolume(1, i, i);
+ _player->driver()->setOutputVolume(1, i, i);
_vm->delay(_vm->tickLength());
}
for (int i = 58; i > 0; i--) {
- _driver->setOutputVolume(1, i, i);
+ _player->driver()->setOutputVolume(1, i, i);
_vm->delay(1);
}
- _driver->setOutputVolume(1, 0, 0);
+ _player->driver()->setOutputVolume(1, 0, 0);
} else {
if (_lastTrack == -1)
@@ -292,9 +292,9 @@ void SoundTowns::beginFadeOut() {
for (int i = 0; i < 12; i++) {
for (int ii = 0; ii < 6; ii++)
- _driver->chanVolume(ii, fadeVolCur[ii]);
+ _player->driver()->channelVolume(ii, fadeVolCur[ii]);
for (int ii = 0x40; ii < 0x46; ii++)
- _driver->chanVolume(ii, fadeVolCur[ii - 0x3A]);
+ _player->driver()->channelVolume(ii, fadeVolCur[ii - 0x3A]);
for (int ii = 0; ii < 6; ii++) {
fadeVolCur[ii] -= fadeVolStep[ii];
@@ -323,20 +323,20 @@ bool SoundTowns::loadInstruments() {
Screen::decodeFrame4(twm, _musicTrackData, 50570);
for (int i = 0; i < 128; i++)
- _driver->loadInstrument(0, i, &_musicTrackData[i * 48 + 8]);
+ _player->driver()->loadInstrument(0, i, &_musicTrackData[i * 48 + 8]);
Screen::decodeFrame4(twm + 3232, _musicTrackData, 50570);
for (int i = 0; i < 32; i++)
- _driver->loadInstrument(0x40, i, &_musicTrackData[i * 128 + 8]);
+ _player->driver()->loadInstrument(0x40, i, &_musicTrackData[i * 128 + 8]);
- _driver->unloadWaveTable(-1);
+ _player->driver()->unloadWaveTable(-1);
uint8 *src = &_musicTrackData[32 * 128 + 8];
for (int i = 0; i < 10; i++) {
- _driver->loadWaveTable(src);
+ _player->driver()->loadWaveTable(src);
src = src + READ_LE_UINT16(&src[12]) + 32;
}
- _driver->reserveSoundEffectChannels(2);
+ _player->driver()->reserveSoundEffectChannels(2);
delete[] twm;
@@ -350,26 +350,26 @@ void SoundTowns::playEuphonyTrack(uint32 offset, int loop) {
const uint8 *src = _musicTrackData + 852;
for (int i = 0; i < 32; i++)
- _driver->configChan_enable(i, *src++);
+ _player->configPart_enable(i, *src++);
for (int i = 0; i < 32; i++)
- _driver->configChan_setMode(i, *src++);
+ _player->configPart_setType(i, *src++);
for (int i = 0; i < 32; i++)
- _driver->configChan_remap(i, *src++);
+ _player->configPart_remap(i, *src++);
for (int i = 0; i < 32; i++)
- _driver->configChan_adjustVolume(i, *src++);
+ _player->configPart_adjustVolume(i, *src++);
for (int i = 0; i < 32; i++)
- _driver->configChan_setTranspose(i, *src++);
+ _player->configPart_setTranspose(i, *src++);
src = _musicTrackData + 1748;
for (int i = 0; i < 6; i++)
- _driver->assignChannel(i, *src++);
+ _player->driver()->assignPartToChannel(i, *src++);
for (int i = 0x40; i < 0x46; i++)
- _driver->assignChannel(i, *src++);
+ _player->driver()->assignPartToChannel(i, *src++);
uint32 trackSize = READ_LE_UINT32(_musicTrackData + 2048);
uint8 startTick = _musicTrackData[2052];
- _driver->setMusicTempo(_musicTrackData[2053]);
+ _player->setTempo(_musicTrackData[2053]);
src = _musicTrackData + 2054;
uint32 l = READ_LE_UINT32(src + trackSize);
@@ -377,14 +377,14 @@ void SoundTowns::playEuphonyTrack(uint32 offset, int loop) {
l = READ_LE_UINT32(src + trackSize);
trackSize += (l + 4);
- _driver->setMusicLoop(loop);
- _driver->startMusicTrack(src, trackSize, startTick);
+ _player->setLoopStatus(loop);
+ _player->startTrack(src, trackSize, startTick);
}
void SoundTowns::fadeOutSoundEffects() {
for (int i = 127; i > 0; i-= 12) {
- _driver->chanVolume(0x46, i);
- _driver->chanVolume(0x47, i);
+ _player->driver()->channelVolume(0x46, i);
+ _player->driver()->channelVolume(0x47, i);
_vm->delay(_vm->tickLength());
}
stopAllSoundEffects();
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 731f2f4ce5..1a2e2c093c 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -39,7 +39,7 @@
namespace Kyra {
-#define RESFILE_VERSION 86
+#define RESFILE_VERSION 87
namespace {
bool checkKyraDat(Common::SeekableReadStream *file) {
diff --git a/engines/lastexpress/data/snd.cpp b/engines/lastexpress/data/snd.cpp
index 2a221afadc..e310bafd18 100644
--- a/engines/lastexpress/data/snd.cpp
+++ b/engines/lastexpress/data/snd.cpp
@@ -442,7 +442,7 @@ void SimpleSound::loadHeader(Common::SeekableReadStream *in) {
_blockSize = _size / _blocks;
}
-Audio::AudioStream *SimpleSound::makeDecoder(Common::SeekableReadStream *in, uint32 size, int32 filterId) const {
+LastExpress_ADPCMStream *SimpleSound::makeDecoder(Common::SeekableReadStream *in, uint32 size, int32 filterId) const {
return new LastExpress_ADPCMStream(in, DisposeAfterUse::YES, size, _blockSize, filterId);
}
@@ -489,7 +489,7 @@ void StreamedSound::setFilterId(int32 filterId) {
if (!_as)
return;
- ((LastExpress_ADPCMStream *)_as)->setFilterId(filterId);
+ _as->setFilterId(filterId);
}
//////////////////////////////////////////////////////////////////////////
@@ -525,8 +525,8 @@ void AppendableSound::queueBuffer(Common::SeekableReadStream *bufferIn) {
// Setup the ADPCM decoder
uint32 sizeIn = (uint32)bufferIn->size();
- Audio::AudioStream *adpcm = makeDecoder(bufferIn, sizeIn);
- ((LastExpress_ADPCMStream *)adpcm)->setFilterId(16);
+ LastExpress_ADPCMStream *adpcm = makeDecoder(bufferIn, sizeIn);
+ adpcm->setFilterId(16);
// Queue the stream
_as->queueAudioStream(adpcm);
diff --git a/engines/lastexpress/data/snd.h b/engines/lastexpress/data/snd.h
index f489304ff3..19e5fda9c9 100644
--- a/engines/lastexpress/data/snd.h
+++ b/engines/lastexpress/data/snd.h
@@ -49,6 +49,8 @@ class SeekableReadStream;
namespace LastExpress {
+class LastExpress_ADPCMStream;
+
class SimpleSound {
public:
SimpleSound();
@@ -59,7 +61,7 @@ public:
protected:
void loadHeader(Common::SeekableReadStream *in);
- Audio::AudioStream *makeDecoder(Common::SeekableReadStream *in, uint32 size, int32 filterId = -1) const;
+ LastExpress_ADPCMStream *makeDecoder(Common::SeekableReadStream *in, uint32 size, int32 filterId = -1) const;
void play(Audio::AudioStream *as);
uint32 _size; ///< data size
@@ -82,7 +84,7 @@ public:
void setFilterId(int32 filterId);
private:
- Audio::AudioStream *_as;
+ LastExpress_ADPCMStream *_as;
bool _loaded;
};
diff --git a/engines/lure/res.cpp b/engines/lure/res.cpp
index 6b2705463d..7a79f48b87 100644
--- a/engines/lure/res.cpp
+++ b/engines/lure/res.cpp
@@ -44,6 +44,10 @@ Resources::Resources() : _rnd(LureEngine::getReference().rnd()) {
MemoryBlock *mb = Disk::getReference().getEntry(STRING_LIST_RESOURCE_ID);
_stringList.load(mb);
delete mb;
+
+ // WORKAROUND: In Spanish the look "Obsevar" should be "Observar"
+ if (!Common::String(_stringList.getString(LOOK)).compareTo("Obsevar"))
+ _stringList.setString(LOOK, "Observar");
}
Resources::~Resources() {
diff --git a/engines/lure/res_struct.cpp b/engines/lure/res_struct.cpp
index 5a4761c87b..ec1a546d05 100644
--- a/engines/lure/res_struct.cpp
+++ b/engines/lure/res_struct.cpp
@@ -1217,26 +1217,19 @@ void BarmanLists::loadFromStream(Common::ReadStream *stream) {
// String list resource class
void StringList::load(MemoryBlock *data) {
- _data = Memory::allocate(data->size());
- _data->copyFrom(data);
+ // Get the number of entries
+ uint numEntries = READ_LE_UINT16(data->data());
- _numEntries = READ_LE_UINT16(_data->data());
- char *p = (char *) _data->data() + sizeof(uint16);
-
- _entries = (char **) Memory::alloc(_numEntries * sizeof(char *));
-
- for (int index = 0; index < _numEntries; ++index) {
- _entries[index] = p;
+ // Iterate through loading the strings one at a time
+ const char *p = (const char *)data->data() + sizeof(uint16);
+ for (uint index = 0; index < numEntries; ++index) {
+ _entries.push_back(p);
p += strlen(p) + 1;
}
}
void StringList::clear() {
- if (_numEntries != 0) {
- Memory::dealloc(_entries);
- delete _data;
- _numEntries = 0;
- }
+ _entries.clear();
}
// Field list and miscellaneous variables
diff --git a/engines/lure/res_struct.h b/engines/lure/res_struct.h
index 9190912f5b..685c55ab13 100644
--- a/engines/lure/res_struct.h
+++ b/engines/lure/res_struct.h
@@ -28,6 +28,7 @@
#include "common/list.h"
#include "common/file.h"
#include "common/ptr.h"
+#include "common/str-array.h"
#include "common/textconsole.h"
namespace Lure {
@@ -850,22 +851,19 @@ enum StringEnum {S_CREDITS = 25, S_RESTART_GAME = 26, S_SAVE_GAME = 27, S_RESTOR
class StringList {
private:
- MemoryBlock *_data;
- int _numEntries;
- char **_entries;
+ Common::StringArray _entries;
public:
- StringList() { _numEntries = 0; }
- ~StringList() { clear(); }
+ StringList() {}
void load(MemoryBlock *data);
void clear();
- int count() { return _numEntries; }
+ int count() { return _entries.size(); }
const char *getString(int index) {
- if ((index < 0) || (index >= _numEntries)) error("Invalid index specified to String List");
- return _entries[index];
+ return _entries[index].c_str();
}
const char *getString(Action action) { return getString((int) action - 1); }
const char *getString(StringEnum sEnum) { return getString((int) sEnum); }
+ void setString(Action action, const Common::String &s) { _entries[(int)action - 1] = s; }
};
// The following class holds the field list used by the script engine as
diff --git a/engines/mads/configure.engine b/engines/mads/configure.engine
index 60d833e9e8..412d65e180 100644
--- a/engines/mads/configure.engine
+++ b/engines/mads/configure.engine
@@ -1,3 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
-add_engine mads "Rex Nebular and the Cosmic Gender Bender" no
+add_engine mads "Rex Nebular and the Cosmic Gender Bender" yes
diff --git a/engines/mads/detection_tables.h b/engines/mads/detection_tables.h
index 56df09577c..f0eb21f5d9 100644
--- a/engines/mads/detection_tables.h
+++ b/engines/mads/detection_tables.h
@@ -55,7 +55,7 @@ static const MADSGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO5(GUIO_NOSPEECH, GAMEOPTION_EASY_MOUSE, GAMEOPTION_ANIMATED_INVENTORY, GAMEOPTION_ANIMATED_INTERFACE, GAMEOPTION_NAUGHTY_MODE)
},
GType_RexNebular,
@@ -73,7 +73,7 @@ static const MADSGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_TESTING,
+ ADGF_NO_FLAGS,
GUIO5(GUIO_NOSPEECH, GAMEOPTION_EASY_MOUSE, GAMEOPTION_ANIMATED_INVENTORY, GAMEOPTION_ANIMATED_INTERFACE, GAMEOPTION_NAUGHTY_MODE)
},
GType_RexNebular,
diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp
index 1976bcb928..5526845552 100644
--- a/engines/mads/nebular/game_nebular.cpp
+++ b/engines/mads/nebular/game_nebular.cpp
@@ -118,6 +118,10 @@ void GameNebular::startGame() {
initializeGlobals();
+ if (_loadGameSlot >= 0)
+ // User selected to resume a savegame
+ return;
+
// Check copy protection
ProtectionResult protectionResult = checkCopyProtection();
diff --git a/engines/mads/nebular/menu_nebular.cpp b/engines/mads/nebular/menu_nebular.cpp
index 6fe17f3beb..0520294b29 100644
--- a/engines/mads/nebular/menu_nebular.cpp
+++ b/engines/mads/nebular/menu_nebular.cpp
@@ -48,6 +48,7 @@ MainMenu::MainMenu(MADSEngine *vm): MenuView(vm) {
_highlightedIndex = -1;
_selectedIndex = -1;
_buttonDown = false;
+ _showEvolve = _showSets = false;
for (int i = 0; i < 7; ++i)
_menuItems[i] = nullptr;
@@ -137,12 +138,14 @@ void MainMenu::doFrame() {
}
_vm->_events->showCursor();
+ showBonusItems();
} else {
if ((_menuItemIndex == -1) || (_frameIndex == 0)) {
if (++_menuItemIndex == 6) {
// Reached end of display animation
_vm->_events->showCursor();
+ showBonusItems();
return;
} else if (_menuItemIndex == 4 && !shouldShowQuotes()) {
++_menuItemIndex;
@@ -180,6 +183,17 @@ void MainMenu::addSpriteSlot() {
_redrawFlag = true;
}
+void MainMenu::showBonusItems() {
+ Scene &scene = _vm->_game->_scene;
+ _showEvolve = Common::File::exists("SECTION0.HAG") && Common::File::exists("evolve.res");
+ _showSets = Common::File::exists("SECTION0.HAG") && Common::File::exists("sets.res");
+
+ if (_showSets)
+ scene._kernelMessages.add(Common::Point(290, 143), 0x4140, 0, 0, 0, "S");
+ if (_showEvolve)
+ scene._kernelMessages.add(Common::Point(305, 143), 0x4140, 0, 0, 0, "E");
+}
+
bool MainMenu::onEvent(Common::Event &event) {
Scene &scene = _vm->_game->_scene;
if (_selectedIndex != -1)
@@ -280,6 +294,10 @@ bool MainMenu::onEvent(Common::Event &event) {
_selectedIndex = _highlightedIndex;
unhighlightItem();
_frameIndex = 0;
+ } else if (_showSets && Common::Rect(290, 165, 300, 185).contains(event.mouse)) {
+ handleAction(SETS);
+ } else if (_showEvolve && Common::Rect(305, 165, 315, 185).contains(event.mouse)) {
+ handleAction(EVOLVE);
}
return true;
@@ -334,6 +352,14 @@ void MainMenu::handleAction(MADSGameAction action) {
TextView::execute(_vm, "quotes");
return;
+ case SETS:
+ AnimationView::execute(_vm, "sets");
+ break;
+
+ case EVOLVE:
+ AnimationView::execute(_vm, "evolve");
+ break;
+
case EXIT:
_vm->_dialogs->_pendingDialog = DIALOG_ADVERT;
break;
diff --git a/engines/mads/nebular/menu_nebular.h b/engines/mads/nebular/menu_nebular.h
index 35af0bb34f..8a0cc3575d 100644
--- a/engines/mads/nebular/menu_nebular.h
+++ b/engines/mads/nebular/menu_nebular.h
@@ -35,7 +35,10 @@ class MADSEngine;
namespace Nebular {
-enum MADSGameAction { START_GAME, RESUME_GAME, SHOW_INTRO, CREDITS, QUOTES, EXIT };
+enum MADSGameAction {
+ START_GAME, RESUME_GAME, SHOW_INTRO, CREDITS, QUOTES, EXIT,
+ SETS, EVOLVE
+};
class MainMenu: public MenuView {
private:
@@ -45,6 +48,7 @@ private:
int _frameIndex;
uint32 _delayTimeout;
bool _skipFlag;
+ bool _showEvolve, _showSets;
/**
* Currently highlighted menu item
@@ -81,7 +85,16 @@ private:
*/
void addSpriteSlot();
+ /**
+ * Returns true if the Quotes item should be shown.
+ * i.e. if the player has completed the game
+ */
bool shouldShowQuotes();
+
+ /**
+ * Show the bonus item icons, if available
+ */
+ void showBonusItems();
protected:
/**
* Display the menu
diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp
index c33ce7f780..9207d87be7 100644
--- a/engines/mads/nebular/nebular_scenes1.cpp
+++ b/engines/mads/nebular/nebular_scenes1.cpp
@@ -84,7 +84,7 @@ void Scene1xx::setPlayerSpritesPrefix() {
} else if (_scene->_nextSceneId == 112)
_game._player._spritesPrefix = "";
- if (oldName == _game._player._spritesPrefix)
+ if (oldName != _game._player._spritesPrefix)
_game._player._spritesChanged = true;
if (_scene->_nextSceneId == 105 || (_scene->_nextSceneId == 109 && _globals[kHoovicAlive])) {
diff --git a/engines/mads/nebular/sound_nebular.cpp b/engines/mads/nebular/sound_nebular.cpp
index 711f82a05b..4c360b23d5 100644
--- a/engines/mads/nebular/sound_nebular.cpp
+++ b/engines/mads/nebular/sound_nebular.cpp
@@ -216,6 +216,8 @@ ASound::ASound(Audio::Mixer *mixer, OPL::OPL *opl, const Common::String &filenam
}
ASound::~ASound() {
+ _opl->stop();
+
Common::List<CachedDataEntry>::iterator i;
for (i = _dataCache.begin(); i != _dataCache.end(); ++i)
delete[] (*i)._data;
@@ -2025,8 +2027,8 @@ const ASound4::CommandPtr ASound4::_commandList[61] = {
&ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::command43,
&ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand,
&ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand,
- &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand,
- &ASound4::nullCommand, &ASound4::command57, &ASound4::nullCommand, &ASound4::command59,
+ &ASound4::command52, &ASound4::command53, &ASound4::command54, &ASound4::command55,
+ &ASound4::command56, &ASound4::command57, &ASound4::command58, &ASound4::command59,
&ASound4::command60
};
diff --git a/engines/mads/resources.cpp b/engines/mads/resources.cpp
index d5352fb205..3b7cf2cab0 100644
--- a/engines/mads/resources.cpp
+++ b/engines/mads/resources.cpp
@@ -151,7 +151,7 @@ void HagArchive::loadIndex(MADSEngine *vm) {
Common::File hagFile;
for (int sectionIndex = -1; sectionIndex < 11; ++sectionIndex) {
- if (sectionIndex == 0)
+ if (sectionIndex == 0 && !Common::File::exists("SECTION0.HAG"))
continue;
// Dragonsphere does not have some sections - skip them
@@ -239,7 +239,7 @@ Common::String HagArchive::getResourceFilename(const Common::String &resourceNam
int value = atoi(resourceName.c_str() + 2);
int hagFileNum = (resType == RESTYPE_ROOM) ? value / 100 : value;
- if (hagFileNum > 0)
+ if (hagFileNum >= 0)
outputFilename = Common::String::format("SECTION%d.HAG", hagFileNum);
}
diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp
index 6f18d7178e..198627e012 100644
--- a/engines/mohawk/sound.cpp
+++ b/engines/mohawk/sound.cpp
@@ -77,8 +77,8 @@ void Sound::initMidi() {
_midiParser->setTimerRate(_midiDriver->getBaseTempo());
}
-Audio::AudioStream *Sound::makeAudioStream(uint16 id, CueList *cueList) {
- Audio::AudioStream *audStream = NULL;
+Audio::RewindableAudioStream *Sound::makeAudioStream(uint16 id, CueList *cueList) {
+ Audio::RewindableAudioStream *audStream = NULL;
switch (_vm->getGameType()) {
case GType_MYST:
@@ -109,17 +109,18 @@ Audio::AudioStream *Sound::makeAudioStream(uint16 id, CueList *cueList) {
Audio::SoundHandle *Sound::playSound(uint16 id, byte volume, bool loop, CueList *cueList) {
debug (0, "Playing sound %d", id);
- Audio::AudioStream *audStream = makeAudioStream(id, cueList);
+ Audio::RewindableAudioStream *rewindStream = makeAudioStream(id, cueList);
- if (audStream) {
+ if (rewindStream) {
SndHandle *handle = getHandle();
handle->type = kUsedHandle;
handle->id = id;
- handle->samplesPerSecond = audStream->getRate();
+ handle->samplesPerSecond = rewindStream->getRate();
// Set the stream to loop here if it's requested
+ Audio::AudioStream *audStream = rewindStream;
if (loop)
- audStream = Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audStream, 0);
+ audStream = Audio::makeLoopingAudioStream(rewindStream, 0);
_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &handle->handle, audStream, -1, volume);
return &handle->handle;
@@ -335,11 +336,12 @@ void Sound::playSLSTSound(uint16 id, bool fade, bool loop, uint16 volume, int16
sndHandle.id = id;
_currentSLSTSounds.push_back(sndHandle);
- Audio::AudioStream *audStream = makeMohawkWaveStream(_vm->getResource(ID_TWAV, id));
+ Audio::RewindableAudioStream *rewindStream = makeMohawkWaveStream(_vm->getResource(ID_TWAV, id));
// Loop here if necessary
+ Audio::AudioStream *audStream = rewindStream;
if (loop)
- audStream = Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audStream, 0);
+ audStream = Audio::makeLoopingAudioStream(rewindStream, 0);
// TODO: Handle fading, possibly just raise the volume of the channel in increments?
@@ -363,7 +365,7 @@ void Sound::resumeSLST() {
_vm->_mixer->pauseHandle(*_currentSLSTSounds[i].handle, false);
}
-Audio::AudioStream *Sound::makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList) {
+Audio::RewindableAudioStream *Sound::makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList) {
uint32 tag = 0;
ADPCMStatus adpcmStatus;
DataChunk dataChunk;
@@ -507,7 +509,7 @@ Audio::AudioStream *Sound::makeMohawkWaveStream(Common::SeekableReadStream *stre
return NULL;
}
-Audio::AudioStream *Sound::makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream) {
+Audio::RewindableAudioStream *Sound::makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream) {
uint16 header = stream->readUint16BE();
uint16 rate = 0;
uint32 size = 0;
@@ -646,15 +648,15 @@ Audio::SoundHandle *Sound::replaceBackgroundMyst(uint16 id, uint16 volume) {
stopBackgroundMyst();
// Play new sound
- Audio::AudioStream *audStream = makeAudioStream(id);
+ Audio::RewindableAudioStream *rewindStream = makeAudioStream(id);
- if (audStream) {
+ if (rewindStream) {
_mystBackgroundSound.type = kUsedHandle;
_mystBackgroundSound.id = id;
- _mystBackgroundSound.samplesPerSecond = audStream->getRate();
+ _mystBackgroundSound.samplesPerSecond = rewindStream->getRate();
// Set the stream to loop
- audStream = Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audStream, 0);
+ Audio::AudioStream *audStream = Audio::makeLoopingAudioStream(rewindStream, 0);
_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_mystBackgroundSound.handle, audStream, -1, volume >> 8);
return &_mystBackgroundSound.handle;
diff --git a/engines/mohawk/sound.h b/engines/mohawk/sound.h
index 49f6751072..75c9492d96 100644
--- a/engines/mohawk/sound.h
+++ b/engines/mohawk/sound.h
@@ -156,13 +156,13 @@ private:
MidiParser *_midiParser;
byte *_midiData;
- static Audio::AudioStream *makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList = NULL);
- static Audio::AudioStream *makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream);
+ static Audio::RewindableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList = NULL);
+ static Audio::RewindableAudioStream *makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream);
void initMidi();
Common::Array<SndHandle> _handles;
SndHandle *getHandle();
- Audio::AudioStream *makeAudioStream(uint16 id, CueList *cueList = NULL);
+ Audio::RewindableAudioStream *makeAudioStream(uint16 id, CueList *cueList = NULL);
uint16 convertMystID(uint16 id);
// Myst-specific
diff --git a/engines/mortevielle/detection_tables.h b/engines/mortevielle/detection_tables.h
index 26611d4271..fb85e749ad 100644
--- a/engines/mortevielle/detection_tables.h
+++ b/engines/mortevielle/detection_tables.h
@@ -124,7 +124,7 @@ static const MortevielleGameDescription MortevielleGameDescriptions[] = {
Common::kPlatformDOS,
ADGF_NO_FLAGS,
GUIO0()
- }, Common::FR_FRA, kUseOriginalData
+ }, Common::FR_FRA, kUseEngineDataFile
},
{ AD_TABLE_END_MARKER , Common::EN_ANY, kUseEngineDataFile}
diff --git a/engines/mortevielle/menu.cpp b/engines/mortevielle/menu.cpp
index b788ce9a71..6235e9f2ed 100644
--- a/engines/mortevielle/menu.cpp
+++ b/engines/mortevielle/menu.cpp
@@ -682,13 +682,10 @@ void Menu::initMenu() {
if (!menuLoaded) {
// Load menu from game data using the original language
if (_vm->getOriginalLanguage() == Common::FR_FRA) {
- if (f.exists("menufr.mor")) {
- if (!f.open("menufr.mor"))
- error("Missing file - menufr.mor");
- } else {
- if (!f.open("menu.mor"))
- error("Missing file - menu.mor");
- }
+ // We do not support reading menu.mor (it has a different format).
+ // If the game version does not have menufr.mor it has to get the menu from the DAT file.
+ if (!f.open("menufr.mor"))
+ error("Missing file - menufr.mor");
} else { // Common::DE_DEU
if (!f.open("menual.mor"))
error("Missing file - menual.mor");
diff --git a/engines/mortevielle/sound.cpp b/engines/mortevielle/sound.cpp
index 23ca9d89b4..f02ccb69ea 100644
--- a/engines/mortevielle/sound.cpp
+++ b/engines/mortevielle/sound.cpp
@@ -139,22 +139,44 @@ void SoundManager::loadAmbiantSounds() {
* @remarks Originally called 'charge_bruit' and 'charge_bruit5'
*/
void SoundManager::loadNoise() {
- Common::File f1, f2;
+ Common::File f1, f5;
- if (!f1.open("bruits")) //Translation: "noise"
- error("Missing file - bruits");
- if (!f2.open("bruit5"))
+ if (!f5.open("bruit5"))
error("Missing file - bruit5");
- _noiseBuf = (byte *)malloc(sizeof(byte) * (f1.size() + f2.size()));
- assert(f1.size() > 32000);
+ if (f1.open("bruits")) { //Translation: "noise"
+ assert(f1.size() > 32000);
+ _noiseBuf = (byte *)malloc(sizeof(byte) * (f1.size() + f5.size()));
- f1.read(_noiseBuf, 32000); // 250 * 128
- f2.read(&_noiseBuf[32000], f2.size());
- f1.read(&_noiseBuf[32000 + f2.size()], f1.size() - 32000); // 19072
+ f1.read(_noiseBuf, 32000); // 250 * 128
+ f5.read(&_noiseBuf[32000], f5.size());
+ f1.read(&_noiseBuf[32000 + f5.size()], f1.size() - 32000); // 19072
- f1.close();
- f2.close();
+ f1.close();
+ } else {
+ Common::File f2, f3, f4;
+ if (!f1.open("bruit1") || !f2.open("bruit2") || !f3.open("bruit3") || !f4.open("bruit4"))
+ error("Missing file - bruits");
+
+ assert(f4.size() == 32000);
+ _noiseBuf = (byte *)malloc(sizeof(byte) * (f1.size() + f2.size() + f3.size() + f4.size() + f5.size()));
+
+ f4.read(_noiseBuf, f4.size());
+ int pos = f4.size();
+ f5.read(&_noiseBuf[pos], f5.size());
+ pos += f5.size();
+ f1.read(&_noiseBuf[pos], f1.size());
+ pos += f1.size();
+ f2.read(&_noiseBuf[pos], f2.size());
+ pos += f2.size();
+ f3.read(&_noiseBuf[pos], f3.size());
+
+ f1.close();
+ f2.close();
+ f3.close();
+ f4.close();
+ }
+ f5.close();
}
void SoundManager::regenbruit() {
diff --git a/engines/mortevielle/utils.cpp b/engines/mortevielle/utils.cpp
index 5137e1892b..cbc22e4886 100644
--- a/engines/mortevielle/utils.cpp
+++ b/engines/mortevielle/utils.cpp
@@ -2115,8 +2115,12 @@ void MortevielleEngine::music() {
_reloadCFIEC = true;
Common::File f;
- if (!f.open("mort.img"))
- error("Missing file - mort.img");
+ if (!f.open("mort.img")) {
+ // Some DOS versions use MORTP2 instead of MORT.IMG
+ // Some have both and they are identical
+ if (!f.open("mortp2"))
+ error("Missing file - mort.img");
+ }
int size = f.size();
byte *compMusicBuf = (byte *)malloc(sizeof(byte) * size);
diff --git a/engines/neverhood/menumodule.cpp b/engines/neverhood/menumodule.cpp
index 6911041e58..826f175d47 100644
--- a/engines/neverhood/menumodule.cpp
+++ b/engines/neverhood/menumodule.cpp
@@ -93,6 +93,10 @@ void MenuModule::setLoadgameInfo(uint index) {
_savegameSlot = (*_savegameList)[index].slotNum;
}
+void MenuModule::setLoadgameSlot(int slot) {
+ _savegameSlot = slot;
+}
+
void MenuModule::setSavegameInfo(const Common::String &description, uint index, bool newSavegame) {
_savegameDescription = description;
_savegameSlot = newSavegame ? -1 : (*_savegameList)[index].slotNum;
@@ -912,7 +916,7 @@ GameStateMenu::GameStateMenu(NeverhoodEngine *vm, Module *parentModule, Savegame
if (slot >= 0) {
if (!isSave) {
- ((MenuModule*)_parentModule)->setLoadgameInfo(slot);
+ ((MenuModule*)_parentModule)->setLoadgameSlot(slot);
} else {
((MenuModule*)_parentModule)->setSavegameInfo(saveDesc,
slot, slot >= saveCount);
diff --git a/engines/neverhood/menumodule.h b/engines/neverhood/menumodule.h
index 6508ccbdf2..1c4ade2369 100644
--- a/engines/neverhood/menumodule.h
+++ b/engines/neverhood/menumodule.h
@@ -43,6 +43,7 @@ public:
MenuModule(NeverhoodEngine *vm, Module *parentModule, int which);
virtual ~MenuModule();
void setLoadgameInfo(uint index);
+ void setLoadgameSlot(int slot);
void setSavegameInfo(const Common::String &description, uint index, bool newSavegame);
void setDeletegameInfo(uint index);
void refreshSaveGameList();
diff --git a/engines/neverhood/modules/module2700.cpp b/engines/neverhood/modules/module2700.cpp
index a510c02558..e0c6509793 100644
--- a/engines/neverhood/modules/module2700.cpp
+++ b/engines/neverhood/modules/module2700.cpp
@@ -761,7 +761,7 @@ void Scene2702::moveCarToPoint(NPoint pt) {
_tracks.findTrackPoint(pt, minMatchTrackIndex, minMatchDistance, _dataResource);
if (minMatchTrackIndex >= 0 && minMatchTrackIndex != _currTrackIndex) {
_newTrackIndex = minMatchTrackIndex;
- _newTrackDestX = pt.x;
+ _newTrackDest = pt;
if (_isUpperTrack) {
if (_currTrackIndex == 0)
sendMessage(_asCar, 0x2003, _trackPoints->size() - 1);
@@ -773,7 +773,7 @@ void Scene2702::moveCarToPoint(NPoint pt) {
sendMessage(_asCar, 0x2003, _trackPoints->size() - 1);
} else {
_newTrackIndex = -1;
- sendMessage(_asCar, 0x2004, pt.x);
+ sendMessage(_asCar, 0x2004, pt);
}
}
@@ -790,7 +790,7 @@ void Scene2702::changeTrack() {
sendMessage(_asCar, NM_POSITION_CHANGE, 0);
else
sendMessage(_asCar, NM_POSITION_CHANGE, _trackPoints->size() - 1);
- sendMessage(_asCar, 0x2004, _newTrackDestX);
+ sendMessage(_asCar, 0x2004, _newTrackDest);
_newTrackIndex = -1;
}
@@ -1092,14 +1092,14 @@ void Scene2706::moveCarToPoint(NPoint pt) {
_tracks.findTrackPoint(pt, minMatchTrackIndex, minMatchDistance, _dataResource);
if (minMatchTrackIndex >= 0 && minMatchTrackIndex != _currTrackIndex) {
_newTrackIndex = minMatchTrackIndex;
- _newTrackDestX = pt.x;
+ _newTrackDest = pt;
if (_currTrackIndex == 0)
sendMessage(_asCar, 0x2003, _trackPoints->size() - 1);
else
sendMessage(_asCar, 0x2003, 0);
} else {
_newTrackIndex = -1;
- sendMessage(_asCar, 0x2004, pt.x);
+ sendMessage(_asCar, 0x2004, pt);
}
}
@@ -1111,7 +1111,7 @@ void Scene2706::changeTrack() {
sendMessage(_asCar, NM_POSITION_CHANGE, _trackPoints->size() - 1);
else
sendMessage(_asCar, NM_POSITION_CHANGE, 0);
- sendMessage(_asCar, 0x2004, _newTrackDestX);
+ sendMessage(_asCar, 0x2004, _newTrackDest);
_newTrackIndex = -1;
}
diff --git a/engines/neverhood/modules/module2700.h b/engines/neverhood/modules/module2700.h
index 9ac2159765..ece8866cd4 100644
--- a/engines/neverhood/modules/module2700.h
+++ b/engines/neverhood/modules/module2700.h
@@ -76,7 +76,7 @@ protected:
Sprite *_asCarShadow;
Sprite *_asCarTrackShadow;
Sprite *_asCarConnectorShadow;
- int16 _newTrackDestX;
+ NPoint _newTrackDest;
bool _isInLight;
int _currTrackIndex, _newTrackIndex;
bool _isUpperTrack;
@@ -132,7 +132,7 @@ protected:
Sprite *_asCarConnector;
Sprite *_asCarTrackShadow;
Sprite *_asCarConnectorShadow;
- int16 _newTrackDestX;
+ NPoint _newTrackDest;
int _currTrackIndex, _newTrackIndex;
Tracks _tracks;
NPointArray *_trackPoints;
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index 55305c4b42..4482375d19 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -4127,6 +4127,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::FR_FRA, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ // Torin's Passage - German Windows CD (from m_kiewitz)
+ // SCI interpreter version 2.100.002
+ // VERSION file "1.0"
+ {"torin", "", {
+ {"resmap.000", 0, "e55c3097329b3c53752301e01c6af2fb", 9787},
+ {"ressci.000", 0, "118f9bec04bfe17c4f87bbb5ddb43c18", 56127540},
+ AD_LISTEND},
+ Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
// Torin's Passage (Multilingual) - German Windows CD
// SCI interpreter version 2.100.002
{"torin", "", {
@@ -4185,7 +4194,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
FANMADE_L("Grostesteing: Plus Mechant que Jamais", "ec9a97ccb134f69249f6ea8b16c13d8e", 1500, "b869f5f11bfe2ab5f67f4f0c618f2ce1", 464657, Common::FR_FRA), // FIXME: Accent
FANMADE("Humanoid Demo", "97d8331293a6d57e8bad58c1efc89a63", 624, "fb354b9abe64011b12159e45d724633f", 452320),
FANMADE("Island of Secrets Demo 0.3", "61279176c3e4530fec9b578877aecda7", 504, "7f4ed7a81b86bea22c62bc98e6d9ec39", 197790),
- FANMADE("Jim’s Quest 1: The Phantom Thesis", "0af50be1d3f0cb77a09137709a76ef4f", 960, "9c042c136548b20d9183495668e03526", 496446),
+ FANMADE("Jim's Quest 1: The Phantom Thesis", "0af50be1d3f0cb77a09137709a76ef4f", 960, "9c042c136548b20d9183495668e03526", 496446),
FANMADE("King's Quest II SCI Pre-Alpha Version", "cdea1c081022e7697a1afffb1d2f9f6a", 2646, "fb2ce39002c3e05f3d83533638dea105", 2310356),
FANMADE("Knight's Quest Demo 1.0", "5e816edf993956752ed06fccfeeae6d9", 1260, "959321f88a22905fa1f8c6d897874744", 703836),
FANMADE("LockerGnome Quest", "3eeff9130206cad0c4e1551e2b9dd2c5", 420, "ae05ca90806fd90cc43f147c82d3547c", 158906),
diff --git a/engines/scumm/POTFILES b/engines/scumm/POTFILES
index 6d10537d3c..246f14d3f0 100644
--- a/engines/scumm/POTFILES
+++ b/engines/scumm/POTFILES
@@ -1,5 +1,6 @@
engines/scumm/dialogs.cpp
engines/scumm/help.cpp
+engines/scumm/input.cpp
engines/scumm/scumm.cpp
engines/scumm/players/player_v3m.cpp
engines/scumm/players/player_v5m.cpp
diff --git a/engines/scumm/imuse_digi/dimuse.cpp b/engines/scumm/imuse_digi/dimuse.cpp
index db260dce42..3f61946bf2 100644
--- a/engines/scumm/imuse_digi/dimuse.cpp
+++ b/engines/scumm/imuse_digi/dimuse.cpp
@@ -201,8 +201,7 @@ void IMuseDigital::saveOrLoad(Serializer *ser) {
track->stream = Audio::makeQueuingAudioStream(freq, (track->mixerFlags & kFlagStereo) != 0);
- _mixer->playStream(track->getType(), &track->mixChanHandle, track->stream, -1, track->getVol(), track->getPan(),
- DisposeAfterUse::YES, false, (track->mixerFlags & kFlagStereo) != 0);
+ _mixer->playStream(track->getType(), &track->mixChanHandle, track->stream, -1, track->getVol(), track->getPan());
_mixer->pauseHandle(track->mixChanHandle, true);
}
}
diff --git a/engines/scumm/imuse_digi/dimuse_track.cpp b/engines/scumm/imuse_digi/dimuse_track.cpp
index 34926fa34e..b7abdd074e 100644
--- a/engines/scumm/imuse_digi/dimuse_track.cpp
+++ b/engines/scumm/imuse_digi/dimuse_track.cpp
@@ -110,8 +110,7 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType,
track->souStreamUsed = (input != 0);
if (track->souStreamUsed) {
- _mixer->playStream(track->getType(), &track->mixChanHandle, input, -1, track->getVol(), track->getPan(),
- DisposeAfterUse::YES, false, (track->mixerFlags & kFlagStereo) != 0);
+ _mixer->playStream(track->getType(), &track->mixChanHandle, input, -1, track->getVol(), track->getPan());
} else {
strcpy(track->soundName, soundName);
track->soundDesc = _sound->openSound(soundId, soundName, soundType, volGroupId, -1);
@@ -167,8 +166,7 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType,
}
track->stream = Audio::makeQueuingAudioStream(freq, track->mixerFlags & kFlagStereo);
- _mixer->playStream(track->getType(), &track->mixChanHandle, track->stream, -1, track->getVol(), track->getPan(),
- DisposeAfterUse::YES, false, (track->mixerFlags & kFlagStereo) != 0);
+ _mixer->playStream(track->getType(), &track->mixChanHandle, track->stream, -1, track->getVol(), track->getPan());
}
track->used = true;
@@ -368,8 +366,7 @@ Track *IMuseDigital::cloneToFadeOutTrack(Track *track, int fadeDelay) {
// Create an appendable output buffer
fadeTrack->stream = Audio::makeQueuingAudioStream(_sound->getFreq(fadeTrack->soundDesc), track->mixerFlags & kFlagStereo);
- _mixer->playStream(track->getType(), &fadeTrack->mixChanHandle, fadeTrack->stream, -1, fadeTrack->getVol(), fadeTrack->getPan(),
- DisposeAfterUse::YES, false, (track->mixerFlags & kFlagStereo) != 0);
+ _mixer->playStream(track->getType(), &fadeTrack->mixChanHandle, fadeTrack->stream, -1, fadeTrack->getVol(), fadeTrack->getPan());
fadeTrack->used = true;
debug(5, "cloneToFadeOutTrack() - end of func, soundId %d, fade soundId %d", track->soundId, fadeTrack->soundId);
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 86048af57c..3ce053f6bc 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -23,6 +23,7 @@
#include "common/config-manager.h"
#include "common/events.h"
#include "common/system.h"
+#include "common/translation.h"
#include "gui/message.h"
#include "gui/gui-manager.h"
@@ -568,9 +569,9 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
lastKeyHit.hasFlags(Common::KBD_CTRL)) {
_snapScroll ^= 1;
if (_snapScroll) {
- messageDialog("Snap scroll on");
+ messageDialog(_("Snap scroll on"));
} else {
- messageDialog("Snap scroll off");
+ messageDialog(_("Snap scroll off"));
}
if (VAR_CAMERA_FAST_X != 0xFF)
@@ -583,7 +584,7 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
vol--;
// Display the music volume
- ValueDisplayDialog dlg("Music volume: ", 0, 16, vol, ']', '[');
+ ValueDisplayDialog dlg(_("Music volume: "), 0, 16, vol, ']', '[');
vol = runDialog(dlg);
vol *= 16;
@@ -600,7 +601,7 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
_defaultTalkDelay++;
// Display the talk speed
- ValueDisplayDialog dlg("Subtitle speed: ", 0, 9, 9 - _defaultTalkDelay, '+', '-');
+ ValueDisplayDialog dlg(_("Subtitle speed: "), 0, 9, 9 - _defaultTalkDelay, '+', '-');
_defaultTalkDelay = 9 - runDialog(dlg);
// Save the new talkspeed value to ConfMan
diff --git a/engines/scumm/players/player_towns.cpp b/engines/scumm/players/player_towns.cpp
index 5b8ca04021..d540fc4f6b 100644
--- a/engines/scumm/players/player_towns.cpp
+++ b/engines/scumm/players/player_towns.cpp
@@ -202,23 +202,24 @@ Player_Towns_v1::Player_Towns_v1(ScummEngine *vm, Audio::Mixer *mixer) : Player_
memset(_soundOverride, 0, _numSoundMax * sizeof(SoundOvrParameters));
}
- _driver = new TownsEuphonyDriver(mixer);
+ _player = new EuphonyPlayer(mixer);
+ _intf = new TownsAudioInterface(mixer, 0);
}
Player_Towns_v1::~Player_Towns_v1() {
- delete _driver;
+ delete _intf;
+ delete _player;
delete[] _soundOverride;
}
bool Player_Towns_v1::init() {
- if (!_driver)
+ if (!_player)
return false;
- if (!_driver->init())
+ if (!_player->init())
return false;
- _driver->reserveSoundEffectChannels(8);
- _intf = _driver->intf();
+ _player->driver()->reserveSoundEffectChannels(8);
// Treat all 6 fm channels and all 8 pcm channels as sound effect channels
// since music seems to exist as CD audio only in the games which use this
@@ -231,7 +232,7 @@ bool Player_Towns_v1::init() {
}
void Player_Towns_v1::setMusicVolume(int vol) {
- _driver->setMusicVolume(vol);
+ _player->driver()->setMusicVolume(vol);
}
void Player_Towns_v1::startSound(int sound) {
@@ -254,7 +255,9 @@ void Player_Towns_v1::startSound(int sound) {
uint16 len = READ_LE_UINT16(ptr) + 2;
playPcmTrack(sound, ptr + 6, velocity, 64, note ? note : (len > 50 ? ptr[50] : 60), READ_LE_UINT16(ptr + 10));
- } else if (type == 1) {
+ // WORKAROUND for bug #1873 INDY3 FMTOWNS: Music in Venice is distorted
+ // The resource for sound 40 accidently sets the sound type to 255 instead of 1.
+ } else if (type == 1 || (_vm->_game.id == GID_INDY3 && sound == 40)) {
playEuphonyTrack(sound, ptr + 6);
} else if (type == 2) {
@@ -275,7 +278,7 @@ void Player_Towns_v1::stopSound(int sound) {
if (sound != 0 && sound == _eupCurrentSound) {
_eupCurrentSound = 0;
_eupLooping = false;
- _driver->stopParser();
+ _player->stop();
}
stopPcmTrack(sound);
@@ -288,7 +291,7 @@ void Player_Towns_v1::stopAllSounds() {
_eupCurrentSound = 0;
_eupLooping = false;
- _driver->stopParser();
+ _player->stop();
stopPcmTrack(0);
}
@@ -297,7 +300,7 @@ int Player_Towns_v1::getSoundStatus(int sound) const {
if (sound == _cdaCurrentSound)
return _vm->_sound->pollCD();
if (sound == _eupCurrentSound)
- return _driver->parserIsPlaying() ? 1 : 0;
+ return _player->isPlaying() ? 1 : 0;
return Player_Towns::getSoundStatus(sound);
}
@@ -306,7 +309,7 @@ int32 Player_Towns_v1::doCommand(int numargs, int args[]) {
switch (args[0]) {
case 2:
- _driver->intf()->callback(73, 0);
+ _player->driver()->cdaToggle(0);
break;
case 3:
@@ -344,7 +347,7 @@ int32 Player_Towns_v1::doCommand(int numargs, int args[]) {
void Player_Towns_v1::setVolumeCD(int left, int right) {
_cdaVolLeft = left & 0xff;
_cdaVolRight = right & 0xff;
- _driver->setOutputVolume(1, left >> 1, right >> 1);
+ _player->driver()->setOutputVolume(1, left >> 1, right >> 1);
}
void Player_Towns_v1::setSoundVolume(int sound, int left, int right) {
@@ -373,7 +376,7 @@ void Player_Towns_v1::saveLoadWithSerializer(Serializer *ser) {
ser->saveLoadEntries(this, cdEntries);
- if (!_eupLooping && !_driver->parserIsPlaying())
+ if (!_eupLooping && !_player->isPlaying())
_eupCurrentSound = 0;
static const SaveLoadEntry eupEntries[] = {
@@ -409,7 +412,9 @@ void Player_Towns_v1::restoreAfterLoad() {
if (_vm->_game.version != 3)
ptr += 2;
- if (ptr[7] == 1) {
+ // WORKAROUND for bug #1873 INDY3 FMTOWNS: Music in Venice is distorted
+ // The resource for sound 40 accidently sets the sound type to 255 instead of 1.
+ if (ptr[7] == 1 || (_vm->_game.id == GID_INDY3 && _eupCurrentSound == 40)) {
setSoundVolume(_eupCurrentSound, _eupVolLeft, _eupVolRight);
playEuphonyTrack(_eupCurrentSound, ptr);
}
@@ -439,10 +444,10 @@ void Player_Towns_v1::restartLoopingSounds() {
c++;
}
- _driver->playSoundEffect(i + 0x3f, _pcmCurrentSound[i].note, _pcmCurrentSound[i].velo, ptr);
+ _player->driver()->playSoundEffect(i + 0x3f, _pcmCurrentSound[i].note, _pcmCurrentSound[i].velo, ptr);
}
- _driver->intf()->callback(73, 1);
+ _player->driver()->cdaToggle(1);
}
void Player_Towns_v1::startSoundEx(int sound, int velo, int pan, int note) {
@@ -492,9 +497,9 @@ void Player_Towns_v1::stopSoundSuspendLooping(int sound) {
} else {
for (int i = 1; i < 9; i++) {
if (sound == _pcmCurrentSound[i].index) {
- if (!_driver->soundEffectIsPlaying(i + 0x3f))
+ if (!_player->driver()->soundEffectIsPlaying(i + 0x3f))
continue;
- _driver->stopSoundEffect(i + 0x3f);
+ _player->driver()->stopSoundEffect(i + 0x3f);
if (_pcmCurrentSound[i].looping)
_pcmCurrentSound[i].paused = 1;
else
@@ -510,23 +515,23 @@ void Player_Towns_v1::playEuphonyTrack(int sound, const uint8 *data) {
const uint8 *trackData = src + 150;
for (int i = 0; i < 32; i++)
- _driver->configChan_enable(i, *src++);
+ _player->configPart_enable(i, *src++);
for (int i = 0; i < 32; i++)
- _driver->configChan_setMode(i, 0xff);
+ _player->configPart_setType(i, 0xff);
for (int i = 0; i < 32; i++)
- _driver->configChan_remap(i, *src++);
+ _player->configPart_remap(i, *src++);
for (int i = 0; i < 32; i++)
- _driver->configChan_adjustVolume(i, *src++);
+ _player->configPart_adjustVolume(i, *src++);
for (int i = 0; i < 32; i++)
- _driver->configChan_setTranspose(i, *src++);
+ _player->configPart_setTranspose(i, *src++);
src += 8;
for (int i = 0; i < 6; i++)
- _driver->assignChannel(i, *src++);
+ _player->driver()->assignPartToChannel(i, *src++);
for (int i = 0; i < data[14]; i++) {
- _driver->loadInstrument(i, i, pos + i * 48);
- _driver->intf()->callback(4, i, i);
+ _player->driver()->loadInstrument(i, i, pos + i * 48);
+ _player->driver()->setInstrument(i, i);
}
_eupVolLeft = _soundOverride[sound].vLeft;
@@ -537,18 +542,18 @@ void Player_Towns_v1::playEuphonyTrack(int sound, const uint8 *data) {
lvl >>= 2;
for (int i = 0; i < 6; i++)
- _driver->chanVolume(i, lvl);
+ _player->driver()->channelVolume(i, lvl);
uint32 trackSize = READ_LE_UINT32(src);
src += 4;
uint8 startTick = *src++;
- _driver->setMusicTempo(*src++);
- _driver->startMusicTrack(trackData, trackSize, startTick);
+ _player->setTempo(*src++);
+ _player->startTrack(trackData, trackSize, startTick);
_eupLooping = (*src != 1) ? 1 : 0;
- _driver->setMusicLoop(_eupLooping != 0);
- _driver->continueParsing();
+ _player->setLoopStatus(_eupLooping != 0);
+ _player->resume();
_eupCurrentSound = sound;
}
diff --git a/engines/scumm/players/player_towns.h b/engines/scumm/players/player_towns.h
index 3736524ee2..576d17e392 100644
--- a/engines/scumm/players/player_towns.h
+++ b/engines/scumm/players/player_towns.h
@@ -104,8 +104,6 @@ public:
void saveLoadWithSerializer(Serializer *ser);
void restoreAfterLoad();
- TownsEuphonyDriver *driver() { return _driver; }
-
private:
void restartLoopingSounds();
void startSoundEx(int sound, int velo, int pan, int note);
@@ -137,7 +135,7 @@ private:
uint8 _cdaCurrentSoundTemp;
uint8 _cdaNumLoopsTemp;
- TownsEuphonyDriver *_driver;
+ EuphonyPlayer *_player;
};
class Player_Towns_v2 : public Player_Towns {
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index a836cf12bc..c85073b877 100644
--- a/engines/scumm/scumm-md5.h
+++ b/engines/scumm/scumm-md5.h
@@ -1,5 +1,5 @@
/*
- This file was generated by the md5table tool on Sun Jun 28 03:19:52 2015
+ This file was generated by the md5table tool on Thu Aug 27 23:44:49 2015
DO NOT EDIT MANUALLY!
*/
@@ -288,6 +288,7 @@ static const MD5Table md5table[] = {
{ "62b8c16b6db226ba95aaa8be73f9885c", "indy3", "EGA", "EGA", -1, Common::ES_ESP, Common::kPlatformAmiga },
{ "632d2fddb8ba97723fa15334763ae857", "thinker1", "", "", 33270, Common::EN_ANY, Common::kPlatformWindows },
{ "63fdcdc95cdeea00060883aed38e5504", "PuttTime", "HE 85", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
+ { "64a22be96d679018696e5c8d3ca8b71d", "freddi", "HE 73", "", 26375, Common::JA_JPN, Common::kPlatformWindows },
{ "6508fd55530e6915507e1cc37f7f045d", "indy3", "EGA", "EGA", -1, Common::EN_ANY, Common::kPlatformDOS },
{ "65563295c3a06493351870f20a1630cf", "spyozon", "HE CUP", "Preview", 5235008, Common::UNK_LANG, Common::kPlatformUnknown },
{ "659942b9a6b519f123a13cca3c333a13", "jungle", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh },
diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp
index bbf7c913b7..681e71d0f6 100644
--- a/engines/sherlock/animation.cpp
+++ b/engines/sherlock/animation.cpp
@@ -22,6 +22,7 @@
#include "sherlock/animation.h"
#include "sherlock/sherlock.h"
+#include "sherlock/scalpel/scalpel_screen.h"
#include "common/algorithm.h"
namespace Sherlock {
@@ -200,19 +201,16 @@ bool Animation::play3DO(const Common::String &filename, bool intro, int minDelay
// Draw the sprite. Note that we explicitly use the raw frame below, rather than the ImageFrame,
// since we don't want the offsets in the image file to be used, just the explicit position we specify
- if (!fadeActive) {
- screen.transBlitFrom(images[imageFrame]._frame, pt);
- } else {
- // Fade active, blit to backbuffer1
- screen._backBuffer1.transBlitFrom(images[imageFrame]._frame, pt);
- }
+ screen._backBuffer1.transBlitFrom(images[imageFrame]._frame, pt);
+ if (!fadeActive)
+ screen.slamArea(pt.x, pt.y, images[imageFrame]._frame.w, images[imageFrame]._frame.h);
} else {
// At this point, either the sprites for the frame has been complete, or there weren't any sprites
// at all to draw for the frame
if (fadeActive) {
// process fading
- screen.blitFrom3DOcolorLimit(fadeLimitColor);
+ static_cast<Scalpel::Scalpel3DOScreen *>(_vm->_screen)->blitFrom3DOcolorLimit(fadeLimitColor);
if (!fadeLimitColor) {
// we are at the end, so stop
diff --git a/engines/sherlock/configure.engine b/engines/sherlock/configure.engine
index a56129a8f0..fd1c354e78 100644
--- a/engines/sherlock/configure.engine
+++ b/engines/sherlock/configure.engine
@@ -1,3 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
-add_engine sherlock "The Lost Files of Sherlock Holmes" no
+add_engine sherlock "The Lost Files of Sherlock Holmes" yes
diff --git a/engines/sherlock/debugger.cpp b/engines/sherlock/debugger.cpp
index 50293db648..39f8da3806 100644
--- a/engines/sherlock/debugger.cpp
+++ b/engines/sherlock/debugger.cpp
@@ -23,7 +23,7 @@
#include "sherlock/debugger.h"
#include "sherlock/sherlock.h"
#include "sherlock/music.h"
-#include "sherlock/scalpel/3do/movie_decoder.h"
+#include "sherlock/scalpel/scalpel.h"
#include "sherlock/scalpel/scalpel_debugger.h"
#include "sherlock/tattoo/tattoo_debugger.h"
#include "audio/mixer.h"
@@ -54,7 +54,7 @@ Debugger::Debugger(SherlockEngine *vm) : GUI::Debugger(), _vm(vm) {
void Debugger::postEnter() {
if (!_3doPlayMovieFile.empty()) {
- Scalpel3DOMoviePlay(_3doPlayMovieFile.c_str(), Common::Point(0, 0));
+ static_cast<Scalpel::ScalpelEngine *>(_vm)->play3doMovie(_3doPlayMovieFile, Common::Point(0, 0));
_3doPlayMovieFile.clear();
}
diff --git a/engines/sherlock/decompress.cpp b/engines/sherlock/decompress.cpp
deleted file mode 100644
index 8e02da3212..0000000000
--- a/engines/sherlock/decompress.cpp
+++ /dev/null
@@ -1,128 +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/decompress.h"
-
-namespace Sherlock {
-
-/**
- * Decompresses an LZW compressed resource. If no outSize is specified, it will
- * decompress the entire resource. If, however, an explicit size is specified,
- * then it means we're already within a resource, and only want to decompress
- * part of it.
- */
-Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source, int32 outSize) {
- if (outSize == -1) {
- source.seek(5);
- outSize = source.readSint32LE();
- }
-
- byte lzWindow[4096];
- uint16 lzWindowPos;
- uint16 cmd;
-
- byte *outBuffer = new byte[outSize];
- byte *outBufferEnd = outBuffer + outSize;
- Common::MemoryReadStream *outS = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
-
- memset(lzWindow, 0xFF, 0xFEE);
- lzWindowPos = 0xFEE;
- cmd = 0;
-
- do {
- cmd >>= 1;
- if (!(cmd & 0x100))
- cmd = source.readByte() | 0xFF00;
-
- if (cmd & 1) {
- byte literal = source.readByte();
- *outBuffer++ = literal;
- lzWindow[lzWindowPos] = literal;
- lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
- } else {
- int copyPos, copyLen;
- copyPos = source.readByte();
- copyLen = source.readByte();
- copyPos = copyPos | ((copyLen & 0xF0) << 4);
- copyLen = (copyLen & 0x0F) + 3;
- while (copyLen--) {
- byte literal = lzWindow[copyPos];
- copyPos = (copyPos + 1) & 0x0FFF;
- *outBuffer++ = literal;
- lzWindow[lzWindowPos] = literal;
- lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
- }
- }
- } while (outBuffer < outBufferEnd);
-
- return outS;
-}
-
-
-/**
- * Decompresses a Rose Tattoo resource
- *
-Common::SeekableReadStream *decompress32(Common::SeekableReadStream &source, int32 outSize) {
- if (outSize == -1) {
- outSize = source.readSint32LE();
- }
-
- byte lzWindow[8192];
- byte *outBuffer = new byte[outSize];
- byte *outBufferEnd = outBuffer + outSize;
- Common::MemoryReadStream *outS = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
-
- memset(lzWindow, 0xFF, 8192);
- int lzWindowPos = 0xFEE;
- int cmd = 0;
-
- do {
- cmd >>= 1;
- if (!(cmd & 0x100))
- cmd = source.readByte() | 0xFF00;
-
- if (cmd & 1) {
- byte literal = source.readByte();
- *outBuffer++ = literal;
- lzWindow[lzWindowPos] = literal;
- lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
- } else {
- int copyPos, copyLen;
- copyPos = source.readByte();
- copyLen = source.readByte();
- copyPos = copyPos | ((copyLen & 0xF0) << 4);
- copyLen = (copyLen & 0x0F) + 3;
- while (copyLen--) {
- byte literal = lzWindow[copyPos];
- copyPos = (copyPos + 1) & 0x0FFF;
- *outBuffer++ = literal;
- lzWindow[lzWindowPos] = literal;
- lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
- }
- }
- } while (outBuffer < outBufferEnd);
-
- return outS;
-}
-*/
-
-} // namespace Sherlock
diff --git a/engines/sherlock/detection_tables.h b/engines/sherlock/detection_tables.h
index e2b5a3dce9..ce6eafcaca 100644
--- a/engines/sherlock/detection_tables.h
+++ b/engines/sherlock/detection_tables.h
@@ -32,7 +32,7 @@ static const SherlockGameDescription gameDescriptions[] = {
AD_ENTRY1s("talk.lib", "ad0c4d6865edf15da4e9204c08815875", 238928),
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_UNSTABLE,
+ ADGF_NO_FLAGS,
GUIO6(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVES, GAMEOPTION_FADE_STYLE, GAMEOPTION_HELP_STYLE,
GAMEOPTION_PORTRAITS_ON, GAMEOPTION_WINDOW_STYLE)
},
@@ -50,7 +50,7 @@ static const SherlockGameDescription gameDescriptions[] = {
AD_LISTEND},
Common::DE_DEU,
Common::kPlatformDOS,
- ADGF_UNSTABLE,
+ ADGF_NO_FLAGS,
GUIO6(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVES, GAMEOPTION_FADE_STYLE, GAMEOPTION_HELP_STYLE,
GAMEOPTION_PORTRAITS_ON, GAMEOPTION_WINDOW_STYLE)
},
@@ -68,7 +68,7 @@ static const SherlockGameDescription gameDescriptions[] = {
AD_LISTEND},
Common::DE_DEU,
Common::kPlatformDOS,
- ADGF_UNSTABLE,
+ ADGF_NO_FLAGS,
GUIO6(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVES, GAMEOPTION_FADE_STYLE, GAMEOPTION_HELP_STYLE,
GAMEOPTION_PORTRAITS_ON, GAMEOPTION_WINDOW_STYLE)
},
@@ -76,6 +76,24 @@ static const SherlockGameDescription gameDescriptions[] = {
},
{
+ // Case of the Serrated Scalpel - German
+ // Provided by max565
+ {
+ "scalpel",
+ 0, {
+ {"talk.lib", 0, "3d813fd8505b391a1f8b3a16b1aa7f2e", 284195},
+ {"music.lib", 0, "68ae2f7684ecf903bd60a00bb6bae195", 366465},
+ AD_LISTEND },
+ Common::DE_DEU,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO6(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVES, GAMEOPTION_FADE_STYLE, GAMEOPTION_HELP_STYLE,
+ GAMEOPTION_PORTRAITS_ON, GAMEOPTION_WINDOW_STYLE)
+ },
+ GType_SerratedScalpel,
+ },
+
+ {
// Case of the Serrated Scalpel - Spanish CD (from multilingual CD)
// Provided by m_kiewitz
{
@@ -86,7 +104,7 @@ static const SherlockGameDescription gameDescriptions[] = {
AD_LISTEND},
Common::ES_ESP,
Common::kPlatformDOS,
- ADGF_UNSTABLE,
+ ADGF_NO_FLAGS,
GUIO6(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVES, GAMEOPTION_FADE_STYLE, GAMEOPTION_HELP_STYLE,
GAMEOPTION_PORTRAITS_ON, GAMEOPTION_WINDOW_STYLE)
},
@@ -102,8 +120,7 @@ static const SherlockGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatform3DO,
ADGF_UNSTABLE,
- GUIO6(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVES, GAMEOPTION_FADE_STYLE, GAMEOPTION_HELP_STYLE,
- GAMEOPTION_PORTRAITS_ON, GAMEOPTION_WINDOW_STYLE)
+ GUIO4(GAMEOPTION_FADE_STYLE, GAMEOPTION_HELP_STYLE,GAMEOPTION_PORTRAITS_ON, GAMEOPTION_WINDOW_STYLE)
},
GType_SerratedScalpel,
},
@@ -117,7 +134,7 @@ static const SherlockGameDescription gameDescriptions[] = {
AD_ENTRY1s("talk.lib", "dbdc8a20c96900aa7e4d02f3fe8a274c", 121102),
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_UNSTABLE | ADGF_DEMO,
+ ADGF_DEMO,
GUIO1(GUIO_NOSPEECH)
},
GType_SerratedScalpel,
@@ -132,7 +149,7 @@ static const SherlockGameDescription gameDescriptions[] = {
AD_ENTRY1s("music.lib", "ec19a09b7fef6fd90b1ab812ce6e9739", 38563),
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_UNSTABLE | ADGF_DEMO,
+ ADGF_DEMO,
GUIO1(GUIO_NOSPEECH)
},
GType_SerratedScalpel,
@@ -145,9 +162,9 @@ static const SherlockGameDescription gameDescriptions[] = {
"rosetattoo",
"CD",
AD_ENTRY1s("talk.lib", "22e8e6406dd2fbbb238c9898928df42e", 770756),
- Common::EN_ANY,
+ Common::FR_FRA,
Common::kPlatformDOS,
- ADGF_UNSTABLE,
+ ADGF_NO_FLAGS,
GUIO3(GAMEOPTION_ORIGINAL_SAVES, GAMEOPTION_HELP_STYLE, GAMEOPTION_TRANSPARENT_WINDOWS)
},
GType_RoseTattoo
@@ -162,7 +179,7 @@ static const SherlockGameDescription gameDescriptions[] = {
AD_ENTRY1s("talk.lib", "9639a756b0993ebd71cb5f4d8b78b2dc", 765134),
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_UNSTABLE,
+ ADGF_NO_FLAGS,
GUIO3(GAMEOPTION_ORIGINAL_SAVES, GAMEOPTION_HELP_STYLE, GAMEOPTION_TRANSPARENT_WINDOWS)
},
GType_RoseTattoo,
@@ -177,7 +194,22 @@ static const SherlockGameDescription gameDescriptions[] = {
AD_ENTRY1s("talk.lib", "5027aa72f0d263ed3b1c764a6c397911", 873864),
Common::DE_DEU,
Common::kPlatformDOS,
- ADGF_UNSTABLE,
+ ADGF_NO_FLAGS,
+ GUIO3(GAMEOPTION_ORIGINAL_SAVES, GAMEOPTION_HELP_STYLE, GAMEOPTION_TRANSPARENT_WINDOWS)
+ },
+ GType_RoseTattoo,
+ },
+
+ {
+ // Case of the Rose Tattoo - Spanish CD
+ // Provided by dianiu
+ {
+ "rosetattoo",
+ "CD",
+ AD_ENTRY1s("talk.lib", "4f3ccf50e1012445624569cd605d7449", 783713),
+ Common::ES_ESP,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
GUIO3(GAMEOPTION_ORIGINAL_SAVES, GAMEOPTION_HELP_STYLE, GAMEOPTION_TRANSPARENT_WINDOWS)
},
GType_RoseTattoo,
diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp
index 079ea0e663..4b0b7dfb3f 100644
--- a/engines/sherlock/events.cpp
+++ b/engines/sherlock/events.cpp
@@ -28,6 +28,7 @@
#include "sherlock/sherlock.h"
#include "sherlock/events.h"
#include "sherlock/surface.h"
+#include "sherlock/tattoo/tattoo.h"
namespace Sherlock {
@@ -44,7 +45,7 @@ Events::Events(SherlockEngine *vm): _vm(vm) {
_oldButtons = _oldRightButton = false;
_firstPress = false;
_waitCounter = 0;
- _frameRate = 0;
+ _frameRate = GAME_FRAME_RATE;
if (_vm->_interactiveFl)
loadCursors("rmouse.vgs");
@@ -97,9 +98,27 @@ void Events::setCursor(const Graphics::Surface &src, int hotspotX, int hotspotY)
if (!IS_3DO) {
// PC 8-bit palettized
CursorMan.replaceCursor(src.getPixels(), src.w, src.h, hotspotX, hotspotY, 0xff);
+ } else if (!_vm->_isScreenDoubled) {
+ CursorMan.replaceCursor(src.getPixels(), src.w, src.h, hotspotX, hotspotY, 0x0000, false, &src.format);
} else {
+ Graphics::Surface tempSurface;
+ tempSurface.create(2 * src.w, 2 * src.h, src.format);
+
+ for (int y = 0; y < src.h; y++) {
+ const uint16 *srcP = (const uint16 *)src.getBasePtr(0, y);
+ uint16 *destP = (uint16 *)tempSurface.getBasePtr(0, 2 * y);
+ for (int x = 0; x < src.w; ++x, ++srcP, destP += 2) {
+ *destP = *srcP;
+ *(destP + 1) = *srcP;
+ *(destP + 2 * src.w) = *srcP;
+ *(destP + 2 * src.w + 1) = *srcP;
+ }
+ }
+
// 3DO RGB565
- CursorMan.replaceCursor(src.getPixels(), src.w, src.h, hotspotX, hotspotY, 0x0000, false, &src.format);
+ CursorMan.replaceCursor(tempSurface.getPixels(), tempSurface.w, tempSurface.h, 2 * hotspotX, 2 * hotspotY, 0x0000, false, &src.format);
+
+ tempSurface.free();
}
showCursor();
}
@@ -155,7 +174,8 @@ void Events::animateCursorIfNeeded() {
}
void Events::showCursor() {
- CursorMan.showMouse(true);
+ if (IS_SERRATED_SCALPEL || !static_cast<Tattoo::TattooEngine *>(_vm)->_runningProlog)
+ CursorMan.showMouse(true);
}
void Events::hideCursor() {
@@ -176,6 +196,8 @@ void Events::pollEvents() {
Common::Event event;
while (g_system->getEventManager()->pollEvent(event)) {
_mousePos = event.mouse;
+ if (_vm->_isScreenDoubled)
+ _mousePos = Common::Point(_mousePos.x / 2, _mousePos.y / 2);
// Handle events
switch (event.type) {
@@ -219,7 +241,11 @@ void Events::pollEventsAndWait() {
}
void Events::warpMouse(const Common::Point &pt) {
- _mousePos = pt - _vm->_screen->_currentScroll;
+ Common::Point pos = pt;
+ if (_vm->_isScreenDoubled)
+ pos = Common::Point(pt.x / 2, pt.y);
+
+ _mousePos = pos - _vm->_screen->_currentScroll;
g_system->warpMouse(_mousePos.x, _mousePos.y);
}
@@ -237,6 +263,10 @@ void Events::setFrameRate(int newRate) {
_frameRate = newRate;
}
+void Events::toggleSpeed() {
+ _frameRate = (_frameRate == GAME_FRAME_RATE) ? GAME_FRAME_RATE * 2 : GAME_FRAME_RATE;
+}
+
bool Events::checkForNextFrameCounter() {
// Check for next game frame
uint32 milli = g_system->getMillis();
@@ -320,7 +350,8 @@ bool Events::delay(uint32 time, bool interruptable) {
g_system->delayMillis(time);
bool result = !(interruptable && (kbHit() || _pressed || _vm->shouldQuit()));
- clearEvents();
+ if (interruptable)
+ clearEvents();
return result;
} else {
// For long periods go into a loop where we delay by 10ms at a time and then
diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h
index e13ef18822..711804dfdf 100644
--- a/engines/sherlock/events.h
+++ b/engines/sherlock/events.h
@@ -149,6 +149,11 @@ public:
void setFrameRate(int newRate);
/**
+ * Toggle between standard game speed and an "extra fast" mode
+ */
+ void toggleSpeed();
+
+ /**
* Return the current game frame number
*/
uint32 getFrameCounter() const { return _frameCounter; }
diff --git a/engines/sherlock/fonts.cpp b/engines/sherlock/fonts.cpp
index 482e795b6d..4d0991a47c 100644
--- a/engines/sherlock/fonts.cpp
+++ b/engines/sherlock/fonts.cpp
@@ -62,6 +62,43 @@ void Fonts::setFont(int fontNum) {
// load font data
_font = new ImageFile(fontFilename);
+
+ if (IS_SERRATED_SCALPEL) {
+ if (_vm->getLanguage() == Common::ES_ESP) {
+ if (_fontNumber == 1) {
+ // Create a new character - inverted exclamation mark (0x88)
+ // Seems this wasn't included originally, but some text has it
+ // This was obviously not done in the original game interpreter
+ ImageFrame &frameExclamationMark = (*_font)[0]; // get actual exclamation mark
+ ImageFrame frameRevExclamationMark;
+
+ frameRevExclamationMark._width = frameExclamationMark._width;
+ frameRevExclamationMark._height = frameExclamationMark._height;
+ frameRevExclamationMark._paletteBase = frameExclamationMark._paletteBase;
+ frameRevExclamationMark._rleEncoded = frameExclamationMark._rleEncoded;
+ frameRevExclamationMark._size = frameExclamationMark._size;
+ frameRevExclamationMark._frame.create(frameExclamationMark._width, frameExclamationMark._height, Graphics::PixelFormat::createFormatCLUT8());
+
+ byte *frameExclMarkPixels = (byte *)frameExclamationMark._frame.getPixels();
+ byte *frameRevExclMarkPixels = (byte *)frameRevExclamationMark._frame.getPixels();
+
+ uint16 revExclMarkY = frameExclamationMark._height - 1;
+ frameRevExclMarkPixels += frameExclamationMark._width * (frameExclamationMark._height - 1);
+ for (uint16 exclMarkY = 0; exclMarkY < frameExclamationMark._height; exclMarkY++) {
+ memcpy(frameRevExclMarkPixels, frameExclMarkPixels, frameExclamationMark._width);
+ revExclMarkY--;
+ frameRevExclMarkPixels -= frameExclamationMark._width;
+ frameExclMarkPixels += frameExclamationMark._width;
+ }
+
+ frameRevExclamationMark._offset.x = frameExclamationMark._offset.x;
+ frameRevExclamationMark._offset.y = frameExclamationMark._offset.y + 1;
+
+ _font->push_back(frameRevExclamationMark);
+ }
+ }
+ }
+
} else {
// 3DO
switch (fontNum) {
@@ -81,7 +118,7 @@ void Fonts::setFont(int fontNum) {
}
_charCount = _font->size();
-
+
// Iterate through the frames to find the widest and tallest font characters
_fontHeight = _widestChar = 0;
for (uint idx = 0; idx < _charCount; ++idx) {
@@ -118,6 +155,24 @@ inline byte Fonts::translateChar(byte c) {
return 135; // and this for SH1
default:
if (IS_SERRATED_SCALPEL) {
+ if (_vm->getLanguage() == Common::ES_ESP) {
+ if (_fontNumber == 1) {
+ // Special workarounds for translated game text, which was skipped because of effectively a bug
+ // This was not done in the original interpreter
+ // It seems at least the inverted exclamation mark was skipped by the original interpreter /
+ // wasn't shown at all.
+ // This character is used for example in the alley room, when talking with the inspector after
+ // searching the corpse. "[0xAD]Claro! Mi experiencia profesional revela que esta mujer fue asesinada..."
+ // The same text gets put inside Watson's journal as well and should be on page 10 right after
+ // talking with the inspector. For further study see bug #6931
+ // Inverted question mark was also skipped, but at least that character is inside the font already.
+ if (c == 0xAD) {
+ // inverted exclamation mark
+ return 0x88; // our own font character, created during setFont()
+ }
+ // Inverted question mask is 0x86 (mapped from 0x88)
+ }
+ }
if (c >= 0x80) { // German SH1 version did this, but not German SH2
c--;
}
@@ -147,10 +202,13 @@ void Fonts::writeString(Surface *surface, const Common::String &str,
}
curChar = translateChar(curChar);
- assert(curChar < _charCount);
- ImageFrame &frame = (*_font)[curChar];
- surface->transBlitFrom(frame, Common::Point(charPos.x, charPos.y + _yOffsets[curChar]), false, overrideColor);
- charPos.x += frame._frame.w + 1;
+ if (curChar < _charCount) {
+ ImageFrame &frame = (*_font)[curChar];
+ surface->transBlitFrom(frame, Common::Point(charPos.x, charPos.y + _yOffsets[curChar]), false, overrideColor);
+ charPos.x += frame._frame.w + 1;
+ } else {
+ warning("Invalid character encountered - %d", (int)curChar);
+ }
}
}
diff --git a/engines/sherlock/image_file.cpp b/engines/sherlock/image_file.cpp
index 3d881eb655..971980a2ac 100644
--- a/engines/sherlock/image_file.cpp
+++ b/engines/sherlock/image_file.cpp
@@ -961,59 +961,57 @@ void ImageFile3DO::loadFont(Common::SeekableReadStream &stream) {
for (curChar = 33; curChar < header_charCount; curChar++) {
// create frame
- {
- ImageFrame imageFrame;
-
- imageFrame._width = widthTablePtr[curChar];
- imageFrame._height = header_fontHeight;
- imageFrame._paletteBase = 0;
- imageFrame._offset.x = 0;
- imageFrame._offset.y = 0;
- imageFrame._rleEncoded = false;
- imageFrame._size = 0;
-
- // Extract pixels
- imageFrame._frame.create(imageFrame._width, imageFrame._height, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
- uint16 *dest = (uint16 *)imageFrame._frame.getPixels();
- Common::fill(dest, dest + imageFrame._width * imageFrame._height, 0);
-
- curCharHeightLeft = header_fontHeight;
- while (curCharHeightLeft) {
- curCharWidthLeft = widthTablePtr[curChar];
- curBitsPtr = curBitsLinePtr;
- curBitsLeft = 8;
- curPosX = 0;
-
- while (curCharWidthLeft) {
- if (!(curPosX & 1)) {
- curBits = *curBitsPtr >> 4;
- } else {
- curBits = *curBitsPtr & 0x0F;
- curBitsPtr++;
- }
- // doing this properly is complicated
- // the 3DO has built-in anti-aliasing
- // this here at least results in somewhat readable text
- // TODO: make it better
- if (curBits) {
- curBitsReversed = (curBits >> 3) | ((curBits & 0x04) >> 1) | ((curBits & 0x02) << 1) | ((curBits & 0x01) << 3);
- curBits = 20 - curBits;
- }
-
- byte curIntensity = curBits;
- *dest = (curIntensity << 11) | (curIntensity << 6) | curIntensity;
- dest++;
-
- curCharWidthLeft--;
- curPosX++;
+ ImageFrame imageFrame;
+
+ imageFrame._width = widthTablePtr[curChar];
+ imageFrame._height = header_fontHeight;
+ imageFrame._paletteBase = 0;
+ imageFrame._offset.x = 0;
+ imageFrame._offset.y = 0;
+ imageFrame._rleEncoded = false;
+ imageFrame._size = 0;
+
+ // Extract pixels
+ imageFrame._frame.create(imageFrame._width, imageFrame._height, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
+ uint16 *dest = (uint16 *)imageFrame._frame.getPixels();
+ Common::fill(dest, dest + imageFrame._width * imageFrame._height, 0);
+
+ curCharHeightLeft = header_fontHeight;
+ while (curCharHeightLeft) {
+ curCharWidthLeft = widthTablePtr[curChar];
+ curBitsPtr = curBitsLinePtr;
+ curBitsLeft = 8;
+ curPosX = 0;
+
+ while (curCharWidthLeft) {
+ if (!(curPosX & 1)) {
+ curBits = *curBitsPtr >> 4;
+ } else {
+ curBits = *curBitsPtr & 0x0F;
+ curBitsPtr++;
+ }
+ // doing this properly is complicated
+ // the 3DO has built-in anti-aliasing
+ // this here at least results in somewhat readable text
+ // TODO: make it better
+ if (curBits) {
+ curBitsReversed = (curBits >> 3) | ((curBits & 0x04) >> 1) | ((curBits & 0x02) << 1) | ((curBits & 0x01) << 3);
+ curBits = 20 - curBits;
}
- curCharHeightLeft--;
- curBitsLinePtr += header_bytesPerLine;
+ byte curIntensity = curBits;
+ *dest = (curIntensity << 11) | (curIntensity << 6) | curIntensity;
+ dest++;
+
+ curCharWidthLeft--;
+ curPosX++;
}
- push_back(imageFrame);
+ curCharHeightLeft--;
+ curBitsLinePtr += header_bytesPerLine;
}
+
+ push_back(imageFrame);
}
// Warning below being used to silence unused variable warnings for now
@@ -1051,10 +1049,12 @@ void StreamingImageFile::close() {
_stream = nullptr;
_frameNumber = -1;
_active = false;
+ _imageFrame._frame.free();
}
bool StreamingImageFile::getNextFrame() {
// Don't proceed if we're already at the end of the stream
+ assert(_stream);
if (_stream->pos() >= _stream->size()) {
_active = false;
return false;
@@ -1081,6 +1081,9 @@ bool StreamingImageFile::getNextFrame() {
_imageFrame._size = frameStream->readUint16LE() - 11;
_imageFrame._rleMarker = frameStream->readByte();
+ // Free the previous frame
+ _imageFrame._frame.free();
+
// Decode the frame
if (_compressed) {
delete frameStream;
diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp
index 334cc05abf..e443b6f727 100644
--- a/engines/sherlock/journal.cpp
+++ b/engines/sherlock/journal.cpp
@@ -24,6 +24,7 @@
#include "sherlock/scalpel/scalpel.h"
#include "sherlock/scalpel/scalpel_fixed_text.h"
#include "sherlock/scalpel/scalpel_journal.h"
+#include "sherlock/scalpel/scalpel_talk.h"
#include "sherlock/tattoo/tattoo.h"
#include "sherlock/tattoo/tattoo_fixed_text.h"
#include "sherlock/tattoo/tattoo_journal.h"
@@ -250,7 +251,7 @@ bool Journal::drawJournal(int direction, int howFar) {
// Print out the found keyword
Common::String lineMatch(matchP, matchP + _find.size());
- byte fgColor = IS_SERRATED_SCALPEL ? (byte)Scalpel::INV_FOREGROUND : (byte)Tattoo::INV_FOREGROUND;
+ byte fgColor = IS_SERRATED_SCALPEL ? (byte)Scalpel::INV_FOREGROUND : (byte)Tattoo::PEN_HIGHLIGHT_COLOR;
screen.gPrint(Common::Point(JOURNAL_LEFT_X + width, yp), fgColor, "%s", lineMatch.c_str());
width += screen.stringWidth(lineMatch.c_str());
@@ -485,9 +486,9 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
// Copy text from the place until either the reply ends, a comment
// {} block is started, or a control character is encountered
journalString += c;
- do {
+ while (*replyP && *replyP < opcodes[0] && *replyP != '{' && *replyP != '}') {
journalString += *replyP++;
- } while (*replyP && *replyP < opcodes[0] && *replyP != '{' && *replyP != '}');
+ }
commentJustPrinted = false;
}
@@ -525,6 +526,9 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
else
journalString += people._characters[c]._name;
+ if (IS_SERRATED_SCALPEL && _vm->getLanguage() == Common::DE_DEU)
+ Scalpel::ScalpelTalk::skipBadText(replyP);
+
const byte *strP = replyP;
byte v;
do {
diff --git a/engines/sherlock/music.cpp b/engines/sherlock/music.cpp
index 7802bf5eeb..8b8f359de3 100644
--- a/engines/sherlock/music.cpp
+++ b/engines/sherlock/music.cpp
@@ -225,6 +225,7 @@ Music::Music(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
_musicOn = false;
_midiOption = false;
_musicVolume = 0;
+ _midiMusicData = nullptr;
if (IS_3DO) {
// 3DO - uses digital samples for music
@@ -397,6 +398,7 @@ bool Music::playMusic(const Common::String &name) {
if (!_musicOn)
return false;
+ _nextSongName = _currentSongName = name;
debugC(kDebugLevelMusic, "Music: playMusic('%s')", name.c_str());
if (!IS_3DO) {
@@ -469,8 +471,8 @@ bool Music::playMusic(const Common::String &name) {
}
}
+ _midiMusicData = midiMusicData;
_midiParser->loadMusic(midiMusicData, midiMusicDataSize);
-
} else {
// 3DO: sample based
Audio::AudioStream *musicStream;
@@ -516,6 +518,8 @@ void Music::freeSong() {
_midiParser->unloadMusic();
}
+ delete[] _midiMusicData;
+ _midiMusicData = nullptr;
_musicPlaying = false;
}
@@ -613,4 +617,10 @@ void Music::getSongNames(Common::StringArray &songs) {
Common::sort(songs.begin(), songs.end());
}
+void Music::checkSongProgress() {
+ if (!isPlaying()) {
+ playMusic(_nextSongName);
+ }
+}
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/music.h b/engines/sherlock/music.h
index afd3a429be..186e2aa2dc 100644
--- a/engines/sherlock/music.h
+++ b/engines/sherlock/music.h
@@ -68,6 +68,7 @@ private:
MidiDriver *_midiDriver;
Audio::SoundHandle _digitalMusicHandle;
MusicType _musicType;
+ byte *_midiMusicData;
/**
* Play the specified music resource
@@ -127,6 +128,12 @@ public:
* Gets the names of all the songs in the game. Used by the debugger.
*/
void getSongNames(Common::StringArray &songs);
+
+ /**
+ * Checks to see if the currently playing song has finished, then the music specified
+ * in _nextSongName will be started
+ */
+ void checkSongProgress();
};
} // End of namespace Sherlock
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index 093f666a46..e70b707404 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -539,7 +539,7 @@ int BaseObject::checkNameForCodes(const Common::String &name, FixedTextActionId
// G: Have object go somewhere
// A: Add onto existing co-ordinates
Common::String sx(name.c_str() + 2, name.c_str() + 5);
- Common::String sy(name.c_str() + 6, name.c_str() + 9);
+ Common::String sy(name.c_str() + 5, name.c_str() + 8);
if (ch == 'G')
_position = Common::Point(atoi(sx.c_str()), atoi(sy.c_str()));
@@ -620,6 +620,7 @@ void Sprite::clear() {
_images = nullptr;
_imageFrame = nullptr;
_walkCount = 0;
+ _oldWalkSequence = 0;
_allow = 0;
_frameNumber = 0;
_position.x = _position.y = 0;
@@ -634,6 +635,7 @@ void Sprite::clear() {
_misc = 0;
_altImages = nullptr;
_altSeq = 0;
+ _centerWalk = 0;
Common::fill(&_stopFrames[0], &_stopFrames[8], (ImageFrame *)nullptr);
}
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp
index b1f4abba47..8057e26204 100644
--- a/engines/sherlock/people.cpp
+++ b/engines/sherlock/people.cpp
@@ -184,8 +184,9 @@ void People::reset() {
Person &p = *_data[idx];
if (IS_SERRATED_SCALPEL) {
- p._type = CHARACTER;
- p._position = Point32(100 * FIXED_INT_MULTIPLIER, 110 * FIXED_INT_MULTIPLIER);
+ p._type = _holmesOn ? CHARACTER : HIDDEN;
+ if (!saves._justLoaded)
+ p._position = Point32(100 * FIXED_INT_MULTIPLIER, 110 * FIXED_INT_MULTIPLIER);
} else if (!talk._scriptMoreFlag && !saves._justLoaded) {
p._type = (idx == 0) ? CHARACTER : INVALID;
p._position = Point32(36 * FIXED_INT_MULTIPLIER, 29 * FIXED_INT_MULTIPLIER);
diff --git a/engines/sherlock/scalpel/3do/movie_decoder.cpp b/engines/sherlock/scalpel/3do/movie_decoder.cpp
index 8e8f99bc19..da4d08ca47 100644
--- a/engines/sherlock/scalpel/3do/movie_decoder.cpp
+++ b/engines/sherlock/scalpel/3do/movie_decoder.cpp
@@ -464,47 +464,4 @@ Audio::AudioStream *Scalpel3DOMovieDecoder::StreamAudioTrack::getAudioStream() c
return _audioStream;
}
-// Test-code
-
-// Code for showing a movie. Only meant for testing/debug purposes
-bool Scalpel3DOMoviePlay(const char *filename, Common::Point pos) {
- Scalpel3DOMovieDecoder *videoDecoder = new Scalpel3DOMovieDecoder();
-
- if (!videoDecoder->loadFile(filename)) {
- warning("Scalpel3DOMoviePlay: could not open '%s'", filename);
- return false;
- }
-
- bool skipVideo = false;
- //byte bytesPerPixel = videoDecoder->getPixelFormat().bytesPerPixel;
- uint16 width = videoDecoder->getWidth();
- uint16 height = videoDecoder->getHeight();
- //uint16 pitch = videoDecoder->getWidth() * bytesPerPixel;
-
- videoDecoder->start();
-
- while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && (!skipVideo)) {
- if (videoDecoder->needsUpdate()) {
- const Graphics::Surface *frame = videoDecoder->decodeNextFrame();
-
- if (frame) {
- g_system->copyRectToScreen(frame->getPixels(), frame->pitch, pos.x, pos.y, width, height);
- g_system->updateScreen();
- }
- }
-
- Common::Event event;
- while (g_system->getEventManager()->pollEvent(event)) {
- if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE))
- skipVideo = true;
- }
-
- g_system->delayMillis(10);
- }
- videoDecoder->close();
- delete videoDecoder;
-
- return !skipVideo;
-}
-
} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/3do/movie_decoder.h b/engines/sherlock/scalpel/3do/movie_decoder.h
index 9f1670fc6c..73b125443b 100644
--- a/engines/sherlock/scalpel/3do/movie_decoder.h
+++ b/engines/sherlock/scalpel/3do/movie_decoder.h
@@ -119,9 +119,6 @@ private:
StreamAudioTrack *_audioTrack;
};
-// Testing
-extern bool Scalpel3DOMoviePlay(const char *filename, Common::Point pos);
-
} // End of namespace Sherlock
#endif
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index c3915a1cf2..b17f38b218 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -21,16 +21,18 @@
*/
#include "engines/util.h"
+#include "gui/saveload.h"
+#include "common/translation.h"
#include "sherlock/scalpel/scalpel.h"
#include "sherlock/scalpel/scalpel_fixed_text.h"
#include "sherlock/scalpel/scalpel_map.h"
#include "sherlock/scalpel/scalpel_people.h"
#include "sherlock/scalpel/scalpel_scene.h"
+#include "sherlock/scalpel/scalpel_screen.h"
#include "sherlock/scalpel/tsage/logo.h"
#include "sherlock/sherlock.h"
#include "sherlock/music.h"
#include "sherlock/animation.h"
-// for 3DO
#include "sherlock/scalpel/3do/movie_decoder.h"
namespace Sherlock {
@@ -100,103 +102,177 @@ static const byte MAP_SEQUENCES[3][MAX_FRAME] = {
struct PeopleData {
const char *portrait;
- const char *name;
+ int fixedTextId;
byte stillSequences[MAX_TALK_SEQUENCES];
byte talkSequences[MAX_TALK_SEQUENCES];
};
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 } }
+ { "HOLM", kFixedText_People_SherlockHolmes, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "WATS", kFixedText_People_DrWatson, { 6, 0, 0 }, { 5, 5, 6, 7, 8, 7, 8, 6, 0, 0 } },
+ { "LEST", kFixedText_People_InspectorLestrade, { 4, 0, 0 }, { 2, 0, 0 } },
+ { "CON1", kFixedText_People_ConstableOBrien, { 2, 0, 0 }, { 1, 0, 0 } },
+ { "CON2", kFixedText_People_ConstableLewis, { 2, 0, 0 }, { 1, 0, 0 } },
+ { "SHEI", kFixedText_People_SheilaParker, { 2, 0, 0 }, { 2, 3, 0, 0 } },
+ { "HENR", kFixedText_People_HenryCarruthers, { 3, 0, 0 }, { 3, 0, 0 } },
+ { "LESL", kFixedText_People_Lesley, { 9, 0, 0 }, { 1, 2, 3, 2, 1, 2, 3, 0, 0 } },
+ { "USH1", kFixedText_People_AnUsher, { 13, 0, 0 }, { 13, 14, 0, 0 } },
+ { "USH2", kFixedText_People_AnUsher, { 2, 0, 0 }, { 2, 0, 0 } },
+ { "FRED", kFixedText_People_FredrickEpstein, { 4, 0, 0 }, { 1, 2, 3, 4, 3, 4, 3, 2, 0, 0 } },
+ { "WORT", kFixedText_People_MrsWorthington, { 9, 0, 0 }, { 8, 0, 0 } },
+ { "COAC", kFixedText_People_TheCoach, { 2, 0, 0 }, { 1, 2, 3, 4, 5, 4, 3, 2, 0, 0 } },
+ { "PLAY", kFixedText_People_APlayer, { 8, 0, 0 }, { 7, 8, 0, 0 } },
+ { "WBOY", kFixedText_People_Tim, { 13, 0, 0 }, { 12, 13, 0, 0 } },
+ { "JAME", kFixedText_People_JamesSanders, { 6, 0, 0 }, { 3, 4, 0, 0 } },
+ { "BELL", kFixedText_People_Belle, { 1, 0, 0 }, { 4, 5, 0, 0 } },
+ { "GIRL", kFixedText_People_CleaningGirl, { 20, 0, 0 }, { 14, 15, 16, 17, 18, 19, 20, 20, 20, 0, 0 } },
+ { "EPST", kFixedText_People_FredrickEpstein, { 17, 0, 0 }, { 16, 17, 18, 18, 18, 17, 17, 0, 0 } },
+ { "WIGG", kFixedText_People_Wiggins, { 3, 0, 0 }, { 2, 3, 0, 0 } },
+ { "PAUL", kFixedText_People_Paul, { 2, 0, 0 }, { 1, 2, 0, 0 } },
+ { "BART", kFixedText_People_TheBartender, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "DIRT", kFixedText_People_ADirtyDrunk, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "SHOU", kFixedText_People_AShoutingDrunk, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "STAG", kFixedText_People_AStaggeringDrunk, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "BOUN", kFixedText_People_TheBouncer, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "SAND", kFixedText_People_JamesSanders, { 6, 0, 0 }, { 5, 6, 0, 0 } },
+ { "CORO", kFixedText_People_TheCoroner, { 6, 0, 0 }, { 4, 5, 0, 0 } },
+ { "EQUE", kFixedText_People_ReginaldSnipes, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "GEOR", kFixedText_People_GeorgeBlackwood, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "LARS", kFixedText_People_Lars, { 7, 0, 0 }, { 5, 6, 0, 0 } },
+ { "PARK", kFixedText_People_SheilaParker, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "CHEM", kFixedText_People_TheChemist, { 8, 0, 0 }, { 8, 9, 0, 0 } },
+ { "GREG", kFixedText_People_InspectorGregson, { 6, 0, 0 }, { 5, 6, 0, 0 } },
+ { "LAWY", kFixedText_People_JacobFarthington, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "MYCR", kFixedText_People_Mycroft, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "SHER", kFixedText_People_OldSherman, { 7, 0, 0 }, { 7, 8, 0, 0 } },
+ { "CHMB", kFixedText_People_Richard, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "BARM", kFixedText_People_TheBarman, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "DAND", kFixedText_People_ADandyPlayer, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "ROUG", kFixedText_People_ARoughlookingPlayer, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "SPEC", kFixedText_People_ASpectator, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "HUNT", kFixedText_People_RobertHunt, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "VIOL", kFixedText_People_Violet, { 3, 0, 0 }, { 3, 4, 0, 0 } },
+ { "PETT", kFixedText_People_Pettigrew, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "APPL", kFixedText_People_Augie, { 8, 0, 0 }, { 14, 15, 0, 0 } },
+ { "ANNA", kFixedText_People_AnnaCarroway, { 16, 0, 0 }, { 3, 4, 5, 6, 0, 0 } },
+ { "GUAR", kFixedText_People_AGuard, { 1, 0, 0 }, { 4, 5, 6, 0, 0 } },
+ { "ANTO", kFixedText_People_AntonioCaruso, { 8, 0, 0 }, { 7, 8, 0, 0 } },
+ { "TOBY", kFixedText_People_TobyTheDog, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "KING", kFixedText_People_SimonKingsley, { 13, 0, 0 }, { 13, 14, 0, 0 } },
+ { "ALFR", kFixedText_People_Alfred, { 2, 0, 0 }, { 2, 3, 0, 0 } },
+ { "LADY", kFixedText_People_LadyBrumwell, { 1, 0, 0 }, { 3, 4, 0, 0 } },
+ { "ROSA", kFixedText_People_MadameRosa, { 1, 0, 0 }, { 1, 30, 0, 0 } },
+ { "LADB", kFixedText_People_LadyBrumwell, { 1, 0, 0 }, { 3, 4, 0, 0 } },
+ { "MOOR", kFixedText_People_JosephMoorehead, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "BEAL", kFixedText_People_MrsBeale, { 5, 0, 0 }, { 14, 15, 16, 17, 18, 19, 20, 0, 0 } },
+ { "LION", kFixedText_People_Felix, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "HOLL", kFixedText_People_Hollingston, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "CALL", kFixedText_People_ConstableCallaghan, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "JERE", kFixedText_People_SergeantDuncan, { 2, 0, 0 }, { 1, 1, 2, 2, 0, 0 } },
+ { "LORD", kFixedText_People_LordBrumwell, { 1, 0, 0 }, { 9, 10, 0, 0 } },
+ { "NIGE", kFixedText_People_NigelJaimeson, { 1, 0, 0 }, { 1, 2, 0, 138, 3, 4, 0, 138, 0, 0 } },
+ { "JONA", kFixedText_People_Jonas, { 1, 0, 0 }, { 1, 8, 0, 0 } },
+ { "DUGA", kFixedText_People_ConstableDugan, { 1, 0, 0 }, { 1, 0, 0 } },
+ { "INSP", kFixedText_People_InspectorLestrade, { 4, 0, 0 }, { 2, 0, 0 } }
};
+uint INFO_BLACK;
+uint BORDER_COLOR;
+uint COMMAND_BACKGROUND;
+uint BUTTON_BACKGROUND;
+uint TALK_FOREGROUND;
+uint TALK_NULL;
+uint BUTTON_TOP;
+uint BUTTON_MIDDLE;
+uint BUTTON_BOTTOM;
+uint COMMAND_FOREGROUND;
+uint COMMAND_HIGHLIGHTED;
+uint COMMAND_NULL;
+uint INFO_FOREGROUND;
+uint INFO_BACKGROUND;
+uint INV_FOREGROUND;
+uint INV_BACKGROUND;
+uint PEN_COLOR;
+
/*----------------------------------------------------------------*/
+#define FROM_RGB(r, g, b) pixelFormatRGB565.RGBToColor(r, g, b)
+
ScalpelEngine::ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc) :
SherlockEngine(syst, gameDesc) {
_darts = nullptr;
_mapResult = 0;
+
+ if (getPlatform() == Common::kPlatform3DO) {
+ const Graphics::PixelFormat pixelFormatRGB565 = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
+ INFO_BLACK = FROM_RGB(0, 0, 0);
+ BORDER_COLOR = FROM_RGB(0x6d, 0x38, 0x10);
+ COMMAND_BACKGROUND = FROM_RGB(0x38, 0x38, 0xce);
+ BUTTON_BACKGROUND = FROM_RGB(0x95, 0x5d, 0x24);
+ TALK_FOREGROUND = FROM_RGB(0xff, 0x55, 0x55);
+ TALK_NULL = FROM_RGB(0xce, 0xc6, 0xc2);
+ BUTTON_TOP = FROM_RGB(0xbe, 0x85, 0x3c);
+ BUTTON_MIDDLE = FROM_RGB(0x9d, 0x40, 0);
+ BUTTON_BOTTOM = FROM_RGB(0x69, 0x24, 0);
+ COMMAND_FOREGROUND = FROM_RGB(0xFF, 0xFF, 0xFF);
+ COMMAND_HIGHLIGHTED = FROM_RGB(0x55, 0xff, 0x55);
+ COMMAND_NULL = FROM_RGB(0x69, 0x24, 0);
+ INFO_FOREGROUND = FROM_RGB(0x55, 0xff, 0xff);
+ INFO_BACKGROUND = FROM_RGB(0, 0, 0x48);
+ INV_FOREGROUND = FROM_RGB(0xff, 0xff, 0x55);
+ INV_BACKGROUND = FROM_RGB(0, 0, 0x48);
+ PEN_COLOR = FROM_RGB(0x50, 0x18, 0);
+ } else {
+ INFO_BLACK = 1;
+ BORDER_COLOR = 237;
+ COMMAND_BACKGROUND = 4;
+ BUTTON_BACKGROUND = 235;
+ TALK_FOREGROUND = 12;
+ TALK_NULL = 16;
+ BUTTON_TOP = 233;
+ BUTTON_MIDDLE = 244;
+ BUTTON_BOTTOM = 248;
+ COMMAND_FOREGROUND = 15;
+ COMMAND_HIGHLIGHTED = 10;
+ COMMAND_NULL = 248;
+ INFO_FOREGROUND = 11;
+ INFO_BACKGROUND = 1;
+ INV_FOREGROUND = 14;
+ INV_BACKGROUND = 1;
+ PEN_COLOR = 250;
+ }
}
ScalpelEngine::~ScalpelEngine() {
delete _darts;
}
-void ScalpelEngine::initialize() {
- // 3DO actually uses RGB555, but some platforms of ours only support RGB565, so we use that
-
- if (getPlatform() == Common::kPlatform3DO) {
- const Graphics::PixelFormat pixelFormatRGB565 = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
- // 320x200 16-bit RGB565 for 3DO support
- initGraphics(320, 200, false, &pixelFormatRGB565);
- } else {
+void ScalpelEngine::setupGraphics() {
+ if (getPlatform() != Common::kPlatform3DO) {
// 320x200 palettized
initGraphics(320, 200, false);
+ } else {
+ // 3DO actually uses RGB555, but some platforms of ours only support RGB565, so we use that
+ const Graphics::PixelFormat pixelFormatRGB565 = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
+
+ // First try for a 640x400 mode
+ g_system->beginGFXTransaction();
+ initCommonGFX(true);
+ g_system->initSize(640, 400, &pixelFormatRGB565);
+ OSystem::TransactionError gfxError = g_system->endGFXTransaction();
+
+ if (gfxError == OSystem::kTransactionSuccess) {
+ _isScreenDoubled = true;
+ } else {
+ // System doesn't support it, so fall back on 320x200 mode
+ initGraphics(320, 200, false, &pixelFormatRGB565);
+ }
}
+}
+
+void ScalpelEngine::initialize() {
+ // Setup graphics mode
+ setupGraphics();
// Let the base engine intialize
SherlockEngine::initialize();
@@ -219,9 +295,14 @@ void ScalpelEngine::initialize() {
loadInventory();
// Set up list of people
- for (int idx = 0; idx < MAX_PEOPLE; ++idx)
- _people->_characters.push_back(PersonData(PEOPLE_DATA[idx].name, PEOPLE_DATA[idx].portrait,
+ ScalpelFixedText &fixedText = *(ScalpelFixedText *)_fixedText;
+ const char *peopleNamePtr = nullptr;
+
+ for (int idx = 0; idx < MAX_PEOPLE; ++idx) {
+ peopleNamePtr = fixedText.getText(PEOPLE_DATA[idx].fixedTextId);
+ _people->_characters.push_back(PersonData(peopleNamePtr, 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);
@@ -599,7 +680,7 @@ bool ScalpelEngine::show3DOSplash() {
if (finished) {
// EA logo movie
- Scalpel3DOMoviePlay("EAlogo.stream", Common::Point(20, 0));
+ play3doMovie("EAlogo.stream", Common::Point(20, 0));
}
// Always clear screen
@@ -608,23 +689,25 @@ bool ScalpelEngine::show3DOSplash() {
}
bool ScalpelEngine::showCityCutscene3DO() {
+ Scalpel3DOScreen &screen = *(Scalpel3DOScreen *)_screen;
_animation->_soundLibraryFilename = "TITLE.SND";
- _screen->clear();
+ screen.clear();
bool finished = _events->delay(2500, true);
- // rain.aiff seems to be playing in an endless loop until
- // sherlock logo fades away TODO
-
if (finished) {
finished = _events->delay(2500, true);
// Play intro music
_music->loadSong("prolog");
+ // Loop rain.aiff until the Sherlock logo fades away.
+ // TODO: The volume is just a guess.
+ _sound->playAiff("prologue/sounds/rain.aiff", 15, true);
+
// Fade screen to grey
- _screen->_backBuffer1.fill(0xCE59); // RGB565: 25, 50, 25 (grey)
- _screen->fadeIntoScreen3DO(2);
+ screen._backBuffer1.fill(0xCE59); // RGB565: 25, 50, 25 (grey)
+ screen.fadeIntoScreen3DO(2);
}
if (finished) {
@@ -632,33 +715,33 @@ bool ScalpelEngine::showCityCutscene3DO() {
}
if (finished) {
- _screen->_backBuffer1.fill(0); // fill backbuffer with black to avoid issues during fade from white
+ screen._backBuffer1.fill(0); // fill backbuffer with black to avoid issues during fade from white
finished = _animation->play3DO("26open1", true, 1, true, 2);
}
if (finished) {
- _screen->_backBuffer1.blitFrom(*_screen); // save into backbuffer 1, used for fade
- _screen->_backBuffer2.blitFrom(*_screen); // save into backbuffer 2, for restoring later
+ screen._backBuffer2.blitFrom(screen._backBuffer1);
// "London, England"
ImageFile3DO titleImage_London("title2a.cel", kImageFile3DOType_Cel);
- _screen->_backBuffer1.transBlitFrom(titleImage_London[0]._frame, Common::Point(30, 50));
+ screen._backBuffer1.transBlitFrom(titleImage_London[0]._frame, Common::Point(30, 50));
- _screen->fadeIntoScreen3DO(1);
+ screen.fadeIntoScreen3DO(1);
finished = _events->delay(1500, true);
if (finished) {
// "November, 1888"
ImageFile3DO titleImage_November("title2b.cel", kImageFile3DOType_Cel);
- _screen->_backBuffer1.transBlitFrom(titleImage_November[0]._frame, Common::Point(100, 100));
+ screen._backBuffer1.transBlitFrom(titleImage_November[0]._frame, Common::Point(100, 100));
- _screen->fadeIntoScreen3DO(1);
+ screen.fadeIntoScreen3DO(1);
finished = _music->waitUntilMSec(14700, 0, 0, 5000);
}
if (finished) {
// Restore screen
- _screen->blitFrom(_screen->_backBuffer2);
+ _screen->_backBuffer1.blitFrom(screen._backBuffer2);
+ _screen->blitFrom(screen._backBuffer1);
}
}
@@ -666,21 +749,19 @@ bool ScalpelEngine::showCityCutscene3DO() {
finished = _animation->play3DO("26open2", true, 1, false, 2);
if (finished) {
- _screen->_backBuffer1.blitFrom(*_screen); // save into backbuffer 1, used for fade
-
// "Sherlock Holmes" (title)
ImageFile3DO titleImage_SherlockHolmesTitle("title1ab.cel", kImageFile3DOType_Cel);
- _screen->_backBuffer1.transBlitFrom(titleImage_SherlockHolmesTitle[0]._frame, Common::Point(34, 5));
+ screen._backBuffer1.transBlitFrom(titleImage_SherlockHolmesTitle[0]._frame, Common::Point(34, 5));
// Blend in
- _screen->fadeIntoScreen3DO(2);
+ screen.fadeIntoScreen3DO(2);
finished = _events->delay(500, true);
// Title should fade in, Copyright should be displayed a bit after that
if (finished) {
ImageFile3DO titleImage_Copyright("title1c.cel", kImageFile3DOType_Cel);
- _screen->transBlitFrom(titleImage_Copyright[0]._frame, Common::Point(20, 190));
+ screen.transBlitFrom(titleImage_Copyright[0]._frame, Common::Point(20, 190));
finished = _events->delay(3500, true);
}
}
@@ -688,29 +769,32 @@ bool ScalpelEngine::showCityCutscene3DO() {
if (finished)
finished = _music->waitUntilMSec(33600, 0, 0, 2000);
+ _sound->stopAiff();
+
if (finished) {
// Fade to black
- _screen->_backBuffer1.clear();
- _screen->fadeIntoScreen3DO(3);
+ screen._backBuffer1.clear();
+ screen.fadeIntoScreen3DO(3);
}
if (finished) {
// "In the alley behind the Regency Theatre..."
ImageFile3DO titleImage_InTheAlley("title1d.cel", kImageFile3DOType_Cel);
- _screen->_backBuffer1.transBlitFrom(titleImage_InTheAlley[0]._frame, Common::Point(72, 51));
+ screen._backBuffer1.transBlitFrom(titleImage_InTheAlley[0]._frame, Common::Point(72, 51));
// Fade in
- _screen->fadeIntoScreen3DO(4);
+ screen.fadeIntoScreen3DO(4);
finished = _music->waitUntilMSec(39900, 0, 0, 2500);
// Fade out
- _screen->_backBuffer1.clear();
- _screen->fadeIntoScreen3DO(4);
+ screen._backBuffer1.clear();
+ screen.fadeIntoScreen3DO(4);
}
return finished;
}
bool ScalpelEngine::showAlleyCutscene3DO() {
+ Scalpel3DOScreen &screen = *(Scalpel3DOScreen *)_screen;
bool finished = _music->waitUntilMSec(43500, 0, 0, 1000);
if (finished)
@@ -718,8 +802,8 @@ bool ScalpelEngine::showAlleyCutscene3DO() {
if (finished) {
// Fade out...
- _screen->_backBuffer1.clear();
- _screen->fadeIntoScreen3DO(3);
+ screen._backBuffer1.clear();
+ screen.fadeIntoScreen3DO(3);
finished = _music->waitUntilMSec(67100, 0, 0, 1000); // 66700
}
@@ -734,8 +818,8 @@ bool ScalpelEngine::showAlleyCutscene3DO() {
// Show screaming victim
ImageFile3DO titleImage_ScreamingVictim("scream.cel", kImageFile3DOType_Cel);
- _screen->clear();
- _screen->transBlitFrom(titleImage_ScreamingVictim[0]._frame, Common::Point(0, 0));
+ screen.clear();
+ screen.transBlitFrom(titleImage_ScreamingVictim[0]._frame, Common::Point(0, 0));
// Play "scream.aiff"
if (_sound->_voices)
@@ -746,8 +830,8 @@ bool ScalpelEngine::showAlleyCutscene3DO() {
if (finished) {
// Fade out
- _screen->_backBuffer1.clear();
- _screen->fadeIntoScreen3DO(5);
+ screen._backBuffer1.clear();
+ screen.fadeIntoScreen3DO(5);
finished = _music->waitUntilMSec(84400, 0, 0, 2000);
}
@@ -757,17 +841,17 @@ bool ScalpelEngine::showAlleyCutscene3DO() {
if (finished) {
// Fade out
- _screen->_backBuffer1.clear();
- _screen->fadeIntoScreen3DO(5);
+ screen._backBuffer1.clear();
+ screen.fadeIntoScreen3DO(5);
}
if (finished) {
// "Early the following morning on Baker Street..."
ImageFile3DO titleImage_EarlyTheFollowingMorning("title3.cel", kImageFile3DOType_Cel);
- _screen->_backBuffer1.transBlitFrom(titleImage_EarlyTheFollowingMorning[0]._frame, Common::Point(35, 51));
+ screen._backBuffer1.transBlitFrom(titleImage_EarlyTheFollowingMorning[0]._frame, Common::Point(35, 51));
// Fade in
- _screen->fadeIntoScreen3DO(4);
+ screen.fadeIntoScreen3DO(4);
finished = _music->waitUntilMSec(96700, 0, 0, 3000);
}
@@ -775,12 +859,13 @@ bool ScalpelEngine::showAlleyCutscene3DO() {
}
bool ScalpelEngine::showStreetCutscene3DO() {
+ Scalpel3DOScreen &screen = *(Scalpel3DOScreen *)_screen;
bool finished = true;
if (finished) {
// fade out "Early the following morning..."
- _screen->_backBuffer1.clear();
- _screen->fadeIntoScreen3DO(4);
+ screen._backBuffer1.clear();
+ screen.fadeIntoScreen3DO(4);
// wait for music a bit
finished = _music->waitUntilMSec(100300, 0, 0, 1000);
@@ -799,8 +884,8 @@ bool ScalpelEngine::showStreetCutscene3DO() {
if (finished) {
// Fade out
- _screen->_backBuffer1.clear();
- _screen->fadeIntoScreen3DO(4);
+ screen._backBuffer1.clear();
+ screen.fadeIntoScreen3DO(4);
}
return finished;
@@ -852,7 +937,7 @@ bool ScalpelEngine::showOfficeCutscene3DO() {
// TODO: Brighten the image, possibly by doing a partial fade
// to white.
- _screen->_backBuffer1.blitFrom(*_screen);
+ _screen->_backBuffer2.blitFrom(_screen->_backBuffer1);
for (int nr = 1; finished && nr <= 4; nr++) {
char filename[15];
@@ -860,7 +945,7 @@ bool ScalpelEngine::showOfficeCutscene3DO() {
ImageFile3DO *creditsImage = new ImageFile3DO(filename, kImageFile3DOType_Cel);
ImageFrame *creditsFrame = &(*creditsImage)[0];
for (int i = 0; finished && i < 200 + creditsFrame->_height; i++) {
- _screen->blitFrom(_screen->_backBuffer1);
+ _screen->blitFrom(_screen->_backBuffer2);
_screen->transBlitFrom(creditsFrame->_frame, Common::Point((320 - creditsFrame->_width) / 2, 200 - i));
if (!_events->delay(70, true))
finished = false;
@@ -1159,6 +1244,182 @@ void ScalpelEngine::flushBrumwellMirror() {
_screen->slamArea(137, 18, 47, 56);
}
+
+void ScalpelEngine::showScummVMSaveDialog() {
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
+
+ int slot = dialog->runModalWithCurrentTarget();
+ if (slot >= 0) {
+ Common::String desc = dialog->getResultString();
+
+ saveGameState(slot, desc);
+ }
+
+ delete dialog;
+}
+
+void ScalpelEngine::showScummVMRestoreDialog() {
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
+
+ int slot = dialog->runModalWithCurrentTarget();
+ if (slot >= 0) {
+ loadGameState(slot);
+ }
+
+ delete dialog;
+}
+
+bool ScalpelEngine::play3doMovie(const Common::String &filename, const Common::Point &pos, bool isPortrait) {
+ Scalpel3DOScreen &screen = *(Scalpel3DOScreen *)_screen;
+ Scalpel3DOMovieDecoder *videoDecoder = new Scalpel3DOMovieDecoder();
+ Graphics::Surface tempSurface;
+
+ Common::Point framePos(pos.x, pos.y);
+ ImageFile3DO *frameImageFile = nullptr;
+ ImageFrame *frameImage = nullptr;
+ bool frameShown = false;
+
+ if (!videoDecoder->loadFile(filename)) {
+ warning("Scalpel3DOMoviePlay: could not open '%s'", filename.c_str());
+ return false;
+ }
+
+ bool halfSize = isPortrait && !_isScreenDoubled;
+ if (isPortrait) {
+ // only for portrait videos, not for EA intro logo and such
+ if ((framePos.x >= 8) && (framePos.y >= 8)) { // safety check
+ framePos.x -= 8;
+ framePos.y -= 8; // frame is 8 pixels on left + top, and 7 pixels on right + bottom
+ }
+
+ frameImageFile = new ImageFile3DO("vidframe.cel", kImageFile3DOType_Cel);
+ frameImage = &(*frameImageFile)[0];
+ }
+
+ bool skipVideo = false;
+ //byte bytesPerPixel = videoDecoder->getPixelFormat().bytesPerPixel;
+ uint16 width = videoDecoder->getWidth();
+ uint16 height = videoDecoder->getHeight();
+ //uint16 pitch = videoDecoder->getWidth() * bytesPerPixel;
+
+ _events->clearEvents();
+ videoDecoder->start();
+
+ // If we're to show the movie at half-size, we'll need a temporary intermediate surface
+ if (halfSize)
+ tempSurface.create(width / 2, height / 2, _screen->getPixelFormat());
+
+ while (!shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) {
+ if (videoDecoder->needsUpdate()) {
+ const Graphics::Surface *frame = videoDecoder->decodeNextFrame();
+
+ if (frame) {
+ if (halfSize) {
+ // movies are 152 x 200
+
+ // Downscale, but calculate average color out of 4 pixels and put that average into the target pixel
+ // TODO: 3DO actually did pixel weighting, exact details about this are unknown
+ // It's also unknown what 3DO exactly did for interpolation
+ // and it's also unknown atm if the CinePak videos contained pixel weighting information
+
+ if ((height & 1) || (width & 1)) {
+ error("Scalpel3DOMoviePlay: critical error, half-size requested on video with uneven height/width");
+ }
+
+ for (int downscaleY = 0; downscaleY < height / 2; downscaleY++) {
+ const uint16 *downscaleSource1Ptr = (const uint16 *)frame->getBasePtr(0, downscaleY * 2);
+ const uint16 *downscaleSource2Ptr = (const uint16 *)frame->getBasePtr(0, (downscaleY * 2) + 1);
+ uint16 *downscaleTargetPtr = (uint16 *)tempSurface.getBasePtr(0, downscaleY);
+
+ for (int downscaleX = 0; downscaleX < width / 2; downscaleX++) {
+ // get 4 pixel colors
+ uint16 downscaleColor = *downscaleSource1Ptr;
+ uint32 downscaleRed = downscaleColor >> 11; // 5 bits
+ uint32 downscaleGreen = (downscaleColor >> 5) & 0x3f; // 6 bits
+ uint32 downscaleBlue = downscaleColor & 0x1f;
+
+ downscaleSource1Ptr++;
+ downscaleColor = *downscaleSource1Ptr;
+ downscaleRed += downscaleColor >> 11;
+ downscaleGreen += (downscaleColor >> 5) & 0x3f;
+ downscaleBlue += downscaleColor & 0x1f;
+
+ downscaleColor = *downscaleSource2Ptr;
+ downscaleRed += downscaleColor >> 11;
+ downscaleGreen += (downscaleColor >> 5) & 0x3f;
+ downscaleBlue += downscaleColor & 0x1f;
+
+ downscaleSource2Ptr++;
+ downscaleColor = *downscaleSource2Ptr;
+ downscaleRed += downscaleColor >> 11;
+ downscaleGreen += (downscaleColor >> 5) & 0x3f;
+ downscaleBlue += downscaleColor & 0x1f;
+
+ // Divide colors by 4, so that we get the average
+ downscaleRed = downscaleRed >> 2;
+ downscaleGreen = downscaleGreen >> 2;
+ downscaleBlue = downscaleBlue >> 2;
+
+ // write new color to target pixel
+ downscaleColor = (downscaleRed << 11) | (downscaleGreen << 5) | downscaleBlue;
+ *downscaleTargetPtr = downscaleColor;
+
+ downscaleSource1Ptr++;
+ downscaleSource2Ptr++;
+ downscaleTargetPtr++;
+ }
+ }
+
+ // Point the drawing frame to the temporary surface
+ frame = &tempSurface;
+ }
+
+ if (isPortrait && !frameShown) {
+ // Draw the frame (not the frame of the video, but a frame around the video) itself
+ _screen->transBlitFrom(frameImage->_frame, framePos);
+ frameShown = true;
+ }
+
+ if (isPortrait && !halfSize) {
+ screen.rawBlitFrom(*frame, Common::Point(pos.x * 2, pos.y * 2));
+ } else {
+ _screen->blitFrom(*frame, pos);
+ }
+
+ _screen->update();
+ }
+ }
+
+ _events->pollEventsAndWait();
+ _events->setButtonState();
+
+ if (_events->kbHit()) {
+ Common::KeyState keyState = _events->getKey();
+ if (keyState.keycode == Common::KEYCODE_ESCAPE)
+ skipVideo = true;
+ } else if (_events->_pressed) {
+ skipVideo = true;
+ }
+ }
+
+ if (halfSize)
+ tempSurface.free();
+
+ videoDecoder->close();
+ delete videoDecoder;
+
+ if (isPortrait) {
+ delete frameImageFile;
+ }
+
+ // Restore scene
+ screen._backBuffer1.blitFrom(screen._backBuffer2);
+ _scene->updateBackground();
+ screen.slamArea(0, 0, screen.w(), CONTROLS_Y);
+
+ return !skipVideo;
+}
+
} // End of namespace Scalpel
} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h
index cb1cb20492..af4d72a7d7 100644
--- a/engines/sherlock/scalpel/scalpel.h
+++ b/engines/sherlock/scalpel/scalpel.h
@@ -30,25 +30,37 @@ namespace Sherlock {
namespace Scalpel {
-enum {
- BUTTON_TOP = 233,
- BUTTON_MIDDLE = 244,
- BUTTON_BOTTOM = 248,
- COMMAND_FOREGROUND = 15,
- COMMAND_HIGHLIGHTED = 10,
- COMMAND_NULL = 248,
- INFO_FOREGROUND = 11,
- INFO_BACKGROUND = 1,
- INV_FOREGROUND = 14,
- INV_BACKGROUND = 1,
- PEN_COLOR = 250
-};
+extern uint BUTTON_TOP;
+extern uint BUTTON_MIDDLE;
+extern uint BUTTON_BOTTOM;
+extern uint COMMAND_FOREGROUND;
+extern uint COMMAND_HIGHLIGHTED;
+extern uint COMMAND_NULL;
+extern uint INFO_FOREGROUND;
+extern uint INFO_BACKGROUND;
+extern uint INV_FOREGROUND;
+extern uint INV_BACKGROUND;
+extern uint PEN_COLOR;
+extern uint INFO_BLACK;
+extern uint BORDER_COLOR;
+extern uint COMMAND_BACKGROUND;
+extern uint BUTTON_BACKGROUND;
+extern uint TALK_FOREGROUND;
+extern uint TALK_NULL;
class ScalpelEngine : public SherlockEngine {
private:
Darts *_darts;
int _mapResult;
+ /**
+ * Initialize graphics mode
+ */
+ void setupGraphics();
+
+ /**
+ * Show the 3DO splash screen
+ */
bool show3DOSplash();
/**
@@ -124,6 +136,21 @@ public:
* This clears the mirror in scene 12 (mansion drawing room) in case anything messed draw over it
*/
void flushBrumwellMirror();
+
+ /**
+ * Show the ScummVM restore savegame dialog
+ */
+ void showScummVMSaveDialog();
+
+ /**
+ * Show the ScummVM restore savegame dialog
+ */
+ void showScummVMRestoreDialog();
+
+ /**
+ * Play back a 3do movie
+ */
+ bool play3doMovie(const Common::String &filename, const Common::Point &pos, bool isPortrait = false);
};
} // End of namespace Scalpel
diff --git a/engines/sherlock/scalpel/scalpel_fixed_text.cpp b/engines/sherlock/scalpel/scalpel_fixed_text.cpp
index 63f84d68c6..372fbc3e7e 100644
--- a/engines/sherlock/scalpel/scalpel_fixed_text.cpp
+++ b/engines/sherlock/scalpel/scalpel_fixed_text.cpp
@@ -55,6 +55,11 @@ static const char *const fixedTextEN[] = {
"Backward",
"Forward",
"Text Not Found !",
+ // SH1: Press key text
+ "Press any Key for More.",
+ "P",
+ "Press any Key to Continue.",
+ "P",
// SH1: Initial Inventory
"A message requesting help",
"A number of business cards",
@@ -68,11 +73,67 @@ static const char *const fixedTextEN[] = {
"Tarot Cards",
"An ornate key",
"A pawn ticket",
- // SH2: Verbs
- "Open",
- "Look",
- "Talk",
- "Journal"
+ // SH1: People names
+ "Sherlock Holmes",
+ "Dr. Watson",
+ "Inspector Lestrade",
+ "Constable O'Brien",
+ "Constable Lewis",
+ "Sheila Parker",
+ "Henry Carruthers",
+ "Lesley",
+ "An Usher",
+ "Fredrick Epstein",
+ "Mrs. Worthington",
+ "The Coach",
+ "A Player",
+ "Tim",
+ "James Sanders",
+ "Belle",
+ "Cleaning Girl",
+ "Wiggins",
+ "Paul",
+ "The Bartender",
+ "A Dirty Drunk",
+ "A Shouting Drunk",
+ "A Staggering Drunk",
+ "The Bouncer",
+ "The Coroner",
+ "Reginald Snipes",
+ "George Blackwood",
+ "Lars",
+ "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",
+ "Joseph Moorehead",
+ "Mrs. Beale",
+ "Felix",
+ "Hollingston",
+ "Constable Callaghan",
+ "Sergeant Duncan",
+ "Lord Brumwell",
+ "Nigel Jaimeson",
+ "Jonas",
+ "Constable Dugan"
};
// sharp-s : 0xE1 / octal 341
@@ -107,6 +168,11 @@ static const char *const fixedTextDE[] = {
"R\201ckw\204rts", // original: "Backward"
"Vorw\204rts", // original: "Forward"
"Text nicht gefunden!",
+ // SH1: Press key text
+ "Mehr auf Tastendruck...",
+ "M",
+ "Beliebige Taste dr\201cken.",
+ "B",
// SH1: Initial Inventory
"Ein Hilferuf von Lestrade",
"Holmes' Visitenkarten",
@@ -117,14 +183,70 @@ static const char *const fixedTextDE[] = {
"Eine offene Taschenuhr",
"Ein Zettel mit Zahlen drauf",
"Ein mehrfach gefalteter Briefbogen",
- "Ein Tarock-Kartenspiel", // [sic]
+ "Ein Tarot-Kartenspiel", // original interpreter: "Ein Tarock-Kartenspiel" [sic]
"Ein verzierter Schl\201ssel",
"Ein Pfandschein",
- // SH2: Verbs
- "\231ffne",
- "Schau",
- "Rede",
- "Tagebuch"
+ // SH1: People names
+ "Sherlock Holmes",
+ "Dr. Watson",
+ "Inspektor Lestrade",
+ "Konstabler O'Brien",
+ "Konstabler Lewis",
+ "Sheila Parker",
+ "Henry Carruthers",
+ "Lesley",
+ "Platzanweiser",
+ "Fredrick Epstein",
+ "Mrs. Worthington",
+ "Der Trainer",
+ "Ein Spieler",
+ "Tim",
+ "James Sanders",
+ "Belle",
+ "Putzm\204dchen",
+ "Wiggins",
+ "Paul",
+ "Gastwirt",
+ "Schmutziger Betrunkener",
+ "Lallender Betrunkener",
+ "Torkelnder Betrunkener",
+ "The Bouncer",
+ "Der Leichenbeschauer",
+ "Reginald Snipes",
+ "George Blackwood",
+ "Lars",
+ "Apotheker",
+ "Inspektor Gregson",
+ "Jacob Farthington",
+ "Mycroft",
+ "Old Sherman",
+ "Richard",
+ "Barkeeper",
+ "Jock Mahoney",
+ "Nobby Charleton",
+ "Zuschauer",
+ "Robert Hunt",
+ "Violet",
+ "Pettigrew",
+ "Augie",
+ "Anna Carroway",
+ "Wache",
+ "Antonio Caruso",
+ "Toby the Dog",
+ "Simon Kingsley",
+ "Alfred",
+ "Lady Brumwell",
+ "Madame Rosa",
+ "Joseph Moorehead",
+ "Mrs. Beale",
+ "Felix",
+ "Hollingston",
+ "Konstabler Callaghan",
+ "Sergeant Duncan",
+ "Lord Brumwell",
+ "Nigel Jaimeson",
+ "Jonas",
+ "Konstabler Dugan"
};
// up-side down exclamation mark - 0xAD / octal 255
@@ -132,11 +254,11 @@ static const char *const fixedTextDE[] = {
// n with a wave on top - 0xA4 / octal 244
static const char *const fixedTextES[] = {
// SH1: Window buttons
- "Exit",
+ "Salir", // original interpreter: "Exit"
"Subir",
"Bajar",
// SH1: Inventory buttons
- "Exit",
+ "Salir", // original interpreter: "Exit"
"Mirar",
"Usar",
"Dar",
@@ -144,7 +266,7 @@ static const char *const fixedTextES[] = {
"Diario de Watson",
"Pagina %d",
// SH1: Journal buttons
- "Exit",
+ "Salir", // original interpreter: "Exit"
"Retroceder",
"Subir",
"baJar",
@@ -154,10 +276,15 @@ static const char *const fixedTextES[] = {
"Ult pagina",
"Imprimir",
// SH1: Journal search
- "Exit",
+ "Salir", // original interpreter: "Exit"
"Retroceder",
"Avanzar",
"Texto no encontrado!",
+ // SH1: Press key text
+ "Tecla para ver mas",
+ "T",
+ "Tecla para continuar",
+ "T",
// SH1: Initial Inventory
"Un mensaje solicitando ayuda",
"Unas cuantas tarjetas de visita",
@@ -171,6 +298,67 @@ static const char *const fixedTextES[] = {
"Unas cartas de Tarot",
"Una llave muy vistosa",
"Una papeleta de empe\244o",
+ // SH1: People names
+ "Sherlock Holmes",
+ "Dr. Watson",
+ "El inspector Lestrade",
+ "El agente O'Brien",
+ "El agente Lewis",
+ "Sheila Parker",
+ "Henry Carruthers",
+ "Lesley",
+ "Un ujier",
+ "Fredrick Epstein",
+ "Mrs. Worthington",
+ "El entrenador",
+ "El jugador",
+ "Tim",
+ "James Sanders",
+ "Belle",
+ "La chica de la limpieza",
+ "Wiggins",
+ "Paul",
+ "El barman",
+ "Un sucio borracho",
+ "Un borracho griton",
+ "Un tambaleante borracho",
+ "El gorila",
+ "El forense",
+ "Reginald Snipes",
+ "George Blackwood",
+ "Lars",
+ "El quimico",
+ "El inspector Gregson",
+ "Jacob Farthington",
+ "Mycroft",
+ "Old Sherman",
+ "Richard",
+ "El barman",
+ "Un jugador dandy",
+ "Un duro jugador",
+ "Un espectador",
+ "Robert Hunt",
+ "Violeta",
+ "Pettigrew",
+ "Augie",
+ "Anna Carroway",
+ "Un guarda",
+ "Antonio Caruso",
+ "El perro Toby",
+ "Simon Kingsley",
+ "Alfred",
+ "Lady Brumwell",
+ "Madame Rosa",
+ "Joseph Moorehead",
+ "Mrs. Beale",
+ "Felix",
+ "Hollingston",
+ "El agente Callaghan",
+ "El sargento Duncan",
+ "Lord Brumwell",
+ "Nigel Jaimeson",
+ "Jonas",
+ "El agente Dugan"
};
// =========================================
diff --git a/engines/sherlock/scalpel/scalpel_fixed_text.h b/engines/sherlock/scalpel/scalpel_fixed_text.h
index eae86b8f27..f46587ce81 100644
--- a/engines/sherlock/scalpel/scalpel_fixed_text.h
+++ b/engines/sherlock/scalpel/scalpel_fixed_text.h
@@ -57,6 +57,11 @@ enum FixedTextId {
kFixedText_JournalSearch_Backward,
kFixedText_JournalSearch_Forward,
kFixedText_JournalSearch_NotFound,
+ // Press key text
+ kFixedText_PressKey_ForMore,
+ kFixedText_PressKey_ForMoreHotkey,
+ kFixedText_PressKey_ToContinue,
+ kFixedText_PressKey_ToContinueHotkey,
// Initial inventory
kFixedText_InitInventory_Message,
kFixedText_InitInventory_HolmesCard,
@@ -69,7 +74,68 @@ enum FixedTextId {
kFixedText_InitInventory_Letter,
kFixedText_InitInventory_Tarot,
kFixedText_InitInventory_OrnateKey,
- kFixedText_InitInventory_PawnTicket
+ kFixedText_InitInventory_PawnTicket,
+ // People names
+ kFixedText_People_SherlockHolmes,
+ kFixedText_People_DrWatson,
+ kFixedText_People_InspectorLestrade,
+ kFixedText_People_ConstableOBrien,
+ kFixedText_People_ConstableLewis,
+ kFixedText_People_SheilaParker,
+ kFixedText_People_HenryCarruthers,
+ kFixedText_People_Lesley,
+ kFixedText_People_AnUsher,
+ kFixedText_People_FredrickEpstein,
+ kFixedText_People_MrsWorthington,
+ kFixedText_People_TheCoach,
+ kFixedText_People_APlayer,
+ kFixedText_People_Tim,
+ kFixedText_People_JamesSanders,
+ kFixedText_People_Belle,
+ kFixedText_People_CleaningGirl,
+ kFixedText_People_Wiggins,
+ kFixedText_People_Paul,
+ kFixedText_People_TheBartender,
+ kFixedText_People_ADirtyDrunk,
+ kFixedText_People_AShoutingDrunk,
+ kFixedText_People_AStaggeringDrunk,
+ kFixedText_People_TheBouncer,
+ kFixedText_People_TheCoroner,
+ kFixedText_People_ReginaldSnipes,
+ kFixedText_People_GeorgeBlackwood,
+ kFixedText_People_Lars,
+ kFixedText_People_TheChemist,
+ kFixedText_People_InspectorGregson,
+ kFixedText_People_JacobFarthington,
+ kFixedText_People_Mycroft,
+ kFixedText_People_OldSherman,
+ kFixedText_People_Richard,
+ kFixedText_People_TheBarman,
+ kFixedText_People_ADandyPlayer,
+ kFixedText_People_ARoughlookingPlayer,
+ kFixedText_People_ASpectator,
+ kFixedText_People_RobertHunt,
+ kFixedText_People_Violet,
+ kFixedText_People_Pettigrew,
+ kFixedText_People_Augie,
+ kFixedText_People_AnnaCarroway,
+ kFixedText_People_AGuard,
+ kFixedText_People_AntonioCaruso,
+ kFixedText_People_TobyTheDog,
+ kFixedText_People_SimonKingsley,
+ kFixedText_People_Alfred,
+ kFixedText_People_LadyBrumwell,
+ kFixedText_People_MadameRosa,
+ kFixedText_People_JosephMoorehead,
+ kFixedText_People_MrsBeale,
+ kFixedText_People_Felix,
+ kFixedText_People_Hollingston,
+ kFixedText_People_ConstableCallaghan,
+ kFixedText_People_SergeantDuncan,
+ kFixedText_People_LordBrumwell,
+ kFixedText_People_NigelJaimeson,
+ kFixedText_People_Jonas,
+ kFixedText_People_ConstableDugan
};
struct FixedTextActionEntry {
diff --git a/engines/sherlock/scalpel/scalpel_journal.cpp b/engines/sherlock/scalpel/scalpel_journal.cpp
index 787d899aee..5c2b8f77f3 100644
--- a/engines/sherlock/scalpel/scalpel_journal.cpp
+++ b/engines/sherlock/scalpel/scalpel_journal.cpp
@@ -104,6 +104,25 @@ void ScalpelJournal::loadLocations() {
while ((c = loc->readByte()) != 0)
line += c;
+ // WORKAROUND: Special fixes for faulty translations
+ // Was obviously not done in the original interpreter
+ if (_vm->getLanguage() == Common::ES_ESP) {
+ // Spanish version
+ // We fix all sorts of typos
+ // see bug #6931
+ if (line == "En el cajellon destras del teatro Regency") {
+ line = "En el callejon detras del teatro Regency";
+ } else if (line == "En el apartamente de Simon Kingsley") {
+ line = "En el apartamento de Simon Kingsley";
+ } else if (line == "Bajo la muelle de Savoy Pier") {
+ line = "Bajo el muelle de Savoy Pier";
+ } else if (line == "En le viejo Sherman") {
+ line = "En el viejo Sherman";
+ } else if (line == "En la entrada de la cada de Anna Carroway") {
+ line = "En la entrada de la casa de Anna Carroway";
+ }
+ }
+
_locations.push_back(line);
}
diff --git a/engines/sherlock/scalpel/scalpel_map.cpp b/engines/sherlock/scalpel/scalpel_map.cpp
index 369822ba02..0924581e38 100644
--- a/engines/sherlock/scalpel/scalpel_map.cpp
+++ b/engines/sherlock/scalpel/scalpel_map.cpp
@@ -100,6 +100,21 @@ void ScalpelMap::loadData() {
while ((c = txtStream->readByte()) != '\0')
line += c;
+ // WORKAROUND: Special fixes for faulty translations
+ // Was obviously not done in the original interpreter
+ if (_vm->getLanguage() == Common::ES_ESP) {
+ // Spanish version
+ if (line == " Alley") {
+ // The "Alley" location was not translated, we do this now
+ // see bug #6931
+ line = " Callejon";
+ } else if (line == " Alamacen") {
+ // "Warehouse" location has a typo, we fix it
+ // see bug #6931
+ line = " Almacen";
+ }
+ }
+
_locationNames.push_back(line);
}
diff --git a/engines/sherlock/scalpel/scalpel_saveload.cpp b/engines/sherlock/scalpel/scalpel_saveload.cpp
index 01ba149813..61830a56b2 100644
--- a/engines/sherlock/scalpel/scalpel_saveload.cpp
+++ b/engines/sherlock/scalpel/scalpel_saveload.cpp
@@ -39,7 +39,8 @@ const int ENV_POINTS[6][3] = {
/*----------------------------------------------------------------*/
-ScalpelSaveManager::ScalpelSaveManager(SherlockEngine *vm, const Common::String &target) : SaveManager(vm, target) {
+ScalpelSaveManager::ScalpelSaveManager(SherlockEngine *vm, const Common::String &target) :
+ SaveManager(vm, target), _envMode(SAVEMODE_NONE) {
}
void ScalpelSaveManager::drawInterface() {
diff --git a/engines/sherlock/scalpel/scalpel_scene.cpp b/engines/sherlock/scalpel/scalpel_scene.cpp
index b2c7339363..b62703e0fb 100644
--- a/engines/sherlock/scalpel/scalpel_scene.cpp
+++ b/engines/sherlock/scalpel/scalpel_scene.cpp
@@ -40,6 +40,11 @@ const int FS_TRANS[8] = {
/*----------------------------------------------------------------*/
+ScalpelScene::~ScalpelScene() {
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx)
+ delete _canimShapes[idx];
+}
+
bool ScalpelScene::loadScene(const Common::String &filename) {
ScalpelMap &map = *(ScalpelMap *)_vm->_map;
bool result = Scene::loadScene(filename);
@@ -71,9 +76,9 @@ void ScalpelScene::drawAllShapes() {
// Draw all canimations which are behind the person
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);
+ 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);
}
// Draw all active shapes which are normal and behind the person
@@ -84,9 +89,9 @@ void ScalpelScene::drawAllShapes() {
// Draw all canimations which are normal and behind the person
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);
+ 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);
}
// Draw any active characters
@@ -113,10 +118,10 @@ void ScalpelScene::drawAllShapes() {
// 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)
- screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position,
- _canimShapes[idx]._flags & OBJ_FLIPPED);
+ if ((_canimShapes[idx]->_type == ACTIVE_BG_SHAPE || _canimShapes[idx]->_type == STATIC_BG_SHAPE) &&
+ _canimShapes[idx]->_misc == NORMAL_FORWARD)
+ screen._backBuffer->transBlitFrom(*_canimShapes[idx]->_imageFrame, _canimShapes[idx]->_position,
+ _canimShapes[idx]->_flags & OBJ_FLIPPED);
}
// Draw all static and active shapes that are FORWARD
@@ -133,10 +138,10 @@ void ScalpelScene::drawAllShapes() {
// Draw all static and active canimations that are forward
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- 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);
+ 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);
}
screen.resetDisplayBounds();
@@ -152,7 +157,7 @@ void ScalpelScene::checkBgShapes() {
// Iterate through the canim list
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- Object &obj = _canimShapes[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)) ?
@@ -221,8 +226,8 @@ void ScalpelScene::doBgAnim() {
people._portrait.checkObject();
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- if (_canimShapes[idx]._type != INVALID && _canimShapes[idx]._type != REMOVE)
- _canimShapes[idx].checkObject();
+ if (_canimShapes[idx]->_type != INVALID && _canimShapes[idx]->_type != REMOVE)
+ _canimShapes[idx]->checkObject();
}
if (_currentScene == DRAWING_ROOM)
@@ -266,7 +271,7 @@ void ScalpelScene::doBgAnim() {
}
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- Object &o = _canimShapes[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));
@@ -287,8 +292,8 @@ void ScalpelScene::doBgAnim() {
people._portrait.adjustObject();
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- if (_canimShapes[idx]._type != INVALID)
- _canimShapes[idx].adjustObject();
+ if (_canimShapes[idx]->_type != INVALID)
+ _canimShapes[idx]->adjustObject();
}
if (people[HOLMES]._type == CHARACTER && people._holmesOn)
@@ -309,7 +314,7 @@ void ScalpelScene::doBgAnim() {
// Draw all canimations which are behind the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- Object &o = _canimShapes[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);
}
@@ -324,14 +329,14 @@ void ScalpelScene::doBgAnim() {
// Draw all canimations which are NORMAL and behind the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
- Object &o = _canimShapes[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[HOLMES]._type == CHARACTER && people[HOLMES]._walkLoaded) {
+ // Draw the player if he's active and his walk has been loaded into memory
+ if (people[HOLMES]._type == CHARACTER && people[HOLMES]._walkLoaded && people._holmesOn) {
// If Holmes is too far to the right, move him back so he's on-screen
int xRight = SHERLOCK_SCREEN_WIDTH - 2 - people[HOLMES]._imageFrame->_frame.w;
int tempX = MIN(people[HOLMES]._position.x / FIXED_INT_MULTIPLIER, xRight);
@@ -352,7 +357,7 @@ void ScalpelScene::doBgAnim() {
// 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];
+ 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);
}
@@ -372,7 +377,7 @@ void ScalpelScene::doBgAnim() {
// 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];
+ 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);
}
@@ -450,16 +455,18 @@ void ScalpelScene::doBgAnim() {
}
for (int idx = _canimShapes.size() - 1; idx >= 0; --idx) {
- Object &o = _canimShapes[idx];
+ Object &o = *_canimShapes[idx];
if (o._type == INVALID) {
// Anim shape was invalidated by checkEndOfSequence, so at this point we can remove it
+ delete _canimShapes[idx];
_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
+ delete _canimShapes[idx];
_canimShapes.remove_at(idx);
} else if (o._type == ACTIVE_BG_SHAPE) {
screen.flushImage(o._imageFrame, o._position,
@@ -496,6 +503,7 @@ int ScalpelScene::startCAnim(int cAnimNum, int playRate) {
int tpDir, walkDir;
int tFrames = 0;
int gotoCode = -1;
+ Object *cObj;
// Validation
if (cAnimNum >= (int)_cAnim.size())
@@ -533,33 +541,33 @@ int ScalpelScene::startCAnim(int cAnimNum, int playRate) {
return 1;
// Add new anim shape entry for displaying the animation
- _canimShapes.push_back(Object());
- Object &cObj = _canimShapes[_canimShapes.size() - 1];
+ cObj = new Object();
+ _canimShapes.push_back(cObj);
// Copy the canimation into the bgShapes type canimation structure so it can be played
- cObj._allow = cAnimNum + 1; // Keep track of the parent structure
- cObj._name = _cAnim[cAnimNum]._name; // Copy name
+ cObj->_allow = cAnimNum + 1; // Keep track of the parent structure
+ cObj->_name = _cAnim[cAnimNum]._name; // Copy name
// Remove any attempt to draw object frame
if (cAnim._type == NO_SHAPE && cAnim._sequences[0] < 100)
cAnim._sequences[0] = 0;
- cObj._sequences = cAnim._sequences;
- cObj._images = nullptr;
- cObj._position = cAnim._position;
- cObj._delta = Common::Point(0, 0);
- cObj._type = cAnim._type;
- cObj._flags = cAnim._flags;
-
- cObj._maxFrames = 0;
- cObj._frameNumber = -1;
- cObj._sequenceNumber = cAnimNum;
- cObj._oldPosition = Common::Point(0, 0);
- cObj._oldSize = Common::Point(0, 0);
- cObj._goto = Common::Point(0, 0);
- cObj._status = 0;
- cObj._misc = 0;
- cObj._imageFrame = nullptr;
+ cObj->_sequences = cAnim._sequences;
+ cObj->_images = nullptr;
+ cObj->_position = cAnim._position;
+ cObj->_delta = Common::Point(0, 0);
+ cObj->_type = cAnim._type;
+ cObj->_flags = cAnim._flags;
+
+ cObj->_maxFrames = 0;
+ cObj->_frameNumber = -1;
+ cObj->_sequenceNumber = cAnimNum;
+ cObj->_oldPosition = Common::Point(0, 0);
+ cObj->_oldSize = Common::Point(0, 0);
+ cObj->_goto = Common::Point(0, 0);
+ cObj->_status = 0;
+ cObj->_misc = 0;
+ cObj->_imageFrame = nullptr;
if (cAnim._name.size() > 0 && cAnim._type != NO_SHAPE) {
if (tpPos.x != -1)
@@ -584,25 +592,25 @@ int ScalpelScene::startCAnim(int cAnimNum, int playRate) {
// Now load the resource as an image
if (!IS_3DO) {
- cObj._images = new ImageFile(fname);
+ cObj->_images = new ImageFile(fname);
} else {
- cObj._images = new ImageFile3DO(fname, kImageFile3DOType_RoomFormat);
+ cObj->_images = new ImageFile3DO(fname, kImageFile3DOType_RoomFormat);
}
- cObj._imageFrame = &(*cObj._images)[0];
- cObj._maxFrames = cObj._images->size();
+ cObj->_imageFrame = &(*cObj->_images)[0];
+ cObj->_maxFrames = cObj->_images->size();
int frames = 0;
if (playRate < 0) {
// Reverse direction
// Count number of frames
- while (frames < MAX_FRAME && cObj._sequences[frames])
+ while (frames < MAX_FRAME && cObj->_sequences[frames])
++frames;
} else {
// Forward direction
BaseObject::_countCAnimFrames = true;
- while (cObj._type == ACTIVE_BG_SHAPE) {
- cObj.checkObject();
+ while (cObj->_type == ACTIVE_BG_SHAPE) {
+ cObj->checkObject();
++frames;
if (frames >= 1000)
@@ -614,10 +622,10 @@ int ScalpelScene::startCAnim(int cAnimNum, int playRate) {
BaseObject::_countCAnimFrames = false;
- cObj._type = cAnim._type;
- cObj._frameNumber = -1;
- cObj._position = cAnim._position;
- cObj._delta = Common::Point(0, 0);
+ cObj->_type = cAnim._type;
+ cObj->_frameNumber = -1;
+ cObj->_position = cAnim._position;
+ cObj->_delta = Common::Point(0, 0);
}
// Return if animation has no frames in it
@@ -631,7 +639,7 @@ int ScalpelScene::startCAnim(int cAnimNum, int playRate) {
if (playRate < 0) {
// Play in reverse
dir = -2;
- cObj._frameNumber = frames - 3;
+ cObj->_frameNumber = frames - 3;
} else {
dir = 0;
}
@@ -648,14 +656,14 @@ int ScalpelScene::startCAnim(int cAnimNum, int playRate) {
// Repeat same frame
int temp = repeat;
while (--temp > 0) {
- cObj._frameNumber--;
+ cObj->_frameNumber--;
doBgAnim();
if (_vm->shouldQuit())
return 0;
}
- cObj._frameNumber += dir;
+ cObj->_frameNumber += dir;
}
people[HOLMES]._type = CHARACTER;
@@ -670,14 +678,18 @@ int ScalpelScene::startCAnim(int cAnimNum, int playRate) {
if (playRate < 0)
// Reverse direction - set to end sequence
- cObj._frameNumber = tFrames - 1;
+ cObj->_frameNumber = tFrames - 1;
- if (cObj._frameNumber <= 26)
- gotoCode = cObj._sequences[cObj._frameNumber + 3];
+ if (cObj->_frameNumber <= 26)
+ gotoCode = cObj->_sequences[cObj->_frameNumber + 3];
- // Unless anim shape has already been freed, set it to REMOVE so doBgAnim can free it
- if (_canimShapes.indexOf(cObj) != -1)
- cObj.checkObject();
+ // Unless anim shape has already been removed, do a final check to allow it to become REMOVEd
+ for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
+ if (_canimShapes[idx] == cObj) {
+ cObj->checkObject();
+ break;
+ }
+ }
if (gotoCode > 0 && !talk._talkToAbort) {
_goToScene = gotoCode;
diff --git a/engines/sherlock/scalpel/scalpel_scene.h b/engines/sherlock/scalpel/scalpel_scene.h
index 8fe3b66b38..8711fea2d0 100644
--- a/engines/sherlock/scalpel/scalpel_scene.h
+++ b/engines/sherlock/scalpel/scalpel_scene.h
@@ -75,6 +75,8 @@ protected:
public:
ScalpelScene(SherlockEngine *vm) : Scene(vm) {}
+ virtual ~ScalpelScene();
+
/**
* Draw all objects and characters.
*/
diff --git a/engines/sherlock/scalpel/scalpel_screen.cpp b/engines/sherlock/scalpel/scalpel_screen.cpp
index 2096dabcdf..71bcca5dc5 100644
--- a/engines/sherlock/scalpel/scalpel_screen.cpp
+++ b/engines/sherlock/scalpel/scalpel_screen.cpp
@@ -45,7 +45,7 @@ void ScalpelScreen::makeButton(const Common::Rect &bounds, int textX,
COMMAND_FOREGROUND, "%s", str.c_str() + 1);
}
-void ScalpelScreen::buttonPrint(const Common::Point &pt, byte color, bool slamIt,
+void ScalpelScreen::buttonPrint(const Common::Point &pt, uint color, bool slamIt,
const Common::String &str) {
int xStart = pt.x - stringWidth(str) / 2;
@@ -88,6 +88,255 @@ void ScalpelScreen::makeField(const Common::Rect &r) {
_backBuffer->vLine(r.right - 1, r.top + 1, r.bottom - 2, BUTTON_TOP);
}
+/*----------------------------------------------------------------*/
+
+void Scalpel3DOScreen::blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds) {
+ if (!_vm->_isScreenDoubled) {
+ ScalpelScreen::blitFrom(src, pt, srcBounds);
+ return;
+ }
+
+ Common::Rect srcRect = srcBounds;
+ Common::Rect destRect(pt.x, pt.y, pt.x + srcRect.width(), pt.y + srcRect.height());
+
+ if (!srcRect.isValidRect() || !clip(srcRect, destRect))
+ return;
+
+ // Add dirty area remapped to the 640x200 surface
+ addDirtyRect(Common::Rect(destRect.left * 2, destRect.top * 2, destRect.right * 2, destRect.bottom * 2));
+
+ // Transfer the area, doubling each pixel
+ for (int yp = 0; yp < srcRect.height(); ++yp) {
+ const uint16 *srcP = (const uint16 *)src.getBasePtr(srcRect.left, srcRect.top + yp);
+ uint16 *destP = (uint16 *)getBasePtr(destRect.left * 2, (destRect.top + yp) * 2);
+
+ for (int xp = srcRect.left; xp < srcRect.right; ++xp, ++srcP, destP += 2) {
+ *destP = *srcP;
+ *(destP + 1) = *srcP;
+ *(destP + 640) = *srcP;
+ *(destP + 640 + 1) = *srcP;
+ }
+ }
+}
+
+void Scalpel3DOScreen::transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt,
+ bool flipped, int overrideColor) {
+ if (!_vm->_isScreenDoubled) {
+ ScalpelScreen::transBlitFromUnscaled(src, pt, flipped, overrideColor);
+ return;
+ }
+
+ Common::Rect drawRect(0, 0, src.w, src.h);
+ Common::Rect destRect(pt.x, pt.y, pt.x + src.w, pt.y + src.h);
+
+ // Clip the display area to on-screen
+ if (!clip(drawRect, destRect))
+ // It's completely off-screen
+ return;
+
+ if (flipped)
+ drawRect = Common::Rect(src.w - drawRect.right, src.h - drawRect.bottom,
+ src.w - drawRect.left, src.h - drawRect.top);
+
+ Common::Point destPt(destRect.left, destRect.top);
+ addDirtyRect(Common::Rect(destPt.x * 2, destPt.y * 2, (destPt.x + drawRect.width()) * 2,
+ (destPt.y + drawRect.height()) * 2));
+
+ assert(src.format.bytesPerPixel == 2 && _surface.format.bytesPerPixel == 2);
+
+ for (int yp = 0; yp < drawRect.height(); ++yp) {
+ const uint16 *srcP = (const uint16 *)src.getBasePtr(
+ flipped ? drawRect.right - 1 : drawRect.left, drawRect.top + yp);
+ uint16 *destP = (uint16 *)getBasePtr(destPt.x * 2, (destPt.y + yp) * 2);
+
+ for (int xp = 0; xp < drawRect.width(); ++xp, destP += 2) {
+ // RGB 0, 0, 0 -> transparent on 3DO
+ if (*srcP) {
+ *destP = *srcP;
+ *(destP + 1) = *srcP;
+ *(destP + 640) = *srcP;
+ *(destP + 640 + 1) = *srcP;
+ }
+
+ srcP = flipped ? srcP - 1 : srcP + 1;
+ }
+ }
+}
+
+void Scalpel3DOScreen::fillRect(const Common::Rect &r, uint color) {
+ if (_vm->_isScreenDoubled)
+ ScalpelScreen::fillRect(Common::Rect(r.left * 2, r.top * 2, r.right * 2, r.bottom * 2), color);
+ else
+ ScalpelScreen::fillRect(r, color);
+}
+
+void Scalpel3DOScreen::fadeIntoScreen3DO(int speed) {
+ Events &events = *_vm->_events;
+ uint16 *currentScreenBasePtr = (uint16 *)getPixels();
+ uint16 *targetScreenBasePtr = (uint16 *)_backBuffer->getPixels();
+ uint16 currentScreenPixel = 0;
+ uint16 targetScreenPixel = 0;
+
+ uint16 currentScreenPixelRed = 0;
+ uint16 currentScreenPixelGreen = 0;
+ uint16 currentScreenPixelBlue = 0;
+
+ uint16 targetScreenPixelRed = 0;
+ uint16 targetScreenPixelGreen = 0;
+ uint16 targetScreenPixelBlue = 0;
+
+ uint16 screenWidth = SHERLOCK_SCREEN_WIDTH;
+ uint16 screenHeight = SHERLOCK_SCREEN_HEIGHT;
+ uint16 screenX = 0;
+ uint16 screenY = 0;
+ uint16 pixelsChanged = 0;
+
+ clearDirtyRects();
+
+ do {
+ pixelsChanged = 0;
+ uint16 *currentScreenPtr = currentScreenBasePtr;
+ uint16 *targetScreenPtr = targetScreenBasePtr;
+
+ for (screenY = 0; screenY < screenHeight; screenY++) {
+ for (screenX = 0; screenX < screenWidth; screenX++) {
+ currentScreenPixel = *currentScreenPtr;
+ targetScreenPixel = *targetScreenPtr;
+
+ if (currentScreenPixel != targetScreenPixel) {
+ // pixel doesn't match, adjust accordingly
+ currentScreenPixelRed = currentScreenPixel & 0xF800;
+ currentScreenPixelGreen = currentScreenPixel & 0x07E0;
+ currentScreenPixelBlue = currentScreenPixel & 0x001F;
+ targetScreenPixelRed = targetScreenPixel & 0xF800;
+ targetScreenPixelGreen = targetScreenPixel & 0x07E0;
+ targetScreenPixelBlue = targetScreenPixel & 0x001F;
+
+ if (currentScreenPixelRed != targetScreenPixelRed) {
+ if (currentScreenPixelRed < targetScreenPixelRed) {
+ currentScreenPixelRed += 0x0800;
+ } else {
+ currentScreenPixelRed -= 0x0800;
+ }
+ }
+ if (currentScreenPixelGreen != targetScreenPixelGreen) {
+ // Adjust +2/-2 because we are running RGB555 at RGB565
+ if (currentScreenPixelGreen < targetScreenPixelGreen) {
+ currentScreenPixelGreen += 0x0040;
+ } else {
+ currentScreenPixelGreen -= 0x0040;
+ }
+ }
+ if (currentScreenPixelBlue != targetScreenPixelBlue) {
+ if (currentScreenPixelBlue < targetScreenPixelBlue) {
+ currentScreenPixelBlue += 0x0001;
+ } else {
+ currentScreenPixelBlue -= 0x0001;
+ }
+ }
+
+ uint16 v = currentScreenPixelRed | currentScreenPixelGreen | currentScreenPixelBlue;
+ *currentScreenPtr = v;
+ if (_vm->_isScreenDoubled) {
+ *(currentScreenPtr + 1) = v;
+ *(currentScreenPtr + 640) = v;
+ *(currentScreenPtr + 640 + 1) = v;
+ }
+
+ pixelsChanged++;
+ }
+
+ currentScreenPtr += _vm->_isScreenDoubled ? 2 : 1;
+ targetScreenPtr++;
+ }
+
+ if (_vm->_isScreenDoubled)
+ currentScreenPtr += 640;
+ }
+
+ // Too much considered dirty at the moment
+ if (_vm->_isScreenDoubled)
+ addDirtyRect(Common::Rect(0, 0, screenWidth * 2, screenHeight * 2));
+ else
+ addDirtyRect(Common::Rect(0, 0, screenWidth, screenHeight));
+
+ events.pollEvents();
+ events.delay(10 * speed);
+ } while ((pixelsChanged) && (!_vm->shouldQuit()));
+}
+
+void Scalpel3DOScreen::blitFrom3DOcolorLimit(uint16 limitColor) {
+ uint16 *currentScreenPtr = (uint16 *)getPixels();
+ uint16 *targetScreenPtr = (uint16 *)_backBuffer->getPixels();
+ uint16 currentScreenPixel = 0;
+
+ uint16 screenWidth = SHERLOCK_SCREEN_WIDTH;
+ uint16 screenHeight = SHERLOCK_SCREEN_HEIGHT;
+ uint16 screenX = 0;
+ uint16 screenY = 0;
+
+ uint16 currentScreenPixelRed = 0;
+ uint16 currentScreenPixelGreen = 0;
+ uint16 currentScreenPixelBlue = 0;
+
+ uint16 limitPixelRed = limitColor & 0xF800;
+ uint16 limitPixelGreen = limitColor & 0x07E0;
+ uint16 limitPixelBlue = limitColor & 0x001F;
+
+ for (screenY = 0; screenY < screenHeight; screenY++) {
+ for (screenX = 0; screenX < screenWidth; screenX++) {
+ currentScreenPixel = *targetScreenPtr;
+
+ currentScreenPixelRed = currentScreenPixel & 0xF800;
+ currentScreenPixelGreen = currentScreenPixel & 0x07E0;
+ currentScreenPixelBlue = currentScreenPixel & 0x001F;
+
+ if (currentScreenPixelRed < limitPixelRed)
+ currentScreenPixelRed = limitPixelRed;
+ if (currentScreenPixelGreen < limitPixelGreen)
+ currentScreenPixelGreen = limitPixelGreen;
+ if (currentScreenPixelBlue < limitPixelBlue)
+ currentScreenPixelBlue = limitPixelBlue;
+
+ uint16 v = currentScreenPixelRed | currentScreenPixelGreen | currentScreenPixelBlue;
+ *currentScreenPtr = v;
+ if (_vm->_isScreenDoubled) {
+ *(currentScreenPtr + 1) = v;
+ *(currentScreenPtr + 640) = v;
+ *(currentScreenPtr + 640 + 1) = v;
+ }
+
+ currentScreenPtr += _vm->_isScreenDoubled ? 2 : 1;
+ targetScreenPtr++;
+ }
+
+ if (_vm->_isScreenDoubled)
+ currentScreenPtr += 640;
+ }
+
+ // Too much considered dirty at the moment
+ if (_vm->_isScreenDoubled)
+ addDirtyRect(Common::Rect(0, 0, screenWidth * 2, screenHeight * 2));
+ else
+ addDirtyRect(Common::Rect(0, 0, screenWidth, screenHeight));
+}
+
+uint16 Scalpel3DOScreen::w() const {
+ return _vm->_isScreenDoubled ? _surface.w / 2 : _surface.w;
+}
+
+uint16 Scalpel3DOScreen::h() const {
+ return _vm->_isScreenDoubled ? _surface.h / 2 : _surface.h;
+}
+
+void Scalpel3DOScreen::rawBlitFrom(const Graphics::Surface &src, const Common::Point &pt) {
+ Common::Rect srcRect(0, 0, src.w, src.h);
+ Common::Rect destRect(pt.x, pt.y, pt.x + src.w, pt.y + src.h);
+
+ addDirtyRect(destRect);
+ _surface.copyRectToSurface(src, destRect.left, destRect.top, srcRect);
+}
+
} // End of namespace Scalpel
} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel_screen.h b/engines/sherlock/scalpel/scalpel_screen.h
index 472fe9e220..d6018a44a0 100644
--- a/engines/sherlock/scalpel/scalpel_screen.h
+++ b/engines/sherlock/scalpel/scalpel_screen.h
@@ -45,7 +45,7 @@ public:
* Prints an interface command with the first letter highlighted to indicate
* what keyboard shortcut is associated with it
*/
- void buttonPrint(const Common::Point &pt, byte color, bool slamIt, const Common::String &str);
+ void buttonPrint(const Common::Point &pt, uint color, bool slamIt, const Common::String &str);
/**
* Draw a panel in the back buffer with a raised area effect around the edges
@@ -59,6 +59,44 @@ public:
void makeField(const Common::Rect &r);
};
+class Scalpel3DOScreen : public ScalpelScreen {
+protected:
+ /**
+ * Draws a sub-section of a surface at a given position within this surface
+ * Overriden for the 3DO to automatically double the size of everything to the underlying 640x400 surface
+ */
+ virtual void blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds);
+
+ /**
+ * Draws a surface at a given position within this surface with transparency
+ */
+ virtual void transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt, bool flipped,
+ int overrideColor);
+public:
+ Scalpel3DOScreen(SherlockEngine *vm) : ScalpelScreen(vm) {}
+ virtual ~Scalpel3DOScreen() {}
+
+ /**
+ * Draws a sub-section of a surface at a given position within this surface
+ */
+ void rawBlitFrom(const Graphics::Surface &src, const Common::Point &pt);
+
+ /**
+ * Fade backbuffer 1 into screen (3DO RGB!)
+ */
+ void fadeIntoScreen3DO(int speed);
+
+ void blitFrom3DOcolorLimit(uint16 color);
+
+ /**
+ * Fill a given area of the surface with a given color
+ */
+ virtual void fillRect(const Common::Rect &r, uint color);
+
+ virtual uint16 w() const;
+ virtual uint16 h() const;
+};
+
} // End of namespace Scalpel
} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel_talk.cpp b/engines/sherlock/scalpel/scalpel_talk.cpp
index 2dda817445..2c447b09ab 100644
--- a/engines/sherlock/scalpel/scalpel_talk.cpp
+++ b/engines/sherlock/scalpel/scalpel_talk.cpp
@@ -22,6 +22,7 @@
#include "sherlock/scalpel/scalpel_talk.h"
#include "sherlock/scalpel/scalpel_fixed_text.h"
+#include "sherlock/scalpel/scalpel_journal.h"
#include "sherlock/scalpel/scalpel_map.h"
#include "sherlock/scalpel/scalpel_people.h"
#include "sherlock/scalpel/scalpel_scene.h"
@@ -189,6 +190,9 @@ void ScalpelTalk::talkInterface(const byte *&str) {
ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen;
UserInterface &ui = *_vm->_ui;
+ if (_vm->getLanguage() == Common::DE_DEU)
+ skipBadText(str);
+
// If the window isn't yet open, draw the window before printing starts
if (!ui._windowOpen && _noTextYet) {
_noTextYet = false;
@@ -528,6 +532,11 @@ OpcodeReturn ScalpelTalk::cmdSummonWindow(const byte *&str) {
return RET_SUCCESS;
}
+void ScalpelTalk::loadTalkFile(const Common::String &filename) {
+ Talk::loadTalkFile(filename);
+ _3doSpeechIndex = 0;
+}
+
void ScalpelTalk::talkWait(const byte *&str) {
UserInterface &ui = *_vm->_ui;
bool pauseFlag = _pauseFlag;
@@ -548,12 +557,49 @@ void ScalpelTalk::nothingToSay() {
}
void ScalpelTalk::switchSpeaker() {
- // If it's the 3DO, pass on to start the actor's conversation movie
- if (IS_3DO)
- talk3DOMovieTrigger(_3doSpeechIndex++);
}
-void ScalpelTalk::talk3DOMovieTrigger(int subIndex) {
+int ScalpelTalk::waitForMore(int delay) {
+ Events &events = *_vm->_events;
+
+ if (!IS_3DO) {
+ return Talk::waitForMore(delay);
+ }
+
+ // Hide the cursor
+ events.hideCursor();
+ events.wait(1);
+
+ switchSpeaker();
+
+ // Play the video
+ talk3DOMovieTrigger(_3doSpeechIndex++);
+
+ // Adjust _talkStealth mode:
+ // mode 1 - It was by a pause without stealth being on before the pause, so reset back to 0
+ // mode 3 - It was set by a pause with stealth being on before the pause, to set it to active
+ // mode 0/2 (Inactive/active) No change
+ switch (_talkStealth) {
+ case 1:
+ _talkStealth = 0;
+ break;
+ case 2:
+ _talkStealth = 2;
+ break;
+ default:
+ break;
+ }
+
+ events.showCursor();
+ events._pressed = events._released = false;
+
+ return 254;
+}
+
+bool ScalpelTalk::talk3DOMovieTrigger(int subIndex) {
+ ScalpelEngine &vm = *(ScalpelEngine *)_vm;
+ Screen &screen = *_vm->_screen;
+
// Find out a few things that we need
int userSelector = _vm->_ui->_selector;
int scriptSelector = _scriptSelect;
@@ -567,15 +613,14 @@ void ScalpelTalk::talk3DOMovieTrigger(int subIndex) {
if (scriptSelector >= 0) {
// Script-selected dialog
selector = scriptSelector;
- subIndex--; // for scripts we adjust subIndex, b/c we won't get called from doTalkControl()
} else {
- warning("talk3DOMovieTrigger: unable to find selector");
- return;
+ warning("talk3DOMovieTrigger: unable to find selector");
+ return true;
}
}
// Make a quick update, so that current text is shown on screen
- _vm->_screen->update();
+ screen.update();
// Figure out that movie filename
Common::String movieFilename;
@@ -597,10 +642,45 @@ void ScalpelTalk::talk3DOMovieTrigger(int subIndex) {
warning("selector: %d", selector);
warning("subindex: %d", subIndex);
- Scalpel3DOMoviePlay(movieFilename.c_str(), Common::Point(5, 5));
+ bool result = vm.play3doMovie(movieFilename, get3doPortraitPosition(), true);
// Restore screen HACK
_vm->_screen->makeAllDirty();
+
+ return result;
+}
+
+Common::Point ScalpelTalk::get3doPortraitPosition() const {
+ // TODO: This current method is only an assumption of how the original figured
+ // out where to place each character's portrait movie.
+ People &people = *_vm->_people;
+ Scene &scene = *_vm->_scene;
+ const int PORTRAIT_W = 100;
+ const int PORTRAIT_H = 76;
+
+ if (_speaker == -1)
+ return Common::Point();
+
+ // Get the position of the character
+ Common::Point pt;
+ if (_speaker == HOLMES) {
+ pt = Common::Point(people[HOLMES]._position.x / FIXED_INT_MULTIPLIER,
+ people[HOLMES]._position.y / FIXED_INT_MULTIPLIER);
+ } else {
+ int objNum = people.findSpeaker(_speaker);
+ if (objNum == -1)
+ return Common::Point();
+
+ pt = scene._bgShapes[objNum]._position;
+ }
+
+ // Adjust the top-left so the center of the portrait will be on the character,
+ // but ensure the portrait will be entirely on-screen
+ pt -= Common::Point(PORTRAIT_W / 2, PORTRAIT_H / 2);
+ pt.x = CLIP((int)pt.x, 10, SHERLOCK_SCREEN_WIDTH - 10 - PORTRAIT_W);
+ pt.y = CLIP((int)pt.y, 10, CONTROLS_Y - PORTRAIT_H - 10);
+
+ return pt;
}
void ScalpelTalk::drawInterface() {
@@ -629,10 +709,14 @@ void ScalpelTalk::drawInterface() {
screen.makeButton(Common::Rect(181, CONTROLS_Y, 221, CONTROLS_Y + 10),
200 - screen.stringWidth(fixedText_Down) / 2, fixedText_Down);
} else {
- int strWidth = screen.stringWidth(Scalpel::PRESS_KEY_TO_CONTINUE);
+ Common::String fixedText_PressKeyToContinue = fixedText.getText(kFixedText_PressKey_ToContinue);
+ Common::String fixedText_PressKeyToContinueHotkey = fixedText.getText(kFixedText_PressKey_ToContinueHotkey);
+ int fixedText_PressKeyToContinueLen = screen.stringWidth(fixedText_PressKeyToContinue);
+
screen.makeButton(Common::Rect(46, CONTROLS_Y, 273, CONTROLS_Y + 10),
- 160 - strWidth / 2, Scalpel::PRESS_KEY_TO_CONTINUE);
- screen.gPrint(Common::Point(160 - strWidth / 2, CONTROLS_Y), COMMAND_FOREGROUND, "P");
+ 160 - fixedText_PressKeyToContinueLen / 2, fixedText_PressKeyToContinue);
+ screen.gPrint(Common::Point(160 - fixedText_PressKeyToContinueLen / 2, CONTROLS_Y), COMMAND_FOREGROUND,
+ "%s", fixedText_PressKeyToContinueHotkey.c_str());
}
}
@@ -930,6 +1014,14 @@ void ScalpelTalk::clearSequences() {
_sequenceStack.clear();
}
+void ScalpelTalk::skipBadText(const byte *&msgP) {
+ // WORKAROUND: Skip over bad text in the original game
+ const char *BAD_PHRASE1 = "Change Speaker to Sherlock Holmes ";
+
+ if (!strncmp((const char *)msgP, BAD_PHRASE1, strlen(BAD_PHRASE1)))
+ msgP += strlen(BAD_PHRASE1);
+}
+
} // End of namespace Scalpel
} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel_talk.h b/engines/sherlock/scalpel/scalpel_talk.h
index 31f78cbf85..3ba61dadc1 100644
--- a/engines/sherlock/scalpel/scalpel_talk.h
+++ b/engines/sherlock/scalpel/scalpel_talk.h
@@ -39,6 +39,11 @@ class ScalpelTalk : public Talk {
private:
Common::Stack<SequenceEntry> _sequenceStack;
+ /**
+ * Get the center position for the current speaker, if any
+ */
+ Common::Point get3doPortraitPosition() const;
+
OpcodeReturn cmdSwitchSpeaker(const byte *&str);
OpcodeReturn cmdAssignPortraitLocation(const byte *&str);
OpcodeReturn cmdGotoScene(const byte *&str);
@@ -84,6 +89,12 @@ public:
virtual ~ScalpelTalk() {}
/**
+ * Opens the talk file 'talk.tlk' and searches the index for the specified
+ * conversation. If found, the data for that conversation is loaded
+ */
+ virtual void loadTalkFile(const Common::String &filename);
+
+ /**
* Called whenever a conversation or item script needs to be run. For standard conversations,
* it opens up a description window similar to how 'talk' does, but shows a 'reply' directly
* instead of waiting for a statement option.
@@ -94,6 +105,12 @@ public:
virtual void talkTo(const Common::String filename);
/**
+ * When the talk window has been displayed, waits a period of time proportional to
+ * the amount of text that's been displayed
+ */
+ virtual int waitForMore(int delay);
+
+ /**
* Draws the interface for conversation display
*/
void drawInterface();
@@ -112,7 +129,12 @@ public:
/**
* Trigger to play a 3DO talk dialog movie
*/
- void talk3DOMovieTrigger(int subIndex);
+ bool talk3DOMovieTrigger(int subIndex);
+
+ /**
+ * Handles skipping over bad text in conversations
+ */
+ static void skipBadText(const byte *&msgP);
/**
* Push the details of a passed object onto the saved sequences stack
@@ -128,7 +150,7 @@ public:
/**
* Returns true if the script stack is empty
*/
- virtual bool isSequencesEmpty() const { return _scriptStack.empty(); }
+ virtual bool isSequencesEmpty() const { return _sequenceStack.empty(); }
/**
* Clears the stack of pending object sequences associated with speakers in the scene
diff --git a/engines/sherlock/scalpel/scalpel_user_interface.cpp b/engines/sherlock/scalpel/scalpel_user_interface.cpp
index a67d464a11..79d74ba999 100644
--- a/engines/sherlock/scalpel/scalpel_user_interface.cpp
+++ b/engines/sherlock/scalpel/scalpel_user_interface.cpp
@@ -65,9 +65,8 @@ const int INVENTORY_POINTS[8][3] = {
};
const char COMMANDS[13] = "LMTPOCIUGJFS";
+const char COMMANDS_3DO[13] = "LMTPOCIUGSFF";
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 int UI_OFFSET_3DO = 16; // (320 - 288) / 2
/*----------------------------------------------------------------*/
@@ -118,10 +117,18 @@ void ScalpelUserInterface::drawInterface(int bufferNum) {
const ImageFrame &src = (*_controlPanel)[0];
int16 x = (!IS_3DO) ? 0 : UI_OFFSET_3DO;
- if (bufferNum & 1)
+ if (bufferNum & 1) {
+ if (IS_3DO)
+ screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y,
+ SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BLACK);
screen._backBuffer1.transBlitFrom(src, Common::Point(x, CONTROLS_Y));
- if (bufferNum & 2)
+ }
+ if (bufferNum & 2) {
+ if (IS_3DO)
+ screen._backBuffer2.fillRect(Common::Rect(0, CONTROLS_Y,
+ SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BLACK);
screen._backBuffer2.transBlitFrom(src, Common::Point(x, CONTROLS_Y));
+ }
if (bufferNum == 3)
screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK);
}
@@ -459,8 +466,8 @@ void ScalpelUserInterface::toggleButton(int num) {
void ScalpelUserInterface::clearInfo() {
if (_infoFlag) {
- _vm->_screen->vgaBar(Common::Rect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 19,
- INFO_LINE + 10), INFO_BLACK);
+ _vm->_screen->vgaBar(Common::Rect(IS_3DO ? 33 : 16, INFO_LINE,
+ SHERLOCK_SCREEN_WIDTH - (IS_3DO ? 33 : 19), INFO_LINE + 10), INFO_BLACK);
_infoFlag = false;
_oldLook = -1;
}
@@ -768,7 +775,7 @@ void ScalpelUserInterface::doEnvControl() {
} else if ((found == 1 && events._released) || _key == 'L') {
saves._envMode = SAVEMODE_LOAD;
if (_selector != -1) {
- saves.loadGame(_selector + 1);
+ saves.loadGame(_selector);
}
} else if ((found == 2 && events._released) || _key == 'S') {
saves._envMode = SAVEMODE_SAVE;
@@ -777,7 +784,7 @@ void ScalpelUserInterface::doEnvControl() {
_oldSelector = _selector;
if (saves.promptForDescription(_selector)) {
- saves.saveGame(_selector + 1, saves._savegames[_selector]);
+ saves.saveGame(_selector, saves._savegames[_selector]);
banishWindow(1);
_windowBounds.top = CONTROLS_Y1;
@@ -860,7 +867,7 @@ void ScalpelUserInterface::doEnvControl() {
// Check whether there are more pending D keys pressed
moreKeys = false;
if (events.kbHit()) {
- Common::KeyState keyState;
+ Common::KeyState keyState = events.getKey();
_key = toupper(keyState.keycode);
moreKeys = _key == 'D';
@@ -941,14 +948,14 @@ void ScalpelUserInterface::doEnvControl() {
if (_selector != -1) {
// Are we already in Load mode?
if (saves._envMode == SAVEMODE_LOAD) {
- saves.loadGame(_selector + 1);
+ saves.loadGame(_selector);
} 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]);
+ saves.saveGame(_selector, saves._savegames[_selector]);
banishWindow();
_windowBounds.top = CONTROLS_Y1;
_key = _oldKey = -1;
@@ -1264,10 +1271,12 @@ void ScalpelUserInterface::doLookControl() {
}
void ScalpelUserInterface::doMainControl() {
+ ScalpelEngine &vm = *(ScalpelEngine *)_vm;
Events &events = *_vm->_events;
ScalpelInventory &inv = *(ScalpelInventory *)_vm->_inventory;
ScalpelSaveManager &saves = *(ScalpelSaveManager *)_vm->_saves;
Common::Point pt = events.mousePos();
+ const char *commands = IS_3DO ? COMMANDS_3DO : COMMANDS;
if ((events._pressed || events._released) && pt.y > CONTROLS_Y) {
events.clearKeyboard();
@@ -1282,16 +1291,18 @@ void ScalpelUserInterface::doMainControl() {
r.right += UI_OFFSET_3DO - 1;
}
if (r.contains(pt))
- _key = COMMANDS[_temp];
+ _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;
+ char key = toupper(_keyPress);
+ const char *c = strchr(commands, key);
+ if (c) {
+ _temp = c - commands;
+ _key = key;
} else {
_temp = 12;
}
@@ -1372,28 +1383,38 @@ void ScalpelUserInterface::doMainControl() {
journalControl();
break;
case 'F':
- pushButton(10);
+ if (IS_3DO) {
+ if (_temp == 10) {
+ pushButton(10);
+ vm.showScummVMRestoreDialog();
+ } else if (_temp == 11) {
+ pushButton(11);
+ vm.showScummVMSaveDialog();
+ }
+ } else {
+ pushButton(10);
- // Create a thumbnail of the current screen before the files dialog is shown, in case
- // the user saves the game
- saves.createThumbnail();
+ // 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;
+ _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;
+ 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);
+ pushButton(IS_3DO ? 9 : 11);
_menuMode = SETUP_MODE;
Settings::show(_vm);
break;
@@ -1645,9 +1666,6 @@ void ScalpelUserInterface::doTalkControl() {
sound._speechPlaying = false;
}
- if (IS_3DO)
- // Trigger to play 3DO movie
- talk.talk3DOMovieTrigger(0);
talk.waitForMore(talk._statements[_selector]._statement.size());
if (talk._talkToAbort)
@@ -1790,6 +1808,7 @@ void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool first
ScalpelInventory &inv = *(ScalpelInventory *)_vm->_inventory;
ScalpelScreen &screen = *(ScalpelScreen *)_vm->_screen;
Talk &talk = *_vm->_talk;
+ FixedText &fixedText = *_vm->_fixedText;
if (str.hasPrefix("_")) {
_lookScriptFlag = true;
@@ -1920,20 +1939,26 @@ void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool first
// Handle display depending on whether all the message was shown
if (!endOfStr) {
+ Common::String fixedText_PressKeyForMore = fixedText.getText(kFixedText_PressKey_ForMore);
+ Common::String fixedText_PressKeyForMoreHotkey = fixedText.getText(kFixedText_PressKey_ForMoreHotkey);
+ int fixedText_PressKeyForMoreLen = screen.stringWidth(fixedText_PressKeyForMore);
+
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");
+ (SHERLOCK_SCREEN_WIDTH - fixedText_PressKeyForMoreLen) / 2,
+ fixedText_PressKeyForMore);
+ screen.gPrint(Common::Point((SHERLOCK_SCREEN_WIDTH - fixedText_PressKeyForMoreLen) / 2, CONTROLS_Y),
+ COMMAND_FOREGROUND, "%s", fixedText_PressKeyForMoreHotkey.c_str());
_descStr = msgP;
} else {
+ Common::String fixedText_PressKeyToContinue = fixedText.getText(kFixedText_PressKey_ToContinue);
+ Common::String fixedText_PressKeyToContinueHotkey = fixedText.getText(kFixedText_PressKey_ToContinueHotkey);
+ int fixedText_PressKeyToContinueLen = screen.stringWidth(fixedText_PressKeyToContinue);
+
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");
+ (SHERLOCK_SCREEN_WIDTH - fixedText_PressKeyToContinueLen) / 2,
+ fixedText_PressKeyToContinue);
+ screen.gPrint(Common::Point((SHERLOCK_SCREEN_WIDTH - fixedText_PressKeyToContinueLen) / 2, CONTROLS_Y),
+ COMMAND_FOREGROUND, "%s", fixedText_PressKeyToContinueHotkey.c_str());
_descStr = "";
}
diff --git a/engines/sherlock/scalpel/scalpel_user_interface.h b/engines/sherlock/scalpel/scalpel_user_interface.h
index 9a55189a66..8c2f3f9e3b 100644
--- a/engines/sherlock/scalpel/scalpel_user_interface.h
+++ b/engines/sherlock/scalpel/scalpel_user_interface.h
@@ -34,12 +34,11 @@ class Talk;
namespace Scalpel {
extern const char COMMANDS[13];
+extern const char COMMANDS_3DO[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;
diff --git a/engines/sherlock/scalpel/tsage/logo.cpp b/engines/sherlock/scalpel/tsage/logo.cpp
index 64539b941a..273d26df74 100644
--- a/engines/sherlock/scalpel/tsage/logo.cpp
+++ b/engines/sherlock/scalpel/tsage/logo.cpp
@@ -163,6 +163,7 @@ Object::Object() {
_angle = _changeCtr = 0;
_walkStartFrame = 0;
_majorDiff = _minorDiff = 0;
+ _updateStartFrame = 0;
}
void Object::setVisage(int visage, int strip) {
@@ -423,6 +424,7 @@ Logo::Logo(ScalpelEngine *vm) : _vm(vm), _lib("sf3.rlb") {
// Initialize counter
_counter = 0;
+ _frameCounter = 0;
// Initialize wait frame counters
_waitFrames = 0;
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 4e40032df9..6f9ef179a3 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -26,6 +26,7 @@
#include "sherlock/scalpel/scalpel.h"
#include "sherlock/scalpel/scalpel_people.h"
#include "sherlock/scalpel/scalpel_scene.h"
+#include "sherlock/scalpel/scalpel_screen.h"
#include "sherlock/tattoo/tattoo.h"
#include "sherlock/tattoo/tattoo_scene.h"
#include "sherlock/tattoo/tattoo_user_interface.h"
@@ -215,7 +216,6 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) {
_currentScene = -1;
_goToScene = -1;
- _loadingSavedGame = false;
_walkedInScene = false;
_version = 0;
_compressed = false;
@@ -273,6 +273,8 @@ void Scene::selectScene() {
}
void Scene::freeScene() {
+ SaveManager &saves = *_vm->_saves;
+
if (_currentScene == -1)
return;
@@ -283,10 +285,8 @@ void Scene::freeScene() {
_vm->_music->freeSong();
_vm->_sound->freeLoadedSounds();
- if (!_loadingSavedGame)
+ if (!saves._justLoaded)
saveSceneStatus();
- else
- _loadingSavedGame = false;
_sequenceBuffer.clear();
_descText.clear();
@@ -562,34 +562,37 @@ bool Scene::loadScene(const Common::String &filename) {
// Read in the walk data
size = rrmStream->readUint16LE();
- Common::SeekableReadStream *walkStream = !_compressed ? rrmStream :
+ Common::SeekableReadStream *walkStream = !_compressed ? rrmStream->readStream(size) :
res.decompress(*rrmStream, size);
- int startPos = walkStream->pos();
- while ((walkStream->pos() - startPos) < size) {
- _walkPoints.push_back(WalkArray());
- _walkPoints[_walkPoints.size() - 1]._fileOffset = walkStream->pos() - startPos;
- _walkPoints[_walkPoints.size() - 1].load(*walkStream, IS_ROSE_TATTOO);
- }
-
- if (_compressed)
- delete walkStream;
-
// Translate the file offsets of the walk directory to indexes in the loaded walk data
for (uint idx1 = 0; idx1 < _zones.size(); ++idx1) {
for (uint idx2 = 0; idx2 < _zones.size(); ++idx2) {
- int fileOffset = _walkDirectory[idx1][idx2];
- if (fileOffset == -1)
+ int dataOffset = _walkDirectory[idx1][idx2];
+ if (dataOffset == -1)
continue;
+ // Check to see if we've already loaded the walk set for the given data offset
uint dataIndex = 0;
- while (dataIndex < _walkPoints.size() && _walkPoints[dataIndex]._fileOffset != fileOffset)
+ while (dataIndex < _walkPoints.size() && _walkPoints[dataIndex]._fileOffset != dataOffset)
++dataIndex;
- assert(dataIndex < _walkPoints.size());
+
+ if (dataIndex == _walkPoints.size()) {
+ // Walk data for that offset hasn't been loaded yet, so load it now
+ _walkPoints.push_back(WalkArray());
+
+ walkStream->seek(dataOffset);
+ _walkPoints[_walkPoints.size() - 1]._fileOffset = dataOffset;
+ _walkPoints[_walkPoints.size() - 1].load(*walkStream, IS_ROSE_TATTOO);
+ dataIndex = _walkPoints.size() - 1;
+ }
+
_walkDirectory[idx1][idx2] = dataIndex;
}
}
+ delete walkStream;
+
if (IS_ROSE_TATTOO) {
// Read in the entrance
_entrance.load(*rrmStream);
@@ -892,28 +895,38 @@ bool Scene::loadScene(const Common::String &filename) {
// === WALK DATA === Read in the walk data
roomStream->seek(header3DO_walkData_offset);
- int startPos = roomStream->pos();
- while ((roomStream->pos() - startPos) < (int)header3DO_walkData_size) {
- _walkPoints.push_back(WalkArray());
- _walkPoints[_walkPoints.size() - 1]._fileOffset = roomStream->pos() - startPos;
- _walkPoints[_walkPoints.size() - 1].load(*roomStream, false);
- }
+ // Read in the walk data
+ Common::SeekableReadStream *walkStream = !_compressed ? roomStream->readStream(header3DO_walkData_size) :
+ res.decompress(*roomStream, header3DO_walkData_size);
// Translate the file offsets of the walk directory to indexes in the loaded walk data
for (uint idx1 = 0; idx1 < _zones.size(); ++idx1) {
for (uint idx2 = 0; idx2 < _zones.size(); ++idx2) {
- int fileOffset = _walkDirectory[idx1][idx2];
- if (fileOffset == -1)
+ int dataOffset = _walkDirectory[idx1][idx2];
+ if (dataOffset == -1)
continue;
+ // Check to see if we've already loaded the walk set for the given data offset
uint dataIndex = 0;
- while (dataIndex < _walkPoints.size() && _walkPoints[dataIndex]._fileOffset != fileOffset)
+ while (dataIndex < _walkPoints.size() && _walkPoints[dataIndex]._fileOffset != dataOffset)
++dataIndex;
- assert(dataIndex < _walkPoints.size());
+
+ if (dataIndex == _walkPoints.size()) {
+ // Walk data for that offset hasn't been loaded yet, so load it now
+ _walkPoints.push_back(WalkArray());
+
+ walkStream->seek(dataOffset);
+ _walkPoints[_walkPoints.size() - 1]._fileOffset = dataOffset;
+ _walkPoints[_walkPoints.size() - 1].load(*walkStream, IS_ROSE_TATTOO);
+ dataIndex = _walkPoints.size() - 1;
+ }
+
_walkDirectory[idx1][idx2] = dataIndex;
}
}
+ delete walkStream;
+
// === EXITS === Read in the exits
roomStream->seek(header3DO_exits_offset);
@@ -1090,9 +1103,9 @@ void Scene::checkSceneFlags(bool flag) {
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
- bool objectFlag = true;
if (o._requiredFlag[0] || o._requiredFlag[1]) {
+ bool objectFlag = true;
if (o._requiredFlag[0] != 0)
objectFlag = _vm->readFlags(o._requiredFlag[0]);
if (o._requiredFlag[1] != 0)
@@ -1282,7 +1295,7 @@ void Scene::transitionToScene() {
} else {
// fade in for 3DO
screen.clear();
- screen.fadeIntoScreen3DO(3);
+ static_cast<Scalpel::Scalpel3DOScreen *>(_vm->_screen)->fadeIntoScreen3DO(3);
}
} else {
screen.slamArea(screen._currentScroll.x, screen._currentScroll.y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
@@ -1376,7 +1389,6 @@ void Scene::synchronize(Serializer &s) {
s.syncAsSint16LE(_currentScene);
} else {
s.syncAsSint16LE(_goToScene);
- _loadingSavedGame = true;
}
for (int sceneNum = 1; sceneNum < SCENES_COUNT; ++sceneNum) {
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index f75dfb40cd..f7aa39fd41 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -145,8 +145,6 @@ public:
class Scene {
private:
- bool _loadingSavedGame;
-
/**
* Loads sounds for the scene
*/
@@ -229,7 +227,7 @@ public:
Common::Array<Exit> _exits;
SceneEntry _entrance;
Common::Array<SceneSound> _sounds;
- ObjectArray _canimShapes;
+ Common::Array<Object *> _canimShapes;
Common::Array<ScaleZone> _scaleZones;
Common::StringArray _objSoundList;
bool _restoreFlag;
diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp
index 4233bca0cb..74da2a80ea 100644
--- a/engines/sherlock/screen.cpp
+++ b/engines/sherlock/screen.cpp
@@ -30,15 +30,17 @@
namespace Sherlock {
Screen *Screen::init(SherlockEngine *vm) {
- if (vm->getGameID() == GType_SerratedScalpel)
- return new Scalpel::ScalpelScreen(vm);
- else
+ if (vm->getGameID() == GType_RoseTattoo)
return new Screen(vm);
+ else if (vm->getPlatform() == Common::kPlatform3DO)
+ return new Scalpel::Scalpel3DOScreen(vm);
+ else
+ return new Scalpel::ScalpelScreen(vm);
}
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()),
+ _backBuffer1(vm->getGameID() == GType_RoseTattoo ? 640 : 320, vm->getGameID() == GType_RoseTattoo ? 480 : 200),
+ _backBuffer2(vm->getGameID() == GType_RoseTattoo ? 640 : 320, vm->getGameID() == GType_RoseTattoo ? 480 : 200),
_backBuffer(&_backBuffer1) {
_transitionSeed = 1;
_fadeStyle = false;
@@ -219,133 +221,9 @@ void Screen::verticalTransition() {
}
}
-void Screen::fadeIntoScreen3DO(int speed) {
- Events &events = *_vm->_events;
- uint16 *currentScreenBasePtr = (uint16 *)getPixels();
- uint16 *targetScreenBasePtr = (uint16 *)_backBuffer->getPixels();
- uint16 currentScreenPixel = 0;
- uint16 targetScreenPixel = 0;
-
- uint16 currentScreenPixelRed = 0;
- uint16 currentScreenPixelGreen = 0;
- uint16 currentScreenPixelBlue = 0;
-
- uint16 targetScreenPixelRed = 0;
- uint16 targetScreenPixelGreen = 0;
- uint16 targetScreenPixelBlue = 0;
-
- uint16 screenWidth = this->w();
- uint16 screenHeight = this->h();
- uint16 screenX = 0;
- uint16 screenY = 0;
- uint16 pixelsChanged = 0;
-
- _dirtyRects.clear();
-
- do {
- pixelsChanged = 0;
- uint16 *currentScreenPtr = currentScreenBasePtr;
- uint16 *targetScreenPtr = targetScreenBasePtr;
-
- for (screenY = 0; screenY < screenHeight; screenY++) {
- for (screenX = 0; screenX < screenWidth; screenX++) {
- currentScreenPixel = *currentScreenPtr;
- targetScreenPixel = *targetScreenPtr;
-
- if (currentScreenPixel != targetScreenPixel) {
- // pixel doesn't match, adjust accordingly
- currentScreenPixelRed = currentScreenPixel & 0xF800;
- currentScreenPixelGreen = currentScreenPixel & 0x07E0;
- currentScreenPixelBlue = currentScreenPixel & 0x001F;
- targetScreenPixelRed = targetScreenPixel & 0xF800;
- targetScreenPixelGreen = targetScreenPixel & 0x07E0;
- targetScreenPixelBlue = targetScreenPixel & 0x001F;
-
- if (currentScreenPixelRed != targetScreenPixelRed) {
- if (currentScreenPixelRed < targetScreenPixelRed) {
- currentScreenPixelRed += 0x0800;
- } else {
- currentScreenPixelRed -= 0x0800;
- }
- }
- if (currentScreenPixelGreen != targetScreenPixelGreen) {
- // Adjust +2/-2 because we are running RGB555 at RGB565
- if (currentScreenPixelGreen < targetScreenPixelGreen) {
- currentScreenPixelGreen += 0x0040;
- } else {
- currentScreenPixelGreen -= 0x0040;
- }
- }
- if (currentScreenPixelBlue != targetScreenPixelBlue) {
- if (currentScreenPixelBlue < targetScreenPixelBlue) {
- currentScreenPixelBlue += 0x0001;
- } else {
- currentScreenPixelBlue -= 0x0001;
- }
- }
- *currentScreenPtr = currentScreenPixelRed | currentScreenPixelGreen | currentScreenPixelBlue;
- pixelsChanged++;
- }
-
- currentScreenPtr++;
- targetScreenPtr++;
- }
- }
-
- // Too much considered dirty at the moment
- addDirtyRect(Common::Rect(0, 0, screenWidth, screenHeight));
-
- events.pollEvents();
- events.delay(10 * speed);
- } while ((pixelsChanged) && (!_vm->shouldQuit()));
-}
-
-void Screen::blitFrom3DOcolorLimit(uint16 limitColor) {
- uint16 *currentScreenPtr = (uint16 *)getPixels();
- uint16 *targetScreenPtr = (uint16 *)_backBuffer->getPixels();
- uint16 currentScreenPixel = 0;
-
- uint16 screenWidth = this->w();
- uint16 screenHeight = this->h();
- uint16 screenX = 0;
- uint16 screenY = 0;
-
- uint16 currentScreenPixelRed = 0;
- uint16 currentScreenPixelGreen = 0;
- uint16 currentScreenPixelBlue = 0;
-
- uint16 limitPixelRed = limitColor & 0xF800;
- uint16 limitPixelGreen = limitColor & 0x07E0;
- uint16 limitPixelBlue = limitColor & 0x001F;
-
- for (screenY = 0; screenY < screenHeight; screenY++) {
- for (screenX = 0; screenX < screenWidth; screenX++) {
- currentScreenPixel = *targetScreenPtr;
-
- currentScreenPixelRed = currentScreenPixel & 0xF800;
- currentScreenPixelGreen = currentScreenPixel & 0x07E0;
- currentScreenPixelBlue = currentScreenPixel & 0x001F;
-
- if (currentScreenPixelRed < limitPixelRed)
- currentScreenPixelRed = limitPixelRed;
- if (currentScreenPixelGreen < limitPixelGreen)
- currentScreenPixelGreen = limitPixelGreen;
- if (currentScreenPixelBlue < limitPixelBlue)
- currentScreenPixelBlue = limitPixelBlue;
-
- *currentScreenPtr = currentScreenPixelRed | currentScreenPixelGreen | currentScreenPixelBlue;
- currentScreenPtr++;
- targetScreenPtr++;
- }
- }
-
- // Too much considered dirty at the moment
- addDirtyRect(Common::Rect(0, 0, screenWidth, screenHeight));
-}
-
void Screen::restoreBackground(const Common::Rect &r) {
if (r.width() > 0 && r.height() > 0)
- _backBuffer1.blitFrom(_backBuffer2, Common::Point(r.left, r.top), r);
+ _backBuffer->blitFrom(_backBuffer2, Common::Point(r.left, r.top), r);
}
void Screen::slamArea(int16 xp, int16 yp, int16 width, int16 height) {
@@ -460,7 +338,7 @@ void Screen::blockMove() {
blockMove(Common::Rect(0, 0, w(), h()));
}
-void Screen::print(const Common::Point &pt, byte color, const char *formatStr, ...) {
+void Screen::print(const Common::Point &pt, uint color, const char *formatStr, ...) {
// Create the string to display
va_list args;
va_start(args, formatStr);
@@ -488,7 +366,7 @@ void Screen::print(const Common::Point &pt, byte color, const char *formatStr, .
slamRect(textBounds);
}
-void Screen::gPrint(const Common::Point &pt, byte color, const char *formatStr, ...) {
+void Screen::gPrint(const Common::Point &pt, uint color, const char *formatStr, ...) {
// Create the string to display
va_list args;
va_start(args, formatStr);
@@ -499,7 +377,7 @@ void Screen::gPrint(const Common::Point &pt, byte color, const char *formatStr,
writeString(str, pt, color);
}
-void Screen::writeString(const Common::String &str, const Common::Point &pt, byte overrideColor) {
+void Screen::writeString(const Common::String &str, const Common::Point &pt, uint overrideColor) {
Fonts::writeString(_backBuffer, str, pt, overrideColor);
}
diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h
index 2e0cef72ca..04a0c1e505 100644
--- a/engines/sherlock/screen.h
+++ b/engines/sherlock/screen.h
@@ -35,22 +35,12 @@ namespace Sherlock {
#define PALETTE_COUNT 256
#define VGA_COLOR_TRANS(x) ((x) * 255 / 63)
#define BG_GREYSCALE_RANGE_END 229
-
-enum {
- BLACK = 0,
- INFO_BLACK = 1,
- BORDER_COLOR = 237,
- COMMAND_BACKGROUND = 4,
- BUTTON_BACKGROUND = 235,
- TALK_FOREGROUND = 12,
- TALK_NULL = 16
-};
+#define BLACK 0
class SherlockEngine;
class Screen : public Surface {
private:
- SherlockEngine *_vm;
Common::List<Common::Rect> _dirtyRects;
uint32 _transitionSeed;
Surface _sceneSurface;
@@ -69,6 +59,13 @@ private:
*/
bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
protected:
+ SherlockEngine *_vm;
+
+ /**
+ * Clear the current dirty rects list
+ */
+ void clearDirtyRects() { _dirtyRects.clear(); }
+
/**
* Adds a rectangle to the list of modified areas of the screen during the
* current frame
@@ -94,7 +91,7 @@ public:
void update();
/**
- * Makes the whole screen dirty, Hack for 3DO movie playing
+ * Makes the whole screen dirty
*/
void makeAllDirty();
@@ -134,22 +131,15 @@ public:
void verticalTransition();
/**
- * Fade backbuffer 1 into screen (3DO RGB!)
- */
- void fadeIntoScreen3DO(int speed);
-
- void blitFrom3DOcolorLimit(uint16 color);
-
- /**
* Prints the text passed onto the back buffer at the given position and color.
* The string is then blitted to the screen
*/
- void print(const Common::Point &pt, byte color, const char *formatStr, ...) GCC_PRINTF(4, 5);
+ void print(const Common::Point &pt, uint color, const char *formatStr, ...) GCC_PRINTF(4, 5);
/**
* Print a strings onto the back buffer without blitting it to the screen
*/
- void gPrint(const Common::Point &pt, byte color, const char *formatStr, ...) GCC_PRINTF(4, 5);
+ void gPrint(const Common::Point &pt, uint color, const char *formatStr, ...) GCC_PRINTF(4, 5);
/**
* Copies a section of the second back buffer into the main back buffer
@@ -223,7 +213,7 @@ public:
/**
* Draws the given string into the back buffer using the images stored in _font
*/
- virtual void writeString(const Common::String &str, const Common::Point &pt, byte overrideColor);
+ virtual void writeString(const Common::String &str, const Common::Point &pt, uint overrideColor);
// Rose Tattoo specific methods
diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp
index ae77c91009..d09fd0b270 100644
--- a/engines/sherlock/sherlock.cpp
+++ b/engines/sherlock/sherlock.cpp
@@ -51,6 +51,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam
_canLoadSave = false;
_showOriginalSavesDialog = false;
_interactiveFl = true;
+ _isScreenDoubled = false;
}
SherlockEngine::~SherlockEngine() {
@@ -237,7 +238,7 @@ void SherlockEngine::loadConfig() {
void SherlockEngine::saveConfig() {
ConfMan.setBool("mute", !_sound->_digitized);
ConfMan.setBool("music_mute", !_music->_musicOn);
- ConfMan.setBool("speech_mute", !_sound->_voices);
+ ConfMan.setBool("speech_mute", !_sound->_speechOn);
ConfMan.setInt("font", _screen->fontNumber());
ConfMan.setBool("fade_style", _screen->_fadeStyle);
diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h
index c05680eb08..b85321c385 100644
--- a/engines/sherlock/sherlock.h
+++ b/engines/sherlock/sherlock.h
@@ -80,6 +80,7 @@ class Resource;
class SherlockEngine : public Engine {
private:
+\
/**
* Main loop for displaying a scene and handling all that occurs within it
*/
@@ -133,6 +134,7 @@ public:
bool _canLoadSave;
bool _showOriginalSavesDialog;
bool _interactiveFl;
+ bool _isScreenDoubled;
public:
SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc);
virtual ~SherlockEngine();
diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp
index fd51462bc0..56ac2a5d9a 100644
--- a/engines/sherlock/sound.cpp
+++ b/engines/sherlock/sound.cpp
@@ -90,7 +90,7 @@ Sound::Sound(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
void Sound::syncSoundSettings() {
_digitized = !ConfMan.getBool("mute");
_speechOn = !ConfMan.getBool("mute") && !ConfMan.getBool("speech_mute");
- _voices = _speechOn ? 1 : 0;
+ _voices = _digitized ? 1 : 0;
}
void Sound::loadSound(const Common::String &name, int priority) {
@@ -123,25 +123,9 @@ byte Sound::decodeSample(byte sample, byte &reference, int16 &scale) {
bool Sound::playSound(const Common::String &name, WaitType waitType, int priority, const char *libraryFilename) {
stopSound();
- Common::String filename = name;
- if (!filename.contains('.')) {
- if (!IS_3DO) {
- if (IS_SERRATED_SCALPEL) {
- filename += ".SND";
- } else {
- filename += ".WAV";
- }
- } else {
- // 3DO uses .aiff extension
- filename += ".AIFF";
- if (!filename.contains('/')) {
- // if no directory was given, use the room sounds directory
- filename = "rooms/sounds/" + filename;
- }
- }
- }
+ Common::String filename = formFilename(name);
- Audio::SoundHandle soundHandle = (IS_SERRATED_SCALPEL) ? _scalpelEffectsHandle : getFreeSoundHandle();
+ Audio::SoundHandle &soundHandle = (IS_SERRATED_SCALPEL) ? _scalpelEffectsHandle : getFreeSoundHandle();
if (!playSoundResource(filename, libraryFilename, Audio::Mixer::kSFXSoundType, soundHandle))
error("Could not find sound resource - %s", filename.c_str());
@@ -168,6 +152,53 @@ bool Sound::playSound(const Common::String &name, WaitType waitType, int priorit
return retval;
}
+Common::String Sound::formFilename(const Common::String &name) {
+ Common::String filename = name;
+
+ if (!filename.contains('.')) {
+ if (!IS_3DO) {
+ if (IS_SERRATED_SCALPEL) {
+ filename += ".SND";
+ } else {
+ filename += ".WAV";
+ }
+ } else {
+ // 3DO uses .aiff extension
+ filename += ".AIFF";
+ if (!filename.contains('/')) {
+ // if no directory was given, use the room sounds directory
+ filename = "rooms/sounds/" + filename;
+ }
+ }
+ }
+
+ return filename;
+}
+
+void Sound::playAiff(const Common::String &name, int volume, bool loop) {
+ Common::File *file = new Common::File();
+ if (!file->open(name)) {
+ delete file;
+ return;
+ }
+ Audio::AudioStream *stream;
+ Audio::RewindableAudioStream *audioStream = Audio::makeAIFFStream(file, DisposeAfterUse::YES);
+ if (loop) {
+ Audio::AudioStream *loopingStream = Audio::makeLoopingAudioStream(audioStream, 0);
+ stream = loopingStream;
+ } else {
+ stream = audioStream;
+ }
+ stopAiff();
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_aiffHandle, stream, -1, volume);
+}
+
+void Sound::stopAiff() {
+ if (_mixer->isSoundHandleActive(_aiffHandle)) {
+ _mixer->stopHandle(_aiffHandle);
+ }
+}
+
void Sound::playLoadedSound(int bufNum, WaitType waitType) {
if (IS_SERRATED_SCALPEL) {
if (_mixer->isSoundHandleActive(_scalpelEffectsHandle) && (_curPriority > _vm->_scene->_sounds[bufNum]._priority))
@@ -198,7 +229,7 @@ void Sound::freeDigiSound() {
_soundPlaying = false;
}
-Audio::SoundHandle Sound::getFreeSoundHandle() {
+Audio::SoundHandle &Sound::getFreeSoundHandle() {
for (int i = 0; i < MAX_MIXER_CHANNELS; i++) {
if (!_mixer->isSoundHandleActive(_tattooEffectsHandle[i]))
return _tattooEffectsHandle[i];
@@ -214,29 +245,32 @@ void Sound::setVolume(int volume) {
void Sound::playSpeech(const Common::String &name) {
Resources &res = *_vm->_res;
Scene &scene = *_vm->_scene;
- stopSpeech();
-
- // TODO: Technically Scalpel has an sfx command which I've set to call this method because it sets the
- // _voice variable as if it were speech. Need to do a play-through of Scalpel and see if it's ever called.
- // If so, will need to enhance this method to handle the Serrated Scalpel voice resources
- assert(IS_ROSE_TATTOO);
- // Figure out which speech library to use
- Common::String libraryName = Common::String::format("speech%02d.lib", scene._currentScene);
- if ((!scumm_strnicmp(name.c_str(), "SLVE12S", 7)) || (!scumm_strnicmp(name.c_str(), "WATS12X", 7))
- || (!scumm_strnicmp(name.c_str(), "HOLM12X", 7)))
- libraryName = "SPEECH12.LIB";
+ // Stop any previously playing speech
+ stopSpeech();
- // If the speech library file doesn't even exist, then we can't play anything
- Common::File f;
- if (!f.exists(libraryName))
- return;
+ if (IS_SERRATED_SCALPEL) {
+ Common::String filename = formFilename(name);
+ if (playSoundResource(filename, Common::String(), Audio::Mixer::kSFXSoundType, _speechHandle))
+ _speechPlaying = true;
+ } else {
+ // Figure out which speech library to use
+ Common::String libraryName = Common::String::format("speech%02d.lib", scene._currentScene);
+ if ((!scumm_strnicmp(name.c_str(), "SLVE12S", 7)) || (!scumm_strnicmp(name.c_str(), "WATS12X", 7))
+ || (!scumm_strnicmp(name.c_str(), "HOLM12X", 7)))
+ libraryName = "SPEECH12.LIB";
+
+ // If the speech library file doesn't even exist, then we can't play anything
+ Common::File f;
+ if (!f.exists(libraryName))
+ return;
- // Ensure the given library is in the cache
- res.addToCache(libraryName);
+ // Ensure the given library is in the cache
+ res.addToCache(libraryName);
- if (playSoundResource(name, libraryName, Audio::Mixer::kSpeechSoundType, _speechHandle))
- _speechPlaying = true;
+ if (playSoundResource(name, libraryName, Audio::Mixer::kSpeechSoundType, _speechHandle))
+ _speechPlaying = true;
+ }
}
void Sound::stopSpeech() {
diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h
index b2d1584e85..0a0ff83d1f 100644
--- a/engines/sherlock/sound.h
+++ b/engines/sherlock/sound.h
@@ -46,6 +46,7 @@ private:
SherlockEngine *_vm;
Audio::Mixer *_mixer;
Audio::SoundHandle _scalpelEffectsHandle;
+ Audio::SoundHandle _aiffHandle;
Audio::SoundHandle _tattooEffectsHandle[MAX_MIXER_CHANNELS];
Audio::SoundHandle _speechHandle;
int _curPriority;
@@ -60,6 +61,11 @@ private:
*/
bool playSoundResource(const Common::String &name, const Common::String &libFilename,
Audio::Mixer::SoundType soundType, Audio::SoundHandle &handle);
+
+ /**
+ * Form a filename from a passed sound resource name
+ */
+ Common::String formFilename(const Common::String &name);
public:
bool _digitized;
int _voices;
@@ -87,6 +93,16 @@ public:
* Play the sound in the specified resource
*/
bool playSound(const Common::String &name, WaitType waitType, int priority = 100, const char *libraryFilename = nullptr);
+
+ /**
+ * Play the specified AIFF file. (Used for the 3DO Scalpel intro.)
+ */
+ void playAiff(const Common::String &name, int volume = Audio::Mixer::kMaxChannelVolume, bool loop = false);
+
+ /**
+ * Stop the AIFF sound that was started with playAiff().
+ */
+ void stopAiff();
/**
* Play a previously loaded sound
@@ -105,8 +121,14 @@ public:
void freeDigiSound();
- Audio::SoundHandle getFreeSoundHandle();
+ /**
+ * Return a sound handle to use
+ */
+ Audio::SoundHandle &getFreeSoundHandle();
+ /**
+ * Set the volume
+ */
void setVolume(int volume);
/**
diff --git a/engines/sherlock/surface.cpp b/engines/sherlock/surface.cpp
index b56692c704..b7fc76325c 100644
--- a/engines/sherlock/surface.cpp
+++ b/engines/sherlock/surface.cpp
@@ -155,8 +155,8 @@ void Surface::transBlitFromUnscaled(const Graphics::Surface &src, const Common::
return;
if (flipped)
- drawRect = Common::Rect(src.w - drawRect.right, src.h - drawRect.bottom,
- src.w - drawRect.left, src.h - drawRect.top);
+ drawRect = Common::Rect(src.w - drawRect.right, drawRect.top,
+ src.w - drawRect.left, drawRect.bottom);
Common::Point destPt(destRect.left, destRect.top);
addDirtyRect(Common::Rect(destPt.x, destPt.y, destPt.x + drawRect.width(),
@@ -201,33 +201,33 @@ void Surface::transBlitFromUnscaled(const Graphics::Surface &src, const Common::
}
}
-void Surface::fillRect(int x1, int y1, int x2, int y2, byte color) {
+void Surface::fillRect(int x1, int y1, int x2, int y2, uint color) {
fillRect(Common::Rect(x1, y1, x2, y2), color);
}
-void Surface::fillRect(const Common::Rect &r, byte color) {
+void Surface::fillRect(const Common::Rect &r, uint color) {
_surface.fillRect(r, color);
addDirtyRect(r);
}
-void Surface::fill(uint16 color) {
- _surface.fillRect(Common::Rect(_surface.w, _surface.h), color);
+void Surface::fill(uint color) {
+ fillRect(Common::Rect(_surface.w, _surface.h), color);
}
bool Surface::clip(Common::Rect &srcBounds, Common::Rect &destBounds) {
- if (destBounds.left >= _surface.w || destBounds.top >= _surface.h ||
+ if (destBounds.left >= w() || destBounds.top >= h() ||
destBounds.right <= 0 || destBounds.bottom <= 0)
return false;
// Clip the bounds if necessary to fit on-screen
- if (destBounds.right > _surface.w) {
- srcBounds.right -= destBounds.right - _surface.w;
- destBounds.right = _surface.w;
+ if (destBounds.right > w()) {
+ srcBounds.right -= destBounds.right - w();
+ destBounds.right = w();
}
- if (destBounds.bottom > _surface.h) {
- srcBounds.bottom -= destBounds.bottom - _surface.h;
- destBounds.bottom = _surface.h;
+ if (destBounds.bottom > h()) {
+ srcBounds.bottom -= destBounds.bottom - h();
+ destBounds.bottom = h();
}
if (destBounds.top < 0) {
@@ -244,7 +244,7 @@ bool Surface::clip(Common::Rect &srcBounds, Common::Rect &destBounds) {
}
void Surface::clear() {
- fillRect(Common::Rect(0, 0, _surface.w, _surface.h), 0);
+ fillRect(Common::Rect(0, 0, w(), h()), 0);
}
void Surface::free() {
@@ -262,11 +262,11 @@ void Surface::setPixels(byte *pixels, int width, int height, Graphics::PixelForm
_surface.setPixels(pixels);
}
-void Surface::writeString(const Common::String &str, const Common::Point &pt, byte overrideColor) {
+void Surface::writeString(const Common::String &str, const Common::Point &pt, uint overrideColor) {
Fonts::writeString(this, str, pt, overrideColor);
}
-void Surface::writeFancyString(const Common::String &str, const Common::Point &pt, byte overrideColor1, byte overrideColor2) {
+void Surface::writeFancyString(const Common::String &str, const Common::Point &pt, uint overrideColor1, uint overrideColor2) {
writeString(str, Common::Point(pt.x, pt.y), overrideColor1);
writeString(str, Common::Point(pt.x + 1, pt.y), overrideColor1);
writeString(str, Common::Point(pt.x + 2, pt.y), overrideColor1);
diff --git a/engines/sherlock/surface.h b/engines/sherlock/surface.h
index 385fb1793e..378c9be9cd 100644
--- a/engines/sherlock/surface.h
+++ b/engines/sherlock/surface.h
@@ -40,30 +40,32 @@ private:
bool _freePixels;
/**
+ * Copy a surface into this one
+ */
+ void blitFrom(const Graphics::Surface &src);
+protected:
+ Graphics::Surface _surface;
+
+ /**
* Clips the given source bounds so the passed destBounds will be entirely on-screen
*/
bool clip(Common::Rect &srcBounds, Common::Rect &destBounds);
/**
- * Copy a surface into this one
+ * Base method stub for signalling dirty rect areas
*/
- void blitFrom(const Graphics::Surface &src);
+ virtual void addDirtyRect(const Common::Rect &r) {}
/**
* Draws a sub-section of a surface at a given position within this surface
*/
- void blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds);
+ virtual void blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds);
/**
* Draws a surface at a given position within this surface with transparency
*/
- void transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt, bool flipped,
+ virtual void transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt, bool flipped,
int overrideColor);
-
-protected:
- Graphics::Surface _surface;
-
- virtual void addDirtyRect(const Common::Rect &r) {}
public:
Surface(uint16 width, uint16 height);
Surface();
@@ -133,14 +135,14 @@ public:
/**
* Fill a given area of the surface with a given color
*/
- void fillRect(int x1, int y1, int x2, int y2, byte color);
+ void fillRect(int x1, int y1, int x2, int y2, uint color);
/**
* Fill a given area of the surface with a given color
*/
- void fillRect(const Common::Rect &r, byte color);
+ virtual void fillRect(const Common::Rect &r, uint color);
- void fill(uint16 color);
+ void fill(uint color);
/**
* Clear the surface
@@ -165,18 +167,18 @@ public:
/**
* Draws the given string into the back buffer using the images stored in _font
*/
- virtual void writeString(const Common::String &str, const Common::Point &pt, byte overrideColor);
- void writeFancyString(const Common::String &str, const Common::Point &pt, byte overrideColor1, byte overrideColor2);
+ virtual void writeString(const Common::String &str, const Common::Point &pt, uint overrideColor);
+ void writeFancyString(const Common::String &str, const Common::Point &pt, uint overrideColor1, uint overrideColor2);
- inline uint16 w() const { return _surface.w; }
- inline uint16 h() const { return _surface.h; }
+ inline virtual uint16 w() const { return _surface.w; }
+ inline virtual uint16 h() const { return _surface.h; }
inline const byte *getPixels() const { return (const byte *)_surface.getPixels(); }
inline byte *getPixels() { return (byte *)_surface.getPixels(); }
inline byte *getBasePtr(int x, int y) { return (byte *)_surface.getBasePtr(x, y); }
inline const byte *getBasePtr(int x, int y) const { return (const byte *)_surface.getBasePtr(x, y); }
inline Graphics::Surface &getRawSurface() { return _surface; }
- inline void hLine(int x, int y, int x2, uint32 color) { _surface.hLine(x, y, x2, color); }
- inline void vLine(int x, int y, int y2, uint32 color) { _surface.vLine(x, y, y2, color); }
+ inline void hLine(int x, int y, int x2, uint color) { _surface.hLine(x, y, x2, color); }
+ inline void vLine(int x, int y, int y2, uint color) { _surface.vLine(x, y, y2, color); }
};
} // End of namespace Sherlock
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index fa00b9d715..e9c52276f6 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -569,14 +569,13 @@ void Talk::loadTalkFile(const Common::String &filename) {
// Create the base of the sound filename used for talking in Rose Tattoo
if (IS_ROSE_TATTOO && _scriptMoreFlag != 1)
sound._talkSoundFile = Common::String(filename.c_str(), filename.c_str() + 7) + ".";
- else if (IS_3DO)
- _3doSpeechIndex = 1;
// Open the talk file for reading
Common::SeekableReadStream *talkStream = res.load(talkFile);
_converseNum = res.resourceIndex();
talkStream->skip(2); // Skip talk file version num
+ _statements.clear();
_statements.resize(talkStream->readByte());
for (uint idx = 0; idx < _statements.size(); ++idx)
_statements[idx].load(*talkStream, IS_ROSE_TATTOO);
@@ -599,7 +598,7 @@ void Talk::stripVoiceCommands() {
// rest of the name following it
statement._reply = Common::String(statement._reply.c_str(),
statement._reply.c_str() + idx) + " " +
- Common::String(statement._reply.c_str() + 9);
+ Common::String(statement._reply.c_str() + idx + 9);
}
}
@@ -753,6 +752,22 @@ void Talk::doScript(const Common::String &script) {
while (*str++ != '}')
;
} else if (isOpcode(c)) {
+ // the original interpreter checked for c being >= 0x80
+ // and if that is the case, it tried to process it as opcode, BUT ALSO ALWAYS skipped over it
+ // This was done inside the Spanish + German interpreters of Serrated Scalpel, not the original
+ // English interpreter (reverse engineered from the binaries).
+ //
+ // This resulted in special characters not getting shown in case they occurred at the start
+ // of sentences like for example the inverted exclamation mark and the inverted question mark.
+ // For further study see fonts.cpp
+ //
+ // We create an inverted exclamation mark for the Spanish version and we show it.
+ //
+ // Us not skipping over those characters may result in an assert() happening inside fonts.cpp
+ // in case more invalid characters exist.
+ // More information see bug #6931
+ //
+
// Handle control code
switch ((this->*_opcodeTable[c - _opcodes[0]])(str)) {
case RET_EXIT:
@@ -832,7 +847,7 @@ int Talk::waitForMore(int delay) {
playingSpeech = sound.isSpeechPlaying();
do {
- if (IS_SERRATED_SCALPEL && sound._speechOn && !sound.isSpeechPlaying())
+ if (IS_SERRATED_SCALPEL && playingSpeech && !sound.isSpeechPlaying())
people._portrait._frameNumber = -1;
scene.doBgAnim();
@@ -876,7 +891,7 @@ int Talk::waitForMore(int delay) {
} while (!_vm->shouldQuit() && key2 == 254 && (delay || (playingSpeech && sound.isSpeechPlaying()))
&& !events._released && !events._rightReleased);
- // If voices was set 2 to indicate a voice file was place, then reset it back to 1
+ // If voices was set 2 to indicate a Scalpel voice file was playing, then reset it back to 1
if (sound._voices == 2)
sound._voices = 1;
@@ -1025,6 +1040,7 @@ OpcodeReturn Talk::cmdEndTextWindow(const byte *&str) {
OpcodeReturn Talk::cmdHolmesOff(const byte *&str) {
People &people = *_vm->_people;
people[HOLMES]._type = REMOVE;
+ people._holmesOn = false;
return RET_SUCCESS;
}
@@ -1032,6 +1048,7 @@ OpcodeReturn Talk::cmdHolmesOff(const byte *&str) {
OpcodeReturn Talk::cmdHolmesOn(const byte *&str) {
People &people = *_vm->_people;
people[HOLMES]._type = CHARACTER;
+ people._holmesOn = true;
return RET_SUCCESS;
}
@@ -1179,7 +1196,7 @@ void Talk::talkWait(const byte *&str) {
_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 (IS_SERRATED_SCALPEL && _wait >= 0 && _wait < 254) {
if (str[0] == _opcodes[OP_SFX_COMMAND])
str += 9;
}
diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h
index a22a39db94..2c0da24d69 100644
--- a/engines/sherlock/talk.h
+++ b/engines/sherlock/talk.h
@@ -215,10 +215,10 @@ protected:
OpcodeReturn cmdWalkToCAnimation(const byte *&str);
protected:
/**
- * Checks, if a character is an opcode
+ * Checks if a character is an opcode
*/
bool isOpcode(byte checkCharacter);
-
+
/**
* Form a table of the display indexes for statements
*/
@@ -228,7 +228,7 @@ protected:
* When the talk window has been displayed, waits a period of time proportional to
* the amount of text that's been displayed
*/
- int waitForMore(int delay);
+ virtual int waitForMore(int delay);
/**
* Display the talk interface window
@@ -308,7 +308,7 @@ public:
* Opens the talk file 'talk.tlk' and searches the index for the specified
* conversation. If found, the data for that conversation is loaded
*/
- void loadTalkFile(const Common::String &filename);
+ virtual void loadTalkFile(const Common::String &filename);
/**
* Push the sequence of a background object that's an NPC that needs to be
diff --git a/engines/sherlock/tattoo/tattoo.cpp b/engines/sherlock/tattoo/tattoo.cpp
index bfb35565bc..3131df7649 100644
--- a/engines/sherlock/tattoo/tattoo.cpp
+++ b/engines/sherlock/tattoo/tattoo.cpp
@@ -65,10 +65,15 @@ void TattooEngine::initialize() {
_res->addToCache("walk.lib");
// Set up list of people
+ TattooFixedText &fixedText = *(TattooFixedText *)_fixedText;
+ const char *peopleNamePtr = nullptr;
+
for (int idx = 0; idx < TATTOO_MAX_PEOPLE; ++idx) {
+ peopleNamePtr = fixedText.getText(PEOPLE_DATA[idx].fixedTextId);
+
_people->_characters.push_back(PersonData(
- getLanguage() == Common::FR_FRA ? FRENCH_NAMES[idx] : ENGLISH_NAMES[idx],
- PORTRAITS[idx], nullptr, nullptr));
+ peopleNamePtr,
+ PEOPLE_DATA[idx].portrait, nullptr, nullptr));
}
// Load the inventory
diff --git a/engines/sherlock/tattoo/tattoo_darts.cpp b/engines/sherlock/tattoo/tattoo_darts.cpp
index cb4b52b01a..512358933d 100644
--- a/engines/sherlock/tattoo/tattoo_darts.cpp
+++ b/engines/sherlock/tattoo/tattoo_darts.cpp
@@ -30,7 +30,8 @@ namespace Tattoo {
enum {
DART_COLOR_FORE = 5,
- PLAYER_COLOR = 11
+ PLAYER_COLOR = 11,
+ DART_BAR_FORE = 208
};
static const int STATUS_INFO_X = 430;
@@ -69,6 +70,7 @@ Darts::Darts(SherlockEngine *vm) : _vm(vm) {
_handX = 0;
_compPlay = 1;
_escapePressed = false;
+ _spacing = 0;
}
void Darts::playDarts(GameType gameType) {
@@ -77,7 +79,6 @@ void Darts::playDarts(GameType gameType) {
Screen &screen = *_vm->_screen;
int oldFontType = screen.fontNumber();
int playerNum = 0;
- int roundStart, score;
int lastDart;
int numHits = 0;
bool gameOver = false;
@@ -90,8 +91,10 @@ void Darts::playDarts(GameType gameType) {
// Load dart graphics and initialize values
loadDarts();
initDarts();
+ events.hideCursor();
while (!done && !_vm->shouldQuit()) {
+ int roundStart, score;
roundStart = score = (playerNum == 0) ? _score1 : _score2;
showNames(playerNum);
@@ -143,7 +146,6 @@ void Darts::playDarts(GameType gameType) {
} else {
// check for cricket game over
bool allClosed = true;
- int nOtherScore;
for (int y = 0; y < 7; y++) {
if (_cricketScore[playerNum][y] < 3)
@@ -151,7 +153,7 @@ void Darts::playDarts(GameType gameType) {
}
if (allClosed) {
- nOtherScore = (playerNum == 0) ? _score2 : _score1;
+ int nOtherScore = (playerNum == 0) ? _score2 : _score1;
if (score >= nOtherScore)
gameOver = true;
}
@@ -416,7 +418,7 @@ void Darts::erasePowerBars() {
bool Darts::dartHit() {
Events &events = *_vm->_events;
- events.pollEventsAndWait();
+ events.pollEvents();
events.setButtonState();
// Keyboard check
@@ -441,10 +443,7 @@ int Darts::doPowerBar(const Common::Point &pt, byte color, int goToPower, int or
events.clearEvents();
events.delay(100);
- while (!_vm->shouldQuit()) {
- if (idx >= DART_BAR_SIZE)
- break;
-
+ while (!_vm->shouldQuit() && idx < DART_BAR_SIZE) {
if ((goToPower - 1) == idx)
break;
else if (goToPower == 0) {
@@ -492,11 +491,8 @@ int Darts::drawHand(int goToPower, int computer) {
Common::Point pt(DARTBOARD_LEFT - HAND_OFFSET[hand], SHERLOCK_SCREEN_HEIGHT - _handSize.y);
int x = 0;
- while (!_vm->shouldQuit()) {
- if (x >= DARTBOARD_WIDTH)
- break;
-
- if ((goToPower - 1) == x)
+ while (!_vm->shouldQuit() && x < DARTBOARD_WIDTH) {
+ if (computer && x >= (goToPower - 1))
break;
else if (goToPower == 0) {
if (dartHit())
@@ -561,22 +557,20 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
int cx, cy;
- int handCy;
- int drawX = 0, drawY = 0, oldDrawX = 0, oldDrawY = 0;
int xSize = 0, ySize = 0, oldxSize = 0, oldySize = 0;
- int handOCx, handOCy;
- int ocx, ocy;
+ int handOCx = 0, handOCy = 0;
+ int ocx = 0, ocy = 0;
int handOldxSize, handOldySize;
int delta = 9;
int dartNum;
int hddy;
+ Common::Point drawPos, oldDrawPos;
// Draw the animation of the hand throwing the dart first
// See which hand animation to use
ImageFile &hands = !computer ? *_hand1 : *_hand2;
int numFrames = !computer ? 14 : 13;
- ocx = ocy = handOCx = handOCy = 0;
oldxSize = oldySize = handOldxSize = handOldySize = 1;
cx = dartPos.x;
cy = SHERLOCK_SCREEN_HEIGHT - _handSize.y - 20;
@@ -590,7 +584,7 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
for (int idx = 0; idx < numFrames; ++idx) {
_handSize.x = hands[idx]._offset.x + hands[idx]._width;
_handSize.y = hands[idx]._offset.y + hands[idx]._height;
- handCy = SHERLOCK_SCREEN_HEIGHT - _handSize.y;
+ int handCy = SHERLOCK_SCREEN_HEIGHT - _handSize.y;
screen._backBuffer1.transBlitFrom(hands[idx], Common::Point(_handX, handCy));
screen.slamArea(_handX, handCy, _handSize.x + 1, _handSize.y);
@@ -610,37 +604,37 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
xSize = (*_dartGraphics)[dartNum]._width;
ySize = (*_dartGraphics)[dartNum]._height;
- ocx = drawX = cx - (*_dartGraphics)[dartNum]._width / 2;
- ocy = drawY = cy - (*_dartGraphics)[dartNum]._height;
+ ocx = drawPos.x = cx - (*_dartGraphics)[dartNum]._width / 2;
+ ocy = drawPos.y = cy - (*_dartGraphics)[dartNum]._height;
// Draw dart
- screen._backBuffer1.transBlitFrom((*_dartGraphics)[dartNum], dartPos);
+ screen._backBuffer1.transBlitFrom((*_dartGraphics)[dartNum], drawPos);
- if (drawX < 0) {
- xSize += drawX;
+ if (drawPos.x < 0) {
+ xSize += drawPos.x;
if (xSize < 0)
xSize = 1;
- drawX = 0;
+ drawPos.x = 0;
}
- if (drawY < 0) {
- ySize += drawY;
+ if (drawPos.y < 0) {
+ ySize += drawPos.y;
if (ySize < 0)
ySize = 1;
- drawY = 0;
+ drawPos.y = 0;
}
// Flush the drawn dart to the screen
- screen.slamArea(drawX, drawY, xSize, ySize);
- if (oldDrawX != -1)
+ screen.slamArea(drawPos.x, drawPos.y, xSize, ySize);
+ if (oldDrawPos.x != -1)
// Flush the erased dart area
- screen.slamArea(oldDrawX, oldDrawY, oldxSize, oldySize);
+ screen.slamArea(oldDrawPos.x, oldDrawPos.y, oldxSize, oldySize);
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(drawX, drawY),
- Common::Rect(drawX, drawY, drawX + xSize, drawY + ySize));
+ screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(drawPos.x, drawPos.y),
+ Common::Rect(drawPos.x, drawPos.y, drawPos.x + xSize, drawPos.y + ySize));
- oldDrawX = drawX;
- oldDrawY = drawY;
+ oldDrawPos.x = drawPos.x;
+ oldDrawPos.y = drawPos.y;
oldxSize = xSize;
oldySize = ySize;
@@ -654,15 +648,15 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
screen.slamArea(handOCx, handOCy, handOldxSize, handOldySize);
// Erase the old dart
- if (oldDrawX != -1)
- screen.slamArea(oldDrawX, oldDrawY, oldxSize, oldySize);
+ if (oldDrawPos.x != -1)
+ screen.slamArea(oldDrawPos.x, oldDrawPos.y, oldxSize, oldySize);
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(drawX, drawY),
- Common::Rect(drawX, drawY, drawX + xSize, drawY + ySize));
+ screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(drawPos.x, drawPos.y),
+ Common::Rect(drawPos.x, drawPos.y, drawPos.x + xSize, drawPos.y + ySize));
cx = dartPos.x;
cy = dartPos.y + 2;
- oldDrawX = oldDrawY = -1;
+ oldDrawPos.x = oldDrawPos.y = -1;
for (int idx = 5; idx <= 23; ++idx) {
dartNum = idx - 4;
@@ -680,38 +674,37 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
xSize = (*_dartGraphics)[dartNum]._width;
ySize = (*_dartGraphics)[dartNum]._height;
- ocx = drawX = cx - (*_dartGraphics)[dartNum]._width / 2;
- ocy = drawY = cy - (*_dartGraphics)[dartNum]._height;
+ ocx = drawPos.x = cx - (*_dartGraphics)[dartNum]._width / 2;
+ ocy = drawPos.y = cy - (*_dartGraphics)[dartNum]._height;
- screen._backBuffer1.transBlitFrom((*_dartGraphics)[dartNum], Common::Point(drawX, drawY));
+ screen._backBuffer1.transBlitFrom((*_dartGraphics)[dartNum], Common::Point(drawPos.x, drawPos.y));
- if (drawX < 0) {
- xSize += drawX;
+ if (drawPos.x < 0) {
+ xSize += drawPos.x;
if (xSize < 0)
xSize = 1;
- drawX = 0;
+ drawPos.x = 0;
}
- if (drawY < 0) {
- ySize += drawY;
+ if (drawPos.y < 0) {
+ ySize += drawPos.y;
if (ySize < 0)
ySize = 1;
- drawY = 0;
+ drawPos.y = 0;
}
// flush the dart
- screen.slamArea(drawX, drawY, xSize, ySize);
- if (oldDrawX != -1)
- screen.slamArea(oldDrawX, oldDrawY, oldxSize, oldySize);
+ screen.slamArea(drawPos.x, drawPos.y, xSize, ySize);
+ if (oldDrawPos.x != -1)
+ screen.slamArea(oldDrawPos.x, oldDrawPos.y, oldxSize, oldySize);
if (idx != 23)
- screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(drawX, drawY),
- Common::Rect(drawX, drawY, drawX + xSize, drawY + ySize)); // erase dart
+ screen._backBuffer1.blitFrom(screen._backBuffer2, drawPos,
+ Common::Rect(drawPos.x, drawPos.y, drawPos.x + xSize, drawPos.y + ySize)); // erase dart
events.wait(1);
- oldDrawX = drawX;
- oldDrawY = drawY;
+ oldDrawPos = drawPos;
oldxSize = xSize;
oldySize = ySize;
}
@@ -787,8 +780,6 @@ void Darts::getComputerNumber(int playerNum, Common::Point &targetPos) {
int score;
int aim = 0;
Common::Point pt;
- bool done = false;
- int cricketaimset = false;
bool shootBull = false;
score = (playerNum == 0) ? _score1 : _score2;
@@ -799,6 +790,7 @@ void Darts::getComputerNumber(int playerNum, Common::Point &targetPos) {
if(score > 60)
shootBull = true;
} else {
+ bool cricketaimset = false;
if (_cricketScore[playerNum][6] < 3) {
// shoot at bull first
aim = CRICKET_VALUE[6];
@@ -842,6 +834,7 @@ void Darts::getComputerNumber(int playerNum, Common::Point &targetPos) {
}
} else {
// Loop in case number does not exist on board
+ bool done = false;
do {
done = findNumberOnBoard(aim, pt);
--aim;
@@ -906,7 +899,7 @@ int Darts::throwDart(int dartNum, int computer) {
if (!computer) {
// Wait for a hit
while (!dartHit() && !_vm->shouldQuit())
- ;
+ events.wait(1);
if (_escapePressed)
return 0;
} else {
@@ -930,7 +923,7 @@ int Darts::throwDart(int dartNum, int computer) {
if (_escapePressed)
return 0;
- height = doPowerBar(Common::Point(DART_BAR_VX, DART_HEIGHT_Y), DART_COLOR_FORE, targetPos.y, 1);
+ height = doPowerBar(Common::Point(DART_BAR_VX, DART_HEIGHT_Y), DART_BAR_FORE, targetPos.y, 1);
if (_escapePressed)
return 0;
diff --git a/engines/sherlock/tattoo/tattoo_fixed_text.cpp b/engines/sherlock/tattoo/tattoo_fixed_text.cpp
index c9345e44d1..38acd78aba 100644
--- a/engines/sherlock/tattoo/tattoo_fixed_text.cpp
+++ b/engines/sherlock/tattoo/tattoo_fixed_text.cpp
@@ -27,23 +27,22 @@ namespace Sherlock {
namespace Tattoo {
-static const char *const FIXED_TEXT_ENGLISH[] = {
+static const char *const fixedTextEN[] = {
"Money",
- "Card",
- "Tobacco",
- "Timetable",
- "Summons",
- "Foolscap",
- "Damp Paper",
- "Bull's Eye",
-
"Money",
"Card",
+ "Card",
+ "Tobacco",
"Tobacco",
"Timetable",
+ "Timetable",
+ "Summons",
"Summons",
"Foolscap",
"Foolscap",
+ "Damp Paper",
+ "Foolscap",
+ "Bull's Eye",
"Bull's Eye Lantern",
"Open",
@@ -60,7 +59,7 @@ static const char *const FIXED_TEXT_ENGLISH[] = {
"Picked up",
"Page %d",
- "Close Journal",
+ "Close Journal",
"Search Journal",
"Save Journal",
"Abort Search",
@@ -77,13 +76,13 @@ static const char *const FIXED_TEXT_ENGLISH[] = {
"to start",
"Hit a key",
"Press a key",
- "bullseye",
+ "bullseye", // ??
"GAME OVER",
"BUSTED",
"Wins",
"Scored",
"points",
- "Hit",
+ "Hit %s %d",
"Double",
"Triple",
@@ -106,65 +105,167 @@ static const char *const FIXED_TEXT_ENGLISH[] = {
"Yes",
"No",
"Enter Password",
- "Going East"
+ "Going East", // correct password, was not and should not to be translated
+ // SH2: People names
+ "Sherlock Holmes",
+ "Dr. Watson",
+ "Mrs. Hudson",
+ "Stanley Forbes",
+ "Mycroft Holmes",
+ "Wiggins",
+ "Police Constable Burns",
+ "Augustus Trimble",
+ "Police Constable Daley",
+ "Matron",
+ "Sister Grace",
+ "Preston McCabe",
+ "Bob Colleran",
+ "Jonas Rigby",
+ "Police Constable Roach",
+ "James Dewar",
+ "Sergeant Jeremy Duncan",
+ "Inspector Gregson",
+ "Inspector Lestrade",
+ "Jesse Needhem",
+ "Arthur Fleming",
+ "Mr. Thomas Pratt",
+ "Mathilda (Tillie) Mason",
+ "Adrian Russell",
+ "Eldridge Whitney",
+ "Hepplethwaite",
+ "Horace Silverbridge",
+ "Old Sherman",
+ "Maxwell Verner",
+ "Millicent Redding",
+ "Virgil Silverbridge",
+ "George O'Keeffe",
+ "Lord Denys Lawton",
+ "Jenkins",
+ "Jock Mahoney",
+ "Bartender",
+ "Lady Cordelia Lockridge",
+ "Pettigrew",
+ "Sir Avery Fanshawe",
+ "Hodgkins",
+ "Wilbur \"Birdy\" Heywood",
+ "Jacob Farthington",
+ "Philip Bledsoe",
+ "Sidney Fowler",
+ "Professor Theodore Totman",
+ "Rose Hinchem",
+ "Tallboy",
+ "Ethlebert \"Stitch\" Rumsey",
+ "Charles Freedman",
+ "Nigel Hemmings",
+ "Fairfax Carter",
+ "Wilhelm II",
+ "Wachthund",
+ "Jonathan Wilson",
+ "David Lloyd-Jones",
+ "Edward Hargrove",
+ "Misteray",
+ "The Lascar",
+ "Parrot",
+ "Vincent Scarrett",
+ "Alexandra",
+ "Queen Victoria",
+ "John Brown",
+ "A Patient",
+ "A Patient",
+ "Patron",
+ "Queen Victoria",
+ "Patient in white",
+ "Lush",
+ "Drunk",
+ "Prostitute",
+ "Mudlark",
+ "Grinder",
+ "Bouncer",
+ "Agnes Ratchet",
+ "Aloysius Ratchet",
+ "Real Estate Agent",
+ "Candy Clerk",
+ "Beadle",
+ "Prussian",
+ "Mrs. Rowbottom",
+ "Miss Lloyd-Jones",
+ "Tavern patron",
+ "User",
+ "Toby",
+ "Stationer",
+ "Law Clerk",
+ "Ministry Clerk",
+ "Bather",
+ "Maid",
+ "Lady Fanshawe",
+ "Sidney Ratchet",
+ "Boy",
+ "Patron",
+ "Constable Brit",
+ "Wagon Driver"
};
-static const char *const FIXED_TEXT_GERMAN[] = {
+// sharp-s : 0xE1 / octal 341
+// small a-umlaut: 0x84 / octal 204
+// small o-umlaut: 0x94 / octal 224
+// small u-umlaut: 0x81 / octal 201
+// large O-umlaut: 0x99 / octal 231
+static const char *const fixedTextDE[] = {
"Geld",
- "S. Holmes",
- "Tabak",
- "Plan",
- "Aufforderg.",
- "Blatt pap.",
- "Dunstig pap",
- "Handlampe",
-
"Geld",
"S. Holmes",
+ "S. Holmes",
"Tabak",
+ "Tabak",
+ "Plan",
"Plan",
"Aufforderg.",
+ "Aufforderg.",
+ "Blatt pap.",
"Pergament",
"Dunstig pap",
+ "Dunstig pap",
+ "Handlampe",
"Handlampe",
- "ffne",
+ "\231ffne",
"Schau",
"Rede",
"Benutze",
- "Journal",
- "Inventory",
- "Options",
- "Losen",
+ "Tagebuch",
+ "Tasche",
+ "Optionen",
+ "L\224osen",
"mit",
"Keine Wirkung...",
- "Diese Person weic im Augenblick nichts zu berichten.",
+ "Diese Person wei\341 im Augenblick nichts zu berichten.",
+ "Picked up", // <-- ??
"Seite %d",
- "Schliecen",
- "Lessen",
+ "Schlie\341en",
+ "Lessen", // <--
"In Datei sichern",
"Suche abbrechen",
- "Rbckwarts suchen ",
+ "R\201ckw\204rts suchen ",
"Vorwarts suchen ",
"Text nicht gefunden",
"Holmes",
"Jock",
"Bull",
- "Runde",
- "Gesamt",
- "Pfeil",
+ "Runde: %d",
+ "Gesamt: %d",
+ "Pfeil # %d",
"zum Starten",
- "Taste dracken",
- "Taste dracken",
- "Bullseye",
- "SPIEL BEENDET",
- "VERLOREN",
- "Gewinnt",
- "Erzielte",
- "Punkte",
- "Treffer",
+ "Taste dr\201cken",
+ "Taste dr\201cken",
+ "Bullseye", // ??
+ "SPIEL BEENDET!",
+ "VERLOREN!",
+ "Gewinnt!", // "Holmes Gewinnt!", "%s Gewinnt!"
+ "Erzielte %d Punkte",
+ "Punkte", // ??
+ "Treffer %s %d",
"Doppel",
"Dreifach",
@@ -177,7 +278,7 @@ static const char *const FIXED_TEXT_GERMAN[] = {
"Soundeffekte",
"Voices",
"Textfenster",
- "Transparente Menbs",
+ "Transparente Men\201s",
"Schriftart andern",
"Aus",
"An",
@@ -186,19 +287,499 @@ static const char *const FIXED_TEXT_GERMAN[] = {
"Sind Sie sicher ?",
"Ja",
"Nein",
- "Pacwort eingeben",
- "Going East"
+ "Pa\341wort eingeben",
+ "Going East", // correct password, was not and should not to be translated
+ // SH2: People names
+ "Sherlock Holmes", // note: People names were not translated in the German interpreter
+ "Dr. Watson",
+ "Mrs. Hudson",
+ "Stanley Forbes",
+ "Mycroft Holmes",
+ "Wiggins",
+ "Police Constable Burns",
+ "Augustus Trimble",
+ "Police Constable Daley",
+ "Matron",
+ "Sister Grace",
+ "Preston McCabe",
+ "Bob Colleran",
+ "Jonas Rigby",
+ "Police Constable Roach",
+ "James Dewar",
+ "Sergeant Jeremy Duncan",
+ "Inspector Gregson",
+ "Inspector Lestrade",
+ "Jesse Needhem",
+ "Arthur Fleming",
+ "Mr. Thomas Pratt",
+ "Mathilda (Tillie) Mason",
+ "Adrian Russell",
+ "Eldridge Whitney",
+ "Hepplethwaite",
+ "Horace Silverbridge",
+ "Old Sherman",
+ "Maxwell Verner",
+ "Millicent Redding",
+ "Virgil Silverbridge",
+ "George O'Keeffe",
+ "Lord Denys Lawton",
+ "Jenkins",
+ "Jock Mahoney",
+ "Bartender",
+ "Lady Cordelia Lockridge",
+ "Pettigrew",
+ "Sir Avery Fanshawe",
+ "Hodgkins",
+ "Wilbur \"Birdy\" Heywood",
+ "Jacob Farthington",
+ "Philip Bledsoe",
+ "Sidney Fowler",
+ "Professor Theodore Totman",
+ "Rose Hinchem",
+ "Tallboy",
+ "Ethlebert \"Stitch\" Rumsey",
+ "Charles Freedman",
+ "Nigel Hemmings",
+ "Fairfax Carter",
+ "Wilhelm II",
+ "Wachthund",
+ "Jonathan Wilson",
+ "David Lloyd-Jones",
+ "Edward Hargrove",
+ "Misteray",
+ "The Lascar",
+ "Parrot",
+ "Vincent Scarrett",
+ "Alexandra",
+ "Queen Victoria",
+ "John Brown",
+ "A Patient",
+ "A Patient",
+ "Patron",
+ "Queen Victoria",
+ "Patient in white",
+ "Lush",
+ "Drunk",
+ "Prostitute",
+ "Mudlark",
+ "Grinder",
+ "Bouncer",
+ "Agnes Ratchet",
+ "Aloysius Ratchet",
+ "Real Estate Agent",
+ "Candy Clerk",
+ "Beadle",
+ "Prussian",
+ "Mrs. Rowbottom",
+ "Miss Lloyd-Jones",
+ "Tavern patron",
+ "User",
+ "Toby",
+ "Stationer",
+ "Law Clerk",
+ "Ministry Clerk",
+ "Bather",
+ "Maid",
+ "Lady Fanshawe",
+ "Sidney Ratchet",
+ "Boy",
+ "Patron",
+ "Constable Brit",
+ "Wagon Driver"
+};
+
+// small a w/ accent grave: 0x85 / octal 205
+// small e w/ accent acute: 0x82 / octal 202
+// small e w/ accent grave: 0x8A / octal 212
+// small e w/ circonflexe: 0x88 / octal 210
+// small cedilla: 0x87 / octal 207
+static const char *const fixedTextFR[] = {
+ "Argent",
+ "Argent",
+ "S. Holmes",
+ "S. Holmes",
+ "Tabac",
+ "Tabac",
+ "Horaire",
+ "Horaire",
+ "Convocation",
+ "Convocation",
+ "Feuille",
+ "Feuille",
+ "F. humide",
+ "Feuille",
+ "Lanterne",
+ "Lanterne",
+
+ "Ouvrir",
+ "Regarder",
+ "Parler",
+ "Utiliser",
+ "Journal", // <--
+ "Inventaire",
+ "Options",
+ "R\202soudre",
+ "avec",
+ "Sans effet...",
+ "Cette personne n'a rien \205 ajouter pour le moment.",
+ "Picked up", // <-- ??
+
+ "Page %d",
+ "Fermer",
+ "Lessen", // <--
+ "Sauvegarder",
+ "Annuler ",
+ "Chercher avant",
+ "Chercher apr\212s",
+ "Texte introuvable !",
+
+ "Holmes",
+ "Jock",
+ "Bull",
+ "Tour: %d",
+ "Total: %d",
+ "Fl\202chette # %d",
+ "pour commencer",
+ "Appuyez sur C",
+ "Appuyez sur C",
+ "Bullseye", // ??
+ "FIN DE LA PARTIE!", // original: "Fin de la partie!"
+ "FIASCO!",
+ "Gagnant!", // "Holmes Gagnant!", "%s Gagnant!"
+ "Total des points: %d",
+ "Punkte", // ??
+ "Treffer %s %d",
+ "double",
+ "triple",
+
+ "Mouillez",
+ "Puis",
+ "Chauffez",
+ "Charger",
+ "Sauvegarder",
+ "Musique",
+ "Sons",
+ "Voix",
+ "Fen\210tres de texte", // 0x88
+ "Menu Transparent",
+ "Changer la fonte",
+ "Aus", // ???
+ "An", // ???
+ "Quitter",
+ "Voulez-vous quitter?",
+ "Sind Sie sicher ?", // ???
+ "Oui",
+ "Non",
+ "Entrez le mot de passe",
+ "Going East", // correct password, was not and should not to be translated
+ // SH2: People names
+ "Sherlock Holmes",
+ "Dr. Watson",
+ "Mme. Hudson",
+ "Stanley Forbes",
+ "Mycroft Holmes",
+ "Wiggins",
+ "Sergent Burns",
+ "Augustus Trimble",
+ "Sergent Daley",
+ "Infirmi\212re chef",
+ "Mme. Grace",
+ "Preston McCabe",
+ "Bob Colleran",
+ "Jonas Rigby",
+ "Sergent Roach",
+ "James Dewar",
+ "Sergent Jeremy Duncan",
+ "Inspecteur Gregson",
+ "Inspecteur Lestrade",
+ "Jesse Needhem",
+ "Arthur Fleming",
+ "M. Thomas Pratt",
+ "Mathilda (Tillie) Mason",
+ "Adrian Russell",
+ "Eldridge Whitney",
+ "Hepplethwaite",
+ "Horace Silverbridge",
+ "Sherman",
+ "Maxwell Verner",
+ "Millicent Redding",
+ "Virgil Silverbridge",
+ "George O'Keeffe",
+ "Lord Denys Lawton",
+ "Jenkins",
+ "Jock Mahoney",
+ "Serveur",
+ "Lady Cordelia Lockridge",
+ "Pettigrew",
+ "Sir Avery Fanshawe",
+ "Hodgkins",
+ "Wilbur \"Birdy\" Heywood",
+ "Jacob Farthington",
+ "Philip Bledsoe",
+ "Sidney Fowler",
+ "Professeur Theodore Totman",
+ "Rose Hinchem",
+ "Tallboy",
+ "Ethlebert \"Stitch\" Rumsey",
+ "Charles Freedman",
+ "Nigel Hemmings",
+ "Fairfax Carter",
+ "Wilhelm II",
+ "Wachthund",
+ "Jonathan Wilson",
+ "David Lloyd-Jones",
+ "Edward Hargrove",
+ "Misteray",
+ "Le Lascar",
+ "Oiseau",
+ "Vincent Scarrett",
+ "Alexandra",
+ "Queen Victoria",
+ "John Brown",
+ "Patient",
+ "Patient",
+ "Client",
+ "Queen Victoria",
+ "Patient en blanc",
+ "Ivrogne",
+ "Ivrogne",
+ "Belle femme",
+ "Mudlark",
+ "Broyeur",
+ "Videur",
+ "Agnes Ratchet",
+ "Aloysius Ratchet",
+ "Immobilier",
+ "Gar\207on",
+ "Beadle",
+ "Prussian",
+ "Mme. Rowbottom",
+ "Mme Lloyd-Jones",
+ "Tavern Client",
+ "User",
+ "Toby",
+ "Papeterie",
+ "Law Clerc",
+ "Ministry Employ\202",
+ "Clint du thermes",
+ "Bonne",
+ "Lady Fanshawe",
+ "Sidney Ratchet",
+ "Gar\207on",
+ "Client",
+ "Sergent Brit",
+ "Wagon Driver"
+};
+
+// small a w/ accent bottom to top : 0xA0 / octal 240
+// small i w/ accent bottom to top : 0xA1 / octal 241
+// small o w/ accent bottom to top : 0xA2 / octal 242
+// small u w/ accent bottom to top : 0xA3 / octal 243
+// small n w/ wavy line : 0xA4 / octal 244
+// inverted question mark : 0xA8 / octal 250
+static const char *const fixedTextES[] = {
+ "Dinero",
+ "Dinero",
+ "Tarjeta",
+ "Tarjeta",
+ "Tabaco",
+ "Tabaco",
+ "Horarios",
+ "Horarios",
+ "Mensaje",
+ "Mensaje",
+ "Papel",
+ "Papel",
+ "Papel",
+ "Papel",
+ "Linterna",
+ "Linterna",
+
+ "Abrir",
+ "Mirar",
+ "Hablar",
+ "Usar",
+ "Diario",
+ "Inventario",
+ "Opciones",
+ "Resolver",
+ "con",
+ "Sin Efecto...",
+ "Esta persona no tiene nada que decir en este momento",
+ "Picked up", // <-- ??
+
+ "P\240gina %d",
+ "Cerrar Diario",
+ "Lessen", // <-- not included?!?!
+ "Salvar en Archivo",
+ "Detener B\243squeda",
+ "Buscar Hacia Atr\240s",
+ "Buscar Hacia Delante",
+ "Texto No Encontrado !",
+
+ "Holmes", //
+ "Jock",
+ "Bull",
+ "Vuelta: %d",
+ "Total del Turno: %d",
+ "Dardo # %d",
+ "para empezar",
+ "Pulsa una tecla",
+ "Pulsa una tecla",
+ "Golpe %s ojo de buey", // ??
+ "FIN DE LA PARTIDA!",
+ "ROTO!",
+ "Gana!", // "Holmes Gana!", "%s Gana!"
+ "Puntuado %d puntos",
+ "puntos", // ??
+ "Golpe %s %d",
+ "doble",
+ "triple",
+
+ "aplicar",
+ "Agua",
+ "Calentar",
+ "Cargar Partida",
+ "Salvar Partida",
+ "M\243sica",
+ "Efectos de Sonido",
+ "Voces",
+ "Ventanas de Texto",
+ "Men\243s Transparentes",
+ "Cambiar Tipo de Letra",
+ "Off", // ???
+ "On", // ???
+ "Salir",
+ "quieres salir?",
+ "\250Est\240s seguro de que",
+ "Si",
+ "Non",
+ "Introducir Palabra Clave",
+ "Vas al Este", // correct password, was translated in Spanish version (???)
+ // SH2: People names
+ "Sherlock Holmes",
+ "Dr. Watson",
+ "Sta. Hudson",
+ "Stanley Forbes",
+ "Mycroft Holmes",
+ "Wiggins",
+ "Agente de Polic\241a Burns",
+ "Augustus Trimble",
+ "Agente de Polic\241a Daley",
+ "Enfermera",
+ "Hermana Grace",
+ "Preston McCabe",
+ "Bob Colleran",
+ "Jonas Rigby",
+ "Agente de Polic\241a Roach",
+ "James Dewar",
+ "Sargento Jeremy Duncan",
+ "Inspector Gregson",
+ "Inspector Lestrade",
+ "Jesse Needhem",
+ "Arthur Fleming",
+ "Sr. Thomas Pratt",
+ "Mathilda (Tillie) Mason",
+ "Adrian Russell",
+ "Eldridge Whitney",
+ "Hepplethwaite",
+ "Horace Silverbridge",
+ "Old Sherman",
+ "Maxwell Verner",
+ "Millicent Redding",
+ "Virgil Silverbridge",
+ "George O'Keeffe",
+ "Lord Denys Lawton",
+ "Jenkins",
+ "Jock Mahoney",
+ "Camarero",
+ "Lady Cordelia Lockridge",
+ "Pettigrew",
+ "Sir Avery Fanshawe",
+ "Hodgkins",
+ "Wilbur \"Birdy\" Heywood",
+ "Jacob Farthington",
+ "Philip Bledsoe",
+ "Sidney Fowler",
+ "Profesor Theodore Totman",
+ "Rose Hinchem",
+ "Tallboy",
+ "Ethlebert \"Stitch\" Rumsey",
+ "Charles Freedman",
+ "Nigel Hemmings",
+ "Fairfax Carter",
+ "Guillermo II",
+ "Wachthund",
+ "Jonathan Wilson",
+ "David Lloyd-Jones",
+ "Edward Hargrove",
+ "Misteray",
+ "The Lascar",
+ "Loro",
+ "Vincent Scarrett",
+ "Alexandra",
+ "Reina Victoria",
+ "John Brown",
+ "Un Paciente",
+ "Un Paciente",
+ "Cliente",
+ "Reina Victoria",
+ "Paciente de blanco",
+ "Exuberante",
+ "Borracho",
+ "Prostituta",
+ "Mudlark",
+ "Grinder",
+ "Mat\242n", // sic? means block in Spanish and not bouncer?!
+ "Agnes Ratchet",
+ "Aloysius Ratchet",
+ "Agente de Bienes Ra\241ces",
+ "Candy Clerk",
+ "Beadle",
+ "Prusiano",
+ "Sta. Rowbottom",
+ "Sra. Lloyd-Jones",
+ "Parroquiano",
+ "Usuario",
+ "Toby",
+ "Papelero",
+ "Secretario de Justicia",
+ "Secreatrio del Ministerio",
+ "Ba\244ista",
+ "Criada",
+ "Lady Fanshawe",
+ "Sidney Ratchet",
+ "Chico",
+ "Patron", // ??? not found??
+ "Agente Brit",
+ "Cochero"
+};
+
+// TODO: There also was a Spanish version of Sherlock Holmes 2
+static const FixedTextLanguageEntry fixedTextLanguages[] = {
+ { Common::DE_DEU, fixedTextDE },
+ { Common::ES_ESP, fixedTextES },
+ { Common::EN_ANY, fixedTextEN },
+ { Common::FR_FRA, fixedTextFR },
+ { Common::UNK_LANG, fixedTextEN }
};
TattooFixedText::TattooFixedText(SherlockEngine *vm) : FixedText(vm) {
- if (vm->getLanguage() == Common::DE_DEU)
- _fixedText = FIXED_TEXT_GERMAN;
- else
- _fixedText = FIXED_TEXT_ENGLISH;
+ // Figure out which fixed texts to use
+ Common::Language curLanguage = _vm->getLanguage();
+
+ const FixedTextLanguageEntry *curLanguageEntry = fixedTextLanguages;
+
+ while (curLanguageEntry->language != Common::UNK_LANG) {
+ if (curLanguageEntry->language == curLanguage)
+ break; // found current language
+ curLanguageEntry++;
+ }
+ _curLanguageEntry = curLanguageEntry;
}
const char *TattooFixedText::getText(int fixedTextId) {
- return _fixedText[fixedTextId];
+ return _curLanguageEntry->fixedTextArray[fixedTextId];
}
const Common::String TattooFixedText::getActionMessage(FixedTextActionId actionId, int messageIndex) {
diff --git a/engines/sherlock/tattoo/tattoo_fixed_text.h b/engines/sherlock/tattoo/tattoo_fixed_text.h
index 3f43678ca2..48d237db3c 100644
--- a/engines/sherlock/tattoo/tattoo_fixed_text.h
+++ b/engines/sherlock/tattoo/tattoo_fixed_text.h
@@ -31,20 +31,20 @@ namespace Tattoo {
enum FixedTextId {
kFixedText_Inv1,
- kFixedText_Inv2,
- kFixedText_Inv3,
- kFixedText_Inv4,
- kFixedText_Inv5,
- kFixedText_Inv6,
- kFixedText_Inv7,
- kFixedText_Inv8,
kFixedText_InvDesc1,
+ kFixedText_Inv2,
kFixedText_InvDesc2,
+ kFixedText_Inv3,
kFixedText_InvDesc3,
+ kFixedText_Inv4,
kFixedText_InvDesc4,
+ kFixedText_Inv5,
kFixedText_InvDesc5,
+ kFixedText_Inv6,
kFixedText_InvDesc6,
+ kFixedText_Inv7,
kFixedText_InvDesc7,
+ kFixedText_Inv8,
kFixedText_InvDesc8,
kFixedText_Open,
kFixedText_Look,
@@ -106,12 +106,114 @@ enum FixedTextId {
kFixedText_Yes,
kFixedText_No,
kFixedText_EnterPassword,
- kFixedText_CorrectPassword
+ kFixedText_CorrectPassword,
+ // SH2: People names
+ kFixedText_People_SherlockHolmes,
+ kFixedText_People_DrWatson,
+ kFixedText_People_MrsHudson,
+ kFixedText_People_StanleyForbes,
+ kFixedText_People_MycroftHolmes,
+ kFixedText_People_Wiggins,
+ kFixedText_People_PoliceConstableBurns,
+ kFixedText_People_AugustusTrimble,
+ kFixedText_People_PoliceConstableDaley,
+ kFixedText_People_Matron,
+ kFixedText_People_SisterGrace,
+ kFixedText_People_PrestonMcCabe,
+ kFixedText_People_BobColleran,
+ kFixedText_People_JonasRigby,
+ kFixedText_People_PoliceConstableRoach,
+ kFixedText_People_JamesDewar,
+ kFixedText_People_SergeantJeremyDuncan,
+ kFixedText_People_InspectorGregson,
+ kFixedText_People_InspectorLestrade,
+ kFixedText_People_JesseNeedhem,
+ kFixedText_People_ArthurFleming,
+ kFixedText_People_MrThomasPratt,
+ kFixedText_People_MathildaTillieMason,
+ kFixedText_People_AdrianRussell,
+ kFixedText_People_EldridgeWhitney,
+ kFixedText_People_Hepplethwaite,
+ kFixedText_People_HoraceSilverbridge,
+ kFixedText_People_OldSherman,
+ kFixedText_People_MaxwellVerner,
+ kFixedText_People_MillicentRedding,
+ kFixedText_People_VirgilSilverbridge,
+ kFixedText_People_GeorgeOKeeffe,
+ kFixedText_People_LordDenysLawton,
+ kFixedText_People_Jenkins,
+ kFixedText_People_JockMahoney,
+ kFixedText_People_Bartender,
+ kFixedText_People_LadyCordeliaLockridge,
+ kFixedText_People_Pettigrew,
+ kFixedText_People_SirAveryFanshawe,
+ kFixedText_People_Hodgkins,
+ kFixedText_People_WilburBirdyHeywood,
+ kFixedText_People_JacobFarthington,
+ kFixedText_People_PhilipBledsoe,
+ kFixedText_People_SidneyFowler,
+ kFixedText_People_ProfessorTheodoreTotman,
+ kFixedText_People_RoseHinchem,
+ kFixedText_People_Tallboy,
+ kFixedText_People_EthlebertStitchRumsey,
+ kFixedText_People_CharlesFreedman,
+ kFixedText_People_NigelHemmings,
+ kFixedText_People_FairfaxCarter,
+ kFixedText_People_WilhelmII,
+ kFixedText_People_Wachthund,
+ kFixedText_People_JonathanWilson,
+ kFixedText_People_DavidLloydJones,
+ kFixedText_People_EdwardHargrove,
+ kFixedText_People_Misteray,
+ kFixedText_People_TheLascar,
+ kFixedText_People_Parrot,
+ kFixedText_People_VincentScarrett,
+ kFixedText_People_Alexandra,
+ kFixedText_People_QueenVictoria,
+ kFixedText_People_JohnBrown,
+ kFixedText_People_APatient1,
+ kFixedText_People_APatient2,
+ kFixedText_People_Patron,
+ kFixedText_People_QueenVictoria2,
+ kFixedText_People_PatientInWhite,
+ kFixedText_People_Lush,
+ kFixedText_People_Drunk,
+ kFixedText_People_Prostitute,
+ kFixedText_People_Mudlark,
+ kFixedText_People_Grinder,
+ kFixedText_People_Bouncer,
+ kFixedText_People_AgnesRatchet,
+ kFixedText_People_AloysiusRatchet,
+ kFixedText_People_RealEstateAgent,
+ kFixedText_People_CandyClerk,
+ kFixedText_People_Beadle,
+ kFixedText_People_Prussian,
+ kFixedText_People_MrsRowbottom,
+ kFixedText_People_MissLloydJones,
+ kFixedText_People_TavernPatron,
+ kFixedText_People_User,
+ kFixedText_People_Toby,
+ kFixedText_People_Stationer,
+ kFixedText_People_LawClerk,
+ kFixedText_People_MinistryClerk,
+ kFixedText_People_Bather,
+ kFixedText_People_Maid,
+ kFixedText_People_LadyFanshawe,
+ kFixedText_People_SidneyRatchet,
+ kFixedText_People_Boy,
+ kFixedText_People_Patron2,
+ kFixedText_People_ConstableBrit,
+ kFixedText_People_WagonDriver
+};
+
+struct FixedTextLanguageEntry {
+ Common::Language language;
+ const char *const *fixedTextArray;
};
class TattooFixedText: public FixedText {
private:
- const char *const *_fixedText;
+ const FixedTextLanguageEntry *_curLanguageEntry;
public:
TattooFixedText(SherlockEngine *vm);
virtual ~TattooFixedText() {}
diff --git a/engines/sherlock/tattoo/tattoo_inventory.cpp b/engines/sherlock/tattoo/tattoo_inventory.cpp
index 6bd1822c10..14e79e9f33 100644
--- a/engines/sherlock/tattoo/tattoo_inventory.cpp
+++ b/engines/sherlock/tattoo/tattoo_inventory.cpp
@@ -43,10 +43,10 @@ void TattooInventory::loadInv() {
Common::SeekableReadStream *stream = _vm->_res->load("invent.txt");
int count = stream->readByte();
- char c;
for (int idx = 0; idx < count; ++idx) {
Common::String name;
+ char c;
while ((c = stream->readByte()) != 0)
name += c;
diff --git a/engines/sherlock/tattoo/tattoo_journal.cpp b/engines/sherlock/tattoo/tattoo_journal.cpp
index 29b40096cb..e836cca620 100644
--- a/engines/sherlock/tattoo/tattoo_journal.cpp
+++ b/engines/sherlock/tattoo/tattoo_journal.cpp
@@ -253,9 +253,11 @@ void TattooJournal::handleButtons() {
// FIgure out the left of the scrollbar scroll area and paging data
const int scrollingWidth = JOURNAL_BAR_WIDTH - BUTTON_SIZE * 2 - 6;
const int scrollingLeft = (SHERLOCK_SCREEN_WIDTH - JOURNAL_BAR_WIDTH) / 2 + BUTTON_SIZE + 3;
- const int numPages = (_maxPage + LINES_PER_PAGE - 1) / LINES_PER_PAGE - 1;
- const int barWidth = CLIP(scrollingWidth / numPages, BUTTON_SIZE, JOURNAL_BAR_WIDTH - BUTTON_SIZE * 2 - 6);
+ const int numPages = (_maxPage + LINES_PER_PAGE - 1) / LINES_PER_PAGE;
+ if (numPages == 1)
+ return;
+ const int barWidth = CLIP(scrollingWidth / numPages, BUTTON_SIZE, JOURNAL_BAR_WIDTH - BUTTON_SIZE * 2 - 6);
const int scrollOffset = mousePos.x - scrollingLeft;
const int page = scrollOffset * FIXED_INT_MULTIPLIER / ((scrollingWidth - barWidth) * (FIXED_INT_MULTIPLIER / (numPages - 1))) + 1;
@@ -345,16 +347,16 @@ void TattooJournal::handleButtons() {
disableControls();
bool notFound = false;
- int dir;
do {
+ int dir;
if ((dir = getFindName(notFound)) != 0) {
_savedIndex = _index;
_savedSub = _sub;
_savedPage = _page;
- if (drawJournal(dir + 2, 1000 * LINES_PER_PAGE) == 0)
- {
+ bool drawResult = drawJournal(dir + 2, 1000 * LINES_PER_PAGE);
+ if (!drawResult) {
_index = _savedIndex;
_sub = _savedSub;
_page = _savedPage;
@@ -362,12 +364,13 @@ void TattooJournal::handleButtons() {
drawFrame();
drawJournal(0, 0);
notFound = true;
- } else {
- break;
}
highlightJournalControls(false);
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
+
+ if (drawResult)
+ break;
} else {
break;
}
@@ -555,7 +558,7 @@ void TattooJournal::highlightJournalControls(bool slamIt) {
_selector = JH_NONE;
} else {
// Calculate the Scroll Position Bar
- int numPages = (_maxPage + LINES_PER_PAGE - 1) / LINES_PER_PAGE - 1;
+ int numPages = (_maxPage + LINES_PER_PAGE - 1) / LINES_PER_PAGE;
int barWidth = (r.width() - BUTTON_SIZE * 2 - 6) / numPages;
barWidth = CLIP(barWidth, BUTTON_SIZE, r.width() - BUTTON_SIZE * 2 - 6);
@@ -671,7 +674,7 @@ void TattooJournal::drawScrollBar() {
r.moveTo((SHERLOCK_SCREEN_WIDTH - r.width()) / 2, SHERLOCK_SCREEN_HEIGHT - r.height());
// Calculate the Scroll Position Bar
- int numPages = (_maxPage + LINES_PER_PAGE - 1) / LINES_PER_PAGE - 1;
+ int numPages = (_maxPage + LINES_PER_PAGE - 1) / LINES_PER_PAGE;
int barWidth = (r.width() - BUTTON_SIZE * 2 - 6) / numPages;
barWidth = CLIP(barWidth, BUTTON_SIZE, r.width() - BUTTON_SIZE * 2 - 6);
int barX;
@@ -729,7 +732,7 @@ void TattooJournal::drawScrollBar() {
void TattooJournal::disableControls() {
Screen &screen = *_vm->_screen;
Common::Rect r(JOURNAL_BAR_WIDTH, BUTTON_SIZE + screen.fontHeight() + 13);
- r.moveTo((SHERLOCK_SCREEN_HEIGHT - r.width()) / 2, SHERLOCK_SCREEN_HEIGHT - r.height());
+ r.moveTo((SHERLOCK_SCREEN_WIDTH - r.width()) / 2, SHERLOCK_SCREEN_HEIGHT - r.height());
const char *JOURNAL_COMMANDS[3] = { FIXED(CloseJournal), FIXED(SearchJournal), FIXED(SaveJournal) };
// Print the Journal commands
@@ -752,7 +755,9 @@ int TattooJournal::getFindName(bool printError) {
int done = 0;
Common::String name;
int cursorX, cursorY;
- bool flag = false;
+ bool blinkFlag = false;
+ int blinkCountdown = 1;
+ enum SearchButtons { SB_CANCEL = 0, SB_BACKWARDS = 1, SB_FORWARDS = 2 };
Common::Rect r(JOURNAL_BAR_WIDTH, (screen.fontHeight() + 4) * 2 + 9);
r.moveTo((SHERLOCK_SCREEN_WIDTH - r.width()) / 2, (SHERLOCK_SCREEN_HEIGHT - r.height()) / 2);
@@ -761,6 +766,7 @@ int TattooJournal::getFindName(bool printError) {
cursorY = r.top + screen.fontHeight() + 12;
drawControls(1);
+ disableControls();
// Backup the area under the text entry
Surface bgSurface(r.width() - 6, screen.fontHeight());
@@ -768,7 +774,8 @@ int TattooJournal::getFindName(bool printError) {
r.right - 3, cursorY + screen.fontHeight()));
if (printError) {
- screen.gPrint(Common::Point(0, cursorY), INFO_TOP, "%s", FIXED(TextNotFound));
+ screen.gPrint(Common::Point(r.left + (r.width() - screen.stringWidth(FIXED(TextNotFound))) / 2, cursorY),
+ INFO_TOP, "%s", FIXED(TextNotFound));
} else {
// If there was a name already entered, copy it to name and display it
if (!_find.empty()) {
@@ -820,21 +827,27 @@ int TattooJournal::getFindName(bool printError) {
events.setButtonState();
// Handle blinking cursor
- flag = !flag;
- if (flag) {
- // Draw cursor
- screen._backBuffer1.fillRect(Common::Rect(cursorX, cursorY, cursorX + 7, cursorY + 8), COMMAND_HIGHLIGHTED);
- screen.slamArea(cursorX, cursorY, 8, 9);
- } else {
- // Erase cursor by restoring background and writing current text
- screen._backBuffer1.blitFrom(bgSurface, Common::Point(r.left + 3, cursorY));
- screen.gPrint(Common::Point(r.left + screen.widestChar() + 3, cursorY), COMMAND_HIGHLIGHTED, "%s", name.c_str());
- screen.slamArea(r.left + 3, r.top, r.width() - 3, screen.fontHeight());
+ if (--blinkCountdown == 0) {
+ blinkCountdown = 3;
+ blinkFlag = !blinkFlag;
+ if (blinkFlag) {
+ // Draw cursor
+ screen._backBuffer1.fillRect(Common::Rect(cursorX, cursorY, cursorX + 7, cursorY + 8), COMMAND_HIGHLIGHTED);
+ screen.slamArea(cursorX, cursorY, 8, 9);
+ }
+ else {
+ // Erase cursor by restoring background and writing current text
+ screen._backBuffer1.blitFrom(bgSurface, Common::Point(r.left + 3, cursorY));
+ screen.gPrint(Common::Point(r.left + screen.widestChar() + 3, cursorY), COMMAND_HIGHLIGHTED, "%s", name.c_str());
+ screen.slamArea(r.left + 3, cursorY, r.width() - 3, screen.fontHeight());
+ }
}
highlightSearchControls(true);
events.wait(2);
+ if (_vm->shouldQuit())
+ return 0;
}
if (events.kbHit()) {
@@ -881,10 +894,11 @@ int TattooJournal::getFindName(bool printError) {
}
}
- if (keyState.ascii && keyState.ascii != '@' && name.size() < 50) {
+ if (keyState.ascii >= ' ' && keyState.ascii != '@' && name.size() < 50) {
if ((cursorX + screen.charWidth(keyState.ascii)) < (r.right - screen.widestChar() * 3)) {
- cursorX += screen.charWidth(keyState.ascii);
- name += toupper(keyState.ascii);
+ char c = toupper(keyState.ascii);
+ cursorX += screen.charWidth(c);
+ name += c;
}
}
@@ -897,13 +911,13 @@ int TattooJournal::getFindName(bool printError) {
if (events._released || events._rightReleased) {
switch (_selector) {
- case JH_CLOSE:
+ case (int)SB_CANCEL:
done = -1;
break;
- case JH_SEARCH:
+ case (int)SB_BACKWARDS:
done = 2;
break;
- case JH_PRINT:
+ case (int)SB_FORWARDS:
done = 1;
break;
default:
@@ -913,6 +927,7 @@ int TattooJournal::getFindName(bool printError) {
} while (!done);
if (done != -1) {
+ // Forwards or backwards search, so save the entered name
_find = name;
result = done;
} else {
diff --git a/engines/sherlock/tattoo/tattoo_map.cpp b/engines/sherlock/tattoo/tattoo_map.cpp
index 4bd85bd5c0..4c7e8c8fef 100644
--- a/engines/sherlock/tattoo/tattoo_map.cpp
+++ b/engines/sherlock/tattoo/tattoo_map.cpp
@@ -134,6 +134,7 @@ int TattooMap::show() {
screen.slamArea(screen._currentScroll.x, screen._currentScroll.y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_WIDTH);
}
+ music.checkSongProgress();
checkMapNames(true);
if (mousePos.x < (SHERLOCK_SCREEN_WIDTH / 6))
@@ -364,8 +365,8 @@ void TattooMap::showCloseUp(int closeUpNum) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
- // Reset scroll position
- screen._currentScroll = Common::Point(0, 0);
+ // Hide the cursor
+ events.hideCursor();
// Get the closeup images
Common::String fname = Common::String::format("res%02d.vgs", closeUpNum + 1);
@@ -402,7 +403,8 @@ void TattooMap::showCloseUp(int closeUpNum) {
for (int step = 0; step < CLOSEUP_STEPS; ++step) {
Common::Point picSize(pic[0].sDrawXSize(scaleVal), pic[0].sDrawYSize(scaleVal));
- Common::Point pt(closeUp.x / 100 - picSize.x / 2, closeUp.y / 100 - picSize.y / 2);
+ Common::Point pt(screen._currentScroll.x + closeUp.x / 100 - picSize.x / 2,
+ screen._currentScroll.y + closeUp.y / 100 - picSize.y / 2);
restoreArea(oldBounds);
screen._backBuffer1.transBlitFrom(pic[0], pt, false, 0, scaleVal);
@@ -418,15 +420,18 @@ void TattooMap::showCloseUp(int closeUpNum) {
}
// Handle final drawing of closeup
- Common::Rect r(SHERLOCK_SCREEN_WIDTH / 2 - pic[0]._width / 2, SHERLOCK_SCREEN_HEIGHT / 2 - pic[0]._height / 2,
- SHERLOCK_SCREEN_WIDTH / 2 - pic[0]._width / 2 + pic[0]._width,
- SHERLOCK_SCREEN_HEIGHT / 2 - pic[0]._height / 2 + pic[0]._height);
+ Common::Rect r(screen._currentScroll.x + SHERLOCK_SCREEN_WIDTH / 2 - pic[0]._width / 2,
+ screen._currentScroll.y + SHERLOCK_SCREEN_HEIGHT / 2 - pic[0]._height / 2,
+ screen._currentScroll.x + SHERLOCK_SCREEN_WIDTH / 2 - pic[0]._width / 2 + pic[0]._width,
+ screen._currentScroll.y + SHERLOCK_SCREEN_HEIGHT / 2 - pic[0]._height / 2 + pic[0]._height);
restoreArea(oldBounds);
screen._backBuffer1.transBlitFrom(pic[0], Common::Point(r.left, r.top));
screen.slamRect(oldBounds);
screen.slamRect(r);
+
events.wait(60);
+ events.showCursor();
}
} // End of namespace Tattoo
diff --git a/engines/sherlock/tattoo/tattoo_people.cpp b/engines/sherlock/tattoo/tattoo_people.cpp
index e3e957e35c..0af8deff9f 100644
--- a/engines/sherlock/tattoo/tattoo_people.cpp
+++ b/engines/sherlock/tattoo/tattoo_people.cpp
@@ -121,12 +121,13 @@ TattooPerson::TattooPerson() : Person() {
_lookHolmes = false;
}
-void TattooPerson::freeAltGraphics() {
- if (_altImages != nullptr) {
- delete _altImages;
- _altImages = nullptr;
- }
+TattooPerson::~TattooPerson() {
+ delete _altImages;
+}
+void TattooPerson::freeAltGraphics() {
+ delete _altImages;
+ _altImages = nullptr;
_altSeq = 0;
}
@@ -874,8 +875,8 @@ Common::Point TattooPerson::getSourcePoint() const {
TattooScene &scene = *(TattooScene *)_vm->_scene;
int scaleVal = scene.getScaleVal(_position);
- return Common::Point(_position.x / FIXED_INT_MULTIPLIER + _imageFrame->sDrawXSize(scaleVal) / 2,
- _position.y / FIXED_INT_MULTIPLIER);
+ return Common::Point(_position.x / FIXED_INT_MULTIPLIER +
+ (_imageFrame ? _imageFrame->sDrawXSize(scaleVal) / 2 : 0), _position.y / FIXED_INT_MULTIPLIER);
}
void TattooPerson::setObjTalkSequence(int seq) {
@@ -1010,7 +1011,6 @@ void TattooPerson::walkHolmesToNPC() {
Screen &screen = *_vm->_screen;
Talk &talk = *_vm->_talk;
TattooPerson &holmes = people[HOLMES];
- int facing;
// Save the character's details
pushNPCPath();
@@ -1073,9 +1073,8 @@ void TattooPerson::walkHolmesToNPC() {
if (!talk._talkToAbort) {
// Setup correct direction for Holmes to face
-
// See where Holmes is with respect to the NPC (x coords)
- facing = (holmes._position.x < _position.x) ? STOP_RIGHT : STOP_LEFT;
+ int facing = (holmes._position.x < _position.x) ? STOP_RIGHT : STOP_LEFT;
// See where Holmes is with respect to the NPC (y coords)
if (holmes._position.y < (_position.y - (10 * FIXED_INT_MULTIPLIER))) {
diff --git a/engines/sherlock/tattoo/tattoo_people.h b/engines/sherlock/tattoo/tattoo_people.h
index 722c4a9aaa..e0d53c67dd 100644
--- a/engines/sherlock/tattoo/tattoo_people.h
+++ b/engines/sherlock/tattoo/tattoo_people.h
@@ -128,7 +128,7 @@ public:
bool _lookHolmes;
public:
TattooPerson();
- virtual ~TattooPerson() {}
+ virtual ~TattooPerson();
/**
* Clear the NPC related data
diff --git a/engines/sherlock/tattoo/tattoo_resources.cpp b/engines/sherlock/tattoo/tattoo_resources.cpp
index 3be41e2650..4b73356d58 100644
--- a/engines/sherlock/tattoo/tattoo_resources.cpp
+++ b/engines/sherlock/tattoo/tattoo_resources.cpp
@@ -21,309 +21,111 @@
*/
#include "sherlock/tattoo/tattoo_resources.h"
+#include "sherlock/tattoo/tattoo_fixed_text.h"
namespace Sherlock {
namespace Tattoo {
-const char PORTRAITS[TATTOO_MAX_PEOPLE][5] = {
- { "HOLM" }, // Sherlock Holmes
- { "WATS" }, // Dr. Watson
- { "HUDS" }, // Mrs. Hudson
- { "FORB" }, // Stanley Forbes
- { "MYCR" }, // Mycroft Holmes
- { "WIGG" }, // Wiggins
- { "BURN" }, // Police Constable Burns
- { "TRIM" }, // Augustus Trimble
- { "DALE" }, // Police Constable Daley
- { "MATR" }, // Matron
- { "GRAC" }, // Sister Grace
- { "MCCA" }, // Preston McCabe
- { "COLL" }, // Bob Colleran
- { "JONA" }, // Jonas Rigby
- { "ROAC" }, // Police Constable Roach
- { "DEWA" }, // James Dewar
- { "JERE" }, // Sergeant Jeremy Duncan
- { "GREG" }, // Inspector Gregson
- { "LEST" }, // Inspector Lestrade
- { "NEED" }, // Jesse Needhem
- { "FLEM" }, // Arthur Fleming
- { "PRAT" }, // Mr. Thomas Pratt
- { "TILL" }, // Mathilda (Tillie) Mason
- { "RUSS" }, // Adrian Russell
- { "WHIT" }, // Eldridge Whitney
- { "HEPP" }, // Hepplethwaite
- { "HORA" }, // Horace Silverbridge
- { "SHER" }, // Old Sherman
- { "VERN" }, // Maxwell Verner
- { "REDD" }, // Millicent Redding
- { "VIRG" }, // Virgil Silverbridge
- { "GEOR" }, // George O'Keeffe
- { "LAWT" }, // Lord Denys Lawton
- { "JENK" }, // Jenkins
- { "JOCK" }, // Jock Mahoney
- { "BART" }, // Bartender
- { "LADY" }, // Lady Cordelia Lockridge
- { "PETT" }, // Pettigrew
- { "FANS" }, // Sir Avery Fanshawe
- { "HODG" }, // Hodgkins
- { "WILB" }, // Wilbur "Birdy" Heywood
- { "JACO" }, // Jacob Farthington
- { "BLED" }, // Philip Bledsoe
- { "FOWL" }, // Sidney Fowler
- { "PROF" }, // Professor Theodore Totman
- { "ROSE" }, // Rose Hinchem
- { "TALL" }, // Tallboy
- { "STIT" }, // Ethlebert "Stitch" Rumsey
- { "FREE" }, // Charles Freedman
- { "HEMM" }, // Nigel Hemmings
- { "CART" }, // Fairfax Carter
- { "WILH" }, // Wilhelm II
- { "WACH" }, // Wachthund
- { "WILS" }, // Jonathan Wilson
- { "DAVE" }, // David Lloyd-Jones
- { "HARG" }, // Edward Hargrove
- { "MORI" }, // Professor James Moriarty
- { "LASC" }, // The Lascar
- { "PARR" }, // Parrot
- { "SCAR" }, // Vincent Scarrett
- { "ALEX" }, // Alexandra
- { "QUEE" }, // Queen Victoria
- { "JOHN" }, // John Brown
- { "PAT1" }, // Patient #1
- { "PAT2" }, // Patient #2
- { "PATR" }, // Patron
- { "QUEN" }, // Queen Victoria
- { "WITE" }, // Patient in White
- { "LUSH" }, // Lush
- { "DRNK" }, // Drunk
- { "PROS" }, // Prostitute
- { "MUDL" }, // Mudlark
- { "GRIN" }, // Grinder
- { "BOUN" }, // Bouncer
- { "RATC" }, // Agnes Ratchet
- { "ALOY" }, // Aloysius Ratchet
- { "REAL" }, // Real Estate Agent
- { "CAND" }, // Candy Clerk
- { "BEAD" }, // Beadle
- { "PRUS" }, // Prussian
- { "ROWB" }, // Mrs. Rowbottom
- { "MSLJ" }, // Miss Lloyd-Jones
- { "TPAT" }, // Tavern patron
- { "USER" }, // User
- { "TOBY" }, // Toby
- { "STAT" }, // Stationer
- { "CLRK" }, // Law Clerk
- { "CLER" }, // Ministry Clerk
- { "BATH" }, // Bather
- { "MAID" }, // Maid
- { "LADF" }, // Lady Fanshawe
- { "SIDN" }, // Sidney Ratchet
- { "BOYO" }, // Boy
- { "PTR2" }, // Second Patron
- { "BRIT" }, // Constable Brit
- { "DROV" } // Wagon Driver
+const PeopleData PEOPLE_DATA[TATTOO_MAX_PEOPLE] = {
+ { "HOLM", kFixedText_People_SherlockHolmes },
+ { "WATS", kFixedText_People_DrWatson },
+ { "HUDS", kFixedText_People_MrsHudson },
+ { "FORB", kFixedText_People_StanleyForbes },
+ { "MYCR", kFixedText_People_MycroftHolmes },
+ { "WIGG", kFixedText_People_Wiggins },
+ { "BURN", kFixedText_People_PoliceConstableBurns },
+ { "TRIM", kFixedText_People_AugustusTrimble },
+ { "DALE", kFixedText_People_PoliceConstableDaley },
+ { "MATR", kFixedText_People_Matron },
+ { "GRAC", kFixedText_People_SisterGrace },
+ { "MCCA", kFixedText_People_PrestonMcCabe },
+ { "COLL", kFixedText_People_BobColleran },
+ { "JONA", kFixedText_People_JonasRigby },
+ { "ROAC", kFixedText_People_PoliceConstableRoach },
+ { "DEWA", kFixedText_People_JamesDewar },
+ { "JERE", kFixedText_People_SergeantJeremyDuncan },
+ { "GREG", kFixedText_People_InspectorGregson },
+ { "LEST", kFixedText_People_InspectorLestrade },
+ { "NEED", kFixedText_People_JesseNeedhem },
+ { "FLEM", kFixedText_People_ArthurFleming },
+ { "PRAT", kFixedText_People_MrThomasPratt },
+ { "TILL", kFixedText_People_MathildaTillieMason },
+ { "RUSS", kFixedText_People_AdrianRussell },
+ { "WHIT", kFixedText_People_EldridgeWhitney },
+ { "HEPP", kFixedText_People_Hepplethwaite },
+ { "HORA", kFixedText_People_HoraceSilverbridge },
+ { "SHER", kFixedText_People_OldSherman },
+ { "VERN", kFixedText_People_MaxwellVerner },
+ { "REDD", kFixedText_People_MillicentRedding },
+ { "VIRG", kFixedText_People_VirgilSilverbridge },
+ { "GEOR", kFixedText_People_GeorgeOKeeffe },
+ { "LAWT", kFixedText_People_LordDenysLawton },
+ { "JENK", kFixedText_People_Jenkins },
+ { "JOCK", kFixedText_People_JockMahoney },
+ { "BART", kFixedText_People_Bartender },
+ { "LADY", kFixedText_People_LadyCordeliaLockridge },
+ { "PETT", kFixedText_People_Pettigrew },
+ { "FANS", kFixedText_People_SirAveryFanshawe },
+ { "HODG", kFixedText_People_Hodgkins },
+ { "WILB", kFixedText_People_WilburBirdyHeywood },
+ { "JACO", kFixedText_People_JacobFarthington },
+ { "BLED", kFixedText_People_PhilipBledsoe },
+ { "FOWL", kFixedText_People_SidneyFowler },
+ { "PROF", kFixedText_People_ProfessorTheodoreTotman },
+ { "ROSE", kFixedText_People_RoseHinchem },
+ { "TALL", kFixedText_People_Tallboy },
+ { "STIT", kFixedText_People_EthlebertStitchRumsey },
+ { "FREE", kFixedText_People_CharlesFreedman },
+ { "HEMM", kFixedText_People_NigelHemmings },
+ { "CART", kFixedText_People_FairfaxCarter },
+ { "WILH", kFixedText_People_WilhelmII },
+ { "WACH", kFixedText_People_Wachthund },
+ { "WILS", kFixedText_People_JonathanWilson },
+ { "DAVE", kFixedText_People_DavidLloydJones },
+ { "HARG", kFixedText_People_EdwardHargrove },
+ { "MORI", kFixedText_People_Misteray },
+ { "LASC", kFixedText_People_TheLascar },
+ { "PARR", kFixedText_People_Parrot },
+ { "SCAR", kFixedText_People_VincentScarrett },
+ { "ALEX", kFixedText_People_Alexandra },
+ { "QUEE", kFixedText_People_QueenVictoria },
+ { "JOHN", kFixedText_People_JohnBrown },
+ { "PAT1", kFixedText_People_APatient1 },
+ { "PAT2", kFixedText_People_APatient2 },
+ { "PATR", kFixedText_People_Patron },
+ { "QUEN", kFixedText_People_QueenVictoria },
+ { "WITE", kFixedText_People_PatientInWhite },
+ { "LUSH", kFixedText_People_Lush },
+ { "DRNK", kFixedText_People_Drunk },
+ { "PROS", kFixedText_People_Prostitute },
+ { "MUDL", kFixedText_People_Mudlark },
+ { "GRIN", kFixedText_People_Grinder },
+ { "BOUN", kFixedText_People_Bouncer },
+ { "RATC", kFixedText_People_AgnesRatchet },
+ { "ALOY", kFixedText_People_AloysiusRatchet },
+ { "REAL", kFixedText_People_RealEstateAgent },
+ { "CAND", kFixedText_People_CandyClerk },
+ { "BEAD", kFixedText_People_Beadle },
+ { "PRUS", kFixedText_People_Prussian },
+ { "ROWB", kFixedText_People_MrsRowbottom },
+ { "MSLJ", kFixedText_People_MissLloydJones },
+ { "TPAT", kFixedText_People_TavernPatron },
+ { "USER", kFixedText_People_User },
+ { "TOBY", kFixedText_People_Toby },
+ { "STAT", kFixedText_People_Stationer },
+ { "CLRK", kFixedText_People_LawClerk },
+ { "CLER", kFixedText_People_MinistryClerk },
+ { "BATH", kFixedText_People_Bather },
+ { "MAID", kFixedText_People_Maid },
+ { "LADF", kFixedText_People_LadyFanshawe },
+ { "SIDN", kFixedText_People_SidneyRatchet },
+ { "BOYO", kFixedText_People_Boy },
+ { "PTR2", kFixedText_People_Patron2 },
+ { "BRIT", kFixedText_People_ConstableBrit },
+ { "DROV", kFixedText_People_WagonDriver }
};
-const char *const FRENCH_NAMES[TATTOO_MAX_PEOPLE] = {
- "Sherlock Holmes",
- "Dr. Watson",
- "Mme. Hudson",
- "Stanley Forbes",
- "Mycroft Holmes",
- "Wiggins",
- "Sergent Burns",
- "Augustus Trimble",
- "Sergent Daley",
- "Infirmi?re chef",
- "Mme. Grace",
- "Preston McCabe",
- "Bob Colleran",
- "Jonas Rigby",
- "Sergent Roach",
- "James Dewar",
- "Sergent Jeremy Duncan",
- "Inspecteur Gregson",
- "Inspecteur Lestrade",
- "Jesse Needhem",
- "Arthur Fleming",
- "M. Thomas Pratt",
- "Mathilda (Tillie) Mason",
- "Adrian Russell",
- "Eldridge Whitney",
- "Hepplethwaite",
- "Horace Silverbridge",
- "Sherman",
- "Maxwell Verner",
- "Millicent Redding",
- "Virgil Silverbridge",
- "George O'Keeffe",
- "Lord Denys Lawton",
- "Jenkins",
- "Jock Mahoney",
- "Serveur",
- "Lady Cordelia Lockridge",
- "Pettigrew",
- "Sir Avery Fanshawe",
- "Hodgkins",
- "Wilbur \"Birdy\" Heywood",
- "Jacob Farthington",
- "Philip Bledsoe",
- "Sidney Fowler",
- "Professeur Theodore Totman",
- "Rose Hinchem",
- "Tallboy",
- "Ethlebert \"Stitch\" Rumsey",
- "Charles Freedman",
- "Nigel Hemmings",
- "Fairfax Carter",
- "Wilhelm II",
- "Wachthund",
- "Jonathan Wilson",
- "David Lloyd-Jones",
- "Edward Hargrove",
- "Misteray",
- "Le Lascar",
- "Oiseau",
- "Vincent Scarrett",
- "Alexandra",
- "Queen Victoria",
- "John Brown",
- "Patient",
- "Patient",
- "Client",
- "Queen Victoria",
- "Patient en blanc",
- "Ivrogne",
- "Ivrogne",
- "Belle femme",
- "Mudlark",
- "Broyeur",
- "Videur",
- "Agnes Ratchet",
- "Aloysius Ratchet",
- "Immobilier",
- "Gar?on",
- "Beadle",
- "Prussian",
- "Mme. Rowbottom",
- "Mme Lloyd-Jones",
- "Tavern Client",
- "User",
- "Toby",
- "Papeterie",
- "Law Clerc",
- "Ministry Employ?",
- "Clint du thermes",
- "Bonne",
- "Lady Fanshawe",
- "Sidney Ratchet",
- "Gar?on",
- "Client",
- "Sergent Brit",
- "Wagon Driver"
-};
-
-const char *const ENGLISH_NAMES[TATTOO_MAX_PEOPLE] = {
- "Sherlock Holmes",
- "Dr. Watson",
- "Mrs. Hudson",
- "Stanley Forbes",
- "Mycroft Holmes",
- "Wiggins",
- "Police Constable Burns",
- "Augustus Trimble",
- "Police Constable Daley",
- "Matron",
- "Sister Grace",
- "Preston McCabe",
- "Bob Colleran",
- "Jonas Rigby",
- "Police Constable Roach",
- "James Dewar",
- "Sergeant Jeremy Duncan",
- "Inspector Gregson",
- "Inspector Lestrade",
- "Jesse Needhem",
- "Arthur Fleming",
- "Mr. Thomas Pratt",
- "Mathilda (Tillie) Mason",
- "Adrian Russell",
- "Eldridge Whitney",
- "Hepplethwaite",
- "Horace Silverbridge",
- "Old Sherman",
- "Maxwell Verner",
- "Millicent Redding",
- "Virgil Silverbridge",
- "George O'Keeffe",
- "Lord Denys Lawton",
- "Jenkins",
- "Jock Mahoney",
- "Bartender",
- "Lady Cordelia Lockridge",
- "Pettigrew",
- "Sir Avery Fanshawe",
- "Hodgkins",
- "Wilbur \"Birdy\" Heywood",
- "Jacob Farthington",
- "Philip Bledsoe",
- "Sidney Fowler",
- "Professor Theodore Totman",
- "Rose Hinchem",
- "Tallboy",
- "Ethlebert \"Stitch\" Rumsey",
- "Charles Freedman",
- "Nigel Hemmings",
- "Fairfax Carter",
- "Wilhelm II",
- "Wachthund",
- "Jonathan Wilson",
- "David Lloyd-Jones",
- "Edward Hargrove",
- "Misteray",
- "The Lascar",
- "Parrot",
- "Vincent Scarrett",
- "Alexandra",
- "Queen Victoria",
- "John Brown",
- "A Patient",
- "A Patient",
- "Patron",
- "Queen Victoria",
- "Patient in white",
- "Lush",
- "Drunk",
- "Prostitute",
- "Mudlark",
- "Grinder",
- "Bouncer",
- "Agnes Ratchet",
- "Aloysius Ratchet",
- "Real Estate Agent",
- "Candy Clerk",
- "Beadle",
- "Prussian",
- "Mrs. Rowbottom",
- "Miss Lloyd-Jones",
- "Tavern patron",
- "User",
- "Toby",
- "Stationer",
- "Law Clerk",
- "Ministry Clerk",
- "Bather",
- "Maid",
- "Lady Fanshawe",
- "Sidney Ratchet",
- "Boy",
- "Patron",
- "Constable Brit",
- "Wagon Driver"
-};
-
-
} // End of namespace Tattoo
} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_resources.h b/engines/sherlock/tattoo/tattoo_resources.h
index b706d90f2d..85a78734b9 100644
--- a/engines/sherlock/tattoo/tattoo_resources.h
+++ b/engines/sherlock/tattoo/tattoo_resources.h
@@ -31,9 +31,12 @@ namespace Tattoo {
#define TATTOO_MAX_PEOPLE 96
-extern const char PORTRAITS[TATTOO_MAX_PEOPLE][5];
-extern const char *const FRENCH_NAMES[TATTOO_MAX_PEOPLE];
-extern const char *const ENGLISH_NAMES[TATTOO_MAX_PEOPLE];
+struct PeopleData {
+ const char *portrait;
+ int fixedTextId;
+};
+
+extern const PeopleData PEOPLE_DATA[TATTOO_MAX_PEOPLE];
} // End of namespace Tattoo
diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp
index f13d0588df..27f37665dc 100644
--- a/engines/sherlock/tattoo/tattoo_scene.cpp
+++ b/engines/sherlock/tattoo/tattoo_scene.cpp
@@ -90,20 +90,25 @@ bool TattooScene::loadScene(const Common::String &filename) {
}
}
+ // Handle loading music for the scene
+ if (talk._scriptMoreFlag != 1 && talk._scriptMoreFlag != 3)
+ music._nextSongName = Common::String::format("res%02d", _currentScene);
+
// Set the NPC paths for the scene
setNPCPath(WATSON);
- // Handle loading music for the scene
- if (music._musicOn) {
- if (talk._scriptMoreFlag != 1 && talk._scriptMoreFlag != 3)
- music._nextSongName = Common::String::format("res%02d", _currentScene);
-
- // If it's a new song, then start it up
- if (music._currentSongName.compareToIgnoreCase(music._nextSongName)) {
- if (music.loadSong(music._nextSongName)) {
- if (music._musicOn)
- music.startSong();
- }
+ // If it's a new song, then start it up
+ if (music._currentSongName.compareToIgnoreCase(music._nextSongName)) {
+ // WORKAROUND: Stop playing music after Diogenes fire scene in the intro,
+ // since it overlaps slightly into the next scene
+ if (talk._scriptName == "prol80p" && _currentScene == 80) {
+ music.stopMusic();
+ events.wait(5);
+ }
+
+ if (music.loadSong(music._nextSongName)) {
+ if (music._musicOn)
+ music.startSong();
}
}
@@ -340,12 +345,14 @@ void TattooScene::doBgAnimCheckCursor() {
void TattooScene::doBgAnim() {
TattooEngine &vm = *(TattooEngine *)_vm;
Events &events = *_vm->_events;
+ Music &music = *_vm->_music;
TattooPeople &people = *(TattooPeople *)_vm->_people;
Screen &screen = *_vm->_screen;
Talk &talk = *_vm->_talk;
TattooUserInterface &ui = *((TattooUserInterface *)_vm->_ui);
doBgAnimCheckCursor();
+ music.checkSongProgress();
talk._talkToAbort = false;
@@ -653,8 +660,6 @@ int TattooScene::startCAnim(int cAnimNum, int playRate) {
if (ui._windowOpen)
ui.banishWindow();
- //_activeCAnim._filesize = cAnim._size;
-
// Open up the room resource file and get the data for the animation
Common::SeekableReadStream *stream = res.load(_roomFilename);
stream->seek(44 + cAnimNum * 4);
@@ -690,6 +695,7 @@ int TattooScene::startCAnim(int cAnimNum, int playRate) {
_goToScene = STARTING_GAME_SCENE;
talk._talkToAbort = true;
_activeCAnim.close();
+ break;
}
}
}
@@ -716,6 +722,7 @@ int TattooScene::startCAnim(int cAnimNum, int playRate) {
// Flag the Canimation to be cleared
_activeCAnim._zPlacement = REMOVE;
_activeCAnim._removeBounds = _activeCAnim._oldBounds;
+ _vm->_ui->_bgFound = -1;
// Free up the animation
_activeCAnim.close();
@@ -809,13 +816,12 @@ void TattooScene::synchronize(Serializer &s) {
int TattooScene::closestZone(const Common::Point &pt) {
int zone = -1;
int dist = 9999;
- int d;
for (uint idx = 0; idx < _zones.size(); ++idx) {
Common::Rect &r = _zones[idx];
// Check the distance from the point to the center of the zone
- d = ABS(r.left + (r.width() / 2) - pt.x) + ABS(r.top + (r.height() / 2) - pt.y);
+ int d = ABS(r.left + (r.width() / 2) - pt.x) + ABS(r.top + (r.height() / 2) - pt.y);
if (d < dist) {
dist = d;
zone = idx;
diff --git a/engines/sherlock/tattoo/tattoo_talk.cpp b/engines/sherlock/tattoo/tattoo_talk.cpp
index a4ceca042b..a5ada7b63e 100644
--- a/engines/sherlock/tattoo/tattoo_talk.cpp
+++ b/engines/sherlock/tattoo/tattoo_talk.cpp
@@ -341,6 +341,10 @@ OpcodeReturn TattooTalk::cmdNextSong(const byte *&str) {
music._nextSongName += str[idx];
str += 7;
+ // WORKAROUND: Original game set wrong music name at the end of the introduction sequence
+ if (_scriptName == "prol80p" && music._nextSongName == "default")
+ music._nextSongName = "01cue90";
+
return RET_SUCCESS;
}
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp
index 160b1ca5a0..ee028f89c2 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.cpp
+++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp
@@ -85,7 +85,6 @@ void TattooUserInterface::lookAtObject() {
Talk &talk = *_vm->_talk;
Common::Point mousePos = events.mousePos();
Common::String desc;
- int cAnimSpeed = 0;
_lookPos = mousePos;
_menuMode = LOOK_MODE;
@@ -95,7 +94,7 @@ void TattooUserInterface::lookAtObject() {
} else {
// Check if there is a Look animation
if (_bgShape->_lookcAnim != 0) {
- cAnimSpeed = _bgShape->_lookcAnim & 0xe0;
+ int cAnimSpeed = _bgShape->_lookcAnim & 0xe0;
cAnimSpeed >>= 5;
++cAnimSpeed;
@@ -216,9 +215,10 @@ void TattooUserInterface::doJournal() {
TattooJournal &journal = *(TattooJournal *)_vm->_journal;
TattooScene &scene = *(TattooScene *)_vm->_scene;
Screen &screen = *_vm->_screen;
- byte lookupTable[PALETTE_SIZE];
+ byte lookupTable[PALETTE_COUNT], lookupTable1[PALETTE_COUNT];
- Common::copy(&_lookupTable[0], &_lookupTable[PALETTE_SIZE], &lookupTable[0]);
+ Common::copy(&_lookupTable[0], &_lookupTable[PALETTE_COUNT], &lookupTable[0]);
+ Common::copy(&_lookupTable1[0], &_lookupTable1[PALETTE_COUNT], &lookupTable1[0]);
_menuMode = JOURNAL_MODE;
journal.show();
@@ -229,7 +229,8 @@ void TattooUserInterface::doJournal() {
// Restore the the old screen palette and greyscale lookup table
screen.clear();
screen.setPalette(screen._cMap);
- Common::copy(&lookupTable[0], &lookupTable[PALETTE_SIZE], &_lookupTable[0]);
+ Common::copy(&lookupTable[0], &lookupTable[PALETTE_COUNT], &_lookupTable[0]);
+ Common::copy(&lookupTable1[0], &lookupTable1[PALETTE_COUNT], &_lookupTable1[0]);
// Restore the scene
screen._backBuffer1.blitFrom(screen._backBuffer2);
@@ -276,7 +277,7 @@ void TattooUserInterface::handleInput() {
scene._goToScene = STARTING_GAME_SCENE;
} else if (_menuMode == STD_MODE) {
if (_keyState.keycode == Common::KEYCODE_s && vm._allowFastMode) {
- vm._fastMode = !vm._fastMode;
+ events.toggleSpeed();
} else if (_keyState.keycode == Common::KEYCODE_l && _bgFound != -1) {
// Beging used for testing that Look dialogs work
@@ -374,10 +375,10 @@ void TattooUserInterface::doStandardControl() {
TattooEngine &vm = *(TattooEngine *)_vm;
Events &events = *_vm->_events;
People &people = *_vm->_people;
+ SaveManager &saves = *_vm->_saves;
TattooScene &scene = *(TattooScene *)_vm->_scene;
Talk &talk = *_vm->_talk;
Common::Point mousePos = events.mousePos();
- bool noDesc = false;
// Don't do any input processing whilst the prolog is running
if (vm._runningProlog)
@@ -458,6 +459,7 @@ void TattooUserInterface::doStandardControl() {
if (_arrowZone == -1 || events._rightReleased)
freeMenu();
+ bool noDesc = false;
if (_personFound) {
if (people[_bgFound - 1000]._description.empty() || people[_bgFound - 1000]._description.hasPrefix(" "))
noDesc = true;
@@ -471,6 +473,7 @@ void TattooUserInterface::doStandardControl() {
if (events._rightReleased) {
// Show the verbs menu for the highlighted object
_tooltipWidget.banishWindow();
+ saves.createThumbnail();
_verbsWidget.load(!noDesc);
_verbsWidget.summonWindow();
@@ -515,11 +518,9 @@ void TattooUserInterface::doStandardControl() {
void TattooUserInterface::doLookControl() {
Events &events = *_vm->_events;
TattooScene &scene = *(TattooScene *)_vm->_scene;
- Sound &sound = *_vm->_sound;
- // See if a mouse button was released or a key pressed, and we want to initiate an action
- // TODO: Not sure about _soundOn.. should be check for speaking voice for text being complete
- if (events._released || events._rightReleased || _keyState.keycode || (sound._voices && !sound._soundOn)) {
+ // See if a mouse button was released or a key pressed to close the active look dialog
+ if (events._released || events._rightReleased || _keyState.keycode) {
// See if we were looking at an inventory object
if (!_invLookFlag) {
// See if there is any more text to display
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.h b/engines/sherlock/tattoo/tattoo_user_interface.h
index c92ff21dd1..d89da4a6da 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.h
+++ b/engines/sherlock/tattoo/tattoo_user_interface.h
@@ -185,6 +185,9 @@ public:
*/
void doBgAnimEraseBackground();
+ /**
+ * Draws overlays onto the scene. Basically, the smoke effects some scenes have
+ */
void drawMaskArea(bool mode);
/**
diff --git a/engines/sherlock/tattoo/widget_base.cpp b/engines/sherlock/tattoo/widget_base.cpp
index 9e10cee0d1..8f0649130a 100644
--- a/engines/sherlock/tattoo/widget_base.cpp
+++ b/engines/sherlock/tattoo/widget_base.cpp
@@ -33,6 +33,7 @@ namespace Tattoo {
WidgetBase::WidgetBase(SherlockEngine *vm) : _vm(vm) {
_scroll = false;
_dialogTimer = 0;
+ _outsideMenu = false;
}
void WidgetBase::summonWindow() {
diff --git a/engines/sherlock/tattoo/widget_files.cpp b/engines/sherlock/tattoo/widget_files.cpp
index c9a20b0f8a..ca5e1bff93 100644
--- a/engines/sherlock/tattoo/widget_files.cpp
+++ b/engines/sherlock/tattoo/widget_files.cpp
@@ -143,19 +143,17 @@ void WidgetFiles::render(FilesRenderMode mode) {
int yp = _surface.fontHeight() + 14;
for (int idx = _savegameIndex; idx < (_savegameIndex + FILES_LINES_COUNT); ++idx) {
- if (OP_NAMES || idx == _selector || idx == _oldSelector) {
- if (idx == _selector && mode != RENDER_ALL)
- color = COMMAND_HIGHLIGHTED;
- else
- color = INFO_TOP;
+ if (idx == _selector && mode != RENDER_ALL)
+ color = COMMAND_HIGHLIGHTED;
+ else
+ color = INFO_TOP;
- if (mode == RENDER_NAMES_AND_SCROLLBAR)
- _surface.fillRect(Common::Rect(4, yp, _surface.w() - BUTTON_SIZE - 9, yp + _surface.fontHeight()), TRANSPARENCY);
+ if (mode == RENDER_NAMES_AND_SCROLLBAR)
+ _surface.fillRect(Common::Rect(4, yp, _surface.w() - BUTTON_SIZE - 9, yp + _surface.fontHeight()), TRANSPARENCY);
- Common::String numStr = Common::String::format("%d.", idx + 1);
- _surface.writeString(numStr, Common::Point(_surface.widestChar(), yp), color);
- _surface.writeString(_savegames[idx], Common::Point(xp, yp), color);
- }
+ Common::String numStr = Common::String::format("%d.", idx + 1);
+ _surface.writeString(numStr, Common::Point(_surface.widestChar(), yp), color);
+ _surface.writeString(_savegames[idx], Common::Point(xp, yp), color);
yp += _surface.fontHeight() + 1;
}
@@ -253,7 +251,6 @@ bool WidgetFiles::getFilename() {
int done = 0;
bool blinkFlag = false;
int blinkCountdown = 0;
- int width;
int cursorColor = 192;
byte color, textColor;
bool insert = true;
@@ -285,7 +282,7 @@ bool WidgetFiles::getFilename() {
char currentChar = (index == (int)filename.size()) ? ' ' : filename[index];
Common::String charString = Common::String::format("%c", currentChar);
- width = screen.charWidth(currentChar);
+ int width = screen.charWidth(currentChar);
// Wait for keypress
while (!events.kbHit()) {
diff --git a/engines/sherlock/tattoo/widget_inventory.cpp b/engines/sherlock/tattoo/widget_inventory.cpp
index 3555ecdffd..b49e30b30d 100644
--- a/engines/sherlock/tattoo/widget_inventory.cpp
+++ b/engines/sherlock/tattoo/widget_inventory.cpp
@@ -641,10 +641,12 @@ void WidgetInventory::handleEvents() {
bool found = false;
if (ui._bgFound != -1) {
if (ui._personFound) {
+ Person &person = people[ui._bgFound - 1000];
+
for (int idx = 0; idx < 2; ++idx) {
- if (!people[ui._bgFound - 1000]._use[idx]._verb.compareToIgnoreCase(_verb) &&
- !people[ui._bgFound - 1000]._use[idx]._target.compareToIgnoreCase(_invTarget)) {
- ui.checkAction(people[ui._bgFound - 1000]._use[idx], ui._bgFound);
+ if (!person._use[idx]._verb.compareToIgnoreCase(_verb) &&
+ !person._use[idx]._target.compareToIgnoreCase(_invTarget)) {
+ ui.checkAction(person._use[idx], ui._bgFound);
found = true;
}
}
diff --git a/engines/sherlock/tattoo/widget_lab.cpp b/engines/sherlock/tattoo/widget_lab.cpp
index 2873b12f22..eb32e2e22c 100644
--- a/engines/sherlock/tattoo/widget_lab.cpp
+++ b/engines/sherlock/tattoo/widget_lab.cpp
@@ -45,7 +45,6 @@ void WidgetLab::handleEvents() {
Common::Point mousePos = events.mousePos();
WidgetBase::handleEvents();
- bool noDesc = false;
// Handle drawing tooltips. If the user is dragging a lab item, display a tooltip for using the item
// on another. Otherwise, fall back on showing standard tooltips
@@ -65,6 +64,7 @@ void WidgetLab::handleEvents() {
if (ui._arrowZone == -1 || events._rightReleased)
ui._tooltipWidget.setText("");
+ bool noDesc = false;
if (ui._bgFound != -1) {
if (ui._bgShape->_description.hasPrefix(" ") || ui._bgShape->_description.empty())
noDesc = true;
diff --git a/engines/sherlock/tattoo/widget_talk.cpp b/engines/sherlock/tattoo/widget_talk.cpp
index 00e8233a95..6e7bde292f 100644
--- a/engines/sherlock/tattoo/widget_talk.cpp
+++ b/engines/sherlock/tattoo/widget_talk.cpp
@@ -369,11 +369,11 @@ void WidgetTalk::handleEvents() {
void WidgetTalk::render(Highlight highlightMode) {
TattooTalk &talk = *(TattooTalk *)_vm->_talk;
- int yp = 5;
- int statementNum = 1;
- byte color;
if (highlightMode != HL_SCROLLBAR_ONLY) {
+ int yp = 5;
+ int statementNum = 1;
+
// Draw all the statements
// Check whether scrolling has occurred, and if so, figure out what the starting
// number for the first visible statement will be
@@ -392,7 +392,7 @@ void WidgetTalk::render(Highlight highlightMode) {
_surface.fillRect(Common::Rect(3, yp, _surface.w() - BUTTON_SIZE - 3, yp + _surface.fontHeight()), TRANSPARENCY);
// Different coloring based on whether the option has been previously chosen or not
- color = (!talk._talkHistory[talk._converseNum][_statementLines[idx]._num]) ?
+ byte color = (!talk._talkHistory[talk._converseNum][_statementLines[idx]._num]) ?
INFO_TOP : INFO_BOTTOM;
if (_statementLines[idx]._num == _selector && highlightMode == HL_CHANGED_HIGHLIGHTS)
diff --git a/engines/sherlock/tattoo/widget_verbs.cpp b/engines/sherlock/tattoo/widget_verbs.cpp
index 0b523a93e9..499afb2e79 100644
--- a/engines/sherlock/tattoo/widget_verbs.cpp
+++ b/engines/sherlock/tattoo/widget_verbs.cpp
@@ -58,9 +58,8 @@ void WidgetVerbs::load(bool objectsOn) {
// person or an object
if (ui._personFound) {
TattooPerson &person = people[ui._activeObj - 1000];
- TattooPerson &npc = people[ui._activeObj - 1001];
- if (!scumm_strnicmp(npc._npcName.c_str(), "WATS", 4))
+ if (!scumm_strnicmp(person._npcName.c_str(), "WATS", 4))
isWatson = true;
@@ -158,7 +157,6 @@ void WidgetVerbs::handleEvents() {
Talk &talk = *_vm->_talk;
TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
Common::Point mousePos = events.mousePos();
- bool noDesc = false;
Common::String strLook = fixedText.getText(kFixedText_Look);
Common::String strTalk = fixedText.getText(kFixedText_Talk);
@@ -184,6 +182,7 @@ void WidgetVerbs::handleEvents() {
ui._personFound = ui._bgFound >= 1000;
ui._bgShape = ui._personFound || ui._bgFound == -1 ? nullptr : &scene._bgShapes[ui._bgFound];
+ bool noDesc = false;
if (ui._personFound) {
if (people[ui._bgFound - 1000]._description.empty() || people[ui._bgFound - 1000]._description.hasPrefix(" "))
noDesc = true;
diff --git a/engines/sword25/detection_tables.h b/engines/sword25/detection_tables.h
index a9f263b7d4..644b8ef366 100644
--- a/engines/sword25/detection_tables.h
+++ b/engines/sword25/detection_tables.h
@@ -129,6 +129,19 @@ static const ADGameDescription gameDescriptions[] = {
GF_EXTRACTED | ADGF_UNSTABLE,
GUIO1(GUIO_NOASPECT)
},
+
+ // Distributed by ScummVM
+ // Contains all language packs, English voice-overs and Hungarian version
+ {
+ "sword25",
+ "Latest version",
+ AD_ENTRY1s("data.b25c", "880a8a67faf4a4e7ab62cf114b771428", 827397764),
+ Common::EN_ANY,
+ Common::kPlatformUnknown,
+ ADGF_UNSTABLE,
+ GUIO1(GUIO_NOASPECT)
+ },
+
AD_TABLE_END_MARKER
};
diff --git a/engines/sword25/gfx/graphicengine.cpp b/engines/sword25/gfx/graphicengine.cpp
index f887c3cd51..fd3b63aeee 100644
--- a/engines/sword25/gfx/graphicengine.cpp
+++ b/engines/sword25/gfx/graphicengine.cpp
@@ -60,13 +60,13 @@ enum {
namespace Sword25 {
-static const uint FRAMETIME_SAMPLE_COUNT = 5; // Anzahl der Framezeiten über die, die Framezeit gemittelt wird
+static const uint FRAMETIME_SAMPLE_COUNT = 5; // Frame duration is averaged over FRAMETIME_SAMPLE_COUNT frames
GraphicEngine::GraphicEngine(Kernel *pKernel) :
_width(0),
_height(0),
_bitDepth(0),
- _lastTimeStamp((uint) -1), // max. BS_INT64 um beim ersten Aufruf von _UpdateLastFrameDuration() einen Reset zu erzwingen
+ _lastTimeStamp((uint) -1), // force reset of _UpdateLastFrameDuration() on first call
_lastFrameDuration(0),
_timerActive(true),
_frameTimeSampleSlot(0),
@@ -87,19 +87,18 @@ GraphicEngine::~GraphicEngine() {
}
bool GraphicEngine::init(int width, int height, int bitDepth, int backbufferCount) {
- // Warnung ausgeben, wenn eine nicht unterstützte Bittiefe gewählt wurde.
+ // Warn when an unsupported bit depth has been selected.
if (bitDepth != BIT_DEPTH) {
warning("Can't use a bit depth of %d (not supported). Falling back to %d.", bitDepth, BIT_DEPTH);
_bitDepth = BIT_DEPTH;
}
- // Warnung ausgeben, wenn nicht genau ein Backbuffer gewählt wurde.
+ // Warn when wrong BackBuffer is specified.
if (backbufferCount != BACKBUFFER_COUNT) {
warning("Can't use %d backbuffers (not supported). Falling back to %d.", backbufferCount, BACKBUFFER_COUNT);
backbufferCount = BACKBUFFER_COUNT;
}
- // Parameter in lokale Variablen kopieren
_width = width;
_height = height;
_bitDepth = bitDepth;
@@ -112,13 +111,13 @@ bool GraphicEngine::init(int width, int height, int bitDepth, int backbufferCoun
_backSurface.create(width, height, format);
- // Standardmäßig ist Vsync an.
+ // By default Vsync is on.
setVsync(true);
- // Layer-Manager initialisieren.
+ // Layer-Manager initialization
_renderObjectManagerPtr.reset(new RenderObjectManager(width, height, backbufferCount + 1));
- // Hauptpanel erstellen
+ // Create the main panel
_mainPanelPtr = _renderObjectManagerPtr->getTreeRoot()->addPanel(width, height, BS_ARGB(0, 0, 0, 0));
if (!_mainPanelPtr.isValid())
return false;
@@ -128,11 +127,10 @@ bool GraphicEngine::init(int width, int height, int bitDepth, int backbufferCoun
}
bool GraphicEngine::startFrame(bool updateAll) {
- // Berechnen, wie viel Zeit seit dem letzten Frame vergangen ist.
- // Dieser Wert kann über GetLastFrameDuration() von Modulen abgefragt werden, die zeitabhängig arbeiten.
+ // Calculate how much time has elapsed since the last frame.
updateLastFrameDuration();
- // Den Layer-Manager auf den nächsten Frame vorbereiten
+ // Prepare the Layer Manager for the next frame
_renderObjectManagerPtr->startFrame();
return true;
@@ -276,7 +274,7 @@ Resource *GraphicEngine::loadResource(const Common::String &filename) {
PackageManager *pPackage = Kernel::getInstance()->getPackage();
assert(pPackage);
- // Datei laden
+ // Loading data
byte *pFileData;
uint fileSize;
pFileData = pPackage->getFile(filename, &fileSize);
@@ -375,10 +373,10 @@ bool GraphicEngine::saveThumbnailScreenshot(const Common::String &filename) {
void GraphicEngine::ARGBColorToLuaColor(lua_State *L, uint color) {
lua_Number components[4] = {
- (lua_Number)((color >> 16) & 0xff), // Rot
- (lua_Number)((color >> 8) & 0xff), // Grün
- (lua_Number)(color & 0xff), // Blau
- (lua_Number)(color >> 24), // Alpha
+ (lua_Number)((color >> 16) & 0xff), // Red
+ (lua_Number)((color >> 8) & 0xff), // Green
+ (lua_Number)(color & 0xff), // Blue
+ (lua_Number)(color >> 24), // Alpha
};
lua_newtable(L);
@@ -395,11 +393,11 @@ uint GraphicEngine::luaColorToARGBColor(lua_State *L, int stackIndex) {
int __startStackDepth = lua_gettop(L);
#endif
- // Sicherstellen, dass wir wirklich eine Tabelle betrachten
+ // Make sure that we really look at a table
luaL_checktype(L, stackIndex, LUA_TTABLE);
- // Größe der Tabelle auslesen
+ // getting table size
uint n = luaL_getn(L, stackIndex);
- // RGB oder RGBA Farben werden unterstützt und sonst keine
+ // only RGB or RGBA colors are supported
if (n != 3 && n != 4)
luaL_argcheck(L, 0, stackIndex, "at least 3 of the 4 color components have to be specified");
diff --git a/engines/sword25/gfx/image/vectorimage.cpp b/engines/sword25/gfx/image/vectorimage.cpp
index 0e5dfb9c53..756d063d43 100644
--- a/engines/sword25/gfx/image/vectorimage.cpp
+++ b/engines/sword25/gfx/image/vectorimage.cpp
@@ -283,7 +283,18 @@ VectorImage::VectorImage(const byte *pFileData, uint fileSize, bool &success, co
case 32:
success = parseDefineShape(3, bs);
return;
+ case 9:
+ // SetBackgroundColor
+ {
+ byte r, g, b;
+ r = bs.getByte();
+ g = bs.getByte();
+ b = bs.getByte();
+ _bgColor = Graphics::ARGBToColor<Graphics::ColorMasks<8888> >(0xff, r, g, b);
+ }
+ break;
default:
+ warning("Ignoring tag: %d, %d bytes", tagType, tagLength);
// Ignore unknown tags
bs.skipBytes(tagLength);
}
diff --git a/engines/sword25/gfx/image/vectorimage.h b/engines/sword25/gfx/image/vectorimage.h
index 057064fc6a..b5c2100681 100644
--- a/engines/sword25/gfx/image/vectorimage.h
+++ b/engines/sword25/gfx/image/vectorimage.h
@@ -228,6 +228,7 @@ private:
byte *_pixelData;
Common::String _fname;
+ uint _bgColor;
};
} // End of namespace Sword25
diff --git a/engines/sword25/gfx/screenshot.cpp b/engines/sword25/gfx/screenshot.cpp
index 4b4f967f29..eeaece97f2 100644
--- a/engines/sword25/gfx/screenshot.cpp
+++ b/engines/sword25/gfx/screenshot.cpp
@@ -40,7 +40,7 @@ namespace Sword25 {
bool Screenshot::saveToFile(Graphics::Surface *data, Common::WriteStream *stream) {
// Convert the RGBA data to RGB
- const byte *pSrc = (const byte *)data->getPixels();
+ const uint32 *pSrc = (const uint32 *)data->getPixels();
// Write our own custom header
stream->writeUint32BE(MKTAG('S','C','R','N')); // SCRN, short for "Screenshot"
@@ -52,11 +52,12 @@ bool Screenshot::saveToFile(Graphics::Surface *data, Common::WriteStream *stream
for (uint x = 0; x < data->w; x++) {
// This is only called by createThumbnail below, which
// provides a fake 'surface' with LE data in it.
- uint32 srcPixel = READ_LE_UINT32(pSrc);
- pSrc += sizeof(uint32);
- stream->writeByte((srcPixel >> 16) & 0xff); // R
- stream->writeByte((srcPixel >> 8) & 0xff); // G
- stream->writeByte(srcPixel & 0xff); // B
+ byte a, r, g, b;
+
+ data->format.colorToARGB(*pSrc++, a, r, g, b);
+ stream->writeByte(r);
+ stream->writeByte(g);
+ stream->writeByte(b);
}
}
@@ -81,30 +82,27 @@ Common::SeekableReadStream *Screenshot::createThumbnail(Graphics::Surface *data)
Graphics::Surface thumbnail;
thumbnail.create(200, 125, g_system->getScreenFormat());
- // Über das Zielbild iterieren und einen Pixel zur Zeit berechnen.
+ // Uber das Zielbild iterieren und einen Pixel zur Zeit berechnen.
uint x, y;
x = y = 0;
- for (byte *pDest = (byte *)thumbnail.getPixels(); pDest < ((byte *)thumbnail.getBasePtr(0, thumbnail.h)); ) {
+ for (uint32 *pDest = (uint32 *)thumbnail.getPixels(); pDest < thumbnail.getBasePtr(0, thumbnail.h); ) {
// Get an average over a 4x4 pixel block in the source image
int alpha, red, green, blue;
alpha = red = green = blue = 0;
for (int j = 0; j < 4; ++j) {
const uint32 *srcP = (const uint32 *)data->getBasePtr(x * 4, y * 4 + j + 50);
for (int i = 0; i < 4; ++i) {
- uint32 pixel = READ_UINT32(srcP + i);
- alpha += (pixel >> 24);
- red += (pixel >> 16) & 0xff;
- green += (pixel >> 8) & 0xff;
- blue += pixel & 0xff;
+ byte a, r, g, b;
+ data->format.colorToARGB(*(srcP + i), a, r, g, b);
+ alpha += a;
+ red += r;
+ green += g;
+ blue += b;
}
}
- // Write target pixel
- *pDest++ = blue / 16;
- *pDest++ = green / 16;
- *pDest++ = red / 16;
- *pDest++ = alpha / 16;
+ *pDest++ = thumbnail.format.ARGBToColor(alpha / 16, red / 16, green / 16, blue / 16);
// Move to next block
++x;
diff --git a/engines/sword25/gfx/staticbitmap.cpp b/engines/sword25/gfx/staticbitmap.cpp
index 1a6c812508..7ab76e625e 100644
--- a/engines/sword25/gfx/staticbitmap.cpp
+++ b/engines/sword25/gfx/staticbitmap.cpp
@@ -124,6 +124,10 @@ uint StaticBitmap::getPixel(int x, int y) const {
assert(pResource->getType() == Resource::TYPE_BITMAP);
BitmapResource *pBitmapResource = static_cast<BitmapResource *>(pResource);
uint result = pBitmapResource->getPixel(x, y);
+ // Convert to LUA-ready format
+ byte a;
+ a = result & 0xff;
+ result = (result >> 8) | (a << 24);
pResource->release();
return result;
}
diff --git a/engines/sword25/gfx/text.cpp b/engines/sword25/gfx/text.cpp
index 904435fcb0..d409c538c0 100644
--- a/engines/sword25/gfx/text.cpp
+++ b/engines/sword25/gfx/text.cpp
@@ -29,10 +29,6 @@
*
*/
-// TODO:
-// Entweder Fontfile absolut abspeichern, oder Verzeichniswechseln verbieten
-// Eine relative Fontfile-Angabe könnte verwandt werden nachdem das Verzeichnis bereits gewechselt wurde und die Datei würde nicht mehr gefunden
-
#include "sword25/kernel/kernel.h"
#include "sword25/kernel/outputpersistenceblock.h"
#include "sword25/kernel/inputpersistenceblock.h"
@@ -99,7 +95,7 @@ void Text::setText(const Common::String &text) {
}
void Text::setColor(uint32 modulationColor) {
- uint32 newModulationColor = (modulationColor & 0xffffff00) | (_modulationColor & 0x000000ff);
+ uint32 newModulationColor = (modulationColor & 0x00ffffff) | (_modulationColor & 0xff000000);
if (newModulationColor != _modulationColor) {
_modulationColor = newModulationColor;
forceRefresh();
@@ -108,7 +104,7 @@ void Text::setColor(uint32 modulationColor) {
void Text::setAlpha(int alpha) {
assert(alpha >= 0 && alpha < 256);
- uint32 newModulationColor = (_modulationColor & 0xffffff00) | alpha;
+ uint32 newModulationColor = (_modulationColor & 0xffffff) | (alpha << 24);
if (newModulationColor != _modulationColor) {
_modulationColor = newModulationColor;
forceRefresh();
@@ -132,12 +128,12 @@ void Text::setAutoWrapThreshold(uint32 autoWrapThreshold) {
}
bool Text::doRender(RectangleList *updateRects) {
- // Font-Resource locken.
+ // lock Font Resource
FontResource *fontPtr = lockFontResource();
if (!fontPtr)
return false;
- // Charactermap-Resource locken.
+ // lock Character map resource
ResourceManager *rmPtr = getResourceManager();
BitmapResource *charMapPtr;
{
@@ -154,18 +150,18 @@ bool Text::doRender(RectangleList *updateRects) {
charMapPtr = static_cast<BitmapResource *>(pResource);
}
- // Framebufferobjekt holen.
+ // Getting frame buffer object
GraphicEngine *gfxPtr = Kernel::getInstance()->getGfx();
assert(gfxPtr);
bool result = true;
Common::Array<Line>::iterator iter = _lines.begin();
for (; iter != _lines.end(); ++iter) {
- // Feststellen, ob überhaupt Buchstaben der aktuellen Zeile vom Update betroffen sind.
+ // Determine whether any letters of the current line are affected by the update.
Common::Rect checkRect = (*iter).bbox;
checkRect.translate(_absoluteX, _absoluteY);
- // Jeden Buchstaben einzeln Rendern.
+ // Render each letter individually.
int curX = _absoluteX + (*iter).bbox.left;
int curY = _absoluteY + (*iter).bbox.top;
for (uint i = 0; i < (*iter).text.size(); ++i) {
@@ -181,24 +177,24 @@ bool Text::doRender(RectangleList *updateRects) {
}
}
- // Charactermap-Resource freigeben.
+ // Free Character map resource
charMapPtr->release();
- // Font-Resource freigeben.
+ // Free Font resource
fontPtr->release();
return result;
}
ResourceManager *Text::getResourceManager() {
- // Pointer auf den Resource-Manager holen.
+ // Getting pointer to resource manager
return Kernel::getInstance()->getResourceManager();
}
FontResource *Text::lockFontResource() {
ResourceManager *rmPtr = getResourceManager();
- // Font-Resource locken.
+ // Lock font resource
FontResource *fontPtr;
{
Resource *resourcePtr = rmPtr->requestResource(_font);
@@ -278,7 +274,7 @@ void Text::updateFormat() {
i = lastSpace;
}
- // Bounding-Box der einzelnen Zeilen relativ zur ersten festlegen (vor allem zentrieren).
+ // Bounding box of each line relative to the first set (center aligned).
_height = 0;
Common::Array<Line>::iterator iter = _lines.begin();
for (; iter != _lines.end(); ++iter) {
@@ -290,7 +286,7 @@ void Text::updateFormat() {
_height += bbox.height();
}
} else {
- // Keine automatische Formatierung, also wird der gesamte Text in nur eine Zeile kopiert.
+ // No auto format, so all the text is copied to a single line.
_lines[0].text = _text;
_lines[0].bbox = Common::Rect(0, 0, _width, _height);
}
@@ -333,11 +329,11 @@ bool Text::unpersist(InputPersistenceBlock &reader) {
result &= RenderObject::unpersist(reader);
- // Farbe und Alpha einlesen.
+ // Read color and alpha
reader.read(_modulationColor);
- // Beim Laden der anderen Member werden die Set-Methoden benutzt statt der tatsächlichen Member.
- // So wird das Layout automatisch aktualisiert und auch alle anderen notwendigen Methoden ausgeführt.
+ // Run all methods on loading relevant members.
+ // So, the layout is automatically updated and all necessary logic is executed.
Common::String font;
reader.readString(font);
diff --git a/engines/sword25/util/lua/scummvm_file.cpp b/engines/sword25/util/lua/scummvm_file.cpp
index c38aba004f..bdceff0c0c 100644
--- a/engines/sword25/util/lua/scummvm_file.cpp
+++ b/engines/sword25/util/lua/scummvm_file.cpp
@@ -183,7 +183,7 @@ Common::String Sword25FileProxy::getLanguage() {
case Common::FR_FRA:
return "fr";
case Common::HU_HUN:
- return "hr";
+ return "hu";
case Common::IT_ITA:
return "it";
case Common::PL_POL:
@@ -210,7 +210,7 @@ void Sword25FileProxy::setLanguage(const Common::String &lang) {
ConfMan.set("language", Common::getLanguageCode(Common::ES_ESP));
else if (lang == "fr")
ConfMan.set("language", Common::getLanguageCode(Common::FR_FRA));
- else if (lang == "hr")
+ else if (lang == "hu")
ConfMan.set("language", Common::getLanguageCode(Common::HU_HUN));
else if (lang == "it")
ConfMan.set("language", Common::getLanguageCode(Common::IT_ITA));
diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp
index 9b4e2494e0..2a9804263a 100644
--- a/engines/tinsel/music.cpp
+++ b/engines/tinsel/music.cpp
@@ -418,9 +418,12 @@ MidiMusicPlayer::MidiMusicPlayer(TinselEngine *vm) {
// Version 2: drivers got installed and fat.opl got copied over by the user
_driver = Audio::MidiDriver_Miles_AdLib_create("MIDPAK.AD", "");
} else {
- // Version 1: sample.ad / sample.opl, have to be copied over by the user for this version
- // That's why we check those last, because then the user gets a proper error message for them
- _driver = Audio::MidiDriver_Miles_AdLib_create("SAMPLE.AD", "SAMPLE.OPL");
+ if ((fileClass.exists("SAMPLE.AD")) || (fileClass.exists("SAMPLE.OPL"))) {
+ // Version 1: sample.ad / sample.opl, have to be copied over by the user for this version
+ _driver = Audio::MidiDriver_Miles_AdLib_create("SAMPLE.AD", "SAMPLE.OPL");
+ } else {
+ error("MILES-ADLIB: timbre file not found (may be called FAT.OPL, MIDPAK.AD, SAMPLE.AD or SAMPLE.OPL, may be in a subdirectory)");
+ }
}
}
break;
diff --git a/engines/tucker/staticres.cpp b/engines/tucker/staticres.cpp
index b884851d7e..b9f6a6efee 100644
--- a/engines/tucker/staticres.cpp
+++ b/engines/tucker/staticres.cpp
@@ -329,8 +329,13 @@ static const SoundSequenceData _soundDataSeq19_20[] = {
{ 53, 2, 14, 100, 1 }, { 78, 2, 0, 100, 2 }, { 80, 0, 0, 100, 4 },
};
+// I've been told that there are versions of the game that don't play the
+// "introdub" music (130) for the first scene of the intro. The English "Euro
+// power pack" release does however, and I see no harm in doing it for every
+// version here. The volume is just a guess, though.
+
const SoundSequenceDataList AnimationSequencePlayer::_soundSeqDataList[] = {
- { 0, 0, 14, 10, 58, _soundDataSeq3_4 },
+ { 130, 80, 14, 10, 58, _soundDataSeq3_4 },
{ 0, 0, 14, 5, 60, _soundDataSeq9_10 },
{ 0, 0, 14, 9, 48, _soundDataSeq21_20 },
{ 1, 80, 14, 4, 25, _soundDataSeq13_14 },
@@ -471,6 +476,7 @@ const char *const AnimationSequencePlayer::_audioFileNamesTable[] = {
"rdfx38.wav",
"rdfx8.wav",
"rdfx9.wav",
+ "introdub.raw",
};
} // namespace Tucker
diff --git a/engines/tucker/tucker.h b/engines/tucker/tucker.h
index a423915a5f..3bbf6a57f5 100644
--- a/engines/tucker/tucker.h
+++ b/engines/tucker/tucker.h
@@ -246,6 +246,15 @@ private:
};
inline int scaleMixerVolume(int volume, int max = 100) {
+ if (volume > max) {
+ // This happens for instance for Bud's line, "Is that the
+ // great mystery invention you had hidden away?" in the intro,
+ // which is played at volume 110 out of 100. This made it very
+ // hard to hear. I'm not sure if this was a bug in the original
+ // game, or if it had the ability to amplify sounds.
+ warning("scaleMixerVolume: Adjusting volume %d to %d", volume, max);
+ volume = max;
+ }
return volume * Audio::Mixer::kMaxChannelVolume / max;
}
diff --git a/engines/wintermute/base/file/base_file.cpp b/engines/wintermute/base/file/base_file.cpp
index 2927c908e2..4589721e7e 100644
--- a/engines/wintermute/base/file/base_file.cpp
+++ b/engines/wintermute/base/file/base_file.cpp
@@ -57,7 +57,7 @@ bool BaseFile::isEOF() {
Common::SeekableReadStream *BaseFile::getMemStream() {
uint32 oldPos = getPos();
seek(0);
- byte *data = new byte[getSize()];
+ byte *data = (byte *)malloc(getSize());
read(data, getSize());
seek(oldPos);
Common::MemoryReadStream *memStream = new Common::MemoryReadStream(data, getSize(), DisposeAfterUse::YES);
diff --git a/engines/wintermute/base/gfx/base_surface.cpp b/engines/wintermute/base/gfx/base_surface.cpp
index f8b96b5baf..3aa500b224 100644
--- a/engines/wintermute/base/gfx/base_surface.cpp
+++ b/engines/wintermute/base/gfx/base_surface.cpp
@@ -75,11 +75,6 @@ bool BaseSurface::displayHalfTrans(int x, int y, Rect32 rect) {
}
//////////////////////////////////////////////////////////////////////////
-bool BaseSurface::displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const Graphics::TransformStruct &transform) {
- return displayTransform(x, y, rect, newRect, transform);
-}
-
-//////////////////////////////////////////////////////////////////////////
bool BaseSurface::create(int width, int height) {
return STATUS_FAILED;
}
diff --git a/engines/wintermute/detection_tables.h b/engines/wintermute/detection_tables.h
index 4e3320159a..25a01766e4 100644
--- a/engines/wintermute/detection_tables.h
+++ b/engines/wintermute/detection_tables.h
@@ -140,9 +140,18 @@ static const WMEGameDescription gameDescriptions[] = {
// Five Lethal Demons
WME_WINENTRY("5ld", "",
WME_ENTRY1s("data.dcp", "1037a77cbd001e0644898addc022322c", 15407750), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
- // Five Magical Amulets
+ // Five Magical Amulets (Czech)
WME_WINENTRY("5ma", "",
- WME_ENTRY1s("data.dcp", "0134e92bcd5fd2837df3971087e96067", 163316498), Common::EN_ANY, ADGF_UNSTABLE, WME_1_7_0),
+ WME_ENTRY2s("czech.dcp", "7b2515a8ceb955c72bc14f0f1fca869e", 184,
+ "data.dcp", "0134e92bcd5fd2837df3971087e96067", 163316498), Common::CZ_CZE, ADGF_UNSTABLE, WME_1_7_0),
+ // Five Magical Amulets (English)
+ WME_WINENTRY("5ma", "",
+ WME_ENTRY2s("english.dcp", "2f97bca09260ba23b645da9f0855ce7f", 893681,
+ "data.dcp", "0134e92bcd5fd2837df3971087e96067", 163316498), Common::EN_ANY, ADGF_UNSTABLE, WME_1_7_0),
+ // Five Magical Amulets (Polish)
+ WME_WINENTRY("5ma", "",
+ WME_ENTRY2s("polish.dcp", "bb877d48795471a17f25b0b5109100d1", 1132197,
+ "data.dcp", "0134e92bcd5fd2837df3971087e96067", 163316498), Common::PL_POL, ADGF_UNSTABLE, WME_1_7_0),
// Actual Destination
WME_WINENTRY("actualdest", "",
WME_ENTRY1s("data.dcp", "6926f44b26f21ceb1d840eaab9aeb510", 9081740), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
@@ -334,6 +343,22 @@ static const WMEGameDescription gameDescriptions[] = {
// Oknytt
WME_WINENTRY("oknytt", "Version 1.0",
WME_ENTRY1s("data.dcp", "6456cf8f429905c83f07509f9da536dd", 109502959), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
+ // Oknytt (Version 1.13 English) (These are detected along with d_sounds.dcp to avoid mass-detecting in the languages-subfolder.)
+ WME_WINENTRY("oknytt", "Version 1.13",
+ WME_ENTRY2s("english.dcp", "d2afd722c78cfe66b7d4250d11f6ae16", 293274135,
+ "d_sounds.dcp", "7d04dff8ca11174486bd4b7a80fdcabb", 154943401), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
+ // Oknytt (Version 1.13 German)
+ WME_WINENTRY("oknytt", "Version 1.13",
+ WME_ENTRY2s("german.dcp", "0fc6401d8d76b04f6da49206ecafa0dc", 304292574,
+ "d_sounds.dcp", "7d04dff8ca11174486bd4b7a80fdcabb", 154943401), Common::DE_DEU, ADGF_UNSTABLE, LATEST_VERSION),
+ // Oknytt (Version 1.13 Russian)
+ WME_WINENTRY("oknytt", "Version 1.13",
+ WME_ENTRY2s("russian.dcp", "dd24a1c0b36a82e2b02fb6c1050d4aad", 362681669,
+ "d_sounds.dcp", "7d04dff8ca11174486bd4b7a80fdcabb", 154943401), Common::RU_RUS, ADGF_UNSTABLE, LATEST_VERSION),
+ // Oknytt (Version 1.13 Spanish)
+ WME_WINENTRY("oknytt", "Version 1.13",
+ WME_ENTRY2s("spanish.dcp", "10c46152cb29581671f3b6b7c229c957", 319406572,
+ "d_sounds.dcp", "7d04dff8ca11174486bd4b7a80fdcabb", 154943401), Common::ES_ESP, ADGF_UNSTABLE, LATEST_VERSION),
// Night Train Demo
WME_WINENTRY("nighttrain", "",
WME_ENTRY1s("data.dcp", "5a027ef84b083a730c9a4c85ec1d3a32", 131760816), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
diff --git a/engines/wintermute/utils/convert_utf.cpp b/engines/wintermute/utils/convert_utf.cpp
index 7ebc011d01..cdb48103d0 100644
--- a/engines/wintermute/utils/convert_utf.cpp
+++ b/engines/wintermute/utils/convert_utf.cpp
@@ -55,8 +55,6 @@ static const UTF32 halfMask = 0x3FFUL;
#define UNI_SUR_HIGH_END (UTF32)0xDBFF
#define UNI_SUR_LOW_START (UTF32)0xDC00
#define UNI_SUR_LOW_END (UTF32)0xDFFF
-#define false 0
-#define true 1
/* --------------------------------------------------------------------- */
@@ -311,7 +309,7 @@ ConversionResult ConvertUTF16toUTF8(
* definition of UTF-8 goes up to 4-byte sequences.
*/
-static Boolean isLegalUTF8(const UTF8 *source, int length) {
+static bool isLegalUTF8(const UTF8 *source, int length) {
UTF8 a;
const UTF8 *srcptr = source + length;
switch (length) {
@@ -356,7 +354,7 @@ static Boolean isLegalUTF8(const UTF8 *source, int length) {
* Exported function to return whether a UTF-8 sequence is legal or not.
* This is not used here; it's just exported.
*/
-Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
+bool isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
int length = trailingBytesForUTF8[*source] + 1;
if (source + length > sourceEnd) {
return false;
diff --git a/engines/wintermute/utils/convert_utf.h b/engines/wintermute/utils/convert_utf.h
index a5f34456f5..d2e54f4af4 100644
--- a/engines/wintermute/utils/convert_utf.h
+++ b/engines/wintermute/utils/convert_utf.h
@@ -96,7 +96,6 @@ namespace Wintermute {
typedef uint32 UTF32; /* at least 32 bits */
typedef uint16 UTF16; /* at least 16 bits */
typedef uint8 UTF8; /* typically 8 bits */
-typedef uint8 Boolean; /* 0 or 1 */
/* Some fundamental constants */
#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
@@ -141,7 +140,7 @@ ConversionResult ConvertUTF32toUTF16(
const UTF32 **sourceStart, const UTF32 *sourceEnd,
UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags);
-Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
+bool isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
} // End of namespace Wintermute
diff --git a/engines/zvision/POTFILES b/engines/zvision/POTFILES
index 48e2782648..61cf42ded2 100644
--- a/engines/zvision/POTFILES
+++ b/engines/zvision/POTFILES
@@ -1 +1 @@
-engines/zvision/detection.cpp
+engines/zvision/detection_tables.h
diff --git a/engines/zvision/video/zork_avi_decoder.cpp b/engines/zvision/video/zork_avi_decoder.cpp
index cf8505ec82..1d23546551 100644
--- a/engines/zvision/video/zork_avi_decoder.cpp
+++ b/engines/zvision/video/zork_avi_decoder.cpp
@@ -34,44 +34,43 @@
namespace ZVision {
Video::AVIDecoder::AVIAudioTrack *ZorkAVIDecoder::createAudioTrack(Video::AVIDecoder::AVIStreamHeader sHeader, Video::AVIDecoder::PCMWaveFormat wvInfo) {
- ZorkAVIDecoder::ZorkAVIAudioTrack *audioTrack = new ZorkAVIDecoder::ZorkAVIAudioTrack(sHeader, wvInfo, _soundType);
- return (Video::AVIDecoder::AVIAudioTrack *)audioTrack;
+ if (wvInfo.tag != kWaveFormatZorkPCM)
+ return new AVIAudioTrack(sHeader, wvInfo, _soundType);
+
+ assert(wvInfo.size == 8);
+ return new ZorkAVIAudioTrack(sHeader, wvInfo, _soundType);
+}
+
+ZorkAVIDecoder::ZorkAVIAudioTrack::ZorkAVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType) :
+ Video::AVIDecoder::AVIAudioTrack(streamHeader, waveFormat, soundType), _queueStream(0), _decoder(waveFormat.channels == 2) {
}
-void ZorkAVIDecoder::ZorkAVIAudioTrack::queueSound(Common::SeekableReadStream *stream) {
- bool updateCurChunk = true;
- if (_audStream) {
- if (_wvInfo.tag == kWaveFormatZorkPCM) {
- assert(_wvInfo.size == 8);
- RawChunkStream::RawChunk chunk = decoder->readNextChunk(stream);
- delete stream;
+void ZorkAVIDecoder::ZorkAVIAudioTrack::createAudioStream() {
+ _queueStream = Audio::makeQueuingAudioStream(_wvInfo.samplesPerSec, _wvInfo.channels == 2);
+ _audioStream = _queueStream;
+}
+
+void ZorkAVIDecoder::ZorkAVIAudioTrack::queueSound(Common::SeekableReadStream *stream) {
+ RawChunkStream::RawChunk chunk = _decoder.readNextChunk(stream);
+ delete stream;
- if (chunk.data) {
- byte flags = Audio::FLAG_16BITS | Audio::FLAG_STEREO;
+ if (chunk.data) {
+ byte flags = Audio::FLAG_16BITS;
+ if (_wvInfo.channels == 2)
+ flags |= Audio::FLAG_STEREO;
#ifdef SCUMM_LITTLE_ENDIAN
- // RawChunkStream produces native endianness int16
- flags |= Audio::FLAG_LITTLE_ENDIAN;
+ // RawChunkStream produces native endianness int16
+ flags |= Audio::FLAG_LITTLE_ENDIAN;
#endif
- _audStream->queueBuffer((byte *)chunk.data, chunk.size, DisposeAfterUse::YES, flags);
- }
- } else {
- updateCurChunk = false;
- AVIAudioTrack::queueSound(stream);
- }
- } else {
- delete stream;
+ _queueStream->queueBuffer((byte *)chunk.data, chunk.size, DisposeAfterUse::YES, flags);
}
- // The superclass always updates _curChunk, whether or not audio has
- // been queued, so we should do that too. Unless the superclass already
- // has done it for us.
- if (updateCurChunk) {
- _curChunk++;
- }
+ _curChunk++;
}
void ZorkAVIDecoder::ZorkAVIAudioTrack::resetStream() {
- decoder->init();
+ AVIAudioTrack::resetStream();
+ _decoder.init();
}
} // End of namespace ZVision
diff --git a/engines/zvision/video/zork_avi_decoder.h b/engines/zvision/video/zork_avi_decoder.h
index 89c0d1e4b9..afcdb05676 100644
--- a/engines/zvision/video/zork_avi_decoder.h
+++ b/engines/zvision/video/zork_avi_decoder.h
@@ -39,22 +39,15 @@ public:
private:
class ZorkAVIAudioTrack : public Video::AVIDecoder::AVIAudioTrack {
public:
- ZorkAVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType) :
- Video::AVIDecoder::AVIAudioTrack(streamHeader, waveFormat, soundType),
- decoder(NULL) {
- if (_audStream) {
- decoder = new RawChunkStream(_audStream->isStereo());
- }
- }
- virtual ~ZorkAVIAudioTrack() {
- if (decoder)
- delete decoder;
- }
+ ZorkAVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType);
+ void createAudioStream();
void queueSound(Common::SeekableReadStream *stream);
void resetStream();
+
private:
- RawChunkStream *decoder;
+ Audio::QueuingAudioStream *_queueStream;
+ RawChunkStream _decoder;
};
Video::AVIDecoder::AVIAudioTrack *createAudioTrack(Video::AVIDecoder::AVIStreamHeader sHeader, Video::AVIDecoder::PCMWaveFormat wvInfo);