diff options
| -rw-r--r-- | engines/kyra/chargen.cpp | 10 | ||||
| -rw-r--r-- | engines/kyra/darkmoon.cpp | 13 | ||||
| -rw-r--r-- | engines/kyra/eob.cpp | 2 | ||||
| -rw-r--r-- | engines/kyra/eobcommon.cpp | 6 | ||||
| -rw-r--r-- | engines/kyra/gui_eob.cpp | 28 | ||||
| -rw-r--r-- | engines/kyra/gui_eob.h | 5 | ||||
| -rw-r--r-- | engines/kyra/kyra_hof.cpp | 2 | ||||
| -rw-r--r-- | engines/kyra/kyra_lok.cpp | 2 | ||||
| -rw-r--r-- | engines/kyra/kyra_mr.cpp | 2 | ||||
| -rw-r--r-- | engines/kyra/kyra_rpg.cpp | 17 | ||||
| -rw-r--r-- | engines/kyra/kyra_rpg.h | 5 | ||||
| -rw-r--r-- | engines/kyra/kyra_v1.cpp | 9 | ||||
| -rw-r--r-- | engines/kyra/kyra_v1.h | 2 | ||||
| -rw-r--r-- | engines/kyra/lol.cpp | 2 | ||||
| -rw-r--r-- | engines/kyra/magic_eob.cpp | 2 | ||||
| -rw-r--r-- | engines/kyra/saveload_eob.cpp | 2 | ||||
| -rw-r--r-- | engines/kyra/scene_eob.cpp | 65 | ||||
| -rw-r--r-- | engines/kyra/scene_rpg.cpp | 76 | ||||
| -rw-r--r-- | engines/kyra/screen.cpp | 190 | ||||
| -rw-r--r-- | engines/kyra/screen.h | 24 | ||||
| -rw-r--r-- | engines/kyra/screen_eob.cpp | 384 | ||||
| -rw-r--r-- | engines/kyra/screen_eob.h | 14 | 
22 files changed, 591 insertions, 271 deletions
| diff --git a/engines/kyra/chargen.cpp b/engines/kyra/chargen.cpp index 23274349e7..73f5fccb92 100644 --- a/engines/kyra/chargen.cpp +++ b/engines/kyra/chargen.cpp @@ -1496,7 +1496,7 @@ TransferPartyWiz::~TransferPartyWiz() {  }  bool TransferPartyWiz::start() { -	_screen->copyPage(0, 12); +	_screen->copyPage(0, (_screen->getPageScaleFactor(0) == 2) ? 1 : 12);  	if (!selectAndLoadTransferFile())  		return false; @@ -1536,7 +1536,7 @@ bool TransferPartyWiz::start() {  bool TransferPartyWiz::selectAndLoadTransferFile() {  	do { -		_screen->copyPage(12, 0); +		_screen->copyPage((_screen->getPageScaleFactor(0) == 2) ? 1 : 12, 0);  		 if (transferFileDialogue(_vm->_savegameFilename))  			 break;  	} while (_vm->_gui->confirmDialogue2(15, 68, 1)); @@ -1566,7 +1566,7 @@ bool TransferPartyWiz::selectAndLoadTransferFile() {  		return false;  	Common::String target = _vm->_gui->transferTargetMenu(eobTargets); -	_screen->copyPage(12, 0); +	_screen->copyPage((_screen->getPageScaleFactor(0) == 2) ? 1 : 12, 0);  	if (target.empty())  		return true; @@ -1579,10 +1579,10 @@ bool TransferPartyWiz::selectAndLoadTransferFile() {  			return true;  	} -	_screen->copyPage(12, 0); +	_screen->copyPage((_screen->getPageScaleFactor(0) == 2) ? 1 : 12, 0);  	bool result = _vm->_gui->transferFileMenu(target, dest); -	_screen->copyPage(12, 0); +	_screen->copyPage((_screen->getPageScaleFactor(0) == 2) ? 1 : 12, 0);  	return result;  } diff --git a/engines/kyra/darkmoon.cpp b/engines/kyra/darkmoon.cpp index 918221e0dd..16bd3dad58 100644 --- a/engines/kyra/darkmoon.cpp +++ b/engines/kyra/darkmoon.cpp @@ -61,10 +61,11 @@ Common::Error DarkMoonEngine::init() {  		Palette pal(16);  		_screen->loadPalette(_egaDefaultPalette, pal, 16);  		_screen->setScreenPalette(pal); -	} else { -		_screen->loadPalette("palette.col", _screen->getPalette(0));  	} +	_screen->loadPalette("PALETTE.COL", _screen->getPalette(0)); +	_screen->setScreenPalette(_screen->getPalette(0)); +  	return Common::kNoError;  } @@ -157,7 +158,9 @@ void DarkMoonEngine::generateMonsterPalettes(const char *file, int16 monsterInde  		int colx = 302 + 3 * i;  		for (int ii = 0; ii < 16; ii++) { -			uint8 col = _screen->getPagePixel(_screen->_curPage, colx, 184 + ii); +			// Don't use getPagePixel() here, since in EGA mode it will try to +			// undither the pixel (although the shape bitmap is undithered already) +			uint8 col = _screen->getCPagePtr(_screen->_curPage | 1)[(184 + ii) * Screen::SCREEN_W + colx];  			int iii = 0;  			for (; iii < 16; iii++) { @@ -175,7 +178,9 @@ void DarkMoonEngine::generateMonsterPalettes(const char *file, int16 monsterInde  			memcpy(tmpPal, _monsterShapes[dci] + 4, 16);  			for (int iii = 0; iii < 16; iii++) { -				uint8 col = _screen->getPagePixel(_screen->_curPage, colx + ii, 184 + iii); +				// Don't use getPagePixel() here, since in EGA mode it will try to +				// undither the pixel (although the shape bitmap is undithered already) +				uint8 col = _screen->getCPagePtr(_screen->_curPage | 1)[(184 + iii) * Screen::SCREEN_W + colx + ii];  				if (newPal[iii])  					tmpPal[newPal[iii]] = col;  			} diff --git a/engines/kyra/eob.cpp b/engines/kyra/eob.cpp index 9e58affded..a7bde9f1ee 100644 --- a/engines/kyra/eob.cpp +++ b/engines/kyra/eob.cpp @@ -69,7 +69,7 @@ Common::Error EoBEngine::init() {  		_screen->loadPalette(_egaDefaultPalette, pal, 16);  		_screen->setScreenPalette(pal);  	} else { -		_screen->loadPalette("palette.col", _screen->getPalette(0)); +		_screen->loadPalette("PALETTE.COL", _screen->getPalette(0));  	}  	return Common::kNoError; diff --git a/engines/kyra/eobcommon.cpp b/engines/kyra/eobcommon.cpp index 9bec256ec7..ff53ba8b0a 100644 --- a/engines/kyra/eobcommon.cpp +++ b/engines/kyra/eobcommon.cpp @@ -371,7 +371,7 @@ Common::Error EoBCoreEngine::init() {  	_screen = new Screen_EoB(this, _system);  	assert(_screen); -	_screen->setResolution(); +	_screen->setResolution(_flags.useHiResOverlay || (_flags.gameID == GI_EOB2 && _configRenderMode == Common::kRenderEGA));  	//MidiDriverType midiDriver = MidiDriver::detectDevice(MDT_PCSPK | MDT_ADLIB);  	_sound = new SoundAdLibPC(this, _mixer); @@ -1738,7 +1738,7 @@ void EoBCoreEngine::seq_portal() {  bool EoBCoreEngine::checkPassword() {  	char answ[20];  	Screen::FontId of = _screen->setFont(Screen::FID_8_FNT); -	_screen->copyPage(0, 10); +	_screen->copyPage(0, (_screen->getPageScaleFactor(0) == 2) ? 4 : 10);  	_screen->setScreenDim(13);  	gui_drawBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, guiSettings()->colors.frame1, guiSettings()->colors.frame2, -1); @@ -1765,7 +1765,7 @@ bool EoBCoreEngine::checkPassword() {  	_screen->modifyScreenDim(13, _screen->_curDim->sx - 1, _screen->_curDim->sy - 2, _screen->_curDim->w + 2, _screen->_curDim->h + 16);  	_screen->setFont(of); -	_screen->copyPage(10, 0); +	_screen->copyPage((_screen->getPageScaleFactor(0) == 2) ? 4 : 10, 0);  	return true;  } diff --git a/engines/kyra/gui_eob.cpp b/engines/kyra/gui_eob.cpp index 39cc4692c4..eadfd10d1e 100644 --- a/engines/kyra/gui_eob.cpp +++ b/engines/kyra/gui_eob.cpp @@ -777,11 +777,11 @@ int EoBCoreEngine::clickedCamp(Button *button) {  	}  	_screen->copyPage(0, 7); -	_screen->copyRegion(0, 120, 0, 0, 176, 24, 0, 12, Screen::CR_NO_P_CHECK); +	_screen->copyRegion(0, 120, 0, 0, 176, 24, 0, (_screen->getPageScaleFactor(0) == 2) ? 1 : 12, Screen::CR_NO_P_CHECK);  	_gui->runCampMenu(); -	_screen->copyRegion(0, 0, 0, 120, 176, 24, 12, 2, Screen::CR_NO_P_CHECK); +	_screen->copyRegion(0, 0, 0, 120, 176, 24, (_screen->getPageScaleFactor(0) == 2) ? 1 : 12, 2, Screen::CR_NO_P_CHECK);  	_screen->setScreenDim(cd);  	drawScene(0); @@ -1170,7 +1170,7 @@ int EoBCoreEngine::clickedSceneSpecial(Button *button) {  int EoBCoreEngine::clickedSpellbookAbort(Button *button) {  	_updateFlags = 0; -	_screen->copyRegion(0, 0, 64, 121, 112, 56, 10, 0, Screen::CR_NO_P_CHECK); +	_screen->copyRegion(0, 0, 64, 121, 112, 56, (_screen->getPageScaleFactor(0) == 2) ? 4 : 10, 0, Screen::CR_NO_P_CHECK);  	_screen->updateScreen();  	gui_drawCompass(true);  	gui_toggleButtons(); @@ -1392,9 +1392,11 @@ GUI_EoB::GUI_EoB(EoBCoreEngine *vm) : GUI(vm), _vm(vm), _screen(vm->_screen) {  	_charSelectRedraw = false; +	_highLightColorTable = (_vm->game() == GI_EOB1 && (_vm->_configRenderMode == Common::kRenderCGA || _vm->_configRenderMode == Common::kRenderEGA)) ? _highlightColorTableEGA : _highlightColorTableVGA;  	_updateBoxIndex = -1;  	_highLightBoxTimer = 0;  	_updateBoxColorIndex = 0; +  	_needRest = false;  } @@ -2170,7 +2172,7 @@ void GUI_EoB::runCampMenu() {  				if (cnt > 4) {  					_vm->dropCharacter(selectCharacterDialogue(53));  					_vm->gui_drawPlayField(false); -					_screen->copyRegion(0, 120, 0, 0, 176, 24, 0, 12, Screen::CR_NO_P_CHECK); +					_screen->copyRegion(0, 120, 0, 0, 176, 24, 0, (_screen->getPageScaleFactor(0) == 2) ? 1 : 12, Screen::CR_NO_P_CHECK);  					_screen->setFont(Screen::FID_6_FNT);  					_vm->gui_drawAllCharPortraitsWithStats();  					_screen->setFont(Screen::FID_8_FNT); @@ -2411,8 +2413,6 @@ void GUI_EoB::messageDialogue2(int dim, int id, int buttonTextCol) {  }  void GUI_EoB::updateBoxFrameHighLight(int box) { -	static const uint8 colorTable[] = { 0x0F, 0xB0, 0xB2, 0xB4, 0xB6, 0xB8, 0xBA, 0xBC, 0x0C, 0xBC, 0xBA, 0xB8, 0xB6, 0xB4, 0xB2, 0xB0, 0x00 }; -  	if (_updateBoxIndex == box) {  		if (_updateBoxIndex == -1)  			return; @@ -2420,18 +2420,18 @@ void GUI_EoB::updateBoxFrameHighLight(int box) {  		if (_vm->_system->getMillis() <= _highLightBoxTimer)  			return; -		if (!colorTable[_updateBoxColorIndex]) +		if (!_highLightColorTable[_updateBoxColorIndex])  			_updateBoxColorIndex = 0; -		const EoBRect16 *r = &_updateBoxFrameHighLights[_updateBoxIndex]; -		_screen->drawBox(r->x1, r->y1, r->x2, r->y2, colorTable[_updateBoxColorIndex++]); +		const EoBRect16 *r = &_highlightFrames[_updateBoxIndex]; +		_screen->drawBox(r->x1, r->y1, r->x2, r->y2, _highLightColorTable[_updateBoxColorIndex++]);  		_screen->updateScreen();  		_highLightBoxTimer = _vm->_system->getMillis() + _vm->_tickLength;  	} else {  		if (_updateBoxIndex != -1) { -			const EoBRect16 *r = &_updateBoxFrameHighLights[_updateBoxIndex]; +			const EoBRect16 *r = &_highlightFrames[_updateBoxIndex];  			_screen->drawBox(r->x1, r->y1, r->x2, r->y2, 12);  			_screen->updateScreen();  		} @@ -2607,7 +2607,7 @@ Common::String GUI_EoB::transferTargetMenu(Common::Array<Common::String> &target  			break;  	} while (_saveSlotIdTemp[slot] == -1); -	_screen->copyRegion(72, 14, 72, 14, 176, 144, 12, 0, Screen::CR_NO_P_CHECK); +	_screen->copyRegion(72, 14, 72, 14, 176, 144, (_screen->getPageScaleFactor(0) == 2) ? 7 : 12, 0, Screen::CR_NO_P_CHECK);  	_screen->modifyScreenDim(11, xo, yo, dm->w, dm->h);  	return (slot < 6) ? _savegameList[_savegameOffset + slot] : Common::String(); @@ -4054,7 +4054,7 @@ void GUI_EoB::restParty_updateRestTime(int hours, bool init) {  	_screen->setFont(of);  } -const EoBRect16 GUI_EoB::_updateBoxFrameHighLights[] = { +const EoBRect16 GUI_EoB::_highlightFrames[] = {  	{ 0x00B7, 0x0001, 0x00F7, 0x0034 },  	{ 0x00FF, 0x0001, 0x013F, 0x0034 },  	{ 0x00B7, 0x0035, 0x00F7, 0x0068 }, @@ -4077,6 +4077,10 @@ const EoBRect16 GUI_EoB::_updateBoxFrameHighLights[] = {  	{ 0x00A3, 0x0068, 0x00C3, 0x0089 }  }; +const uint8 GUI_EoB::_highlightColorTableVGA[] = { 0x0F, 0xB0, 0xB2, 0xB4, 0xB6, 0xB8, 0xBA, 0xBC, 0x0C, 0xBC, 0xBA, 0xB8, 0xB6, 0xB4, 0xB2, 0xB0, 0x00 }; + +const uint8 GUI_EoB::_highlightColorTableEGA[] = { 0x0C, 0x0D, 0x0E, 0x0F, 0x0E, 0x0D, 0x00 }; +  } // End of namespace Kyra  #endif // ENABLE_EOB diff --git a/engines/kyra/gui_eob.h b/engines/kyra/gui_eob.h index 759ed641ce..f6be18ffbb 100644 --- a/engines/kyra/gui_eob.h +++ b/engines/kyra/gui_eob.h @@ -148,9 +148,12 @@ private:  	int _updateBoxIndex;  	int _updateBoxColorIndex; +	const uint8 *_highLightColorTable;  	uint32 _highLightBoxTimer; -	static const EoBRect16 _updateBoxFrameHighLights[]; +	static const EoBRect16 _highlightFrames[]; +	static const uint8 _highlightColorTableVGA[]; +	static const uint8 _highlightColorTableEGA[];  };  }	// End of namespace Kyra diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index 0ba173d9d0..b07e3a4965 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -221,7 +221,7 @@ void KyraEngine_HoF::pauseEngineIntern(bool pause) {  Common::Error KyraEngine_HoF::init() {  	_screen = new Screen_HoF(this, _system);  	assert(_screen); -	_screen->setResolution(); +	_screen->setResolution(_flags.useHiResOverlay);  	_debugger = new Debugger_HoF(this);  	assert(_debugger); diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index d7e79575ec..e8a2c02e6e 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -172,7 +172,7 @@ Common::Error KyraEngine_LoK::init() {  	else  		_screen = new Screen_LoK(this, _system);  	assert(_screen); -	_screen->setResolution(); +	_screen->setResolution(_flags.useHiResOverlay);  	_debugger = new Debugger_LoK(this);  	assert(_debugger); diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index 39ed0d038a..38f473a619 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -203,7 +203,7 @@ KyraEngine_MR::~KyraEngine_MR() {  Common::Error KyraEngine_MR::init() {  	_screen = new Screen_MR(this, _system);  	assert(_screen); -	_screen->setResolution(); +	_screen->setResolution(_flags.useHiResOverlay);  	_debugger = new Debugger_v2(this);  	assert(_debugger); diff --git a/engines/kyra/kyra_rpg.cpp b/engines/kyra/kyra_rpg.cpp index 1e3890b124..121731e394 100644 --- a/engines/kyra/kyra_rpg.cpp +++ b/engines/kyra/kyra_rpg.cpp @@ -41,13 +41,17 @@ KyraRpgEngine::KyraRpgEngine(OSystem *system, const GameFlags &flags) : KyraEngi  	_currentLevel = 0; -	_vmpPtr = 0;  	_vcnBlocks = 0;  	_vcfBlocks = 0;  	_vcnTransitionMask = 0;  	_vcnShift = 0;  	_vcnColTable = 0; +	_vcnBlockWidth = 4; +	_vcnBlockHeight = 8; +	_vcnFlip0 = 0; +	_vcnFlip1 = 1;  	_vmpPtr = 0; +	_vmpSize = 0;  	_blockBrightness = _wllVcnOffset = 0;  	_blockDrawingBuffer = 0;  	_sceneWindowBuffer = 0; @@ -167,10 +171,17 @@ Common::Error KyraRpgEngine::init() {  	_wllWallFlags = new uint8[256];  	memset(_wllWallFlags, 0, 256); +	if (_flags.gameID == GI_EOB2 && _configRenderMode == Common::kRenderEGA) { +		_vcnBlockWidth <<= 1; +		_vcnBlockHeight <<= 1; +		SWAP(_vcnFlip0, _vcnFlip1); +	} +  	_blockDrawingBuffer = new uint16[1320];  	memset(_blockDrawingBuffer, 0, 1320 * sizeof(uint16)); -	_sceneWindowBuffer = new uint8[21120]; -	memset(_sceneWindowBuffer, 0, 21120); +	uint32 swbSize = 22 * _vcnBlockWidth * 2 * 15 * _vcnBlockHeight; +	_sceneWindowBuffer = new uint8[swbSize]; +	memset(_sceneWindowBuffer, 0, swbSize);  	_lvlShapeTop = new int16[18];  	memset(_lvlShapeTop, 0, 18 * sizeof(int16)); diff --git a/engines/kyra/kyra_rpg.h b/engines/kyra/kyra_rpg.h index f4678e302a..50a4c9bdc1 100644 --- a/engines/kyra/kyra_rpg.h +++ b/engines/kyra/kyra_rpg.h @@ -222,6 +222,7 @@ protected:  	uint16 _decorationCount;  	int16 _mappedDecorationsCount;  	uint16 *_vmpPtr; +	uint16 _vmpSize;  	uint8 *_vcnBlocks;  	uint8 *_vcfBlocks;  	uint8 *_vcnTransitionMask; @@ -231,6 +232,10 @@ protected:  	uint8 *_sceneWindowBuffer;  	uint8 _blockBrightness;  	uint8 _wllVcnOffset; +	uint8 _vcnBlockWidth; +	uint8 _vcnBlockHeight; +	uint8 _vcnFlip0; +	uint8 _vcnFlip1;  	uint8 **_doorShapes; diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 0f7da7673b..7c67af2f13 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -230,7 +230,7 @@ KyraEngine_v1::~KyraEngine_v1() {  	delete _debugger;  } -Common::Point KyraEngine_v1::getMousePos() const { +Common::Point KyraEngine_v1::getMousePos() {  	Common::Point mouse = _eventMan->getMousePos();  	if (_flags.useHiResOverlay) { @@ -238,6 +238,9 @@ Common::Point KyraEngine_v1::getMousePos() const {  		mouse.y >>= 1;  	} +	mouse.x /= screen()->getPageScaleFactor(0); +	mouse.y /= screen()->getPageScaleFactor(0); +  	return mouse;  } @@ -313,6 +316,8 @@ int KyraEngine_v1::checkInput(Button *buttonList, bool mainLoop, int eventFlag)  				_mouseX >>= 1;  				_mouseY >>= 1;  			} +			_mouseX /= screen()->getPageScaleFactor(0); +			_mouseY /= screen()->getPageScaleFactor(0);  			keys = (event.type == Common::EVENT_LBUTTONDOWN ? 199 : (200 | 0x800));  			breakLoop = true;  			} break; @@ -325,6 +330,8 @@ int KyraEngine_v1::checkInput(Button *buttonList, bool mainLoop, int eventFlag)  				_mouseX >>= 1;  				_mouseY >>= 1;  			} +			_mouseX /= screen()->getPageScaleFactor(0); +			_mouseY /= screen()->getPageScaleFactor(0);  			keys = (event.type == Common::EVENT_RBUTTONDOWN ? 201 : (202 | 0x800));  			breakLoop = true;  			} break; diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index 2c2901a753..95d58d4ab2 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -210,7 +210,7 @@ public:  	// input  	void setMousePos(int x, int y); -	Common::Point getMousePos() const; +	Common::Point getMousePos();  	// config specific  	bool speechEnabled(); diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 38e9d33259..022a878e0a 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -364,7 +364,7 @@ GUI *LoLEngine::gui() const {  Common::Error LoLEngine::init() {  	_screen = new Screen_LoL(this, _system);  	assert(_screen); -	_screen->setResolution(); +	_screen->setResolution(_flags.useHiResOverlay);  	_debugger = new Debugger_LoL(this);  	assert(_debugger); diff --git a/engines/kyra/magic_eob.cpp b/engines/kyra/magic_eob.cpp index fbddd620d1..b2949ce1d5 100644 --- a/engines/kyra/magic_eob.cpp +++ b/engines/kyra/magic_eob.cpp @@ -60,7 +60,7 @@ void EoBCoreEngine::useMagicBookOrSymbol(int charIndex, int type) {  	}  	if (!_updateFlags) -		_screen->copyRegion(64, 121, 0, 0, 112, 56, 0, 10, Screen::CR_NO_P_CHECK); +		_screen->copyRegion(64, 121, 0, 0, 112, 56, 0, (_screen->getPageScaleFactor(0) == 2) ? 4 : 10, Screen::CR_NO_P_CHECK);  	_updateFlags = 1;  	gui_setPlayFieldButtons();  	gui_drawSpellbook(); diff --git a/engines/kyra/saveload_eob.cpp b/engines/kyra/saveload_eob.cpp index 7f20c124ff..4a446aa3f3 100644 --- a/engines/kyra/saveload_eob.cpp +++ b/engines/kyra/saveload_eob.cpp @@ -298,7 +298,7 @@ Common::Error EoBCoreEngine::loadGameState(int slot) {  		useMagicBookOrSymbol(_openBookChar, _openBookType);  	} -	_screen->copyRegion(0, 120, 0, 0, 176, 24, 0, 12, Screen::CR_NO_P_CHECK); +	_screen->copyRegion(0, 120, 0, 0, 176, 24, 0, (_screen->getPageScaleFactor(0) == 2) ? 1 : 12, Screen::CR_NO_P_CHECK);  	gui_toggleButtons();  	setHandItem(_itemInHand); diff --git a/engines/kyra/scene_eob.cpp b/engines/kyra/scene_eob.cpp index 5a06fe7977..3db055db90 100644 --- a/engines/kyra/scene_eob.cpp +++ b/engines/kyra/scene_eob.cpp @@ -144,10 +144,10 @@ Common::String EoBCoreEngine::initLevelData(int sub) {  		const char *vmpPattern = (_flags.gameID == GI_EOB1 && (_configRenderMode == Common::kRenderEGA || _configRenderMode == Common::kRenderCGA)) ? "%s.EMP" : "%s.VMP";  		Common::SeekableReadStream *s = _res->createReadStream(Common::String::format(vmpPattern, (const char *)pos)); -		uint16 size = s->readUint16LE(); +		_vmpSize = s->readUint16LE();  		delete[] _vmpPtr; -		_vmpPtr = new uint16[size]; -		for (int i = 0; i < size; i++) +		_vmpPtr = new uint16[_vmpSize]; +		for (int i = 0; i < _vmpSize; i++)  			_vmpPtr[i] = s->readUint16LE();  		delete s; @@ -185,6 +185,8 @@ Common::String EoBCoreEngine::initLevelData(int sub) {  			_screen->getPalette(0).copy(backupPal, 224, 32, 224);  			_screen->createFadeTable(src, _screen->getFadeTable(4), 12, 85);    // grey (shadow)  			_screen->setFadeTableIndex(4); +			if (_flags.gameID == GI_EOB2 && _configRenderMode == Common::kRenderEGA) +				_screen->setScreenPalette(_screen->getPalette(0));  		}  	} @@ -280,25 +282,64 @@ void EoBCoreEngine::loadVcnData(const char *file, const uint8 *cgaMapping) {  	const char *filePattern = (_flags.gameID == GI_EOB1 && (_configRenderMode == Common::kRenderEGA || _configRenderMode == Common::kRenderCGA)) ? "%s.ECN" : "%s.VCN";  	_screen->loadBitmap(Common::String::format(filePattern, _lastBlockDataFile).c_str(), 3, 3, 0);  	const uint8 *pos = _screen->getCPagePtr(3); -	uint32 tlen = READ_LE_UINT16(pos) << 5; + +	uint32 vcnSize = READ_LE_UINT16(pos) * _vcnBlockWidth * _vcnBlockHeight;  	pos += 2; -	if (!(_flags.gameID == GI_EOB1 && (_configRenderMode == Common::kRenderEGA || _configRenderMode == Common::kRenderCGA))) -		memcpy(_vcnColTable, pos, 32); + +	const uint8 *colMap = pos;  	pos += 32; +  	delete[] _vcnBlocks; -	_vcnBlocks = new uint8[tlen]; +	_vcnBlocks = new uint8[vcnSize]; -	if (_configRenderMode == Common::kRenderCGA) { +	if (_flags.gameID == GI_EOB2 && _configRenderMode == Common::kRenderEGA) { +		const uint8 *egaTable = _screen->getEGADitheringTable(); +		assert(_vmpPtr); +		assert(egaTable); + +		delete[] _vcnTransitionMask; +		_vcnTransitionMask = new uint8[vcnSize]; + +		for (int i = 0; i < _vmpSize; i++) { +			uint16 vcnOffs = _vmpPtr[i] & 0x3FFF; +			const uint8 *src = &pos[vcnOffs << 5]; +			uint8 *dst1 = &_vcnBlocks[vcnOffs << 7]; +			uint8 *dst3 = &_vcnTransitionMask[vcnOffs << 7]; +			int palOffset = (i < 330) ? 0 : _wllVcnOffset; + +			for (int y = 0; y < 8; y++) { +				uint8 *dst2 = dst1 + 8; +				uint8 *dst4 = dst3 + 8; + +				for (int x = 0; x < 4; x++) { +					uint8 in = *src++; + +					dst1[0] = dst2[0] = egaTable[colMap[(in >> 4) + palOffset]]; +					dst1[1] = dst2[1] = egaTable[colMap[(in & 0x0f) + palOffset]]; +					dst3[0] = dst4[0] = (in & 0xf0) ? 0 : 0xff; +					dst3[1] = dst4[1] = (in & 0x0f) ? 0 : 0xff; + +					dst1 += 2; +					dst2 += 2; +					dst3 += 2; +					dst4 += 2; +				} + +				dst1 += 8; +				dst3 += 8; +			} +		} +	} else if (_configRenderMode == Common::kRenderCGA) {  		uint8 *tmp = _screen->encodeShape(0, 0, 1, 8, false, cgaMapping);  		delete[] tmp;  		delete[] _vcnTransitionMask; -		_vcnTransitionMask = new uint8[tlen]; +		_vcnTransitionMask = new uint8[vcnSize];  		uint8 tblSwitch = 0;  		uint8 *dst = _vcnBlocks;  		uint8 *dst2 = _vcnTransitionMask; -		while (dst < _vcnBlocks + tlen) { +		while (dst < _vcnBlocks + vcnSize) {  			const uint16 *table = _screen->getCGADitheringTable((tblSwitch++) & 1);  			for (int ii = 0; ii < 2; ii++) {  				*dst++ = ((table[pos[0]] & 0x000f) << 4) | ((table[pos[0]] & 0x0f00) >> 8); @@ -322,7 +363,9 @@ void EoBCoreEngine::loadVcnData(const char *file, const uint8 *cgaMapping) {  			}  		}  	} else { -		memcpy(_vcnBlocks, pos, tlen); +		if (_configRenderMode != Common::kRenderEGA) +			memcpy(_vcnColTable, colMap, 32); +		memcpy(_vcnBlocks, pos, vcnSize);  	}  } diff --git a/engines/kyra/scene_rpg.cpp b/engines/kyra/scene_rpg.cpp index da7c9fdb90..b015b10cd9 100644 --- a/engines/kyra/scene_rpg.cpp +++ b/engines/kyra/scene_rpg.cpp @@ -348,6 +348,9 @@ bool KyraRpgEngine::checkSceneUpdateNeed(int block) {  void KyraRpgEngine::drawVcnBlocks() {  	uint8 *d = _sceneWindowBuffer;  	uint16 *bdb = _blockDrawingBuffer; +	uint16 pitch = 22 * _vcnBlockWidth * 2; +	uint8 pxl[2]; +	pxl[0] = pxl[1] = 0;  	for (int y = 0; y < 15; y++) {  		for (int x = 0; x < 22; x++) { @@ -371,7 +374,7 @@ void KyraRpgEngine::drawVcnBlocks() {  			uint8 *src = 0;  			if (vcnOffset) { -				src = &_vcnBlocks[vcnOffset << 5]; +				src = &_vcnBlocks[vcnOffset * _vcnBlockWidth * _vcnBlockHeight];  				wllVcnOffset = _wllVcnOffset;  			} else {  				// floor/ceiling blocks @@ -381,36 +384,37 @@ void KyraRpgEngine::drawVcnBlocks() {  					vcnOffset &= 0x3fff;  				} -				src = (_vcfBlocks ? _vcfBlocks : _vcnBlocks) + (vcnOffset << 5); +				src = (_vcfBlocks ? _vcfBlocks : _vcnBlocks) + (vcnOffset * _vcnBlockWidth * _vcnBlockHeight);  			}  			uint8 shift = _vcnShift ? _vcnShift[vcnOffset] : _blockBrightness;  			if (horizontalFlip) { -				for (int blockY = 0; blockY < 8; blockY++) { -					src += 3; -					for (int blockX = 0; blockX < 4; blockX++) { +				for (int blockY = 0; blockY < _vcnBlockHeight; blockY++) { +					src += (_vcnBlockWidth - 1); +					for (int blockX = 0; blockX < _vcnBlockWidth; blockX++) {  						uint8 bl = *src--; -						*d++ = _vcnColTable[((bl & 0x0f) + wllVcnOffset) | shift]; -						*d++ = _vcnColTable[((bl >> 4) + wllVcnOffset) | shift]; +						d[_vcnFlip0] = _vcnColTable[((bl & 0x0f) + wllVcnOffset) | shift]; +						d[_vcnFlip1] = _vcnColTable[((bl >> 4) + wllVcnOffset) | shift]; +						d += 2;  					} -					src += 5; -					d += 168; +					src += (_vcnBlockWidth + 1); +					d += (pitch - 2 * _vcnBlockWidth);  				}  			} else { -				for (int blockY = 0; blockY < 8; blockY++) { -					for (int blockX = 0; blockX < 4; blockX++) { +				for (int blockY = 0; blockY < _vcnBlockHeight; blockY++) { +					for (int blockX = 0; blockX < _vcnBlockWidth; blockX++) {  						uint8 bl = *src++;  						*d++ = _vcnColTable[((bl >> 4) + wllVcnOffset) | shift];  						*d++ = _vcnColTable[((bl & 0x0f) + wllVcnOffset) | shift];  					} -					d += 168; +					d += (pitch - 2 * _vcnBlockWidth);  				}  			} -			d -= 1400; +			d -= (pitch * _vcnBlockHeight - 2 * _vcnBlockWidth);  			if (vcnExtraOffsetWll) { -				d -= 8; +				d -= (2 * _vcnBlockWidth);  				horizontalFlip = false;  				if (vcnExtraOffsetWll & 0x4000) { @@ -419,38 +423,38 @@ void KyraRpgEngine::drawVcnBlocks() {  				}  				shift = _vcnShift ? _vcnShift[vcnExtraOffsetWll] : _blockBrightness; -				src = &_vcnBlocks[vcnExtraOffsetWll << 5]; -				uint8 *maskTable = _vcnTransitionMask ? &_vcnTransitionMask[vcnExtraOffsetWll << 5] : 0; +				src = &_vcnBlocks[vcnExtraOffsetWll * _vcnBlockWidth * _vcnBlockHeight]; +				uint8 *maskTable = _vcnTransitionMask ? &_vcnTransitionMask[vcnExtraOffsetWll * _vcnBlockWidth * _vcnBlockHeight] : 0;  				if (horizontalFlip) { -					for (int blockY = 0; blockY < 8; blockY++) { -						src += 3; -						maskTable += 3; -						for (int blockX = 0; blockX < 4; blockX++) { +					for (int blockY = 0; blockY < _vcnBlockHeight; blockY++) { +						src += (_vcnBlockWidth - 1); +						maskTable += (_vcnBlockWidth - 1); +						for (int blockX = 0; blockX < _vcnBlockWidth; blockX++) {  							uint8 bl = *src--;  							uint8 mask = _vcnTransitionMask ? *maskTable-- : 0; -							uint8 h = _vcnColTable[((bl & 0x0f) + wllVcnRmdOffset) | shift]; -							uint8 l = _vcnColTable[((bl >> 4) + wllVcnRmdOffset) | shift]; +							pxl[_vcnFlip0] = _vcnColTable[((bl & 0x0f) + wllVcnRmdOffset) | shift]; +							pxl[_vcnFlip1] = _vcnColTable[((bl >> 4) + wllVcnRmdOffset) | shift];  							if (_vcnTransitionMask) -								*d = (*d & (mask & 0x0f)) | h; -							else if (h) -								*d = h; +								*d = (*d & (mask & 0x0f)) | pxl[0]; +							else if (pxl[0]) +								*d = pxl[0];  							d++;  							if (_vcnTransitionMask) -								*d = (*d & (mask >> 4)) | l; -							else if (l) -								*d = l; +								*d = (*d & (mask >> 4)) | pxl[1]; +							else if (pxl[1]) +								*d = pxl[1];  							d++;  						} -						src += 5; -						maskTable += 5; -						d += 168; +						src += (_vcnBlockWidth + 1); +						maskTable += (_vcnBlockWidth + 1); +						d += (pitch - 2 * _vcnBlockWidth);  					}  				} else { -					for (int blockY = 0; blockY < 8; blockY++) { -						for (int blockX = 0; blockX < 4; blockX++) { +					for (int blockY = 0; blockY < _vcnBlockHeight; blockY++) { +						for (int blockX = 0; blockX < _vcnBlockWidth; blockX++) {  							uint8 bl = *src++;  							uint8 mask = _vcnTransitionMask ? *maskTable++ : 0;  							uint8 h = _vcnColTable[((bl >> 4) + wllVcnRmdOffset) | shift]; @@ -468,13 +472,13 @@ void KyraRpgEngine::drawVcnBlocks() {  								*d = l;  							d++;  						} -						d += 168; +						d += (pitch - 2 * _vcnBlockWidth);  					}  				} -				d -= 1400; +				d -= (pitch * _vcnBlockHeight - 2 * _vcnBlockWidth);  			}  		} -		d += 1232; +		d += (pitch * (_vcnBlockHeight - 1));  	}  	screen()->copyBlockToPage(_sceneDrawPage1, _sceneXoffset, 0, 176, 120, _sceneWindowBuffer); diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 3087a8a027..ef6333b350 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -39,7 +39,7 @@ namespace Kyra {  Screen::Screen(KyraEngine_v1 *vm, OSystem *system, const ScreenDim *dimTable, const int dimTableSize)  	: _system(system), _vm(vm), _sjisInvisibleColor(0), _dimTable(dimTable), _dimTableCount(dimTableSize), -	_cursorColorKey((vm->game() == GI_KYRA1) ? 0xFF : 0x00) { +	_cursorColorKey((vm->game() == GI_KYRA1 || vm->game() == GI_EOB1 || vm->game() == GI_EOB2) ? 0xFF : 0) {  	_debugEnabled = false;  	_maskMinY = _maskMaxY = -1; @@ -50,8 +50,14 @@ Screen::Screen(KyraEngine_v1 *vm, OSystem *system, const ScreenDim *dimTable, co  	memset(_fonts, 0, sizeof(_fonts)); +	memset(_pagePtrs, 0, sizeof(_pagePtrs)); +	// Set scale factor to 1 (no scaling) for all pages +	memset(_pageScaleFactor, 1, sizeof(_pageScaleFactor)); +	// In VGA mode the odd and even page pointers point to the same buffers. +	for (int i = 0; i < SCREEN_PAGE_NUM; i++) +		_pageMapping[i] = i & ~1; +  	_renderMode = Common::kRenderDefault; -	_cgaDrawCharDitheringTable = 0;  	_currentFont = FID_8_FNT;  	_paletteChanged = true; @@ -92,6 +98,12 @@ bool Screen::init() {  	if (ConfMan.hasKey("render_mode"))  		_renderMode = Common::parseRenderMode(ConfMan.get("render_mode")); +	// CGA and EGA modes use additional pages to do the CGA/EGA specific graphics conversions. +	if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA) { +		for (int i = 0; i < 8; i++) +			_pageMapping[i] = i; +	} +  	memset(_fonts, 0, sizeof(_fonts));  	if (_vm->gameFlags().useHiResOverlay) { @@ -119,25 +131,28 @@ bool Screen::init() {  	_curPage = 0; -	int numPages = SCREEN_PAGE_NUM / 2; -	// CGA and EGA modes use additional pages to do the CGA/EGA specific graphics conversions. -	if (_renderMode == Common::kRenderEGA || _renderMode == Common::kRenderCGA) -		numPages += 4; - -	uint8 *pagePtr = new uint8[numPages * SCREEN_PAGE_SIZE]; -	memset(pagePtr, 0, numPages * SCREEN_PAGE_SIZE); - -	if (_renderMode == Common::kRenderEGA || _renderMode == Common::kRenderCGA) { -		// Unlike VGA mode the odd and even page numbers do not always point to the same buffers. -		// Instead, the odd pages are used for CGA/EGA specific graphics conversions. -		int pageNum = 0; -		for (; pageNum < 8; pageNum++) -			_pagePtrs[pageNum] = pagePtr + pageNum * SCREEN_PAGE_SIZE; -		for (; pageNum < SCREEN_PAGE_NUM; pageNum += 2) -			_pagePtrs[pageNum] = _pagePtrs[pageNum + 1] = pagePtr + (pageNum / 2) * SCREEN_PAGE_SIZE; -	} else { -		for (int pageNum = 0; pageNum < SCREEN_PAGE_NUM; pageNum += 2) -			_pagePtrs[pageNum] = _pagePtrs[pageNum + 1] = pagePtr + (pageNum / 2) * SCREEN_PAGE_SIZE; +	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 = 0; +	for (int i = 0; i < numPages; i++) +		bufferSize += (SCREEN_PAGE_SIZE * _pageScaleFactor[realPages[i]] * _pageScaleFactor[realPages[i]]); + +	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 * _pageScaleFactor[i] * _pageScaleFactor[i]); +		}  	}  	memset(_shapePages, 0, sizeof(_shapePages)); @@ -211,7 +226,7 @@ bool Screen::enableScreenDebug(bool enable) {  	if (_debugEnabled != enable) {  		_debugEnabled = enable; -		setResolution(); +		setResolution(_vm->gameFlags().useHiResOverlay);  		_forceFullUpdate = true;  		updateScreen();  	} @@ -219,14 +234,14 @@ bool Screen::enableScreenDebug(bool enable) {  	return temp;  } -void Screen::setResolution() { +void Screen::setResolution(bool hiRes) {  	byte palette[3*256];  	_system->getPaletteManager()->grabPalette(palette, 0, 256);  	int width = 320, height = 200;  	bool defaultTo1xScaler = false; -	if (_vm->gameFlags().useHiResOverlay) { +	if (hiRes) {  		defaultTo1xScaler = true;  		height = 400; @@ -261,7 +276,7 @@ void Screen::updateScreen() {  		needRealUpdate = true;  		if (!_useOverlays) -			_system->copyRectToScreen(getPagePtr(2), SCREEN_W, 320, 0, SCREEN_W, SCREEN_H); +			_system->copyRectToScreen(getPagePtr(2), SCREEN_W, 320, 0, SCREEN_W * _pageScaleFactor[2], SCREEN_H * _pageScaleFactor[2]);  		else  			_system->copyRectToScreen(getPagePtr(2), SCREEN_W, 640, 0, SCREEN_W, SCREEN_H);  	} @@ -272,12 +287,12 @@ void Screen::updateScreen() {  void Screen::updateDirtyRects() {  	if (_forceFullUpdate) { -		_system->copyRectToScreen(getCPagePtr(0), SCREEN_W, 0, 0, SCREEN_W, SCREEN_H); +		_system->copyRectToScreen(getCPagePtr(0), SCREEN_W * _pageScaleFactor[0], 0, 0, SCREEN_W * _pageScaleFactor[0], SCREEN_H * _pageScaleFactor[0]);  	} else {  		const byte *page0 = getCPagePtr(0);  		Common::List<Common::Rect>::iterator it;  		for (it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) { -			_system->copyRectToScreen(page0 + it->top * SCREEN_W + it->left, SCREEN_W, it->left, it->top, it->width(), it->height()); +			_system->copyRectToScreen(page0 + it->top * SCREEN_W * _pageScaleFactor[0] + it->left, SCREEN_W * _pageScaleFactor[0], it->left, it->top, it->width(), it->height());  		}  	}  	_forceFullUpdate = false; @@ -451,6 +466,11 @@ const uint8 *Screen::getCPagePtr(int pageNum) const {  	return _pagePtrs[pageNum];  } +int Screen::getPageScaleFactor(int pageNum) { +	assert(pageNum < SCREEN_PAGE_NUM); +	return _pageScaleFactor[pageNum]; +} +  uint8 *Screen::getPageRect(int pageNum, int x, int y, int w, int h) {  	assert(pageNum < SCREEN_PAGE_NUM);  	if (pageNum == 0 || pageNum == 1) @@ -462,7 +482,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, SCREEN_PAGE_SIZE * _pageScaleFactor[_curPage] * _pageScaleFactor[_curPage]);  	clearOverlayPage(pageNum);  } @@ -476,7 +496,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, SCREEN_PAGE_SIZE * _pageScaleFactor[_curPage] * _pageScaleFactor[_curPage]);  	clearOverlayPage(_curPage);  } @@ -632,12 +652,17 @@ uint8 Screen::getPagePixel(int pageNum, int x, int y) {  void Screen::setPagePixel(int pageNum, int x, int y, uint8 color) {  	assert(pageNum < SCREEN_PAGE_NUM);  	assert(x >= 0 && x < SCREEN_W && y >= 0 && y < SCREEN_H); +  	if (pageNum == 0 || pageNum == 1)  		addDirtyRect(x, y, 1, 1);  	if (_use16ColorMode) {  		color &= 0x0F;  		color |= (color << 4); +	} else if (_renderMode == Common::kRenderCGA) { +		color &= 0x03; +	} else if (_renderMode == Common::kRenderEGA) { +		color &= 0x0F;  	}  	_pagePtrs[pageNum][y * SCREEN_W + x] = color; @@ -845,16 +870,26 @@ void Screen::copyToPage0(int y, int h, uint8 page, uint8 *seqBuf) {  }  void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage, int flags) { +	// Since we don't (need to) do any actual scaling, we check for compatible pages here +	assert(_pageScaleFactor[srcPage] == _pageScaleFactor[dstPage]); + +	x1 *= _pageScaleFactor[srcPage]; +	y1 *= _pageScaleFactor[srcPage]; +	x2 *= _pageScaleFactor[dstPage]; +	y2 *= _pageScaleFactor[dstPage]; +	w *= _pageScaleFactor[srcPage]; +	h *= _pageScaleFactor[srcPage]; +  	if (x2 < 0) {  		if (x2  <= -w)  			return;  		w += x2;  		x1 -= x2;  		x2 = 0; -	} else if (x2 + w >= SCREEN_W) { -		if (x2 > SCREEN_W) +	} else if (x2 + w >= SCREEN_W * _pageScaleFactor[dstPage]) { +		if (x2 > SCREEN_W * _pageScaleFactor[dstPage])  			return; -		w = SCREEN_W - x2; +		w = SCREEN_W * _pageScaleFactor[srcPage] - x2;  	}  	if (y2 < 0) { @@ -863,14 +898,14 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag  		h += y2;  		y1 -= y2;  		y2 = 0; -	} else if (y2 + h >= SCREEN_H) { -		if (y2 > SCREEN_H) +	} else if (y2 + h >= SCREEN_H * _pageScaleFactor[dstPage]) { +		if (y2 > SCREEN_H * _pageScaleFactor[dstPage])  			return; -		h = SCREEN_H - y2; +		h = SCREEN_H * _pageScaleFactor[srcPage] - 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 * _pageScaleFactor[srcPage] + x1; +	uint8 *dst = getPagePtr(dstPage) + y2 * SCREEN_W * _pageScaleFactor[dstPage] + x2;  	if (src == dst)  		return; @@ -883,8 +918,8 @@ 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; +			src += SCREEN_W * _pageScaleFactor[srcPage]; +			dst += SCREEN_W * _pageScaleFactor[dstPage];  		}  	} else {  		while (h--) { @@ -892,19 +927,24 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag  				if (src[i])  					dst[i] = src[i];  			} -			src += SCREEN_W; -			dst += SCREEN_W; +			src += SCREEN_W * _pageScaleFactor[srcPage]; +			dst += SCREEN_W * _pageScaleFactor[dstPage];  		}  	}  }  void Screen::copyRegionToBuffer(int pageNum, int x, int y, int w, int h, uint8 *dest) { +	x *= _pageScaleFactor[pageNum]; +	y *= _pageScaleFactor[pageNum]; +	w *= _pageScaleFactor[pageNum]; +	h *= _pageScaleFactor[pageNum]; +  	if (y < 0) {  		dest += (-y) * w;  		h += y;  		y = 0;  	} else if (y + h > SCREEN_H) { -		h = SCREEN_H - y; +		h = SCREEN_H * _pageScaleFactor[pageNum] - y;  	}  	if (x < 0) { @@ -912,7 +952,7 @@ void Screen::copyRegionToBuffer(int pageNum, int x, int y, int w, int h, uint8 *  		w += x;  		x = 0;  	} else if (x + w > SCREEN_W) { -		w = SCREEN_W - x; +		w = SCREEN_W * _pageScaleFactor[pageNum] - x;  	}  	if (w < 0 || h < 0) @@ -921,14 +961,17 @@ 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, pagePtr + i * SCREEN_W * _pageScaleFactor[pageNum] + x, w);  }  void Screen::copyPage(uint8 srcPage, uint8 dstPage) { +	// Since we don't (need to) do any actual scaling, we check for compatible pages here +	assert(_pageScaleFactor[srcPage] == _pageScaleFactor[dstPage]); +  	uint8 *src = getPagePtr(srcPage);  	uint8 *dst = getPagePtr(dstPage);  	if (src != dst) -		memcpy(dst, src, SCREEN_W * SCREEN_H); +		memcpy(dst, src, SCREEN_W * _pageScaleFactor[srcPage] * SCREEN_H * _pageScaleFactor[srcPage]);  	copyOverlayRegion(0, 0, 0, 0, SCREEN_W, SCREEN_H, srcPage, dstPage);  	if (dstPage == 0 || dstPage == 1) @@ -955,7 +998,12 @@ 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; +	x *= _pageScaleFactor[pageNum]; +	y *= _pageScaleFactor[pageNum]; +	w *= _pageScaleFactor[pageNum]; +	h *= _pageScaleFactor[pageNum]; + +	uint8 *dst = getPagePtr(pageNum) + y * SCREEN_W * _pageScaleFactor[pageNum] + x;  	if (pageNum == 0 || pageNum == 1)  		addDirtyRect(x, y, w, h); @@ -964,7 +1012,7 @@ void Screen::copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint  	while (h--) {  		memcpy(dst, src, w); -		dst += SCREEN_W; +		dst += SCREEN_W * _pageScaleFactor[pageNum];  		src += w;  	}  } @@ -1132,7 +1180,7 @@ void Screen::drawLine(bool vertical, int x, int y, int length, int color) {  		int currLine = 0;  		while (currLine < length) {  			*ptr = color; -			ptr += SCREEN_W; +			ptr += SCREEN_W * _pageScaleFactor[_curPage];  			currLine++;  		}  	} else { @@ -1178,7 +1226,7 @@ bool Screen::loadFont(FontId fontId, const char *filename) {  			fnt = new AMIGAFont();  #ifdef ENABLE_EOB  		else if (_vm->game() == GI_EOB1 || _vm->game() == GI_EOB2) -			fnt = new OldDOSFont(_renderMode, _cgaDrawCharDitheringTable); +			fnt = new OldDOSFont(_renderMode, (_vm->game() == GI_EOB2) && (_renderMode == Common::kRenderEGA));  #endif // ENABLE_EOB  		else  			fnt = new DOSFont(); @@ -1265,12 +1313,12 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2  			break;  		} else if (c == '\r') {  			x = x_start; -			y += charHeightFnt + _charOffset; +			y += (charHeightFnt + _charOffset);  		} else {  			int charWidth = getCharWidth(c);  			if (x + charWidth > SCREEN_W) {  				x = x_start; -				y += charHeightFnt + _charOffset; +				y += (charHeightFnt + _charOffset);  				if (y >= SCREEN_H)  					break;  			} @@ -1307,6 +1355,9 @@ void Screen::drawChar(uint16 c, int x, int y) {  	if (x + charWidth > SCREEN_W || y + charHeight > SCREEN_H)  		return; +	x *= _pageScaleFactor[_curPage]; +	y *= _pageScaleFactor[_curPage]; +  	if (useOverlay) {  		uint8 *destPage = getOverlayPtr(_curPage);  		if (!destPage) { @@ -1318,11 +1369,11 @@ void Screen::drawChar(uint16 c, int x, int y) {  		fnt->drawChar(c, destPage, 640);  	} else { -		fnt->drawChar(c, getPagePtr(_curPage) + y * SCREEN_W + x, SCREEN_W); +		fnt->drawChar(c, getPagePtr(_curPage) + y * SCREEN_W * _pageScaleFactor[_curPage] + x, SCREEN_W * _pageScaleFactor[_curPage]);  	}  	if (_curPage == 0 || _curPage == 1) -		addDirtyRect(x, y, charWidth, charHeight); +		addDirtyRect(x, y, charWidth * _pageScaleFactor[_curPage], charHeight * _pageScaleFactor[_curPage]);  }  void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...) { @@ -3084,16 +3135,11 @@ bool Screen::loadPalette(const char *filename, Palette &pal) {  		numCols = stream->size() / Palette::kPC98BytesPerColor;  		pal.loadPC98Palette(*stream, 0, MIN(maxCols, numCols));  	} else if (_renderMode == Common::kRenderEGA) { -		// EOB II checks the number of palette bytes to distinguish between real EGA palettes -		// and normal palettes (which are used to generate a color map). -		if (stream->size() == 16) { -			numCols = 16; -			pal.loadEGAPalette(*stream, 0, 16); -		} else { -			numCols = stream->size() / Palette::kVGABytesPerColor; -			pal.loadVGAPalette(*stream, 0, numCols); -		} - +		numCols = stream->size(); +		// There aren't any 16 color EGA palette files. So this shouldn't ever get triggered. +		assert (numCols != 16); +		numCols /= Palette::kVGABytesPerColor; +		pal.loadVGAPalette(*stream, 0, numCols);  	} else {  		numCols = stream->size() / Palette::kVGABytesPerColor;  		pal.loadVGAPalette(*stream, 0, MIN(maxCols, numCols)); @@ -3163,7 +3209,7 @@ void Screen::addDirtyRect(int x, int y, int w, int h) {  	Common::Rect r(x, y, x + w, y + h);  	// Clip rectangle -	r.clip(SCREEN_W, SCREEN_H); +	r.clip(SCREEN_W * _pageScaleFactor[0], SCREEN_H * _pageScaleFactor[0]);  	// If it is empty after clipping, we are done  	if (r.isEmpty()) @@ -3270,6 +3316,8 @@ void Screen::crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int s  	if (srcPage > 13 || dstPage > 13)  		error("Screen::crossFadeRegion(): attempting to use temp page as source or dest page."); +	assert(_pageScaleFactor[srcPage] == _pageScaleFactor[dstPage]); +  	hideMouse();  	uint16 *wB = (uint16 *)_pagePtrs[14]; @@ -3287,23 +3335,19 @@ void Screen::crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int s  	for (int i = 0; i < h; i++)  		SWAP(hB[_vm->_rnd.getRandomNumberRng(0, h - 1)], hB[i]); -	uint8 *s = _pagePtrs[srcPage]; -	uint8 *d = _pagePtrs[dstPage]; -  	for (int i = 0; i < h; i++) {  		int iH = i;  		uint32 end = _system->getMillis() + 3;  		for (int ii = 0; ii < w; ii++) { -			int sX = x1 + wB[ii]; -			int sY = y1 + hB[iH]; -			int dX = x2 + wB[ii]; -			int dY = y2 + hB[iH]; +			int sX = (x1 + wB[ii]); +			int sY = (y1 + hB[iH]); +			int dX = (x2 + wB[ii]); +			int dY = (y2 + hB[iH]);  			if (++iH >= h)  				iH = 0; -			d[dY * 320 + dX] = s[sY * 320 + sX]; -			addDirtyRect(dX, dY, 1, 1); +			setPagePixel(dstPage, dX, dY, getPagePixel(srcPage, sX, sY));  		}  		// This tries to speed things up, to get similiar speeds as in DOSBox etc. diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h index fcb5ef2be4..18c0aa90f7 100644 --- a/engines/kyra/screen.h +++ b/engines/kyra/screen.h @@ -145,7 +145,7 @@ private:   */  class OldDOSFont : public Font {  public: -	OldDOSFont(Common::RenderMode mode, const uint16 *cgaDitheringTable); +	OldDOSFont(Common::RenderMode mode, bool useHiResEGADithering);  	~OldDOSFont();  	bool load(Common::SeekableReadStream &file); @@ -167,7 +167,10 @@ private:  	int _numGlyphs;  	Common::RenderMode _renderMode; -	const uint16 *_cgaDitheringTable; +	bool _useHiResEGADithering; + +	static uint16 *_cgaDitheringTable; +	static int _numRef;  };  #endif // ENABLE_EOB @@ -395,7 +398,7 @@ public:  	// init  	virtual bool init(); -	virtual void setResolution(); +	virtual void setResolution(bool hiRes = false);  	void updateScreen(); @@ -422,14 +425,16 @@ public:  	void copyBlockToPage(int pageNum, int x, int y, int w, int h, const uint8 *src);  	void shuffleScreen(int sx, int sy, int w, int h, int srcPage, int dstPage, int ticks, bool transparent); -	void fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum = -1, bool xored = false); +	virtual void fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum = -1, bool xored = false);  	void clearPage(int pageNum); -	uint8 getPagePixel(int pageNum, int x, int y); -	void setPagePixel(int pageNum, int x, int y, uint8 color); +	virtual uint8 getPagePixel(int pageNum, int x, int y); +	virtual void setPagePixel(int pageNum, int x, int y, uint8 color);  	const uint8 *getCPagePtr(int pageNum) const; +	int getPageScaleFactor(int pageNum); +  	uint8 *getPageRect(int pageNum, int x, int y, int w, int h);  	// palette handling @@ -453,7 +458,7 @@ public:  	void copyPalette(const int dst, const int src);  	// gui specific (processing on _curPage) -	void drawLine(bool vertical, int x, int y, int length, int color); +	virtual void drawLine(bool vertical, int x, int y, int length, int color);  	void drawClippedLine(int x1, int y1, int x2, int y2, int color);  	virtual void drawShadedBox(int x1, int y1, int x2, int y2, int color1, int color2);  	void drawBox(int x1, int y1, int x2, int y2, int color); @@ -468,7 +473,7 @@ public:  	int getCharWidth(uint16 c) const;  	int getTextWidth(const char *str) const; -	void printText(const char *str, int x, int y, uint8 color1, uint8 color2); +	virtual void printText(const char *str, int x, int y, uint8 color1, uint8 color2);  	virtual void setTextColorMap(const uint8 *cmap) = 0;  	void setTextColor(const uint8 *cmap, int a, int b); @@ -569,13 +574,14 @@ protected:  	uint8 *_pagePtrs[16];  	uint8 *_sjisOverlayPtrs[SCREEN_OVLS_NUM]; +	uint8 _pageScaleFactor[SCREEN_PAGE_NUM]; +	uint8 _pageMapping[SCREEN_PAGE_NUM];  	bool _useOverlays;  	bool _useSJIS;  	bool _use16ColorMode;  	bool _isAmiga;  	Common::RenderMode _renderMode; -	uint16 *_cgaDrawCharDitheringTable;  	uint8 _sjisInvisibleColor; diff --git a/engines/kyra/screen_eob.cpp b/engines/kyra/screen_eob.cpp index 51665a00b1..38521d757c 100644 --- a/engines/kyra/screen_eob.cpp +++ b/engines/kyra/screen_eob.cpp @@ -51,7 +51,7 @@ Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system,  	_dsScaleTrans = 0;  	_cgaScaleTable = 0;  	_gfxMaxY = 0; -	_egaColorMap = 0; +	_egaDitheringTable = 0;  	_egaPixelValueTable = 0;  	_cgaMappingDefault = 0;  	_cgaDitheringTables[0] = _cgaDitheringTables[1] = 0; @@ -62,11 +62,10 @@ Screen_EoB::~Screen_EoB() {  	delete[] _fadeData;  	delete[] _dsTempPage;  	delete[] _cgaScaleTable; -	delete[] _egaColorMap; +	delete[] _egaDitheringTable;  	delete[] _egaPixelValueTable;  	delete[] _cgaDitheringTables[0];  	delete[] _cgaDitheringTables[1]; -	delete[] _cgaDrawCharDitheringTable;  }  bool Screen_EoB::init() { @@ -74,6 +73,12 @@ bool Screen_EoB::init() {  }  bool Screen_EoB::init(bool useHiResEGADithering) { +	// Define hi-res pages for EGA mode in EOB II +	if (useHiResEGADithering) { +		for (int i = 0; i < 8; i++) +			_pageScaleFactor[i] = 2; +	} +  	if (Screen::init()) {  		int temp;  		_gfxMaxY = _vm->staticres()->loadRawData(kEoBBaseExpObjectY, temp); @@ -96,10 +101,10 @@ bool Screen_EoB::init(bool useHiResEGADithering) {  		if (_renderMode == Common::kRenderEGA) {  			_useHiResEGADithering = useHiResEGADithering; -			_egaColorMap = new uint8[256]; +			_egaDitheringTable = new uint8[256];  			_egaPixelValueTable = new uint8[256];  			for (int i = 0; i < 256; i++) { -				_egaColorMap[i] = i & 0x0f; +				_egaDitheringTable[i] = i & 0x0f;  				_egaPixelValueTable[i] = i & 0x0f;  			} @@ -110,12 +115,6 @@ bool Screen_EoB::init(bool useHiResEGADithering) {  			_cgaDitheringTables[1] = new uint16[256];  			memset(_cgaDitheringTables[1], 0, 256 * sizeof(uint16)); -			_cgaDrawCharDitheringTable = new uint16[256]; -			memset(_cgaDrawCharDitheringTable, 0, 256 * sizeof(uint16)); -			static const uint bits[] = { 0, 3, 12, 15 }; -			for (int i = 0; i < 256; i++) -				_cgaDrawCharDitheringTable[i] = (bits[i & 3] << 8) | (bits[(i >> 2) & 3] << 12) | (bits[(i >> 4) & 3] << 0) | (bits[(i >> 6) & 3] << 4); -  			_cgaScaleTable = new uint8[256];  			memset(_cgaScaleTable, 0, 256 * sizeof(uint8));  			for (int i = 0; i < 256; i++) @@ -143,13 +142,19 @@ void Screen_EoB::setMouseCursor(int x, int y, const byte *shape) {  void Screen_EoB::setMouseCursor(int x, int y, const byte *shape, const uint8 *ovl) {  	if (!shape)  		return; -	int mouseW = shape[2] << 3; -	int mouseH = shape[3]; -	uint8 *cursor = new uint8[mouseW * mouseH]; -	fillRect(0, 0, mouseW, mouseH, _cursorColorKey, 8); -	drawShape(8, shape, 0, 0, 0, 2, ovl); + +	int mouseW = (shape[2] << 3); +	int mouseH = (shape[3]); +	int colorKey = (_renderMode == Common::kRenderCGA) ? 0 : _cursorColorKey; + +	uint8 *cursor = new uint8[mouseW * _pageScaleFactor[6] * mouseH * _pageScaleFactor[6]]; +	// 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 * _pageScaleFactor[6] * mouseH * _pageScaleFactor[6]); +	copyBlockToPage(6, 0, 0, mouseW, mouseH, cursor); +	drawShape(6, shape, 0, 0, 0, 2, ovl);  	CursorMan.showMouse(false); -	copyRegionToBuffer(8, 0, 0, mouseW, mouseH, cursor); +	copyRegionToBuffer(6, 0, 0, mouseW, mouseH, cursor);  	// Mouse cursor post processing for CGA mode. Unlike the original (which uses drawShape for the mouse cursor)  	// the cursor manager cannot know whether a pixel value of 0 is supposed to be black or transparent. Thus, we @@ -174,7 +179,7 @@ void Screen_EoB::setMouseCursor(int x, int y, const byte *shape, const uint8 *ov  		}  	} -	CursorMan.replaceCursor(cursor, mouseW, mouseH, x, y, _cursorColorKey); +	CursorMan.replaceCursor(cursor, mouseW * _pageScaleFactor[6], mouseH * _pageScaleFactor[6], x, y, colorKey);  	if (isMouseVisible())  		CursorMan.showMouse(true);  	delete[] cursor; @@ -190,6 +195,19 @@ void Screen_EoB::loadFileDataToPage(Common::SeekableReadStream *s, int pageNum,  	s->read(_pagePtrs[pageNum], size);  } +void Screen_EoB::printText(const char *str, int x, int y, uint8 color1, uint8 color2) { +	if (_useHiResEGADithering) { +		// This is sort of an abuse of the text color map. But since EOB doesn't use it anyway +		// and the font drawing code needs access to both the original color values and the +		// EGA dithering colors we pass them on like this. +		uint8 cmap[2]; +		cmap[0] = _egaDitheringTable[color2]; +		cmap[1] = _egaDitheringTable[color1]; +		setTextColor(cmap, 2, 3); +	} +	Screen::printText(str, x, y, color1, color2); +} +  void Screen_EoB::printShadedText(const char *string, int x, int y, int col1, int col2) {  	printText(string, x - 1, y, 12, col2);  	printText(string, x, y + 1, 12, 0); @@ -256,87 +274,153 @@ void Screen_EoB::convertPage(int srcPage, int dstPage, const uint8 *cgaMapping)  	if (_renderMode == Common::kRenderCGA) {  		if (cgaMapping)  			generateCGADitheringTables(cgaMapping); +  		uint16 *d = (uint16*)dst;  		uint8 tblSwitch = 0;  		for (int height = SCREEN_H; height; height--) {  			const uint16 *table = _cgaDitheringTables[(tblSwitch++) & 1];  			for (int width = SCREEN_W / 2; width; width--) { -				*d++ = table[((src[1] & 0x0f) << 4) | (src[0] & 0x0f)]; +				WRITE_LE_UINT16(d++, table[((src[1] & 0x0f) << 4) | (src[0] & 0x0f)]);  				src += 2;  			}  		} -		if (dstPage == 0 || dstPage == 1) -			_forceFullUpdate = true; +	} else if (_useHiResEGADithering) { +		for (int height = SCREEN_H; height; height--) { +			uint8 *dst2 = dst + SCREEN_W * 2; +			for (int width = SCREEN_W; width; width--) { +				uint8 in = _egaDitheringTable[*src++]; +				*dst++ = *dst2++ = in >> 4; +				*dst++ = *dst2++ = in & 0x0f; +			} +			dst += (SCREEN_W * 2); +		}  	} else if (_renderMode == Common::kRenderEGA) {  		uint32 len = SCREEN_W * SCREEN_H; -		if (_useHiResEGADithering) { -			while (len--) { -				uint8 col = _egaColorMap[*src++] & 0x0f; -				*dst++ = col; +		while (len--) +			*dst++ = *src++ & 0x0f; + +	} else { +		copyPage(srcPage, dstPage); +	} -				/*for (int i = 4; i; i--) { -					uint8 col = _egaColorMap[*src++]; +	if (dstPage == 0 || dstPage == 1) +		_forceFullUpdate = true; +} -				}*/ -			} -		} else { -			while (len--) -				*dst++ = *src++ & 0x0f; +void Screen_EoB::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum, bool xored) { +	if (!_useHiResEGADithering) { +		Screen::fillRect(x1, y1, x2, y2, color, pageNum, xored); +		return; +	} + +	assert(x2 < SCREEN_W && y2 < SCREEN_H); +	if (pageNum == -1) +		pageNum = _curPage; + +	uint16 pitch = (SCREEN_W - (x2 - x1 + 1)) * _pageScaleFactor[pageNum]; +	uint8 col1 = (_egaDitheringTable[color] >> 4); +	uint8 col2 = (_egaDitheringTable[color] & 0x0f); + +	x1 *= _pageScaleFactor[pageNum]; +	y1 *= _pageScaleFactor[pageNum]; +	x2 *= _pageScaleFactor[pageNum]; +	y2 *= _pageScaleFactor[pageNum]; +	uint16 w = x2 - x1 + _pageScaleFactor[pageNum]; +	uint16 h = y2 - y1 + _pageScaleFactor[pageNum]; + +	uint8 *dst = getPagePtr(pageNum) + y1 * SCREEN_W * _pageScaleFactor[pageNum] + x1; +	if (pageNum == 0 || pageNum == 1) +		addDirtyRect(x1, y1, w, h); + +	while (h--) { +		for (uint16 w1 = w; w1; w1 -= 2) { +			*dst++ = col1; +			*dst++ = col2;  		} +		dst += pitch; +	} +} -		if (dstPage == 0 || dstPage == 1) -			_forceFullUpdate = true; +void Screen_EoB::drawLine(bool vertical, int x, int y, int length, int color) { +	if (!_useHiResEGADithering) { +		Screen::drawLine(vertical, x, y, length, color); +		return; +	} + +	uint16 pitch = (SCREEN_W - 1) * _pageScaleFactor[_curPage]; +	uint8 col1 = (_egaDitheringTable[color] >> 4); +	uint8 col2 = (_egaDitheringTable[color] & 0x0f); + +	x *= _pageScaleFactor[_curPage]; +	y *= _pageScaleFactor[_curPage]; +	length *= _pageScaleFactor[_curPage]; +	uint8 *ptr = getPagePtr(_curPage) + y * SCREEN_W * _pageScaleFactor[_curPage] + x; +	uint8 *ptr2 = ptr + SCREEN_W * _pageScaleFactor[_curPage]; + +	if (vertical) { +		assert((y + length) <= SCREEN_H * _pageScaleFactor[_curPage]); +		int currLine = 0; +		while (currLine < length) { +			*ptr++ = col1; +			*ptr++ = col2; +			ptr += pitch; +			currLine++; +		}  	} else { -		copyPage(srcPage, dstPage); +		assert((x + length) <= SCREEN_W * _pageScaleFactor[_curPage]); +		int currLine = 0; +		while (currLine < length) { +			*ptr++ = *ptr2++ = col1; +			*ptr++ = *ptr2++ = col2; +			currLine += 2; +		}  	} + +	if (_curPage == 0 || _curPage == 1) +		addDirtyRect(x, y, (vertical) ? _pageScaleFactor[_curPage] : length, (vertical) ? length : _pageScaleFactor[_curPage]);  } -void Screen_EoB::setScreenPalette(const Palette &pal) { -	if (_renderMode == Common::kRenderEGA && _egaColorMap && pal.getNumColors() != 16) { -		const uint8 *src = pal.getData(); -		uint8 *dst = _egaColorMap; - -		for (int i = 256; i; i--) { -			uint8 r = *src++; -			uint8 g = *src++; -			uint8 b = *src++; - -			uint8 col = 0; -			uint16 min = 11907; - -			for (int ii = 256; ii; ii--) { -				const uint8 *palEntry = _egaMatchTable + (ii - 1) * 3; -				if (*palEntry == 0xff) -					continue; - -				int e_r = palEntry[0]; -				e_r -= r; -				int e_g = palEntry[1]; -				e_g -= g; -				int e_b = palEntry[2]; -				e_b -= b; - -				int s = (e_r * e_r) + (e_g * e_g) + (e_b * e_b); - -				if (s < min) { -					min = s; -					col = ii - 1; -				} -			} -			*dst++ = col; -		} +uint8 Screen_EoB::getPagePixel(int pageNum, int x, int y) { +	if (!_useHiResEGADithering) +		return Screen::getPagePixel(pageNum, x, y); -		memset(_egaPixelValueTable, 0, 256); -		for (int i = 0; i < 256; i++) -			_egaPixelValueTable[_egaColorMap[i]] = i; +	x *= _pageScaleFactor[_curPage]; +	y *= _pageScaleFactor[_curPage]; +	uint8 *pos = &_pagePtrs[pageNum][y * SCREEN_W * _pageScaleFactor[_curPage] + x]; -	} else if (_renderMode == Common::kRenderEGA) { +	return _egaPixelValueTable[(pos[0] << 4) | (pos[1] & 0x0f)]; +} + +void Screen_EoB::setPagePixel(int pageNum, int x, int y, uint8 color) { +	if (!_useHiResEGADithering) { +		Screen::setPagePixel(pageNum, x, y, color); +		return; +	} + +	assert(pageNum < SCREEN_PAGE_NUM); +	assert(x >= 0 && x < SCREEN_W && y >= 0 && y < SCREEN_H); + +	x *= _pageScaleFactor[_curPage]; +	y *= _pageScaleFactor[_curPage]; + +	if (pageNum == 0 || pageNum == 1) +		addDirtyRect(x, y, _pageScaleFactor[pageNum], _pageScaleFactor[pageNum]); + +	uint8 *pos = &_pagePtrs[pageNum][y * SCREEN_W * _pageScaleFactor[_curPage] + x]; +	uint8 *pos2 = pos + SCREEN_W * _pageScaleFactor[_curPage]; +	pos[0] = pos2[0] = _egaDitheringTable[color] >> 4; +	pos[1] = pos2[1] = _egaDitheringTable[color] & 0x0f; +} + +void Screen_EoB::setScreenPalette(const Palette &pal) { +	if (_useHiResEGADithering && pal.getNumColors() != 16) { +		generateEGADitheringTable(pal); +	} else if (_renderMode == Common::kRenderEGA && pal.getNumColors() == 16) {  		_screenPalette->copy(pal);  		_system->getPaletteManager()->setPalette(_screenPalette->getData(), 0, _screenPalette->getNumColors()); - -	} else if (_renderMode != Common::kRenderCGA) { +	} else if (_renderMode != Common::kRenderCGA && _renderMode != Common::kRenderEGA) {  		Screen::setScreenPalette(pal);  	}  } @@ -457,7 +541,7 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool enco  		uint8 nib = 0, col = 0;  		uint8 *colorMap = 0; -		if (_renderMode != Common::kRenderEGA) { +		if (_renderMode != Common::kRenderEGA || _useHiResEGADithering) {  			colorMap = new uint8[0x100];  			memset(colorMap, 0xff, 0x100);  		} @@ -472,7 +556,7 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool enco  		*dst++ = (w & 0xff);  		*dst++ = (h & 0xff); -		if (_renderMode == Common::kRenderEGA) { +		if (_renderMode == Common::kRenderEGA && !_useHiResEGADithering) {  			for (int i = 0; i < 16; i++)  				dst[i] = i;  		} else { @@ -536,7 +620,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,  		y += _dsY1;  	} -	dst += (_dsX1 << 3); +	dst += (_dsX1 << 3) * _pageScaleFactor[pageNum];  	int16 dX = x - (_dsX1 << 3);  	int16 dY = y;  	int16 dW = _dsX2 - _dsX1; @@ -608,11 +692,11 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,  			marginRight = w2 - marginLeft - width;  		} -		dst += (dY * 320 + dX); +		dst += (dY * SCREEN_W * _pageScaleFactor[pageNum] * _pageScaleFactor[pageNum] + dX * _pageScaleFactor[pageNum]);  		uint8 *dstL = dst;  		if (pageNum == 0 || pageNum == 1) -			addDirtyRect(rX, rY, rW, rH); +			addDirtyRect(rX * _pageScaleFactor[pageNum], rY * _pageScaleFactor[pageNum], rW * _pageScaleFactor[pageNum], rH * _pageScaleFactor[pageNum]);  		while (dH--) {  			int16 xpos = (int16) marginLeft; @@ -647,7 +731,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,  				} while (xpos > 0);  			} -			dst -= xpos; +			dst -= (xpos * _pageScaleFactor[pageNum]);  			xpos += width;  			while (xpos > 0) { @@ -656,11 +740,12 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,  				src += pixelStep;  				if (m) { -					drawShapeSetPixel(dst++, c); +					drawShapeSetPixel(dst, c, SCREEN_W * _pageScaleFactor[pageNum]); +					dst += _pageScaleFactor[pageNum];  					xpos--;  				} else {  					uint8 len = (flags & 1) ? src[1] : src[0]; -					dst += len; +					dst += (len * _pageScaleFactor[pageNum]);  					xpos -= len;  					src += pixelStep;  				} @@ -686,7 +771,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,  				} while (xpos > 0);  			} -			dstL += 320; +			dstL += SCREEN_W * _pageScaleFactor[pageNum] * _pageScaleFactor[pageNum];  			dst = dstL;  			if (flags & 1)  				src = src2 + 1; @@ -754,12 +839,12 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,  		if (d < width)  			width = d; -		dst += (dY * 320 + dX); +		dst += (dY * _pageScaleFactor[pageNum] * SCREEN_W * _pageScaleFactor[pageNum] + dX * _pageScaleFactor[pageNum]);  		if (pageNum == 0 || pageNum == 1) -			addDirtyRect(rX, rY, rW, rH); +			addDirtyRect(rX * _pageScaleFactor[pageNum], rY * _pageScaleFactor[pageNum], rW * _pageScaleFactor[pageNum], rH * _pageScaleFactor[pageNum]); -		int pitch = 320 - width; +		int pitch = SCREEN_W * _pageScaleFactor[pageNum] * _pageScaleFactor[pageNum] - width * _pageScaleFactor[pageNum];  		int16 lineSrcStep = (w2 - width) / pixelsPerByte;  		uint8 lineSrcStepRemainder = (w2 - width) % pixelsPerByte; @@ -802,9 +887,9 @@ 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++; -				shift = (shift - (pixelStep * pixelPacking) & 7); +					drawShapeSetPixel(dst, col, SCREEN_W * _pageScaleFactor[pageNum]); +				dst += _pageScaleFactor[pageNum]; +				shift = ((shift - (pixelStep * pixelPacking)) & 7);  			}  			src += lineSrcStep;  			dst += pitch; @@ -1266,25 +1351,36 @@ const uint16 *Screen_EoB::getCGADitheringTable(int index) {  	return !(index & ~1) ? _cgaDitheringTables[index] : 0;  } -void Screen_EoB::drawShapeSetPixel(uint8 *dst, uint8 c) { +const uint8 *Screen_EoB::getEGADitheringTable() { +	return _egaDitheringTable; +} + +void Screen_EoB::drawShapeSetPixel(uint8 *dst, uint8 col, uint16 pitch) {  	if ((_renderMode != Common::kRenderCGA && _renderMode != Common::kRenderEGA) || _useHiResEGADithering) {  		if (_shapeFadeMode[0]) {  			if (_shapeFadeMode[1]) { -				c = *dst; +				col = _useHiResEGADithering ? _egaPixelValueTable[(dst[0] << 4) | (dst[1] & 0x0f)] : *dst;  			} else {  				_shapeFadeInternal &= 7; -				c = *(dst + _shapeFadeInternal++); +				 col = _useHiResEGADithering ? _egaPixelValueTable[(dst[_shapeFadeInternal] << 4) | (dst[_shapeFadeInternal + 1] & 0x0f)] : dst[_shapeFadeInternal]; +				_shapeFadeInternal++;  			}  		}  		if (_shapeFadeMode[1]) {  			uint8 cnt = _shapeFadeMode[1];  			while (cnt--) -				c = _fadeData[_fadeDataIndex + c]; +				col = _fadeData[_fadeDataIndex + col];  		}  	} -	*dst = c; +	if (_useHiResEGADithering) { +		col = _egaDitheringTable[col]; +		dst[0] = dst[pitch] = col >> 4; +		dst[1] = dst[pitch + 1] = col & 0x0f; +	} else { +		*dst = col; +	}  }  void Screen_EoB::scaleShapeProcessLine2Bit(uint8 *&shpDst, const uint8 *&shpSrc, uint32 transOffsetDst, uint32 transOffsetSrc) { @@ -1340,6 +1436,43 @@ bool Screen_EoB::posWithinRect(int posX, int posY, int x1, int y1, int x2, int y  	return true;  } +void Screen_EoB::generateEGADitheringTable(const Palette &pal) { +	assert(_egaDitheringTable); +	const uint8 *src = pal.getData(); +	uint8 *dst = _egaDitheringTable; + +	for (int i = 256; i; i--) { +		int r = *src++; +		int g = *src++; +		int b = *src++; + +		uint8 col = 0; +		uint16 min = 0x2E83; + +		for (int ii = 256; ii; ii--) { +			const uint8 *palEntry = _egaMatchTable + (ii - 1) * 3; +			if (*palEntry == 0xff) +				continue; + +			int e_r = palEntry[0] - r; +			int e_g = palEntry[1] - g; +			int e_b = palEntry[2] - b; + +			uint16 s = (e_r * e_r) + (e_g * e_g) + (e_b * e_b); + +			if (s <= min) { +				min = s; +				col = ii - 1; +			} +		} +		*dst++ = col; +	} + +	memset(_egaPixelValueTable, 0, 256); +	for (int i = 0; i < 256; i++) +		_egaPixelValueTable[_egaDitheringTable[i]] = i; +} +  void Screen_EoB::generateCGADitheringTables(const uint8 *mappingData) {  	for (int i = 0; i < 256; i++) {  		_cgaDitheringTables[0][i] = (mappingData[(i >> 4) + 16] << 8) | mappingData[i & 0x0f]; @@ -1398,14 +1531,34 @@ const uint8 Screen_EoB::_egaMatchTable[] = {  	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0x3F  }; -OldDOSFont::OldDOSFont(Common::RenderMode mode, const uint16 *cgaDitheringTable) : _renderMode(mode), _cgaDitheringTable(cgaDitheringTable) { +uint16 *OldDOSFont::_cgaDitheringTable = 0; +int OldDOSFont::_numRef = 0; + +OldDOSFont::OldDOSFont(Common::RenderMode mode, bool useHiResEGADithering) : _renderMode(mode), _useHiResEGADithering(useHiResEGADithering) {  	_data = 0;  	_width = _height = _numGlyphs = 0;  	_bitmapOffsets = 0; + +	_numRef++; +	if (!_cgaDitheringTable && _numRef == 1) { +		_cgaDitheringTable = new uint16[256]; +		memset(_cgaDitheringTable, 0, 256 * sizeof(uint16)); +		static const uint bits[] = { 0, 3, 12, 15 }; +		for (int i = 0; i < 256; i++) +			_cgaDitheringTable[i] = (bits[i & 3] << 8) | (bits[(i >> 2) & 3] << 12) | (bits[(i >> 4) & 3] << 0) | (bits[(i >> 6) & 3] << 4); +	}  }  OldDOSFont::~OldDOSFont() {  	unload(); + +	if (_numRef) +		--_numRef; + +	if (_cgaDitheringTable && !_numRef) { +		delete[] _cgaDitheringTable; +		_cgaDitheringTable = 0; +	}  }  bool OldDOSFont::load(Common::SeekableReadStream &file) { @@ -1491,18 +1644,27 @@ void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const {  	}  	const uint8 *src = &_data[_bitmapOffsets[c]]; +	uint8 *dst2 = dst + pitch;  	int w = (_width - 1) >> 3;  	pitch -= _width; +	if (_useHiResEGADithering) +		pitch *= 2; +  	uint8 color1 = _colorMap[1];  	uint8 color2 = _colorMap[0]; +	uint8 colEGA11 = _colorMap[3] >> 4; +	uint8 colEGA12 = _colorMap[3] & 0x0f; +	uint8 colEGA21 = _colorMap[2] >> 4; +	uint8 colEGA22 = _colorMap[2] & 0x0f; +  	static const uint16 cgaColorMask[] = { 0, 0x5555, 0xAAAA, 0xFFFF };  	uint16 cgaMask1 = cgaColorMask[color1 & 3];  	uint16 cgaMask2 = cgaColorMask[color2 & 3]; -	if (_renderMode == Common::kRenderCGA) { +	if (_renderMode == Common::kRenderCGA || (_renderMode == Common::kRenderEGA && !_useHiResEGADithering)) {  		color1 &= 0x0f;  		color2 &= 0x0f;  	} @@ -1559,13 +1721,27 @@ void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const {  						break;  					} -					if (s & i) { -						if (color1) -							*dst = color1; -					} else if (color2) { -						*dst = color2; +					if (_useHiResEGADithering) { +						if (s & i) { +							if (color1) { +								dst[0] = dst2[0] = colEGA11; +								dst[1] = dst2[1] = colEGA12; +							} +						} else if (color2) { +							dst[0] = dst2[0] = colEGA21; +							dst[1] = dst2[1] = colEGA22; +						} +						dst += 2; +						dst2 += 2; +					} else { +						if (s & i) { +							if (color1) +								*dst = color1; +						} else if (color2) { +							*dst = color2; +						} +						dst++;  					} -					dst++;  				}  				if (cW) @@ -1574,7 +1750,9 @@ void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const {  					runWidthLoop = false;  			}  		} +  		dst += pitch; +		dst2 += pitch;  	}  } diff --git a/engines/kyra/screen_eob.h b/engines/kyra/screen_eob.h index cf8f86953d..2bcfbd8f60 100644 --- a/engines/kyra/screen_eob.h +++ b/engines/kyra/screen_eob.h @@ -46,12 +46,19 @@ public:  	void loadFileDataToPage(Common::SeekableReadStream *s, int pageNum, uint32 size); +	void printText(const char *str, int x, int y, uint8 color1, uint8 color2);  	void printShadedText(const char *string, int x, int y, int col1, int col2); +  	void loadEoBBitmap(const char *file, const uint8 *cgaMapping, int tempPage, int destPage, int convertToPage);  	void loadShapeSetBitmap(const char *file, int tempPage, int destPage);  	void convertPage(int srcPage, int dstPage, const uint8 *cgaMapping); +	void fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum = -1, bool xored = false); +	void drawLine(bool vertical, int x, int y, int length, int color); +	uint8 getPagePixel(int pageNum, int x, int y); +	void setPagePixel(int pageNum, int x, int y, uint8 color); +  	void setScreenPalette(const Palette &pal);  	uint8 *encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool encode8bit = false, const uint8 *cgaMapping = 0); @@ -76,14 +83,17 @@ public:  	void setFadeTableIndex(int index);  	void createFadeTable(uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight);  	uint8 *getFadeTable(int index); +  	const uint16 *getCGADitheringTable(int index); +	const uint8 *getEGADitheringTable();  private: -	void drawShapeSetPixel(uint8 *dst, uint8 c); +	void drawShapeSetPixel(uint8 *dst, uint8 col, uint16 pitch);  	void scaleShapeProcessLine2Bit(uint8 *&shpDst, const uint8 *&shpSrc, uint32 transOffsetDst, uint32 transOffsetSrc);  	void scaleShapeProcessLine4Bit(uint8 *&dst, const uint8 *&src);  	bool posWithinRect(int posX, int posY, int x1, int y1, int x2, int y2); +	void generateEGADitheringTable(const Palette &pal);  	void generateCGADitheringTables(const uint8 *mappingData);  	int _dsDiv, _dsRem, _dsScaleTrans; @@ -104,7 +114,7 @@ private:  	uint16 *_cgaDitheringTables[2];  	const uint8 *_cgaMappingDefault; -	uint8 *_egaColorMap; +	uint8 *_egaDitheringTable;  	uint8 *_egaPixelValueTable;  	bool _useHiResEGADithering; | 
