void Sprite::getScaledSpriteBuffer(SpriteList &spriteList, uint spriteNumber, int scale, int &width, int &height, int &xAlign, int &yAlign, const byte *&buffer) { SpriteInfo *spriteInfo; if (spriteList.size() <= spriteNumber) { // this can occur in IHNM while loading a saved game from chapter 1-5 when being in the end chapter warning("spriteList.size() <= spriteNumber"); return; } spriteInfo = &spriteList[spriteNumber]; if (scale < 256) { xAlign = (spriteInfo->xAlign * scale) >> 8; //TODO: do we need to take in account sprite x&y aligns ? yAlign = (spriteInfo->yAlign * scale) >> 8; // ???? height = (spriteInfo->height * scale + 0x7f) >> 8; width = (spriteInfo->width * scale + 0x7f) >> 8; size_t outLength = width * height; if (outLength > 0) { scaleBuffer(&spriteInfo->decodedBuffer.front(), spriteInfo->width, spriteInfo->height, scale, outLength); buffer = &_decodeBuf.front(); } else { buffer = NULL; } } else {
void Sprite::loadList(int resourceId, SpriteList &spriteList) { SpriteInfo *spriteInfo; ByteArray spriteListData; uint16 oldSpriteCount; uint16 newSpriteCount; uint16 spriteCount; uint i; int outputLength, inputLength; uint32 offset; const byte *spritePointer; const byte *spriteDataPointer; _vm->_resource->loadResource(_spriteContext, resourceId, spriteListData); if (spriteListData.empty()) { return; } ByteArrayReadStreamEndian readS(spriteListData, _spriteContext->isBigEndian()); spriteCount = readS.readUint16(); debug(9, "Sprites: %d", spriteCount); oldSpriteCount = spriteList.size(); newSpriteCount = oldSpriteCount + spriteCount; spriteList.resize(newSpriteCount); bool bigHeader = _vm->getGameId() == GID_IHNM || _vm->isMacResources(); for (i = oldSpriteCount; i < spriteList.size(); i++) { spriteInfo = &spriteList[i]; if (bigHeader) offset = readS.readUint32(); else offset = readS.readUint16(); if (offset >= spriteListData.size()) { // ITE Mac demos throw this warning warning("Sprite::loadList offset exceeded"); spriteList.resize(i); return; } spritePointer = spriteListData.getBuffer(); spritePointer += offset; if (bigHeader) { Common::MemoryReadStreamEndian readS2(spritePointer, 8, _spriteContext->isBigEndian()); spriteInfo->xAlign = readS2.readSint16(); spriteInfo->yAlign = readS2.readSint16(); spriteInfo->width = readS2.readUint16(); spriteInfo->height = readS2.readUint16(); spriteDataPointer = spritePointer + readS2.pos(); } else { Common::MemoryReadStreamEndian readS2(spritePointer, 4, false); spriteInfo->xAlign = readS2.readSByte(); spriteInfo->yAlign = readS2.readSByte(); spriteInfo->width = readS2.readByte(); spriteInfo->height = readS2.readByte(); spriteDataPointer = spritePointer + readS2.pos(); } outputLength = spriteInfo->width * spriteInfo->height; inputLength = spriteListData.size() - (spriteDataPointer - spriteListData.getBuffer()); spriteInfo->decodedBuffer.resize(outputLength); if (outputLength > 0) { decodeRLEBuffer(spriteDataPointer, inputLength, outputLength); byte *dst = &spriteInfo->decodedBuffer.front(); #ifdef ENABLE_IHNM // IHNM sprites are upside-down, for reasons which i can only // assume are perverse. To simplify things, flip them now. Not // at drawing time. if (_vm->getGameId() == GID_IHNM) { byte *src = &_decodeBuf[spriteInfo->width * (spriteInfo->height - 1)]; for (int j = 0; j < spriteInfo->height; j++) { memcpy(dst, src, spriteInfo->width); src -= spriteInfo->width; dst += spriteInfo->width; } } else #endif memcpy(dst, &_decodeBuf.front(), outputLength); } } }