Initial commit
This commit is contained in:
248
engines/stark/formats/xmg.cpp
Normal file
248
engines/stark/formats/xmg.cpp
Normal file
@@ -0,0 +1,248 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "engines/stark/formats/xmg.h"
|
||||
#include "engines/stark/debug.h"
|
||||
#include "engines/stark/gfx/driver.h"
|
||||
|
||||
#include "graphics/conversion.h"
|
||||
#include "graphics/pixelformat.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
namespace Stark {
|
||||
namespace Formats {
|
||||
|
||||
XMGDecoder::XMGDecoder(Common::ReadStream *stream) :
|
||||
_width(0),
|
||||
_height(0),
|
||||
_currX(0),
|
||||
_currY(0),
|
||||
_stream(stream),
|
||||
_transColor(0) {
|
||||
}
|
||||
|
||||
Graphics::Surface *XMGDecoder::decode(Common::ReadStream *stream) {
|
||||
XMGDecoder dec(stream);
|
||||
dec.readHeader();
|
||||
return dec.decodeImage();
|
||||
}
|
||||
|
||||
void XMGDecoder::readSize(Common::ReadStream *stream, uint &width, uint &height) {
|
||||
XMGDecoder dec(stream);
|
||||
dec.readHeader();
|
||||
|
||||
width = dec._width;
|
||||
height = dec._height;
|
||||
}
|
||||
|
||||
void XMGDecoder::readHeader() {
|
||||
// Read the file version
|
||||
uint32 version = _stream->readUint32LE();
|
||||
if (version != 3) {
|
||||
error("Stark::XMG: File version unknown: %d", version);
|
||||
}
|
||||
|
||||
// Read the transparency color (RGBA)
|
||||
_transColor = _stream->readUint32LE();
|
||||
|
||||
// Read the image size
|
||||
_width = _stream->readUint32LE();
|
||||
_height = _stream->readUint32LE();
|
||||
debugC(10, kDebugXMG, "Stark::XMG: Version=%d, TransparencyColor=0x%08x, size=%dx%d", version, _transColor, _width, _height);
|
||||
|
||||
// Read the scan length
|
||||
uint32 scanLen = _stream->readUint32LE();
|
||||
if (scanLen != 3 * _width) {
|
||||
error("Stark::XMG: The scan length (%d) doesn't match the width bytes (%d)", scanLen, 3 * _width);
|
||||
}
|
||||
|
||||
// Unknown
|
||||
uint32 unknown2 = _stream->readUint32LE();
|
||||
debugC(kDebugUnknown, "Stark::XMG: unknown2 = %08x = %d", unknown2, unknown2);
|
||||
uint32 unknown3 = _stream->readUint32LE();
|
||||
debugC(kDebugUnknown, "Stark::XMG: unknown3 = %08x = %d", unknown3, unknown3);
|
||||
}
|
||||
|
||||
Graphics::Surface *XMGDecoder::decodeImage() {
|
||||
// Create the destination surface
|
||||
Graphics::Surface *surface = new Graphics::Surface();
|
||||
surface->create(_width, _height, Gfx::Driver::getRGBAPixelFormat());
|
||||
|
||||
_currX = 0, _currY = 0;
|
||||
while (!_stream->eos()) {
|
||||
if (_currX >= _width) {
|
||||
assert(_currX == _width);
|
||||
_currX = 0;
|
||||
_currY += 2;
|
||||
if (_currY >= _height)
|
||||
break;
|
||||
}
|
||||
|
||||
// Read the number and mode of the tiles
|
||||
byte op = _stream->readByte();
|
||||
uint16 count;
|
||||
if ((op & 0xC0) != 0xC0) {
|
||||
count = op & 0x3F;
|
||||
} else {
|
||||
count = ((op & 0xF) << 8) + _stream->readByte();
|
||||
op <<= 2;
|
||||
}
|
||||
op &= 0xC0;
|
||||
|
||||
// Process the current serie
|
||||
for (int i = 0; i < count; i++) {
|
||||
Block block = decodeBlock(op);
|
||||
drawBlock(block, surface);
|
||||
}
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
XMGDecoder::Block XMGDecoder::decodeBlock(byte op) {
|
||||
Block block;
|
||||
|
||||
switch (op) {
|
||||
case 0x00:
|
||||
// YCrCb
|
||||
block = processYCrCb();
|
||||
break;
|
||||
case 0x40:
|
||||
// Trans
|
||||
block = processTrans();
|
||||
break;
|
||||
case 0x80:
|
||||
// RGB
|
||||
block = processRGB();
|
||||
break;
|
||||
default:
|
||||
error("Unsupported color mode '%d'", op);
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
void XMGDecoder::drawBlock(const Block &block, Graphics::Surface *surface) {
|
||||
uint32 *pixels = (uint32 *)surface->getBasePtr(_currX, _currY);
|
||||
|
||||
bool drawTwoColumns = _currX + 1 < _width;
|
||||
bool drawTwoLines = _currY + 1 < _height;
|
||||
|
||||
pixels[0] = TO_LE_32(block.a1);
|
||||
|
||||
if (drawTwoColumns) {
|
||||
pixels[1] = TO_LE_32(block.a2);
|
||||
}
|
||||
|
||||
if (drawTwoLines) {
|
||||
pixels[_width + 0] = TO_LE_32(block.b1);
|
||||
}
|
||||
|
||||
if (drawTwoColumns && drawTwoLines) {
|
||||
pixels[_width + 1] = TO_LE_32(block.b2);
|
||||
}
|
||||
|
||||
_currX += drawTwoColumns ? 2 : 1;
|
||||
}
|
||||
|
||||
XMGDecoder::Block XMGDecoder::processYCrCb() {
|
||||
byte y0, y1, y2, y3;
|
||||
byte cr, cb;
|
||||
|
||||
y0 = _stream->readByte();
|
||||
y1 = _stream->readByte();
|
||||
y2 = _stream->readByte();
|
||||
y3 = _stream->readByte();
|
||||
cr = _stream->readByte();
|
||||
cb = _stream->readByte();
|
||||
|
||||
byte r, g, b;
|
||||
Block block;
|
||||
|
||||
Graphics::YUV2RGB(y0, cb, cr, r, g, b);
|
||||
block.a1 = (255u << 24) + (b << 16) + (g << 8) + r;
|
||||
|
||||
Graphics::YUV2RGB(y1, cb, cr, r, g, b);
|
||||
block.a2 = (255u << 24) + (b << 16) + (g << 8) + r;
|
||||
|
||||
Graphics::YUV2RGB(y2, cb, cr, r, g, b);
|
||||
block.b1 = (255u << 24) + (b << 16) + (g << 8) + r;
|
||||
|
||||
Graphics::YUV2RGB(y3, cb, cr, r, g, b);
|
||||
block.b2 = (255u << 24) + (b << 16) + (g << 8) + r;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
XMGDecoder::Block XMGDecoder::processTrans() {
|
||||
Block block;
|
||||
|
||||
block.a1 = 0;
|
||||
block.a2 = 0;
|
||||
block.b1 = 0;
|
||||
block.b2 = 0;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
XMGDecoder::Block XMGDecoder::processRGB() {
|
||||
Block block;
|
||||
uint32 color;
|
||||
|
||||
color = _stream->readUint16LE();
|
||||
color += _stream->readByte() << 16;
|
||||
if (color != _transColor)
|
||||
color += 255u << 24;
|
||||
else
|
||||
color = 0;
|
||||
block.a1 = color;
|
||||
|
||||
color = _stream->readUint16LE();
|
||||
color += _stream->readByte() << 16;
|
||||
if (color != _transColor)
|
||||
color += 255u << 24;
|
||||
else
|
||||
color = 0;
|
||||
block.a2 = color;
|
||||
|
||||
color = _stream->readUint16LE();
|
||||
color += _stream->readByte() << 16;
|
||||
if (color != _transColor)
|
||||
color += 255u << 24;
|
||||
else
|
||||
color = 0;
|
||||
block.b1 = color;
|
||||
|
||||
color = _stream->readUint16LE();
|
||||
color += _stream->readByte() << 16;
|
||||
if (color != _transColor)
|
||||
color += 255u << 24;
|
||||
else
|
||||
color = 0;
|
||||
block.b2 = color;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
} // End of namespace Formats
|
||||
} // End of namespace Stark
|
||||
Reference in New Issue
Block a user