SCI: Improved multilanguage support for SCI1 and SCI1.1.

svn-id: r43217
This commit is contained in:
Walter van Niftrik 2009-08-10 18:37:47 +00:00
parent bd71d79e73
commit dd9e569325
7 changed files with 86 additions and 13 deletions

View file

@ -497,6 +497,9 @@ int game_init(EngineState *s) {
if (s->sfx_init_flags & SFX_STATE_FLAG_NOSOUND) if (s->sfx_init_flags & SFX_STATE_FLAG_NOSOUND)
game_init_sound(s, 0); game_init_sound(s, 0);
// Load game language into printLang property of game object
s->getLanguage();
return 0; return 0;
} }

View file

@ -320,6 +320,7 @@ SciKernelFunction kfunct_mappers[] = {
/*(?)*/ DEFUN("Lock", kLock, "iii*"), /*(?)*/ DEFUN("Lock", kLock, "iii*"),
/*(?)*/ DEFUN("Palette", kPalette, "i.*"), /*(?)*/ DEFUN("Palette", kPalette, "i.*"),
/*(?)*/ DEFUN("IsItSkip", kIsItSkip, "iiiii"), /*(?)*/ DEFUN("IsItSkip", kIsItSkip, "iiiii"),
/*7b*/ DEFUN("StrSplit", kStrSplit, "rrZr"),
// Non-experimental Functions without a fixed ID // Non-experimental Functions without a fixed ID
DEFUN("CosMult", kTimesCos, "ii"), DEFUN("CosMult", kTimesCos, "ii"),
@ -345,7 +346,6 @@ SciKernelFunction kfunct_mappers[] = {
DEFUN("MemorySegment", kStub, ".*"), DEFUN("MemorySegment", kStub, ".*"),
DEFUN("ListOps", kStub, ".*"), DEFUN("ListOps", kStub, ".*"),
DEFUN("ATan", kStub, ".*"), DEFUN("ATan", kStub, ".*"),
DEFUN("StrSplit", kStub, ".*"),
DEFUN("MergePoly", kStub, ".*"), DEFUN("MergePoly", kStub, ".*"),
DEFUN("AssertPalette", kStub, ".*"), DEFUN("AssertPalette", kStub, ".*"),
DEFUN("TextColors", kStub, ".*"), DEFUN("TextColors", kStub, ".*"),

View file

@ -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 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 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 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); reg_t k_Unknown(EngineState *s, int funct_nr, int argc, reg_t *argv);
// The Unknown/Unnamed kernel function // The Unknown/Unnamed kernel function

View file

@ -812,4 +812,21 @@ reg_t kSetQuitStr(EngineState *s, int funct_nr, int argc, reg_t *argv) {
return s->r_acc; 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 } // End of namespace Sci

View file

@ -33,7 +33,7 @@ MessageTuple MessageState::getTuple() {
t.noun = *(_engineCursor.index_record + 0); t.noun = *(_engineCursor.index_record + 0);
t.verb = *(_engineCursor.index_record + 1); t.verb = *(_engineCursor.index_record + 1);
if (_version == 2101) { if (_version == 2) {
t.cond = 0; t.cond = 0;
t.seq = 1; t.seq = 1;
} else { } else {
@ -47,7 +47,7 @@ MessageTuple MessageState::getTuple() {
MessageTuple MessageState::getRefTuple() { MessageTuple MessageState::getRefTuple() {
MessageTuple t; MessageTuple t;
if (_version == 2101) { if (_version == 2) {
t.noun = 0; t.noun = 0;
t.verb = 0; t.verb = 0;
t.cond = 0; t.cond = 0;
@ -68,7 +68,7 @@ void MessageState::initCursor() {
} }
void MessageState::advanceCursor(bool increaseSeq) { void MessageState::advanceCursor(bool increaseSeq) {
_engineCursor.index_record += ((_version == 2101) ? 4 : 11); _engineCursor.index_record += ((_version == 2) ? 4 : 11);
_engineCursor.index++; _engineCursor.index++;
if (increaseSeq) if (increaseSeq)
@ -142,7 +142,7 @@ int MessageState::getMessage() {
} }
int MessageState::getTalker() { int MessageState::getTalker() {
return (_version == 2101) ? -1 : *(_engineCursor.index_record + 4); return (_version == 2) ? -1 : *(_engineCursor.index_record + 4);
} }
MessageTuple &MessageState::getLastTuple() { MessageTuple &MessageState::getLastTuple() {
@ -154,7 +154,7 @@ int MessageState::getLastModule() {
} }
Common::String MessageState::getText() { 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 strippedStr;
Common::String skippedSubstr; Common::String skippedSubstr;
@ -215,7 +215,7 @@ void MessageState::gotoNext() {
} }
int MessageState::getLength() { 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; char *stringptr = (char *)_currentResource->data + offset;
return strlen(stringptr); return strlen(stringptr);
} }
@ -244,8 +244,12 @@ int MessageState::loadRes(ResourceManager *resmgr, int module, bool lock) {
_locked = lock; _locked = lock;
_version = READ_LE_UINT16(_currentResource->data); _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); _recordCount = READ_LE_UINT16(_currentResource->data + 4 + offs);
_indexRecords = _currentResource->data + 6 + offs; _indexRecords = _currentResource->data + 6 + offs;

View file

@ -172,15 +172,62 @@ Common::String EngineState::getLanguageString(const char *str, kLanguage lang) c
return Common::String(str); 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) { Common::String EngineState::strSplit(const char *str, const char *sep) {
EngineState *s = this; EngineState *s = this;
kLanguage lang = (kLanguage)GET_SEL32V(s->game_obj, printLang); kLanguage lang = getLanguage();
kLanguage subLang = (kLanguage)GET_SEL32V(s->game_obj, subtitleLang); kLanguage subLang = K_LANG_NONE;
// Use English when no language settings are present in the game if (((SciEngine*)g_engine)->getKernel()->_selectorMap.subtitleLang != -1)
if (lang == K_LANG_NONE) subLang = (kLanguage)GET_SEL32V(s->game_obj, subtitleLang);
lang = K_LANG_ENGLISH;
Common::String retval = getLanguageString(str, lang); Common::String retval = getLanguageString(str, lang);

View file

@ -125,6 +125,7 @@ public:
virtual ~EngineState(); virtual ~EngineState();
virtual void saveLoadWithSerializer(Common::Serializer &ser); virtual void saveLoadWithSerializer(Common::Serializer &ser);
kLanguage getLanguage();
public: public:
int widget_serial_counter; /**< Used for savegames */ int widget_serial_counter; /**< Used for savegames */