aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra
diff options
context:
space:
mode:
authorathrxx2012-02-21 21:14:28 +0100
committerathrxx2012-02-21 21:48:46 +0100
commit66da4777d476c6a9fc2a13351e3b30afc748fd94 (patch)
treee501a86f10aa7f1a39420d08a529f492c7abe95c /engines/kyra
parent3c1e2686b8e8ad36f1cdc3bb2afebd7f9de72845 (diff)
downloadscummvm-rg350-66da4777d476c6a9fc2a13351e3b30afc748fd94.tar.gz
scummvm-rg350-66da4777d476c6a9fc2a13351e3b30afc748fd94.tar.bz2
scummvm-rg350-66da4777d476c6a9fc2a13351e3b30afc748fd94.zip
KYRA: (EOB) - implement EGA mode (hi res dithering) for EOB II
(also fix various thing connected to CGA/EGA modes)
Diffstat (limited to 'engines/kyra')
-rw-r--r--engines/kyra/chargen.cpp10
-rw-r--r--engines/kyra/darkmoon.cpp13
-rw-r--r--engines/kyra/eob.cpp2
-rw-r--r--engines/kyra/eobcommon.cpp6
-rw-r--r--engines/kyra/gui_eob.cpp28
-rw-r--r--engines/kyra/gui_eob.h5
-rw-r--r--engines/kyra/kyra_hof.cpp2
-rw-r--r--engines/kyra/kyra_lok.cpp2
-rw-r--r--engines/kyra/kyra_mr.cpp2
-rw-r--r--engines/kyra/kyra_rpg.cpp17
-rw-r--r--engines/kyra/kyra_rpg.h5
-rw-r--r--engines/kyra/kyra_v1.cpp9
-rw-r--r--engines/kyra/kyra_v1.h2
-rw-r--r--engines/kyra/lol.cpp2
-rw-r--r--engines/kyra/magic_eob.cpp2
-rw-r--r--engines/kyra/saveload_eob.cpp2
-rw-r--r--engines/kyra/scene_eob.cpp65
-rw-r--r--engines/kyra/scene_rpg.cpp76
-rw-r--r--engines/kyra/screen.cpp190
-rw-r--r--engines/kyra/screen.h24
-rw-r--r--engines/kyra/screen_eob.cpp384
-rw-r--r--engines/kyra/screen_eob.h14
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;