ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

xmg.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "engines/stark/formats/xmg.h"
00024 #include "engines/stark/debug.h"
00025 #include "engines/stark/gfx/driver.h"
00026 
00027 #include "graphics/conversion.h"
00028 #include "graphics/pixelformat.h"
00029 #include "graphics/surface.h"
00030 #include "common/stream.h"
00031 #include "common/textconsole.h"
00032 
00033 namespace Stark {
00034 namespace Formats {
00035 
00036 XMGDecoder::XMGDecoder(Common::ReadStream *stream) :
00037         _width(0),
00038         _height(0),
00039         _currX(0),
00040         _currY(0),
00041         _stream(stream),
00042         _transColor(0) {
00043 }
00044 
00045 Graphics::Surface *XMGDecoder::decode(Common::ReadStream *stream) {
00046     XMGDecoder dec(stream);
00047     dec.readHeader();
00048     return dec.decodeImage();
00049 }
00050 
00051 void XMGDecoder::readSize(Common::ReadStream *stream, uint &width, uint &height) {
00052     XMGDecoder dec(stream);
00053     dec.readHeader();
00054 
00055     width = dec._width;
00056     height = dec._height;
00057 }
00058 
00059 void XMGDecoder::readHeader() {
00060     // Read the file version
00061     uint32 version = _stream->readUint32LE();
00062     if (version != 3) {
00063         error("Stark::XMG: File version unknown: %d", version);
00064     }
00065 
00066     // Read the transparency color (RGBA)
00067     _transColor = _stream->readUint32LE();
00068 
00069     // Read the image size
00070     _width = _stream->readUint32LE();
00071     _height = _stream->readUint32LE();
00072     debugC(10, kDebugXMG, "Stark::XMG: Version=%d, TransparencyColor=0x%08x, size=%dx%d", version, _transColor, _width, _height);
00073 
00074     // Read the scan length
00075     uint32 scanLen = _stream->readUint32LE();
00076     if (scanLen != 3 * _width) {
00077         error("Stark::XMG: The scan length (%d) doesn't match the width bytes (%d)", scanLen, 3 * _width);
00078     }
00079 
00080     // Unknown
00081     uint32 unknown2 = _stream->readUint32LE();
00082     debugC(kDebugUnknown, "Stark::XMG: unknown2 = %08x = %d", unknown2, unknown2);
00083     uint32 unknown3 = _stream->readUint32LE();
00084     debugC(kDebugUnknown, "Stark::XMG: unknown3 = %08x = %d", unknown3, unknown3);
00085 }
00086 
00087 Graphics::Surface *XMGDecoder::decodeImage() {
00088     // Create the destination surface
00089     Graphics::Surface *surface = new Graphics::Surface();
00090     surface->create(_width, _height, Gfx::Driver::getRGBAPixelFormat());
00091 
00092     _currX = 0, _currY = 0;
00093     while (!_stream->eos()) {
00094         if (_currX >= _width) {
00095             assert(_currX == _width);
00096             _currX = 0;
00097             _currY += 2;
00098             if (_currY >= _height)
00099                 break;
00100         }
00101 
00102         // Read the number and mode of the tiles
00103         byte op = _stream->readByte();
00104         uint16 count;
00105         if ((op & 0xC0) != 0xC0) {
00106             count = op & 0x3F;
00107         } else {
00108             count = ((op & 0xF) << 8) + _stream->readByte();
00109             op <<= 2;
00110         }
00111         op &= 0xC0;
00112 
00113         // Process the current serie
00114         for (int i = 0; i < count; i++) {
00115             Block block = decodeBlock(op);
00116             drawBlock(block, surface);
00117         }
00118     }
00119 
00120     return surface;
00121 }
00122 
00123 XMGDecoder::Block XMGDecoder::decodeBlock(byte op) {
00124     Block block;
00125 
00126     switch (op) {
00127         case 0x00:
00128             // YCrCb
00129             block = processYCrCb();
00130             break;
00131         case 0x40:
00132             // Trans
00133             block = processTrans();
00134             break;
00135         case 0x80:
00136             // RGB
00137             block = processRGB();
00138             break;
00139         default:
00140             error("Unsupported color mode '%d'", op);
00141     }
00142 
00143     return block;
00144 }
00145 
00146 void XMGDecoder::drawBlock(const Block &block, Graphics::Surface *surface) {
00147     uint32 *pixels = (uint32 *)surface->getBasePtr(_currX, _currY);
00148 
00149     bool drawTwoColumns = _currX + 1 < _width;
00150     bool drawTwoLines = _currY + 1 < _height;
00151 
00152     pixels[0] = TO_LE_32(block.a1);
00153 
00154     if (drawTwoColumns) {
00155         pixels[1] = TO_LE_32(block.a2);
00156     }
00157 
00158     if (drawTwoLines) {
00159         pixels[_width + 0] = TO_LE_32(block.b1);
00160     }
00161 
00162     if (drawTwoColumns && drawTwoLines) {
00163         pixels[_width + 1] = TO_LE_32(block.b2);
00164     }
00165 
00166     _currX += drawTwoColumns ? 2 : 1;
00167 }
00168 
00169 XMGDecoder::Block XMGDecoder::processYCrCb() {
00170     byte y0, y1, y2, y3;
00171     byte cr, cb;
00172 
00173     y0 = _stream->readByte();
00174     y1 = _stream->readByte();
00175     y2 = _stream->readByte();
00176     y3 = _stream->readByte();
00177     cr = _stream->readByte();
00178     cb = _stream->readByte();
00179 
00180     byte r, g, b;
00181     Block block;
00182 
00183     Graphics::YUV2RGB(y0, cb, cr, r, g, b);
00184     block.a1 = (255u << 24) + (b << 16) + (g << 8) + r;
00185 
00186     Graphics::YUV2RGB(y1, cb, cr, r, g, b);
00187     block.a2 = (255u << 24) + (b << 16) + (g << 8) + r;
00188 
00189     Graphics::YUV2RGB(y2, cb, cr, r, g, b);
00190     block.b1 = (255u << 24) + (b << 16) + (g << 8) + r;
00191 
00192     Graphics::YUV2RGB(y3, cb, cr, r, g, b);
00193     block.b2 = (255u << 24) + (b << 16) + (g << 8) + r;
00194 
00195     return block;
00196 }
00197 
00198 XMGDecoder::Block XMGDecoder::processTrans() {
00199     Block block;
00200 
00201     block.a1 = 0;
00202     block.a2 = 0;
00203     block.b1 = 0;
00204     block.b2 = 0;
00205 
00206     return block;
00207 }
00208 
00209 XMGDecoder::Block XMGDecoder::processRGB() {
00210     Block block;
00211     uint32 color;
00212 
00213     color = _stream->readUint16LE();
00214     color += _stream->readByte() << 16;
00215     if (color != _transColor)
00216         color += 255 << 24;
00217     else
00218         color = 0;
00219     block.a1 = color;
00220 
00221     color = _stream->readUint16LE();
00222     color += _stream->readByte() << 16;
00223     if (color != _transColor)
00224         color += 255 << 24;
00225     else
00226         color = 0;
00227     block.a2 = color;
00228 
00229     color = _stream->readUint16LE();
00230     color += _stream->readByte() << 16;
00231     if (color != _transColor)
00232         color += 255 << 24;
00233     else
00234         color = 0;
00235     block.b1 = color;
00236 
00237     color = _stream->readUint16LE();
00238     color += _stream->readByte() << 16;
00239     if (color != _transColor)
00240         color += 255 << 24;
00241     else
00242         color = 0;
00243     block.b2 = color;
00244 
00245     return block;
00246 }
00247 
00248 } // End of namespace Formats
00249 } // End of namespace Stark


Generated on Sat May 18 2019 05:01:30 for ResidualVM by doxygen 1.7.1
curved edge   curved edge