Esempio n. 1
0
SciVersion GameFeatures::detectMessageFunctionType() {
	if (_messageFunctionType != SCI_VERSION_NONE)
		return _messageFunctionType;

	if (getSciVersion() > SCI_VERSION_1_1) {
		_messageFunctionType = SCI_VERSION_1_1;
		return _messageFunctionType;
	} else if (getSciVersion() < SCI_VERSION_1_1) {
		_messageFunctionType = SCI_VERSION_1_LATE;
		return _messageFunctionType;
	}

	Common::List<ResourceId> resources = g_sci->getResMan()->listResources(kResourceTypeMessage, -1);

	if (resources.empty()) {
		// No messages found, so this doesn't really matter anyway...
		_messageFunctionType = SCI_VERSION_1_1;
		return _messageFunctionType;
	}

	Resource *res = g_sci->getResMan()->findResource(*resources.begin(), false);
	assert(res);

	// Only v2 Message resources use the kGetMessage kernel function.
	// v3-v5 use the kMessage kernel function.

	if (READ_SCI11ENDIAN_UINT32(res->data) / 1000 == 2)
		_messageFunctionType = SCI_VERSION_1_LATE;
	else
		_messageFunctionType = SCI_VERSION_1_1;

	debugC(1, kDebugLevelVM, "Detected message function type: %s", getSciVersionDesc(_messageFunctionType));
	return _messageFunctionType;
}
Esempio n. 2
0
void GfxText32::drawChar(const uint8 charIndex) {
	byte *bitmap = _segMan->getHunkPointer(_bitmap);
	byte *pixels = bitmap + READ_SCI11ENDIAN_UINT32(bitmap + 28);

	_font->drawToBuffer(charIndex, _drawPosition.y, _drawPosition.x, _foreColor, _dimmed, pixels, _width, _height);
	_drawPosition.x += _font->getCharWidth(charIndex);
}
Esempio n. 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;
}
Esempio n. 4
0
void GfxText32::erase(const Common::Rect &rect, const bool doScaling) {
	Common::Rect targetRect = doScaling ? rect : scaleRect(rect);

	byte *bitmap = _segMan->getHunkPointer(_bitmap);
	byte *pixels = bitmap + READ_SCI11ENDIAN_UINT32(bitmap + 28);

	// NOTE: There is an extra optimisation within the SCI code to
	// do a single memset if the scaledRect is the same size as
	// the bitmap, not implemented here.
	Buffer buffer(_width, _height, pixels);
	buffer.fillRect(targetRect, _backColor);
}
Esempio n. 5
0
void GfxText32::drawFrame(const Common::Rect &rect, const int16 size, const uint8 color, const bool doScaling) {
	Common::Rect targetRect = doScaling ? scaleRect(rect) : rect;

	byte *bitmap = _segMan->getHunkPointer(_bitmap);
	byte *pixels = bitmap + READ_SCI11ENDIAN_UINT32(bitmap + 28);

	// NOTE: Not fully disassembled, but this should be right
	// TODO: Implement variable frame size
	assert(size == 1);
	Buffer buffer(_width, _height, pixels);
	buffer.frameRect(targetRect, color);
}
Esempio n. 6
0
const HunkPalette::EntryHeader HunkPalette::getEntryHeader() const {
    const byte *const data = getPalPointer();

    EntryHeader header;
    header.startColor = data[10];
    header.numColors = READ_SCI11ENDIAN_UINT16(data + 14);
    header.used = data[16];
    header.sharedUsed = data[17];
    header.version = READ_SCI11ENDIAN_UINT32(data + kEntryVersionOffset);

    return header;
}
Esempio n. 7
0
uint32 RobotDecoder::createCel5(const byte *rawVideoData, const int16 screenItemIndex, const bool usePalette) {
	_verticalScaleFactor = rawVideoData[1];
	const int16 celWidth = (int16)READ_SCI11ENDIAN_UINT16(rawVideoData + 2);
	const int16 celHeight = (int16)READ_SCI11ENDIAN_UINT16(rawVideoData + 4);
	const Common::Point celPosition((int16)READ_SCI11ENDIAN_UINT16(rawVideoData + 10),
									(int16)READ_SCI11ENDIAN_UINT16(rawVideoData + 12));
	const uint16 dataSize = READ_SCI11ENDIAN_UINT16(rawVideoData + 14);
	const int16 numDataChunks = (int16)READ_SCI11ENDIAN_UINT16(rawVideoData + 16);

	rawVideoData += kCelHeaderSize;

	const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
	const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
	const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
	const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;

	Common::Point origin;
	if (scriptWidth == kLowResX && scriptHeight == kLowResY) {
		const Ratio lowResToScreenX(screenWidth, kLowResX);
		const Ratio lowResToScreenY(screenHeight, kLowResY);
		const Ratio screenToLowResX(kLowResX, screenWidth);
		const Ratio screenToLowResY(kLowResY, screenHeight);

		const int16 scaledX = celPosition.x + (_position.x * lowResToScreenX).toInt();
		const int16 scaledY1 = celPosition.y + (_position.y * lowResToScreenY).toInt();
		const int16 scaledY2 = scaledY1 + celHeight - 1;

		const int16 lowResX = (scaledX * screenToLowResX).toInt();
		const int16 lowResY = (scaledY2 * screenToLowResY).toInt();

		origin.x = (scaledX - (lowResX * lowResToScreenX).toInt()) * -1;
		origin.y = (lowResY * lowResToScreenY).toInt() - scaledY1;
		_screenItemX[screenItemIndex] = lowResX;
		_screenItemY[screenItemIndex] = lowResY;

		debugC(kDebugLevelVideo, "Low resolution position c: %d %d l: %d/%d %d/%d d: %d %d s: %d/%d %d/%d x: %d y: %d", celPosition.x, celPosition.y, lowResX, scriptWidth, lowResY, scriptHeight, origin.x, origin.y, scaledX, screenWidth, scaledY2, screenHeight, scaledX - origin.x, scaledY2 - origin.y);
	} else {
		const int16 highResX = celPosition.x + _position.x;
		const int16 highResY = celPosition.y + _position.y + celHeight - 1;

		origin.x = 0;
		origin.y = celHeight - 1;
		_screenItemX[screenItemIndex] = highResX;
		_screenItemY[screenItemIndex] = highResY;

		debugC(kDebugLevelVideo, "High resolution position c: %d %d s: %d %d d: %d %d", celPosition.x, celPosition.y, highResX, highResY, origin.x, origin.y);
	}

	_originalScreenItemX[screenItemIndex] = celPosition.x;
	_originalScreenItemY[screenItemIndex] = celPosition.y;

	assert(_celHandles[screenItemIndex].area >= celWidth * celHeight);

	SciBitmap &bitmap = *_segMan->lookupBitmap(_celHandles[screenItemIndex].bitmapId);
	assert(bitmap.getWidth() == celWidth && bitmap.getHeight() == celHeight);
	assert(bitmap.getXResolution() == _xResolution && bitmap.getYResolution() == _yResolution);
	assert(bitmap.getHunkPaletteOffset() == (uint32)bitmap.getWidth() * bitmap.getHeight() + SciBitmap::getBitmapHeaderSize());
	bitmap.setOrigin(origin);

	byte *targetBuffer = nullptr;
	if (_verticalScaleFactor == 100) {
		// direct copy to bitmap
		targetBuffer = bitmap.getPixels();
	} else {
		// go through squashed cel decompressor
		_celDecompressionBuffer.resize(_celDecompressionArea >= celWidth * (celHeight * _verticalScaleFactor / 100));
		targetBuffer = _celDecompressionBuffer.begin();
	}

	for (int i = 0; i < numDataChunks; ++i) {
		uint compressedSize = READ_SCI11ENDIAN_UINT32(rawVideoData);
		uint decompressedSize = READ_SCI11ENDIAN_UINT32(rawVideoData + 4);
		uint16 compressionType = READ_SCI11ENDIAN_UINT16(rawVideoData + 8);
		rawVideoData += 10;

		switch (compressionType) {
		case kCompressionLZS: {
			Common::MemoryReadStream videoDataStream(rawVideoData, compressedSize, DisposeAfterUse::NO);
			_decompressor.unpack(&videoDataStream, targetBuffer, compressedSize, decompressedSize);
			break;
		}
		case kCompressionNone:
			Common::copy(rawVideoData, rawVideoData + decompressedSize, targetBuffer);
			break;
		default:
			error("Unknown compression type %d!", compressionType);
		}

		rawVideoData += compressedSize;
		targetBuffer += decompressedSize;
	}

	if (_verticalScaleFactor != 100) {
		expandCel(bitmap.getPixels(), _celDecompressionBuffer.begin(), celWidth, celHeight);
	}

	if (usePalette) {
		Common::copy(_rawPalette, _rawPalette + kRawPaletteSize, bitmap.getHunkPalette());
	}

	return kCelHeaderSize + dataSize;
}
Esempio n. 8
0
bool MessageState::getRecord(CursorStack &stack, bool recurse, MessageRecord &record) {
	Resource *res = g_sci->getResMan()->findResource(ResourceId(kResourceTypeMessage, stack.getModule()), 0);

	if (!res) {
		warning("Failed to open message resource %d", stack.getModule());
		return false;
	}

	MessageReader *reader;
	int version = READ_SCI11ENDIAN_UINT32(res->data) / 1000;

	switch (version) {
	case 2:
		reader = new MessageReaderV2(res->data, res->size);
		break;
	case 3:
		reader = new MessageReaderV3(res->data, res->size);
		break;
	case 4:
#ifdef ENABLE_SCI32
	case 5: // v5 seems to be compatible with v4
		// SCI32 Mac is different than SCI32 DOS/Win here
		if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2_1)
			reader = new MessageReaderV4_MacSCI32(res->data, res->size);
		else
#endif
			reader = new MessageReaderV4(res->data, res->size);
		break;
	default:
		error("Message: unsupported resource version %d", version);
		return false;
	}

	if (!reader->init()) {
		delete reader;

		warning("Message: failed to read resource header");
		return false;
	}

	while (1) {
		MessageTuple &t = stack.top();

		if (!reader->findRecord(t, record)) {
			// Tuple not found
			if (recurse && (stack.size() > 1)) {
				stack.pop();
				continue;
			}

			delete reader;
			return false;
		}

		if (recurse) {
			MessageTuple &ref = record.refTuple;

			if (ref.noun || ref.verb || ref.cond) {
				t.seq++;
				stack.push(ref);
				continue;
			}
		}

		delete reader;
		return true;
	}
}
Esempio n. 9
0
reg_t GfxText32::createFontBitmap(const CelInfo32 &celInfo, const Common::Rect &rect, const Common::String &text, const int16 foreColor, const int16 backColor, const GuiResourceId fontId, const int16 skipColor, const int16 borderColor, const bool dimmed, reg_t *outBitmapObject) {
	_field_22 = 0;
	_borderColor = borderColor;
	_text = text;
	_textRect = rect;
	_foreColor = foreColor;
	_dimmed = dimmed;

	setFont(fontId);

	int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
	int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;

	int borderSize = 1;
	mulinc(_textRect, Ratio(_scaledWidth, scriptWidth), Ratio(_scaledHeight, scriptHeight));

	CelObjView view(celInfo.resourceId, celInfo.loopNo, celInfo.celNo);
	_skipColor = view._transparentColor;
	_width = view._width * _scaledWidth / view._scaledWidth;
	_height = view._height * _scaledHeight / view._scaledHeight;

	Common::Rect bitmapRect(_width, _height);
	if (_textRect.intersects(bitmapRect)) {
		_textRect.clip(bitmapRect);
	} else {
		_textRect = Common::Rect();
	}

	_bitmap = _segMan->allocateHunkEntry("FontBitmap()", _width * _height + CelObjMem::getBitmapHeaderSize());
	byte *bitmap = _segMan->getHunkPointer(_bitmap);
	CelObjMem::buildBitmapHeader(bitmap, _width, _height, _skipColor, 0, 0, _scaledWidth, _scaledHeight, 0, false);

	Buffer buffer(_width, _height, bitmap + READ_SCI11ENDIAN_UINT32(bitmap + 28));

	// NOTE: The engine filled the bitmap pixels with 11 here, which is silly
	// because then it just erased the bitmap using the skip color. So we don't
	// fill the bitmap redundantly here.

	_backColor = _skipColor;
	erase(bitmapRect, false);
	_backColor = backColor;

	view.draw(buffer, bitmapRect, Common::Point(0, 0), false, Ratio(_scaledWidth, view._scaledWidth), Ratio(_scaledHeight, view._scaledHeight));

	if (_backColor != skipColor && _foreColor != skipColor) {
		erase(_textRect, false);
	}

	if (text.size() > 0) {
		if (_foreColor == skipColor) {
			error("TODO: Implement transparent text");
		} else {
			if (borderColor != -1) {
				drawFrame(bitmapRect, borderSize, _borderColor, false);
			}

			drawTextBox();
		}
	}

	*outBitmapObject = _bitmap;
	return _bitmap;
}