diff options
author | Max Horn | 2007-01-28 20:11:31 +0000 |
---|---|---|
committer | Max Horn | 2007-01-28 20:11:31 +0000 |
commit | 27432a4dc13ec3f80eac61f17296aef5533e46bf (patch) | |
tree | 0c4c2e800229bb9f93e85d79f6df8572ebeb6f6e | |
parent | e287f181edbec10bd6ba54f713eb44acecf47b40 (diff) | |
download | scummvm-rg350-27432a4dc13ec3f80eac61f17296aef5533e46bf.tar.gz scummvm-rg350-27432a4dc13ec3f80eac61f17296aef5533e46bf.tar.bz2 scummvm-rg350-27432a4dc13ec3f80eac61f17296aef5533e46bf.zip |
Moved some stuff from CharsetRenderer (back) to ScummEngine, added comments
svn-id: r25250
-rw-r--r-- | engines/scumm/actor.cpp | 2 | ||||
-rw-r--r-- | engines/scumm/charset.cpp | 81 | ||||
-rw-r--r-- | engines/scumm/charset.h | 13 | ||||
-rw-r--r-- | engines/scumm/gfx.cpp | 42 | ||||
-rw-r--r-- | engines/scumm/he/script_v70he.cpp | 2 | ||||
-rw-r--r-- | engines/scumm/he/script_v90he.cpp | 2 | ||||
-rw-r--r-- | engines/scumm/saveload.cpp | 2 | ||||
-rw-r--r-- | engines/scumm/script_v6.cpp | 2 | ||||
-rw-r--r-- | engines/scumm/scumm.cpp | 10 | ||||
-rw-r--r-- | engines/scumm/scumm.h | 13 | ||||
-rw-r--r-- | engines/scumm/string.cpp | 50 |
11 files changed, 117 insertions, 102 deletions
diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp index 7b5db837e5..f360cd5b3d 100644 --- a/engines/scumm/actor.cpp +++ b/engines/scumm/actor.cpp @@ -1895,7 +1895,7 @@ void ScummEngine::stopTalk() { ((ScummEngine_v7 *)this)->clearSubtitleQueue(); #endif } else { - _charset->restoreCharsetBg(); + restoreCharsetBg(); } } diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp index a50e749d0f..6fb1949ede 100644 --- a/engines/scumm/charset.cpp +++ b/engines/scumm/charset.cpp @@ -29,6 +29,19 @@ namespace Scumm { +/* +TODO: +Right now our charset renderers directly access _textSurface, as well as the +virtual screens of ScummEngine. Ideally, this would not be the case. Instead, +ScummVM would simply pass the appropriate Surface to the resp. methods. +Of course it is not quite as simple, various flags and offsets have to +be taken into account for that. + +The advantage will be cleaner coder (easier to debug, in particular), and a +better separation of the various modules. +*/ + + void ScummEngine::loadCJKFont() { Common::File fp; _useCJKMode = false; @@ -186,10 +199,6 @@ byte *ScummEngine::get2byteCharPtr(int idx) { CharsetRenderer::CharsetRenderer(ScummEngine *vm) { - - _nextLeft = 0; - _nextTop = 0; - _top = 0; _left = 0; _startLeft = 0; @@ -206,18 +215,9 @@ CharsetRenderer::CharsetRenderer(ScummEngine *vm) { _vm = vm; _curId = 0; - - const int size = _vm->_screenWidth * _vm->_screenHeight; - _textSurface.pixels = malloc(size); - _textSurface.w = _vm->_screenWidth; - _textSurface.h = _vm->_screenHeight; - _textSurface.pitch = _vm->_screenWidth; - _textSurface.bytesPerPixel = 1; - clearTextSurface(); } CharsetRenderer::~CharsetRenderer() { - free(_textSurface.pixels); } CharsetRendererCommon::CharsetRendererCommon(ScummEngine *vm) @@ -1258,8 +1258,8 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) { dst = vs->getPixels(_left, drawTop); drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight); } else { - dst = (byte *)_textSurface.pixels + _top * _textSurface.pitch + _left; - drawBits1(_textSurface, dst, charPtr, drawTop, origWidth, origHeight); + dst = (byte *)_vm->_textSurface.pixels + _top * _vm->_textSurface.pitch + _left; + drawBits1(_vm->_textSurface, dst, charPtr, drawTop, origWidth, origHeight); } if (_str.left > _left) @@ -1317,7 +1317,7 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) { int offsX, offsY; VirtScreen *vs; const byte *charPtr; - int is2byte = (chr >= 0x80 && _vm->_useCJKMode) ? 1 : 0; + bool is2byte = (chr >= 0x80 && _vm->_useCJKMode); assertRange(1, _curId, _vm->_numCharsets - 1, "charset"); @@ -1400,20 +1400,38 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) { _vm->markRectAsDirty(vs->number, _left, _left + width, drawTop, drawTop + height); - byte *dstPtr; - byte *back = NULL; - if (!ignoreCharsetMask) { _hasMask = true; _textScreenID = vs->number; } + printCharIntern(is2byte, charPtr, origWidth, origHeight, width, height, vs, ignoreCharsetMask); + + _left += origWidth; + + if (_str.right < _left) { + _str.right = _left; + if (_shadowMode != kNoShadowMode) + _str.right++; + } + + if (_str.bottom < _top + height) + _str.bottom = _top + height; + + _top -= offsY; +} + +void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr, int origWidth, int origHeight, int width, int height, VirtScreen *vs, bool ignoreCharsetMask) { + byte *dstPtr; + byte *back = NULL; + int drawTop = _top - vs->topline; + if ((_vm->_game.heversion >= 71 && _bitDepth >= 8) || (_vm->_game.heversion >= 90 && _bitDepth == 0)) { #ifndef DISABLE_HE if (ignoreCharsetMask || !vs->hasTwoBuffers) { dstPtr = vs->getPixels(0, 0); } else { - dstPtr = (byte *)_textSurface.pixels; + dstPtr = (byte *)_vm->_textSurface.pixels; } if (_blitAlso && vs->hasTwoBuffers) { @@ -1442,8 +1460,8 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) { dstSurface = *vs; dstPtr = vs->getPixels(_left, drawTop); } else { - dstSurface = _textSurface; - dstPtr = (byte *)_textSurface.pixels + (_top - _vm->_screenTop) * _textSurface.pitch + _left; + dstSurface = _vm->_textSurface; + dstPtr = (byte *)_vm->_textSurface.pixels + (_top - _vm->_screenTop) * _vm->_textSurface.pitch + _left; } if (_blitAlso && vs->hasTwoBuffers) { @@ -1498,19 +1516,6 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) { } } } - - _left += origWidth; - - if (_str.right < _left) { - _str.right = _left; - if (_shadowMode != kNoShadowMode) - _str.right++; - } - - if (_str.bottom < _top + height) - _str.bottom = _top + height; - - _top -= offsY; } void CharsetRendererClassic::drawChar(int chr, const Graphics::Surface &s, int x, int y) { @@ -1686,7 +1691,7 @@ void CharsetRendererNut::printChar(int chr, bool ignoreCharsetMask) { s = *vs; s.pixels = vs->getPixels(0, 0); } else { - s = _textSurface; + s = _vm->_textSurface; drawTop -= _vm->_screenTop; } @@ -1753,8 +1758,8 @@ void CharsetRendererNES::printChar(int chr, bool ignoreCharsetMask) { dst = vs->getPixels(_left, drawTop); drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight); } else { - dst = (byte *)_textSurface.pixels + _top * _textSurface.pitch + _left; - drawBits1(_textSurface, dst, charPtr, drawTop, origWidth, origHeight); + dst = (byte *)_vm->_textSurface.pixels + _top * _vm->_textSurface.pitch + _left; + drawBits1(_vm->_textSurface, dst, charPtr, drawTop, origWidth, origHeight); } if (_str.left > _left) diff --git a/engines/scumm/charset.h b/engines/scumm/charset.h index 54091eeee7..04aecb98cb 100644 --- a/engines/scumm/charset.h +++ b/engines/scumm/charset.h @@ -43,7 +43,6 @@ class CharsetRenderer { public: Common::Rect _str; - int _nextLeft, _nextTop; int _top; int _left, _startLeft; @@ -62,12 +61,6 @@ public: bool _firstChar; bool _disableOffsX; - /** - * All text is normally rendered into this overlay surface. Then later - * drawStripToScreen() composits it over the game graphics. - */ - Graphics::Surface _textSurface; - protected: ScummEngine *_vm; byte _curId; @@ -76,10 +69,6 @@ public: CharsetRenderer(ScummEngine *vm); virtual ~CharsetRenderer(); - void restoreCharsetBg(); - void clearCharsetMask(); - void clearTextSurface(); - virtual void printChar(int chr, bool ignoreCharsetMask) = 0; virtual void drawChar(int chr, const Graphics::Surface &s, int x, int y) {} @@ -127,6 +116,8 @@ class CharsetRendererClassic : public CharsetRendererCommon { protected: void drawBitsN(const Graphics::Surface &s, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height); + void printCharIntern(bool is2byte, const byte *charPtr, int origWidth, int origHeight, int width, int height, VirtScreen *vs, bool ignoreCharsetMask); + public: CharsetRendererClassic(ScummEngine *vm) : CharsetRendererCommon(vm) {} diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp index e7696a11d8..d53f27934e 100644 --- a/engines/scumm/gfx.cpp +++ b/engines/scumm/gfx.cpp @@ -545,7 +545,7 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i assert(top >= 0 && bottom <= vs->h); // Paranoia checks assert(x >= 0 && width <= vs->pitch); - assert(_charset->_textSurface.pixels); + assert(_textSurface.pixels); assert(_compositeBuf); if (width > vs->w - x) @@ -570,10 +570,10 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i if (_game.version < 7) { // Handle the text mask in older games; newer (V7/V8) games do not use it anymore. - const byte *text = (byte *)_charset->_textSurface.getBasePtr(x, y); + const byte *text = (byte *)_textSurface.getBasePtr(x, y); #ifdef __DS__ - DS::asmDrawStripToScreen(height, width, text, src, dst, vs->pitch, _screenWidth, _charset->_textSurface.pitch); + DS::asmDrawStripToScreen(height, width, text, src, dst, vs->pitch, _screenWidth, _textSurface.pitch); #else // Compose the text over the game graphics for (int h = 0; h < height; ++h) { @@ -585,7 +585,7 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i } src += vs->pitch; dst += _screenWidth; - text += _charset->_textSurface.pitch; + text += _textSurface.pitch; } #endif } else { @@ -904,36 +904,36 @@ void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) { if (vs->hasTwoBuffers && _currentRoom != 0 && isLightOn()) { blit(screenBuf, vs->pitch, vs->getBackPixels(rect.left, rect.top), vs->pitch, width, height); if (vs->number == kMainVirtScreen && _charset->_hasMask) { - byte *mask = (byte *)_charset->_textSurface.getBasePtr(rect.left, rect.top - _screenTop); - fill(mask, _charset->_textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width, height); + byte *mask = (byte *)_textSurface.getBasePtr(rect.left, rect.top - _screenTop); + fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width, height); } } else { fill(screenBuf, vs->pitch, backColor, width, height); } } -void CharsetRenderer::restoreCharsetBg() { - _nextLeft = _vm->_string[0].xpos; - _nextTop = _vm->_string[0].ypos + _vm->_screenTop; +void ScummEngine::restoreCharsetBg() { + _nextLeft = _string[0].xpos; + _nextTop = _string[0].ypos + _screenTop; - if (_hasMask) { - _hasMask = false; - _str.left = -1; - _left = -1; + if (_charset->_hasMask) { + _charset->_hasMask = false; + _charset->_str.left = -1; + _charset->_left = -1; // Restore background on the whole text area. This code is based on // restoreBackground(), but was changed to only restore those parts which are // currently covered by the charset mask. - VirtScreen *vs = &_vm->virtscr[_textScreenID]; + VirtScreen *vs = &virtscr[_charset->_textScreenID]; if (!vs->h) return; - _vm->markRectAsDirty(vs->number, Common::Rect(vs->w, vs->h), USAGE_BIT_RESTORED); + markRectAsDirty(vs->number, Common::Rect(vs->w, vs->h), USAGE_BIT_RESTORED); byte *screenBuf = vs->getPixels(0, 0); - if (vs->hasTwoBuffers && _vm->_currentRoom != 0 && _vm->isLightOn()) { + if (vs->hasTwoBuffers && _currentRoom != 0 && isLightOn()) { if (vs->number != kMainVirtScreen) { // Restore from back buffer const byte *backBuf = vs->getBackPixels(0, 0); @@ -951,11 +951,11 @@ void CharsetRenderer::restoreCharsetBg() { } } -void CharsetRenderer::clearCharsetMask() { - memset(_vm->getResourceAddress(rtBuffer, 9), 0, _vm->_gdi->_imgBufOffs[1]); +void ScummEngine::clearCharsetMask() { + memset(getResourceAddress(rtBuffer, 9), 0, _gdi->_imgBufOffs[1]); } -void CharsetRenderer::clearTextSurface() { +void ScummEngine::clearTextSurface() { memset(_textSurface.pixels, CHARSET_MASK_TRANSPARENCY, _textSurface.pitch * _textSurface.h); } @@ -1098,8 +1098,8 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) { error("can only copy bg to main window"); blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height); if (_charset->_hasMask) { - byte *mask = (byte *)_charset->_textSurface.getBasePtr(x, y - _screenTop); - fill(mask, _charset->_textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width, height); + byte *mask = (byte *)_textSurface.getBasePtr(x, y - _screenTop); + fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width, height); } } else if (_game.heversion == 100) { // Flags are used for different methods in HE games diff --git a/engines/scumm/he/script_v70he.cpp b/engines/scumm/he/script_v70he.cpp index 16bdddb6cd..3faa01ef4e 100644 --- a/engines/scumm/he/script_v70he.cpp +++ b/engines/scumm/he/script_v70he.cpp @@ -784,7 +784,7 @@ void ScummEngine_v70he::o70_kernelSetFunctions() { _skipDrawObject = 0; break; case 23: - _charset->clearCharsetMask(); + clearCharsetMask(); _fullRedraw = true; break; case 24: diff --git a/engines/scumm/he/script_v90he.cpp b/engines/scumm/he/script_v90he.cpp index d5ef7c32f1..031a4a7478 100644 --- a/engines/scumm/he/script_v90he.cpp +++ b/engines/scumm/he/script_v90he.cpp @@ -2594,7 +2594,7 @@ void ScummEngine_v90he::o90_kernelSetFunctions() { _skipDrawObject = 0; break; case 23: - _charset->clearCharsetMask(); + clearCharsetMask(); _fullRedraw = true; break; case 24: diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index 72001625e3..ca513e25d8 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -353,7 +353,7 @@ bool ScummEngine::loadState(int slot, bool compat) { // Reset charset mask _charset->_hasMask = false; - _charset->clearTextSurface(); + clearTextSurface(); _lastCodePtr = NULL; _drawObjectQueNr = 0; diff --git a/engines/scumm/script_v6.cpp b/engines/scumm/script_v6.cpp index af93dbfafb..d2e9a49458 100644 --- a/engines/scumm/script_v6.cpp +++ b/engines/scumm/script_v6.cpp @@ -2650,7 +2650,7 @@ void ScummEngine_v6::o6_kernelSetFunctions() { setShadowPalette(args[3], args[4], args[5], args[1], args[2], 0, 256); break; case 110: - _charset->clearCharsetMask(); + clearCharsetMask(); break; case 111: a = derefActor(args[1], "o6_kernelSetFunctions: 111"); diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 986492633a..622a33b591 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -529,6 +529,8 @@ ScummEngine::~ScummEngine() { delete _costumeLoader; delete _costumeRenderer; + _textSurface.free(); + free(_shadowPalette); free(_palManipPalette); @@ -1074,6 +1076,10 @@ void ScummEngine::setupScumm() { // Create the charset renderer setupCharsetRenderer(); + // Create and clear the text surface + _textSurface.create(_screenWidth, _screenHeight, 1); + clearTextSurface(); + // Create the costume renderer setupCostumeRenderer(); @@ -1324,6 +1330,8 @@ void ScummEngine::resetScumm() { _defaultTalkDelay = 3; _talkDelay = 0; _keepText = false; + _nextLeft = 0; + _nextTop = 0; _currentCursor = 0; _cursor.state = 0; @@ -1732,7 +1740,7 @@ load_game: scummLoop_handleSaveLoad(); if (_completeScreenRedraw) { - _charset->clearCharsetMask(); + clearCharsetMask(); _charset->_hasMask = false; // HACK as in game save stuff isn't supported currently diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index 3fd614edce..f661db08c5 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -1162,6 +1162,13 @@ protected: public: CharsetRenderer *_charset; byte _charsetColorMap[16]; + + /** + * All text is normally rendered into this overlay surface. Then later + * drawStripToScreen() composits it over the game graphics. + */ + Graphics::Surface _textSurface; + protected: byte _charsetColor; byte _charsetData[23][16]; @@ -1171,6 +1178,12 @@ protected: bool _keepText; + int _nextLeft, _nextTop; + + void restoreCharsetBg(); + void clearCharsetMask(); + void clearTextSurface(); + virtual void initCharset(int charset); void printString(int m, const byte *msg); diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp index b4cd07750e..19bac38ba9 100644 --- a/engines/scumm/string.cpp +++ b/engines/scumm/string.cpp @@ -311,7 +311,7 @@ bool ScummEngine::handleNextCharsetCode(Actor *a, int *code) { _charset->setCurID(*buffer++); buffer += 2; memcpy(_charsetColorMap, _charsetData[_charset->getCurID()], 4); - _charset->_nextTop -= _charset->getFontHeight() - oldy; + _nextTop -= _charset->getFontHeight() - oldy; break; default: error("handleNextCharsetCode: invalid code %d", c); @@ -506,18 +506,18 @@ void ScummEngine::CHARSET_1() { if (_game.version >= 7) { #ifndef DISABLE_SCUMM_7_8 ((ScummEngine_v7 *)this)->clearSubtitleQueue(); - _charset->_nextLeft = _string[0].xpos; - _charset->_nextTop = _string[0].ypos; + _nextLeft = _string[0].xpos; + _nextTop = _string[0].ypos; #endif } else { - _charset->restoreCharsetBg(); + restoreCharsetBg(); } } t = _charset->_right - _string[0].xpos - 1; if (_charset->_center) { - if (t > _charset->_nextLeft) - t = _charset->_nextLeft; + if (t > _nextLeft) + t = _nextLeft; t *= 2; } @@ -525,9 +525,9 @@ void ScummEngine::CHARSET_1() { _charset->addLinebreaks(0, _charsetBuffer + _charsetBufPos, 0, t); if (_charset->_center) { - _charset->_nextLeft -= _charset->getStringWidth(0, _charsetBuffer + _charsetBufPos) / 2; - if (_charset->_nextLeft < 0) - _charset->_nextLeft = 0; + _nextLeft -= _charset->getStringWidth(0, _charsetBuffer + _charsetBufPos) / 2; + if (_nextLeft < 0) + _nextLeft = 0; } _charset->_disableOffsX = _charset->_firstChar = !_keepText; @@ -542,7 +542,7 @@ void ScummEngine::CHARSET_1() { if (c == 13) { newLine:; - _charset->_nextLeft = _string[0].xpos; + _nextLeft = _string[0].xpos; #ifndef DISABLE_SCUMM_7_8 if (_game.version >= 7 && subtitleLine != subtitleBuffer) { ((ScummEngine_v7 *)this)->addSubtitleToQueue(subtitleBuffer, subtitlePos, _charsetColor, _charset->getCurID()); @@ -550,15 +550,15 @@ void ScummEngine::CHARSET_1() { } #endif if (_charset->_center) { - _charset->_nextLeft -= _charset->getStringWidth(0, _charsetBuffer + _charsetBufPos) / 2; + _nextLeft -= _charset->getStringWidth(0, _charsetBuffer + _charsetBufPos) / 2; } if (_game.version == 0) { break; } else if (!(_game.platform == Common::kPlatformFMTowns) && _string[0].height) { - _charset->_nextTop += _string[0].height; + _nextTop += _string[0].height; } else { - _charset->_nextTop += _charset->getFontHeight(); + _nextTop += _charset->getFontHeight(); } if (_game.version > 3) { // FIXME - is this really needed? @@ -568,16 +568,16 @@ void ScummEngine::CHARSET_1() { } // Handle line overflow for V3. See also bug #1306269. - if (_game.version == 3 && _charset->_nextLeft >= _screenWidth) { - _charset->_nextLeft = _screenWidth; + if (_game.version == 3 && _nextLeft >= _screenWidth) { + _nextLeft = _screenWidth; } // Handle line breaks for V1-V2 - if (_game.version <= 2 && _charset->_nextLeft >= _screenWidth) { + if (_game.version <= 2 && _nextLeft >= _screenWidth) { goto newLine; } - _charset->_left = _charset->_nextLeft; - _charset->_top = _charset->_nextTop; + _charset->_left = _nextLeft; + _charset->_top = _nextTop; if (_game.version >= 7) { #ifndef DISABLE_SCUMM_7_8 @@ -614,8 +614,8 @@ void ScummEngine::CHARSET_1() { _charset->printChar(c, false); } } - _charset->_nextLeft = _charset->_left; - _charset->_nextTop = _charset->_top; + _nextLeft = _charset->_left; + _nextTop = _charset->_top; } if (_game.version <= 2) { @@ -695,8 +695,6 @@ void ScummEngine::drawString(int a, const byte *msg) { _charset->_left -= _charset->getStringWidth(a, buf) / 2; } - const bool ignoreCharsetMask = (_game.version < 7); - if (!buf[0]) { buf[0] = ' '; buf[1] = 0; @@ -732,7 +730,7 @@ void ScummEngine::drawString(int a, const byte *msg) { _charset->_left = _charset->_startLeft; } if (!(_game.platform == Common::kPlatformFMTowns) && _string[0].height) { - _charset->_nextTop += _string[0].height; + _nextTop += _string[0].height; } else { _charset->_top += fontHeight; } @@ -774,7 +772,7 @@ void ScummEngine::drawString(int a, const byte *msg) { } } } - _charset->printChar(c, ignoreCharsetMask); + _charset->printChar(c, (_game.version < 7)); _charset->_blitAlso = false; if (cmi_pos_hack) { @@ -785,8 +783,8 @@ void ScummEngine::drawString(int a, const byte *msg) { } if (a == 0) { - _charset->_nextLeft = _charset->_left; - _charset->_nextTop = _charset->_top; + _nextLeft = _charset->_left; + _nextTop = _charset->_top; } _string[a].xpos = _charset->_str.right + 8; // Indy3: Fixes Grail Diary text positioning |