diff options
author | James Brown | 2003-02-14 16:01:55 +0000 |
---|---|---|
committer | James Brown | 2003-02-14 16:01:55 +0000 |
commit | d054457496883bc4ae85700f9bcfae38628e6f2a (patch) | |
tree | a7eb8e4b1f36df5b03217fb8f1485f18ff95d5cd | |
parent | db0997e890de515796a3cabcb663b8d5e799a82c (diff) | |
download | scummvm-rg350-d054457496883bc4ae85700f9bcfae38628e6f2a.tar.gz scummvm-rg350-d054457496883bc4ae85700f9bcfae38628e6f2a.tar.bz2 scummvm-rg350-d054457496883bc4ae85700f9bcfae38628e6f2a.zip |
Patch #682981: Experimental translation optimisation (version 2), and
#683384: Smush Regression Workaround
svn-id: r6607
-rw-r--r-- | scumm/scumm.h | 7 | ||||
-rw-r--r-- | scumm/smush/player.cpp | 6 | ||||
-rw-r--r-- | scumm/string.cpp | 121 |
3 files changed, 108 insertions, 26 deletions
diff --git a/scumm/scumm.h b/scumm/scumm.h index f0637a0508..97d956afd2 100644 --- a/scumm/scumm.h +++ b/scumm/scumm.h @@ -228,6 +228,11 @@ enum MouseButtonStatus { msClicked = 2 }; +struct langIndexNode { + char tag[9]; + int32 offset; +}; + class Scumm : public Engine { friend void NORETURN CDECL error(const char *s, ...); // FIXME - ugly but error() accesses g_scumm... friend class ScummDebugger; @@ -967,6 +972,8 @@ public: bool _keepText; bool _existLanguageFile; char *_languageBuffer; + struct langIndexNode *_languageIndex; + int _languageStrCount; void loadLanguageBundle(); void translateText(byte *text, byte *trans_buff); byte _transText[500]; diff --git a/scumm/smush/player.cpp b/scumm/smush/player.cpp index cdce084e00..8024704485 100644 --- a/scumm/smush/player.cpp +++ b/scumm/smush/player.cpp @@ -486,6 +486,12 @@ void SmushPlayer::handleTextResource(Chunk & b) { g_scumm->translateText((byte*)str - 1, g_scumm->_transText); while(*str++ != '/'); string2 = (char*)g_scumm->_transText; + + // If string2 contains formatting information there probably + // wasn't any translation for it in the language.tab file. In + // that case, pretend there is no string2. + if (string2[0] == '^') + string2[0] = 0; } while(str[0] == '^') { diff --git a/scumm/string.cpp b/scumm/string.cpp index 111737a6ba..ebc546a47a 100644 --- a/scumm/string.cpp +++ b/scumm/string.cpp @@ -812,8 +812,17 @@ void Scumm::initCharset(int charsetno) _charsetColorMap[i] = _charsetData[_charset->getCurID()][i]; } +int indexCompare(const void *p1, const void *p2) +{ + struct langIndexNode *i1 = (struct langIndexNode *) p1; + struct langIndexNode *i2 = (struct langIndexNode *) p2; + + return strcmp(i1->tag, i2->tag); +} + void Scumm::loadLanguageBundle() { File file; + int32 size; if (_gameId == GID_DIG) { file.open("language.bnd", _gameDataPath); @@ -828,9 +837,64 @@ void Scumm::loadLanguageBundle() { return; } - _languageBuffer = (char*)malloc(file.size()); - file.read(_languageBuffer, file.size()); + size = file.size(); + _languageBuffer = (char*)malloc(size); + file.read(_languageBuffer, size); file.close(); + + // Create an index of the language file. + // FIXME: Extend this mechanism to also cover The Dig? + + if (_gameId == GID_CMI) { + int32 i; + char *ptr = _languageBuffer; + + // Count the number of lines in the language file. + + _languageStrCount = 0; + + for (;;) { + ptr = strpbrk(ptr, "\n\r"); + if (ptr == NULL) + break; + while (*ptr == '\n' || *ptr == '\r') + ptr++; + _languageStrCount++; + } + + // Fill the language file index. This is just an array of + // tags and offsets. I did consider using a balanced tree + // instead, but the extra overhead in the node structure would + // easily have doubled the memory consumption of the index. + + _languageIndex = (struct langIndexNode *) malloc(_languageStrCount * sizeof(struct langIndexNode)); + + ptr = _languageBuffer; + + for (i = 0; i < _languageStrCount; i++) { + int j; + + for (j = 0; j < 8 && !isspace(ptr[j]); j++) + _languageIndex[i].tag[j] = toupper(ptr[j]); + _languageIndex[i].tag[j] = 0; + ptr += (j + 1); + _languageIndex[i].offset = ptr - _languageBuffer; + ptr = strpbrk(ptr, "\n\r"); + if (ptr == NULL) + break; + while (*ptr == '\n' || *ptr == '\r') + ptr++; + } + + // Conceptually, it may be more elegant to construct the + // index so that it is sorted, or otherwise ordered, from the + // start. However, this is less error-prone and likely to be + // much more optimized than anything I might implement. + + qsort(_languageIndex, _languageStrCount, sizeof(struct langIndexNode), indexCompare); + free(_languageBuffer); + } + _existLanguageFile = true; } @@ -844,33 +908,38 @@ void Scumm::translateText(byte *text, byte *trans_buff) { pos = 0; if (_gameId == GID_CMI) { + struct langIndexNode target; + struct langIndexNode *found; + // copy name from text /..../ - for (l = 0; (l < 20) && (text[l + 1] != '/'); l++) { - name[l] = text[l + 1]; - } - name[l] = 0; - for (;;) { - if(buf[pos] == 0) { - trans_buff[0] = '\0'; - break; - } - l = 0; - do { - tmp[l++] = buf[pos++]; - assert(l < 499); - } while((buf[pos] != 0) && (buf[pos] != 0x0d) && (buf[pos + 1] != 0x0a)); - tmp[l] = 0; - pos += 2; - l = 0; - do { - tmp2[l] = tmp[l]; - l++; - } while((tmp[l] != 0) && (tmp[l] != 9) && (l < 19)); - tmp2[l] = 0; - if (scumm_stricmp(tmp2, name) == 0) { - strcpy((char*)trans_buff, &tmp[l + 1]); + for (l = 0; (l < 8) && (text[l + 1] != '/'); l++) + target.tag[l] = toupper(text[l + 1]); + target.tag[l] = 0; + + found = (struct langIndexNode *) bsearch(&target, _languageIndex, _languageStrCount, sizeof(struct langIndexNode), indexCompare); + + if (found != NULL) { + File file; + + file.open("language.tab", _gameDataPath); + if (file.isOpen()) { + byte *ptr = trans_buff; + byte c; + + file.seek(found->offset, SEEK_SET); + for (;;) { + c = file.readByte(); + if (c == 10 || c == 13) { + *ptr = 0; + break; + } else + *ptr++ = c; + } + file.close(); return; } + // Some evil person removed the language file? + _existLanguageFile = false; } } else if (_gameId == GID_DIG) { // copy name from text /..../ |