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)
game_init_sound(s, 0);
// Load game language into printLang property of game object
s->getLanguage();
return 0;
}

View file

@ -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, ".*"),

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 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

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

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