scummvm/kyra/cpsimage.cpp
2005-01-09 16:06:29 +00:00

186 lines
4.5 KiB
C++

/* ScummVM - Scumm Interpreter
* Copyright (C) 2004-2005 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header$
*
*/
#include "stdafx.h"
#include "resource.h"
#include "codecs.h"
#include "common/stream.h"
namespace Kyra {
struct CPSResource {
uint32 size;
uint16 width;
};
static const CPSResource CPSResourceTable[] = {
{ 64000, 320 }, { 7740, 180 }, { 46080, 320 }, { 0, 0 }
};
static int16 getWidthFromCPSRes(uint32 size) {
int16 c = 0;
for (; CPSResourceTable[c].size; ++c) {
if (CPSResourceTable[c].size == size)
return CPSResourceTable[c].width;
}
return -1;
}
CPSImage::CPSImage(uint8* buffer, uint32 size) {
if (!buffer) {
error("resource created without data");
}
_ownPalette = 0;
Common::MemoryReadStream bufferstream(buffer, size);
// reads in the Header
_cpsHeader._filesize = bufferstream.readUint16LE() + 2;
_cpsHeader._format = bufferstream.readUint16LE();
_cpsHeader._imagesize = bufferstream.readUint16LE();
_cpsHeader._pal = bufferstream.readUint32LE();
// lets check a bit
if(_cpsHeader._pal == 0x3000000) {
// if this was a compressed palette you should have strange graphics
uint8* palbuffer = new uint8[768];
assert(palbuffer);
bufferstream.read(palbuffer, 768 * sizeof(uint8));
_ownPalette = new Palette(palbuffer, 768);
assert(palbuffer);
}
_image = new uint8[_cpsHeader._imagesize];
assert(_image);
uint8* imagebuffer = &buffer[bufferstream.pos()];
assert(imagebuffer);
if(_cpsHeader._format == 4) {
Compression::decode80(imagebuffer, _image);
} else if(_cpsHeader._format == 3) {
Compression::decode3(imagebuffer, _image, _cpsHeader._imagesize);
} else {
error("unknown CPS format %d", _cpsHeader._format);
}
int16 width = getWidthFromCPSRes(_cpsHeader._imagesize);
if(width == -1) {
warning("unknown CPS width(imagesize: %d)", _cpsHeader._imagesize);
delete [] buffer;
return;
}
_width = (uint16)width;
_height = _cpsHeader._imagesize / _width;
_transparency = -1;
delete [] buffer;
}
CPSImage::~CPSImage() {
delete [] _image;
delete _ownPalette;
}
void CPSImage::drawToPlane(uint8* plane, uint16 planepitch, uint16 planeheight, uint16 x, uint16 y) {
uint8* src = _image;
uint8* dst = &plane[y * planepitch + x];
uint32 copysize = planepitch - x;
if (copysize > _width)
copysize = _width;
if (_transparency == -1) {
// 'fast' blitting
for (uint16 y_ = 0; y_ < _height && y + y_ < planeheight; ++y_) {
memcpy(dst, src, copysize * sizeof(uint8));
dst += planepitch;
src += _width;
}
} else {
// oh no! we have transparency so we have a very slow copy :/
for (uint16 yadd = 0; yadd < _height; ++yadd) {
for (uint16 xadd = 0; xadd < copysize; ++xadd) {
if (*src == _transparency) {
++dst;
++src;
} else {
*dst++ = *src++;
}
}
src += _width - copysize;
dst += planepitch - copysize;
}
}
}
void CPSImage::drawToPlane(uint8* plane, uint16 planepitch, uint16 planeheight, uint16 x, uint16 y,
uint16 srcx, uint16 srcy, uint16 srcwidth, uint16 srcheight) {
uint8* src = &_image[srcy * _width + srcx];
uint8* dst = &plane[y * planepitch + x];
uint32 copysize = planepitch - x;
if (srcwidth > _width)
srcwidth = _width;
if (copysize > srcwidth)
copysize = srcwidth;
if (_transparency == -1) {
// 'fast' blitting
for (uint16 y_ = 0; y_ < srcheight && y + y_ < planeheight; ++y_) {
memcpy(dst, src, copysize * sizeof(uint8));
dst += planepitch;
src += _width;
}
} else {
// oh no! we have transparency so we have a very slow copy :/
for (uint16 yadd = 0; yadd < srcheight; ++yadd) {
for (uint16 xadd = 0; xadd < copysize; ++xadd) {
if (*src == _transparency) {
++dst;
++src;
} else {
*dst++ = *src++;
}
}
dst += planepitch - copysize;
src += _width - copysize;
}
}
}
} // end of namespace Kyra