diff options
Diffstat (limited to 'engines/voyeur/graphics.cpp')
| -rw-r--r-- | engines/voyeur/graphics.cpp | 1054 | 
1 files changed, 1054 insertions, 0 deletions
| diff --git a/engines/voyeur/graphics.cpp b/engines/voyeur/graphics.cpp new file mode 100644 index 0000000000..ce5b91fb8a --- /dev/null +++ b/engines/voyeur/graphics.cpp @@ -0,0 +1,1054 @@ +/* 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. + * + */ + +#include "voyeur/graphics.h" +#include "voyeur/voyeur.h" +#include "voyeur/staticres.h" +#include "engines/util.h" +#include "graphics/palette.h" +#include "graphics/surface.h" + +namespace Voyeur { + +/*------------------------------------------------------------------------*/ + +DrawInfo::DrawInfo(int penColor, const Common::Point &pos) { +	_penColor = penColor; +	_pos = pos; +} + +/*------------------------------------------------------------------------*/ + +GraphicsManager::GraphicsManager(VoyeurEngine *vm) : _defaultDrawInfo(1, Common::Point()), _drawPtr(&_defaultDrawInfo), _vm(vm) { +	_SVGAMode = 0; +	_planeSelect = 0; +	_saveBack = true; +	_clipPtr = NULL; +	_viewPortListPtr = NULL; +	_backgroundPage = NULL; +	_vPort = NULL; +	_fontPtr = NULL; +	Common::fill(&_VGAColors[0], &_VGAColors[PALETTE_SIZE], 0); +	_fontChar = new PictureResource(0, 0xff, 0xff, 0, Common::Rect(), 0, NULL, 0); +	_backColors = nullptr; +} + +void GraphicsManager::sInitGraphics() { +	initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT, false); +	_screenSurface.create(SCREEN_WIDTH, SCREEN_HEIGHT, Graphics::PixelFormat::createFormatCLUT8()); +	clearPalette(); +} + +GraphicsManager::~GraphicsManager() { +	_screenSurface.free(); +	delete _fontChar; +} + +void GraphicsManager::setupMCGASaveRect(ViewPortResource *viewPort) { +	if (viewPort->_activePage) { +		viewPort->_activePage->_flags |= 1; +		Common::Rect *clipRect = _clipPtr; +		_clipPtr = &viewPort->_clipRect; + +		sDrawPic(viewPort->_activePage, viewPort->_currentPic, Common::Point()); + +		_clipPtr = clipRect; +	} + +	viewPort->_rectListCount[1] = -1; +} + +void GraphicsManager::addRectOptSaveRect(ViewPortResource *viewPort, int idx, const Common::Rect &bounds) { +	if (viewPort->_rectListCount[idx] == -1) +		return; + +	// TODO: Lots of code in original, which I suspect may be overlapping rect merging +	viewPort->_rectListPtr[idx]->push_back(bounds); +	++viewPort->_rectListCount[idx]; +} + +void GraphicsManager::restoreMCGASaveRect(ViewPortResource *viewPort) { +	if (viewPort->_rectListCount[0] != -1) { +		for (int i = 0; i < viewPort->_rectListCount[0]; ++i) { +			addRectOptSaveRect(viewPort, 1, (*viewPort->_rectListPtr[0])[i]); +		} +	} else { +		viewPort->_rectListCount[1] = -1; +	} + +	restoreBack(*viewPort->_rectListPtr[1], viewPort->_rectListCount[1], viewPort->_pages[0], +		viewPort->_pages[1]); +	 +	int count = viewPort->_rectListCount[0]; +	restoreBack(*viewPort->_rectListPtr[0], viewPort->_rectListCount[0],  +		viewPort->_activePage, viewPort->_currentPic); + +	SWAP(viewPort->_rectListPtr[0], viewPort->_rectListPtr[1]); +	viewPort->_rectListCount[1] = count; +} + +void GraphicsManager::addRectNoSaveBack(ViewPortResource *viewPort, int idx, const Common::Rect &bounds) { +	// Stubbed/dummy method in the original. +} + +void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *destDisplay, +		const Common::Point &initialOffset) { +	int width1, width2; +	int widthDiff, widthDiff2; +	int height1; +	int srcOffset; +	int screenOffset; +	int srcFlags, destFlags; +	ViewPortResource *destViewPort = NULL; +	Common::Rect newBounds; +	Common::Rect backBounds; +	int tmpWidth = 0; +	int tmpHeight = 0; +	bool isClipped = false; +	byte pixel = 0; +	int runLength; + +	byte *srcImgData, *destImgData; +	byte *srcP, *destP; +	byte byteVal, byteVal2; + +	PictureResource *srcPic; +	PictureResource *destPic; + +	// Get the picture parameters, or deference viewport pointers to get their pictures +	if (srcDisplay->_flags & DISPFLAG_VIEWPORT) { +		// A viewport was passed, not a picture +		srcPic = ((ViewPortResource *)srcDisplay)->_currentPic; +	} else { +		srcPic = (PictureResource *)srcDisplay; +	} + +	if (destDisplay->_flags & DISPFLAG_VIEWPORT) { +		// A viewport was passed, not a picture +		destViewPort = (ViewPortResource *)destDisplay; +		destPic = destViewPort->_currentPic; +	} else { +		destPic = (PictureResource *)destDisplay; +	} + +	Common::Point offset = Common::Point(initialOffset.x + srcPic->_bounds.left - destPic->_bounds.left,  +		initialOffset.y + srcPic->_bounds.top - destPic->_bounds.top); +	width1 = width2 = srcPic->_bounds.width(); +	height1 = srcPic->_bounds.height(); +	srcOffset = 0; +	srcFlags = srcPic->_flags; +	destFlags = destPic->_flags; +	byte *cursorData = NULL; + +	if (srcFlags & 1) { +		if (_clipPtr) { +			int xs = _clipPtr->left - destPic->_bounds.left; +			int ys = _clipPtr->top - destPic->_bounds.top; +			newBounds = Common::Rect(xs, ys, xs + _clipPtr->width(), ys + _clipPtr->height()); +		} else if (destViewPort) { +			int xs = destViewPort->_clipRect.left - destPic->_bounds.left; +			int ys = destViewPort->_clipRect.top - destPic->_bounds.top; +			newBounds = Common::Rect(xs, ys, xs + destViewPort->_clipRect.width(), +				ys + destViewPort->_clipRect.height()); +		} else { +			newBounds = Common::Rect(0, 0, destPic->_bounds.width(), destPic->_bounds.height()); +		} + +		tmpHeight = offset.y - newBounds.top; +		if (tmpHeight < 0) { +			srcOffset -= tmpHeight * width2; +			height1 += tmpHeight; +			offset.y = newBounds.top; +			 +			if (height1 <= 0) +				return; + +			isClipped = true; +		} + +		int yMin = newBounds.bottom - (offset.y + height1); +		if (yMin < 0) { +			height1 += yMin; +			if (height1 <= 0) +				return; +		} + +		tmpWidth = offset.x - newBounds.left; +		if (tmpWidth < 0) { +			srcOffset -= tmpWidth; +			width2 += tmpWidth; +			offset.x = newBounds.left; + +			if (width2 <= 0) +				return; + +			isClipped = true; +		} + +		int xMin = newBounds.right - (offset.x + width2); +		if (xMin < 0) { +			width2 += xMin; +			if (width2 <= 0) +				return; + +			isClipped = true; +		} +	} + +	screenOffset = offset.y * destPic->_bounds.width() + offset.x; +	widthDiff = width1 - width2; +	widthDiff2 = destPic->_bounds.width() - width2; + +	if (destViewPort) { +		if (!_saveBack || ((srcPic->_flags & DISPFLAG_800) != 0)) { +			backBounds.left = destPic->_bounds.left + offset.x; +			backBounds.top = destPic->_bounds.top + offset.y; +			backBounds.setWidth(width2); +			backBounds.setHeight(height1); +			addRectOptSaveRect(destViewPort, 1, backBounds); + +		} else if (!destViewPort->_addFn) { +			if (destViewPort->_rectListCount[destViewPort->_pageIndex] < -1) { +				Common::Rect r; +				r.left = destPic->_bounds.left + offset.x; +				r.top = destPic->_bounds.top + offset.y; +				r.setWidth(width2); +				r.setHeight(height1); + +				(*destViewPort->_rectListPtr[destViewPort->_pageIndex]).push_back(r); +				++destViewPort->_rectListCount[destViewPort->_pageIndex]; +			} +		} else { +			int xs = offset.x + destPic->_bounds.left; +			int ys = offset.y + destPic->_bounds.top; +			backBounds = Common::Rect(xs, ys, xs + width2, ys + height1); + +			(this->*destViewPort->_addFn)(destViewPort, destViewPort->_bounds.top, backBounds); +		} +	} + +	if (srcFlags & DISPFLAG_1000) { +		int imageDataShift = 0; +		srcImgData = srcPic->_imgData + (imageDataShift << 14); +		for (uint idx = 0; idx < srcPic->_maskData; ++idx) { +			if (imageDataShift < 4) +				++imageDataShift; +		} + +		destImgData = destPic->_imgData + (imageDataShift << 14); +		for (uint idx = 0; idx < srcPic->_maskData; ++idx) { +			if (imageDataShift < 4) +				++imageDataShift; +		}		 +	} else { +		srcImgData = srcPic->_imgData; +		destImgData = destPic->_imgData; +	} + +	if (srcPic->_select != 0xff) +		return; + +	if (destFlags & DISPFLAG_CURSOR) { +		cursorData = new byte[width2 * height1]; +		Common::fill(cursorData, cursorData + width2 * height1, 0); +		destImgData = cursorData; +	} + +	if (srcPic->_pick == 0xff) { +		if (srcFlags & DISPFLAG_8) { +			error("TODO: sDrawPic variation"); +		} else { +			// loc_258B8 +			srcP = srcImgData + srcOffset; + +			if (destFlags & DISPFLAG_8) { +				// loc_258D8 +				destP = destImgData + screenOffset; + +				if (srcFlags & DISPFLAG_2) { +					// loc_25652 +					srcP = srcImgData + srcOffset; + +					if (destFlags & DISPFLAG_8) { +						// loc_2566F +						if (srcFlags & DISPFLAG_2) { +							// loc_256FA +							srcP = (byte *)_screenSurface.getPixels() + srcOffset; + +							for (int yp = 0; yp < height1; ++yp) { +								for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) { +									pixel = *srcP; +									if (pixel) +										*destP = pixel; +								} + +								srcP += widthDiff; +								destP += widthDiff2; +							} +						} else { +							// loc_25706 +							for (int yp = 0; yp < height1; ++yp) { +								Common::copy(srcP, srcP + width2, destP); +								srcP += width2 + widthDiff; +								destP += width2 + widthDiff2; +							} +						} +					} else { +						// loc_25773 +						destP = destImgData + screenOffset; + +						if (srcFlags & DISPFLAG_2) { +							// loc_25793 +							for (int yp = 0; yp < height1; ++yp) { +								Common::copy(srcP, srcP + width2, destP); +								srcP += width2 + widthDiff; +								destP += width2 + widthDiff2; +							} +						} else { +							// loc_25829 +							destP = (byte *)_screenSurface.getPixels() + screenOffset; + +							for (int yp = 0; yp < height1; ++yp) { +								Common::copy(srcP, srcP + width2, destP); +								srcP += width2 + widthDiff; +								destP += width2 + widthDiff2; +							} +						} +					} +				} else { +					// loc_25D40 +					if (srcFlags & DISPFLAG_100) { +						// loc_25D4A +						error("TODO: sDrawPic variation"); +					} else { +						// loc_2606D +						destP = (byte *)_screenSurface.getPixels() + screenOffset; + +						for (int yp = 0; yp < height1; ++yp) { +							Common::copy(srcP, srcP + width2, destP); +							destP += width2 + widthDiff2; +							srcP += width2 + widthDiff; +						} +					} +				} +			} else { +				// loc_2615E +				destP = destImgData + screenOffset; + +				if (srcFlags & DISPFLAG_2) { +					// loc_2617e +					if (srcFlags & DISPFLAG_100) { +						// loc_26188 +						srcP = srcImgData; +						if (isClipped) { +							// loc_26199 +							tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0; +							int xMax = tmpWidth + width2; +							tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0; + +							width2 = srcPic->_bounds.width(); +							height1 = tmpHeight + height1; +							 +							for (int yp = 0; yp < height1; ++yp) { +								runLength = 0; + +								for (int xp = 0; xp < width2; ++xp, --runLength) { +									if (runLength <= 0) { +										pixel = *srcP++; +										if (pixel & 0x80) { +											pixel &= 0x7f; +											runLength = *srcP++; +											if (!runLength) +												runLength = width2; +										} +									} + +									if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) { +										if (pixel > 0) +											*destP = pixel; +										++destP; +									} +								} + +								if (yp >= tmpHeight) +									destP += widthDiff2; +							} +						} else { +							// loc_262BE +							byteVal = 0; +							for (int yp = 0; yp < height1; ++yp) { +								for (int xp = 0; xp < width2; ++xp) { +									byteVal2 = 0; +									if (!byteVal2) { +										byteVal = *++srcP; +										if (byteVal & 0x80) { +											byteVal &= 0x7f; +											byteVal2 = *srcP++; + +											if (!byteVal2) +												byteVal2 = width2; +										} +									} + +									if (byteVal > 0) +										*destP = byteVal; + +									++destP; +									--byteVal2; +								} + +								destP += widthDiff2; +							} +						} +					} else { +						// loc_2637F +						// Copy with transparency +						for (int yp = 0; yp < height1; ++yp) { +							for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) { +								if (*srcP != 0) +									*destP = *srcP; +							} + +							destP += widthDiff2; +							srcP += widthDiff; +						} +					} +				} else { +					if (srcFlags & 0x100) { +						// Simple run-length encoded image +						srcP = srcImgData; + +						if (isClipped) { +							// loc_26424 +							tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0; +							int xMax = tmpWidth + width2; +							tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0; +							width2 = srcPic->_bounds.width(); +							height1 = tmpHeight + height1; + +							for (int yp = 0; yp < height1; ++yp) { +								runLength = 0; +								for (int xp = 0; xp < width2; ++xp, --runLength) { +									if (runLength <= 0) { +										pixel = *srcP++; +										if (pixel & 0x80) { +											pixel &= 0x7F; +											runLength = *srcP++; + +											if (!runLength) +												runLength = width2; +										} +									} + +									if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) { +										*destP++ = pixel; +									} +								} + +								if (yp >= tmpHeight) +									destP += widthDiff2; +							} +						} else { +							// loc_26543 +							for (int yp = 0; yp < height1; ++yp) { +								int runLen = 0; +								for (int xp = 0; xp < width2; ++xp, --runLen) { +									if (runLen <= 0) { +										// Start of run length, so get pixel and repeat length +										pixel = *srcP++; +										if (pixel & 0x80) { +											pixel &= 0x7f; +											runLen = *srcP++; +											if (runLen == 0) +												runLen = width2; +										} +									} + +									// Copy pixel to output +									*destP++ = pixel; +								} + +								destP += widthDiff2; +							} +						} +					} else { +						for (int yp = 0; yp < height1; ++yp) { +							Common::copy(srcP, srcP + width2, destP); +							destP += width2 + widthDiff2; +							srcP += width2 + widthDiff; +						} +					} +				} +			} +		} +	} else { +		// loc_26666 +		if (srcPic->_pick == 0) { +			// loc_2727A +			byte onOff = srcPic->_onOff; + +			if (srcFlags & DISPFLAG_2) { +				if (!(srcFlags & DISPFLAG_8)) { +					srcP = srcImgData + srcOffset; +					 +					if (destFlags & DISPFLAG_8) { +						// loc_272C3 +						error("TODO: sDrawPic variation"); +					} else { +						destP = destImgData + screenOffset; +						for (int yp = 0; yp < height1; ++yp) { +							for (int xp = 0; xp < width2; ++xp, ++destP) { +								if ((int8)*srcP++ < 0) +									*destP = onOff; +							} + +							destP += widthDiff2; +							srcP += widthDiff; +						} +					} +				} +			} else { +				// loc_27477 +				if (destFlags & DISPFLAG_8) { +					// loc_27481 +					destP = (byte *)_screenSurface.getPixels() + screenOffset; +					for (int yp = 0; yp < height1; ++yp) { +						Common::fill(destP, destP + width2, onOff); +						destP += width2 + widthDiff2; +					} +				} else { +					// loc_2753C +					destP = destImgData + screenOffset; + +					for (int yp = 0; yp < height1; ++yp) { +						Common::fill(destP, destP + width2, onOff); +						destP += width2 + widthDiff2; +					} +				} +			} + +		} else { +			// loc_26673 +			int pick = srcPic->_pick; +			int onOff = srcPic->_onOff; + +			if (!(srcFlags & PICFLAG_PIC_OFFSET)) { +				srcP = srcImgData += srcOffset; +				pixel = 0; + +				if (destFlags & PICFLAG_PIC_OFFSET) { +					destP = destImgData + screenOffset; +					if (srcFlags & PICFLAG_2) { +						if (srcFlags & PICFLAG_100) { +							if (isClipped) { +								// loc_266E3 +								destP = (byte *)_screenSurface.getPixels() + screenOffset; +								tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0; +								int xMax = tmpWidth + width2; +								tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0; +								pick = 0x7F; +								width2 = srcPic->_bounds.width(); +								height1 = tmpHeight + height1; + +								for (int yp = 0; yp < height1; ++yp) { +									int runLen = 0; +									for (int xp = 0; xp < width2; ++xp, --runLen) { +										if (runLen <= 0) { +											pixel = *srcP++; +											if (pixel & 0x80) { +												pixel &= 0x7F; +												runLen = *srcP++; +												if (!runLen) +													runLen = width2; +											} +										} + +										if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) { +											if (pixel) { +												*destP = (pixel & pick) ^ onOff; +											} +											++destP; +										} +									} +									if (yp >= tmpHeight) +										destP += widthDiff2; +								} +							} else { +								// loc_26815 +								destP = (byte *)_screenSurface.getPixels() + screenOffset; + +								for (int yp = 0; yp < height1; ++yp) { +									for (int xi = 0; xi < width2; ++xi, ++destP) { +										byteVal2 = 0; +										for (int xp = 0; xp < width2; ++xp, ++destP, --byteVal2) { +											if (!byteVal2) { +												pixel = *srcP++; +												if (pixel & 0x80) { +													pixel &= 0x7F; +													byteVal2 = *srcP++; +													if (!byteVal2) { +														byteVal2 = width2; +													} +												} +											} + +											if (pixel) +												*destP = (pixel & pick) ^ onOff; +										} +									} + +									destP += widthDiff2; +								} +							} +						} else { +							// Direct screen write +							destP = (byte *)_screenSurface.getPixels() + screenOffset; + +							for (int yp = 0; yp < height1; ++yp) { +								for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) { +									if (*srcP) +										*destP = (*srcP & pick) ^ onOff; +								} +								destP += widthDiff2; +								srcP += widthDiff; +							} +						} +					} else if (srcFlags & PICFLAG_100) { +						srcP = srcImgData; +						if (isClipped) { +							// loc_269FD +							tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0; +							int xMax = tmpWidth + width2; +							tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0; +							width2 = srcPic->_bounds.width(); +							height1 = tmpHeight + height1; + +							for (int yp = 0; yp < height1; ++yp) { +								runLength = 0; +								for (int xp = 0; xp < width2; ++xp, --runLength) { +									if (runLength <= 0) { +										pixel = *srcP++; +										if (pixel & 0x80) { +											pixel &= 0x7F; +											runLength = *srcP++; + +											if (!runLength) +												runLength = width2; +										} +									} + +									if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) { +										*destP++ = (pixel & 0x80) ^ onOff; +									} +								} +							} +						} else { +							// loc_26BD5 +							destP = (byte *)_screenSurface.getPixels() + screenOffset; + +							for (int yp = 0; yp < height1; ++yp) { +								byteVal2 = 0; + +								for (int xp = 0; xp < width2; ++xp, ++destP) { +									if (!byteVal2) { +										pixel = *srcP++; +										if (pixel & 0x80) { +											pixel &= 0x7F; +											byteVal2 = *srcP++; +											if (!byteVal2) +												byteVal2 = width2; +										} +									} + +									*destP = (pixel & pick) ^ onOff; +								} + +								destP += widthDiff2; +							} +						} +					} else { +						// loc_26C9A +						destP = (byte *)_screenSurface.getPixels() + screenOffset; + +						for (int yp = 0; yp < height1; ++yp) { +							for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) { +								*destP = (*srcP & pick) ^ onOff; +							} +							destP += widthDiff2; +							srcP += widthDiff; +						} +					} +				} else { +					// loc_26D2F +					destP = destImgData + screenOffset; + +					if (srcFlags & PICFLAG_2) { +						// loc_26D4F +						if (srcFlags & PICFLAG_100) { +							srcP = srcImgData; + +							if (isClipped) { +								// loc_26D6A +								tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0; +								int xMax = tmpWidth + width2; +								tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0; +								width2 = srcPic->_bounds.width(); +								height1 = tmpHeight + height1; + +								for (int yp = 0; yp < height1; ++yp) { +									runLength = 0; + +									for (int xp = 0; xp < width2; ++xp, --runLength) { +										if (runLength <= 0) { +											pixel = *srcP++; +											if (pixel & 0x80) { +												pixel &= 0x7F; +												runLength = *srcP++; +												if (!runLength) +													runLength = width2; +											} +										} + +										if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) { +											if (pixel) +												*destP = (pixel & pick) ^ onOff; + +											++destP; +										} +									} + +									if (yp >= tmpHeight) +										destP += widthDiff2; +								} +							} else { +								// loc_26E95 +								for (int yp = 0; yp < height1; ++yp) { +									byteVal2 = 0; +									for (int xp = 0; xp < width2; ++xp, ++destP, --byteVal2) { +										if (!byteVal2) { +											pixel = *srcP++; +											if (pixel & 0x80) { +												pixel &= 0x7F; +												byteVal2 = *srcP++; +												if (!byteVal2) +													byteVal2 = width2; +											} +										} + +										if (pixel) +											*destP = (pixel & pick) ^ onOff; +									} + +									destP += widthDiff2; +								} +							} +						} else { +							// loc_26F5D +							for (int yp = 0; yp < height1; ++yp) { +								for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) { +									if (*srcP) +										*destP = (*srcP & pick) ^ onOff; +								} +								destP += widthDiff2; +								srcP += widthDiff; +							} +						} +					} else { +						// loc_26FEF +						if (srcFlags & PICFLAG_100) { +							// loc_26FF9 +							for (int yp = 0; yp < height1; ++yp) { +								for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) { +									*destP = (*srcP & pick) ^ onOff; +								} +								destP += widthDiff2; +								srcP += widthDiff; +							} +						} else { +							// loc_271F0 +							srcP = srcImgData; +							 +							if (isClipped) { +								// loc_2700A +								tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0; +								int xMax = tmpWidth + width2; +								tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0; +								width2 = srcPic->_bounds.width(); +								height1 = tmpHeight + height1; + +								for (int yp = 0; yp < height1; ++yp) { +									runLength = 0; + +									for (int xp = 0; xp < width2; ++xp, --runLength) { +										if (runLength <= 0) { +											pixel = *srcP++; +											if (pixel & 0x80) { +												pixel &= 0x7F; +												runLength = *srcP++; +												if (!runLength) +													runLength = width2; +											} +										} + +										if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) { +											*destP++ = (pixel & pick) ^ onOff; +										} +									} + +									if (yp >= tmpHeight) +										destP += widthDiff2; +								} +							} else { +								// loc_2712F +								for (int yp = 0; yp < height1; ++yp) { +									byteVal2 = 0; +									for (int xp = 0; xp < width2; ++xp, ++destP, --byteVal2) { +										if (!byteVal2) { +											pixel = *srcP++; +											if (pixel & 0x80) { +												pixel &= 0x7F; +												byteVal2 = *srcP++; +												if (!byteVal2) +													byteVal2 = width2; +											} +										} + +										*destP = (*srcP & pick) ^ onOff; +									} +									destP += widthDiff2; +								} +							} +						} +					} +				} +			} +		} +	} + +	if (cursorData) { +		_vm->_eventsManager->setCursor(cursorData, width2, height1); +		delete[] cursorData; +	} +} + +void GraphicsManager::drawANumber(DisplayResource *display, int num, const Common::Point &pt) { +	PictureResource *pic = _vm->_bVoy->boltEntry(num + 261)._picResource; +	sDrawPic(pic, display, pt); +} + +void GraphicsManager::fillPic(DisplayResource *display, byte onOff) { +	PictureResource *pic; +	if (display->_flags & DISPFLAG_VIEWPORT) { +		pic = ((ViewPortResource *)display)->_currentPic; +	} else { +		pic = (PictureResource *)display; +	} + +	PictureResource picResource; +	picResource._flags = 0; +	picResource._select = 0xff; +	picResource._pick = 0; +	picResource._onOff = onOff; +	picResource._bounds = pic->_bounds; + +	sDrawPic(&picResource, display, Common::Point()); +} + +/** + * Queues the given picture for display + */ +void GraphicsManager::sDisplayPic(PictureResource *pic) { +	_vm->_eventsManager->_intPtr._flipWait = true; +} + +void GraphicsManager::flipPage() { +	Common::Array<ViewPortResource *> &viewPorts = _viewPortListPtr->_entries; +	bool flipFlag = false; + +	for (uint idx = 0; idx < viewPorts.size(); ++idx) { +		if (viewPorts[idx]->_flags & DISPFLAG_20) { +			if ((viewPorts[idx]->_flags & (DISPFLAG_8 || DISPFLAG_1))  +					== (DISPFLAG_8 || DISPFLAG_1)) { +				if (_planeSelect == idx) +					sDisplayPic(viewPorts[idx]->_currentPic); +				flipFlag = true; +			} +		} + +		if (flipFlag) { +			ViewPortResource &viewPort = *viewPorts[idx]; + +			viewPort._lastPage = viewPort._pageIndex; +			++viewPort._pageIndex; + +			if (viewPort._pageIndex >= viewPort._pageCount) +				viewPort._pageIndex = 0; + +			assert(viewPort._pageIndex < 2); +			viewPort._currentPic = viewPort._pages[viewPort._pageIndex]; +			viewPort._flags = (viewPort._flags & ~DISPFLAG_8) | DISPFLAG_40; +		} +	} +} + +void GraphicsManager::restoreBack(Common::Array<Common::Rect> &rectList, int rectListCount, +		PictureResource *srcPic, PictureResource *destPic) { +	// WORKAROUND: Since _backgroundPage can point to a resource freed at the end of display methods, +	// I'm now explicitly resetting it to null in screenReset(), so at this point it can be null +	if (!srcPic) +		return; + +	bool saveBack = _saveBack; +	_saveBack = false; + +	if (rectListCount == -1) { +		sDrawPic(srcPic, destPic, Common::Point()); +	} else { +		for (int i = rectListCount - 1; i >= 0; --i) { +			_clipPtr = &rectList[i]; +			sDrawPic(srcPic, destPic, Common::Point()); +		} +	} + +	_saveBack = saveBack; +} + +void GraphicsManager::clearPalette() { +	byte palette[768]; +	Common::fill(&palette[0], &palette[768], 0); +	g_system->getPaletteManager()->setPalette(&palette[0], 0, 256); +} + +void GraphicsManager::setPalette(const byte *palette, int start, int count) { +	g_system->getPaletteManager()->setPalette(palette, start, count); +	_vm->_eventsManager->_gameData._hasPalette = false; +} + +void GraphicsManager::setPalette128(const byte *palette, int start, int count) { +	byte rgb[3]; +	g_system->getPaletteManager()->grabPalette(&rgb[0], 128, 1); +	g_system->getPaletteManager()->setPalette(palette, start, count); +	g_system->getPaletteManager()->setPalette(&rgb[0], 128, 1); +} + + +void GraphicsManager::resetPalette() { +	for (int i = 0; i < 256; ++i) +		setColor(i, 0, 0, 0); + +	_vm->_eventsManager->_intPtr._hasPalette = true; +} + +void GraphicsManager::setColor(int idx, byte r, byte g, byte b) { +	byte *vgaP = &_VGAColors[idx * 3]; +	vgaP[0] = r; +	vgaP[1] = g; +	vgaP[2] = b; + +	_vm->_eventsManager->_intPtr._palStartIndex = MIN(_vm->_eventsManager->_intPtr._palStartIndex, idx); +	_vm->_eventsManager->_intPtr._palEndIndex = MAX(_vm->_eventsManager->_intPtr._palEndIndex, idx); +} + +void GraphicsManager::setOneColor(int idx, byte r, byte g, byte b) { +	byte palEntry[3]; +	palEntry[0] = r; +	palEntry[1] = g; +	palEntry[2] = b; +	g_system->getPaletteManager()->setPalette(&palEntry[0], idx, 1); +} + +void GraphicsManager::setColors(int start, int count, const byte *pal) { +	for (int i = 0; i < count; ++i) { +		if ((i + start) != 128) { +			const byte *rgb = pal + i * 3; +			setColor(i + start, rgb[0], rgb[1], rgb[2]); +		} +	} + +	_vm->_eventsManager->_intPtr._hasPalette = true; +} + +void GraphicsManager::screenReset() { +	resetPalette(); + +	_backgroundPage = NULL; +	(*_vPort)->setupViewPort(NULL); +	fillPic(*_vPort, 0);	 + +	_vm->flipPageAndWait(); +} + +void GraphicsManager::fadeDownICF1(int steps) { +	if (steps > 0) { +		int stepAmount = _vm->_voy->_fadingAmount2 / steps; + +		for (int idx = 0; idx < steps; ++idx) { +			_vm->_voy->_fadingAmount2 -= stepAmount; +			_vm->_eventsManager->delay(1); +		} +	} + +	_vm->_voy->_fadingAmount2 = 0; +} + +void GraphicsManager::fadeUpICF1(int steps) { +	if (steps > 0) { +		int stepAmount = (63 - _vm->_voy->_fadingAmount2) / steps; + +		for (int idx = 0; idx < steps; ++idx) { +			_vm->_voy->_fadingAmount2 += stepAmount; +			_vm->_eventsManager->delay(1); +		} +	} + +	_vm->_voy->_fadingAmount2 = 63; +} + +void GraphicsManager::fadeDownICF(int steps) { +	if (steps > 0) { +		_vm->_eventsManager->hideCursor(); +		int stepAmount1 = _vm->_voy->_fadingAmount1 / steps; +		int stepAmount2 = _vm->_voy->_fadingAmount2 / steps; + +		for (int idx = 0; idx < steps; ++idx) { +			_vm->_voy->_fadingAmount1 -= stepAmount1; +			_vm->_voy->_fadingAmount2 -= stepAmount2; +			_vm->_eventsManager->delay(1); +		} +	} + +	_vm->_voy->_fadingAmount1 = 0; +	_vm->_voy->_fadingAmount2 = 0; +} + +void GraphicsManager::drawDot() { +	for (int y = 0; y < 9; ++y) { +		byte *pDest = (byte *)_screenSurface.getPixels() + DOT_LINE_START[y] + DOT_LINE_OFFSET[y]; +		Common::fill(pDest, pDest + DOT_LINE_LENGTH[y], 0x80); +	} +} + +void GraphicsManager::synchronize(Common::Serializer &s) { +	s.syncBytes(&_VGAColors[0], PALETTE_SIZE); +} + +} // End of namespace Voyeur | 
