mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 05:38:56 +00:00
SAGA: Support decoding AGA and ECS graphics
This commit is contained in:
parent
8ff65b22cc
commit
ee8151e007
@ -389,7 +389,7 @@ void Anim::load(uint16 animId, const ByteArray &resourceData) {
|
||||
} else
|
||||
anim = _animations[animId] = new AnimationData();
|
||||
|
||||
ByteArrayReadStreamEndian headerReadS(resourceData, _vm->isBigEndian());
|
||||
ByteArrayReadStreamEndian headerReadS(resourceData, _vm->isBigEndian() && !_vm->isAGA() && !_vm->isECS());
|
||||
anim->magic = headerReadS.readUint16LE(); // cause ALWAYS LE
|
||||
anim->screenWidth = headerReadS.readUint16();
|
||||
anim->screenHeight = headerReadS.readUint16();
|
||||
@ -689,6 +689,70 @@ void Anim::decodeFrame(AnimationData *anim, size_t frameOffset, byte *buf, size_
|
||||
#define VALIDATE_WRITE_POINTER
|
||||
#endif
|
||||
|
||||
if (_vm->isAGA() || _vm->isECS()) {
|
||||
int curY = 0, curX = 0;
|
||||
unsigned realY;
|
||||
unsigned outbit;
|
||||
// TODO: Check if we want to use tempaltes instead to optimize AGA case
|
||||
unsigned int pixelSize = _vm->isAGA() ? 8 : 5;
|
||||
while (1) {
|
||||
markByte = readS.readByte();
|
||||
if (markByte == SAGA_FRAME_AMIGA_END)
|
||||
break;
|
||||
if (markByte == SAGA_FRAME_AMIGA_START) {
|
||||
xStart = readS.readByte();
|
||||
yStart = readS.readUint16BE();
|
||||
/* int xPos = */ readS.readUint16BE();
|
||||
/* int yPos = */ readS.readUint16BE();
|
||||
/* int width = */ readS.readUint16BE();
|
||||
/*int height = */ readS.readUint16BE();
|
||||
curX = xStart;
|
||||
curY = yStart;
|
||||
realY = curY / pixelSize;
|
||||
outbit = curY % pixelSize;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8 param = markByte & SAGA_FRAME_AMIGA_PARAM_MASK;
|
||||
|
||||
switch (markByte & SAGA_FRAME_AMIGA_OPCODE_MASK) {
|
||||
case SAGA_FRAME_AMIGA_OPCODE_LITERAL:
|
||||
for (i = 0; i < param + 1; i++, curX++) {
|
||||
byte b = readS.readByte();
|
||||
for (unsigned inbit = 0;inbit < 8; inbit++) {
|
||||
unsigned realX = (curX << 3) + 7 - inbit;
|
||||
if (realX < screenWidth && realY < screenHeight) {
|
||||
buf[realX + realY * screenWidth] =
|
||||
(buf[realX + realY * screenWidth] & (~(1 << outbit))) | (((b >> inbit) & 1) << outbit);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
||||
case SAGA_FRAME_AMIGA_OPCODE_TRANSPARENT:
|
||||
curX += param;
|
||||
continue;
|
||||
|
||||
case SAGA_FRAME_AMIGA_OPCODE_NEWLINE:
|
||||
curY++;
|
||||
curX = param;
|
||||
outbit++;
|
||||
if (outbit >= pixelSize) {
|
||||
outbit -= pixelSize;
|
||||
realY++;
|
||||
}
|
||||
continue;
|
||||
case SAGA_FRAME_AMIGA_OPCODE_REPOSITION:
|
||||
curY = readS.readUint16BE();
|
||||
realY = curY / pixelSize;
|
||||
outbit = curY % pixelSize;
|
||||
curX = param;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Begin RLE decompression to output buffer
|
||||
do {
|
||||
@ -815,6 +879,44 @@ int Anim::fillFrameOffsets(AnimationData *anim, bool reallyFill) {
|
||||
|
||||
Common::MemoryReadStreamEndian readS(&anim->resourceData.front(), anim->resourceData.size(), !_vm->isBigEndian()); // RLE has inversion BE<>LE
|
||||
|
||||
if (_vm->isAGA() || _vm->isECS()) {
|
||||
while (readS.pos() != readS.size()) {
|
||||
if (reallyFill) {
|
||||
anim->frameOffsets[currentFrame] = readS.pos();
|
||||
|
||||
if (currentFrame == anim->maxFrame) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
currentFrame++;
|
||||
|
||||
while (1) {
|
||||
markByte = readS.readByte();
|
||||
|
||||
// debug(7, "_pos=%X currentFrame=%i markByte=%X", (int) readS.pos(), (int) currentFrame, (int) markByte);
|
||||
if (markByte == SAGA_FRAME_AMIGA_END)
|
||||
break;
|
||||
if (markByte == SAGA_FRAME_AMIGA_START) {
|
||||
readS.seek(11, SEEK_CUR);
|
||||
continue;
|
||||
}
|
||||
switch (markByte & SAGA_FRAME_AMIGA_OPCODE_MASK) {
|
||||
case SAGA_FRAME_AMIGA_OPCODE_LITERAL:
|
||||
readS.seek((markByte & SAGA_FRAME_AMIGA_PARAM_MASK) + 1, SEEK_CUR);
|
||||
continue;
|
||||
|
||||
case SAGA_FRAME_AMIGA_OPCODE_TRANSPARENT:
|
||||
case SAGA_FRAME_AMIGA_OPCODE_NEWLINE:
|
||||
continue;
|
||||
case SAGA_FRAME_AMIGA_OPCODE_REPOSITION:
|
||||
readS.readSint16BE();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return currentFrame;
|
||||
}
|
||||
|
||||
while (readS.pos() != readS.size()) {
|
||||
if (reallyFill) {
|
||||
anim->frameOffsets[currentFrame] = readS.pos();
|
||||
|
@ -40,6 +40,15 @@ namespace Saga {
|
||||
#define SAGA_FRAME_UNCOMPRESSED_RUN 0x40
|
||||
#define SAGA_FRAME_EMPTY_RUN 0xC0
|
||||
|
||||
#define SAGA_FRAME_AMIGA_OPCODE_REPOSITION 0x00
|
||||
#define SAGA_FRAME_AMIGA_OPCODE_LITERAL 0x40
|
||||
#define SAGA_FRAME_AMIGA_OPCODE_TRANSPARENT 0xC0
|
||||
#define SAGA_FRAME_AMIGA_OPCODE_NEWLINE 0x80
|
||||
#define SAGA_FRAME_AMIGA_OPCODE_MASK 0xC0
|
||||
#define SAGA_FRAME_AMIGA_PARAM_MASK 0x3F
|
||||
#define SAGA_FRAME_AMIGA_END 0x3F
|
||||
#define SAGA_FRAME_AMIGA_START 0x3E
|
||||
|
||||
enum AnimationState {
|
||||
ANIM_PLAYING = 0x01,
|
||||
ANIM_PAUSE = 0x02,
|
||||
|
@ -43,11 +43,45 @@ static int granulate(int value, int granularity) {
|
||||
}
|
||||
}
|
||||
|
||||
bool SagaEngine::decodeBGImageMask(const ByteArray &imageData, ByteArray &outputBuffer, int *w, int *h, bool flip) {
|
||||
if (isAGA() || isECS()) {
|
||||
if (imageData.size() < 160 * 137 + 64)
|
||||
return false;
|
||||
*w = 320;
|
||||
*h = 137;
|
||||
outputBuffer.resize(320*137);
|
||||
|
||||
// First read types
|
||||
for (int i = 0; i < 160*137; i++) {
|
||||
outputBuffer[2 * i] = (imageData[i] << 4) | 0xf;
|
||||
outputBuffer[2 * i + 1] = (imageData[i] << 4) | 0xf;
|
||||
}
|
||||
|
||||
// Now instead of storing depth amiga variant stores precomputed mask for every
|
||||
// depth. Obviously not every set of precomputed masks is valid but we assume
|
||||
// that it is. So far it has always been the case. If ever it isn't then we'll
|
||||
// get a minor graphical glitch
|
||||
for (int depth = 15; depth > 0; depth--) {
|
||||
uint32 off = READ_BE_UINT32(&imageData[160 * 137 + 4 * (15 - depth)]);
|
||||
if (off == 0)
|
||||
continue;
|
||||
off += 160 * 137;
|
||||
if (imageData.size() < off + 137 * 40)
|
||||
return false;
|
||||
for (int y = 0; y < 137; y++)
|
||||
for (int x = 0; x < 320; x++)
|
||||
if ((imageData[y * 40 + (x / 8) + off] << (x % 8)) & 0x80)
|
||||
outputBuffer[y * 320 + x] = (outputBuffer[y * 320 + x] & 0xf0) | (depth - 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return decodeBGImage(imageData, outputBuffer, w, h, flip);
|
||||
}
|
||||
|
||||
bool SagaEngine::decodeBGImage(const ByteArray &imageData, ByteArray &outputBuffer, int *w, int *h, bool flip) {
|
||||
ImageHeader hdr;
|
||||
int modex_height;
|
||||
const byte *RLE_data_ptr;
|
||||
size_t RLE_data_len;
|
||||
ByteArray decodeBuffer;
|
||||
|
||||
if (imageData.size() <= SAGA_IMAGE_DATA_OFFSET) {
|
||||
@ -62,20 +96,38 @@ bool SagaEngine::decodeBGImage(const ByteArray &imageData, ByteArray &outputBuff
|
||||
readS.readUint16();
|
||||
readS.readUint16();
|
||||
|
||||
RLE_data_ptr = &imageData.front() + SAGA_IMAGE_DATA_OFFSET;
|
||||
RLE_data_len = imageData.size() - SAGA_IMAGE_DATA_OFFSET;
|
||||
|
||||
modex_height = granulate(hdr.height, 4);
|
||||
|
||||
decodeBuffer.resize(hdr.width * modex_height);
|
||||
|
||||
outputBuffer.resize(hdr.width * hdr.height);
|
||||
|
||||
if (!decodeBGImageRLE(RLE_data_ptr, RLE_data_len, decodeBuffer)) {
|
||||
return false;
|
||||
}
|
||||
if (isAGA() || isECS()) {
|
||||
int planePitch = (hdr.width + 15) & ~15;
|
||||
int linePitch = isAGA() ? planePitch : (planePitch * 5 / 8);
|
||||
unsigned bitnum = isAGA() ? 8 : 5;
|
||||
int headerSize = 8 + (3 << bitnum);
|
||||
const byte *RLE_data_ptr = &imageData.front() + headerSize;
|
||||
size_t RLE_data_len = imageData.size() - headerSize;
|
||||
|
||||
unbankBGImage(outputBuffer.getBuffer(), decodeBuffer.getBuffer(), hdr.width, hdr.height);
|
||||
if (RLE_data_len != (size_t) linePitch * hdr.height)
|
||||
return false;
|
||||
|
||||
memset(outputBuffer.getBuffer(), 0, hdr.width * hdr.height);
|
||||
for (int y = 0; y < hdr.height; y++)
|
||||
for (int x = 0; x < hdr.width; x++)
|
||||
for (unsigned bit = 0; bit < bitnum; bit++) {
|
||||
int inXbit = x + bit * planePitch;
|
||||
outputBuffer[y * hdr.width + x] |= ((RLE_data_ptr[y * linePitch + inXbit / 8] >> (7 - inXbit % 8)) & 1) << bit;
|
||||
}
|
||||
} else {
|
||||
int modex_height = granulate(hdr.height, 4);
|
||||
const byte *RLE_data_ptr;
|
||||
size_t RLE_data_len;
|
||||
decodeBuffer.resize(hdr.width * modex_height);
|
||||
RLE_data_ptr = &imageData.front() + SAGA_IMAGE_DATA_OFFSET;
|
||||
RLE_data_len = imageData.size() - SAGA_IMAGE_DATA_OFFSET;
|
||||
if (!decodeBGImageRLE(RLE_data_ptr, RLE_data_len, decodeBuffer)) {
|
||||
return false;
|
||||
}
|
||||
unbankBGImage(outputBuffer.getBuffer(), decodeBuffer.getBuffer(), hdr.width, hdr.height);
|
||||
}
|
||||
|
||||
// For some reason bg images in IHNM are upside down
|
||||
if (getGameId() == GID_IHNM && !flip) {
|
||||
|
@ -124,10 +124,11 @@ void IsoMap::loadImages(const ByteArray &resourceData) {
|
||||
error("IsoMap::loadImages wrong resourceLength");
|
||||
}
|
||||
|
||||
bool longOffset = _vm->isAGA() || _vm->isECS();
|
||||
|
||||
ByteArrayReadStreamEndian readS(resourceData, _vm->isBigEndian());
|
||||
readS.readUint16(); // skip
|
||||
i = readS.readUint16();
|
||||
i = longOffset ? readS.readUint32() : readS.readUint16();
|
||||
i = i / SAGA_ISOTILEDATA_LEN;
|
||||
_tilesTable.resize(i);
|
||||
Common::Array<size_t> tempOffsets;
|
||||
@ -139,7 +140,7 @@ void IsoMap::loadImages(const ByteArray &resourceData) {
|
||||
tileData = &_tilesTable[i];
|
||||
tileData->height = readS.readByte();
|
||||
tileData->attributes = readS.readSByte();
|
||||
tempOffsets[i] = readS.readUint16();
|
||||
tempOffsets[i] = longOffset ? readS.readUint32() : readS.readUint16();
|
||||
tileData->terrainMask = readS.readUint16();
|
||||
tileData->FGDBGDAttr = readS.readByte();
|
||||
readS.readByte(); //skip
|
||||
@ -152,6 +153,7 @@ void IsoMap::loadImages(const ByteArray &resourceData) {
|
||||
|
||||
for (i = 0; i < _tilesTable.size(); i++) {
|
||||
_tilesTable[i].tilePointer = _tileData.getBuffer() + tempOffsets[i] - offsetDiff;
|
||||
_tilesTable[i].tileSize = i + 1 == (int)_tilesTable.size() ? resourceData.size() - tempOffsets[i] : tempOffsets[i+1] - tempOffsets[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -819,6 +821,40 @@ void IsoMap::drawTile(uint16 tileIndex, const Point &point, const Location *loca
|
||||
|
||||
readPointer = tilePointer;
|
||||
lowBound = MIN((int)(drawPoint.y + height), (int)_tileClip.bottom);
|
||||
|
||||
if (_vm->isAGA() || _vm->isECS()) {
|
||||
if (height == 0)
|
||||
return;
|
||||
int pitchLine = _tilesTable[tileIndex].tileSize / height;
|
||||
int pitchPlane = _vm->isAGA() ? pitchLine / 8 : pitchLine / 5;
|
||||
int width = pitchPlane * 8;
|
||||
int bitnum = _vm->isAGA() ? 8 : 5;
|
||||
Common::Rect bounds(
|
||||
MAX((int)drawPoint.x, (int)_tileClip.left),
|
||||
MAX((int)drawPoint.y, (int)_tileClip.top),
|
||||
MIN((int)drawPoint.x + width, (int)_tileClip.right),
|
||||
MIN((int)drawPoint.y + height, (int)_tileClip.bottom)
|
||||
);
|
||||
for (row = bounds.top; row < bounds.bottom; row++)
|
||||
for (col = bounds.left; col < bounds.right; col++) {
|
||||
int sourceX = (col - drawPoint.x);
|
||||
int sourceY = (row - drawPoint.y);
|
||||
byte res = 0;
|
||||
|
||||
for (int bit = 0; bit < bitnum; bit++) {
|
||||
unsigned inOff = sourceY * pitchLine + sourceX / 8 + pitchPlane * bit;
|
||||
if (inOff >= _tilesTable[tileIndex].tileSize) {
|
||||
//warning("Overrun sourceX=%d, sourceY=%d, pitch=%d, height=%d", sourceX, sourceY, pitchLine, height);
|
||||
continue;
|
||||
}
|
||||
res |= ((tilePointer[inOff] >> (7 - sourceX % 8)) & 1) << bit;
|
||||
}
|
||||
if (res != 0)
|
||||
_vm->_gfx->getBackBufferPixels()[col + (row * _vm->_gfx->getBackBufferPitch())] = res;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (row = drawPoint.y; row < lowBound; row++) {
|
||||
widthCount = 0;
|
||||
if (row >= _tileClip.top) {
|
||||
|
@ -90,6 +90,7 @@ enum TileMapEdgeType {
|
||||
|
||||
struct IsoTileData {
|
||||
byte height;
|
||||
size_t tileSize;
|
||||
int8 attributes;
|
||||
byte *tilePointer;
|
||||
uint16 terrainMask;
|
||||
|
@ -475,6 +475,7 @@ private:
|
||||
|
||||
public:
|
||||
bool decodeBGImage(const ByteArray &imageData, ByteArray &outputBuffer, int *w, int *h, bool flip = false);
|
||||
bool decodeBGImageMask(const ByteArray &imageData, ByteArray &outputBuffer, int *w, int *h, bool flip = false);
|
||||
const byte *getImagePal(const ByteArray &imageData) {
|
||||
if (imageData.size() <= SAGA_IMAGE_HEADER_LEN) {
|
||||
return NULL;
|
||||
|
@ -971,7 +971,10 @@ void Scene::processSceneResources(SceneResourceDataArray &resourceList, SceneLoa
|
||||
error("Scene::ProcessSceneResources(): Duplicate background mask resource encountered");
|
||||
|
||||
debug(3, "Loading BACKGROUND MASK resource.");
|
||||
_vm->decodeBGImage(resourceData, _bgMask.buffer, &_bgMask.w, &_bgMask.h, true);
|
||||
if (flags & kLoadBgMaskIsImage)
|
||||
_vm->decodeBGImage(resourceData, _bgMask.buffer, &_bgMask.w, &_bgMask.h, true);
|
||||
else
|
||||
_vm->decodeBGImageMask(resourceData, _bgMask.buffer, &_bgMask.w, &_bgMask.h, true);
|
||||
_bgMask.loaded = true;
|
||||
|
||||
// At least in ITE the mask needs to be clipped.
|
||||
@ -1053,15 +1056,21 @@ void Scene::processSceneResources(SceneResourceDataArray &resourceList, SceneLoa
|
||||
{
|
||||
PalEntry pal[PAL_ENTRIES];
|
||||
byte *palPtr = resourceData.getBuffer();
|
||||
uint16 c;
|
||||
|
||||
if (resourceData.size() < 3 * PAL_ENTRIES)
|
||||
if (resourceData.size() < 3 * _vm->getPalNumEntries())
|
||||
error("Too small scene palette %i", (int)resourceData.size());
|
||||
|
||||
for (uint16 c = 0; c < PAL_ENTRIES; c++) {
|
||||
for (c = 0; c < _vm->getPalNumEntries(); c++) {
|
||||
pal[c].red = *palPtr++;
|
||||
pal[c].green = *palPtr++;
|
||||
pal[c].blue = *palPtr++;
|
||||
}
|
||||
for (; c < PAL_ENTRIES; c++) {
|
||||
pal[c].red = 0;
|
||||
pal[c].green = 0;
|
||||
pal[c].blue = 0;
|
||||
}
|
||||
_vm->_gfx->setPalette(pal);
|
||||
}
|
||||
break;
|
||||
|
@ -33,6 +33,83 @@
|
||||
|
||||
namespace Saga {
|
||||
|
||||
namespace {
|
||||
|
||||
template<int bitsPerPixel, int bitsPerEntry>
|
||||
bool blitAmigaSprite(byte *outBuf, int outPitch, const byte *inputBuffer, size_t inLength, int width, int height) {
|
||||
byte *outPointer = outBuf;
|
||||
int c;
|
||||
int widthAligned = (width + 15) & ~15;
|
||||
|
||||
Common::MemoryReadStream readS(inputBuffer, inLength);
|
||||
const byte *ptr = inputBuffer, *end = inputBuffer + inLength;
|
||||
|
||||
for (int bitOut = 0; bitOut < bitsPerPixel; bitOut++)
|
||||
for (int x = 0; x < widthAligned; x += bitsPerEntry) {
|
||||
for (int y = 0; y < height; ) {
|
||||
int bg_runcount = bitsPerEntry == 16 ? READ_BE_UINT16(ptr) : *ptr;
|
||||
ptr += bitsPerEntry / 8;
|
||||
if (ptr >= end)
|
||||
return true;
|
||||
|
||||
// Transparent
|
||||
y += bg_runcount;
|
||||
|
||||
if (y > height) {
|
||||
warning("Sprite height overrun in transparent run: coord=%d+%dx%d, size=%dx%d, pos=%d",
|
||||
x, bitOut, y, width, height, (int)readS.pos());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (y == height) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int fg_runcount = bitsPerEntry == 16 ? READ_BE_UINT16(ptr) : *ptr;
|
||||
ptr += bitsPerEntry / 8;
|
||||
if (ptr >= end)
|
||||
return true;
|
||||
|
||||
for (c = 0; c < fg_runcount && ptr < end; c++, y++) {
|
||||
uint16 val = bitsPerEntry == 16 ? READ_BE_UINT16(ptr) : *ptr;
|
||||
ptr += bitsPerEntry / 8;
|
||||
if (y >= height) {
|
||||
warning("Sprite height overrun in opaque run: coord=%d+%dx%d, size=%dx%d, pos=%d",
|
||||
x, bitOut, y, width, height, (int)readS.pos());
|
||||
return false;
|
||||
}
|
||||
for (int bitIn = 0; bitIn < bitsPerEntry; bitIn++) {
|
||||
int realX = x + (bitsPerEntry - 1 - bitIn);
|
||||
if (realX >= width) {
|
||||
continue;
|
||||
}
|
||||
outPointer[y * outPitch + realX] =
|
||||
(outPointer[y * outPitch + realX] & ~(1 << bitOut)) | (((val >> bitIn) & 1) << bitOut);
|
||||
}
|
||||
}
|
||||
if (bitsPerEntry < 8) {
|
||||
byte mask = (byte) ~(0xff << bitsPerEntry);
|
||||
for (c = 0, y -= fg_runcount; c < fg_runcount; c++, y++) {
|
||||
for (int z = 0; z < bitsPerEntry; z++) {
|
||||
int realX = x + z;
|
||||
if (realX >= width) {
|
||||
continue;
|
||||
}
|
||||
outPointer[y * outPitch + realX] &= mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fg_runcount == 0 && bg_runcount == 0) {
|
||||
warning("Sprite zero-sized run: coord=%d+%dx%d, size=%dx%d, pos=%d",
|
||||
x, bitOut, y, width, height, (int)readS.pos());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
#define RID_IHNM_ARROW_SPRITES 13
|
||||
#define RID_IHNM_SAVEREMINDER_SPRITES 14
|
||||
#define RID_IHNMDEMO_ARROW_SPRITES 8
|
||||
@ -92,7 +169,7 @@ void Sprite::loadList(int resourceId, SpriteList &spriteList) {
|
||||
|
||||
for (uint i = oldSpriteCount; i < spriteList.size(); i++) {
|
||||
uint32 offset;
|
||||
if (bigHeader)
|
||||
if (bigHeader || _vm->isITEAmiga())
|
||||
offset = readS.readUint32();
|
||||
else
|
||||
offset = readS.readUint16();
|
||||
@ -134,7 +211,15 @@ void Sprite::loadList(int resourceId, SpriteList &spriteList) {
|
||||
int inputLength = spriteListData.size() - (spriteDataPointer - spriteListData.getBuffer());
|
||||
spriteInfo->decodedBuffer.resize(outputLength);
|
||||
if (outputLength > 0) {
|
||||
decodeRLEBuffer(spriteDataPointer, inputLength, outputLength);
|
||||
if (_vm->isAGA() || _vm->isECS()) {
|
||||
_decodeBuf.resize(spriteInfo->width * spriteInfo->height);
|
||||
memset(&_decodeBuf.front(), 0, _decodeBuf.size());
|
||||
if (_vm->isAGA())
|
||||
blitAmigaSprite<8, 16>(&_decodeBuf.front(), spriteInfo->width, spriteDataPointer, inputLength, spriteInfo->width, spriteInfo->height);
|
||||
else
|
||||
blitAmigaSprite<4, 8>(&_decodeBuf.front(), spriteInfo->width, spriteDataPointer, inputLength, spriteInfo->width, spriteInfo->height);
|
||||
} else
|
||||
decodeRLEBuffer(spriteDataPointer, inputLength, outputLength);
|
||||
byte *dst = &spriteInfo->decodedBuffer.front();
|
||||
#ifdef ENABLE_IHNM
|
||||
// IHNM sprites are upside-down, for reasons which i can only
|
||||
|
Loading…
Reference in New Issue
Block a user