diff options
Diffstat (limited to 'engines/kyra/text_lol.cpp')
-rw-r--r-- | engines/kyra/text_lol.cpp | 573 |
1 files changed, 573 insertions, 0 deletions
diff --git a/engines/kyra/text_lol.cpp b/engines/kyra/text_lol.cpp new file mode 100644 index 0000000000..fe7ac6d81d --- /dev/null +++ b/engines/kyra/text_lol.cpp @@ -0,0 +1,573 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "kyra/lol.h" +#include "kyra/screen_lol.h" +#include "kyra/util.h" + +namespace Kyra { + +TextDisplayer_LoL::TextDisplayer_LoL(LoLEngine *vm, Screen_LoL *screen) : _vm(vm), _screen(screen), + _scriptParameter(0), _stringLength(0), _animWidth(0), _animColour1(0), _animColour2(0), _animFlag(true), + _printFlag(false), _lineWidth(0), _numChars(0), _numCharsPrinted(0), _posX(0), _posY(0), _colour1(0), _colour2(0) { + + memset(_stringParameters, 0, 15 * sizeof(char*)); + _buffer = new char[600]; + memset(_buffer, 0, 600); + + _out = new char[1024]; + memset(_out, 0, 1024); + + _backupBuffer = new char[40]; + memset(_out, 0, 40); + + _currentLine = new char[85]; + memset(_out, 0, 85); + + _pageBuffer1 = new uint8[0xfa00]; + _pageBuffer2 = new uint8[0xfa00]; +} + +TextDisplayer_LoL::~TextDisplayer_LoL() { + delete[] _buffer; + delete[] _out; + delete[] _backupBuffer; + delete[] _currentLine; + delete[] _pageBuffer1; + delete[] _pageBuffer2; +} + +void TextDisplayer_LoL::setupField(bool mode) { + if (_vm->textEnabled()) { + if (mode) { + _screen->copyRegionToBuffer(3, 0, 0, 320, 200, _pageBuffer1); + _screen->copyRegion(80, 142, 0, 0, 240, 37, 0, 3, Screen::CR_NO_P_CHECK); + _screen->copyRegionToBuffer(3, 0, 0, 320, 200, _pageBuffer2); + _screen->copyBlockToPage(3, 0, 0, 320, 200, _pageBuffer1); + } else { + _screen->clearDim(4); + int cp = _screen->setCurPage(2); + _screen->copyRegionToBuffer(3, 0, 0, 320, 200, _pageBuffer1); + _screen->copyBlockToPage(3, 0, 0, 320, 200, _pageBuffer2); + _screen->copyRegion(80, 142, 0, 0, 240, 37, 3, 2, Screen::CR_NO_P_CHECK); + + for (int i = 177; i > 141; i--) { + uint32 endTime = _vm->_system->getMillis() + _vm->_tickLength; + _screen->hideMouse(); + _screen->copyRegion(83, i, 83, i - 1, 235, 3, 0, 0, Screen::CR_NO_P_CHECK); + _screen->copyRegion(83, i + 1, 83, i + 1, 235, 1, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + _screen->showMouse(); + _vm->delayUntil(endTime); + } + + _screen->copyBlockToPage(3, 0, 0, 320, 200, _pageBuffer1); + _screen->setCurPage(cp); + + _vm->_updateFlags &= 0xfffd; + } + } else { + if (!mode) + _screen->clearDim(4); + _vm->toggleSelectedCharacterFrame(1); + } +} + +void TextDisplayer_LoL::expandField() { + if (_vm->textEnabled()) { + _vm->_restorePalette = 0; + _vm->_updateCharV4 = 0; + //_vm->toggleGuiUnk(11, 0); + _screen->clearDim(3); + _screen->copyRegionToBuffer(3, 0, 0, 320, 200, _pageBuffer1); + _screen->copyRegion(83, 140, 0, 0, 235, 3, 0, 2, Screen::CR_NO_P_CHECK); + + for (int i = 140; i < 177; i++) { + uint32 endTime = _vm->_system->getMillis() + _vm->_tickLength; + _screen->hideMouse(); + _screen->copyRegion(0, 0, 83, i, 235, 3, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + _screen->showMouse(); + _vm->delayUntil(endTime); + } + + _screen->copyBlockToPage(3, 0, 0, 320, 200, _pageBuffer1); + _vm->_updateFlags |= 2; + + } else { + _screen->clearDim(3); + _vm->toggleSelectedCharacterFrame(0); + } +} +void TextDisplayer_LoL::setAnimParameters(const char *str, int x, uint8 col1, uint8 col2) { + static const char defaultStr[] = "<MORE>"; + + if (str) { + _animString = str; + _animWidth = x; + _animColour1 = col1; + _animColour2 = col2; + } else { + _animString = defaultStr; + _animWidth = 7; + _animColour1 = 0; + _animColour2 = 0; + } +} + +void TextDisplayer_LoL::play(int dim, char *str, EMCState *script, int16 *paramList, int16 paramIndex) { + memcpy(_curPara, _stringParameters, 15 * sizeof(char*)); + char *cmds = _curPara[0]; + + if (dim == 3) { + if (_vm->_updateFlags & 2) { + _screen->clearDim(4); + dim = _screen->curDimIndex(); + _colour1 = 254; + } else { + _screen->clearDim(3); + dim = _screen->curDimIndex(); + _colour1 = 192; + uint8 col[3]; + _screen->loadColour254(col); + _screen->setPaletteIndex(192, col[0], col[1], col[2]); + //toggleGuiUnk(11, 1); + _vm->_updateCharV4 = 0; + _vm->_restorePalette = 0; + } + + } else { + _screen->setScreenDim(dim); + _colour1 = 254; + } + + int cp = _screen->setCurPage(0); + Screen::FontId of = _screen->setFont(Screen::FID_9_FNT); + + memset(_backupBuffer, 0, 40); + + if (preprocessString(str, script, paramList, paramIndex)) { + vsnprintf(_out, 1024, str, cmds); + _stringLength = strlen(_out); + displayText(_out); + } else { + _stringLength = strlen(str); + displayText(str); + displayText(str); + } + + for (int i = 0; i < 10; i++) { + if (!_backupBuffer[i << 1]) + break; + str[_backupBuffer[(i << 1) + 1]] = _backupBuffer[i << 1]; + } + + _screen->setScreenDim(dim); + _screen->setCurPage(cp); + _screen->setFont(of); + + _vm->_restorePalette = 0; +} + +bool TextDisplayer_LoL::preprocessString(char *str, EMCState *script, int16 *paramList, int16 paramIndex) { + int cnt = 0; + bool res = false; + char *tmpd = _buffer; + char **cmds = _curPara; + + for (char *s = str; *s;) { + if (*s++ != '%') + continue; + + char pos = *s; + char para1 = 0; + bool eos = false; + + switch (pos) { + case '\0': + eos = true; + break; + case '#': + para1 = *++s; + switch (para1) { + case 'E': + case 'G': + case 'X': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 's': + case 'u': + case 'x': + break; + default: + eos = true; + break; + } + break; + case ' ': + case '+': + case '-': + ++s; + default: + break; + } + + if (eos) + continue; + + char para2 = *s; + + switch (para2) { + case '\0': + eos = true; + break; + case '0': + ++s; + break; + default: + while(para2 && para2 > 47 && para2 < 58) + para2 = *++s; + break; + } + + if (eos) + continue; + + char para3 = *++s; + + switch (para3) { + case 'a': + _backupBuffer[cnt++] = para3; + _backupBuffer[cnt++] = (int16) (s - str); + snprintf(tmpd, 7, "%d", _scriptParameter); + *cmds++ = tmpd; + tmpd += strlen(tmpd) + 1; + res = true; + *s++ = 's'; + break; + + case 'n': + _backupBuffer[cnt++] = para3; + _backupBuffer[cnt++] = (int16) (s - str); + *cmds++ = _vm->_characters[script ? script->stack[script->sp + paramIndex] : paramList[paramIndex]].name; + paramIndex++; + res = true; + *s++ = 's'; + break; + + case 's': + *cmds++ = _vm->getLangString(script ? script->stack[script->sp + paramIndex] : paramList[paramIndex]); + paramIndex++; + res = true; + s++; + break; + + case 'X': + case 'd': + case 'u': + case 'x': + snprintf(tmpd, 7, "%d", script ? script->stack[script->sp + paramIndex] : paramList[paramIndex]); + *cmds++ = tmpd; + tmpd += strlen(tmpd) + 1; + paramIndex++; + res = true; + *s++ = 's'; + break; + + case '\0': + default: + continue; + } + } + + return res; +} + +void TextDisplayer_LoL::displayText(char *str, ...) { + _printFlag = false; + + _lineWidth = 0; + _numChars = 0; + _numCharsPrinted = 0; + + _tempString1 = str; + _tempString2 = 0; + + _currentLine[0] = 0; + + memset(_ctrl, 0, 3); + + _colour1 = _screen->_curDim->unk8; + _colour2 = _screen->_curDim->unkA; + _posX = _screen->_curDim->unkC; + _posY = _screen->_curDim->unkE; + + char c = parseCommand(); + + va_list args; + va_start(args, str); + + const ScreenDim *sd = _screen->_curDim; + + while (c) { + char a = tolower(_ctrl[1]); + + if (!_tempString2 && c == '%' ) { + if (a == 'd') { + snprintf(_scriptParaString, 11, "%d", va_arg(args, int)); + _tempString2 = _scriptParaString; + } else if (a == 's') { + _tempString2 = va_arg(args, char*); + } else { + break; + } + + _ctrl[0] = _ctrl[2]; + _ctrl[2] = _ctrl[1] = 0; + c = parseCommand(); + } + + switch (c - 1) { + case 0: + printLine(_currentLine); + //if (!_dlgAnimCallback) + // break; + + portraitAnimation2(); + _numCharsPrinted = 0; + break; + + case 1: + printLine(_currentLine); + _colour2 = parseCommand(); + break; + + case 5: + printLine(_currentLine); + _colour1 = parseCommand(); + break; + + case 8: + //TODO + break; + + case 11: + //TODO + break; + + case 12: + printLine(_currentLine); + _screen->_dimLineCount++; + _posX = 0; + _posY++; + break; + + case 18: + //TODO + break; + + case 23: + //TODO + break; + + case 24: + //TODO + break; + + case 26: + //TODO + break; + + case 28: + //TODO + break; + + default: + _lineWidth += _screen->getCharWidth(c); + _currentLine[_numChars++] = c; + _currentLine[_numChars] = 0; + + if ((_posX + _lineWidth) > (sd->w << 3)) + printLine(_currentLine); + + break; + } + + c = parseCommand(); + } + + va_end(args); + + if (_numChars) + printLine(_currentLine); +} + +char TextDisplayer_LoL::parseCommand() { + if (!_ctrl[1]) + readNextPara(); + + char res = _ctrl[1]; + _ctrl[1] = _ctrl[2]; + _ctrl[2] = 0; + + if (!_ctrl[1]) + readNextPara(); + + return res; +} + +void TextDisplayer_LoL::readNextPara() { + char d = 0; + + if (_tempString2) { + if (*_tempString2) { + d = *_tempString2++; + } else { + _tempString2 = 0; + d = _ctrl[0]; + } + } + + if (!d && _tempString1) { + if (*_tempString1) + d = *_tempString1++; + else + _tempString1 = 0; + } + + _ctrl[1] = d; + _ctrl[2] = 0; +} + +void TextDisplayer_LoL::printLine(char *str) { + const ScreenDim *sd = _screen->_curDim; + + int fh = (_screen->getFontHeight() + _screen->_charOffset); + int lines = (sd->h - _screen->_charOffset) / fh; + + while (_posY >= lines) { + if (lines <= _screen->_dimLineCount && _animFlag) { + _screen->_dimLineCount = 0; + //if (_dlgAnimCallback) { + portraitAnimation2(); + _numCharsPrinted = 0; + //} + } + + int h1 = ((sd->h / fh) - 1) * fh; + int h2 = sd->h - fh; + + if (h2) + _screen->copyRegion(sd->sx << 3, sd->sy + fh, sd->sx << 3, sd->sy, sd->w << 3, h2, _screen->_curPage, _screen->_curPage, Screen::CR_NO_P_CHECK); + + _screen->fillRect(sd->sx << 3, sd->sy + h1, (sd->sx + sd->w - 1) << 3, sd->sy + sd->h - 1, _colour2); + + _posY--; + } + + int x1 = (sd->sx << 3) + _posX; + int y = sd->sy + fh * _posY; + int w = sd->w << 3; + int lw = _lineWidth; + int s = _numChars; + char c = 0; + + if ((lw + _posX) > w) { + if ((lines - 1) <= _screen->_dimLineCount && _animFlag) + w -= (_animWidth * (_screen->getFontWidth() + _screen->_charWidth)); + + w -= _posX; + + int n2 = 0; + int n1 = s - 1; + + while (n1 > 0) { + //cut off line after last space + c = str[n1]; + lw -= _screen->getCharWidth(c); + + if (!n2 && lw <= w) + n2 = n1; + + if (n2 && c == ' ') { + s = n1; + _printFlag = false; + break; + } + + n1--; + } + + if (!n1) { + if (_posX && !_printFlag) { + s = lw = 0; + _printFlag = true; + } else { + s = n2; + } + } + } + + c = str[s]; + str[s] = 0; + + _screen->printText(str, x1, y, _colour1, _colour2); + _posX += lw; + _numCharsPrinted += strlen(str); + + str[s] = c; + + if (c == ' ') + s++; + + if (str[s] == ' ') + s++; + + strcpy(str, &str[s]); + _numChars = strlen(str); + _lineWidth = _screen->getTextWidth(str); + + if (!_numChars && _posX < (sd->w << 3)) + return; + + _posX = 0; + _posY++; + _screen->_dimLineCount++; + + printLine(str); +} + +/*void TextDisplayer_LoL::portraitAnimation1(const char *str, uint16 lineWidth, uint8 col1, uint8 col2, uint16 numCharsPrinted) { + +}*/ + +void TextDisplayer_LoL::portraitAnimation2() { + // TODO +} + +} // end of namespace Kyra |