/** * Load Sprite Bank */ int AnimationManager::loadSpriteBank(int idx, const Common::String &filename) { int result = 0; Bank[idx]._loadedFl = true; Bank[idx]._filename = filename; byte *fileDataPtr = _vm->_fileIO->loadFile(filename); Bank[idx]._fileHeader = 0; if (fileDataPtr[1] == 'L' && fileDataPtr[2] == 'E') Bank[idx]._fileHeader = 1; else if (fileDataPtr[1] == 'O' && fileDataPtr[2] == 'R') Bank[idx]._fileHeader = 2; if (!Bank[idx]._fileHeader) { _vm->_globals->freeMemory(fileDataPtr); Bank[idx]._loadedFl = false; result = -1; } Bank[idx]._data = fileDataPtr; int objectDataIdx = 0; for(objectDataIdx = 0; objectDataIdx <= 249; objectDataIdx++) { int width = _vm->_objectsMan->getWidth(fileDataPtr, objectDataIdx); int height = _vm->_objectsMan->getHeight(fileDataPtr, objectDataIdx); if (!width && !height) break; } if (objectDataIdx > 249) { _vm->_globals->freeMemory(fileDataPtr); Bank[idx]._loadedFl = false; result = -2; } Bank[idx]._objDataIdx = objectDataIdx; Common::String ofsFilename = Bank[idx]._filename; char ch; do { ch = ofsFilename.lastChar(); ofsFilename.deleteLastChar(); } while (ch != '.'); ofsFilename += ".OFS"; Common::File f; if (f.exists(ofsFilename)) { byte *ofsData = _vm->_fileIO->loadFile(ofsFilename); byte *curOfsData = ofsData; for (int objIdx = 0; objIdx < Bank[idx]._objDataIdx; ++objIdx, curOfsData += 8) { int x1 = READ_LE_INT16(curOfsData); int y1 = READ_LE_INT16(curOfsData + 2); int x2 = READ_LE_INT16(curOfsData + 4); int y2 = READ_LE_INT16(curOfsData + 6); _vm->_objectsMan->setOffsetXY(Bank[idx]._data, objIdx, x1, y1, 0); if (Bank[idx]._fileHeader == 2) _vm->_objectsMan->setOffsetXY(Bank[idx]._data, objIdx, x2, y2, 1); } _vm->_globals->freeMemory(ofsData); result = 0; } return result; }
// Box void FontManager::box(int idx, int messageId, const Common::String &filename, int xp, int yp) { int textPosX = xp; if (idx < 0) error("Bad number for text"); _fontFixedWidth = 11; _boxWidth = 11 * _text[idx]._length; if (_text[idx]._textLoadedFl) { int textType = _text[idx]._textType; if (textType != 6 && textType != 1 && textType != 3 && textType != 5) { int yCurrent = yp + 5; for (int lineNum = 0; lineNum < _text[idx]._lineCount; ++lineNum) { displayText(xp + 5, yCurrent, _text[idx]._lines[lineNum], _text[idx]._color); yCurrent += _fontFixedHeight + 1; } } else { int height = _text[idx]._height; int width = _text[idx]._width; _vm->_graphicsMan->restoreSurfaceRect( _vm->_graphicsMan->_frontBuffer, _text[idx]._textBlock, xp, yp, _text[idx]._width, _text[idx]._height); _vm->_graphicsMan->addDirtyRect(xp, yp, xp + width, yp + height); } } else { int lineCount = 0; for (int i = 0; i <= 19; i++) _textSortArray[i] = 0; _text[idx]._textLoadedFl = true; Common::String file = filename; if (strncmp(file.c_str(), _oldName.c_str(), strlen(file.c_str())) != 0) { // Starting to access a new file, so read in the index file for the file _oldName = file; _indexName = Common::String(file.c_str(), file.size() - 3); _indexName += "IND"; Common::File f; if (!f.open(_indexName)) error("Error opening file - %s", _indexName.c_str()); int filesize = f.size(); for (int i = 0; i < (filesize / 4); ++i) _index[i] = f.readUint32LE(); f.close(); } int bufSize; if (filename[0] != 'Z' || filename[1] != 'O') { Common::File f; if (!f.open(file)) error("Error opening file - %s", _indexName.c_str()); bufSize = 2048; f.seek(_index[messageId]); _tempText = _vm->_globals->allocMemory(2058); if (_tempText == NULL) error("Error allocating text"); Common::fill(&_tempText[0], &_tempText[2058], 0); f.read(_tempText, 2048); f.close(); } else { bufSize = 100; _tempText = _vm->_globals->allocMemory(110); Common::fill(&_tempText[0], &_tempText[110], 0); memcpy(_tempText, _zoneText + _index[messageId], 96); WRITE_LE_UINT16((uint16 *)_tempText + 48, READ_LE_INT16(_zoneText + _index[messageId] + 96)); } byte *curTempTextPtr = _tempText; for (int i = 0; i < bufSize; i++) { byte curChar = *curTempTextPtr; if ((byte)(*curTempTextPtr + 46) > 27) { if ((byte)(curChar + 80) > 27) { if ((byte)(curChar - 65) <= 25 || (byte)(curChar - 97) <= 25) curChar = 32; } else { curChar -= 79; } } else { curChar += 111; } *curTempTextPtr = curChar; curTempTextPtr++; }; int textLength; for (textLength = 0; textLength < bufSize; textLength++) { byte curChar = _tempText[textLength]; if (curChar == '\r' || curChar == '\n') { _tempText[textLength] = 0; if (!_text[idx]._length) break; } } if (bufSize && bufSize > textLength) { _text[idx]._length = textLength; _boxWidth = 0; for (int curStrIdx = 0; curStrIdx < textLength + 1; curStrIdx++) { byte curChar = _tempText[curStrIdx]; if (curChar <= 31) curChar = ' '; _boxWidth += _vm->_objectsMan->getWidth(_font, curChar - 32); } _boxWidth += 2; _text[idx]._pos.x = 320 - abs(_boxWidth / 2); textPosX = _vm->_events->_startPos.x + _text[idx]._pos.x; lineCount = 1; _text[idx]._lines[0] = Common::String((const char *)_tempText, textLength); } else { if (!_boxWidth) _boxWidth = 240; int tempTextIdx = 0; int lineSize; byte curChar; do { int curLineSize = 0; int ptrb = _boxWidth - 4; for (;;) { lineSize = curLineSize; do { curChar = _tempText[tempTextIdx + curLineSize++]; } while (curChar != ' ' && curChar != '%'); if (curLineSize >= ptrb / _fontFixedWidth) { if (curChar == '%') curChar = ' '; break; } if (curChar == '%') { lineSize = curLineSize; break; } } // WORKAROUND: Perhaps due to the usage of ScummVM strings here, recalculate what the // actual length of the line to be copied will be. Otherwise, you can see artifacts, // such as a single character beyond the end of string NULL. int actualSize = 0; while (actualSize < lineSize && _tempText[tempTextIdx + actualSize]) ++actualSize; _text[idx]._lines[lineCount] = Common::String((const char *)_tempText + tempTextIdx, actualSize); _textSortArray[lineCount++] = lineSize; tempTextIdx += lineSize; } while (curChar != '%'); for (int i = 0; i <= 19; i++) { if (_textSortArray[i] <= 0) { _textSortArray[i] = 0; } else { int ptrc = 0; for (int curIdx = 0; curIdx < _textSortArray[i] - 1; curIdx++) { Common::String &line = _text[idx]._lines[i]; byte curChar2 = (curIdx >= (int)line.size()) ? '\0' : line.c_str()[curIdx]; if (curChar2 <= 31) curChar2 = ' '; ptrc += _vm->_objectsMan->getWidth(_font, (byte)curChar2 - 32); } _textSortArray[i] = ptrc; } } for (int i = 0; i <= 19; i++) { for (int j = i + 1; j != i; j = (j + 1) % 20) { if (_textSortArray[i] < _textSortArray[j]) _textSortArray[i] = 0; } }; for (int i = 0; i <= 19; i++) { if (_textSortArray[i]) _boxWidth = _textSortArray[i]; } if ((_text[idx]._textType < 2) || (_text[idx]._textType > 3)) { int i; for (i = xp - _vm->_events->_startPos.x; _boxWidth + i > 638 && i > -2 && _text[idx]._textType; i -= 2) ; _text[idx]._pos.x = i; textPosX = _vm->_events->_startPos.x + i; } else { _text[idx]._pos.x = textPosX; } } int posX = textPosX; int posY = yp; int saveWidth = _boxWidth + 10; int saveHeight = (_fontFixedHeight + 1) * lineCount + 12; if (_text[idx]._textType == 6) { _text[idx]._pos.x = 315 - abs(saveWidth / 2); textPosX = posX = _vm->_events->_startPos.x + _text[idx]._pos.x; _text[idx]._pos.y = posY = 50; } int textType = _text[idx]._textType; if (textType == 1 || textType == 3 || textType == 5 || textType == 6) { int size = saveHeight * saveWidth; byte *ptrd = _vm->_globals->allocMemory(size); if (ptrd == NULL) error("Cutting a block for text box (%d)", size); _vm->_graphicsMan->copySurfaceRect(_vm->_graphicsMan->_frontBuffer, ptrd, posX, posY, saveWidth, saveHeight); _vm->_graphicsMan->fillSurface(ptrd, _vm->_graphicsMan->_colorTable, size); _vm->_graphicsMan->restoreSurfaceRect(_vm->_graphicsMan->_frontBuffer, ptrd, posX, posY, saveWidth, saveHeight); _vm->_globals->freeMemory(ptrd); _vm->_graphicsMan->drawHorizontalLine(_vm->_graphicsMan->_frontBuffer, posX, posY, saveWidth, (byte)-2); _vm->_graphicsMan->drawHorizontalLine(_vm->_graphicsMan->_frontBuffer, posX, saveHeight + posY, saveWidth, (byte)-2); _vm->_graphicsMan->drawVerticalLine(_vm->_graphicsMan->_frontBuffer, posX, posY, saveHeight, (byte)-2); _vm->_graphicsMan->drawVerticalLine(_vm->_graphicsMan->_frontBuffer, saveWidth + posX, posY, saveHeight, (byte)-2); } _text[idx]._lineCount = lineCount; int textPosY = posY + 5; for (int lineNum = 0; lineNum < lineCount; ++lineNum) { displayText(textPosX + 5, textPosY, _text[idx]._lines[lineNum], _text[idx]._color); textPosY += _fontFixedHeight + 1; } int blockWidth = saveWidth + 1; int blockHeight = saveHeight + 1; _text[idx]._width = blockWidth; _text[idx]._height = blockHeight; textType = _text[idx]._textType; if (textType == 6 || textType == 1 || textType == 3 || textType == 5) { _text[idx]._textBlock = _vm->_globals->freeMemory(_text[idx]._textBlock); int blockSize = blockHeight * blockWidth; byte *ptre = _vm->_globals->allocMemory(blockSize + 20); if (ptre == NULL) error("Cutting a block for text box (%d)", blockSize); _text[idx]._textBlock = ptre; _text[idx]._width = blockWidth; _text[idx]._height = blockHeight; _vm->_graphicsMan->copySurfaceRect(_vm->_graphicsMan->_frontBuffer, _text[idx]._textBlock, posX, posY, _text[idx]._width, blockHeight); } _tempText = _vm->_globals->freeMemory(_tempText); } }