Exemple #1
0
void GfxPicture::drawSci11Vga() {
	byte *inbuffer = _resource->data;
	int size = _resource->size;
	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);
	Palette palette;

	// Header
	// [headerSize:WORD] [unknown:BYTE] [priorityBandCount:BYTE] [hasCel:BYTE] [unknown:BYTE]
	// [unknown:WORD] [unknown:WORD] [unknown:WORD] [unknown:WORD] [unknown:WORD]
	// Offset 16
	// [vectorDataOffset:DWORD] [unknown:DWORD] [unknown:DWORD] [paletteDataOffset:DWORD]
	// Offset 32
	// [celHeaderOffset:DWORD] [unknown:DWORD]
	// [priorityBandData:WORD] * priorityBandCount
	// [priority:BYTE] [unknown:BYTE]

	// priority bands are supposed to be 14 for sci1.1 pictures
	assert(priorityBandsCount == 14);

	if (_addToFlag) {
		_priority = inbuffer[40 + priorityBandsCount * 2] & 0xF;
	}

	// display Cel-data
	if (has_cel) {
		// Create palette and set it
		_palette->createFromData(inbuffer + palette_data_ptr, size - palette_data_ptr, &palette);
		_palette->set(&palette, true);

		drawCelData(inbuffer, size, cel_headerPos, cel_RlePos, cel_LiteralPos, 0, 0, 0);
	}

	// process vector data
	drawVectorData(inbuffer + vector_dataPos, vector_size);

	// Set priority band information
	_ports->priorityBandsInitSci11(inbuffer + 40);
}
Exemple #2
0
void GfxPicture::drawSci11Vga() {
	SciSpan<const byte> inbuffer(*_resource);
	int priorityBandsCount = inbuffer[3];
	int has_cel = inbuffer[4];
	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
	// [headerSize:WORD] [unknown:BYTE] [priorityBandCount:BYTE] [hasCel:BYTE] [unknown:BYTE]
	// [unknown:WORD] [unknown:WORD] [unknown:WORD] [unknown:WORD] [unknown:WORD]
	// Offset 16
	// [vectorDataOffset:DWORD] [unknown:DWORD] [unknown:DWORD] [paletteDataOffset:DWORD]
	// Offset 32
	// [celHeaderOffset:DWORD] [unknown:DWORD]
	// [priorityBandData:WORD] * priorityBandCount
	// [priority:BYTE] [unknown:BYTE]

	// priority bands are supposed to be 14 for sci1.1 pictures
	assert(priorityBandsCount == 14);

	if (_addToFlag) {
		_priority = inbuffer[40 + priorityBandsCount * 2] & 0xF;
	}

	// display Cel-data
	if (has_cel) {
		// Create palette and set it
		_palette->createFromData(inbuffer.subspan(palette_data_ptr), &palette);
		_palette->set(&palette, true);

		drawCelData(inbuffer, cel_headerPos, cel_RlePos, cel_LiteralPos, 0, 0, 0, 0, false);
	}

	// process vector data
	drawVectorData(inbuffer.subspan(vector_dataPos, vector_size));

	// Set priority band information
	_ports->priorityBandsInitSci11(inbuffer.subspan(40));
}
Exemple #3
0
void GfxPicture::drawSci32Vga(int16 celNo, int16 drawX, int16 drawY, int16 pictureX, 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
	// [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]

	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);
	cel_headerPos += 42;
}
Exemple #4
0
void GfxPicture::drawVectorData(byte *data, int dataSize) {
	byte pic_op;
	byte pic_color = _screen->getColorDefaultVectorData();
	byte pic_priority = 255, pic_control = 255;
	int16 x = 0, y = 0, oldx, oldy;
	byte EGApalettes[PIC_EGAPALETTE_TOTALSIZE] = {0};
	byte *EGApalette = &EGApalettes[_EGApaletteNo * PIC_EGAPALETTE_SIZE];
	byte EGApriority[PIC_EGAPRIORITY_SIZE] = {0};
	bool isEGA = false;
	int curPos = 0;
	uint16 size;
	byte pixel;
	int i;
	Palette palette;
	int16 pattern_Code = 0, pattern_Texture = 0;
	bool icemanDrawFix = false;
	bool ignoreBrokenPriority = false;

	memset(&palette, 0, sizeof(palette));

	if (_EGApaletteNo >= PIC_EGAPALETTE_COUNT)
		_EGApaletteNo = 0;

	if (_resMan->getViewType() == kViewEga) {
		isEGA = true;
		// 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));

		if (g_sci->getGameId() == GID_ICEMAN) {
			// 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->isUnditheringEnabled()) && ((_resourceId >= 53 && _resourceId <= 58) || (_resourceId == 61)))
				icemanDrawFix = true;
		}
		if (g_sci->getGameId() == GID_KQ5) {
			// WORKAROUND: ignore the seemingly broken priority of picture 48
			// (island overview). Fixes bug #3041044.
			if (_resourceId == 48)
				ignoreBrokenPriority = true;
		}
		if (g_sci->getGameId() == GID_SQ4) {
			// WORKAROUND: ignore the seemingly broken priority of pictures 546
			// and 547 (Vohaul's head and Roger Jr trapped). Fixes bug #3046543.
			if (_resourceId == 546 || _resourceId == 547)
				ignoreBrokenPriority = true;
			// WORKAROUND: ignore the seemingly broken priority of picture 631
			// (SQ1 view from the cockpit). Fixes bug #3046513.
			if (_resourceId == 631)
				ignoreBrokenPriority = true;
		}
	}

	// Drawing
	while (curPos < dataSize) {
#ifdef DEBUG_PICTURE_DRAW
		debug("Picture op: %X (%s) at %d", data[curPos], picOpcodeNames[data[curPos] - 0xF0], curPos);
#endif
		switch (pic_op = data[curPos++]) {
		case PIC_OP_SET_COLOR:
			pic_color = data[curPos++];
			if (isEGA) {
				pic_color = EGApalette[pic_color];
				pic_color ^= pic_color << 4;
			}
			break;
		case PIC_OP_DISABLE_VISUAL:
			pic_color = 0xFF;
			break;

		case PIC_OP_SET_PRIORITY:
			pic_priority = data[curPos++] & 0x0F;
			if (isEGA)
				pic_priority = EGApriority[pic_priority];
			if (ignoreBrokenPriority)
				pic_priority = 255;
			break;
		case PIC_OP_DISABLE_PRIORITY:
			pic_priority = 255;
			break;

		case PIC_OP_SET_CONTROL:
			pic_control = data[curPos++] & 0x0F;
			break;
		case PIC_OP_DISABLE_CONTROL:
			pic_control = 255;
			break;

		case PIC_OP_SHORT_LINES: // short line
			vectorGetAbsCoords(data, curPos, x, y);
			while (vectorIsNonOpcode(data[curPos])) {
				oldx = x; oldy = y;
				vectorGetRelCoords(data, curPos, x, y);
				Common::Point startPoint(oldx, oldy);
				Common::Point endPoint(x, y);
				_ports->offsetLine(startPoint, endPoint);
				_screen->drawLine(startPoint, endPoint, pic_color, pic_priority, pic_control);
			}
			break;
		case PIC_OP_MEDIUM_LINES: // medium line
			vectorGetAbsCoords(data, curPos, x, y);
			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;
					}
				}
			}
			while (vectorIsNonOpcode(data[curPos])) {
				oldx = x; oldy = y;
				vectorGetRelCoordsMed(data, curPos, x, y);
				Common::Point startPoint(oldx, oldy);
				Common::Point endPoint(x, y);
				_ports->offsetLine(startPoint, endPoint);
				_screen->drawLine(startPoint, endPoint, pic_color, pic_priority, pic_control);
			}
			break;
		case PIC_OP_LONG_LINES: // long line
			vectorGetAbsCoords(data, curPos, x, y);
			while (vectorIsNonOpcode(data[curPos])) {
				oldx = x; oldy = y;
				vectorGetAbsCoords(data, curPos, x, y);
				Common::Point startPoint(oldx, oldy);
				Common::Point endPoint(x, y);
				_ports->offsetLine(startPoint, endPoint);
				_screen->drawLine(startPoint, endPoint, pic_color, pic_priority, pic_control);
			}
			break;

		case PIC_OP_FILL: //fill
			while (vectorIsNonOpcode(data[curPos])) {
				vectorGetAbsCoords(data, curPos, x, y);
				vectorFloodFill(x, y, pic_color, pic_priority, pic_control);
			}
			break;

		// Pattern opcodes are handled in sierra sci1.1+ as actual NOPs and
		// normally they definitely should not occur inside picture data for
		// such games.
		case PIC_OP_SET_PATTERN:
			if (_resourceType >= SCI_PICTURE_TYPE_SCI11) {
				if (g_sci->getGameId() == GID_SQ4) {
					// WORKAROUND: For SQ4 / for some pictures handle this like
					// a terminator. This picture includes garbage data, first a
					// set pattern w/o parameter and then short pattern. I guess
					// that garbage is a left over from the sq4-floppy (sci1) to
					// sq4-cd (sci1.1) conversion.
					switch (_resourceId) {
					case 35:
					case 381:
					case 376:
						return;
					default:
						break;
					}
				}
				error("pic-operation set pattern inside sci1.1+ vector data");
			}
			pattern_Code = data[curPos++];
			break;
		case PIC_OP_SHORT_PATTERNS:
			if (_resourceType >= SCI_PICTURE_TYPE_SCI11)
				error("pic-operation short pattern inside sci1.1+ vector data");
			vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
			vectorGetAbsCoords(data, curPos, x, y);
			vectorPattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
			while (vectorIsNonOpcode(data[curPos])) {
				vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
				vectorGetRelCoords(data, curPos, x, y);
				vectorPattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
			}
			break;
		case PIC_OP_MEDIUM_PATTERNS:
			if (_resourceType >= SCI_PICTURE_TYPE_SCI11)
				error("pic-operation medium pattern inside sci1.1+ vector data");
			vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
			vectorGetAbsCoords(data, curPos, x, y);
			vectorPattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
			while (vectorIsNonOpcode(data[curPos])) {
				vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
				vectorGetRelCoordsMed(data, curPos, x, y);
				vectorPattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
			}
			break;
		case PIC_OP_ABSOLUTE_PATTERN:
			if (_resourceType >= SCI_PICTURE_TYPE_SCI11)
				error("pic-operation absolute pattern inside sci1.1+ vector data");
			while (vectorIsNonOpcode(data[curPos])) {
				vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
				vectorGetAbsCoords(data, curPos, x, y);
				vectorPattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
			}
			break;

		case PIC_OP_OPX: // Extended functions
			if (isEGA) {
#ifdef DEBUG_PICTURE_DRAW
				debug("* Picture ex op: %X (%s) at %d", data[curPos], picExOpcodeNamesEGA[data[curPos]], curPos);
#endif
				switch (pic_op = data[curPos++]) {
				case PIC_OPX_EGA_SET_PALETTE_ENTRIES:
					while (vectorIsNonOpcode(data[curPos])) {
						pixel = data[curPos++];
						if (pixel >= PIC_EGAPALETTE_TOTALSIZE) {
							error("picture trying to write to invalid EGA-palette");
						}
						EGApalettes[pixel] = data[curPos++];
					}
					break;
				case PIC_OPX_EGA_SET_PALETTE:
					pixel = data[curPos++];
					if (pixel >= PIC_EGAPALETTE_COUNT) {
						error("picture trying to write to invalid palette %d", (int)pixel);
					}
					pixel *= PIC_EGAPALETTE_SIZE;
					for (i = 0; i < PIC_EGAPALETTE_SIZE; i++) {
						EGApalettes[pixel + i] = data[curPos++];
					}
					break;
				case PIC_OPX_EGA_MONO0:
					curPos += 41;
					break;
				case PIC_OPX_EGA_MONO1:
				case PIC_OPX_EGA_MONO3:
					curPos++;
					break;
				case PIC_OPX_EGA_MONO2:
				case PIC_OPX_EGA_MONO4:
					break;
				case PIC_OPX_EGA_EMBEDDED_VIEW:
					vectorGetAbsCoordsNoMirror(data, curPos, x, y);
					size = READ_LE_UINT16(data + curPos); curPos += 2;
					_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);
					curPos += size;
					break;
				case PIC_OPX_EGA_SET_PRIORITY_TABLE:
					_ports->priorityBandsInit(data + curPos);
					curPos += 14;
					break;
				default:
					error("Unsupported sci1 extended pic-operation %X", pic_op);
				}
			} else {
#ifdef DEBUG_PICTURE_DRAW
				debug("* Picture ex op: %X (%s) at %d", data[curPos], picExOpcodeNamesVGA[data[curPos]], curPos);
#endif
				switch (pic_op = data[curPos++]) {
				case PIC_OPX_VGA_SET_PALETTE_ENTRIES:
					while (vectorIsNonOpcode(data[curPos])) {
						curPos++; // skip commands
					}
					break;
				case PIC_OPX_VGA_SET_PALETTE:
					if (_resMan->getViewType() == kViewAmiga || _resMan->getViewType() == kViewAmiga64) {
						if ((data[curPos] == 0x00) && (data[curPos + 1] == 0x01) && ((data[curPos + 32] & 0xF0) != 0xF0)) {
							// Left-Over VGA palette, we simply ignore it
							curPos += 256 + 4 + 1024;
						} else {
							// Setting half of the Amiga palette
							_palette->modifyAmigaPalette(&data[curPos]);
							curPos += 32;
						}
					} 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++];
						}
						_palette->set(&palette, true);
					}
					break;
				case PIC_OPX_VGA_EMBEDDED_VIEW: // draw cel
					vectorGetAbsCoordsNoMirror(data, curPos, x, y);
					size = READ_LE_UINT16(data + curPos); curPos += 2;
					_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);
					curPos += size;
					break;
				case PIC_OPX_VGA_PRIORITY_TABLE_EQDIST:
					_ports->priorityBandsInit(-1, READ_LE_UINT16(data + curPos), READ_LE_UINT16(data + curPos + 2));
					curPos += 4;
					break;
				case PIC_OPX_VGA_PRIORITY_TABLE_EXPLICIT:
					_ports->priorityBandsInit(data + curPos);
					curPos += 14;
					break;
				default:
					error("Unsupported sci1 extended pic-operation %X", pic_op);
				}
			}
			break;
		case PIC_OP_TERMINATE:
			_priority = pic_priority;
			// Dithering EGA pictures
			if (isEGA) {
				_screen->dither(_addToFlag);
				switch (g_sci->getGameId()) {
				case GID_SQ3:
					switch (_resourceId) {
					case 154: // SQ3: intro, ship gets sucked in
						_screen->ditherForceDitheredColor(0xD0);
						break;
					default:
						break;
					}
					break;
				default:
					break;
				}
			}
			return;
		default:
			error("Unsupported pic-operation %X", pic_op);
		}
		if ((_EGAdrawingVisualize) && (isEGA)) {
			_screen->copyToScreen();
			g_system->updateScreen();
			g_system->delayMillis(10);
		}
	}
	error("picture vector data without terminator");
}