diff --git a/engines/scumm/insane/insane.cpp b/engines/scumm/insane/insane.cpp index 99b6f283fbe..c21a360d591 100644 --- a/engines/scumm/insane/insane.cpp +++ b/engines/scumm/insane/insane.cpp @@ -1294,14 +1294,18 @@ void Insane::smlayer_showStatusMsg(int32 arg_0, byte *renderBitmap, int32 codecp assert(sf != NULL); + if (_vm->_language == Common::HE_ISR && !(flags & kStyleAlignCenter)) { + flags |= kStyleAlignRight; + pos_x = _player->_width - 1 - pos_x; + } + TextStyleFlags flg = (TextStyleFlags)(flags & 7); // flags: // bit 0 - center 0x01 // bit 1 - not used (align right) 0x02 // bit 2 - word wrap 0x04 // bit 3 - switchable 0x08 // bit 4 - fill background 0x10 - TextStyleFlags flg = (TextStyleFlags)(flags & 7); - if ((flg & kStyleWordWrap) || _vm->_language == Common::HE_ISR) { + if (flg & kStyleWordWrap) { Common::Rect clipRect(0, 0, _player->_width, _player->_height); sf->drawStringWrap(str, renderBitmap, clipRect, pos_x, pos_y, color, flg); } else { diff --git a/engines/scumm/nut_renderer.h b/engines/scumm/nut_renderer.h index bf52f80e993..95aaa415094 100644 --- a/engines/scumm/nut_renderer.h +++ b/engines/scumm/nut_renderer.h @@ -48,7 +48,7 @@ protected: byte *_paletteMap; byte _bpp; byte _palette[16]; - const bool _direction; + const int _direction; const int8 *_2byteShadowXOffsetTable; const int8 *_2byteShadowYOffsetTable; diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index 690fc4f80e8..4fd074dfeef 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -821,8 +821,8 @@ static void syncWithSerializer(Common::Serializer &s, ObjectData &od) { s.syncAsByte(od.flags, VER(46)); } -static void syncWithSerializer(Common::Serializer &s, VerbSlot &vs, bool isISR) { - s.syncAsSint16LE(!isISR ? vs.curRect.left : vs.origLeft, VER(8)); +static void syncWithSerializer(Common::Serializer &s, VerbSlot &vs, bool isV7orISR) { + s.syncAsSint16LE(!isV7orISR ? vs.curRect.left : vs.origLeft, VER(8)); s.syncAsSint16LE(vs.curRect.top, VER(8)); s.syncAsSint16LE(vs.curRect.right, VER(8)); s.syncAsSint16LE(vs.curRect.bottom, VER(8)); @@ -844,15 +844,15 @@ static void syncWithSerializer(Common::Serializer &s, VerbSlot &vs, bool isISR) s.syncAsByte(vs.center, VER(8)); s.syncAsByte(vs.prep, VER(8)); s.syncAsUint16LE(vs.imgindex, VER(8)); - if (isISR && s.isLoading() && s.getVersion() >= 8) + if (isV7orISR && s.isLoading() && s.getVersion() >= 8) vs.curRect.left = vs.origLeft; } -static void syncWithSerializerNonISR(Common::Serializer &s, VerbSlot &vs) { +static void syncWithSerializerDef(Common::Serializer &s, VerbSlot &vs) { syncWithSerializer(s, vs, false); } -static void syncWithSerializerISR(Common::Serializer &s, VerbSlot &vs) { +static void syncWithSerializerV7orISR(Common::Serializer &s, VerbSlot &vs) { syncWithSerializer(s, vs, true); } @@ -1239,7 +1239,7 @@ void ScummEngine::saveLoadWithSerializer(Common::Serializer &s) { // // Save/load misc stuff // - s.syncArray(_verbs, _numVerbs, _language != Common::HE_ISR ? syncWithSerializerNonISR : syncWithSerializerISR); + s.syncArray(_verbs, _numVerbs, (_game.version < 7 && _language != Common::HE_ISR) ? syncWithSerializerDef : syncWithSerializerV7orISR); s.syncArray(vm.nest, 16, syncWithSerializer); s.syncArray(_sentence, 6, syncWithSerializer); s.syncArray(_string, 6, syncWithSerializer); diff --git a/engines/scumm/script_v8.cpp b/engines/scumm/script_v8.cpp index fd6df11d658..2325ba54d64 100644 --- a/engines/scumm/script_v8.cpp +++ b/engines/scumm/script_v8.cpp @@ -977,10 +977,7 @@ void ScummEngine_v8::o8_verbOps() { break; case 0x9A: // SO_VERB_AT Set verb (X,Y) placement vs->curRect.top = pop(); - if (_language == Common::HE_ISR) - vs->curRect.right = _screenWidth - 1 - pop(); - else - vs->origLeft = pop(); + vs->origLeft = pop(); break; case 0x9B: // SO_VERB_ON Turn verb on vs->curmode = 1; diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp index 914b1e03742..06fa7653e40 100644 --- a/engines/scumm/smush/smush_player.cpp +++ b/engines/scumm/smush/smush_player.cpp @@ -661,6 +661,12 @@ void SmushPlayer::handleTextResource(uint32 subType, int32 subSize, Common::Seek // changes on the fly will be ignored for Smush texts, since our code design does // not permit it and the feature isn't used anyway). + if (_vm->_language == Common::HE_ISR && !(flags & kStyleAlignCenter)) { + flags |= kStyleAlignRight; + pos_x = _width - 1 - pos_x; + } + + TextStyleFlags flg = (TextStyleFlags)(flags & 7); // flags: // bit 0 - center 0x01 // bit 1 - not used (align right) 0x02 @@ -671,8 +677,8 @@ void SmushPlayer::handleTextResource(uint32 subType, int32 subSize, Common::Seek // bit 6 - vertical fix (COMI) 0x40 (COMI handles this in the printing method, but I haven't seen a case where it is used) // bit 7 - skip ^ codes (COMI) 0x80 (should be irrelevant for Smush, we strip these commands anyway) // bit 8 - no vertical fix (COMI) 0x100 (COMI handles this in the printing method, but I haven't seen a case where it is used) - TextStyleFlags flg = (TextStyleFlags)(flags & 7); - if ((flg & kStyleWordWrap) || _vm->_language == Common::HE_ISR) { + + if (flg & kStyleWordWrap) { // COMI has to do it all a bit different, of course. SCUMM7 games immediately render the text from here and actually use the clipping data // provided by the text resource. COMI does not render directly, but enqueues a blast string (which is then drawn through the usual main // loop routines). During that process the rect data will get dumped and replaced with the following default values. It's hard to tell diff --git a/engines/scumm/string_v7.cpp b/engines/scumm/string_v7.cpp index 6029dfbefd6..a121c481ecf 100644 --- a/engines/scumm/string_v7.cpp +++ b/engines/scumm/string_v7.cpp @@ -39,6 +39,7 @@ TextRenderer_v7::TextRenderer_v7(ScummEngine *vm, GlyphRenderer_v7 *gr) : _screenWidth(vm->_screenWidth), _useCJKMode(vm->_useCJKMode), _direction(vm->_language == Common::HE_ISR ? -1 : 1), + _rtlCenteredOffset(vm->_language == Common::HE_ISR ? 1 : 0), _spacing(vm->_language != Common::JA_JPN ? 1 : 0), _lineBreakMarker(vm->_newLineCharacter), _newStyle (gr->newStyleWrapping()), @@ -147,39 +148,33 @@ int TextRenderer_v7::getStringHeight(const char *str, uint numBytesMax) { } void TextRenderer_v7::drawSubstring(const char *str, uint numBytesMax, byte *buffer, Common::Rect &clipRect, int x, int y, int pitch, int16 &col, TextStyleFlags flags) { - if (_lang == Common::HE_ISR) { - for (int i = numBytesMax; i > 0; i--) { - x += _gr->drawChar(buffer, clipRect, x, y, pitch, col, flags, str[i - 1]); - } - } else { - for (int i = 0; str[i] != 0 && numBytesMax; ++i) { - if (_newStyle && str[i] == '^') { - if (str[i + 1] == 'f') { - _gr->setFont(str[i + 3] - '0'); - i += 3; - numBytesMax -= 4; - continue; - } else if (str[i + 1] == 'c') { - col = str[i + 4] - '0' + 10 *(str[i + 3] - '0'); - i += 4; - numBytesMax -= 5; - continue; - } else if (str[i + 1] == 'l') { - i++; - numBytesMax -= 2; - continue; - } + for (int i = 0; str[i] != 0 && numBytesMax; ++i) { + if (_newStyle && str[i] == '^') { + if (str[i + 1] == 'f') { + _gr->setFont(str[i + 3] - '0'); + i += 3; + numBytesMax -= 4; + continue; + } else if (str[i + 1] == 'c') { + col = str[i + 4] - '0' + 10 *(str[i + 3] - '0'); + i += 4; + numBytesMax -= 5; + continue; + } else if (str[i + 1] == 'l') { + i++; + numBytesMax -= 2; + continue; } + } - if (is2ByteCharacter(_lang, str[i])) { - x += _gr->draw2byte(buffer, clipRect, x, y, pitch, col, (byte)str[i] + 256 * (byte)str[i + 1]); - ++i; - --numBytesMax; - } else if (str[i] != '\n' && str[i] != _lineBreakMarker) { - x += _gr->drawChar(buffer, clipRect, x, y, pitch, col, flags, str[i]); - } + if (is2ByteCharacter(_lang, str[i])) { + x += _gr->draw2byte(buffer, clipRect, x, y, pitch, col, (byte)str[i] + 256 * (byte)str[i + 1]); + ++i; --numBytesMax; + } else if (str[i] != '\n' && str[i] != _lineBreakMarker) { + x += _gr->drawChar(buffer, clipRect, x, y, pitch, col, flags, str[i]); } + --numBytesMax; } } @@ -215,21 +210,25 @@ void TextRenderer_v7::drawString(const char *str, byte *buffer, Common::Rect &cl int xpos = x; if (flags & kStyleAlignCenter) - xpos = x - _direction * width / 2; - else if (((flags & kStyleAlignRight) && _direction == 1) || ((flags & kStyleAlignLeft) && _direction == -1)) + xpos = x - _direction * width / 2 + (_rtlCenteredOffset & width); + else if (((flags & kStyleAlignRight) && _direction == 1) || (!(flags & kStyleAlignRight) && _direction == -1)) + // The original interpreter apparently does not expect a right-to-left written language when the kStyleAlignRight flag is set. + // It just right-aligns a left-to-right string. So we now move xpos to the left like the original interpreter would if it is a + // left-to-right string, but leave it on the right in case of a right-to-left string (and vice versa for right-to-left strings + // with kStyleAlignLeft flag). xpos = x - _direction * width; if (!_newStyle) - xpos = CLIP(xpos, clipRect.left, _screenWidth - width); + xpos = (_direction == 1) ? CLIP(xpos, clipRect.left, _screenWidth - width) : CLIP(xpos, clipRect.left + width, _screenWidth - 1); - drawSubstring(str + lineStart, len, buffer, clipRect, _direction * width, y, pitch, col, flags); + drawSubstring(str + lineStart, len, buffer, clipRect, xpos, y, pitch, col, flags); y += height; } lineStart = pos + 1; } - clipRect.left = (flags & kStyleAlignCenter) ? x - maxWidth / 2: ((flags & kStyleAlignRight) ? x - maxWidth : x); + clipRect.left = (flags & kStyleAlignCenter) ? x - maxWidth / 2 : ((flags & kStyleAlignRight) ? x - maxWidth : x); clipRect.right = MIN(clipRect.right, clipRect.left + maxWidth); clipRect.top = y2; clipRect.bottom = y; @@ -349,7 +348,7 @@ void TextRenderer_v7::drawStringWrap(const char *str, byte *buffer, Common::Rect if (x - (maxWidth >> 1) < clipRect.left) x = clipRect.left + (maxWidth >> 1); } else if (flags & kStyleAlignRight) { - if (x < clipRect.right) + if (x > clipRect.right) x = clipRect.right; if (x < clipRect.left + maxWidth); x = clipRect.left + maxWidth; @@ -366,12 +365,16 @@ void TextRenderer_v7::drawStringWrap(const char *str, byte *buffer, Common::Rect for (int i = 0; i < numSubstrings; i++) { int xpos = x; if (flags & kStyleAlignCenter) - xpos = x - _direction * substrWidths[i] / 2; - else if (((flags & kStyleAlignRight) && _direction == 1) || ((flags & kStyleAlignLeft) && _direction == -1)) + xpos = x - _direction * substrWidths[i] / 2 + (_rtlCenteredOffset & substrWidths[i]); + else if (((flags & kStyleAlignRight) && _direction == 1) || (!(flags & kStyleAlignRight) && _direction == -1)) + // The original interpreter apparently does not expect a right-to-left written language when the kStyleAlignRight flag is set. + // It just right-aligns a left-to-right string. So we now move xpos to the left like the original interpreter would if it is a + // left-to-right string, but leave it on the right in case of a right-to-left string (and vice versa for right-to-left strings + // with kStyleAlignLeft flag). xpos = x - _direction * substrWidths[i]; if (!_newStyle) - xpos = CLIP(xpos, clipRect.left, _screenWidth - substrWidths[i]); + xpos = (_direction == 1) ? CLIP(xpos, clipRect.left, _screenWidth - substrWidths[i]) : CLIP(xpos, clipRect.left + substrWidths[i], _screenWidth - 1); len = substrByteLength[i] > 0 ? substrByteLength[i] : 0; drawSubstring(str + substrStart[i], len, buffer, clipRect, xpos, y, pitch, col, flags); @@ -440,6 +443,12 @@ void ScummEngine_v7::drawBlastTexts() { _charset->setCurID(_blastTextQueue[i].charset); + // If a Hebrew String comes up that is still marked as kStyleAlignLeft we fix it here... + if (_language == Common::HE_ISR && !(bt.flags & (kStyleAlignCenter | kStyleAlignRight))) { + bt.flags = (TextStyleFlags)(bt.flags | kStyleAlignRight); + bt.xpos = _screenWidth - 1 - bt.xpos; + } + if (bt.flags & kStyleWordWrap) { bt.rect = _wrappedTextClipRect; diff --git a/engines/scumm/string_v7.h b/engines/scumm/string_v7.h index 9f1af4e8e74..85d9b3c63a9 100644 --- a/engines/scumm/string_v7.h +++ b/engines/scumm/string_v7.h @@ -63,7 +63,8 @@ private: const Common::Language _lang; const byte _gameId; const bool _useCJKMode; - const bool _direction; + const int _direction; + const int _rtlCenteredOffset; const int _spacing; const byte _2byteCharWidth; const byte _lineBreakMarker; diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp index 6a49a7050cb..57e640a4c04 100644 --- a/engines/scumm/verbs.cpp +++ b/engines/scumm/verbs.cpp @@ -994,7 +994,15 @@ void ScummEngine_v7::drawVerb(int verb, int mode) { else if (mode && vs->hicolor) color = vs->hicolor; - TextStyleFlags flags = vs->center ? kStyleAlignCenter : kStyleAlignLeft; + TextStyleFlags flags = kStyleAlignLeft; + int xpos = vs->origLeft; + + if (vs->center) { + flags = kStyleAlignCenter; + } else if (_language == Common::HE_ISR) { + flags = kStyleAlignRight; + xpos = _screenWidth - 1 - vs->origLeft; + } const byte *msg = getResourceAddress(rtVerb, verb); if (!msg) @@ -1015,9 +1023,9 @@ void ScummEngine_v7::drawVerb(int verb, int mode) { _charset->setCurID(vs->charset_nr); // Compute the text rect - vs->oldRect = vs->curRect = _textV7->calcStringDimensions((const char*)msg, vs->origLeft, vs->curRect.top, vs->center ? kStyleAlignCenter : kStyleAlignLeft); + vs->oldRect = vs->curRect = _textV7->calcStringDimensions((const char*)msg, xpos, vs->curRect.top, flags); - const int maxWidth = /*_language == Common::HE_ISR ? vs->curRect.right + 1 :*/ _screenWidth - vs->curRect.left; + const int maxWidth = _screenWidth - vs->curRect.left; int finalWidth = maxWidth; if (_game.version == 8 && _textV7->getStringWidth((const char*)buf) > maxWidth) { @@ -1036,30 +1044,12 @@ void ScummEngine_v7::drawVerb(int verb, int mode) { --len; } - enqueueText(tmpBuf, vs->origLeft, vs->curRect.top, color, vs->charset_nr, flags); - enqueueText(&msg[len + 1], vs->origLeft, vs->curRect.top + _verbLineSpacing, color, vs->charset_nr, flags); + enqueueText(tmpBuf, xpos, vs->curRect.top, color, vs->charset_nr, flags); + enqueueText(&msg[len + 1], xpos, vs->curRect.top + _verbLineSpacing, color, vs->charset_nr, flags); vs->curRect.right = vs->curRect.left + finalWidth; - vs->curRect.bottom += _verbLineSpacing; - /* - int16 leftPos = vs->curRect.left; - if (_language == Common::HE_ISR) - vs->curRect.left = vs->origLeft = leftPos = vs->curRect.right - _charset->getStringWidth(0, tmpBuf); - else - vs->curRect.right = vs->curRect.left + _charset->getStringWidth(0, tmpBuf); - enqueueText(tmpBuf, leftPos, vs->curRect.top, color, vs->charset_nr, vs->center); - if (len >= 0) { - if (_language == Common::HE_ISR) - leftPos = vs->curRect.right - _charset->getStringWidth(0, &msg[len + 1]); - enqueueText(&msg[len + 1], leftPos, vs->curRect.top + _verbLineSpacing, color, vs->charset_nr, vs->center); - vs->curRect.bottom += _verbLineSpacing; - }*/ - } else {/* - if (_language == Common::HE_ISR) - vs->curRect.left = vs->origLeft = vs->curRect.right - textWidth; - else - vs->curRect.right = vs->curRect.left + textWidth; - enqueueText(msg, vs->curRect.left, vs->curRect.top, color, vs->charset_nr, vs->center);*/ - enqueueText(msg, vs->origLeft, vs->curRect.top, color, vs->charset_nr, flags); + vs->curRect.bottom += _verbLineSpacing; + } else { + enqueueText(msg, xpos, vs->curRect.top, color, vs->charset_nr, flags); } _charset->setCurID(oldID); }