mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-05 10:26:40 +00:00
BLADERUNNER: SUBTITLES.MIX pack support
This commit is contained in:
parent
bf46900c7c
commit
6f55071c57
@ -56,7 +56,7 @@ bool MIXArchive::open(const Common::String &filename) {
|
||||
_entries[i].length = _fd.readUint32LE();
|
||||
|
||||
#if BLADERUNNER_DEBUG_CONSOLE
|
||||
debug("%08x %-12d %-12d", _entries[i].id, _entries[i].offset, _entries[i].length);
|
||||
debug("%08x %-12d %-12d", _entries[i].hash, _entries[i].offset, _entries[i].length);
|
||||
#endif
|
||||
|
||||
// Verify that the entries are sorted by id. Note that id is signed.
|
||||
|
@ -505,6 +505,11 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
|
||||
_mainFont->setSpacing(1, 0);
|
||||
|
||||
_subtitles = new Subtitles(this);
|
||||
r = openArchive("SUBTITLES.MIX");
|
||||
if (!r) {
|
||||
_subtitles->setSubtitlesSystemInactive(true); // no subtitles support
|
||||
}
|
||||
_subtitles->init();
|
||||
|
||||
for (int i = 0; i != 43; ++i) {
|
||||
Shape *shape = new Shape(this);
|
||||
@ -678,6 +683,9 @@ void BladeRunnerEngine::shutdown() {
|
||||
_mainFont = nullptr;
|
||||
}
|
||||
|
||||
if(isArchiveOpen("SUBTITLES.MIX")) {
|
||||
closeArchive("SUBTITLES.MIX");
|
||||
}
|
||||
if (_subtitles) {
|
||||
delete _subtitles;
|
||||
_subtitles = nullptr;
|
||||
|
@ -106,7 +106,7 @@ public:
|
||||
#if BLADERUNNER_DEBUG_GAME
|
||||
static const int kArchiveCount = 100;
|
||||
#else
|
||||
static const int kArchiveCount = 10;
|
||||
static const int kArchiveCount = 11; // +1 to original value (10) to accommodate for SUBTITLES.MIX resource
|
||||
#endif
|
||||
static const int kActorCount = 100;
|
||||
static const int kActorVoiceOver = kActorCount - 1;
|
||||
|
@ -37,46 +37,6 @@ Font::~Font() {
|
||||
close();
|
||||
}
|
||||
|
||||
#if BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
// for external FON font file / subtitles support
|
||||
bool Font::openFromStream(Common::ScopedPtr<Common::SeekableReadStream> &stream, int screenWidth, int screenHeight, int spacing1, int spacing2, uint16 color) {
|
||||
reset();
|
||||
|
||||
_screenWidth = screenWidth;
|
||||
_screenHeight = screenHeight;
|
||||
_spacing1 = spacing1;
|
||||
_spacing2 = spacing2;
|
||||
_color = color;
|
||||
|
||||
if (!stream) {
|
||||
return false;
|
||||
}
|
||||
_characterCount = stream->readUint32LE();
|
||||
debug("Font's character count: %d", _characterCount);
|
||||
_maxWidth = stream->readUint32LE();
|
||||
_maxHeight = stream->readUint32LE();
|
||||
_dataSize = stream->readUint32LE();
|
||||
_data = new uint16[_dataSize];
|
||||
if (!_data) {
|
||||
debug("Font::open failed to allocate font buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _characterCount; i++) {
|
||||
_characters[i].x = stream->readUint32LE();
|
||||
_characters[i].y = stream->readUint32LE();
|
||||
_characters[i].width = stream->readUint32LE();
|
||||
_characters[i].height = stream->readUint32LE();
|
||||
_characters[i].dataOffset = stream->readUint32LE();
|
||||
debug("char::%d character x: %d, y: %d, w: %d, h:%d, do: %d", i, _characters[i].x, _characters[i].y, _characters[i].width, _characters[i].height, _characters[i].dataOffset);
|
||||
}
|
||||
for (int i = 0; i < _dataSize; i++) {
|
||||
_data[i] = stream->readUint16LE();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif // BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
|
||||
bool Font::open(const Common::String &fileName, int screenWidth, int screenHeight, int spacing1, int spacing2, uint16 color) {
|
||||
reset();
|
||||
|
||||
|
@ -63,9 +63,6 @@ public:
|
||||
Font(BladeRunnerEngine *vm);
|
||||
~Font();
|
||||
|
||||
#if BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
bool openFromStream(Common::ScopedPtr<Common::SeekableReadStream> &s, int screenWidth, int screenHeight, int spacing1, int spacing2, uint16 color);
|
||||
#endif // BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
bool open(const Common::String &fileName, int screenWidth, int screenHeight, int spacing1, int spacing2, uint16 color);
|
||||
void close();
|
||||
|
||||
|
@ -42,7 +42,7 @@ void OuttakePlayer::play(const Common::String &name, bool noLocalization, int co
|
||||
if (!noLocalization) {
|
||||
resName = resName + "_" + _vm->_languageCode;
|
||||
}
|
||||
|
||||
Common::String resNameNoVQASuffix = resName;
|
||||
resName = resName + ".VQA";
|
||||
|
||||
VQAPlayer vqa_player(_vm, &_vm->_surfaceBack); // surfaceBack is needed here for subtitles rendering properly, original was _surfaceFront here
|
||||
@ -62,7 +62,7 @@ void OuttakePlayer::play(const Common::String &name, bool noLocalization, int co
|
||||
break;
|
||||
|
||||
if (frame >= 0) {
|
||||
_vm->_subtitles->getOuttakeSubsText(resName + ".TRE" , frame);
|
||||
_vm->_subtitles->getOuttakeSubsText(resNameNoVQASuffix, frame);
|
||||
_vm->_subtitles->tickOuttakes(_vm->_surfaceFront);
|
||||
_vm->blitToScreen(_vm->_surfaceFront);
|
||||
}
|
||||
|
@ -39,10 +39,9 @@ namespace BladeRunner {
|
||||
*
|
||||
* TODO in python script (FON from png glyphs) check if you can have semi-transparent pixels to better outline the fringe points of the glyphs - check what happens when MSB is set (transparency) and the rest of the color value is not all 0s.
|
||||
* TODO Catch error for bad symbol in a quote (one that causes the font to crash) - this could happen with the corrupted internal font (TAHOMA18) -> font crash or bad font display / garbage character
|
||||
* TODO add a keyboard shortcut key to enable / disable subtitles?
|
||||
* TODO have a debug script to detect/report problematic lines (too long)
|
||||
*
|
||||
* TODO? put external FON and TRE in a new folder "SUBS" - case insensitive (?)
|
||||
* TODO? add a keyboard shortcut key to enable / disable subtitles?
|
||||
* TODO? Use another escape sequence to progressively display text in a line (like in SCUMM games) <-- this could be very useful with very long lines - might also need an extra manual time or ticks parameter to determine when during the display of the first segment we should switch to the second.
|
||||
* TODO? A more advanced subtitles system
|
||||
* TODO: subtitles could be independent from sound playing (but should disappear when switching between UI screens)
|
||||
@ -66,19 +65,18 @@ namespace BladeRunner {
|
||||
*/
|
||||
|
||||
#if BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
const Common::String Subtitles::SUBTITLES_FONT_FILENAME = "SUBTITLES.FON";
|
||||
const Common::String Subtitles::SUBTITLES_FONT_FILENAME = "SUBTLS_E.FON";
|
||||
#else
|
||||
const Common::String Subtitles::SUBTITLES_FONT_FILENAME = "TAHOMA18.FON";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* All entries need to have the language code appended (after a '_').
|
||||
* The outtakes then need a substring ".VQA"
|
||||
* And all entries should have the suffix extension ".TRE"
|
||||
* And all entries should get the suffix extension ".TRE" (or FUTURE: the last letter in extension "TR*" should also be the language code)
|
||||
* If/When adding new TRE resources here --> Update kMaxTextResourceEntries and also update method getIdxForSubsTreName()
|
||||
*/
|
||||
const Common::String Subtitles::SUBTITLES_FILENAME_PREFIXES[kMaxTextResourceEntries] = {
|
||||
"outQuotes", // 0 // (in-game subtitles, not VQA subtitles)
|
||||
"INGQUO", // 0 // (in-game subtitles, not VQA subtitles)
|
||||
"WSTLGO", // 1
|
||||
"BRLOGO", // 2
|
||||
"INTRO", // 3
|
||||
@ -97,14 +95,13 @@ const Common::String Subtitles::SUBTITLES_FILENAME_PREFIXES[kMaxTextResourceEntr
|
||||
"END04B", // 16
|
||||
"END04C", // 17
|
||||
"END06", // 18
|
||||
"END07", // 19
|
||||
"END01A", // 20
|
||||
"END01B", // 21
|
||||
"END01C", // 22
|
||||
"END01D", // 23
|
||||
"END01E", // 24
|
||||
"END01F", // 25
|
||||
"END03" // 26
|
||||
"END01A", // 19
|
||||
"END01B", // 20
|
||||
"END01C", // 21
|
||||
"END01D", // 22
|
||||
"END01E", // 23
|
||||
"END01F", // 24
|
||||
"END03" // 25
|
||||
};
|
||||
|
||||
/**
|
||||
@ -112,56 +109,83 @@ const Common::String Subtitles::SUBTITLES_FILENAME_PREFIXES[kMaxTextResourceEntr
|
||||
*/
|
||||
Subtitles::Subtitles(BladeRunnerEngine *vm) {
|
||||
_vm = vm;
|
||||
_subtitlesSystemInactive = false;
|
||||
// Initializing and reseting Subtitles
|
||||
for (int i = 0; i < kMaxTextResourceEntries; i++) {
|
||||
_gameSubsFdEntries[i] = nullptr;
|
||||
_vqaSubsTextResourceEntries[i] = nullptr;
|
||||
}
|
||||
#if BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
_gameSubsFontsFd = nullptr;
|
||||
_subsFont = nullptr;
|
||||
#else
|
||||
_subsFont = nullptr;
|
||||
_subsBgFont = nullptr;
|
||||
#endif // BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
reset();
|
||||
// Done - Subtitles Reset
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtitles Destructor
|
||||
*/
|
||||
Subtitles::~Subtitles() {
|
||||
// delete any resource entries in the _vqaSubsTextResourceEntries table
|
||||
// and close any open text resource files
|
||||
for (int i = 0; i != kMaxTextResourceEntries; ++i) {
|
||||
if (_vqaSubsTextResourceEntries[i] != nullptr) {
|
||||
delete _vqaSubsTextResourceEntries[i];
|
||||
_vqaSubsTextResourceEntries[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (_subsFont != nullptr) {
|
||||
_subsFont->close();
|
||||
delete _subsFont;
|
||||
_subsFont = nullptr;
|
||||
}
|
||||
#if !BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
if (_subsBgFont != nullptr) {
|
||||
_subsBgFont->close();
|
||||
delete _subsBgFont;
|
||||
_subsBgFont = nullptr;
|
||||
}
|
||||
#endif // !BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
}
|
||||
|
||||
//
|
||||
// Init is kept separated from constructor to allow not loading up resources if subtitles system is disabled
|
||||
//
|
||||
void Subtitles::init(void) {
|
||||
if (_subtitlesSystemInactive) {
|
||||
return;
|
||||
}
|
||||
//
|
||||
// Loading text resources
|
||||
for (int i = 0; i < kMaxTextResourceEntries; i++) {
|
||||
_gameSubsFdEntries[i] = new Common::File();
|
||||
_vqaSubsTextResourceEntries[i] = new TextResource(_vm);
|
||||
Common::String tmpConstructedFileName = "";
|
||||
tmpConstructedFileName = SUBTITLES_FILENAME_PREFIXES[i] + "_" + _vm->_languageCode;
|
||||
if (i > 0) {
|
||||
tmpConstructedFileName += ".VQA";
|
||||
}
|
||||
tmpConstructedFileName += ".TRE";
|
||||
if (openGameSubs(tmpConstructedFileName) && loadGameSubsText(i)) {
|
||||
_gameSubsFdEntriesFound[i] = true;
|
||||
//tmpConstructedFileName += ".TRE"; // = Common::String::format("%s.TR%s", tmpConstructedFileName.c_str(), _vm->_languageCode.c_str());
|
||||
if ( _vqaSubsTextResourceEntries[i]->open(tmpConstructedFileName)) {
|
||||
_gameSubsResourceEntriesFound[i] = true;
|
||||
}
|
||||
}
|
||||
// Done - Loading text resources
|
||||
//
|
||||
// Initializing/Loading Subtitles' Fonts
|
||||
#if BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
// Open external fonts file (FON file) and load fonts
|
||||
_gameSubsFontsFd = new Common::File();
|
||||
_subsFont = new Font(_vm);
|
||||
if (openSubsFontFile() && loadSubsFont()) {
|
||||
_subsFontsLoaded = true;
|
||||
}
|
||||
#else
|
||||
_subsFont = new Font(_vm);
|
||||
// Use TAHOMA18.FON (is corrupted in places)
|
||||
// 10PT or TAHOMA24 or KIA6PT have all caps glyphs (and also are too big or too small) so they are not appropriate.
|
||||
if (_subsFont ->open(SUBTITLES_FONT_FILENAME, 640, 480, -1, 0, 0)) { // Color setting does not seem to affect the TAHOMA fonts or does it affect the black outline since we give 0 here?
|
||||
#if BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
_subsFont->setSpacing(-1, 0);
|
||||
#else
|
||||
_subsFont->setSpacing(1, 0);
|
||||
_subsFont->setWhiteColor();
|
||||
#endif // BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
_subsFontsLoaded = true;
|
||||
} else {
|
||||
_subsFontsLoaded = false;
|
||||
}
|
||||
#if !BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
_subsBgFont = new Font(_vm);
|
||||
if (_subsFontsLoaded && _subsBgFont ->open(SUBTITLES_FONT_FILENAME, 640, 480, -1, 0, 0)) { // TODO dark color? --- color does not seem to affect the TAHOMA fonts or does it affect the black outline since we give 0 here? ?? - we should give the original color here. What is it for TAHOMA?
|
||||
_subsBgFont ->setSpacing(1, 0);
|
||||
@ -182,51 +206,8 @@ Subtitles::Subtitles(BladeRunnerEngine *vm) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtitles Destructor
|
||||
*/
|
||||
Subtitles::~Subtitles() {
|
||||
// delete any resource entries in the _vqaSubsTextResourceEntries table
|
||||
// and close any open text resource files
|
||||
for (int i = 0; i != kMaxTextResourceEntries; ++i) {
|
||||
if (_vqaSubsTextResourceEntries[i] != nullptr) {
|
||||
delete _vqaSubsTextResourceEntries[i];
|
||||
_vqaSubsTextResourceEntries[i] = nullptr;
|
||||
}
|
||||
if (_gameSubsFdEntries[i] != nullptr) {
|
||||
|
||||
if (isOpenGameSubs(i)) {
|
||||
closeGameSubs(i);
|
||||
}
|
||||
delete _gameSubsFdEntries[i];
|
||||
_gameSubsFdEntries[i] = nullptr;
|
||||
}
|
||||
}
|
||||
#if BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
if (_subsFont != nullptr) {
|
||||
_subsFont->close();
|
||||
delete _subsFont;
|
||||
_subsFont = nullptr;
|
||||
}
|
||||
if (_gameSubsFontsFd != nullptr) {
|
||||
if (isOpenSubsFontFile()) {
|
||||
closeSubsFontFile();
|
||||
}
|
||||
delete _gameSubsFontsFd;
|
||||
_gameSubsFontsFd = nullptr;
|
||||
}
|
||||
#else
|
||||
if (_subsFont != nullptr) {
|
||||
_subsFont->close();
|
||||
delete _subsFont;
|
||||
_subsFont = nullptr;
|
||||
}
|
||||
if (_subsBgFont != nullptr) {
|
||||
_subsBgFont->close();
|
||||
delete _subsBgFont;
|
||||
_subsBgFont = nullptr;
|
||||
}
|
||||
#endif // BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
void Subtitles::setSubtitlesSystemInactive(bool flag) {
|
||||
_subtitlesSystemInactive = flag;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -237,10 +218,6 @@ int Subtitles::getIdxForSubsTreName(const Common::String &treName) const {
|
||||
Common::String tmpConstructedFileName = "";
|
||||
for (int i = 0; i < kMaxTextResourceEntries; ++i) {
|
||||
tmpConstructedFileName = SUBTITLES_FILENAME_PREFIXES[i] + "_" + _vm->_languageCode;
|
||||
if (i > 0) {
|
||||
tmpConstructedFileName += ".VQA";
|
||||
}
|
||||
tmpConstructedFileName += ".TRE";
|
||||
if (tmpConstructedFileName == treName) {
|
||||
return i;
|
||||
}
|
||||
@ -249,178 +226,18 @@ int Subtitles::getIdxForSubsTreName(const Common::String &treName) const {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Open an external subtitles File and store its file descriptor
|
||||
* @return true if successful, false otherwise
|
||||
*/
|
||||
bool Subtitles::openGameSubs(const Common::String &filename) {
|
||||
uint32 gameSubsEntryCount = 0;
|
||||
int subTreIdx = getIdxForSubsTreName(filename);
|
||||
|
||||
if (subTreIdx < 0 || _gameSubsFdEntries[subTreIdx] == nullptr) {
|
||||
debug("Subtitles::open(): Could not open %s", filename.c_str());
|
||||
return false;
|
||||
}
|
||||
// debug("Now opening subs file: %s", filename.c_str());
|
||||
|
||||
if (!_gameSubsFdEntries[subTreIdx]->open(filename)) {
|
||||
debug("Subtitles::open(): Could not open %s", filename.c_str());
|
||||
return false;
|
||||
}
|
||||
gameSubsEntryCount = _gameSubsFdEntries[subTreIdx]->readUint32LE();
|
||||
|
||||
if (_gameSubsFdEntries[subTreIdx]->err()) {
|
||||
error("Subtitles::open(): Error reading entries in %s", filename.c_str());
|
||||
_gameSubsFdEntries[subTreIdx]->close();
|
||||
return false;
|
||||
}
|
||||
debug("Subtitles::open: Opened in-game external subs file %s with %d entries", filename.c_str(), gameSubsEntryCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close an open external subtitles File
|
||||
*/
|
||||
void Subtitles::closeGameSubs(int subTreIdx) {
|
||||
if (subTreIdx < 0 || _gameSubsFdEntries[subTreIdx] == nullptr) {
|
||||
debug("Subtitles::close(): Could not close file with Idx %d", subTreIdx);
|
||||
return;
|
||||
}
|
||||
return _gameSubsFdEntries[subTreIdx]->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether an external subtitles File is open
|
||||
*/
|
||||
bool Subtitles::isOpenGameSubs(int subTreIdx) const {
|
||||
if (subTreIdx < 0 || _gameSubsFdEntries[subTreIdx] == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return _gameSubsFdEntries[subTreIdx]->isOpen();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the game subs as a TRE resource and store them in a specific entry in _vqaSubsTextResourceEntries table
|
||||
*/
|
||||
bool Subtitles::loadGameSubsText(int subTreIdx) {
|
||||
bool r = false;
|
||||
Common::SeekableReadStream *stream = createReadStreamForGameSubs(subTreIdx);
|
||||
if (stream != nullptr) {
|
||||
Common::ScopedPtr<Common::SeekableReadStream> s(stream);
|
||||
r = _vqaSubsTextResourceEntries[subTreIdx]->openFromStream(s);
|
||||
if (!r) {
|
||||
error("Failed to load subtitle text");
|
||||
}
|
||||
closeGameSubs(subTreIdx);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auxiliary method for loadGameSubsText
|
||||
* @return nullptr if failure, otherwise return a pointer to a new SafeSeekableSubReadStream
|
||||
*/
|
||||
Common::SeekableReadStream *Subtitles::createReadStreamForGameSubs(int subTreIdx) {
|
||||
if (subTreIdx < 0 || _gameSubsFdEntries[subTreIdx] == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!isOpenGameSubs(subTreIdx)) {
|
||||
return nullptr;
|
||||
}
|
||||
return new Common::SafeSeekableSubReadStream(_gameSubsFdEntries[subTreIdx], 0, _gameSubsFdEntries[subTreIdx]->size(), DisposeAfterUse::YES); // TODO changed to YES from NO is this ok?
|
||||
}
|
||||
|
||||
#if BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
//
|
||||
// EXTERN FONT MANAGEMENT - Font Open/ Create Read Stream / Load / Close methods
|
||||
//
|
||||
|
||||
/**
|
||||
* @return true if successfully opened the external fonts (FON) file, false otherwise
|
||||
*/
|
||||
bool Subtitles::openSubsFontFile() {
|
||||
uint32 subFontsTableEntryCount = 0;
|
||||
// debug("Now opening subs file: %s", SUBTITLES_FONT_FILENAME.c_str());
|
||||
|
||||
if (_gameSubsFontsFd == nullptr || !_gameSubsFontsFd->open(SUBTITLES_FONT_FILENAME)) {
|
||||
debug("Subtitles FONT::open(): Could not open %s", SUBTITLES_FONT_FILENAME.c_str());
|
||||
return false;
|
||||
}
|
||||
subFontsTableEntryCount = _gameSubsFontsFd->readUint32LE(); // only for debug report purposes
|
||||
|
||||
if (_gameSubsFontsFd->err()) {
|
||||
error("Subtitles FONT::open(): Error reading entries in %s", SUBTITLES_FONT_FILENAME.c_str());
|
||||
_gameSubsFontsFd->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
debug("Subtitles FONT::open: Opened in-game external subs FONT file %s with %d entries", SUBTITLES_FONT_FILENAME.c_str(), subFontsTableEntryCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the external Fonts (FON) file
|
||||
*/
|
||||
void Subtitles::closeSubsFontFile() {
|
||||
if (_gameSubsFontsFd != nullptr) {
|
||||
_gameSubsFontsFd->close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the external fonts (FON) file has been opened
|
||||
*/
|
||||
bool Subtitles::isOpenSubsFontFile() const {
|
||||
return _gameSubsFontsFd != nullptr && _gameSubsFontsFd->isOpen();
|
||||
}
|
||||
|
||||
/**
|
||||
* Auxiliary function to create a read stream fro the external fonts file
|
||||
* @return a pointer to the stream if successful, or nullptr otherwise
|
||||
*/
|
||||
Common::SeekableReadStream *Subtitles::createReadStreamForSubFonts() {
|
||||
if (_gameSubsFontsFd == nullptr || !isOpenSubsFontFile()) {
|
||||
return nullptr;
|
||||
}
|
||||
return new Common::SafeSeekableSubReadStream(_gameSubsFontsFd, 0, _gameSubsFontsFd->size(), DisposeAfterUse::YES); // TODO changed to YES from NO is this ok?
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the font from the external font file
|
||||
* @return true if successful, or false otherwise
|
||||
*/
|
||||
bool Subtitles::loadSubsFont() {
|
||||
bool r = false;
|
||||
Common::SeekableReadStream *stream = createReadStreamForSubFonts();
|
||||
if (stream != nullptr) {
|
||||
Common::ScopedPtr<Common::SeekableReadStream> s(stream);
|
||||
r = _subsFont->openFromStream(s, 640, 480, -1, 0, 0);
|
||||
|
||||
if (!r) {
|
||||
error("Failed to load subtitle FONT");
|
||||
} else {
|
||||
_subsFont->setSpacing(-1, 0);
|
||||
}
|
||||
//_subsFont->setSpacing(0, 0);
|
||||
closeSubsFontFile();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
//
|
||||
// END OF EXTERNAL FONT MANAGEMENT
|
||||
//
|
||||
#endif // BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
|
||||
/**
|
||||
* Get the active subtitle text by searching with actor ID and speech ID
|
||||
* Use this method for in-game dialogue - Not dialogue during a VQA cutscene
|
||||
* Returns the dialogue quote, but also sets the private _currentSubtitleTextFull member
|
||||
*/
|
||||
const char *Subtitles::getInGameSubsText(int actorId, int speech_id) {
|
||||
if (_subtitlesSystemInactive) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int32 id = 10000 * actorId + speech_id;
|
||||
if (!_gameSubsFdEntriesFound[0]) {
|
||||
if (!_gameSubsResourceEntriesFound[0]) {
|
||||
if (_currentSubtitleTextFull != "") {
|
||||
_currentSubtitleTextFull = "";
|
||||
_subtitlesQuoteChanged = true;
|
||||
@ -439,8 +256,12 @@ const char *Subtitles::getInGameSubsText(int actorId, int speech_id) {
|
||||
* Returns the dialogue quote, but also sets the private _currentSubtitleTextFull member
|
||||
*/
|
||||
const char *Subtitles::getOuttakeSubsText(const Common::String &outtakesName, int frame) {
|
||||
if (_subtitlesSystemInactive) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int fileIdx = getIdxForSubsTreName(outtakesName);
|
||||
if (fileIdx == -1 || !_gameSubsFdEntriesFound[fileIdx]) {
|
||||
if (fileIdx == -1 || !_gameSubsResourceEntriesFound[fileIdx]) {
|
||||
if (_currentSubtitleTextFull != "") {
|
||||
_currentSubtitleTextFull = "";
|
||||
_subtitlesQuoteChanged = true;
|
||||
@ -476,6 +297,9 @@ void Subtitles::setGameSubsText(Common::String dbgQuote) {
|
||||
* @return true if the member was set now, false if the member was already set
|
||||
*/
|
||||
bool Subtitles::show() {
|
||||
if (_subtitlesSystemInactive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_isVisible) {
|
||||
return false;
|
||||
@ -489,6 +313,10 @@ bool Subtitles::show() {
|
||||
* @return true if the member was cleared, false if it was already clear.
|
||||
*/
|
||||
bool Subtitles::hide() {
|
||||
if (_subtitlesSystemInactive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_isVisible) {
|
||||
return false;
|
||||
}
|
||||
@ -502,7 +330,7 @@ bool Subtitles::hide() {
|
||||
* @return the value of the _isVisible member boolean var
|
||||
*/
|
||||
bool Subtitles::isVisible() const {
|
||||
return _isVisible;
|
||||
return _subtitlesSystemInactive || _isVisible;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -514,7 +342,7 @@ void Subtitles::tickOuttakes(Graphics::Surface &s) {
|
||||
} else {
|
||||
_vm->_subtitles->show();
|
||||
}
|
||||
if (!_vm->isSubtitlesEnabled()) {
|
||||
if (_subtitlesSystemInactive || !_vm->isSubtitlesEnabled()) {
|
||||
return;
|
||||
}
|
||||
if (!_isVisible) { // keep it as a separate if
|
||||
@ -530,7 +358,7 @@ void Subtitles::tick(Graphics::Surface &s) {
|
||||
if (!_vm->_audioSpeech->isPlaying()) {
|
||||
_vm->_subtitles->hide(); // TODO might need a better system. Don't call it always.
|
||||
}
|
||||
if (!_vm->isSubtitlesEnabled()) {
|
||||
if (_subtitlesSystemInactive || !_vm->isSubtitlesEnabled()) {
|
||||
return;
|
||||
}
|
||||
if (!_isVisible) { // keep it as a separate if
|
||||
@ -726,37 +554,15 @@ void Subtitles::reset() {
|
||||
delete _vqaSubsTextResourceEntries[i];
|
||||
_vqaSubsTextResourceEntries[i] = nullptr;
|
||||
}
|
||||
_gameSubsFdEntriesFound[i] = false;
|
||||
|
||||
if (_gameSubsFdEntries[i] != nullptr) {
|
||||
if (isOpenGameSubs(i)) {
|
||||
closeGameSubs(i);
|
||||
}
|
||||
delete _gameSubsFdEntries[i];
|
||||
_gameSubsFdEntries[i] = nullptr;
|
||||
}
|
||||
_gameSubsResourceEntriesFound[i] = false;
|
||||
}
|
||||
|
||||
#if BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
if (_subsFont != nullptr) {
|
||||
_subsFont->close();
|
||||
delete _subsFont;
|
||||
_subsFont = nullptr;
|
||||
}
|
||||
|
||||
if (_gameSubsFontsFd != nullptr) {
|
||||
if (isOpenSubsFontFile()) {
|
||||
closeSubsFontFile();
|
||||
}
|
||||
delete _gameSubsFontsFd;
|
||||
_gameSubsFontsFd = nullptr;
|
||||
}
|
||||
#else
|
||||
if (_subsFont != nullptr) {
|
||||
if (_subsFont != nullptr) {
|
||||
_subsFont->close();
|
||||
delete _subsFont;
|
||||
_subsFont = nullptr;
|
||||
}
|
||||
#if !BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
if (_subsBgFont != nullptr) {
|
||||
_subsBgFont->close();
|
||||
delete _subsBgFont;
|
||||
|
@ -48,7 +48,7 @@ class Subtitles {
|
||||
// TODO Or just support the current _vm->_languageCode ? [current implementation]
|
||||
static const int kMaxNumOfSubtitlesLines = 3;
|
||||
static const int kMaxWidthPerLineToAutoSplitThresholdPx = 610;
|
||||
static const int kMaxTextResourceEntries = 1 + 26; // Support in-game subs (1) and all possible VQAs (26) with spoken dialogue!
|
||||
static const int kMaxTextResourceEntries = 1 + 25; // Support in-game subs (1) and all possible VQAs (26) with spoken dialogue!
|
||||
static const Common::String SUBTITLES_FILENAME_PREFIXES[kMaxTextResourceEntries];
|
||||
static const Common::String SUBTITLES_FONT_FILENAME;
|
||||
|
||||
@ -70,17 +70,16 @@ class Subtitles {
|
||||
int _currentSubtitleLines;
|
||||
bool _subtitlesQuoteChanged;
|
||||
|
||||
Common::File *_gameSubsFdEntries[kMaxTextResourceEntries]; // an array of pointers to TRE FILEs
|
||||
bool _gameSubsFdEntriesFound[kMaxTextResourceEntries]; // false if a TRE file did not open successfully
|
||||
bool _gameSubsResourceEntriesFound[kMaxTextResourceEntries]; // false if a TRE file did not open successfully
|
||||
bool _subsFontsLoaded; // false if external fonts did not load, or internal fonts (fore and background) did not load
|
||||
#if BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
Common::File *_gameSubsFontsFd; // the file for the external FONT for subtitles
|
||||
#endif // BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
bool _subtitlesSystemInactive; // true if the whole subtitles subsystem should be disabled (due to missing required resources)
|
||||
|
||||
public:
|
||||
Subtitles(BladeRunnerEngine *vm);
|
||||
~Subtitles();
|
||||
|
||||
void init();
|
||||
void setSubtitlesSystemInactive(bool flag); // disable subtitles system (possibly due to missing important resources like SUBTITLES.MIX file)
|
||||
const char *getInGameSubsText(int actorId, int speech_id) ; // get the text for actorId, quoteId (in-game subs)
|
||||
const char *getOuttakeSubsText(const Common::String &outtakesName, int frame); // get the text for this frame if any
|
||||
|
||||
@ -92,24 +91,6 @@ public:
|
||||
void tickOuttakes(Graphics::Surface &s);
|
||||
|
||||
private:
|
||||
Common::SeekableReadStream *createReadStreamForGameSubs(int subTreIdx);
|
||||
|
||||
bool openGameSubs(const Common::String &filename);
|
||||
void closeGameSubs(int subTreIdx);
|
||||
bool isOpenGameSubs(int subTreIdx) const;
|
||||
|
||||
bool loadGameSubsText(int subTreIdx); // populate a GAME SUBS TextResource with subtitles
|
||||
//
|
||||
//
|
||||
#if BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
Common::SeekableReadStream *createReadStreamForSubFonts();
|
||||
bool openSubsFontFile();
|
||||
void closeSubsFontFile();
|
||||
bool isOpenSubsFontFile() const; //
|
||||
bool loadSubsFont(); // create a the font object from a FON file (external)
|
||||
#endif // BLADERUNNER_SUBTITLES_EXTERNAL_FONT
|
||||
|
||||
|
||||
void draw(Graphics::Surface &s);
|
||||
// bool showAt(int x, int y); // TODO maybe future use (?)
|
||||
void calculatePosition();
|
||||
|
@ -43,48 +43,6 @@ TextResource::~TextResource() {
|
||||
delete[] _strings;
|
||||
}
|
||||
|
||||
// for TRE subtitles support
|
||||
bool TextResource::openFromStream(Common::ScopedPtr<Common::SeekableReadStream> &s) {
|
||||
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_count = s->readUint32LE();
|
||||
|
||||
_ids = new uint32[_count];
|
||||
_offsets = new uint32[_count + 1];
|
||||
|
||||
for (uint32 i = 0; i != _count; ++i) {
|
||||
_ids[i] = s->readUint32LE();
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i != _count + 1; ++i) {
|
||||
_offsets[i] = s->readUint32LE();
|
||||
}
|
||||
|
||||
uint32 stringsStart = s->pos() - 4;
|
||||
|
||||
for (uint32 i = 0; i != _count + 1; ++i) {
|
||||
_offsets[i] -= stringsStart;
|
||||
}
|
||||
|
||||
uint32 remain = s->size() - s->pos();
|
||||
_strings = new char[remain];
|
||||
|
||||
assert(remain >= _offsets[_count]);
|
||||
|
||||
s->read(_strings, remain);
|
||||
#if BLADERUNNER_DEBUG_CONSOLE
|
||||
// debug("\nRESOURCE:: from Stream\n----------------");
|
||||
// for (uint32 i = 0; i != (uint32)_count; ++i) {
|
||||
// debug("%3d: %s", _ids[i], getText(_ids[i]));
|
||||
// }
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TextResource::open(const Common::String &name) {
|
||||
assert(name.size() <= 8);
|
||||
|
||||
|
@ -45,7 +45,6 @@ public:
|
||||
~TextResource();
|
||||
|
||||
bool open(const Common::String &name);
|
||||
bool openFromStream(Common::ScopedPtr<Common::SeekableReadStream> &s);
|
||||
|
||||
const char *getText(uint32 id) const;
|
||||
const char *getOuttakeTextByFrame(uint32 frame) const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user