diff options
| -rw-r--r-- | engines/kyra/detection_tables.h | 81 | ||||
| -rw-r--r-- | engines/kyra/kyra_v1.h | 1 | ||||
| -rw-r--r-- | engines/kyra/screen.cpp | 366 | ||||
| -rw-r--r-- | engines/kyra/screen.h | 41 | ||||
| -rw-r--r-- | engines/kyra/screen_eob.cpp | 293 | ||||
| -rw-r--r-- | engines/kyra/screen_eob.h | 6 | 
6 files changed, 585 insertions, 203 deletions
| diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h index 43dc0cc881..0b45977d22 100644 --- a/engines/kyra/detection_tables.h +++ b/engines/kyra/detection_tables.h @@ -22,45 +22,46 @@  namespace { -#define FLAGS(x, y, z, a, b, c, d, e, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, d, e, id } -#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, d, e, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, d, e, id } - -#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, false, true, Kyra::GI_KYRA1) -#define KYRA1_OLDFLOPPY_FLAGS FLAGS(false, false, false, true, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, false, true, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_DEMO_CD_FLAGS FLAGS(true, true, true, false, false, false, false, false, Kyra::GI_KYRA1) - -#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, false, true, Kyra::GI_KYRA2) -#define KYRA2_FLOPPY_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, false, false, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, false, true, false, false, false, Kyra::GI_KYRA2) - -#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, false, false, true, true, Kyra::GI_KYRA3) -#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, false, false, true, false, Kyra::GI_KYRA3) -#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, true, false, Kyra::GI_KYRA3) - -#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, false, false, Kyra::GI_LOL) -#define LOL_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, false, Kyra::GI_LOL) -#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_LOL) -#define LOL_FLOPPY_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, false, false, false, false, false, false, Kyra::GI_LOL) -#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, false, true, Kyra::GI_LOL) -#define LOL_PC9801_FLAGS FLAGS(false, false, false, false, true, true, false, false, Kyra::GI_LOL) -#define LOL_FMTOWNS_FLAGS FLAGS(false, false, false, false, true, false, false, false, Kyra::GI_LOL) -#define LOL_DEMO_FLAGS FLAGS(true, true, false, false, false, false, false, false, Kyra::GI_LOL) -#define LOL_KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, Kyra::GI_KYRA2) - -#define EOB_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_EOB1) -#define EOB2_FLAGS FLAGS(false, false, false, false, false, false, false, false, Kyra::GI_EOB2) +#define EOB2_SJIS_FLAGS FLAGS(false, false, false, false, true, false, false, false, Kyra::GI_EOB2) +#define FLAGS(x, y, z, a, b, c, d, e, f, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, d, e, f, id } +#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, d, e, f, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, d, e, f, id } + +#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, false, false, true, Kyra::GI_KYRA1) +#define KYRA1_OLDFLOPPY_FLAGS FLAGS(false, false, false, true, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, false, true, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_DEMO_CD_FLAGS FLAGS(true, true, true, false, false, false, false, false, false, Kyra::GI_KYRA1) + +#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, false, false, true, Kyra::GI_KYRA2) +#define KYRA2_FLOPPY_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, false, false, false, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, false, true, false, false, false, false, Kyra::GI_KYRA2) + +#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, false, false, false, true, true, Kyra::GI_KYRA3) +#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, false, false, false, true, false, Kyra::GI_KYRA3) +#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, true, false, Kyra::GI_KYRA3) + +#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, false, false, false, Kyra::GI_LOL) +#define LOL_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, false, false, Kyra::GI_LOL) +#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, false, false, Kyra::GI_LOL) +#define LOL_FLOPPY_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, false, false, false, false, false, false, false, Kyra::GI_LOL) +#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, false, false, true, Kyra::GI_LOL) +#define LOL_PC9801_FLAGS FLAGS(false, false, false, false, true, true, false, false, false, Kyra::GI_LOL) +#define LOL_FMTOWNS_FLAGS FLAGS(false, false, false, false, true, false, false, false, false, Kyra::GI_LOL) +#define LOL_DEMO_FLAGS FLAGS(true, true, false, false, false, false, false, false, false, Kyra::GI_LOL) +#define LOL_KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, false, false, Kyra::GI_KYRA2) + +#define EOB_FLAGS FLAGS(false, false, false, false, false, false, false, false, false, Kyra::GI_EOB1) +#define EOB2_FLAGS FLAGS(false, false, false, false, false, false, false, false, false, Kyra::GI_EOB2)  #define GAMEOPTION_KYRA3_AUDIENCE GUIO_GAMEOPTIONS1  #define GAMEOPTION_KYRA3_SKIP     GUIO_GAMEOPTIONS2 @@ -1685,7 +1686,7 @@ const KYRAGameDescription adGameDescs[] = {  	},  #endif // ENABLE_EOB -	{ AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0) } +	{ AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) }  };  const PlainGameDescriptor gameList[] = { diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index bbbd59a4b8..9fdddb89a9 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -122,6 +122,7 @@ struct GameFlags {  	bool isOldFloppy          : 1;  	bool useHiRes             : 1;  	bool use16ColorMode       : 1; +	bool useHiColorMode       : 1;  	bool useDigSound          : 1;  	bool useInstallerPackage  : 1; diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index bce45b2514..a0cab913b9 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -58,6 +58,13 @@ Screen::Screen(KyraEngine_v1 *vm, OSystem *system, const ScreenDim *dimTable, co  	_renderMode = Common::kRenderDefault;  	_sjisMixedFontMode = false; +	_useHiColorScreen = _vm->gameFlags().useHiColorMode; +	_screenPageSize = SCREEN_PAGE_SIZE; +	_16bitPalette = 0; +	_16bitConversionPalette = 0; +	_16bitShadingLevel = 0; +	_bytesPerPixel = 1; +  	_currentFont = FID_8_FNT;  	_paletteChanged = true;  	_curDim = 0; @@ -76,6 +83,8 @@ Screen::~Screen() {  	delete _internFadePalette;  	delete[] _decodeShapeBuffer;  	delete[] _animBlockPtr; +	delete[] _16bitPalette; +	delete[] _16bitConversionPalette;  	for (uint i = 0; i < _palettes.size(); ++i)  		delete _palettes[i]; @@ -127,7 +136,17 @@ bool Screen::init() {  		_sjisInvisibleColor = (_vm->game() == GI_KYRA1) ? 0x80 : 0xF6;  		_sjisMixedFontMode = !_use16ColorMode; -		for (int i = 0; i < SCREEN_OVLS_NUM; ++i) { +		if (!_sjisOverlayPtrs[0]) { +			// We alway assume 2 bytes per pixel here when the backend is in hicolor mode, since this is the surface that is passed to the backend. +			// We do this regardsless of the paramater sent to enableHiColorMode() so as not to have to change the backend color mode. +			// Conversions from 8bit to 16bit have to take place when copying data to this surface here. +			int bpp = _useHiColorScreen ? 2 : 1; +			_sjisOverlayPtrs[0] = new uint8[SCREEN_OVL_SJIS_SIZE * bpp]; +			assert(_sjisOverlayPtrs[0]); +			memset(_sjisOverlayPtrs[0], _sjisInvisibleColor, SCREEN_OVL_SJIS_SIZE * bpp); +		} + +		for (int i = 1; i < SCREEN_OVLS_NUM; ++i) {  			if (!_sjisOverlayPtrs[i]) {  				_sjisOverlayPtrs[i] = new uint8[SCREEN_OVL_SJIS_SIZE];  				assert(_sjisOverlayPtrs[i]); @@ -147,27 +166,7 @@ bool Screen::init() {  	_curPage = 0; -	Common::Array<uint8> realPages; -	for (int i = 0; i < SCREEN_PAGE_NUM; i++) { -		if (Common::find(realPages.begin(), realPages.end(), _pageMapping[i]) == realPages.end()) -			realPages.push_back(_pageMapping[i]); -	} - -	int numPages = realPages.size(); -	uint32 bufferSize = numPages * SCREEN_PAGE_SIZE; - -	uint8 *pagePtr = new uint8[bufferSize]; -	memset(pagePtr, 0, bufferSize); - -	memset(_pagePtrs, 0, sizeof(_pagePtrs)); -	for (int i = 0; i < SCREEN_PAGE_NUM; i++) { -		if (_pagePtrs[_pageMapping[i]]) { -			_pagePtrs[i] = _pagePtrs[_pageMapping[i]]; -		} else { -			_pagePtrs[i] = pagePtr; -			pagePtr += SCREEN_PAGE_SIZE; -		} -	} +	enableHiColorMode(false);  	memset(_shapePages, 0, sizeof(_shapePages)); @@ -223,6 +222,7 @@ bool Screen::init() {  	_charOffset = 0;  	for (int i = 0; i < ARRAYSIZE(_textColorsMap); ++i)  		_textColorsMap[i] = i; +	_textColorsMap16bit[0] = _textColorsMap16bit[1] = 0;  	_decodeShapeBuffer = NULL;  	_decodeShapeBufferSize = 0;  	_animBlockPtr = NULL; @@ -249,8 +249,9 @@ bool Screen::enableScreenDebug(bool enable) {  }  void Screen::setResolution() { -	byte palette[3*256]; -	_system->getPaletteManager()->grabPalette(palette, 0, 256); +	byte palette[3 * 256]; +	if (!_useHiColorScreen) +		_system->getPaletteManager()->grabPalette(palette, 0, 256);  	int width = 320, height = 200; @@ -268,9 +269,49 @@ void Screen::setResolution() {  			width = 320;  	} -	initGraphics(width, height); +	if (_useHiColorScreen) { +		Graphics::PixelFormat px(2, 5, 5, 5, 0, 10, 5, 0, 0); +		Common::List<Graphics::PixelFormat> tryModes = _system->getSupportedFormats(); +		for (Common::List<Graphics::PixelFormat>::iterator g = tryModes.begin(); g != tryModes.end(); ++g) { +			if (g->bytesPerPixel != 2 || g->aBits()) { +				g = tryModes.reverse_erase(g); +			} else if (*g == px) { +				tryModes.clear(); +				tryModes.push_back(px); +				break; +			} +		} +		initGraphics(width, height, tryModes); +		if (_system->getScreenFormat().bytesPerPixel != 2) +			error("Required graphics mode not supported by platform."); +		 +	} else { +		initGraphics(width, height); +		_system->getPaletteManager()->setPalette(palette, 0, 256); +	} +} + +void Screen::enableHiColorMode(bool enabled) { +	if (_useHiColorScreen && enabled) { +		if (!_16bitPalette) +			_16bitPalette = new uint16[1024]; +		memset(_16bitPalette, 0, 1024 * sizeof(uint16)); +		delete[] _16bitConversionPalette; +		_16bitConversionPalette = 0; +		_bytesPerPixel = 2; +	} else { +		if (_useHiColorScreen) { +			if (!_16bitConversionPalette) +				_16bitConversionPalette = new uint16[256]; +			memset(_16bitConversionPalette, 0, 256 * sizeof(uint16)); +		} + +		delete[] _16bitPalette; +		_16bitPalette = 0; +		_bytesPerPixel = 1; +	} -	_system->getPaletteManager()->setPalette(palette, 0, 256); +	resetPagePtrsAndBuffers(SCREEN_PAGE_SIZE * _bytesPerPixel);  }  void Screen::updateScreen() { @@ -386,22 +427,22 @@ void Screen::updateDirtyRectsOvl() {  	if (_forceFullUpdate) {  		const byte *src = getCPagePtr(0);  		byte *dst = _sjisOverlayPtrs[0]; -  		scale2x(dst, 640, src, SCREEN_W, SCREEN_W, SCREEN_H);  		mergeOverlay(0, 0, 640, 400); -		_system->copyRectToScreen(dst, 640, 0, 0, 640, 400); +		_system->copyRectToScreen(dst, _useHiColorScreen ? 1280 : 640, 0, 0, 640, 400);  	} else {  		const byte *page0 = getCPagePtr(0);  		byte *ovl0 = _sjisOverlayPtrs[0]; +		int dstBpp = _useHiColorScreen ? 2 : 1;  		Common::List<Common::Rect>::iterator it;  		for (it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) { -			byte *dst = ovl0 + it->top * 1280 + (it->left<<1); -			const byte *src = page0 + it->top * SCREEN_W + it->left; +			byte *dst = ovl0 + it->top * 1280 * dstBpp + (it->left << dstBpp); +			const byte *src = page0 + it->top * SCREEN_W * _bytesPerPixel + it->left * _bytesPerPixel;  			scale2x(dst, 640, src, SCREEN_W, it->width(), it->height());  			mergeOverlay(it->left<<1, it->top<<1, it->width()<<1, it->height()<<1); -			_system->copyRectToScreen(dst, 640, it->left<<1, it->top<<1, it->width()<<1, it->height()<<1); +			_system->copyRectToScreen(dst, _useHiColorScreen ? 1280 : 640, it->left << 1, it->top << 1, it->width() << 1, it->height() << 1);  		}  	} @@ -410,18 +451,31 @@ void Screen::updateDirtyRectsOvl() {  }  void Screen::scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h) { +	int srcBpp = _bytesPerPixel; +	int dstBpp = _useHiColorScreen ? 2 : 1; +  	byte *dstL1 = dst; -	byte *dstL2 = dst + dstPitch; +	byte *dstL2 = dst + dstPitch * dstBpp; -	int dstAdd = dstPitch * 2 - w * 2; -	int srcAdd = srcPitch - w; +	int dstAdd = (dstPitch * 2 - w * 2) * dstBpp; +	int srcAdd = (srcPitch - w) * srcBpp; +	int dstInc = 2 * dstBpp;  	while (h--) { -		for (int x = 0; x < w; ++x, dstL1 += 2, dstL2 += 2) { -			uint16 col = *src++; -			col |= col << 8; -			*(uint16 *)(dstL1) = col; -			*(uint16 *)(dstL2) = col; +		for (int x = 0; x < w; x++, src += srcBpp, dstL1 += dstInc, dstL2 += dstInc) { +			if (dstBpp == 1) { +				uint16 col = *src; +				col |= col << 8; +				*(uint16 *)(dstL1) = *(uint16 *)(dstL2) = col; +			} else if (dstBpp == srcBpp) { +				uint32 col = *(const uint16 *)src; +				col |= col << 16; +				*(uint32 *)(dstL1) = *(uint32 *)(dstL2) = col; +			} else if (dstBpp == 2) { +				uint32 col = _16bitConversionPalette[*src]; +				col |= col << 16; +				*(uint32 *)(dstL1) = *(uint32 *)(dstL2) = col; +			}  		}  		dstL1 += dstAdd; dstL2 += dstAdd;  		src += srcAdd; @@ -429,18 +483,24 @@ void Screen::scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int  }  void Screen::mergeOverlay(int x, int y, int w, int h) { -	byte *dst = _sjisOverlayPtrs[0] + y * 640 + x; +	int bpp = _useHiColorScreen ? 2 : 1; +	byte *dst = _sjisOverlayPtrs[0] + y * 640 * bpp + x * bpp;  	const byte *src = _sjisOverlayPtrs[1] + y * 640 + x; +	uint16 *p16 = _16bitPalette ? _16bitPalette : (_16bitConversionPalette ? _16bitConversionPalette : 0);  	int add = 640 - w;  	while (h--) { -		for (x = 0; x < w; ++x, ++dst) { +		for (x = 0; x < w; ++x, dst += bpp) {  			byte col = *src++; -			if (col != _sjisInvisibleColor) -				*dst = col; +			if (col != _sjisInvisibleColor) { +				if (bpp == 2) +					*(uint16*)dst = p16[col]; +				else +					*dst = col; +			}  		} -		dst += add; +		dst += add * bpp;  		src += add;  	}  } @@ -468,6 +528,35 @@ void Screen::setScreenDim(int dim) {  	_curDimIndex = dim;  } +void Screen::resetPagePtrsAndBuffers(int pageSize) { +	_screenPageSize = pageSize; + +	delete[] _pagePtrs[0]; +	memset(_pagePtrs, 0, sizeof(_pagePtrs)); + +	Common::Array<uint8> realPages; +	for (int i = 0; i < SCREEN_PAGE_NUM; i++) { +		if (Common::find(realPages.begin(), realPages.end(), _pageMapping[i]) == realPages.end()) +			realPages.push_back(_pageMapping[i]); +	} + +	int numPages = realPages.size(); +	uint32 bufferSize = numPages * _screenPageSize; + +	uint8 *pagePtr = new uint8[bufferSize]; +	memset(pagePtr, 0, bufferSize); + +	memset(_pagePtrs, 0, sizeof(_pagePtrs)); +	for (int i = 0; i < SCREEN_PAGE_NUM; i++) { +		if (_pagePtrs[_pageMapping[i]]) { +			_pagePtrs[i] = _pagePtrs[_pageMapping[i]]; +		} else { +			_pagePtrs[i] = pagePtr; +			pagePtr += _screenPageSize; +		} +	} +} +  uint8 *Screen::getPagePtr(int pageNum) {  	assert(pageNum < SCREEN_PAGE_NUM);  	return _pagePtrs[pageNum]; @@ -489,7 +578,7 @@ void Screen::clearPage(int pageNum) {  	assert(pageNum < SCREEN_PAGE_NUM);  	if (pageNum == 0 || pageNum == 1)  		_forceFullUpdate = true; -	memset(getPagePtr(pageNum), 0, SCREEN_PAGE_SIZE); +	memset(getPagePtr(pageNum), 0, _screenPageSize);  	clearOverlayPage(pageNum);  } @@ -503,7 +592,7 @@ int Screen::setCurPage(int pageNum) {  void Screen::clearCurPage() {  	if (_curPage == 0 || _curPage == 1)  		_forceFullUpdate = true; -	memset(getPagePtr(_curPage), 0, SCREEN_PAGE_SIZE); +	memset(getPagePtr(_curPage), 0, _screenPageSize);  	clearOverlayPage(_curPage);  } @@ -670,9 +759,13 @@ void Screen::setPagePixel(int pageNum, int x, int y, uint8 color) {  		color &= 0x03;  	} else if (_renderMode == Common::kRenderEGA && !_useHiResEGADithering) {  		color &= 0x0F; +	}  +	 +	if (_bytesPerPixel == 2) { +		*(uint16*)(&_pagePtrs[pageNum][y * SCREEN_W * 2 + x * 2]) = _16bitPalette[color]; +	} else { +		_pagePtrs[pageNum][y * SCREEN_W + x] = color;  	} - -	_pagePtrs[pageNum][y * SCREEN_W + x] = color;  }  void Screen::fadeFromBlack(int delay, const UpdateFunctor *upFunc) { @@ -707,6 +800,8 @@ void Screen::fadePalette(const Palette &pal, int delay, const UpdateFunctor *upF  		if (upFunc && upFunc->isValid())  			(*upFunc)(); +		else if (_useHiColorScreen) +			updateScreen();  		else  			_system->updateScreen(); @@ -821,6 +916,22 @@ void Screen::setScreenPalette(const Palette &pal) {  	}  	_paletteChanged = true; + +	if (_useHiColorScreen) { +		if (_16bitPalette) +			memcpy(_16bitPalette, pal.getData(), 512); + +		// Generate 16bit palette for the 8bit/16 bit conversion in scale2x() +		if (_16bitConversionPalette) { +			Graphics::PixelFormat pixelFormat = _system->getScreenFormat(); +			for (int i = 0; i < 256; ++i) +				_16bitConversionPalette[i] = pixelFormat.RGBToColor(screenPal[i * 3], screenPal[i * 3 + 1], screenPal[i * 3 + 2]); +			// The whole Surface has to be converted again after each palette chance +			_forceFullUpdate = true; +		} +		return; +	} +  	_system->getPaletteManager()->setPalette(screenPal, 0, pal.getNumColors());  } @@ -908,8 +1019,8 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag  		h = SCREEN_H - y2;  	} -	const uint8 *src = getPagePtr(srcPage) + y1 * SCREEN_W + x1; -	uint8 *dst = getPagePtr(dstPage) + y2 * SCREEN_W + x2; +	const uint8 *src = getPagePtr(srcPage) + y1 * SCREEN_W * _bytesPerPixel + x1 * _bytesPerPixel; +	uint8 *dst = getPagePtr(dstPage) + y2 * SCREEN_W * _bytesPerPixel + x2 * _bytesPerPixel;  	if (src == dst)  		return; @@ -921,18 +1032,24 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag  	if (flags & CR_NO_P_CHECK) {  		while (h--) { -			memmove(dst, src, w); -			src += SCREEN_W; -			dst += SCREEN_W; +			memmove(dst, src, w * _bytesPerPixel); +			src += SCREEN_W * _bytesPerPixel; +			dst += SCREEN_W * _bytesPerPixel;  		}  	} else {  		while (h--) {  			for (int i = 0; i < w; ++i) { -				if (src[i]) -					dst[i] = src[i]; +				if (_bytesPerPixel == 2) { +					uint px = *(const uint16*)&src[i << 1]; +					if (px) +						*(uint16*)&dst[i << 1] = px; +				} else { +					if (src[i]) +						dst[i] = src[i]; +				}  			} -			src += SCREEN_W; -			dst += SCREEN_W; +			src += SCREEN_W * _bytesPerPixel; +			dst += SCREEN_W * _bytesPerPixel;  		}  	}  } @@ -960,14 +1077,14 @@ void Screen::copyRegionToBuffer(int pageNum, int x, int y, int w, int h, uint8 *  	uint8 *pagePtr = getPagePtr(pageNum);  	for (int i = y; i < y + h; ++i) -		memcpy(dest + (i - y) * w, pagePtr + i * SCREEN_W + x, w); +		memcpy(dest + (i - y) * w * _bytesPerPixel, pagePtr + i * SCREEN_W * _bytesPerPixel + x * _bytesPerPixel, w * _bytesPerPixel);  }  void Screen::copyPage(uint8 srcPage, uint8 dstPage) {  	uint8 *src = getPagePtr(srcPage);  	uint8 *dst = getPagePtr(dstPage);  	if (src != dst) -		memcpy(dst, src, SCREEN_W * SCREEN_H); +		memcpy(dst, src, SCREEN_W * SCREEN_H * _bytesPerPixel);  	copyOverlayRegion(0, 0, 0, 0, SCREEN_W, SCREEN_H, srcPage, dstPage);  	if (dstPage == 0 || dstPage == 1) @@ -994,7 +1111,7 @@ void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint  	if (w < 0 || h < 0)  		return; -	uint8 *dst = getPagePtr(pageNum) + y * SCREEN_W + x; +	uint8 *dst = getPagePtr(pageNum) + y * SCREEN_W * _bytesPerPixel + x * _bytesPerPixel;  	if (pageNum == 0 || pageNum == 1)  		addDirtyRect(x, y, w, h); @@ -1002,9 +1119,9 @@ void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint  	clearOverlayRect(pageNum, x, y, w, h);  	while (h--) { -		memcpy(dst, src, w); -		dst += SCREEN_W; -		src += w; +		memcpy(dst, src, w * _bytesPerPixel); +		dst += SCREEN_W * _bytesPerPixel; +		src += w * _bytesPerPixel;  	}  } @@ -1066,10 +1183,11 @@ void Screen::shuffleScreen(int sx, int sy, int w, int h, int srcPage, int dstPag  void Screen::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum, bool xored) {  	assert(x2 < SCREEN_W && y2 < SCREEN_H); +	uint16 color16 = 0;  	if (pageNum == -1)  		pageNum = _curPage; -	uint8 *dst = getPagePtr(pageNum) + y1 * SCREEN_W + x1; +	uint8 *dst = getPagePtr(pageNum) + y1 * SCREEN_W * _bytesPerPixel + x1 * _bytesPerPixel;  	if (pageNum == 0 || pageNum == 1)  		addDirtyRect(x1, y1, x2-x1+1, y2-y1+1); @@ -1083,9 +1201,11 @@ void Screen::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum,  		color &= 0x03;  	} else if (_renderMode == Common::kRenderEGA && !_useHiResEGADithering) {  		color &= 0x0F; -	} +	} else if (_bytesPerPixel == 2) +		color16 = shade16bitColor(_16bitPalette[color]);  	if (xored) { +		// no 16 bit support for this (unneeded)  		for (; y1 <= y2; ++y1) {  			for (int x = x1; x <= x2; ++x)  				dst[x] ^= color; @@ -1093,8 +1213,14 @@ void Screen::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum,  		}  	} else {  		for (; y1 <= y2; ++y1) { -			memset(dst, color, x2 - x1 + 1); -			dst += SCREEN_W; +			if (_bytesPerPixel == 2) { +				uint16 *ptr = (uint16*)dst; +				for (int i = 0; i < x2 - x1 + 1; i++) +					*ptr++ = color16; +			} else { +				memset(dst, color, x2 - x1 + 1); +			} +			dst += SCREEN_W * _bytesPerPixel;  		}  	}  } @@ -1151,7 +1277,7 @@ void Screen::drawClippedLine(int x1, int y1, int x2, int y2, int color) {  }  void Screen::drawLine(bool vertical, int x, int y, int length, int color) { -	uint8 *ptr = getPagePtr(_curPage) + y * SCREEN_W + x; +	uint8 *ptr = getPagePtr(_curPage) + y * SCREEN_W * _bytesPerPixel + x * _bytesPerPixel;  	if (_use16ColorMode) {  		color &= 0x0F; @@ -1160,19 +1286,30 @@ void Screen::drawLine(bool vertical, int x, int y, int length, int color) {  		color &= 0x03;  	} else if (_renderMode == Common::kRenderEGA && !_useHiResEGADithering) {  		color &= 0x0F; -	} +	} else if (_bytesPerPixel == 2) +		color = shade16bitColor(_16bitPalette[color]);  	if (vertical) {  		assert((y + length) <= SCREEN_H);  		int currLine = 0;  		while (currLine < length) { -			*ptr = color; -			ptr += SCREEN_W; +			if (_bytesPerPixel == 2) +				*(uint16*)ptr = color; +			else +				*ptr = color; +			ptr += SCREEN_W * _bytesPerPixel;  			currLine++;  		}  	} else {  		assert((x + length) <= SCREEN_W); -		memset(ptr, color, length); +		if (_bytesPerPixel == 2) { +			for (int i = 0; i < length; i++) { +				*(uint16*)ptr = color; +				ptr += 2; +			} +		} else { +			memset(ptr, color, length); +		}  	}  	if (_curPage == 0 || _curPage == 1) @@ -1189,14 +1326,25 @@ void Screen::setAnimBlockPtr(int size) {  	_animBlockSize = size;  } -void Screen::setTextColor(const uint8 *cmap, int a, int b) { -	memcpy(&_textColorsMap[a], cmap, b-a+1); +void Screen::setTextColor(const uint8 *cmap8, int a, int b) { +	memcpy(&_textColorsMap[a], cmap8, (b - a + 1)); +	// We need to update the color tables of all fonts, we +	// setup so far here. +	for (int i = 0; i < FID_NUM; ++i) { +		if (_fonts[i])  +			_fonts[i]->setColorMap(_textColorsMap); +	} +} +void Screen::setTextColor16bit(const uint16 *cmap16) { +	assert(cmap16); +	_textColorsMap16bit[0] = cmap16[0]; +	_textColorsMap16bit[1] = cmap16[1];  	// We need to update the color tables of all fonts, we  	// setup so far here.  	for (int i = 0; i < FID_NUM; ++i) {  		if (_fonts[i]) -			_fonts[i]->setColorMap(_textColorsMap); +			_fonts[i]->set16bitColorMap(_textColorsMap16bit);  	}  } @@ -1281,10 +1429,17 @@ int Screen::getTextWidth(const char *str) {  }  void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2) { -	uint8 cmap[2]; -	cmap[0] = color2; -	cmap[1] = color1; -	setTextColor(cmap, 0, 1); +	uint16 cmap16[2]; +	if (_16bitPalette) { +		cmap16[0] = color2 ? shade16bitColor(_16bitPalette[color2]) : 0xFFFF; +		cmap16[1] = _16bitPalette[color1]; +		setTextColor16bit(cmap16); +	}	 + +	uint8 cmap8[2]; +	cmap8[0] = color2; +	cmap8[1] = color1; +	setTextColor(cmap8, 0, 1);  	FontId curFont = _currentFont; @@ -1360,11 +1515,12 @@ void Screen::drawChar(uint16 c, int x, int y) {  			return;  		} -		destPage += (y * 2) * 640 + (x * 2); +		int bpp = (_currentFont == Screen::FID_SJIS_FNT) ? 1 : 2; +		destPage += (y * 2) * 640 * bpp + (x * 2 * bpp); -		fnt->drawChar(c, destPage, 640); +		fnt->drawChar(c, destPage, 640, bpp);  	} else { -		fnt->drawChar(c, getPagePtr(_curPage) + y * SCREEN_W + x, SCREEN_W); +		fnt->drawChar(c, getPagePtr(_curPage) + y * SCREEN_W * _bytesPerPixel + x * _bytesPerPixel, SCREEN_W, _bytesPerPixel);  	}  	if (_curPage == 0 || _curPage == 1) @@ -2846,6 +3002,18 @@ int16 Screen::encodeShapeAndCalculateSize(uint8 *from, uint8 *to, int size_to) {  	return (to - toPtr);  } +uint16 Screen::shade16bitColor(uint16 col) { +	uint8 r = (col & 0x1f); +	uint8 g = (col & 0x3E0) >> 5; +	uint8 b = (col & 0x7C00) >> 10; + +	r = (r > _16bitShadingLevel) ? r - _16bitShadingLevel : 0; +	g = (g > _16bitShadingLevel) ? g - _16bitShadingLevel : 0; +	b = (b > _16bitShadingLevel) ? b - _16bitShadingLevel : 0; + +	return (b << 10) | (g << 5) | r; +} +  void Screen::hideMouse() {  	++_mouseLockCount;  	CursorMan.showMouse(false); @@ -3072,7 +3240,7 @@ void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, Palette  	uint8 *srcPtr = srcData + 10 + palSize;  	uint8 *dstData = getPagePtr(dstPage); -	memset(dstData, 0, SCREEN_PAGE_SIZE); +	memset(dstData, 0, _screenPageSize);  	if (dstPage == 0 || tempPage == 0)  		_forceFullUpdate = true; @@ -3117,7 +3285,7 @@ bool Screen::loadPalette(const char *filename, Palette &pal) {  	debugC(3, kDebugLevelScreen, "Screen::loadPalette('%s', %p)", filename, (const void *)&pal); -	const int maxCols = pal.getNumColors(); +	const int maxCols = _16bitPalette ? 256 : pal.getNumColors();  	int numCols = 0;  	if (_isAmiga) { @@ -3133,8 +3301,15 @@ bool Screen::loadPalette(const char *filename, Palette &pal) {  		numCols /= Palette::kVGABytesPerColor;  		pal.loadVGAPalette(*stream, 0, numCols);  	} else { -		numCols = stream->size() / Palette::kVGABytesPerColor; -		pal.loadVGAPalette(*stream, 0, MIN(maxCols, numCols)); +		if (_bytesPerPixel == 2) { +			numCols = stream->size() / 2; +			pal.loadHiColorPalette(*stream, 0, numCols); +		} else if (!_16bitPalette) { +			numCols = stream->size() / Palette::kVGABytesPerColor; +			pal.loadVGAPalette(*stream, 0, MIN(maxCols, numCols)); +		} else { +			error("Screen::loadPalette(): Failed to load file '%s' with invalid size %d in HiColor mode", filename, stream->size()); +		}  	}  	if (numCols > maxCols) @@ -3407,7 +3582,7 @@ int DOSFont::getCharWidth(uint16 c) const {  	return _widthTable[c];  } -void DOSFont::drawChar(uint16 c, byte *dst, int pitch) const { +void DOSFont::drawChar(uint16 c, byte *dst, int pitch, int) const {  	if (c >= _numGlyphs)  		return; @@ -3549,7 +3724,7 @@ int AMIGAFont::getCharWidth(uint16 c) const {  	return _chars[c].width;  } -void AMIGAFont::drawChar(uint16 c, byte *dst, int pitch) const { +void AMIGAFont::drawChar(uint16 c, byte *dst, int pitch, int) const {  	if (c >= 255)  		return; @@ -3624,7 +3799,7 @@ void SJISFont::setColorMap(const uint8 *src) {  	}  } -void SJISFont::drawChar(uint16 c, byte *dst, int pitch) const { +void SJISFont::drawChar(uint16 c, byte *dst, int pitch, int) const {  	uint8 color1, color2;  	if (_is16Color) { @@ -3672,6 +3847,19 @@ void Palette::loadVGAPalette(Common::ReadStream &stream, int startIndex, int col  		*pos++ = stream.readByte() & 0x3F;  } +void Palette::loadHiColorPalette(Common::ReadStream &stream, int startIndex, int colors) { +	uint16 *pos = (uint16*)(_palData + startIndex * 2); + +	Graphics::PixelFormat currentFormat = g_system->getScreenFormat(); +	Graphics::PixelFormat originalFormat(2, 5, 5, 5, 0, 5, 10, 0, 0); + +	for (int i = 0; i < colors; i++) { +		uint8 r, g, b; +		originalFormat.colorToRGB(stream.readUint16LE(), r, g, b); +		*pos++ = currentFormat.RGBToColor(r, g, b); +	} +} +  void Palette::loadEGAPalette(Common::ReadStream &stream, int startIndex, int colors) {  	assert(startIndex + colors <= 16); diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h index 0b287aa8bc..bac93ae49c 100644 --- a/engines/kyra/screen.h +++ b/engines/kyra/screen.h @@ -94,6 +94,11 @@ public:  	virtual void setColorMap(const uint8 *src) = 0;  	/** +	* Sets a text 16bit palette map. Only used in in EOB II FM-Towns. The map contains 2 entries. +	*/ +	virtual void set16bitColorMap(const uint16 *src) {} + +	/**  	 * Draws a specific character.  	 *  	 * TODO/FIXME: Replace this with a nicer API. Currently @@ -101,7 +106,7 @@ public:  	 * We use this API, since it's hard to assure dirty rect  	 * handling from outside Screen.  	 */ -	virtual void drawChar(uint16 c, byte *dst, int pitch) const = 0; +	virtual void drawChar(uint16 c, byte *dst, int pitch, int bpp) const = 0;  };  /** @@ -120,7 +125,7 @@ public:  	int getWidth() const { return _width; }  	int getCharWidth(uint16 c) const;  	void setColorMap(const uint8 *src) { _colorMap = src; } -	void drawChar(uint16 c, byte *dst, int pitch) const; +	void drawChar(uint16 c, byte *dst, int pitch, int) const;  private:  	void unload(); @@ -153,8 +158,9 @@ public:  	int getHeight() const { return _height; }  	int getWidth() const { return _width; }  	int getCharWidth(uint16 c) const; -	void setColorMap(const uint8 *src) { _colorMap = src; } -	void drawChar(uint16 c, byte *dst, int pitch) const; +	void setColorMap(const uint8 *src) { _colorMap8bit = src; } +	void set16bitColorMap(const uint16 *src) { _colorMap16bit = src; } +	void drawChar(uint16 c, byte *dst, int pitch, int bpp) const;  private:  	void unload(); @@ -163,7 +169,8 @@ private:  	uint16 *_bitmapOffsets;  	int _width, _height; -	const uint8 *_colorMap; +	const uint8 *_colorMap8bit; +	const uint16 *_colorMap16bit;  	int _numGlyphs; @@ -187,7 +194,7 @@ public:  	int getWidth() const { return _width; }  	int getCharWidth(uint16 c) const;  	void setColorMap(const uint8 *src) {} -	void drawChar(uint16 c, byte *dst, int pitch) const; +	void drawChar(uint16 c, byte *dst, int pitch, int) const;  private:  	void unload(); @@ -221,7 +228,7 @@ public:  	int getWidth() const;  	int getCharWidth(uint16 c) const;  	void setColorMap(const uint8 *src); -	virtual void drawChar(uint16 c, byte *dst, int pitch) const; +	virtual void drawChar(uint16 c, byte *dst, int pitch, int) const;  protected:  	void unload(); @@ -276,6 +283,11 @@ public:  	void loadVGAPalette(Common::ReadStream &stream, int startIndex, int colors);  	/** +	* Load a HiColor palette from the given stream. +	*/ +	void loadHiColorPalette(Common::ReadStream &stream, int startIndex, int colors); + +	/**  	 * Load a EGA palette from the given stream.  	 */  	void loadEGAPalette(Common::ReadStream &stream, int startIndex, int colors); @@ -423,6 +435,7 @@ public:  	// init  	virtual bool init();  	virtual void setResolution(); +	virtual void enableHiColorMode(bool enabled);  	void updateScreen(); @@ -499,6 +512,7 @@ public:  	virtual void setTextColorMap(const uint8 *cmap) = 0;  	void setTextColor(const uint8 *cmap, int a, int b); +	void setTextColor16bit(const uint16 *cmap16);  	const ScreenDim *getScreenDim(int dim) const;  	void modifyScreenDim(int dim, int x, int y, int w, int h); @@ -570,7 +584,10 @@ public:  	// RPG specific, this does not belong here  	void crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage); +	void set16bitShadingLevel(int lvl) { _16bitShadingLevel = lvl; } +  protected: +	void resetPagePtrsAndBuffers(int pageSize);  	uint8 *getPagePtr(int pageNum);  	virtual void updateDirtyRects();  	void updateDirtyRectsAmiga(); @@ -602,8 +619,11 @@ protected:  	bool _useSJIS;  	bool _use16ColorMode;  	bool _useHiResEGADithering; +	bool _useHiColorScreen;  	bool _isAmiga;  	Common::RenderMode _renderMode; +	int _bytesPerPixel; +	int _screenPageSize;  	uint8 _sjisInvisibleColor;  	bool _sjisMixedFontMode; @@ -612,8 +632,15 @@ protected:  	Common::Array<Palette *> _palettes;  	Palette *_internFadePalette; +	uint16 shade16bitColor(uint16 col); + +	uint16 *_16bitPalette; +	uint16 *_16bitConversionPalette; +	uint8 _16bitShadingLevel; +  	Font *_fonts[FID_NUM];  	uint8 _textColorsMap[16]; +	uint16 _textColorsMap16bit[2];  	uint8 *_decodeShapeBuffer;  	int _decodeShapeBufferSize; diff --git a/engines/kyra/screen_eob.cpp b/engines/kyra/screen_eob.cpp index 6553ffa76c..88c53fdb7b 100644 --- a/engines/kyra/screen_eob.cpp +++ b/engines/kyra/screen_eob.cpp @@ -46,6 +46,7 @@ Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system,  	_gfxX = _gfxY = 0;  	_gfxCol = 0;  	_dsTempPage = 0; +	_convertHiColorBuffer = 0;  	_dsDiv = 0;  	_dsRem = 0;  	_dsScaleTrans = 0; @@ -60,6 +61,7 @@ Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system,  Screen_EoB::~Screen_EoB() {  	delete[] _dsTempPage; +	delete[] _convertHiColorBuffer;  	delete[] _cgaScaleTable;  	delete[] _egaDitheringTable;  	delete[] _egaDitheringTempPage; @@ -74,6 +76,9 @@ bool Screen_EoB::init() {  		_dsTempPage = new uint8[12000]; +		if (_vm->gameFlags().platform == Common::kPlatformFMTowns) { +			_convertHiColorBuffer = new uint8[SCREEN_H * SCREEN_W]; +		}  		if (_vm->gameFlags().useHiRes && _renderMode == Common::kRenderEGA) {  			_useHiResEGADithering = true;  			_egaDitheringTable = new uint8[256]; @@ -120,11 +125,12 @@ void Screen_EoB::setMouseCursor(int x, int y, const byte *shape, const uint8 *ov  	int colorKey = (_renderMode == Common::kRenderCGA) ? 0 : _cursorColorKey;  	int scaleFactor = _useHiResEGADithering ? 2 : 1; +	int bpp = _useHiColorScreen ? 2 : 1; -	uint8 *cursor = new uint8[mouseW * scaleFactor * mouseH * scaleFactor]; +	uint8 *cursor = new uint8[mouseW * scaleFactor * bpp * mouseH * scaleFactor];  	// We use memset and copyBlockToPage instead of fillRect to make sure that the  	// color key 0xFF doesn't get converted into EGA color -	memset(cursor, colorKey, mouseW * scaleFactor * mouseH * scaleFactor); +	memset(cursor, colorKey, mouseW * scaleFactor * bpp * mouseH * scaleFactor);  	copyBlockToPage(6, 0, 0, mouseW * scaleFactor, mouseH * scaleFactor, cursor);  	drawShape(6, shape, 0, 0, 0, 2, ovl);  	CursorMan.showMouse(false); @@ -156,8 +162,13 @@ void Screen_EoB::setMouseCursor(int x, int y, const byte *shape, const uint8 *ov  			}  		}  	} +	 +	// Convert color key to 16 bit after drawing the mouse cursor. +	// The cursor has been converted to 16 bit in scale2x(). +	colorKey = _16bitConversionPalette ? _16bitConversionPalette[colorKey] : colorKey; +	Graphics::PixelFormat pixelFormat = _system->getScreenFormat(); -	CursorMan.replaceCursor(cursor, mouseW * scaleFactor, mouseH * scaleFactor, x, y, colorKey); +	CursorMan.replaceCursor(cursor, mouseW * scaleFactor, mouseH * scaleFactor, x, y, colorKey, false, &pixelFormat);  	if (isMouseVisible())  		CursorMan.showMouse(true);  	delete[] cursor; @@ -217,9 +228,13 @@ void Screen_EoB::loadEoBBitmap(const char *file, const uint8 *cgaMapping, int te  		}  	} -	if (convertToPage == -1) { +	if (convertToPage == -1)  		return; -	} else if (convertToPage == 2 && _renderMode == Common::kRenderCGA) { + +	if (_16bitPalette) +		convertToHiColor(destPage); + +	if (convertToPage == 2 && _renderMode == Common::kRenderCGA) {  		convertPage(destPage, 4, cgaMapping);  		copyRegion(0, 0, 0, 0, 320, 200, 4, 2, Screen::CR_NO_P_CHECK);  	} else if (convertToPage == 0) { @@ -262,7 +277,10 @@ void Screen_EoB::convertPage(int srcPage, int dstPage, const uint8 *cgaMapping)  }  void Screen_EoB::setScreenPalette(const Palette &pal) { -	if (_useHiResEGADithering && pal.getNumColors() != 16) { +	if (_bytesPerPixel == 2) { +		for (int i = 0; i < 4; i++) +			createFadeTable16bit((const uint16*)(pal.getData()), &_16bitPalette[i * 256], 0, i * 53); +	}else if (_useHiResEGADithering && pal.getNumColors() != 16) {  		generateEGADitheringTable(pal);  	} else if (_renderMode == Common::kRenderEGA && pal.getNumColors() == 16) {  		_screenPalette->copy(pal); @@ -297,7 +315,26 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool enco  	if (_renderMode == Common::kRenderEGA && !_useHiResEGADithering)  		encode8bit = false; -	if (_renderMode == Common::kRenderCGA) { +	if (_bytesPerPixel == 2) { +		shapesize = h * (w << 3) + 4; +		shp = new uint8[shapesize]; +		memset(shp, 0, shapesize); +		uint8 *dst = shp; + +		*dst++ = 0; +		*dst++ = (h & 0xFF); +		*dst++ = (w & 0xFF); +		*dst++ = (h & 0xFF); + +		w <<= 3; + +		for (int i = 0; i < h; ++i) { +			memcpy(dst, src, w); +			srcLineStart += SCREEN_W; +			src = srcLineStart; +			dst += w; +		} +	} else if (_renderMode == Common::kRenderCGA) {  		if (cgaMapping)  			generateCGADitheringTables(cgaMapping);  		shapesize = h * (w << 2) + 4; @@ -485,7 +522,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,  	}  	va_end(args); -	dst += (_dsX1 << 3); +	dst += (_dsX1 << (2 + _bytesPerPixel));  	int16 dX = x - (_dsX1 << 3);  	int16 dY = y;  	int16 dW = _dsX2 - _dsX1; @@ -506,7 +543,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,  	int pixelStep = (flags & 1) ? -1 : 1; -	if (pixelsPerByte == 1)  { +	if (pixelsPerByte < 2)  {  		uint16 marginLeft = 0;  		uint16 marginRight = 0; @@ -557,7 +594,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,  			marginRight = w2 - marginLeft - width;  		} -		dst += (dY * SCREEN_W + dX); +		dst += (dY * SCREEN_W * _bytesPerPixel + dX * _bytesPerPixel);  		uint8 *dstL = dst;  		if (pageNum == 0 || pageNum == 1) @@ -567,36 +604,45 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,  			int16 xpos = (int16) marginLeft;  			if (flags & 1) { -				for (int i = 0; i < w2; i++) { -					if (*src++ == 0) { -						i += (*src - 1); -						src += (*src - 1); +				if (pixelsPerByte == 1) { +					for (int i = 0; i < w2; i++) { +						if (*src++ == 0) { +							i += (*src - 1); +							src += (*src - 1); +						}  					} +				} else { +					src += w2;  				}  				src--;  			}  			const uint8 *src2 = src;  			if (xpos) { -				do { -					uint8 val = (flags & 1) ? *(src - 1) : *src; -					while (val && xpos) { -						src += pixelStep; -						xpos--; -						val = (flags & 1) ? *(src - 1) : *src; -					} +				if (pixelsPerByte == 1) { +					do { +						uint8 val = (flags & 1) ? *(src - 1) : *src; +						while (val && xpos) { +							src += pixelStep; +							xpos--; +							val = (flags & 1) ? *(src - 1) : *src; +						} -					val = (flags & 1) ? *(src - 1) : *src; -					if (!val) { -						src += pixelStep; -						uint8 bt = (flags & 1) ? src[1] : src[0]; -						src += pixelStep; -						xpos = xpos - bt; -					} -				} while (xpos > 0); +						val = (flags & 1) ? *(src - 1) : *src; +						if (!val) { +							src += pixelStep; +							uint8 bt = (flags & 1) ? src[1] : src[0]; +							src += pixelStep; +							xpos = xpos - bt; +						} +					} while (xpos > 0); +				} else { +					src += (xpos * pixelStep); +					xpos = 0; +				}  			} -			dst -= xpos; +			dst -= xpos * _bytesPerPixel;  			xpos += width;  			while (xpos > 0) { @@ -606,37 +652,45 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,  				if (m) {  					drawShapeSetPixel(dst, c); -					dst++; +					dst += _bytesPerPixel;  					xpos--; -				} else { +				} else if (pixelsPerByte) {  					uint8 len = (flags & 1) ? src[1] : src[0]; -					dst += len; +					dst += len * _bytesPerPixel;  					xpos -= len;  					src += pixelStep; +				} else { +					dst += _bytesPerPixel; +					xpos--;  				}  			}  			xpos += marginRight;  			if (xpos) {  				do { -					uint8 val = (flags & 1) ? *(src - 1) : *src; -					while (val && xpos) { -						src += pixelStep; -						xpos--; -						val = (flags & 1) ? *(src - 1) : *src; -					} +					if (pixelsPerByte == 1) { +						uint8 val = (flags & 1) ? *(src - 1) : *src; +						while (val && xpos) { +							src += pixelStep; +							xpos--; +							val = (flags & 1) ? *(src - 1) : *src; +						} -					val = (flags & 1) ? *(src - 1) : *src; -					if (!val) { -						src += pixelStep; -						uint8 bt = (flags & 1) ? src[1] : src[0]; -						src += pixelStep; -						xpos = xpos - bt; +						val = (flags & 1) ? *(src - 1) : *src; +						if (!val) { +							src += pixelStep; +							uint8 bt = (flags & 1) ? src[1] : src[0]; +							src += pixelStep; +							xpos = xpos - bt; +						} +					} else { +						src += (xpos * pixelStep); +						xpos = 0;  					}  				} while (xpos > 0);  			} -			dstL += SCREEN_W; +			dstL += SCREEN_W * _bytesPerPixel;  			dst = dstL;  			if (flags & 1)  				src = src2 + 1; @@ -704,7 +758,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,  		if (d < width)  			width = d; -		dst += (dY * SCREEN_W + dX); +		dst += (dY * SCREEN_W * _bytesPerPixel + dX * _bytesPerPixel);  		if (pageNum == 0 || pageNum == 1)  			addDirtyRect(rX, rY, rW, rH); @@ -753,11 +807,11 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,  				uint8 col = (pixelsPerByte == 2) ? pal[(in >> shift) & pixelPackingMask] : (*dst & ((trans >> shift) & (pixelPackingMask))) | pal[(in >> shift) & pixelPackingMask];  				if (col || pixelsPerByte == 4)  					drawShapeSetPixel(dst, col); -				dst++; +				dst += _bytesPerPixel;  				shift = ((shift - (pixelStep * pixelPacking)) & 7);  			}  			src += lineSrcStep; -			dst += pitch; +			dst += (pitch * _bytesPerPixel);  		}  	}  } @@ -1167,11 +1221,11 @@ void Screen_EoB::setFadeTable(const uint8 *table) {  	_dsShapeFadingTable = table;  } -void Screen_EoB::createFadeTable(uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight) { +void Screen_EoB::createFadeTable(const uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight) {  	if (!palData)  		return; -	uint8 *src = palData + 3 * rootColor; +	const uint8 *src = palData + 3 * rootColor;  	uint8 r = *src++;  	uint8 g = *src++;  	uint8 b = *src; @@ -1189,7 +1243,7 @@ void Screen_EoB::createFadeTable(uint8 *palData, uint8 *dst, uint8 rootColor, ui  		tmp = (uint16)((*src - b) * weight) << 1;  		tb = *src++ - ((tmp >> 8) & 0xFF); -		uint8 *d = palData + 3; +		const uint8 *d = palData + 3;  		uint16 v = 0xFFFF;  		uint8 col = rootColor; @@ -1210,6 +1264,65 @@ void Screen_EoB::createFadeTable(uint8 *palData, uint8 *dst, uint8 rootColor, ui  	}  } +void Screen_EoB::createFadeTable16bit(const uint16 *palData, uint16 *dst, uint16 rootColor, uint8 weight) { +	uint8 r8 = (rootColor & 0x1f); +	uint8 g8 = (rootColor & 0x3E0) >> 5; +	uint8 b8 = (rootColor & 0x7C00) >> 10; + +	int root_r = r8 << 4; +	int root_g = g8 << 4; +	int root_b = b8 << 4; + +	*dst++ = palData[0]; + +	for (uint8 i = 1; i; i++) { +		r8 = (palData[i] & 0x1f); +		g8 = (palData[i] & 0x3E0) >> 5; +		b8 = (palData[i] & 0x7C00) >> 10; + +		int red = r8 << 4; +		int green = g8 << 4; +		int blue = b8 << 4; + +		if (red > root_r) { +			red -= weight; +			if (root_r > red) +				red = root_r; +		} else { +			red += weight; +			if (root_r < red) +				red = root_r; +		} + +		if (green > root_g) { +			green -= weight; +			if (root_g > green) +				green = root_g; +		} else { +			green += weight; +			if (root_g < green) +				green = root_g; +		} + +		if (blue > root_b) { +			blue -= weight; +			if (root_b > blue) +				blue = root_b; +		} else { +			blue += weight; +			if (root_b < blue) +				blue = root_b; +		} + +		r8 = red >> 4; +		g8 = green >> 4; +		b8 = blue >> 4; + +		*dst++ = (b8 << 10) | (g8 << 5) | r8; +	} + +} +  const uint16 *Screen_EoB::getCGADitheringTable(int index) {  	return !(index & ~1) ? _cgaDitheringTables[index] : 0;  } @@ -1218,6 +1331,40 @@ const uint8 *Screen_EoB::getEGADitheringTable() {  	return _egaDitheringTable;  } +void Screen_EoB::convertToHiColor(int page) { +	if (!_16bitPalette) +		return; +	uint16 *dst = (uint16 *)getCPagePtr(page); +	memcpy(_convertHiColorBuffer, dst, SCREEN_H * SCREEN_W); +	uint8 *src = _convertHiColorBuffer; +	for (int s = SCREEN_H * SCREEN_W; s; --s) +		*dst++ = _16bitPalette[*src++]; +} + +void Screen_EoB::shadeRect(int x1, int y1, int x2, int y2, int shadingLevel) { +	if (!_16bitPalette) +		return; + +	int l = _16bitShadingLevel; +	_16bitShadingLevel = shadingLevel; + +	if (_curPage == 0 || _curPage == 1) +		addDirtyRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1); + +	uint16 *dst = (uint16*)(getPagePtr(_curPage) + y1 * SCREEN_W * _bytesPerPixel + x1 * _bytesPerPixel); + +	for (; y1 < y2; ++y1) { +		uint16 *ptr = dst; +		for (int i = 0; i < x2 - x1; i++) { +			*ptr = shade16bitColor(*ptr); +			ptr++; +		} +		dst += SCREEN_W; +	} + +	_16bitShadingLevel = l; +} +  void Screen_EoB::updateDirtyRects() {  	if (!_useHiResEGADithering) {  		Screen::updateDirtyRects(); @@ -1260,7 +1407,10 @@ void Screen_EoB::ditherRect(const uint8 *src, uint8 *dst, int dstPitch, int srcW  }  void Screen_EoB::drawShapeSetPixel(uint8 *dst, uint8 col) { -	if ((_renderMode != Common::kRenderCGA && _renderMode != Common::kRenderEGA) || _useHiResEGADithering) { +	if (_bytesPerPixel == 2) { +		*(uint16*)dst = _16bitPalette[(_dsShapeFadingLevel << 8) + col]; +		return; +	} else if ((_renderMode != Common::kRenderCGA && _renderMode != Common::kRenderEGA) || _useHiResEGADithering) {  		if (_dsBackgroundFading) {  			if (_dsShapeFadingLevel) {  				col = *dst; @@ -1485,7 +1635,7 @@ int OldDOSFont::getCharWidth(uint16 c) const {  	return _width;  } -void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const { +void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch, int bpp) const {  	static const uint8 renderMaskTable6[] = { 0xFC, 0x00, 0x7E, 0x00, 0x3F, 0x00, 0x1F, 0x80, 0x0F, 0xC0, 0x07, 0xE0, 0x03, 0xF0, 0x01, 0xF8 };  	static const uint8 renderMaskTable8[] = { 0xFF, 0x00, 0x7F, 0x80, 0x3F, 0xC0, 0x1F, 0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0x03, 0xFC, 0x01, 0xFE }; @@ -1536,24 +1686,28 @@ void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const {  		}  	} +	pitch *= bpp;  	const uint8 *src = &_data[_bitmapOffsets[c]];  	uint8 *dst2 = dst + pitch;  	int w = (_width - 1) >> 3; -	pitch -= _width; +	pitch -= _width * bpp; -	uint8 color1 = _colorMap[1]; -	uint8 color2 = _colorMap[0]; +	uint16 color1 = _colorMap8bit[1]; +	uint16 color2 = _colorMap8bit[0]; -	static const uint16 cgaColorMask[] = { 0, 0x5555, 0xAAAA, 0xFFFF }; -	uint16 cgaMask1 = cgaColorMask[color1 & 3]; -	uint16 cgaMask2 = cgaColorMask[color2 & 3]; - -	if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA) { +	if (bpp == 2) { +		color1 = _colorMap16bit[1]; +		color2 = _colorMap16bit[0]; +	} else if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA) {  		color1 &= 0x0F;  		color2 &= 0x0F;  	} +	static const uint16 cgaColorMask[] = { 0, 0x5555, 0xAAAA, 0xFFFF }; +	uint16 cgaMask1 = cgaColorMask[color1 & 3]; +	uint16 cgaMask2 = cgaColorMask[color2 & 3]; +  	int cH = _height;  	while (cH--) {  		int cW = w; @@ -1607,12 +1761,19 @@ void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const {  					}  					if (s & i) { -						if (color1) +						if (bpp == 2) +							*(uint16*)dst = color1; +						else if (color1)  							*dst = color1; -					} else if (color2) { -						*dst = color2; +					} else { +						if (bpp == 2) { +							if (color2 != 0xFFFF) +								*(uint16*)dst = color2; +						} else if (color2) { +							*dst = color2; +						}  					} -					dst++; +					dst += bpp;  				}  				if (cW) diff --git a/engines/kyra/screen_eob.h b/engines/kyra/screen_eob.h index 42c7e59e28..7c2a31e9d3 100644 --- a/engines/kyra/screen_eob.h +++ b/engines/kyra/screen_eob.h @@ -76,11 +76,14 @@ public:  	int getRectSize(int w, int h);  	void setFadeTable(const uint8 *table); -	void createFadeTable(uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight); +	void createFadeTable(const uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight); +	void createFadeTable16bit(const uint16 *palData, uint16 *dst, uint16 rootColor, uint8 weight);  	const uint16 *getCGADitheringTable(int index);  	const uint8 *getEGADitheringTable(); +	void convertToHiColor(int page); +	void shadeRect(int x1, int y1, int x2, int y2, int shadingLevel);  private:  	void updateDirtyRects();  	void ditherRect(const uint8 *src, uint8 *dst, int dstPitch, int srcW, int srcH, int colorKey = -1); @@ -106,6 +109,7 @@ private:  	uint8 _shapeOverlay[16];  	uint8 *_dsTempPage; +	uint8 *_convertHiColorBuffer;  	uint16 *_cgaDitheringTables[2];  	const uint8 *_cgaMappingDefault; | 
