From eff78c442474185ecb1bde59bfc54c276178c480 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 4 Nov 2014 22:01:21 +0100 Subject: SCI: fix Japanese Space Quest 4 (intro + buttons) At least SQ4 uses #j text prefix as signal for the interpreter to not use the PC9801 hires font, but to use the internal low res font instead --- engines/sci/engine/kgraphics.cpp | 33 ++++++++++++---- engines/sci/engine/state.cpp | 84 ++++++++++++++++++++++------------------ 2 files changed, 72 insertions(+), 45 deletions(-) (limited to 'engines/sci/engine') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index c2089bcd4d..ee2249bd9d 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -354,13 +354,16 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) { } textWidth = dest[3].toUint16(); textHeight = dest[2].toUint16(); + + uint16 languageSplitter = 0; + Common::String splitText = g_sci->strSplitLanguage(text.c_str(), &languageSplitter, sep); #ifdef ENABLE_SCI32 if (g_sci->_gfxText32) - g_sci->_gfxText32->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight); + g_sci->_gfxText32->kernelTextSize(splitText.c_str(), font_nr, maxwidth, &textWidth, &textHeight); else #endif - g_sci->_gfxText16->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight); + g_sci->_gfxText16->kernelTextSize(splitText.c_str(), languageSplitter, font_nr, maxwidth, &textWidth, &textHeight); // One of the game texts in LB2 German contains loads of spaces in // its end. We trim the text here, otherwise the graphics code will @@ -376,7 +379,7 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) { // Copy over the trimmed string... s->_segMan->strcpy(argv[1], text.c_str()); // ...and recalculate bounding box dimensions - g_sci->_gfxText16->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight); + g_sci->_gfxText16->kernelTextSize(splitText.c_str(), languageSplitter, font_nr, maxwidth, &textWidth, &textHeight); } } @@ -818,16 +821,29 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { if (!textReference.isNull()) text = s->_segMan->getString(textReference); + uint16 languageSplitter = 0; + Common::String splitText; + + switch (type) { + case SCI_CONTROLS_TYPE_BUTTON: + case SCI_CONTROLS_TYPE_TEXTEDIT: + splitText = g_sci->strSplitLanguage(text.c_str(), &languageSplitter, NULL); + break; + case SCI_CONTROLS_TYPE_TEXT: + splitText = g_sci->strSplitLanguage(text.c_str(), &languageSplitter); + break; + } + switch (type) { case SCI_CONTROLS_TYPE_BUTTON: debugC(kDebugLevelGraphics, "drawing button %04x:%04x to %d,%d", PRINT_REG(controlObject), x, y); - g_sci->_gfxControls16->kernelDrawButton(rect, controlObject, g_sci->strSplit(text.c_str(), NULL).c_str(), fontId, style, hilite); + g_sci->_gfxControls16->kernelDrawButton(rect, controlObject, splitText.c_str(), languageSplitter, fontId, style, hilite); return; case SCI_CONTROLS_TYPE_TEXT: alignment = readSelectorValue(s->_segMan, controlObject, SELECTOR(mode)); debugC(kDebugLevelGraphics, "drawing text %04x:%04x ('%s') to %d,%d, mode=%d", PRINT_REG(controlObject), text.c_str(), x, y, alignment); - g_sci->_gfxControls16->kernelDrawText(rect, controlObject, g_sci->strSplit(text.c_str()).c_str(), fontId, alignment, style, hilite); + g_sci->_gfxControls16->kernelDrawText(rect, controlObject, splitText.c_str(), languageSplitter, fontId, alignment, style, hilite); s->r_acc = g_sci->_gfxText16->allocAndFillReferenceRectArray(); return; @@ -841,7 +857,7 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { writeSelectorValue(s->_segMan, controlObject, SELECTOR(cursor), cursorPos); } debugC(kDebugLevelGraphics, "drawing edit control %04x:%04x (text %04x:%04x, '%s') to %d,%d", PRINT_REG(controlObject), PRINT_REG(textReference), text.c_str(), x, y); - g_sci->_gfxControls16->kernelDrawTextEdit(rect, controlObject, g_sci->strSplit(text.c_str(), NULL).c_str(), fontId, mode, style, cursorPos, maxChars, hilite); + g_sci->_gfxControls16->kernelDrawTextEdit(rect, controlObject, splitText.c_str(), languageSplitter, fontId, mode, style, cursorPos, maxChars, hilite); return; case SCI_CONTROLS_TYPE_ICON: @@ -1165,8 +1181,11 @@ reg_t kDisplay(EngineState *s, int argc, reg_t *argv) { argc--; argc--; argv++; argv++; text = g_sci->getKernel()->lookupText(textp, index); } + + uint16 languageSplitter = 0; + Common::String splitText = g_sci->strSplitLanguage(text.c_str(), &languageSplitter); - return g_sci->_gfxPaint16->kernelDisplay(g_sci->strSplit(text.c_str()).c_str(), argc, argv); + return g_sci->_gfxPaint16->kernelDisplay(splitText.c_str(), languageSplitter, argc, argv); } reg_t kSetVideoMode(EngineState *s, int argc, reg_t *argv) { diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 1b7fa7699e..c07dc925e0 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -203,37 +203,45 @@ static kLanguage charToLanguage(const char c) { } } -Common::String SciEngine::getSciLanguageString(const Common::String &str, kLanguage lang, kLanguage *lang2) const { - kLanguage secondLang = K_LANG_NONE; - - const char *seeker = str.c_str(); - while (*seeker) { - if ((*seeker == '%') || (*seeker == '#')) { - secondLang = charToLanguage(*(seeker + 1)); - - if (secondLang != K_LANG_NONE) +Common::String SciEngine::getSciLanguageString(const Common::String &str, kLanguage requestedLanguage, kLanguage *secondaryLanguage, uint16 *languageSplitter) const { + kLanguage foundLanguage = K_LANG_NONE; + const byte *textPtr = (byte *)str.c_str(); + byte curChar = 0; + byte curChar2 = 0; + + while (1) { + curChar = *textPtr; + if (!curChar) + break; + + if ((curChar == '%') || (curChar == '#')) { + curChar2 = *(textPtr + 1); + foundLanguage = charToLanguage(curChar2); + + if (foundLanguage != K_LANG_NONE) { + // Return language splitter + if (languageSplitter) + *languageSplitter = curChar | ( curChar2 << 8 ); + // Return the secondary language found in the string + if (secondaryLanguage) + *secondaryLanguage = foundLanguage; break; + } } - - ++seeker; + textPtr++; } - // Return the secondary language found in the string - if (lang2) - *lang2 = secondLang; - - if (secondLang == lang) { - if (*(++seeker) == 'J') { + if (foundLanguage == requestedLanguage) { + if (curChar2 == 'J') { // Japanese including Kanji, displayed with system font // Convert half-width characters to full-width equivalents Common::String fullWidth; - byte curChar, curChar2; uint16 mappedChar; - seeker++; + textPtr += 2; // skip over language splitter while (1) { - curChar = *(seeker); + curChar = *textPtr; switch (curChar) { case 0: // Terminator NUL @@ -243,7 +251,7 @@ Common::String SciEngine::getSciLanguageString(const Common::String &str, kLangu // inside GetLongest() (text16). We do it here, because it's much cleaner and // we have to process the text here anyway. // Occurs for example in Police Quest 2 intro - curChar2 = *(seeker + 1); + curChar2 = *(textPtr + 1); switch (curChar2) { case 'n': case 'N': @@ -251,12 +259,12 @@ Common::String SciEngine::getSciLanguageString(const Common::String &str, kLangu case 'R': fullWidth += ' '; fullWidth += 0x0D; // CR - seeker += 2; + textPtr += 2; continue; } } - seeker++; + textPtr++; mappedChar = s_halfWidthSJISMap[curChar]; if (mappedChar) { @@ -264,7 +272,7 @@ Common::String SciEngine::getSciLanguageString(const Common::String &str, kLangu fullWidth += mappedChar & 0xFF; } else { // Copy double-byte character - curChar2 = *(seeker++); + curChar2 = *(textPtr++); if (!curChar) { error("SJIS character %02X is missing second byte", curChar); break; @@ -275,14 +283,14 @@ Common::String SciEngine::getSciLanguageString(const Common::String &str, kLangu } } else { - return Common::String(seeker + 1); + return Common::String((const char *)(textPtr + 2)); } } - if (*seeker) - return Common::String(str.c_str(), seeker - str.c_str()); - else - return str; + if (curChar) + return Common::String(str.c_str(), (const char *)textPtr - str.c_str()); + + return str; } kLanguage SciEngine::getSciLanguage() { @@ -341,25 +349,25 @@ void SciEngine::setSciLanguage() { setSciLanguage(getSciLanguage()); } -Common::String SciEngine::strSplit(const char *str, const char *sep) { - kLanguage lang = getSciLanguage(); - kLanguage subLang = K_LANG_NONE; +Common::String SciEngine::strSplitLanguage(const char *str, uint16 *languageSplitter, const char *sep) { + kLanguage activeLanguage = getSciLanguage(); + kLanguage subtitleLanguage = K_LANG_NONE; if (SELECTOR(subtitleLang) != -1) - subLang = (kLanguage)readSelectorValue(_gamestate->_segMan, _gameObjectAddress, SELECTOR(subtitleLang)); + subtitleLanguage = (kLanguage)readSelectorValue(_gamestate->_segMan, _gameObjectAddress, SELECTOR(subtitleLang)); - kLanguage secondLang; - Common::String retval = getSciLanguageString(str, lang, &secondLang); + kLanguage foundLanguage; + Common::String retval = getSciLanguageString(str, activeLanguage, &foundLanguage, languageSplitter); // Don't add subtitle when separator is not set, subtitle language is not set, or // string contains only one language - if ((sep == NULL) || (subLang == K_LANG_NONE) || (secondLang == K_LANG_NONE)) + if ((sep == NULL) || (subtitleLanguage == K_LANG_NONE) || (foundLanguage == K_LANG_NONE)) return retval; // Add subtitle, unless the subtitle language doesn't match the languages in the string - if ((subLang == K_LANG_ENGLISH) || (subLang == secondLang)) { + if ((subtitleLanguage == K_LANG_ENGLISH) || (subtitleLanguage == foundLanguage)) { retval += sep; - retval += getSciLanguageString(str, subLang); + retval += getSciLanguageString(str, subtitleLanguage); } return retval; -- cgit v1.2.3