From dd9e5693253784c81fb509a208ca15943a3aadc8 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Mon, 10 Aug 2009 18:37:47 +0000 Subject: SCI: Improved multilanguage support for SCI1 and SCI1.1. svn-id: r43217 --- engines/sci/engine/game.cpp | 3 +++ engines/sci/engine/kernel.cpp | 2 +- engines/sci/engine/kernel.h | 1 + engines/sci/engine/kstring.cpp | 17 +++++++++++++ engines/sci/engine/message.cpp | 18 +++++++------ engines/sci/engine/state.cpp | 57 ++++++++++++++++++++++++++++++++++++++---- engines/sci/engine/state.h | 1 + 7 files changed, 86 insertions(+), 13 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index 0a74ac32e4..fa64957bec 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -497,6 +497,9 @@ int game_init(EngineState *s) { if (s->sfx_init_flags & SFX_STATE_FLAG_NOSOUND) game_init_sound(s, 0); + // Load game language into printLang property of game object + s->getLanguage(); + return 0; } diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 4133f4cb3b..2ccd88b709 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -320,6 +320,7 @@ SciKernelFunction kfunct_mappers[] = { /*(?)*/ DEFUN("Lock", kLock, "iii*"), /*(?)*/ DEFUN("Palette", kPalette, "i.*"), /*(?)*/ DEFUN("IsItSkip", kIsItSkip, "iiiii"), + /*7b*/ DEFUN("StrSplit", kStrSplit, "rrZr"), // Non-experimental Functions without a fixed ID DEFUN("CosMult", kTimesCos, "ii"), @@ -345,7 +346,6 @@ SciKernelFunction kfunct_mappers[] = { DEFUN("MemorySegment", kStub, ".*"), DEFUN("ListOps", kStub, ".*"), DEFUN("ATan", kStub, ".*"), - DEFUN("StrSplit", kStub, ".*"), DEFUN("MergePoly", kStub, ".*"), DEFUN("AssertPalette", kStub, ".*"), DEFUN("TextColors", kStub, ".*"), diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 15f7c9fcf3..83b43542d4 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -540,6 +540,7 @@ reg_t kResCheck(EngineState *s, int funct_nr, int argc, reg_t *argv); reg_t kSetQuitStr(EngineState *s, int funct_nr, int argc, reg_t *argv); reg_t kShowMovie(EngineState *s, int funct_nr, int argc, reg_t *argv); reg_t kSetVideoMode(EngineState *s, int funct_nr, int argc, reg_t *argv); +reg_t kStrSplit(EngineState *s, int funct_nr, int argc, reg_t *argv); reg_t k_Unknown(EngineState *s, int funct_nr, int argc, reg_t *argv); // The Unknown/Unnamed kernel function diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index b6bb404d5b..6e5a19bba9 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -812,4 +812,21 @@ reg_t kSetQuitStr(EngineState *s, int funct_nr, int argc, reg_t *argv) { return s->r_acc; } +reg_t kStrSplit(EngineState *s, int funct_nr, int argc, reg_t *argv) { + const char *format = kernel_dereference_char_pointer(s, argv[1], 0); + const char *sep = !argv[2].isNull() ? kernel_dereference_char_pointer(s, argv[2], 0) : NULL; + Common::String str = s->strSplit(format, sep); + + // Make sure target buffer is large enough + char *buf = kernel_dereference_char_pointer(s, argv[0], str.size() + 1); + + if (buf) { + strcpy(buf, str.c_str()); + return argv[0]; + } else { + warning("StrSplit: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(argv[0]), str.size() + 1, str.c_str()); + return NULL_REG; + } +} + } // End of namespace Sci diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp index c019f7a3bc..a55d692afe 100644 --- a/engines/sci/engine/message.cpp +++ b/engines/sci/engine/message.cpp @@ -33,7 +33,7 @@ MessageTuple MessageState::getTuple() { t.noun = *(_engineCursor.index_record + 0); t.verb = *(_engineCursor.index_record + 1); - if (_version == 2101) { + if (_version == 2) { t.cond = 0; t.seq = 1; } else { @@ -47,7 +47,7 @@ MessageTuple MessageState::getTuple() { MessageTuple MessageState::getRefTuple() { MessageTuple t; - if (_version == 2101) { + if (_version == 2) { t.noun = 0; t.verb = 0; t.cond = 0; @@ -68,7 +68,7 @@ void MessageState::initCursor() { } void MessageState::advanceCursor(bool increaseSeq) { - _engineCursor.index_record += ((_version == 2101) ? 4 : 11); + _engineCursor.index_record += ((_version == 2) ? 4 : 11); _engineCursor.index++; if (increaseSeq) @@ -142,7 +142,7 @@ int MessageState::getMessage() { } int MessageState::getTalker() { - return (_version == 2101) ? -1 : *(_engineCursor.index_record + 4); + return (_version == 2) ? -1 : *(_engineCursor.index_record + 4); } MessageTuple &MessageState::getLastTuple() { @@ -154,7 +154,7 @@ int MessageState::getLastModule() { } Common::String MessageState::getText() { - char *str = (char *)_currentResource->data + READ_LE_UINT16(_engineCursor.index_record + ((_version == 2101) ? 2 : 5)); + char *str = (char *)_currentResource->data + READ_LE_UINT16(_engineCursor.index_record + ((_version == 2) ? 2 : 5)); Common::String strippedStr; Common::String skippedSubstr; @@ -215,7 +215,7 @@ void MessageState::gotoNext() { } int MessageState::getLength() { - int offset = READ_LE_UINT16(_engineCursor.index_record + ((_version == 2101) ? 2 : 5)); + int offset = READ_LE_UINT16(_engineCursor.index_record + ((_version == 2) ? 2 : 5)); char *stringptr = (char *)_currentResource->data + offset; return strlen(stringptr); } @@ -244,8 +244,12 @@ int MessageState::loadRes(ResourceManager *resmgr, int module, bool lock) { _locked = lock; _version = READ_LE_UINT16(_currentResource->data); + debug(5, "Message: reading resource %d.msg, version %d.%03d", _module, _version / 1000, _version % 1000); - int offs = (_version == 2101) ? 0 : 4; + // We assume for now that storing the major version is sufficient + _version /= 1000; + + int offs = (_version == 2) ? 0 : 4; _recordCount = READ_LE_UINT16(_currentResource->data + 4 + offs); _indexRecords = _currentResource->data + 6 + offs; diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 38320c29cc..405c9ec66f 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -172,15 +172,62 @@ Common::String EngineState::getLanguageString(const char *str, kLanguage lang) c return Common::String(str); } +kLanguage EngineState::getLanguage() { + kLanguage lang = K_LANG_ENGLISH; + + if (((SciEngine*)g_engine)->getKernel()->_selectorMap.printLang != -1) { + EngineState *s = this; + + lang = (kLanguage)GET_SEL32V(s->game_obj, printLang); + + if ((_version == SCI_VERSION_1_1) || (lang == K_LANG_NONE)) { + // If language is set to none, we use the language from the game detector. + // SSCI reads this from resource.cfg (early games do not have a language + // setting in resource.cfg, but instead have the secondary language number + // hardcoded in the game script). + // SCI1.1 games always use the language setting from the config file + // (essentially disabling runtime language switching). + // Note: only a limited number of multilanguage games have been tested + // so far, so this information may not be 100% accurate. + switch (((Sci::SciEngine*)g_engine)->getLanguage()) { + case Common::FR_FRA: + lang = K_LANG_FRENCH; + break; + case Common::ES_ESP: + lang = K_LANG_SPANISH; + break; + case Common::IT_ITA: + lang = K_LANG_ITALIAN; + break; + case Common::DE_DEU: + lang = K_LANG_GERMAN; + break; + case Common::JA_JPN: + lang = K_LANG_JAPANESE; + break; + case Common::PT_BRA: + lang = K_LANG_PORTUGUESE; + break; + default: + lang = K_LANG_ENGLISH; + } + + // Store language in printLang selector + PUT_SEL32V(s->game_obj, printLang, lang); + } + } + + return lang; +} + Common::String EngineState::strSplit(const char *str, const char *sep) { EngineState *s = this; - kLanguage lang = (kLanguage)GET_SEL32V(s->game_obj, printLang); - kLanguage subLang = (kLanguage)GET_SEL32V(s->game_obj, subtitleLang); + kLanguage lang = getLanguage(); + kLanguage subLang = K_LANG_NONE; - // Use English when no language settings are present in the game - if (lang == K_LANG_NONE) - lang = K_LANG_ENGLISH; + if (((SciEngine*)g_engine)->getKernel()->_selectorMap.subtitleLang != -1) + subLang = (kLanguage)GET_SEL32V(s->game_obj, subtitleLang); Common::String retval = getLanguageString(str, lang); diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index b41e9e383a..3db926ab3d 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -125,6 +125,7 @@ public: virtual ~EngineState(); virtual void saveLoadWithSerializer(Common::Serializer &ser); + kLanguage getLanguage(); public: int widget_serial_counter; /**< Used for savegames */ -- cgit v1.2.3