2009-10-03 20:49:18 +00:00
|
|
|
/* 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* $URL$
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2009-10-10 02:16:23 +00:00
|
|
|
#include "common/stack.h"
|
2010-02-17 23:37:32 +00:00
|
|
|
#include "common/system.h"
|
|
|
|
|
2009-10-03 20:49:18 +00:00
|
|
|
#include "sci/sci.h"
|
|
|
|
#include "sci/engine/state.h"
|
2010-01-05 01:37:57 +00:00
|
|
|
#include "sci/graphics/screen.h"
|
|
|
|
#include "sci/graphics/palette.h"
|
2010-02-06 19:35:51 +00:00
|
|
|
#include "sci/graphics/coordadjuster.h"
|
2010-01-31 12:35:15 +00:00
|
|
|
#include "sci/graphics/ports.h"
|
2010-01-05 01:37:57 +00:00
|
|
|
#include "sci/graphics/picture.h"
|
2009-10-03 20:49:18 +00:00
|
|
|
|
|
|
|
namespace Sci {
|
|
|
|
|
2010-02-06 19:35:51 +00:00
|
|
|
GfxPicture::GfxPicture(ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxPorts *ports, GfxScreen *screen, GfxPalette *palette, GuiResourceId resourceId, bool EGAdrawingVisualize)
|
|
|
|
: _resMan(resMan), _coordAdjuster(coordAdjuster), _ports(ports), _screen(screen), _palette(palette), _resourceId(resourceId), _EGAdrawingVisualize(EGAdrawingVisualize) {
|
2009-10-03 20:49:18 +00:00
|
|
|
assert(resourceId != -1);
|
|
|
|
initData(resourceId);
|
|
|
|
}
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
GfxPicture::~GfxPicture() {
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
void GfxPicture::initData(GuiResourceId resourceId) {
|
2009-10-11 16:12:24 +00:00
|
|
|
_resource = _resMan->findResource(ResourceId(kResourceTypePic, resourceId), false);
|
2009-10-03 20:49:18 +00:00
|
|
|
if (!_resource) {
|
|
|
|
error("picture resource %d not found", resourceId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
GuiResourceId GfxPicture::getResourceId() {
|
2009-10-03 20:49:18 +00:00
|
|
|
return _resourceId;
|
|
|
|
}
|
|
|
|
|
2010-07-13 15:46:21 +00:00
|
|
|
// differentiation between various picture formats can NOT get done using sci-version checks.
|
|
|
|
// Games like PQ1 use the "old" vector data picture format, but are actually SCI1.1
|
|
|
|
// We should leave this that way to decide the format on-the-fly instead of hardcoding it in any way
|
2010-02-05 12:14:03 +00:00
|
|
|
void GfxPicture::draw(int16 animationNr, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo) {
|
2009-12-26 19:06:17 +00:00
|
|
|
uint16 headerSize;
|
|
|
|
|
2009-10-07 20:58:33 +00:00
|
|
|
_animationNr = animationNr;
|
|
|
|
_mirroredFlag = mirroredFlag;
|
2009-10-03 20:49:18 +00:00
|
|
|
_addToFlag = addToFlag;
|
|
|
|
_EGApaletteNo = EGApaletteNo;
|
|
|
|
_priority = 0;
|
|
|
|
|
2009-12-26 19:06:17 +00:00
|
|
|
headerSize = READ_LE_UINT16(_resource->data);
|
|
|
|
switch (headerSize) {
|
|
|
|
case 0x26: // SCI 1.1 VGA picture
|
2010-05-25 18:45:25 +00:00
|
|
|
_resourceType = SCI_PICTURE_TYPE_SCI11;
|
2010-05-25 12:04:32 +00:00
|
|
|
if (_addToFlag)
|
|
|
|
_priority = 15;
|
2009-10-06 06:50:31 +00:00
|
|
|
drawSci11Vga();
|
2009-12-26 19:06:17 +00:00
|
|
|
break;
|
2009-12-26 21:19:48 +00:00
|
|
|
#ifdef ENABLE_SCI32
|
2009-12-26 19:06:17 +00:00
|
|
|
case 0x0e: // SCI32 VGA picture
|
2010-05-25 18:45:25 +00:00
|
|
|
_resourceType = SCI_PICTURE_TYPE_SCI32;
|
2010-07-21 13:13:55 +00:00
|
|
|
//drawSci32Vga();
|
2009-12-26 19:06:17 +00:00
|
|
|
break;
|
2009-12-26 21:19:48 +00:00
|
|
|
#endif
|
2009-12-26 19:06:17 +00:00
|
|
|
default:
|
2009-10-16 11:49:56 +00:00
|
|
|
// VGA, EGA or Amiga vector data
|
2010-05-25 18:45:25 +00:00
|
|
|
_resourceType = SCI_PICTURE_TYPE_REGULAR;
|
2009-10-03 20:49:18 +00:00
|
|
|
drawVectorData(_resource->data, _resource->size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
void GfxPicture::reset() {
|
2009-10-03 20:49:18 +00:00
|
|
|
int16 x, y;
|
2010-01-31 12:35:15 +00:00
|
|
|
for (y = _ports->getPort()->top; y < _screen->getHeight(); y++) {
|
2010-01-06 13:05:14 +00:00
|
|
|
for (x = 0; x < _screen->getWidth(); x++) {
|
2010-05-15 08:57:13 +00:00
|
|
|
_screen->putPixel(x, y, GFX_SCREEN_MASK_ALL, 255, 0, 0);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
void GfxPicture::drawSci11Vga() {
|
2009-10-03 20:49:18 +00:00
|
|
|
byte *inbuffer = _resource->data;
|
|
|
|
int size = _resource->size;
|
2009-10-11 11:42:50 +00:00
|
|
|
int has_cel = READ_LE_UINT16(inbuffer + 4);
|
|
|
|
int vector_dataPos = READ_LE_UINT16(inbuffer + 16);
|
|
|
|
int vector_size = size - vector_dataPos;
|
2009-10-03 20:49:18 +00:00
|
|
|
int palette_data_ptr = READ_LE_UINT16(inbuffer + 28);
|
2009-10-11 11:42:50 +00:00
|
|
|
int cel_headerPos = READ_LE_UINT16(inbuffer + 32);
|
|
|
|
int cel_RlePos = READ_LE_UINT16(inbuffer + cel_headerPos + 24);
|
|
|
|
int cel_LiteralPos = READ_LE_UINT16(inbuffer + cel_headerPos + 28);
|
2010-01-05 01:37:57 +00:00
|
|
|
Palette palette;
|
2009-10-03 20:49:18 +00:00
|
|
|
|
|
|
|
// Create palette and set it
|
2010-06-23 11:47:14 +00:00
|
|
|
_palette->createFromData(inbuffer + palette_data_ptr, size - palette_data_ptr, &palette);
|
2010-01-26 22:45:52 +00:00
|
|
|
_palette->set(&palette, true);
|
2009-10-03 20:49:18 +00:00
|
|
|
|
|
|
|
// display Cel-data
|
2010-05-25 12:04:32 +00:00
|
|
|
if (has_cel)
|
2010-05-25 18:45:25 +00:00
|
|
|
drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, 0, 0);
|
2009-10-03 20:49:18 +00:00
|
|
|
|
|
|
|
// process vector data
|
2009-10-11 11:42:50 +00:00
|
|
|
drawVectorData(inbuffer + vector_dataPos, vector_size);
|
2010-01-19 14:26:21 +00:00
|
|
|
|
|
|
|
// Remember priority band information for later
|
2010-01-31 12:35:15 +00:00
|
|
|
_ports->priorityBandsRemember(inbuffer + 40);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
|
2009-12-26 21:19:48 +00:00
|
|
|
#ifdef ENABLE_SCI32
|
2010-02-05 12:14:03 +00:00
|
|
|
int16 GfxPicture::getSci32celCount() {
|
2010-02-02 16:25:35 +00:00
|
|
|
byte *inbuffer = _resource->data;
|
|
|
|
return inbuffer[2];
|
|
|
|
}
|
|
|
|
|
2010-07-22 10:24:08 +00:00
|
|
|
int16 GfxPicture::getSci32celY(int16 celNo) {
|
|
|
|
byte *inbuffer = _resource->data;
|
|
|
|
int header_size = READ_LE_UINT16(inbuffer);
|
|
|
|
int cel_headerPos = header_size + 42 * celNo;
|
|
|
|
return READ_LE_UINT16(inbuffer + cel_headerPos + 40);
|
|
|
|
}
|
|
|
|
|
|
|
|
int16 GfxPicture::getSci32celX(int16 celNo) {
|
|
|
|
byte *inbuffer = _resource->data;
|
|
|
|
int header_size = READ_LE_UINT16(inbuffer);
|
|
|
|
int cel_headerPos = header_size + 42 * celNo;
|
|
|
|
return READ_LE_UINT16(inbuffer + cel_headerPos + 38);
|
|
|
|
}
|
|
|
|
|
2010-07-22 12:36:58 +00:00
|
|
|
int16 GfxPicture::getSci32celPriority(int16 celNo) {
|
|
|
|
byte *inbuffer = _resource->data;
|
|
|
|
int header_size = READ_LE_UINT16(inbuffer);
|
|
|
|
int cel_headerPos = header_size + 42 * celNo;
|
|
|
|
return READ_LE_UINT16(inbuffer + cel_headerPos + 36);
|
|
|
|
}
|
|
|
|
|
2010-07-22 10:24:08 +00:00
|
|
|
void GfxPicture::drawSci32Vga(int16 celNo, int16 callerX, int16 callerY, bool mirrored) {
|
2009-12-26 19:06:17 +00:00
|
|
|
byte *inbuffer = _resource->data;
|
|
|
|
int size = _resource->size;
|
|
|
|
int header_size = READ_LE_UINT16(inbuffer);
|
|
|
|
int palette_data_ptr = READ_LE_UINT16(inbuffer + 6);
|
2010-07-22 20:11:53 +00:00
|
|
|
// int celCount = inbuffer[2];
|
2009-12-26 19:06:17 +00:00
|
|
|
int cel_headerPos = header_size;
|
2010-01-05 13:51:47 +00:00
|
|
|
int cel_RlePos, cel_LiteralPos;
|
2010-01-05 01:37:57 +00:00
|
|
|
Palette palette;
|
2009-12-26 19:06:17 +00:00
|
|
|
|
2010-02-02 16:25:35 +00:00
|
|
|
// HACK
|
2010-07-22 10:24:08 +00:00
|
|
|
_mirroredFlag = mirrored;
|
2010-02-02 16:25:35 +00:00
|
|
|
_addToFlag = false;
|
2010-05-26 13:24:32 +00:00
|
|
|
_resourceType = SCI_PICTURE_TYPE_SCI32;
|
2010-02-02 16:25:35 +00:00
|
|
|
|
2010-07-22 20:11:53 +00:00
|
|
|
if (celNo == 0) {
|
2010-02-02 16:25:35 +00:00
|
|
|
// Create palette and set it
|
2010-06-23 11:47:14 +00:00
|
|
|
_palette->createFromData(inbuffer + palette_data_ptr, size - palette_data_ptr, &palette);
|
2010-02-02 16:25:35 +00:00
|
|
|
_palette->set(&palette, true);
|
|
|
|
}
|
2009-12-26 19:06:17 +00:00
|
|
|
|
2010-07-22 20:11:53 +00:00
|
|
|
// Header
|
|
|
|
// [headerSize:WORD] [celCount:BYTE] [Unknown:BYTE] [Unknown:WORD] [paletteOffset:DWORD] [Unknown:DWORD]
|
|
|
|
// cel-header follow afterwards, each is 42 bytes
|
|
|
|
// Cel-Header
|
|
|
|
// [width:WORD] [height:WORD] [displaceX:WORD] [displaceY:WORD] [clearColor:BYTE] [compressed:BYTE]
|
|
|
|
// offset 10-23 is unknown
|
|
|
|
// [rleOffset:DWORD] [literalOffset:DWORD] [Unknown:WORD] [Unknown:WORD] [priority:WORD] [relativeXpos:WORD] [relativeYpos:WORD]
|
2010-07-21 13:13:55 +00:00
|
|
|
|
2010-07-22 20:11:53 +00:00
|
|
|
cel_headerPos += 42 * celNo;
|
2010-07-21 13:13:55 +00:00
|
|
|
|
2010-07-22 20:11:53 +00:00
|
|
|
if (mirrored) {
|
|
|
|
// switch around relativeXpos
|
|
|
|
Common::Rect displayArea = _coordAdjuster->pictureGetDisplayArea();
|
|
|
|
callerX = displayArea.width() - callerX - READ_LE_UINT16(inbuffer + cel_headerPos + 0);
|
2010-01-05 13:51:47 +00:00
|
|
|
}
|
2010-07-22 20:11:53 +00:00
|
|
|
|
|
|
|
cel_RlePos = READ_LE_UINT32(inbuffer + cel_headerPos + 24);
|
|
|
|
cel_LiteralPos = READ_LE_UINT32(inbuffer + cel_headerPos + 28);
|
|
|
|
|
|
|
|
drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, callerX, callerY);
|
|
|
|
cel_headerPos += 42;
|
2009-12-26 19:06:17 +00:00
|
|
|
}
|
2009-12-26 21:19:48 +00:00
|
|
|
#endif
|
2009-12-26 19:06:17 +00:00
|
|
|
|
2010-05-25 18:45:25 +00:00
|
|
|
void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos, int literalPos, int16 callerX, int16 callerY) {
|
2009-10-11 11:42:50 +00:00
|
|
|
byte *celBitmap = NULL;
|
|
|
|
byte *ptr = NULL;
|
|
|
|
byte *headerPtr = inbuffer + headerPos;
|
|
|
|
byte *rlePtr = inbuffer + rlePos;
|
|
|
|
byte *literalPtr = inbuffer + literalPos;
|
|
|
|
uint16 width = READ_LE_UINT16(headerPtr + 0);
|
|
|
|
uint16 height = READ_LE_UINT16(headerPtr + 2);
|
2009-12-26 19:06:17 +00:00
|
|
|
int16 displaceX, displaceY;
|
2009-10-03 20:49:18 +00:00
|
|
|
byte priority = _addToFlag ? _priority : 0;
|
2009-12-26 19:06:17 +00:00
|
|
|
byte clearColor;
|
2009-12-26 19:23:57 +00:00
|
|
|
bool compression = true;
|
2009-10-11 11:42:50 +00:00
|
|
|
byte curByte, runLength;
|
2009-10-14 09:46:02 +00:00
|
|
|
int16 y, lastY, x, leftX, rightX;
|
2010-01-05 20:52:19 +00:00
|
|
|
int pixelNr, pixelCount;
|
2009-10-11 11:42:50 +00:00
|
|
|
|
2009-12-26 21:19:48 +00:00
|
|
|
#ifdef ENABLE_SCI32
|
2010-05-25 18:45:25 +00:00
|
|
|
if (_resourceType != SCI_PICTURE_TYPE_SCI32) {
|
2009-12-26 21:19:48 +00:00
|
|
|
#endif
|
2009-12-26 19:06:17 +00:00
|
|
|
displaceX = (signed char)headerPtr[4];
|
|
|
|
displaceY = (unsigned char)headerPtr[5];
|
2010-05-25 18:45:25 +00:00
|
|
|
if (_resourceType == SCI_PICTURE_TYPE_SCI11) {
|
2010-05-25 12:53:35 +00:00
|
|
|
// SCI1.1 uses hardcoded clearcolor for pictures, even if cel header specifies otherwise
|
|
|
|
clearColor = _screen->getColorWhite();
|
|
|
|
} else {
|
|
|
|
clearColor = headerPtr[6];
|
|
|
|
}
|
2009-12-26 21:19:48 +00:00
|
|
|
#ifdef ENABLE_SCI32
|
2009-12-26 19:06:17 +00:00
|
|
|
} else {
|
|
|
|
displaceX = READ_LE_UINT16(headerPtr + 4); // probably signed?!?
|
|
|
|
displaceY = READ_LE_UINT16(headerPtr + 6); // probably signed?!?
|
|
|
|
clearColor = headerPtr[8];
|
2009-12-26 19:23:57 +00:00
|
|
|
if (headerPtr[9] == 0)
|
|
|
|
compression = false;
|
2009-12-26 19:06:17 +00:00
|
|
|
}
|
2009-12-26 21:19:48 +00:00
|
|
|
#endif
|
2009-12-26 19:06:17 +00:00
|
|
|
|
2009-10-14 09:46:02 +00:00
|
|
|
if (displaceX || displaceY)
|
2009-10-11 11:42:50 +00:00
|
|
|
error("unsupported embedded cel-data in picture");
|
|
|
|
|
|
|
|
pixelCount = width * height;
|
|
|
|
celBitmap = new byte[pixelCount];
|
|
|
|
if (!celBitmap)
|
|
|
|
error("Unable to allocate temporary memory for picture drawing");
|
|
|
|
|
2009-12-26 19:23:57 +00:00
|
|
|
if (compression) {
|
|
|
|
// We will unpack cel-data into a temporary buffer and then plot it to screen
|
|
|
|
// That needs to be done cause a mirrored picture may be requested
|
|
|
|
memset(celBitmap, clearColor, pixelCount);
|
|
|
|
pixelNr = 0;
|
|
|
|
ptr = celBitmap;
|
|
|
|
if (literalPos == 0) {
|
|
|
|
// decompression for data that has only one stream (vecor embedded view data)
|
|
|
|
switch (_resMan->getViewType()) {
|
|
|
|
case kViewEga:
|
|
|
|
while (pixelNr < pixelCount) {
|
|
|
|
curByte = *rlePtr++;
|
|
|
|
runLength = curByte >> 4;
|
|
|
|
memset(ptr + pixelNr, curByte & 0x0F, MIN<uint16>(runLength, pixelCount - pixelNr));
|
|
|
|
pixelNr += runLength;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case kViewVga:
|
|
|
|
case kViewVga11:
|
|
|
|
while (pixelNr < pixelCount) {
|
|
|
|
curByte = *rlePtr++;
|
|
|
|
runLength = curByte & 0x3F;
|
|
|
|
switch (curByte & 0xC0) {
|
|
|
|
case 0: // copy bytes as-is
|
|
|
|
while (runLength-- && pixelNr < pixelCount)
|
|
|
|
ptr[pixelNr++] = *rlePtr++;
|
|
|
|
break;
|
|
|
|
case 0x80: // fill with color
|
|
|
|
memset(ptr + pixelNr, *rlePtr++, MIN<uint16>(runLength, pixelCount - pixelNr));
|
|
|
|
pixelNr += runLength;
|
|
|
|
break;
|
|
|
|
case 0xC0: // fill with transparent
|
|
|
|
pixelNr += runLength;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case kViewAmiga:
|
|
|
|
while (pixelNr < pixelCount) {
|
|
|
|
curByte = *rlePtr++;
|
|
|
|
if (curByte & 0x07) { // fill with color
|
|
|
|
runLength = curByte & 0x07;
|
|
|
|
curByte = curByte >> 3;
|
|
|
|
while (runLength-- && pixelNr < pixelCount) {
|
|
|
|
ptr[pixelNr++] = curByte;
|
|
|
|
}
|
|
|
|
} else { // fill with transparent
|
|
|
|
runLength = curByte >> 3;
|
|
|
|
pixelNr += runLength;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
error("Unsupported picture viewtype");
|
2009-10-15 11:47:05 +00:00
|
|
|
}
|
2009-12-26 19:23:57 +00:00
|
|
|
} else {
|
|
|
|
// decompression for data that has two separate streams (probably SCI 1.1 picture)
|
2009-10-11 11:42:50 +00:00
|
|
|
while (pixelNr < pixelCount) {
|
|
|
|
curByte = *rlePtr++;
|
|
|
|
runLength = curByte & 0x3F;
|
|
|
|
switch (curByte & 0xC0) {
|
|
|
|
case 0: // copy bytes as-is
|
|
|
|
while (runLength-- && pixelNr < pixelCount)
|
2009-12-26 19:23:57 +00:00
|
|
|
ptr[pixelNr++] = *literalPtr++;
|
2009-10-11 11:42:50 +00:00
|
|
|
break;
|
|
|
|
case 0x80: // fill with color
|
2009-12-26 19:23:57 +00:00
|
|
|
memset(ptr + pixelNr, *literalPtr++, MIN<uint16>(runLength, pixelCount - pixelNr));
|
2009-10-11 11:42:50 +00:00
|
|
|
pixelNr += runLength;
|
|
|
|
break;
|
|
|
|
case 0xC0: // fill with transparent
|
|
|
|
pixelNr += runLength;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2009-12-26 19:23:57 +00:00
|
|
|
// No compression (some SCI32 pictures)
|
|
|
|
memcpy(celBitmap, rlePtr, pixelCount);
|
2009-10-11 11:42:50 +00:00
|
|
|
}
|
|
|
|
|
2010-02-06 19:35:51 +00:00
|
|
|
Common::Rect displayArea = _coordAdjuster->pictureGetDisplayArea();
|
|
|
|
|
|
|
|
y = callerY + displayArea.top;
|
|
|
|
lastY = MIN<int16>(height + y, displayArea.bottom);
|
|
|
|
leftX = callerX + displayArea.left;
|
|
|
|
rightX = MIN<int16>(width + leftX, displayArea.right);
|
2009-10-11 11:42:50 +00:00
|
|
|
|
2009-10-29 20:32:55 +00:00
|
|
|
// Change clearcolor to white, if we dont add to an existing picture. That way we will paint everything on screen
|
|
|
|
// but white and that wont matter because the screen is supposed to be already white. It seems that most (if not all)
|
|
|
|
// SCI1.1 games use color 0 as transparency and SCI1 games use color 255 as transparency. Sierra SCI seems to paint
|
|
|
|
// the whole data to screen and wont skip over transparent pixels. So this will actually make it work like Sierra
|
|
|
|
if (!_addToFlag)
|
2010-01-06 13:05:14 +00:00
|
|
|
clearColor = _screen->getColorWhite();
|
2009-10-29 20:32:55 +00:00
|
|
|
|
2010-07-13 15:42:59 +00:00
|
|
|
byte drawMask = priority == 255 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL | GFX_SCREEN_MASK_PRIORITY;
|
|
|
|
|
2009-10-11 11:42:50 +00:00
|
|
|
ptr = celBitmap;
|
|
|
|
if (!_mirroredFlag) {
|
|
|
|
// Draw bitmap to screen
|
2009-10-14 09:46:02 +00:00
|
|
|
x = leftX;
|
2009-10-11 11:42:50 +00:00
|
|
|
while (y < lastY) {
|
|
|
|
curByte = *ptr++;
|
|
|
|
if ((curByte != clearColor) && (priority >= _screen->getPriority(x, y)))
|
2010-07-13 15:42:59 +00:00
|
|
|
_screen->putPixel(x, y, drawMask, curByte, priority, 0);
|
2010-02-01 00:53:13 +00:00
|
|
|
|
2009-10-11 11:42:50 +00:00
|
|
|
x++;
|
2010-02-01 00:53:13 +00:00
|
|
|
|
2009-10-14 09:46:02 +00:00
|
|
|
if (x >= rightX) {
|
2010-02-01 00:53:13 +00:00
|
|
|
if (width > rightX - leftX) // Skip extra pixels at the end of the row
|
|
|
|
ptr += width - (rightX - leftX);
|
|
|
|
x = leftX;
|
|
|
|
y++;
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
}
|
2009-10-11 11:42:50 +00:00
|
|
|
} else {
|
|
|
|
// Draw bitmap to screen (mirrored)
|
2009-10-14 09:46:02 +00:00
|
|
|
x = rightX - 1;
|
2009-10-11 11:42:50 +00:00
|
|
|
while (y < lastY) {
|
|
|
|
curByte = *ptr++;
|
|
|
|
if ((curByte != clearColor) && (priority >= _screen->getPriority(x, y)))
|
2010-07-13 15:42:59 +00:00
|
|
|
_screen->putPixel(x, y, drawMask, curByte, priority, 0);
|
2010-02-01 00:53:13 +00:00
|
|
|
|
2009-10-14 09:46:02 +00:00
|
|
|
if (x == leftX) {
|
2010-02-01 00:53:13 +00:00
|
|
|
if (width > rightX - leftX) // Skip extra pixels at the end of the row
|
|
|
|
ptr += width - (rightX - leftX);
|
|
|
|
x = rightX;
|
|
|
|
y++;
|
2009-10-11 11:42:50 +00:00
|
|
|
}
|
2010-02-01 00:53:13 +00:00
|
|
|
|
2009-10-11 11:42:50 +00:00
|
|
|
x--;
|
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
2010-02-01 00:53:13 +00:00
|
|
|
|
2009-10-11 14:15:37 +00:00
|
|
|
delete[] celBitmap;
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
enum {
|
|
|
|
PIC_OP_SET_COLOR = 0xf0,
|
|
|
|
PIC_OP_DISABLE_VISUAL = 0xf1,
|
|
|
|
PIC_OP_SET_PRIORITY = 0xf2,
|
|
|
|
PIC_OP_DISABLE_PRIORITY = 0xf3,
|
|
|
|
PIC_OP_SHORT_PATTERNS = 0xf4,
|
|
|
|
PIC_OP_MEDIUM_LINES = 0xf5,
|
|
|
|
PIC_OP_LONG_LINES = 0xf6,
|
|
|
|
PIC_OP_SHORT_LINES = 0xf7,
|
|
|
|
PIC_OP_FILL = 0xf8,
|
|
|
|
PIC_OP_SET_PATTERN = 0xf9,
|
|
|
|
PIC_OP_ABSOLUTE_PATTERN = 0xfa,
|
|
|
|
PIC_OP_SET_CONTROL = 0xfb,
|
|
|
|
PIC_OP_DISABLE_CONTROL = 0xfc,
|
|
|
|
PIC_OP_MEDIUM_PATTERNS = 0xfd,
|
|
|
|
PIC_OP_OPX = 0xfe,
|
|
|
|
PIC_OP_TERMINATE = 0xff
|
|
|
|
};
|
|
|
|
#define PIC_OP_FIRST PIC_OP_SET_COLOR
|
|
|
|
|
|
|
|
enum {
|
2009-10-05 20:21:59 +00:00
|
|
|
PIC_OPX_EGA_SET_PALETTE_ENTRIES = 0,
|
|
|
|
PIC_OPX_EGA_SET_PALETTE = 1,
|
|
|
|
PIC_OPX_EGA_MONO0 = 2,
|
|
|
|
PIC_OPX_EGA_MONO1 = 3,
|
|
|
|
PIC_OPX_EGA_MONO2 = 4,
|
|
|
|
PIC_OPX_EGA_MONO3 = 5,
|
|
|
|
PIC_OPX_EGA_MONO4 = 6,
|
|
|
|
PIC_OPX_EGA_EMBEDDED_VIEW = 7,
|
|
|
|
PIC_OPX_EGA_SET_PRIORITY_TABLE = 8
|
2009-10-03 20:49:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
2009-10-05 20:21:59 +00:00
|
|
|
PIC_OPX_VGA_SET_PALETTE_ENTRIES = 0,
|
|
|
|
PIC_OPX_VGA_EMBEDDED_VIEW = 1,
|
|
|
|
PIC_OPX_VGA_SET_PALETTE = 2,
|
|
|
|
PIC_OPX_VGA_PRIORITY_TABLE_EQDIST = 3,
|
|
|
|
PIC_OPX_VGA_PRIORITY_TABLE_EXPLICIT = 4
|
2009-10-03 20:49:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define PIC_EGAPALETTE_COUNT 4
|
|
|
|
#define PIC_EGAPALETTE_SIZE 40
|
|
|
|
#define PIC_EGAPALETTE_TOTALSIZE PIC_EGAPALETTE_COUNT*PIC_EGAPALETTE_SIZE
|
2009-10-06 06:50:31 +00:00
|
|
|
#define PIC_EGAPRIORITY_SIZE PIC_EGAPALETTE_SIZE
|
2009-10-03 20:49:18 +00:00
|
|
|
|
2009-10-04 11:59:29 +00:00
|
|
|
static const byte vector_defaultEGApalette[PIC_EGAPALETTE_SIZE] = {
|
2009-10-03 20:49:18 +00:00
|
|
|
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
|
|
|
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x88,
|
|
|
|
0x88, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x88,
|
|
|
|
0x88, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
|
|
|
|
0x08, 0x91, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x88
|
|
|
|
};
|
|
|
|
|
2009-10-06 06:50:31 +00:00
|
|
|
static const byte vector_defaultEGApriority[PIC_EGAPRIORITY_SIZE] = {
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
|
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
|
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
|
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
|
|
|
|
};
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
void GfxPicture::drawVectorData(byte *data, int dataSize) {
|
2009-10-03 20:49:18 +00:00
|
|
|
byte pic_op;
|
2010-01-06 13:05:14 +00:00
|
|
|
byte pic_color = _screen->getColorDefaultVectorData();
|
2009-10-29 14:16:20 +00:00
|
|
|
byte pic_priority = 255, pic_control = 255;
|
2009-10-03 20:49:18 +00:00
|
|
|
int16 x = 0, y = 0, oldx, oldy;
|
|
|
|
byte EGApalettes[PIC_EGAPALETTE_TOTALSIZE] = {0};
|
2009-10-23 19:08:32 +00:00
|
|
|
byte *EGApalette = &EGApalettes[_EGApaletteNo * PIC_EGAPALETTE_SIZE];
|
2009-10-06 06:50:31 +00:00
|
|
|
byte EGApriority[PIC_EGAPRIORITY_SIZE] = {0};
|
2009-10-05 20:19:07 +00:00
|
|
|
bool isEGA = false;
|
2009-10-03 20:49:18 +00:00
|
|
|
int curPos = 0;
|
|
|
|
uint16 size;
|
2009-12-07 09:30:14 +00:00
|
|
|
byte pixel;
|
2009-10-03 20:49:18 +00:00
|
|
|
int i;
|
2010-01-05 01:37:57 +00:00
|
|
|
Palette palette;
|
2009-10-03 20:49:18 +00:00
|
|
|
int16 pattern_Code = 0, pattern_Texture = 0;
|
2010-05-20 05:48:37 +00:00
|
|
|
bool icemanDrawFix = false;
|
2009-10-03 20:49:18 +00:00
|
|
|
|
2009-10-04 11:59:29 +00:00
|
|
|
memset(&palette, 0, sizeof(palette));
|
|
|
|
|
2009-10-03 20:49:18 +00:00
|
|
|
if (_EGApaletteNo >= PIC_EGAPALETTE_COUNT)
|
|
|
|
_EGApaletteNo = 0;
|
|
|
|
|
2009-10-11 16:12:24 +00:00
|
|
|
if (_resMan->getViewType() == kViewEga) {
|
2009-10-05 20:19:07 +00:00
|
|
|
isEGA = true;
|
2009-10-06 06:50:31 +00:00
|
|
|
// setup default mapping tables
|
|
|
|
for (i = 0; i < PIC_EGAPALETTE_TOTALSIZE; i += PIC_EGAPALETTE_SIZE)
|
|
|
|
memcpy(&EGApalettes[i], &vector_defaultEGApalette, sizeof(vector_defaultEGApalette));
|
|
|
|
memcpy(&EGApriority, &vector_defaultEGApriority, sizeof(vector_defaultEGApriority));
|
2010-05-20 05:48:37 +00:00
|
|
|
|
2010-06-25 16:16:29 +00:00
|
|
|
if (g_sci->getGameId() == GID_ICEMAN) {
|
2010-05-20 05:48:37 +00:00
|
|
|
// WORKAROUND: we remove certain visual&priority lines in underwater rooms of iceman, when not dithering the
|
|
|
|
// picture. Normally those lines aren't shown, because they share the same color as the dithered
|
|
|
|
// fill color combination. When not dithering, those lines would appear and get distracting.
|
|
|
|
if ((_screen->getUnditherState()) && ((_resourceId >= 53 && _resourceId <= 58) || (_resourceId == 61)))
|
|
|
|
icemanDrawFix = true;
|
|
|
|
}
|
2009-10-06 06:50:31 +00:00
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
|
|
|
|
// Drawing
|
|
|
|
while (curPos < dataSize) {
|
2010-01-25 10:17:55 +00:00
|
|
|
//warning("%X at %d", data[curPos], curPos);
|
2009-10-03 20:49:18 +00:00
|
|
|
switch (pic_op = data[curPos++]) {
|
|
|
|
case PIC_OP_SET_COLOR:
|
2009-10-05 22:42:41 +00:00
|
|
|
pic_color = data[curPos++];
|
|
|
|
if (isEGA) {
|
|
|
|
pic_color = EGApalette[pic_color];
|
|
|
|
pic_color ^= pic_color << 4;
|
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
break;
|
|
|
|
case PIC_OP_DISABLE_VISUAL:
|
|
|
|
pic_color = 0xFF;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIC_OP_SET_PRIORITY:
|
2009-10-09 16:51:10 +00:00
|
|
|
pic_priority = data[curPos++] & 0x0F;
|
2009-10-06 06:50:31 +00:00
|
|
|
if (isEGA) {
|
2009-10-07 16:16:34 +00:00
|
|
|
pic_priority = EGApriority[pic_priority];
|
2009-10-06 06:50:31 +00:00
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
break;
|
|
|
|
case PIC_OP_DISABLE_PRIORITY:
|
|
|
|
pic_priority = 255;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIC_OP_SET_CONTROL:
|
2009-10-09 16:51:10 +00:00
|
|
|
pic_control = data[curPos++] & 0x0F;
|
2009-10-03 20:49:18 +00:00
|
|
|
break;
|
|
|
|
case PIC_OP_DISABLE_CONTROL:
|
|
|
|
pic_control = 255;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIC_OP_SHORT_LINES: // short line
|
2009-10-06 17:17:12 +00:00
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
2009-10-03 20:49:18 +00:00
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
|
|
|
oldx = x; oldy = y;
|
2009-10-06 17:17:12 +00:00
|
|
|
vectorGetRelCoords(data, curPos, x, y);
|
2009-10-12 08:25:38 +00:00
|
|
|
Common::Point startPoint(oldx, oldy);
|
|
|
|
Common::Point endPoint(x, y);
|
2010-01-31 12:35:15 +00:00
|
|
|
_ports->offsetLine(startPoint, endPoint);
|
2009-10-12 08:25:38 +00:00
|
|
|
_screen->drawLine(startPoint, endPoint, pic_color, pic_priority, pic_control);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PIC_OP_MEDIUM_LINES: // medium line
|
2009-10-06 17:17:12 +00:00
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
2010-05-20 05:48:37 +00:00
|
|
|
if (icemanDrawFix) {
|
|
|
|
// WORKAROUND: remove certain lines in iceman ffs. see above
|
|
|
|
if ((pic_color == 1) && (pic_priority == 14)) {
|
|
|
|
if ((y < 100) || (!(y & 1))) {
|
|
|
|
pic_color = 255;
|
|
|
|
pic_priority = 255;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
|
|
|
oldx = x; oldy = y;
|
2009-10-06 17:17:12 +00:00
|
|
|
vectorGetRelCoordsMed(data, curPos, x, y);
|
2009-10-12 08:25:38 +00:00
|
|
|
Common::Point startPoint(oldx, oldy);
|
|
|
|
Common::Point endPoint(x, y);
|
2010-01-31 12:35:15 +00:00
|
|
|
_ports->offsetLine(startPoint, endPoint);
|
2009-10-12 08:25:38 +00:00
|
|
|
_screen->drawLine(startPoint, endPoint, pic_color, pic_priority, pic_control);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PIC_OP_LONG_LINES: // long line
|
2009-10-06 17:17:12 +00:00
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
2009-10-03 20:49:18 +00:00
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
2009-10-06 17:17:12 +00:00
|
|
|
oldx = x; oldy = y;
|
2009-10-03 20:49:18 +00:00
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
2009-10-12 08:25:38 +00:00
|
|
|
Common::Point startPoint(oldx, oldy);
|
|
|
|
Common::Point endPoint(x, y);
|
2010-01-31 12:35:15 +00:00
|
|
|
_ports->offsetLine(startPoint, endPoint);
|
2009-10-12 08:25:38 +00:00
|
|
|
_screen->drawLine(startPoint, endPoint, pic_color, pic_priority, pic_control);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIC_OP_FILL: //fill
|
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
2009-10-09 18:06:24 +00:00
|
|
|
vectorFloodFill(x, y, pic_color, pic_priority, pic_control);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2010-05-25 18:48:50 +00:00
|
|
|
// Pattern opcodes are handled in sierra sci1.1+ as actual NOPs and normally they definitely should not occur
|
|
|
|
// inside picture data for such games
|
2009-10-03 20:49:18 +00:00
|
|
|
case PIC_OP_SET_PATTERN:
|
2010-05-25 18:45:25 +00:00
|
|
|
if (_resourceType >= SCI_PICTURE_TYPE_SCI11) {
|
2010-06-25 16:16:29 +00:00
|
|
|
if (g_sci->getGameId() == GID_SQ4) {
|
2010-05-26 17:15:49 +00:00
|
|
|
// WORKAROUND: For SQ4 / for some pictures handle this like a terminator
|
2010-05-25 18:45:25 +00:00
|
|
|
// This picture includes garbage data, first a set pattern w/o parameter and then short pattern
|
2010-05-26 17:15:49 +00:00
|
|
|
// I guess that garbage is a left over from the sq4-floppy (sci1) to sq4-cd (sci1.1) conversion
|
|
|
|
switch (_resourceId) {
|
2010-07-21 20:13:24 +00:00
|
|
|
case 35:
|
2010-05-26 17:15:49 +00:00
|
|
|
case 381:
|
|
|
|
case 376:
|
2010-05-25 18:45:25 +00:00
|
|
|
return;
|
2010-05-26 17:15:49 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2010-05-25 18:45:25 +00:00
|
|
|
}
|
|
|
|
error("pic-operation set pattern inside sci1.1+ vector data");
|
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
pattern_Code = data[curPos++];
|
|
|
|
break;
|
|
|
|
case PIC_OP_SHORT_PATTERNS:
|
2010-05-25 18:45:25 +00:00
|
|
|
if (_resourceType >= SCI_PICTURE_TYPE_SCI11)
|
|
|
|
error("pic-operation short pattern inside sci1.1+ vector data");
|
2009-10-03 20:49:18 +00:00
|
|
|
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
|
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
2009-10-09 18:06:24 +00:00
|
|
|
vectorPattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
|
2009-10-03 20:49:18 +00:00
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
|
|
|
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
|
2009-10-06 17:17:12 +00:00
|
|
|
vectorGetRelCoords(data, curPos, x, y);
|
2009-10-09 18:06:24 +00:00
|
|
|
vectorPattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PIC_OP_MEDIUM_PATTERNS:
|
2010-05-25 18:45:25 +00:00
|
|
|
if (_resourceType >= SCI_PICTURE_TYPE_SCI11)
|
|
|
|
error("pic-operation medium pattern inside sci1.1+ vector data");
|
2009-10-03 20:49:18 +00:00
|
|
|
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
|
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
2009-10-09 18:06:24 +00:00
|
|
|
vectorPattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
|
2009-10-03 20:49:18 +00:00
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
|
|
|
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
|
2009-10-06 17:17:12 +00:00
|
|
|
vectorGetRelCoordsMed(data, curPos, x, y);
|
2009-10-09 18:06:24 +00:00
|
|
|
vectorPattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PIC_OP_ABSOLUTE_PATTERN:
|
2010-05-25 18:45:25 +00:00
|
|
|
if (_resourceType >= SCI_PICTURE_TYPE_SCI11)
|
|
|
|
error("pic-operation absolute pattern inside sci1.1+ vector data");
|
2009-10-03 20:49:18 +00:00
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
|
|
|
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
|
|
|
|
vectorGetAbsCoords(data, curPos, x, y);
|
2009-10-09 18:06:24 +00:00
|
|
|
vectorPattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIC_OP_OPX: // Extended functions
|
2009-10-05 20:19:07 +00:00
|
|
|
if (isEGA) {
|
2009-10-03 20:49:18 +00:00
|
|
|
switch (pic_op = data[curPos++]) {
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_EGA_SET_PALETTE_ENTRIES:
|
2009-10-03 20:49:18 +00:00
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
2009-12-07 09:30:14 +00:00
|
|
|
pixel = data[curPos++];
|
|
|
|
if (pixel >= PIC_EGAPALETTE_TOTALSIZE) {
|
2009-10-03 20:49:18 +00:00
|
|
|
error("picture trying to write to invalid EGA-palette");
|
|
|
|
}
|
2009-12-07 09:30:14 +00:00
|
|
|
EGApalettes[pixel] = data[curPos++];
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_EGA_SET_PALETTE:
|
2009-12-07 09:30:14 +00:00
|
|
|
pixel = data[curPos++];
|
|
|
|
if (pixel >= PIC_EGAPALETTE_COUNT) {
|
|
|
|
error("picture trying to write to invalid palette %d", (int)pixel);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
2009-12-07 09:30:14 +00:00
|
|
|
pixel *= PIC_EGAPALETTE_SIZE;
|
2009-10-03 20:49:18 +00:00
|
|
|
for (i = 0; i < PIC_EGAPALETTE_SIZE; i++) {
|
2009-12-07 09:30:14 +00:00
|
|
|
EGApalettes[pixel + i] = data[curPos++];
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_EGA_MONO0:
|
2009-10-03 20:49:18 +00:00
|
|
|
curPos += 41;
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_EGA_MONO1:
|
|
|
|
case PIC_OPX_EGA_MONO3:
|
2009-10-03 20:49:18 +00:00
|
|
|
curPos++;
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_EGA_MONO2:
|
|
|
|
case PIC_OPX_EGA_MONO4:
|
2009-10-03 20:49:18 +00:00
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_EGA_EMBEDDED_VIEW:
|
2009-10-19 18:06:33 +00:00
|
|
|
vectorGetAbsCoordsNoMirror(data, curPos, x, y);
|
2009-10-03 20:49:18 +00:00
|
|
|
size = READ_LE_UINT16(data + curPos); curPos += 2;
|
2009-10-16 11:46:18 +00:00
|
|
|
_priority = pic_priority; // set global priority so the cel gets drawn using current priority as well
|
2010-05-25 18:45:25 +00:00
|
|
|
drawCelData(data, _resource->size, curPos, curPos + 8, 0, x, y);
|
2009-10-03 20:49:18 +00:00
|
|
|
curPos += size;
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_EGA_SET_PRIORITY_TABLE:
|
2010-01-31 12:35:15 +00:00
|
|
|
_ports->priorityBandsInit(data + curPos);
|
2009-10-03 20:49:18 +00:00
|
|
|
curPos += 14;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error("Unsupported sci1 extended pic-operation %X", pic_op);
|
|
|
|
}
|
2009-10-05 20:19:07 +00:00
|
|
|
} else {
|
|
|
|
switch (pic_op = data[curPos++]) {
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_VGA_SET_PALETTE_ENTRIES:
|
2009-10-05 20:19:07 +00:00
|
|
|
while (vectorIsNonOpcode(data[curPos])) {
|
|
|
|
curPos++; // skip commands
|
|
|
|
}
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_VGA_SET_PALETTE:
|
2010-01-25 12:34:40 +00:00
|
|
|
if (_resMan->isAmiga32color()) {
|
2010-01-25 10:17:55 +00:00
|
|
|
if ((data[curPos] == 0x00) && (data[curPos + 1] == 0x01) && ((data[curPos + 32] & 0xF0) != 0xF0)) {
|
|
|
|
// Left-Over VGA palette, we simply ignore it
|
2010-01-25 17:09:31 +00:00
|
|
|
curPos += 256 + 4 + 1024;
|
2010-01-25 10:17:55 +00:00
|
|
|
} else {
|
2010-01-25 11:26:32 +00:00
|
|
|
// Setting half of the amiga palette
|
2010-01-25 11:15:40 +00:00
|
|
|
_palette->modifyAmigaPalette(&data[curPos]);
|
2010-01-25 10:17:55 +00:00
|
|
|
curPos += 32;
|
|
|
|
}
|
2010-01-24 21:46:30 +00:00
|
|
|
} else {
|
|
|
|
curPos += 256 + 4; // Skip over mapping and timestamp
|
|
|
|
for (i = 0; i < 256; i++) {
|
|
|
|
palette.colors[i].used = data[curPos++];
|
|
|
|
palette.colors[i].r = data[curPos++]; palette.colors[i].g = data[curPos++]; palette.colors[i].b = data[curPos++];
|
|
|
|
}
|
2010-01-26 22:45:52 +00:00
|
|
|
_palette->set(&palette, true);
|
2009-10-05 20:19:07 +00:00
|
|
|
}
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_VGA_EMBEDDED_VIEW: // draw cel
|
2009-10-19 18:06:33 +00:00
|
|
|
vectorGetAbsCoordsNoMirror(data, curPos, x, y);
|
2009-10-05 20:19:07 +00:00
|
|
|
size = READ_LE_UINT16(data + curPos); curPos += 2;
|
2009-10-16 11:46:18 +00:00
|
|
|
_priority = pic_priority; // set global priority so the cel gets drawn using current priority as well
|
2010-05-25 18:45:25 +00:00
|
|
|
drawCelData(data, _resource->size, curPos, curPos + 8, 0, x, y);
|
2009-10-05 20:19:07 +00:00
|
|
|
curPos += size;
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_VGA_PRIORITY_TABLE_EQDIST:
|
2010-01-31 12:35:15 +00:00
|
|
|
_ports->priorityBandsInit(-1, READ_LE_UINT16(data + curPos), READ_LE_UINT16(data + curPos + 2));
|
2009-10-05 20:19:07 +00:00
|
|
|
curPos += 4;
|
|
|
|
break;
|
2009-10-05 20:21:59 +00:00
|
|
|
case PIC_OPX_VGA_PRIORITY_TABLE_EXPLICIT:
|
2010-01-31 12:35:15 +00:00
|
|
|
_ports->priorityBandsInit(data + curPos);
|
2009-10-05 20:19:07 +00:00
|
|
|
curPos += 14;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error("Unsupported sci1 extended pic-operation %X", pic_op);
|
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PIC_OP_TERMINATE:
|
|
|
|
_priority = pic_priority;
|
2009-10-05 21:38:51 +00:00
|
|
|
// Dithering EGA pictures
|
|
|
|
if (isEGA) {
|
2009-10-09 20:54:02 +00:00
|
|
|
_screen->dither(_addToFlag);
|
2009-10-05 21:38:51 +00:00
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
return;
|
|
|
|
default:
|
|
|
|
error("Unsupported pic-operation %X", pic_op);
|
|
|
|
}
|
2010-01-09 14:09:45 +00:00
|
|
|
if ((_EGAdrawingVisualize) && (isEGA)) {
|
|
|
|
_screen->copyToScreen();
|
|
|
|
g_system->updateScreen();
|
|
|
|
g_system->delayMillis(10);
|
|
|
|
}
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
error("picture vector data without terminator");
|
|
|
|
}
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
bool GfxPicture::vectorIsNonOpcode(byte pixel) {
|
2009-12-07 09:30:14 +00:00
|
|
|
if (pixel >= PIC_OP_FIRST)
|
2009-10-03 20:49:18 +00:00
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
void GfxPicture::vectorGetAbsCoords(byte *data, int &curPos, int16 &x, int16 &y) {
|
2009-12-07 09:30:14 +00:00
|
|
|
byte pixel = data[curPos++];
|
|
|
|
x = data[curPos++] + ((pixel & 0xF0) << 4);
|
|
|
|
y = data[curPos++] + ((pixel & 0x0F) << 8);
|
2009-10-07 20:58:33 +00:00
|
|
|
if (_mirroredFlag) x = 319 - x;
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
void GfxPicture::vectorGetAbsCoordsNoMirror(byte *data, int &curPos, int16 &x, int16 &y) {
|
2009-12-07 09:30:14 +00:00
|
|
|
byte pixel = data[curPos++];
|
|
|
|
x = data[curPos++] + ((pixel & 0xF0) << 4);
|
|
|
|
y = data[curPos++] + ((pixel & 0x0F) << 8);
|
2009-10-19 18:06:33 +00:00
|
|
|
}
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
void GfxPicture::vectorGetRelCoords(byte *data, int &curPos, int16 &x, int16 &y) {
|
2009-12-07 09:30:14 +00:00
|
|
|
byte pixel = data[curPos++];
|
|
|
|
if (pixel & 0x80) {
|
|
|
|
x -= ((pixel >> 4) & 7) * (_mirroredFlag ? -1 : 1);
|
2009-10-03 20:49:18 +00:00
|
|
|
} else {
|
2009-12-07 09:30:14 +00:00
|
|
|
x += (pixel >> 4) * (_mirroredFlag ? -1 : 1);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
2009-12-07 09:30:14 +00:00
|
|
|
if (pixel & 0x08) {
|
|
|
|
y -= (pixel & 7);
|
2009-10-03 20:49:18 +00:00
|
|
|
} else {
|
2009-12-07 09:30:14 +00:00
|
|
|
y += (pixel & 7);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
void GfxPicture::vectorGetRelCoordsMed(byte *data, int &curPos, int16 &x, int16 &y) {
|
2009-12-07 09:30:14 +00:00
|
|
|
byte pixel = data[curPos++];
|
|
|
|
if (pixel & 0x80) {
|
|
|
|
y -= (pixel & 0x7F);
|
2009-10-03 20:49:18 +00:00
|
|
|
} else {
|
2009-12-07 09:30:14 +00:00
|
|
|
y += pixel;
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
2009-12-07 09:30:14 +00:00
|
|
|
pixel = data[curPos++];
|
|
|
|
if (pixel & 0x80) {
|
|
|
|
x -= (128 - (pixel & 0x7F)) * (_mirroredFlag ? -1 : 1);
|
2009-10-03 20:49:18 +00:00
|
|
|
} else {
|
2009-12-07 09:30:14 +00:00
|
|
|
x += pixel * (_mirroredFlag ? -1 : 1);
|
2009-10-03 20:49:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
void GfxPicture::vectorGetPatternTexture(byte *data, int &curPos, int16 pattern_Code, int16 &pattern_Texture) {
|
2009-10-03 20:49:18 +00:00
|
|
|
if (pattern_Code & SCI_PATTERN_CODE_USE_TEXTURE) {
|
|
|
|
pattern_Texture = (data[curPos++] >> 1) & 0x7f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-09 18:06:24 +00:00
|
|
|
// Do not replace w/ some generic code. This algo really needs to behave exactly as the one from sierra
|
2010-02-05 12:14:03 +00:00
|
|
|
void GfxPicture::vectorFloodFill(int16 x, int16 y, byte color, byte priority, byte control) {
|
2010-01-31 12:35:15 +00:00
|
|
|
Port *curPort = _ports->getPort();
|
2009-10-09 18:06:24 +00:00
|
|
|
Common::Stack<Common::Point> stack;
|
|
|
|
Common::Point p, p1;
|
2009-10-13 08:03:09 +00:00
|
|
|
byte screenMask = _screen->getDrawingMask(color, priority, control);
|
2009-10-28 15:07:24 +00:00
|
|
|
byte matchedMask, matchMask;
|
2009-10-13 08:03:09 +00:00
|
|
|
int16 w, e, a_set, b_set;
|
2009-10-09 18:06:24 +00:00
|
|
|
|
|
|
|
p.x = x + curPort->left;
|
|
|
|
p.y = y + curPort->top;
|
|
|
|
stack.push(p);
|
|
|
|
|
|
|
|
byte searchColor = _screen->getVisual(p.x, p.y);
|
|
|
|
byte searchPriority = _screen->getPriority(p.x, p.y);
|
|
|
|
byte searchControl = _screen->getControl(p.x, p.y);
|
2009-10-13 08:03:09 +00:00
|
|
|
|
2009-10-28 15:15:18 +00:00
|
|
|
// This logic was taken directly from sierra sci, floodfill will get aborted on various occations
|
2010-05-15 08:57:13 +00:00
|
|
|
if (screenMask & GFX_SCREEN_MASK_VISUAL) {
|
2010-01-06 13:05:14 +00:00
|
|
|
if ((color == _screen->getColorWhite()) || (searchColor != _screen->getColorWhite()))
|
2009-10-29 14:16:20 +00:00
|
|
|
return;
|
2010-05-15 08:57:13 +00:00
|
|
|
} else if (screenMask & GFX_SCREEN_MASK_PRIORITY) {
|
2009-10-28 15:15:18 +00:00
|
|
|
if ((priority == 0) || (searchPriority != 0))
|
|
|
|
return;
|
2010-05-15 08:57:13 +00:00
|
|
|
} else if (screenMask & GFX_SCREEN_MASK_CONTROL) {
|
2009-10-28 15:15:18 +00:00
|
|
|
if ((control == 0) || (searchControl != 0))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-28 15:07:24 +00:00
|
|
|
// Now remove screens, that already got the right color/priority/control
|
2010-05-15 08:57:13 +00:00
|
|
|
if ((screenMask & GFX_SCREEN_MASK_VISUAL) && (searchColor == color))
|
|
|
|
screenMask ^= GFX_SCREEN_MASK_VISUAL;
|
|
|
|
if ((screenMask & GFX_SCREEN_MASK_PRIORITY) && (searchPriority == priority))
|
|
|
|
screenMask ^= GFX_SCREEN_MASK_PRIORITY;
|
|
|
|
if ((screenMask & GFX_SCREEN_MASK_CONTROL) && (searchControl == control))
|
|
|
|
screenMask ^= GFX_SCREEN_MASK_CONTROL;
|
2009-10-28 15:07:24 +00:00
|
|
|
|
|
|
|
// Exit, if no screens left
|
|
|
|
if (!screenMask)
|
|
|
|
return;
|
|
|
|
|
2010-05-15 08:57:13 +00:00
|
|
|
if (screenMask & GFX_SCREEN_MASK_VISUAL) {
|
|
|
|
matchMask = GFX_SCREEN_MASK_VISUAL;
|
|
|
|
} else if (screenMask & GFX_SCREEN_MASK_PRIORITY) {
|
|
|
|
matchMask = GFX_SCREEN_MASK_PRIORITY;
|
2009-10-28 15:15:18 +00:00
|
|
|
} else {
|
2010-05-15 08:57:13 +00:00
|
|
|
matchMask = GFX_SCREEN_MASK_CONTROL;
|
2009-10-13 08:03:09 +00:00
|
|
|
}
|
2009-10-09 18:06:24 +00:00
|
|
|
|
|
|
|
// hard borders for filling
|
|
|
|
int l = curPort->rect.left + curPort->left;
|
|
|
|
int t = curPort->rect.top + curPort->top;
|
|
|
|
int r = curPort->rect.right + curPort->left - 1;
|
|
|
|
int b = curPort->rect.bottom + curPort->top - 1;
|
|
|
|
while (stack.size()) {
|
|
|
|
p = stack.pop();
|
2009-10-28 15:07:24 +00:00
|
|
|
if ((matchedMask = _screen->isFillMatch(p.x, p.y, matchMask, searchColor, searchPriority, searchControl)) == 0) // already filled
|
2009-10-09 18:06:24 +00:00
|
|
|
continue;
|
|
|
|
_screen->putPixel(p.x, p.y, screenMask, color, priority, control);
|
|
|
|
w = p.x;
|
|
|
|
e = p.x;
|
|
|
|
// moving west and east pointers as long as there is a matching color to fill
|
2009-10-28 15:07:24 +00:00
|
|
|
while (w > l && (matchedMask = _screen->isFillMatch(w - 1, p.y, matchMask, searchColor, searchPriority, searchControl)))
|
2009-10-13 08:03:09 +00:00
|
|
|
_screen->putPixel(--w, p.y, screenMask, color, priority, control);
|
2009-10-28 15:07:24 +00:00
|
|
|
while (e < r && (matchedMask = _screen->isFillMatch(e + 1, p.y, matchMask, searchColor, searchPriority, searchControl)))
|
2009-10-13 08:03:09 +00:00
|
|
|
_screen->putPixel(++e, p.y, screenMask, color, priority, control);
|
2009-10-09 18:06:24 +00:00
|
|
|
// checking lines above and below for possible flood targets
|
|
|
|
a_set = b_set = 0;
|
|
|
|
while (w <= e) {
|
2009-10-28 15:07:24 +00:00
|
|
|
if (p.y > t && (matchedMask = _screen->isFillMatch(w, p.y - 1, matchMask, searchColor, searchPriority, searchControl))) { // one line above
|
2009-10-09 18:06:24 +00:00
|
|
|
if (a_set == 0) {
|
|
|
|
p1.x = w;
|
|
|
|
p1.y = p.y - 1;
|
|
|
|
stack.push(p1);
|
|
|
|
a_set = 1;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
a_set = 0;
|
|
|
|
|
2009-10-28 15:07:24 +00:00
|
|
|
if (p.y < b && (matchedMask = _screen->isFillMatch(w, p.y + 1, matchMask, searchColor, searchPriority, searchControl))) { // one line below
|
2009-10-09 18:06:24 +00:00
|
|
|
if (b_set == 0) {
|
|
|
|
p1.x = w;
|
|
|
|
p1.y = p.y + 1;
|
|
|
|
stack.push(p1);
|
|
|
|
b_set = 1;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
b_set = 0;
|
|
|
|
w++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bitmap for drawing sierra circles
|
|
|
|
static const byte vectorPatternCircles[8][30] = {
|
|
|
|
{ 0x01 },
|
2009-10-25 08:46:56 +00:00
|
|
|
{ 0x72, 0x02 },
|
2009-10-09 18:06:24 +00:00
|
|
|
{ 0xCE, 0xF7, 0x7D, 0x0E },
|
|
|
|
{ 0x1C, 0x3E, 0x7F, 0x7F, 0x7F, 0x3E, 0x1C, 0x00 },
|
|
|
|
{ 0x38, 0xF8, 0xF3, 0xDF, 0x7F, 0xFF, 0xFD, 0xF7, 0x9F, 0x3F, 0x38 },
|
|
|
|
{ 0x70, 0xC0, 0x1F, 0xFE, 0xE3, 0x3F, 0xFF, 0xF7, 0x7F, 0xFF, 0xE7, 0x3F, 0xFE, 0xC3, 0x1F, 0xF8, 0x00 },
|
|
|
|
{ 0xF0, 0x01, 0xFF, 0xE1, 0xFF, 0xF8, 0x3F, 0xFF, 0xDF, 0xFF, 0xF7, 0xFF, 0xFD, 0x7F, 0xFF, 0x9F, 0xFF,
|
|
|
|
0xE3, 0xFF, 0xF0, 0x1F, 0xF0, 0x01 },
|
|
|
|
{ 0xE0, 0x03, 0xF8, 0x0F, 0xFC, 0x1F, 0xFE, 0x3F, 0xFE, 0x3F, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF,
|
|
|
|
0x7F, 0xFF, 0x7F, 0xFE, 0x3F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8, 0x0F, 0xE0, 0x03 }
|
|
|
|
// { 0x01 };
|
|
|
|
// { 0x03, 0x03, 0x03 },
|
|
|
|
// { 0x02, 0x07, 0x07, 0x07, 0x02 },
|
|
|
|
// { 0x06, 0x06, 0x0F, 0x0F, 0x0F, 0x06, 0x06 },
|
|
|
|
// { 0x04, 0x0E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x04 },
|
|
|
|
// { 0x0C, 0x1E, 0x1E, 0x1E, 0x3F, 0x3F, 0x3F, 0x1E, 0x1E, 0x1E, 0x0C },
|
|
|
|
// { 0x1C, 0x3E, 0x3E, 0x3E, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x3E, 0x3E, 0x3E, 0x1C },
|
|
|
|
// { 0x18, 0x3C, 0x7E, 0x7E, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x7E, 0x7E, 0x3C, 0x18 }
|
|
|
|
};
|
|
|
|
|
|
|
|
// TODO: perhaps this is a better way to set the s_patternTextures array below?
|
|
|
|
// in that case one would need to adjust bits of secondary table. Bit 256 is ignored by original interpreter
|
|
|
|
#if 0
|
|
|
|
static const byte patternTextures[32 * 2] = {
|
|
|
|
0x04, 0x29, 0x40, 0x24, 0x09, 0x41, 0x25, 0x45,
|
|
|
|
0x41, 0x90, 0x50, 0x44, 0x48, 0x08, 0x42, 0x28,
|
|
|
|
0x89, 0x52, 0x89, 0x88, 0x10, 0x48, 0xA4, 0x08,
|
|
|
|
0x44, 0x15, 0x28, 0x24, 0x00, 0x0A, 0x24, 0x20,
|
|
|
|
// Now the table is actually duplicated, so we won't need to wrap around
|
|
|
|
0x04, 0x29, 0x40, 0x24, 0x09, 0x41, 0x25, 0x45,
|
|
|
|
0x41, 0x90, 0x50, 0x44, 0x48, 0x08, 0x42, 0x28,
|
|
|
|
0x89, 0x52, 0x89, 0x88, 0x10, 0x48, 0xA4, 0x08,
|
|
|
|
0x44, 0x15, 0x28, 0x24, 0x00, 0x0A, 0x24, 0x20,
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// This table is bitwise upwards (from bit0 to bit7), sierras original table went down the bits (bit7 to bit0)
|
|
|
|
// this was done to simplify things, so we can just run through the table w/o worrying too much about clipping
|
|
|
|
static const bool vectorPatternTextures[32 * 8 * 2] = {
|
|
|
|
false, false, true, false, false, false, false, false, // 0x04
|
|
|
|
true, false, false, true, false, true, false, false, // 0x29
|
|
|
|
false, false, false, false, false, false, true, false, // 0x40
|
|
|
|
false, false, true, false, false, true, false, false, // 0x24
|
|
|
|
true, false, false, true, false, false, false, false, // 0x09
|
|
|
|
true, false, false, false, false, false, true, false, // 0x41
|
|
|
|
true, false, true, false, false, true, false, false, // 0x25
|
|
|
|
true, false, true, false, false, false, true, false, // 0x45
|
|
|
|
true, false, false, false, false, false, true, false, // 0x41
|
|
|
|
false, false, false, false, true, false, false, true, // 0x90
|
|
|
|
false, false, false, false, true, false, true, false, // 0x50
|
|
|
|
false, false, true, false, false, false, true, false, // 0x44
|
|
|
|
false, false, false, true, false, false, true, false, // 0x48
|
|
|
|
false, false, false, true, false, false, false, false, // 0x08
|
|
|
|
false, true, false, false, false, false, true, false, // 0x42
|
|
|
|
false, false, false, true, false, true, false, false, // 0x28
|
|
|
|
true, false, false, true, false, false, false, true, // 0x89
|
|
|
|
false, true, false, false, true, false, true, false, // 0x52
|
|
|
|
true, false, false, true, false, false, false, true, // 0x89
|
|
|
|
false, false, false, true, false, false, false, true, // 0x88
|
|
|
|
false, false, false, false, true, false, false, false, // 0x10
|
|
|
|
false, false, false, true, false, false, true, false, // 0x48
|
|
|
|
false, false, true, false, false, true, false, true, // 0xA4
|
|
|
|
false, false, false, true, false, false, false, false, // 0x08
|
|
|
|
false, false, true, false, false, false, true, false, // 0x44
|
|
|
|
true, false, true, false, true, false, false, false, // 0x15
|
|
|
|
false, false, false, true, false, true, false, false, // 0x28
|
|
|
|
false, false, true, false, false, true, false, false, // 0x24
|
|
|
|
false, false, false, false, false, false, false, false, // 0x00
|
|
|
|
false, true, false, true, false, false, false, false, // 0x0A
|
|
|
|
false, false, true, false, false, true, false, false, // 0x24
|
|
|
|
false, false, false, false, false, true, false, // 0x20 (last bit is not mentioned cause original interpreter also ignores that bit)
|
|
|
|
// Now the table is actually duplicated, so we won't need to wrap around
|
|
|
|
false, false, true, false, false, false, false, false, // 0x04
|
|
|
|
true, false, false, true, false, true, false, false, // 0x29
|
|
|
|
false, false, false, false, false, false, true, false, // 0x40
|
|
|
|
false, false, true, false, false, true, false, false, // 0x24
|
|
|
|
true, false, false, true, false, false, false, false, // 0x09
|
|
|
|
true, false, false, false, false, false, true, false, // 0x41
|
|
|
|
true, false, true, false, false, true, false, false, // 0x25
|
|
|
|
true, false, true, false, false, false, true, false, // 0x45
|
|
|
|
true, false, false, false, false, false, true, false, // 0x41
|
|
|
|
false, false, false, false, true, false, false, true, // 0x90
|
|
|
|
false, false, false, false, true, false, true, false, // 0x50
|
|
|
|
false, false, true, false, false, false, true, false, // 0x44
|
|
|
|
false, false, false, true, false, false, true, false, // 0x48
|
|
|
|
false, false, false, true, false, false, false, false, // 0x08
|
|
|
|
false, true, false, false, false, false, true, false, // 0x42
|
|
|
|
false, false, false, true, false, true, false, false, // 0x28
|
|
|
|
true, false, false, true, false, false, false, true, // 0x89
|
|
|
|
false, true, false, false, true, false, true, false, // 0x52
|
|
|
|
true, false, false, true, false, false, false, true, // 0x89
|
|
|
|
false, false, false, true, false, false, false, true, // 0x88
|
|
|
|
false, false, false, false, true, false, false, false, // 0x10
|
|
|
|
false, false, false, true, false, false, true, false, // 0x48
|
|
|
|
false, false, true, false, false, true, false, true, // 0xA4
|
|
|
|
false, false, false, true, false, false, false, false, // 0x08
|
|
|
|
false, false, true, false, false, false, true, false, // 0x44
|
|
|
|
true, false, true, false, true, false, false, false, // 0x15
|
|
|
|
false, false, false, true, false, true, false, false, // 0x28
|
|
|
|
false, false, true, false, false, true, false, false, // 0x24
|
|
|
|
false, false, false, false, false, false, false, false, // 0x00
|
|
|
|
false, true, false, true, false, false, false, false, // 0x0A
|
|
|
|
false, false, true, false, false, true, false, false, // 0x24
|
|
|
|
false, false, false, false, false, true, false, // 0x20 (last bit is not mentioned cause original interpreter also ignores that bit)
|
|
|
|
};
|
|
|
|
|
|
|
|
// Bit offsets into pattern_textures
|
|
|
|
static const byte vectorPatternTextureOffset[128] = {
|
|
|
|
0x00, 0x18, 0x30, 0xc4, 0xdc, 0x65, 0xeb, 0x48,
|
|
|
|
0x60, 0xbd, 0x89, 0x05, 0x0a, 0xf4, 0x7d, 0x7d,
|
|
|
|
0x85, 0xb0, 0x8e, 0x95, 0x1f, 0x22, 0x0d, 0xdf,
|
|
|
|
0x2a, 0x78, 0xd5, 0x73, 0x1c, 0xb4, 0x40, 0xa1,
|
|
|
|
0xb9, 0x3c, 0xca, 0x58, 0x92, 0x34, 0xcc, 0xce,
|
|
|
|
0xd7, 0x42, 0x90, 0x0f, 0x8b, 0x7f, 0x32, 0xed,
|
|
|
|
0x5c, 0x9d, 0xc8, 0x99, 0xad, 0x4e, 0x56, 0xa6,
|
|
|
|
0xf7, 0x68, 0xb7, 0x25, 0x82, 0x37, 0x3a, 0x51,
|
|
|
|
0x69, 0x26, 0x38, 0x52, 0x9e, 0x9a, 0x4f, 0xa7,
|
|
|
|
0x43, 0x10, 0x80, 0xee, 0x3d, 0x59, 0x35, 0xcf,
|
|
|
|
0x79, 0x74, 0xb5, 0xa2, 0xb1, 0x96, 0x23, 0xe0,
|
|
|
|
0xbe, 0x05, 0xf5, 0x6e, 0x19, 0xc5, 0x66, 0x49,
|
|
|
|
0xf0, 0xd1, 0x54, 0xa9, 0x70, 0x4b, 0xa4, 0xe2,
|
|
|
|
0xe6, 0xe5, 0xab, 0xe4, 0xd2, 0xaa, 0x4c, 0xe3,
|
|
|
|
0x06, 0x6f, 0xc6, 0x4a, 0xa4, 0x75, 0x97, 0xe1
|
|
|
|
};
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
void GfxPicture::vectorPatternBox(Common::Rect box, byte color, byte prio, byte control) {
|
2009-10-09 18:06:24 +00:00
|
|
|
byte flag = _screen->getDrawingMask(color, prio, control);
|
|
|
|
int y, x;
|
|
|
|
|
|
|
|
for (y = box.top; y < box.bottom; y++) {
|
|
|
|
for (x = box.left; x < box.right; x++) {
|
|
|
|
_screen->putPixel(x, y, flag, color, prio, control);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
void GfxPicture::vectorPatternTexturedBox(Common::Rect box, byte color, byte prio, byte control, byte texture) {
|
2009-10-09 18:06:24 +00:00
|
|
|
byte flag = _screen->getDrawingMask(color, prio, control);
|
|
|
|
const bool *textureData = &vectorPatternTextures[vectorPatternTextureOffset[texture]];
|
|
|
|
int y, x;
|
|
|
|
|
|
|
|
for (y = box.top; y < box.bottom; y++) {
|
|
|
|
for (x = box.left; x < box.right; x++) {
|
|
|
|
if (*textureData) {
|
|
|
|
_screen->putPixel(x, y, flag, color, prio, control);
|
|
|
|
}
|
|
|
|
textureData++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
void GfxPicture::vectorPatternCircle(Common::Rect box, byte size, byte color, byte prio, byte control) {
|
2009-10-09 18:06:24 +00:00
|
|
|
byte flag = _screen->getDrawingMask(color, prio, control);
|
2009-10-09 21:49:04 +00:00
|
|
|
const byte *circleData = vectorPatternCircles[size];
|
2009-10-09 18:06:24 +00:00
|
|
|
byte bitmap = *circleData;
|
|
|
|
byte bitNo = 0;
|
|
|
|
int y, x;
|
|
|
|
|
|
|
|
for (y = box.top; y < box.bottom; y++) {
|
|
|
|
for (x = box.left; x < box.right; x++) {
|
|
|
|
if (bitmap & 1) {
|
|
|
|
_screen->putPixel(x, y, flag, color, prio, control);
|
|
|
|
}
|
|
|
|
bitNo++;
|
|
|
|
if (bitNo == 8) {
|
|
|
|
circleData++; bitmap = *circleData; bitNo = 0;
|
|
|
|
} else {
|
|
|
|
bitmap = bitmap >> 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
void GfxPicture::vectorPatternTexturedCircle(Common::Rect box, byte size, byte color, byte prio, byte control, byte texture) {
|
2009-10-09 18:06:24 +00:00
|
|
|
byte flag = _screen->getDrawingMask(color, prio, control);
|
2009-10-09 21:49:04 +00:00
|
|
|
const byte *circleData = vectorPatternCircles[size];
|
2009-10-09 18:06:24 +00:00
|
|
|
byte bitmap = *circleData;
|
|
|
|
byte bitNo = 0;
|
|
|
|
const bool *textureData = &vectorPatternTextures[vectorPatternTextureOffset[texture]];
|
|
|
|
int y, x;
|
|
|
|
|
|
|
|
for (y = box.top; y < box.bottom; y++) {
|
|
|
|
for (x = box.left; x < box.right; x++) {
|
|
|
|
if (bitmap & 1) {
|
|
|
|
if (*textureData) {
|
|
|
|
_screen->putPixel(x, y, flag, color, prio, control);
|
|
|
|
}
|
|
|
|
textureData++;
|
|
|
|
}
|
|
|
|
bitNo++;
|
|
|
|
if (bitNo == 8) {
|
|
|
|
circleData++; bitmap = *circleData; bitNo = 0;
|
|
|
|
} else {
|
|
|
|
bitmap = bitmap >> 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-05 12:14:03 +00:00
|
|
|
void GfxPicture::vectorPattern(int16 x, int16 y, byte color, byte priority, byte control, byte code, byte texture) {
|
2009-10-09 18:06:24 +00:00
|
|
|
byte size = code & SCI_PATTERN_CODE_PENSIZE;
|
|
|
|
Common::Rect rect;
|
|
|
|
|
|
|
|
// We need to adjust the given coordinates, because the ones given us do not define upper left but somewhat middle
|
|
|
|
y -= size; if (y < 0) y = 0;
|
|
|
|
x -= size; if (x < 0) x = 0;
|
|
|
|
|
|
|
|
rect.top = y; rect.left = x;
|
|
|
|
rect.setHeight((size*2)+1); rect.setWidth((size*2)+2);
|
2010-01-31 12:35:15 +00:00
|
|
|
_ports->offsetRect(rect);
|
2010-01-06 13:05:14 +00:00
|
|
|
rect.clip(_screen->getWidth(), _screen->getHeight());
|
2009-10-09 18:06:24 +00:00
|
|
|
|
|
|
|
if (code & SCI_PATTERN_CODE_RECTANGLE) {
|
|
|
|
// Rectangle
|
|
|
|
if (code & SCI_PATTERN_CODE_USE_TEXTURE) {
|
|
|
|
vectorPatternTexturedBox(rect, color, priority, control, texture);
|
|
|
|
} else {
|
|
|
|
vectorPatternBox(rect, color, priority, control);
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// Circle
|
|
|
|
if (code & SCI_PATTERN_CODE_USE_TEXTURE) {
|
|
|
|
vectorPatternTexturedCircle(rect, size, color, priority, control, texture);
|
|
|
|
} else {
|
|
|
|
vectorPatternCircle(rect, size, color, priority, control);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-04 21:26:33 +00:00
|
|
|
} // End of namespace Sci
|