aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/graphics/picture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/graphics/picture.cpp')
-rw-r--r--engines/sci/graphics/picture.cpp226
1 files changed, 52 insertions, 174 deletions
diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp
index 864327feaa..9e9dede1ae 100644
--- a/engines/sci/graphics/picture.cpp
+++ b/engines/sci/graphics/picture.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "common/span.h"
#include "common/stack.h"
#include "common/system.h"
@@ -68,22 +69,16 @@ void GfxPicture::draw(int16 animationNr, bool mirroredFlag, bool addToFlag, int1
_EGApaletteNo = EGApaletteNo;
_priority = 0;
- headerSize = READ_LE_UINT16(_resource->data);
+ headerSize = _resource->getUint16LEAt(0);
switch (headerSize) {
case 0x26: // SCI 1.1 VGA picture
_resourceType = SCI_PICTURE_TYPE_SCI11;
drawSci11Vga();
break;
-#ifdef ENABLE_SCI32
- case 0x0e: // SCI32 VGA picture
- _resourceType = SCI_PICTURE_TYPE_SCI32;
- drawSci32Vga(0, 0, 0, 0, 0, false);
- break;
-#endif
default:
// VGA, EGA or Amiga vector data
_resourceType = SCI_PICTURE_TYPE_REGULAR;
- drawVectorData(_resource->data, _resource->size);
+ drawVectorData(*_resource);
}
}
@@ -100,16 +95,15 @@ void GfxPicture::reset() {
}
void GfxPicture::drawSci11Vga() {
- byte *inbuffer = _resource->data;
- int size = _resource->size;
+ SciSpan<const byte> inbuffer(*_resource);
int priorityBandsCount = inbuffer[3];
int has_cel = inbuffer[4];
- int vector_dataPos = READ_LE_UINT32(inbuffer + 16);
- int vector_size = size - vector_dataPos;
- int palette_data_ptr = READ_LE_UINT32(inbuffer + 28);
- int cel_headerPos = READ_LE_UINT32(inbuffer + 32);
- int cel_RlePos = READ_LE_UINT32(inbuffer + cel_headerPos + 24);
- int cel_LiteralPos = READ_LE_UINT32(inbuffer + cel_headerPos + 28);
+ int vector_dataPos = inbuffer.getUint32LEAt(16);
+ int vector_size = _resource->size() - vector_dataPos;
+ int palette_data_ptr = inbuffer.getUint32LEAt(28);
+ int cel_headerPos = inbuffer.getUint32LEAt(32);
+ int cel_RlePos = inbuffer.getUint32LEAt(cel_headerPos + 24);
+ int cel_LiteralPos = inbuffer.getUint32LEAt(cel_headerPos + 28);
Palette palette;
// Header
@@ -132,113 +126,24 @@ void GfxPicture::drawSci11Vga() {
// display Cel-data
if (has_cel) {
// Create palette and set it
- _palette->createFromData(inbuffer + palette_data_ptr, size - palette_data_ptr, &palette);
+ _palette->createFromData(inbuffer.subspan(palette_data_ptr), &palette);
_palette->set(&palette, true);
- drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, 0, 0, 0, 0, false);
+ drawCelData(inbuffer, cel_headerPos, cel_RlePos, cel_LiteralPos, 0, 0, 0, 0, false);
}
// process vector data
- drawVectorData(inbuffer + vector_dataPos, vector_size);
+ drawVectorData(inbuffer.subspan(vector_dataPos, vector_size));
// Set priority band information
- _ports->priorityBandsInitSci11(inbuffer + 40);
-}
-
-#ifdef ENABLE_SCI32
-int16 GfxPicture::getSci32celCount() {
- byte *inbuffer = _resource->data;
- return inbuffer[2];
-}
-
-int16 GfxPicture::getSci32celX(int16 celNo) {
- byte *inbuffer = _resource->data;
- int header_size = READ_SCI11ENDIAN_UINT16(inbuffer);
- int cel_headerPos = header_size + 42 * celNo;
- return READ_SCI11ENDIAN_UINT16(inbuffer + cel_headerPos + 38);
-}
-
-int16 GfxPicture::getSci32celY(int16 celNo) {
- byte *inbuffer = _resource->data;
- int header_size = READ_SCI11ENDIAN_UINT16(inbuffer);
- int cel_headerPos = header_size + 42 * celNo;
- return READ_SCI11ENDIAN_UINT16(inbuffer + cel_headerPos + 40);
-}
-
-int16 GfxPicture::getSci32celWidth(int16 celNo) {
- byte *inbuffer = _resource->data;
- int header_size = READ_SCI11ENDIAN_UINT16(inbuffer);
- int cel_headerPos = header_size + 42 * celNo;
- return READ_SCI11ENDIAN_UINT16(inbuffer + cel_headerPos + 0);
-}
-
-int16 GfxPicture::getSci32celHeight(int16 celNo) {
- byte *inbuffer = _resource->data;
- int header_size = READ_SCI11ENDIAN_UINT16(inbuffer);
- int cel_headerPos = header_size + 42 * celNo;
- return READ_SCI11ENDIAN_UINT16(inbuffer + cel_headerPos + 2);
-}
-
-
-int16 GfxPicture::getSci32celPriority(int16 celNo) {
- byte *inbuffer = _resource->data;
- int header_size = READ_SCI11ENDIAN_UINT16(inbuffer);
- int cel_headerPos = header_size + 42 * celNo;
- return READ_SCI11ENDIAN_UINT16(inbuffer + cel_headerPos + 36);
-}
-
-void GfxPicture::drawSci32Vga(int16 celNo, int16 drawX, int16 drawY, int16 pictureX, int16 pictureY, bool mirrored) {
- byte *inbuffer = _resource->data;
- int size = _resource->size;
- int header_size = READ_SCI11ENDIAN_UINT16(inbuffer);
- int palette_data_ptr = READ_SCI11ENDIAN_UINT32(inbuffer + 6);
-// int celCount = inbuffer[2];
- int cel_headerPos = header_size;
- int cel_RlePos, cel_LiteralPos;
- Palette palette;
-
- // HACK
- _mirroredFlag = mirrored;
- _addToFlag = false;
- _resourceType = SCI_PICTURE_TYPE_SCI32;
-
- if (celNo == 0) {
- // Create palette and set it
- _palette->createFromData(inbuffer + palette_data_ptr, size - palette_data_ptr, &palette);
- _palette->set(&palette, true);
- }
-
- // Header
- // 0[headerSize:WORD] 2[celCount:BYTE] 3[Unknown:BYTE] 4[celHeaderSize:WORD] 6[paletteOffset:DWORD] 10[Unknown:WORD] 12[Unknown:WORD]
- // cel-header follow afterwards, each is 42 bytes
- // Cel-Header
- // 0[width:WORD] 2[height:WORD] 4[displaceX:WORD] 6[displaceY:WORD] 8[clearColor:BYTE] 9[compressed:BYTE]
- // offset 10-23 is unknown
- // 24[rleOffset:DWORD] 28[literalOffset:DWORD] 32[Unknown:WORD] 34[Unknown:WORD] 36[priority:WORD] 38[relativeXpos:WORD] 40[relativeYpos:WORD]
-
- cel_headerPos += 42 * celNo;
-
- if (mirrored) {
- // switch around relativeXpos
- Common::Rect displayArea = _coordAdjuster->pictureGetDisplayArea();
- drawX = displayArea.width() - drawX - READ_SCI11ENDIAN_UINT16(inbuffer + cel_headerPos + 0);
- }
-
- cel_RlePos = READ_SCI11ENDIAN_UINT32(inbuffer + cel_headerPos + 24);
- cel_LiteralPos = READ_SCI11ENDIAN_UINT32(inbuffer + cel_headerPos + 28);
-
- drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, drawX, drawY, pictureX, pictureY, false);
- cel_headerPos += 42;
+ _ports->priorityBandsInitSci11(inbuffer.subspan(40));
}
-#endif
-extern void unpackCelData(byte *inBuffer, byte *celBitmap, byte clearColor, int pixelCount, int rlePos, int literalPos, ViewType viewType, uint16 width, bool isMacSci11ViewData);
+extern void unpackCelData(const SciSpan<const byte> &inBuffer, SciSpan<byte> &celBitmap, byte clearColor, int rlePos, int literalPos, ViewType viewType, uint16 width, bool isMacSci11ViewData);
-void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos, int literalPos, int16 drawX, int16 drawY, int16 pictureX, int16 pictureY, bool isEGA) {
- byte *celBitmap = NULL;
- byte *ptr = NULL;
- byte *headerPtr = inbuffer + headerPos;
- byte *rlePtr = inbuffer + rlePos;
+void GfxPicture::drawCelData(const SciSpan<const byte> &inbuffer, int headerPos, int rlePos, int literalPos, int16 drawX, int16 drawY, int16 pictureX, int16 pictureY, bool isEGA) {
+ const SciSpan<const byte> headerPtr = inbuffer.subspan(headerPos);
+ const SciSpan<const byte> rlePtr = inbuffer.subspan(rlePos);
// displaceX, displaceY fields are ignored, and may contain garbage
// (e.g. pic 261 in Dr. Brain 1 Spanish - bug #3614914)
//int16 displaceX, displaceY;
@@ -254,30 +159,16 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
if (!isEGA && !_addToFlag)
priority = 0;
-#ifdef ENABLE_SCI32
- if (_resourceType != SCI_PICTURE_TYPE_SCI32) {
-#endif
- // Width/height here are always LE, even in Mac versions
- width = READ_LE_UINT16(headerPtr + 0);
- height = READ_LE_UINT16(headerPtr + 2);
- //displaceX = (signed char)headerPtr[4];
- //displaceY = (unsigned char)headerPtr[5];
- if (_resourceType == SCI_PICTURE_TYPE_SCI11)
- // SCI1.1 uses hardcoded clearcolor for pictures, even if cel header specifies otherwise
- clearColor = _screen->getColorWhite();
- else
- clearColor = headerPtr[6];
-#ifdef ENABLE_SCI32
- } else {
- width = READ_SCI11ENDIAN_UINT16(headerPtr + 0);
- height = READ_SCI11ENDIAN_UINT16(headerPtr + 2);
- //displaceX = READ_SCI11ENDIAN_UINT16(headerPtr + 4); // probably signed?!?
- //displaceY = READ_SCI11ENDIAN_UINT16(headerPtr + 6); // probably signed?!?
- clearColor = headerPtr[8];
- if (headerPtr[9] == 0)
- compression = false;
- }
-#endif
+ // Width/height here are always LE, even in Mac versions
+ width = headerPtr.getUint16LEAt(0);
+ height = headerPtr.getUint16LEAt(2);
+ //displaceX = (signed char)headerPtr[4];
+ //displaceY = (unsigned char)headerPtr[5];
+ if (_resourceType == SCI_PICTURE_TYPE_SCI11)
+ // SCI1.1 uses hardcoded clearcolor for pictures, even if cel header specifies otherwise
+ clearColor = _screen->getColorWhite();
+ else
+ clearColor = headerPtr[6];
//if (displaceX || displaceY)
// error("unsupported embedded cel-data in picture");
@@ -285,7 +176,8 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
// 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
pixelCount = width * height;
- celBitmap = new byte[pixelCount];
+ Common::SpanOwner<SciSpan<byte> > celBitmap;
+ celBitmap->allocate(pixelCount, _resource->name());
if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2) {
// See GfxView::unpackCel() for why this black/white swap is done
@@ -296,22 +188,11 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
clearColor = 0;
}
- if (compression)
- unpackCelData(inbuffer, celBitmap, clearColor, pixelCount, rlePos, literalPos, _resMan->getViewType(), width, false);
- else
+ if (compression) {
+ unpackCelData(inbuffer, *celBitmap, clearColor, rlePos, literalPos, _resMan->getViewType(), width, false);
+ } else
// No compression (some SCI32 pictures)
- memcpy(celBitmap, rlePtr, pixelCount);
-
- if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2) {
- // See GfxView::unpackCel() for why this black/white swap is done
- // This picture swap is only needed in SCI32, not SCI1.1
- for (int i = 0; i < pixelCount; i++) {
- if (celBitmap[i] == 0)
- celBitmap[i] = 0xff;
- else if (celBitmap[i] == 0xff)
- celBitmap[i] = 0;
- }
- }
+ memcpy(celBitmap->getUnsafeDataAt(0, pixelCount), rlePtr.getUnsafeDataAt(0, pixelCount), pixelCount);
Common::Rect displayArea = _coordAdjuster->pictureGetDisplayArea();
@@ -356,13 +237,12 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
// but white and that won't 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.
- // SCI32 doesn't use _addToFlag at all.
- if (!_addToFlag && _resourceType != SCI_PICTURE_TYPE_SCI32)
+ if (!_addToFlag)
clearColor = _screen->getColorWhite();
byte drawMask = priority > 15 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL | GFX_SCREEN_MASK_PRIORITY;
- ptr = celBitmap;
+ SciSpan<const byte> ptr = *celBitmap;
ptr += skipCelBitmapPixels;
ptr += skipCelBitmapLines * width;
@@ -440,8 +320,6 @@ void GfxPicture::drawCelData(byte *inbuffer, int size, int headerPos, int rlePos
}
}
}
-
- delete[] celBitmap;
}
enum {
@@ -549,7 +427,7 @@ static const byte vector_defaultEGApriority[PIC_EGAPRIORITY_SIZE] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
-void GfxPicture::drawVectorData(byte *data, int dataSize) {
+void GfxPicture::drawVectorData(const SciSpan<const byte> &data) {
byte pic_op;
byte pic_color = _screen->getColorDefaultVectorData();
byte pic_priority = 255, pic_control = 255;
@@ -558,7 +436,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
byte *EGApalette = &EGApalettes[_EGApaletteNo * PIC_EGAPALETTE_SIZE];
byte EGApriority[PIC_EGAPRIORITY_SIZE] = {0};
bool isEGA = false;
- int curPos = 0;
+ uint curPos = 0;
uint16 size;
byte pixel;
int i;
@@ -591,7 +469,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
}
// Drawing
- while (curPos < dataSize) {
+ while (curPos < data.size()) {
#ifdef DEBUG_PICTURE_DRAW
debug("Picture op: %X (%s) at %d", data[curPos], picOpcodeNames[data[curPos] - 0xF0], curPos);
_screen->copyToScreen();
@@ -774,7 +652,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
break;
case PIC_OPX_EGA_EMBEDDED_VIEW:
vectorGetAbsCoordsNoMirror(data, curPos, x, y);
- size = READ_LE_UINT16(data + curPos); curPos += 2;
+ size = data.getUint16LEAt(curPos); curPos += 2;
// hardcoded in SSCI, 16 for SCI1early excluding Space Quest 4, 0 for anything else
// fixes sq4 pictures 546+547 (Vohaul's head and Roger Jr trapped). Bug #5250
// fixes sq4 picture 631 (SQ1 view from cockpit). Bug 5249
@@ -783,11 +661,11 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
} else {
_priority = 0;
}
- drawCelData(data, _resource->size, curPos, curPos + 8, 0, x, y, 0, 0, true);
+ drawCelData(data, curPos, curPos + 8, 0, x, y, 0, 0, true);
curPos += size;
break;
case PIC_OPX_EGA_SET_PRIORITY_TABLE:
- _ports->priorityBandsInit(data + curPos);
+ _ports->priorityBandsInit(data.subspan(curPos, 14));
curPos += 14;
break;
default:
@@ -810,7 +688,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
curPos += 256 + 4 + 1024;
} else {
// Setting half of the Amiga palette
- _palette->modifyAmigaPalette(&data[curPos]);
+ _palette->modifyAmigaPalette(data.subspan(curPos));
curPos += 32;
}
} else {
@@ -824,7 +702,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
break;
case PIC_OPX_VGA_EMBEDDED_VIEW: // draw cel
vectorGetAbsCoordsNoMirror(data, curPos, x, y);
- size = READ_LE_UINT16(data + curPos); curPos += 2;
+ size = data.getUint16LEAt(curPos); curPos += 2;
if (getSciVersion() <= SCI_VERSION_1_EARLY) {
// During SCI1Early sierra always used 0 as priority for cels inside picture resources
// fixes Space Quest 4 orange ship lifting off (bug #6446)
@@ -832,15 +710,15 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
} else {
_priority = pic_priority; // set global priority so the cel gets drawn using current priority as well
}
- drawCelData(data, _resource->size, curPos, curPos + 8, 0, x, y, 0, 0, false);
+ drawCelData(data, curPos, curPos + 8, 0, x, y, 0, 0, false);
curPos += size;
break;
case PIC_OPX_VGA_PRIORITY_TABLE_EQDIST:
- _ports->priorityBandsInit(-1, READ_LE_UINT16(data + curPos), READ_LE_UINT16(data + curPos + 2));
+ _ports->priorityBandsInit(-1, data.getUint16LEAt(curPos), data.getUint16LEAt(curPos + 2));
curPos += 4;
break;
case PIC_OPX_VGA_PRIORITY_TABLE_EXPLICIT:
- _ports->priorityBandsInit(data + curPos);
+ _ports->priorityBandsInit(data.subspan(curPos, 14));
curPos += 14;
break;
default:
@@ -886,20 +764,20 @@ bool GfxPicture::vectorIsNonOpcode(byte pixel) {
return true;
}
-void GfxPicture::vectorGetAbsCoords(byte *data, int &curPos, int16 &x, int16 &y) {
+void GfxPicture::vectorGetAbsCoords(const SciSpan<const byte> &data, uint &curPos, int16 &x, int16 &y) {
byte pixel = data[curPos++];
x = data[curPos++] + ((pixel & 0xF0) << 4);
y = data[curPos++] + ((pixel & 0x0F) << 8);
if (_mirroredFlag) x = 319 - x;
}
-void GfxPicture::vectorGetAbsCoordsNoMirror(byte *data, int &curPos, int16 &x, int16 &y) {
+void GfxPicture::vectorGetAbsCoordsNoMirror(const SciSpan<const byte> &data, uint &curPos, int16 &x, int16 &y) {
byte pixel = data[curPos++];
x = data[curPos++] + ((pixel & 0xF0) << 4);
y = data[curPos++] + ((pixel & 0x0F) << 8);
}
-void GfxPicture::vectorGetRelCoords(byte *data, int &curPos, int16 &x, int16 &y) {
+void GfxPicture::vectorGetRelCoords(const SciSpan<const byte> &data, uint &curPos, int16 &x, int16 &y) {
byte pixel = data[curPos++];
if (pixel & 0x80) {
x -= ((pixel >> 4) & 7) * (_mirroredFlag ? -1 : 1);
@@ -913,7 +791,7 @@ void GfxPicture::vectorGetRelCoords(byte *data, int &curPos, int16 &x, int16 &y)
}
}
-void GfxPicture::vectorGetRelCoordsMed(byte *data, int &curPos, int16 &x, int16 &y) {
+void GfxPicture::vectorGetRelCoordsMed(const SciSpan<const byte> &data, uint &curPos, int16 &x, int16 &y) {
byte pixel = data[curPos++];
if (pixel & 0x80) {
y -= (pixel & 0x7F);
@@ -928,7 +806,7 @@ void GfxPicture::vectorGetRelCoordsMed(byte *data, int &curPos, int16 &x, int16
}
}
-void GfxPicture::vectorGetPatternTexture(byte *data, int &curPos, int16 pattern_Code, int16 &pattern_Texture) {
+void GfxPicture::vectorGetPatternTexture(const SciSpan<const byte> &data, uint &curPos, int16 pattern_Code, int16 &pattern_Texture) {
if (pattern_Code & SCI_PATTERN_CODE_USE_TEXTURE) {
pattern_Texture = (data[curPos++] >> 1) & 0x7f;
}