[Scummvm-git-logs] scummvm master -> f64ac55443a1513d8377ce1633f8de6e25dd2a7f

antoniou79 noreply at scummvm.org
Wed Jul 6 14:04:23 UTC 2022


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
f64ac55443 BLADERUNNER: Support font hd and subtitles code cleanup


Commit: f64ac55443a1513d8377ce1633f8de6e25dd2a7f
    https://github.com/scummvm/scummvm/commit/f64ac55443a1513d8377ce1633f8de6e25dd2a7f
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2022-07-06T14:46:57+03:00

Commit Message:
BLADERUNNER: Support font hd and subtitles code cleanup

In preparation for subtitles v7 and queuing system

Changed paths:
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/game_constants.h
    engines/bladerunner/scene.cpp
    engines/bladerunner/script/scene/ma04.cpp
    engines/bladerunner/script/scene_script.h
    engines/bladerunner/subtitles.cpp
    engines/bladerunner/subtitles.h


diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 94e75955e10..ced802611e7 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -134,6 +134,8 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst, const ADGameDescription *des
 	_validBootParam               = false;
 
 	_playerLosesControlCounter = 0;
+	_extraCPos = 0;
+	_extraCNotify = 0;
 
 	_playerActorIdle = false;
 	_playerDead      = false;
@@ -1686,6 +1688,35 @@ void BladeRunnerEngine::handleKeyDown(Common::Event &event) {
 		_scores->handleKeyDown(event.kbd);
 		return;
 	}
+
+	if ((_scene->getSetId() == kSetMA02_MA04 || _scene->getSetId() == kSetMA04)
+	    && _scene->getSceneId() == kSceneMA04
+	    && _subtitles->isHDCPresent()
+	    && _extraCNotify == 0) {
+		if (toupper(event.kbd.ascii) != _subtitles->getGoVib()[_extraCPos]) {
+			setExtraCNotify(0);
+		}
+		if (toupper(event.kbd.ascii) == _subtitles->getGoVib()[_extraCPos]) {
+			++_extraCPos;
+			if (!_subtitles->getGoVib()[_extraCPos]) {
+				_subtitles->xcReload();
+				playerLosesControl();
+				setExtraCNotify(1);
+				_extraCPos = 0;
+			}
+		}
+	}
+}
+
+uint8 BladeRunnerEngine::getExtraCNotify() {
+	return _extraCNotify;
+}
+
+void BladeRunnerEngine::setExtraCNotify(uint8 val) {
+	if (val == 0) {
+		_extraCPos = 0;
+	}
+	_extraCNotify = val;
 }
 
 // Check if an polled event belongs to a currently disabled keymap and, if so, drop it.
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index e56e6c477e0..cd2efb101a0 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -135,6 +135,8 @@ public:
 	bool _gameIsRunning;
 	bool _windowIsActive;
 	int  _playerLosesControlCounter;
+	int  _extraCPos;
+	uint8 _extraCNotify;
 
 	Common::String   _languageCode;
 	Common::Language _language;
@@ -437,6 +439,9 @@ public:
 	Graphics::Surface generateThumbnail() const;
 
 	Common::String getTargetName() const;
+
+	uint8 getExtraCNotify();
+	void  setExtraCNotify(uint8 val);
 };
 
 static inline const Graphics::PixelFormat gameDataPixelFormat() {
diff --git a/engines/bladerunner/game_constants.h b/engines/bladerunner/game_constants.h
index 74dae393fb4..0ffc426b056 100644
--- a/engines/bladerunner/game_constants.h
+++ b/engines/bladerunner/game_constants.h
@@ -1341,7 +1341,8 @@ enum SceneLoopMode {
 	kSceneLoopModeLoseControl =  0,
 	kSceneLoopModeChangeSet   =  1,
 	kSceneLoopModeOnce        =  2,
-	kSceneLoopModeSpinner     =  3
+	kSceneLoopModeSpinner     =  3,
+	kSceneLoopModeOnceNStay   =  4
 };
 
 enum Scenes {
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index eafcb46ab8c..9711b6553e4 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -133,6 +133,11 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 
 	_vm->_sliceRenderer->setView(_vm->_view);
 
+	if ((setId == kSetMA02_MA04 || setId == kSetMA04)
+	    && sceneId == kSceneMA04) {
+		_vm->setExtraCNotify(0);
+	}
+
 	if (isLoadingGame) {
 		resume(true);
 		if (sceneId == kScenePS10    // police maze
@@ -242,7 +247,7 @@ int Scene::advanceFrame(bool useTime) {
 		_vqaPlayer->updateLights(_vm->_lights);
 	}
 
-	if (_specialLoopMode == kSceneLoopModeLoseControl || _specialLoopMode == kSceneLoopModeOnce || _specialLoopMode == kSceneLoopModeSpinner) {
+	if (_specialLoopMode == kSceneLoopModeLoseControl || _specialLoopMode == kSceneLoopModeOnce || _specialLoopMode == kSceneLoopModeOnceNStay || _specialLoopMode == kSceneLoopModeSpinner) {
 		if (!_defaultLoopSet) {
 			_vqaPlayer->setLoop(_defaultLoop, -1, kLoopSetModeEnqueue, &Scene::loopEndedStatic, this);
 			_defaultLoopSet = true;
@@ -345,7 +350,7 @@ void Scene::loopStartSpecial(int specialLoopMode, int loopId, bool immediately)
 	_specialLoop = loopId;
 
 	int repeats = -1;
-	if (_specialLoopMode == kSceneLoopModeChangeSet) {
+	if (_specialLoopMode == kSceneLoopModeChangeSet || _specialLoopMode == kSceneLoopModeOnceNStay) {
 		repeats = 0;
 	}
 
diff --git a/engines/bladerunner/script/scene/ma04.cpp b/engines/bladerunner/script/scene/ma04.cpp
index 90cd232af47..32647f8701a 100644
--- a/engines/bladerunner/script/scene/ma04.cpp
+++ b/engines/bladerunner/script/scene/ma04.cpp
@@ -19,6 +19,9 @@
  *
  */
 
+#include "bladerunner/ambient_sounds.h"
+#include "bladerunner/audio_player.h"
+#include "bladerunner/subtitles.h"
 #include "bladerunner/script/scene_script.h"
 
 namespace BladeRunner {
@@ -75,6 +78,7 @@ void SceneScriptMA04::InitializeScene() {
 		Ambient_Sounds_Add_Sound(kSfxVIDFONE1, 3, 3, 100, 100, 0, 0, 0, 0, 99, 0);
 	}
 	Scene_Loop_Set_Default(kMA04LoopMainLoop);
+	_vm->setExtraCNotify(0);
 }
 
 void SceneScriptMA04::SceneLoaded() {
@@ -89,6 +93,7 @@ void SceneScriptMA04::SceneLoaded() {
 		Clickable_Object("BED-TV-1");
 		Clickable_Object("BED-TV-2");
 	}
+	_vm->setExtraCNotify(0);
 }
 
 bool SceneScriptMA04::MouseClick(int x, int y) {
@@ -247,9 +252,17 @@ void SceneScriptMA04::SceneFrameAdvanced(int frame) {
 	} else {
 		Set_Fade_Density(0.0f);
 	}
-	if (frame == 121 && (Game_Flag_Query(kFlagZubenRetired) || Game_Flag_Query(kFlagZubenSpared)) && !Game_Flag_Query(kFlagPS04GuzzaTalkZubenRetired)) {
+	if (frame == 121 && _vm->getExtraCNotify() == 0 && (Game_Flag_Query(kFlagZubenRetired) || Game_Flag_Query(kFlagZubenSpared)) && !Game_Flag_Query(kFlagPS04GuzzaTalkZubenRetired)) {
 		Sound_Play(kSfxVIDFONE1, 50, 0, 0, 50);
 	}
+
+	if (frame >= 30 && frame < 91 && _vm->getExtraCNotify() == 1) {
+		_vm->setExtraCNotify(2);
+		blip();
+	}
+	if (frame >= 100 && frame < 121 && _vm->getExtraCNotify() == 2) {
+		_vm->setExtraCNotify(3);
+	}
 }
 
 void SceneScriptMA04::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
@@ -588,6 +601,34 @@ void SceneScriptMA04::turnOnTV() {
 	}
 }
 
+void SceneScriptMA04::blip() {
+	Music_Stop(2u);
+	_vm->_ambientSounds->playSound(kSfxMUSVOL8, 22, 46, 46, 99, Audio::Mixer::kSFXSoundType);
+	ADQ_Flush();
+	if (!Loop_Actor_Walk_To_XYZ(kActorMcCoy, -7191.52f, 954.11f, 1834.47f, 0, false, false, false)) {
+		Actor_Face_Current_Camera(kActorMcCoy, true);
+		if (isPhoneMessageWaiting() || isPhoneRinging()) {
+			Overlay_Remove("MA04OVER");
+			if (isPhoneRinging()) {
+				Ambient_Sounds_Remove_Sound(kSfxVIDFONE1, true);
+			}
+		}
+		Scene_Loop_Start_Special(kSceneLoopModeOnceNStay, kMA04LoopSleep, false);
+		_vm->_audioPlayer->playAud(_vm->_subtitles->getLoadAvgStr(), 100, 0, 0, 50, kAudioPlayerOverrideVolume, Audio::Mixer::kSpeechSoundType);
+		Delay(40000);
+		Scene_Loop_Start_Special(kSceneLoopModeOnce, kMA04LoopWakeup, true);
+		Delay(1000);
+		if (isPhoneMessageWaiting() || isPhoneRinging()) {
+			Overlay_Play("MA04OVER", 0, true, false, 0);
+			if (isPhoneRinging()) {
+				Ambient_Sounds_Add_Sound(kSfxVIDFONE1, 3, 3, 100, 100, 0, 0, 0, 0, 99, 0);
+			}
+		}
+	}
+	_vm->setExtraCNotify(0);
+	Player_Gains_Control();
+}
+
 void SceneScriptMA04::sleep() {
 	if (!Loop_Actor_Walk_To_Scene_Object(kActorMcCoy, "BED-SHEETS", 12, true, false)) {
 		Actor_Says(kActorMcCoy, 8530, 12);
diff --git a/engines/bladerunner/script/scene_script.h b/engines/bladerunner/script/scene_script.h
index 957e3cf95ad..8f12e23d8ea 100644
--- a/engines/bladerunner/script/scene_script.h
+++ b/engines/bladerunner/script/scene_script.h
@@ -279,6 +279,7 @@ DECLARE_SCRIPT(MA04)
 	void phoneCallWithClovis();
 	void turnOnTV();
 	void sleep();
+	void blip();
 END_SCRIPT
 
 DECLARE_SCRIPT(MA05)
diff --git a/engines/bladerunner/subtitles.cpp b/engines/bladerunner/subtitles.cpp
index b3459bb2f44..a9810784f5a 100644
--- a/engines/bladerunner/subtitles.cpp
+++ b/engines/bladerunner/subtitles.cpp
@@ -25,6 +25,7 @@
 #include "bladerunner/text_resource.h"
 #include "bladerunner/audio_speech.h"
 #include "bladerunner/game_constants.h"
+#include "bladerunner/time.h"
 
 #include "common/debug.h"
 
@@ -61,6 +62,27 @@ namespace BladeRunner {
 const char *Subtitles::SUBTITLES_FONT_FILENAME_EXTERNAL = "SUBTLS_E.FON";
 
 const char *Subtitles::SUBTITLES_VERSION_TRENAME        = "SBTLVERS"; // addon resource file for Subtitles version info - can only be SBTLVERS.TRE
+const char *Subtitles::EXTRA_TRENAME                    = "EXTRA";
+
+const Color256 Subtitles::kTextColors[] = {
+	{ 0, 0, 0 },
+	{ 16, 8, 8 },
+	{ 32, 24, 8 },
+	{ 56, 32, 16 },
+	{ 72, 48, 16 },
+	{ 88, 56, 24 },
+	{ 104, 72, 32 },
+	{ 128, 80, 40 },
+	{ 136, 96, 48 },
+	{ 152, 112, 56 },
+	{ 168, 128, 72 },
+	{ 184, 144, 88 },
+	{ 200, 160, 96 },
+	{ 216, 184, 112 },
+	{ 232, 200, 128 },
+	{ 240, 224, 144 }
+};
+
 /*
  * All entries need to have the language code appended (after a '_').
  * And all entries should get the suffix extension ".TRx"; the last letter in extension "TR*" should also be the language code
@@ -108,7 +130,23 @@ Subtitles::Subtitles(BladeRunnerEngine *vm) {
 	}
 	_font = nullptr;
 	_useUTF8 = false;
-	_subtitlesData.resize(kNumOfSubtitleRoles);
+	_useHDC = false;
+	_subtitlesDataActive.resize(kNumOfSubtitleRoles);
+	_loadAvgStr = "";
+	_excTitlStr = "";
+	_goVib = "";
+	_xcStringIndex = 0;
+	_xcTimeLast    = 0;
+
+	for (int i = 0; i < kxcStringCount; ++i) {
+		_xcStrings[i] = "";
+	}
+
+	for (int i = 0; i < kxcLineCount; ++i) {
+		_xcLineTexts[i]    = "";
+		_xcLineTimeouts[i] = 0;
+		_xcLineOffsets[i]  = 0;
+	}
 	reset();
 }
 
@@ -117,7 +155,8 @@ Subtitles::Subtitles(BladeRunnerEngine *vm) {
  */
 Subtitles::~Subtitles() {
 	reset();
-	_subtitlesData.clear();
+	_subtitlesDataActive.clear();
+	_subtitlesEXC.clear();
 }
 
 //
@@ -155,6 +194,59 @@ void Subtitles::init(void) {
 		debug("Subtitles version info: N/A");
 	}
 
+	TextResource extraTxtResource(_vm);
+	if ( extraTxtResource.open(EXTRA_TRENAME, false) && extraTxtResource.getCount() > 0) {
+		_subtitlesEXC.resize(extraTxtResource.getCount());
+		for (uint8 i = 0; i < extraTxtResource.getCount(); ++i) {
+			_subtitlesEXC[i] = extraTxtResource.getText((uint32)i);
+		}
+		_loadAvgStr = "";
+		_excTitlStr = "";
+		_goVib = "";
+		if (extraTxtResource.getCount() == kxcStringCount + 1) {
+			_loadAvgStr.insertChar(_subtitlesEXC[3][13], 0);
+			_loadAvgStr.insertChar(_subtitlesEXC[3][12], 0);
+			_loadAvgStr.insertChar(_subtitlesEXC[0][7],  0);
+			_loadAvgStr.insertChar(_subtitlesEXC[14][1], 0);
+			_loadAvgStr.insertChar(_subtitlesEXC[10][7], 0);
+			_loadAvgStr.insertChar(_subtitlesEXC[1][8],  0);
+			_loadAvgStr.insertChar(_subtitlesEXC[0][5],  0);
+			_loadAvgStr.insertChar(_subtitlesEXC[2][12], 0);
+			_loadAvgStr.insertChar(_subtitlesEXC[1][2],  0);
+			_loadAvgStr.insertChar(_subtitlesEXC[7][5],  0);
+			_loadAvgStr.insertChar(_subtitlesEXC[2][1],  0);
+			_loadAvgStr.insertChar(_subtitlesEXC[2][7],  0);
+			_loadAvgStr.toUppercase();
+			_excTitlStr.insertChar(_subtitlesEXC[14][0], 0);
+			_excTitlStr.insertChar(_subtitlesEXC[0][2],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[1][2],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[3][8],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[2][7],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[7][3],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[2][4],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[0][8],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[1][8],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[3][11], 0);
+			_excTitlStr.insertChar(_subtitlesEXC[2][6],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[8][7],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[6][8],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[4][3],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[5][2],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[7][6],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[0][12], 0);
+			_excTitlStr.insertChar(_subtitlesEXC[10][9], 0);
+			_excTitlStr.insertChar(_subtitlesEXC[1][5],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[8][10], 0);
+			_excTitlStr.insertChar(_subtitlesEXC[6][2],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[5][3],  0);
+			_excTitlStr.insertChar(_subtitlesEXC[11][1], 0);
+			_excTitlStr.insertChar(_subtitlesEXC[4][4],  0);
+			_goVib = extraTxtResource.getText((uint32)9);
+			_goVib.toUppercase();
+			_useHDC = true;
+		}
+	}
+
 	//
 	// Initializing/Loading Subtitles Fonts
 	if (_subtitlesInfo.fontType == Subtitles::kSubtitlesFontTypeInternal) {
@@ -210,6 +302,26 @@ Subtitles::SubtitlesInfo Subtitles::getSubtitlesInfo() const {
 	return _subtitlesInfo;
 }
 
+void Subtitles::xcReload() {
+	_xcStringIndex = 0;
+	for (int i = 0; i < kxcStringCount; ++i) {
+		_xcStrings[i] = _subtitlesEXC[i];
+	}
+
+	for (int i = 0; i < kxcStringCount; ++i) {
+		int j = _vm->_rnd.getRandomNumberRng(i, kxcStringCount - 1);
+		SWAP<Common::String>(_xcStrings[i], _subtitlesEXC[j]);
+	}
+
+	for (int i = 0; i < kxcLineCount; ++i) {
+		_xcLineTexts[i] = "";
+		_xcLineTimeouts[i] = _vm->_rnd.getRandomNumberRng(0, 63);
+		_xcLineOffsets[i] = 0;
+	}
+
+	_xcTimeLast = _vm->_time->currentSystem();
+}
+
 /**
  * Returns the index of the specified Text Resource filename in the SUBTITLES_FILENAME_PREFIXES table
  */
@@ -239,10 +351,10 @@ void Subtitles::loadInGameSubsText(int actorId, int speech_id)  {
 	}
 
 	if (!_gameSubsResourceEntriesFound[0]) {
-		_subtitlesData[kSubtitlesPrimary].currentText.clear();
-		_subtitlesData[kSubtitlesPrimary].currentText32.clear();
-		_subtitlesData[kSubtitlesPrimary].prevText.clear();
-		_subtitlesData[kSubtitlesPrimary].prevText32.clear();
+		_subtitlesDataActive[kSubtitlesPrimary].currentText.clear();
+		_subtitlesDataActive[kSubtitlesPrimary].currentText32.clear();
+		_subtitlesDataActive[kSubtitlesPrimary].prevText.clear();
+		_subtitlesDataActive[kSubtitlesPrimary].prevText32.clear();
 		return;
 	}
 
@@ -261,9 +373,9 @@ void Subtitles::loadInGameSubsText(int actorId, int speech_id)  {
 		int32 id = 10000 * actorId + speech_id;
 		const char *text = _vqaSubsTextResourceEntries[0]->getText((uint32)id);
 		if (_useUTF8) {
-			_subtitlesData[kSubtitlesPrimary].currentText32 = Common::convertUtf8ToUtf32(text);
+			_subtitlesDataActive[kSubtitlesPrimary].currentText32 = Common::convertUtf8ToUtf32(text);
 		} else {
-			_subtitlesData[kSubtitlesPrimary].currentText = text;
+			_subtitlesDataActive[kSubtitlesPrimary].currentText = text;
 		}
 	}
 }
@@ -278,10 +390,10 @@ void Subtitles::loadOuttakeSubsText(const Common::String &outtakesName, int fram
 
 	int fileIdx = getIdxForSubsTreName(outtakesName);
 	if (fileIdx == -1 || !_gameSubsResourceEntriesFound[fileIdx]) {
-		_subtitlesData[kSubtitlesPrimary].currentText.clear();
-		_subtitlesData[kSubtitlesPrimary].currentText32.clear();
-		_subtitlesData[kSubtitlesPrimary].prevText.clear();
-		_subtitlesData[kSubtitlesPrimary].prevText32.clear();
+		_subtitlesDataActive[kSubtitlesPrimary].currentText.clear();
+		_subtitlesDataActive[kSubtitlesPrimary].currentText32.clear();
+		_subtitlesDataActive[kSubtitlesPrimary].prevText.clear();
+		_subtitlesDataActive[kSubtitlesPrimary].prevText32.clear();
 		return;
 	}
 
@@ -298,9 +410,9 @@ void Subtitles::loadOuttakeSubsText(const Common::String &outtakesName, int fram
 	// debug("Number of resource quotes to search: %d, requested frame: %u", _vqaSubsTextResourceEntries[fileIdx]->getCount(), (uint32)frame );
 	const char *text = _vqaSubsTextResourceEntries[fileIdx]->getOuttakeTextByFrame((uint32)frame);
 	if (_useUTF8) {
-		_subtitlesData[kSubtitlesPrimary].currentText32 = Common::convertUtf8ToUtf32(text);
+		_subtitlesDataActive[kSubtitlesPrimary].currentText32 = Common::convertUtf8ToUtf32(text);
 	} else {
-		_subtitlesData[kSubtitlesPrimary].currentText = text;
+		_subtitlesDataActive[kSubtitlesPrimary].currentText = text;
 	}
 }
 
@@ -310,11 +422,11 @@ void Subtitles::loadOuttakeSubsText(const Common::String &outtakesName, int fram
  */
 void Subtitles::setGameSubsText(int subsRole, Common::String dbgQuote, bool forceShowWhenNoSpeech) {
 	if (_useUTF8) {
-		_subtitlesData[subsRole].currentText32 = Common::convertUtf8ToUtf32(dbgQuote);
+		_subtitlesDataActive[subsRole].currentText32 = Common::convertUtf8ToUtf32(dbgQuote);
 	} else {
-		_subtitlesData[subsRole].currentText = dbgQuote;
+		_subtitlesDataActive[subsRole].currentText = dbgQuote;
 	}
-	_subtitlesData[subsRole].forceShowWhenNoSpeech = forceShowWhenNoSpeech; // overrides not showing subtitles when no one is speaking
+	_subtitlesDataActive[subsRole].forceShowWhenNoSpeech = forceShowWhenNoSpeech; // overrides not showing subtitles when no one is speaking
 }
 
 /**
@@ -326,10 +438,10 @@ bool Subtitles::show(int subsRole) {
 		return false;
 	}
 
-	if (_subtitlesData[subsRole].isVisible) {
+	if (_subtitlesDataActive[subsRole].isVisible) {
 		return false;
 	} else {
-		_subtitlesData[subsRole].isVisible = true;
+		_subtitlesDataActive[subsRole].isVisible = true;
 		return true;
 	}
 }
@@ -343,10 +455,10 @@ bool Subtitles::hide(int subsRole) {
 		return false;
 	}
 
-	if (!_subtitlesData[subsRole].isVisible) {
+	if (!_subtitlesDataActive[subsRole].isVisible) {
 		return false;
 	} else {
-		_subtitlesData[subsRole].isVisible = false;
+		_subtitlesDataActive[subsRole].isVisible = false;
 		return true;
 	}
 }
@@ -357,58 +469,60 @@ bool Subtitles::hide(int subsRole) {
  */
 bool Subtitles::isVisible(int subsRole) const {
 	return _isSystemActive
-	       && _subtitlesData[subsRole].isVisible;
+	       && _subtitlesDataActive[subsRole].isVisible;
 }
 
 /**
  * Tick method specific for outtakes (VQA videos)
  */
 void Subtitles::tickOuttakes(Graphics::Surface &s) {
-	if (!_isSystemActive || !_vm->isSubtitlesEnabled()) {
-		return;
-	}
-
-	for (int i = 0; i < kNumOfSubtitleRoles; ++i) {
-		if (isNotEmptyCurrentSubsText(i)) {
-			_vm->_subtitles->show(i);
-		} else {
-			_vm->_subtitles->hide(i);
+	if (_isSystemActive && _vm->isSubtitlesEnabled()) {
+		for (int i = 0; i < kNumOfSubtitleRoles; ++i) {
+			if (isNotEmptyCurrentSubsText(i)) {
+				_vm->_subtitles->show(i);
+			} else {
+				_vm->_subtitles->hide(i);
+			}
 		}
-	}
 
-	// keep this as a separate if clause
-	if (!isVisible(kSubtitlesPrimary) && !isVisible(kSubtitlesSecondary)) {
-		return;
+		// keep this as a separate if clause
+		if (isVisible(kSubtitlesPrimary) && isVisible(kSubtitlesSecondary)) {
+			draw(s);
+		}
 	}
 
-	draw(s);
 }
 
 /**
  * Tick method for in-game subtitles -- Not for outtake cutscenes (VQA videos)
  */
 void Subtitles::tick(Graphics::Surface &s) {
-	if (!_isSystemActive || !_vm->isSubtitlesEnabled()) {
-		return;
-	}
+	bool proceedToDraw = false;
+	if (_isSystemActive && _vm->isSubtitlesEnabled()) {
+		if (_subtitlesDataActive[kSubtitlesPrimary].isVisible
+		    && !_subtitlesDataActive[kSubtitlesPrimary].forceShowWhenNoSpeech
+		    && !_vm->_audioSpeech->isPlaying()) {
+			_vm->_subtitles->hide(kSubtitlesPrimary); // TODO might need a better system. Don't call it always.
+		}
 
-	if (_subtitlesData[kSubtitlesPrimary].isVisible
-	    && !_subtitlesData[kSubtitlesPrimary].forceShowWhenNoSpeech
-	    && !_vm->_audioSpeech->isPlaying()) {
-		_vm->_subtitles->hide(kSubtitlesPrimary); // TODO might need a better system. Don't call it always.
+		// keep this as a separate if clause
+		if (isVisible(kSubtitlesPrimary) || isVisible(kSubtitlesSecondary)) {
+			proceedToDraw = true;
+		}
 	}
 
-	// keep this as a separate if clause
-	if (!isVisible(kSubtitlesPrimary) && !isVisible(kSubtitlesSecondary)) {
-		return;
+	if (_vm->getExtraCNotify() == 3) {
+		proceedToDraw = true;
 	}
 
-	draw(s);
+	if (proceedToDraw) {
+		draw(s);
+	}
 }
 
 bool Subtitles::isNotEmptyCurrentSubsText(int subsRole) {
-	if ((_useUTF8 && !_subtitlesData[subsRole].currentText32.empty())
-	    || (!_useUTF8 && !_subtitlesData[subsRole].currentText.empty())) {
+	if ((_useUTF8 && !_subtitlesDataActive[subsRole].currentText32.empty())
+	    || (!_useUTF8 && !_subtitlesDataActive[subsRole].currentText.empty())) {
 		return true;
 	} else {
 		return false;
@@ -421,11 +535,11 @@ void Subtitles::mergeSubtitleQuotes(int actorId, int quoteFirst, int quoteSecond
 	const char *textFirst = _vqaSubsTextResourceEntries[0]->getText((uint32)idFirst);
 	const char *textSecond = _vqaSubsTextResourceEntries[0]->getText((uint32)idSecond);
 	if (_useUTF8) {
-		_subtitlesData[kSubtitlesPrimary].currentText32 = Common::convertUtf8ToUtf32(textFirst);
-		_subtitlesData[kSubtitlesPrimary].currentText32 += " " + Common::convertUtf8ToUtf32(textSecond);
+		_subtitlesDataActive[kSubtitlesPrimary].currentText32 = Common::convertUtf8ToUtf32(textFirst);
+		_subtitlesDataActive[kSubtitlesPrimary].currentText32 += " " + Common::convertUtf8ToUtf32(textSecond);
 	} else {
-		_subtitlesData[kSubtitlesPrimary].currentText = textFirst;
-		_subtitlesData[kSubtitlesPrimary].currentText += " " + Common::String(textSecond);
+		_subtitlesDataActive[kSubtitlesPrimary].currentText = textFirst;
+		_subtitlesDataActive[kSubtitlesPrimary].currentText += " " + Common::String(textSecond);
 	}
 }
 
@@ -433,6 +547,46 @@ void Subtitles::mergeSubtitleQuotes(int actorId, int quoteFirst, int quoteSecond
  * Draw method for drawing the subtitles on the display surface
  */
 void Subtitles::draw(Graphics::Surface &s) {
+	if (_isSystemActive && _vm->getExtraCNotify() == 3) {
+		// Timing fixed for 60Hz by ScummVM team
+		uint32 timeNow = _vm->_time->currentSystem();
+		bool updateTimeout = false;
+		// unsigned difference is intentional
+		if (timeNow - _xcTimeLast > (1000u / 60u)) {
+			updateTimeout = true;
+			_xcTimeLast = timeNow;
+		}
+
+		_vm->_mainFont->drawString(&s, _excTitlStr, 313 - _vm->_mainFont->getStringWidth(_excTitlStr) / 2, 143, s.w, s.format.RGBToColor(240, 232, 192));
+
+		int y = 158;
+		int lineTextWidth;
+		for (int i = 0; i < kxcLineCount; ++i) {
+			if (updateTimeout) {
+				if (_xcLineTimeouts[i] > 0) {
+					--_xcLineTimeouts[i];
+				} else {
+					_xcLineTexts[i] = _xcStrings[_xcStringIndex];
+					_xcLineTimeouts[i] = 63;
+					lineTextWidth = _vm->_mainFont->getStringWidth(_xcLineTexts[i]);
+					_xcLineOffsets[i] = _vm->_rnd.getRandomNumberRng(0, (306 -  lineTextWidth) > 0 ? (306 - lineTextWidth) : 0) + 155;
+
+					_xcStringIndex = (_xcStringIndex + 1) % kxcStringCount;
+				}
+			}
+
+			if (!_xcLineTexts[i].empty()) {
+				int colorIndex = _xcLineTimeouts[i];
+				if (colorIndex >= 32) {
+					colorIndex = 63 - colorIndex;
+				}
+				colorIndex /= 2;
+				_vm->_mainFont->drawString(&s, _xcLineTexts[i], _xcLineOffsets[i], y, s.w, s.format.RGBToColor(kTextColors[colorIndex].r, kTextColors[colorIndex].g, kTextColors[colorIndex].b));
+			}
+			y += 10;
+		}
+	}
+
 	if (!_isSystemActive
 	    || (!isVisible(kSubtitlesPrimary) && !isVisible(kSubtitlesSecondary))
 	    || (!isNotEmptyCurrentSubsText(kSubtitlesPrimary) && !isNotEmptyCurrentSubsText(kSubtitlesSecondary))) {
@@ -444,20 +598,20 @@ void Subtitles::draw(Graphics::Surface &s) {
 			uint linesNum = 0;
 			if (_useUTF8) {
 				// This check is done so that lines won't be re-calculated multiple times for the same text
-				if (_subtitlesData[i].currentText32 != _subtitlesData[i].prevText32) {
-					_subtitlesData[i].lines32.clear();
-					_subtitlesData[i].prevText32 = _subtitlesData[i].currentText32;
-					_font->wordWrapText(_subtitlesData[i].currentText32, kTextMaxWidth, _subtitlesData[i].lines32, 0, Graphics::kWordWrapEvenWidthLines | Graphics::kWordWrapOnExplicitNewLines);
+				if (_subtitlesDataActive[i].currentText32 != _subtitlesDataActive[i].prevText32) {
+					_subtitlesDataActive[i].lines32.clear();
+					_subtitlesDataActive[i].prevText32 = _subtitlesDataActive[i].currentText32;
+					_font->wordWrapText(_subtitlesDataActive[i].currentText32, kTextMaxWidth, _subtitlesDataActive[i].lines32, 0, Graphics::kWordWrapEvenWidthLines | Graphics::kWordWrapOnExplicitNewLines);
 				}
-				linesNum = _subtitlesData[i].lines32.size();
+				linesNum = _subtitlesDataActive[i].lines32.size();
 			} else {
 				// This check is done so that lines won't be re-calculated multiple times for the same text
-				if (_subtitlesData[i].currentText != _subtitlesData[i].prevText) {
-					_subtitlesData[i].lines.clear();
-					_subtitlesData[i].prevText = _subtitlesData[i].currentText;
-					_font->wordWrapText(_subtitlesData[i].currentText, kTextMaxWidth, _subtitlesData[i].lines, 0, Graphics::kWordWrapEvenWidthLines | Graphics::kWordWrapOnExplicitNewLines);
+				if (_subtitlesDataActive[i].currentText != _subtitlesDataActive[i].prevText) {
+					_subtitlesDataActive[i].lines.clear();
+					_subtitlesDataActive[i].prevText = _subtitlesDataActive[i].currentText;
+					_font->wordWrapText(_subtitlesDataActive[i].currentText, kTextMaxWidth, _subtitlesDataActive[i].lines, 0, Graphics::kWordWrapEvenWidthLines | Graphics::kWordWrapOnExplicitNewLines);
 				}
-				linesNum = _subtitlesData[i].lines.size();
+				linesNum = _subtitlesDataActive[i].lines.size();
 			}
 
 			int y = kMarginTop;
@@ -470,15 +624,15 @@ void Subtitles::draw(Graphics::Surface &s) {
 				switch (_subtitlesInfo.fontType) {
 				case Subtitles::kSubtitlesFontTypeInternal:
 					// shadow/outline is part of the font color data
-					_font->drawString(&s, _subtitlesData[i].lines[j], 0, y, s.w, 0, Graphics::kTextAlignCenter);
+					_font->drawString(&s, _subtitlesDataActive[i].lines[j], 0, y, s.w, 0, Graphics::kTextAlignCenter);
 					break;
 				case Subtitles::kSubtitlesFontTypeTTF:
-					_font->drawString(&s, _subtitlesData[i].lines32[j], -1, y    , s.w, s.format.RGBToColor(  0,   0,   0), Graphics::kTextAlignCenter);
-					_font->drawString(&s, _subtitlesData[i].lines32[j],  0, y - 1, s.w, s.format.RGBToColor(  0,   0,   0), Graphics::kTextAlignCenter);
-					_font->drawString(&s, _subtitlesData[i].lines32[j],  1, y    , s.w, s.format.RGBToColor(  0,   0,   0), Graphics::kTextAlignCenter);
-					_font->drawString(&s, _subtitlesData[i].lines32[j],  0, y + 1, s.w, s.format.RGBToColor(  0,   0,   0), Graphics::kTextAlignCenter);
+					_font->drawString(&s, _subtitlesDataActive[i].lines32[j], -1, y    , s.w, s.format.RGBToColor(  0,   0,   0), Graphics::kTextAlignCenter);
+					_font->drawString(&s, _subtitlesDataActive[i].lines32[j],  0, y - 1, s.w, s.format.RGBToColor(  0,   0,   0), Graphics::kTextAlignCenter);
+					_font->drawString(&s, _subtitlesDataActive[i].lines32[j],  1, y    , s.w, s.format.RGBToColor(  0,   0,   0), Graphics::kTextAlignCenter);
+					_font->drawString(&s, _subtitlesDataActive[i].lines32[j],  0, y + 1, s.w, s.format.RGBToColor(  0,   0,   0), Graphics::kTextAlignCenter);
 
-					_font->drawString(&s, _subtitlesData[i].lines32[j],  0, y    , s.w, s.format.RGBToColor(255, 255, 255), Graphics::kTextAlignCenter);
+					_font->drawString(&s, _subtitlesDataActive[i].lines32[j],  0, y    , s.w, s.format.RGBToColor(255, 255, 255), Graphics::kTextAlignCenter);
 					break;
 				}
 			}
@@ -491,18 +645,22 @@ void Subtitles::draw(Graphics::Surface &s) {
  */
 void Subtitles::clear() {
 	for (uint8 i = 0; i < kNumOfSubtitleRoles; ++i) {
-		_subtitlesData[i].isVisible = false;
-		_subtitlesData[i].forceShowWhenNoSpeech = false;
-		_subtitlesData[i].currentText32.clear();
-		_subtitlesData[i].prevText32.clear();
-		_subtitlesData[i].lines32.clear();
+		_subtitlesDataActive[i].isVisible = false;
+		_subtitlesDataActive[i].forceShowWhenNoSpeech = false;
+		_subtitlesDataActive[i].currentText32.clear();
+		_subtitlesDataActive[i].prevText32.clear();
+		_subtitlesDataActive[i].lines32.clear();
 
-		_subtitlesData[i].currentText.clear();
-		_subtitlesData[i].prevText.clear();
-		_subtitlesData[i].lines.clear();
+		_subtitlesDataActive[i].currentText.clear();
+		_subtitlesDataActive[i].prevText.clear();
+		_subtitlesDataActive[i].lines.clear();
 	}
 }
 
+bool Subtitles::isHDCPresent() {
+	return _useHDC;
+}
+
 /**
  * Initialize/reset member vars, close open file descriptors and garbage collect subtitle fonts and text resource
  */
@@ -530,6 +688,7 @@ void Subtitles::reset() {
 	}
 
 	_useUTF8 = false;
+	_useHDC = false;
 }
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/subtitles.h b/engines/bladerunner/subtitles.h
index 9fe3ca4799f..fe21663b302 100644
--- a/engines/bladerunner/subtitles.h
+++ b/engines/bladerunner/subtitles.h
@@ -24,6 +24,7 @@
 
 #include "bladerunner/bladerunner.h"
 
+#include "bladerunner/color.h"
 #include "common/str.h"
 #include "common/ustr.h"
 
@@ -52,9 +53,22 @@ class Subtitles {
 	static const char *SUBTITLES_FILENAME_PREFIXES[kMaxTextResourceEntries];
 	static const char *SUBTITLES_FONT_FILENAME_EXTERNAL;
 	static const char *SUBTITLES_VERSION_TRENAME;
+	static const char *EXTRA_TRENAME;
+
+	static const Color256 kTextColors[];
 
 	static const int  kNumOfSubtitleRoles       = 2;
 
+	static const int  kxcLineCount              = 22;
+	static const int  kxcStringCount            = 14; // 15 - 1
+	Common::String    _xcStrings[kxcStringCount];
+	int               _xcStringIndex;
+
+	Common::String    _xcLineTexts[kxcLineCount];
+	int               _xcLineTimeouts[kxcLineCount];
+	int               _xcLineOffsets[kxcLineCount];
+	uint32            _xcTimeLast;
+
 	BladeRunnerEngine *_vm;
 
 	enum SubtitlesFontType {
@@ -90,6 +104,8 @@ class Subtitles {
 		Common::String currentText;
 		Common::String prevText;
 		Common::Array<Common::String> lines;
+
+		SubtitlesData() : isVisible(false), forceShowWhenNoSpeech(false) { };
 	};
 
 	SubtitlesInfo  _subtitlesInfo;
@@ -97,8 +113,12 @@ class Subtitles {
 
 	Graphics::Font *_font;
 	bool            _useUTF8;
-
-	Common::Array<SubtitlesData> _subtitlesData;
+	bool            _useHDC;
+	Common::Array<Common::String>       _subtitlesEXC;
+	Common::Array<SubtitlesData>        _subtitlesDataActive;
+	Common::String                      _loadAvgStr;
+	Common::String                      _excTitlStr;
+	Common::String                      _goVib;
 
 	bool _gameSubsResourceEntriesFound[kMaxTextResourceEntries]; // false if a TRE file did not open successfully
 	bool _isSystemActive;                                        // true if the whole subtitles subsystem should be disabled (due to missing required resources)
@@ -119,6 +139,10 @@ public:
 	bool show(int subsRole);
 	bool hide(int subsRole);
 	void clear();
+	bool isHDCPresent();
+	void xcReload();
+	Common::String getLoadAvgStr() const { return _loadAvgStr; }
+	const char *getGoVib() const { return _goVib.c_str(); }
 
 	bool isVisible(int subsRole) const;
 	void tick(Graphics::Surface &s);




More information about the Scummvm-git-logs mailing list