diff options
author | athrxx | 2012-02-13 17:04:05 +0100 |
---|---|---|
committer | athrxx | 2012-02-21 21:48:41 +0100 |
commit | 151d314912b08d7d598a3995524d89c8b4ab0371 (patch) | |
tree | 3900afdabb806c3fb6e46c947c672e369eeaf952 /engines/kyra | |
parent | 86a817beb5eef248c5f5e28f18133db802a59c2e (diff) | |
download | scummvm-rg350-151d314912b08d7d598a3995524d89c8b4ab0371.tar.gz scummvm-rg350-151d314912b08d7d598a3995524d89c8b4ab0371.tar.bz2 scummvm-rg350-151d314912b08d7d598a3995524d89c8b4ab0371.zip |
KYRA: (EOB) - complete CGA graphics mode implementation
Diffstat (limited to 'engines/kyra')
-rw-r--r-- | engines/kyra/eob.cpp | 5 | ||||
-rw-r--r-- | engines/kyra/eob.h | 3 | ||||
-rw-r--r-- | engines/kyra/eobcommon.cpp | 34 | ||||
-rw-r--r-- | engines/kyra/eobcommon.h | 6 | ||||
-rw-r--r-- | engines/kyra/gui_eob.cpp | 89 | ||||
-rw-r--r-- | engines/kyra/items_eob.cpp | 9 | ||||
-rw-r--r-- | engines/kyra/kyra_rpg.cpp | 2 | ||||
-rw-r--r-- | engines/kyra/kyra_rpg.h | 1 | ||||
-rw-r--r-- | engines/kyra/scene_eob.cpp | 50 | ||||
-rw-r--r-- | engines/kyra/scene_rpg.cpp | 64 | ||||
-rw-r--r-- | engines/kyra/screen.cpp | 17 | ||||
-rw-r--r-- | engines/kyra/screen_eob.cpp | 540 | ||||
-rw-r--r-- | engines/kyra/screen_eob.h | 16 | ||||
-rw-r--r-- | engines/kyra/sequences_eob.cpp | 1 | ||||
-rw-r--r-- | engines/kyra/sprites_eob.cpp | 4 | ||||
-rw-r--r-- | engines/kyra/staticres_eob.cpp | 11 |
16 files changed, 519 insertions, 333 deletions
diff --git a/engines/kyra/eob.cpp b/engines/kyra/eob.cpp index 3a1cfc1c84..769e77e63c 100644 --- a/engines/kyra/eob.cpp +++ b/engines/kyra/eob.cpp @@ -55,7 +55,8 @@ Common::Error EoBEngine::init() { initStaticResource(); - _itemsOverlay = _res->fileData((_configRenderMode == Common::kRenderEGA || _configRenderMode == Common::kRenderCGA) ? "ITEMRMP.EGA" : "ITEMRMP.VGA", 0); + if (_configRenderMode != Common::kRenderCGA) + _itemsOverlay = _res->fileData((_configRenderMode == Common::kRenderEGA) ? "ITEMRMP.EGA" : "ITEMRMP.VGA", 0); _screen->modifyScreenDim(7, 0x01, 0xB3, 0x22, 0x12); _screen->modifyScreenDim(9, 0x01, 0x7D, 0x26, 0x3F); @@ -553,7 +554,7 @@ void EoBEngine::healParty() { } const KyraRpgGUISettings *EoBEngine::guiSettings() { - return &_guiSettings; + return (_configRenderMode == Common::kRenderCGA || _configRenderMode == Common::kRenderEGA) ? &_guiSettingsEGA : &_guiSettingsVGA; } } // End of namespace Kyra diff --git a/engines/kyra/eob.h b/engines/kyra/eob.h index 9d583a0cd7..37ce483702 100644 --- a/engines/kyra/eob.h +++ b/engines/kyra/eob.h @@ -108,7 +108,8 @@ private: const KyraRpgGUISettings *guiSettings(); - static const KyraRpgGUISettings _guiSettings; + static const KyraRpgGUISettings _guiSettingsVGA; + static const KyraRpgGUISettings _guiSettingsEGA; static const uint8 _egaDefaultPalette[]; }; diff --git a/engines/kyra/eobcommon.cpp b/engines/kyra/eobcommon.cpp index a68c7de9e8..ecac20a7f8 100644 --- a/engines/kyra/eobcommon.cpp +++ b/engines/kyra/eobcommon.cpp @@ -65,7 +65,6 @@ EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags) _itemIconShapes = _wallOfForceShapes = _teleporterShapes = _sparkShapes = _compassShapes = 0; _redSplatShape = _greenSplatShape = _deadCharShape = _disabledCharGrid = 0; _blackBoxSmallGrid = _weaponSlotGrid = _blackBoxWideGrid = _lightningColumnShape = 0; - _tempIconShape = 0; _monsterDustStrings = 0; _enemyMageSpellList = 0; @@ -93,7 +92,7 @@ EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags) _doorSwitches = 0; _monsterProps = 0; _monsterDecorations = 0; - _monsterOvl1 = _monsterOvl2 = 0; + _monsterFlashOverlay = _monsterStoneOverlay = 0; _monsters = 0; _dstMonsterIndex = 0; _preventMonsterFlash = false; @@ -214,7 +213,7 @@ EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags) _mnNumWord = _numSpells = _mageSpellListSize = _spellLevelsMageSize = _spellLevelsClericSize = 0; _inventorySlotsX = _slotValidationFlags = _encodeMonsterShpTable = 0; _cgaMappingDefault = _cgaMappingAlt = _cgaMappingInv = _cgaLevelMappingIndex = _cgaMappingItemsL = _cgaMappingItemsS = _cgaMappingThrown = _cgaMappingIcons = _cgaMappingDeco = 0; - memset(_cgaMappingLevel, 0, sizeof(_cgaMappingLevel)); + memset(_cgaMappingLevel, 0, sizeof(_cgaMappingLevel)); memset(_expRequirementTables, 0, sizeof(_expRequirementTables)); memset(_saveThrowTables, 0, sizeof(_saveThrowTables)); memset(_doorType, 0, sizeof(_doorType)); @@ -271,8 +270,8 @@ EoBCoreEngine::~EoBCoreEngine() { delete[] _itemNames; delete[] _flyingObjects; - delete[] _monsterOvl1; - delete[] _monsterOvl2; + delete[] _monsterFlashOverlay; + delete[] _monsterStoneOverlay; delete[] _monsters; if (_monsterDecorations) { @@ -483,11 +482,11 @@ Common::Error EoBCoreEngine::init() { _doorSwitches = new SpriteDecoration[6]; memset(_doorSwitches, 0, 6 * sizeof(SpriteDecoration)); - _monsterOvl1 = new uint8[16]; - _monsterOvl2 = new uint8[16]; - memset(_monsterOvl1, 15, 16 * sizeof(uint8)); - memset(_monsterOvl2, 13, 16 * sizeof(uint8)); - _monsterOvl1[0] = _monsterOvl2[0] = 0; + _monsterFlashOverlay = new uint8[16]; + _monsterStoneOverlay = new uint8[16]; + memset(_monsterFlashOverlay, (_configRenderMode == Common::kRenderCGA) ? 0xff : 0x0f, 16 * sizeof(uint8)); + memset(_monsterStoneOverlay, 0x0d, 16 * sizeof(uint8)); + _monsterFlashOverlay[0] = _monsterStoneOverlay[0] = 0; // Prevent autosave on game startup _lastAutosave = _system->getMillis(); @@ -700,7 +699,6 @@ void EoBCoreEngine::loadItemsAndDecorationsShapes() { _itemIconShapes = new const uint8*[_numItemIconShapes]; for (int i = 0; i < _numItemIconShapes; i++) _itemIconShapes[i] = _screen->encodeShape((i % 0x14) << 1, (i / 0x14) << 4, 2, 0x10, false, _cgaMappingIcons); - _tempIconShape = new uint8[300]; _screen->loadShapeSetBitmap("DECORATE", 5, 3); @@ -774,7 +772,6 @@ void EoBCoreEngine::releaseItemsAndDecorationsShapes() { } delete[] _itemIconShapes; } - delete[] _tempIconShape; if (_sparkShapes) { for (int i = 0; i < 3; i++) { @@ -838,18 +835,13 @@ void EoBCoreEngine::setHandItem(Item itemIndex) { _itemInHand = itemIndex; int icon = _items[_itemInHand].icon; const uint8 *shp = _itemIconShapes[icon]; + const uint8 *ovl = 0; - if (icon && (_items[_itemInHand].flags & 0x80) && (_partyEffectFlags & 2)) { - memcpy(_tempIconShape, shp, shp[1] * shp[2] * 4 + 20); - if (_flags.gameID == GI_EOB1) - _screen->replaceShapePalette(_tempIconShape, &_itemsOverlay[icon << 4]); - else - _screen->applyShapeOverlay(_tempIconShape, 3); - shp = _tempIconShape; - } + if (icon && (_items[_itemInHand].flags & 0x80) && (_partyEffectFlags & 2)) + ovl = _flags.gameID == GI_EOB1 ? ((_configRenderMode == Common::kRenderCGA) ? _itemsOverlayCGA : &_itemsOverlay[icon << 4]) : _screen->generateShapeOverlay(shp, 3); int mouseOffs = itemIndex ? 8 : 0; - _screen->setMouseCursor(mouseOffs, mouseOffs, shp); + _screen->setMouseCursor(mouseOffs, mouseOffs, shp, ovl); } int EoBCoreEngine::getDexterityArmorClassModifier(int dexterity) { diff --git a/engines/kyra/eobcommon.h b/engines/kyra/eobcommon.h index 49589c809c..38be2a64e8 100644 --- a/engines/kyra/eobcommon.h +++ b/engines/kyra/eobcommon.h @@ -302,8 +302,8 @@ protected: const uint8 *_blackBoxWideGrid; const uint8 *_lightningColumnShape; - uint8 *_tempIconShape; uint8 *_itemsOverlay; + static const uint8 _itemsOverlayCGA[]; static const uint8 _teleporterShapeDefs[]; static const uint8 _wallOfForceShapeDefs[]; @@ -528,8 +528,8 @@ protected: void updateMonstersSpellStatus(EoBMonsterInPlay *m); void setBlockMonsterDirection(int block, int dir); - uint8 *_monsterOvl1; - uint8 *_monsterOvl2; + uint8 *_monsterFlashOverlay; + uint8 *_monsterStoneOverlay; SpriteDecoration *_monsterDecorations; EoBMonsterProperty *_monsterProps; diff --git a/engines/kyra/gui_eob.cpp b/engines/kyra/gui_eob.cpp index 2fdfb0c011..39cc4692c4 100644 --- a/engines/kyra/gui_eob.cpp +++ b/engines/kyra/gui_eob.cpp @@ -116,7 +116,7 @@ void EoBCoreEngine::gui_drawCharPortraitWithStats(int index) { if (c->damageTaken > 0) { _screen->drawShape(2, _redSplatShape, x2 + 13, y2 + 30, 0); Common::String tmpStr = Common::String::format("%d", c->damageTaken); - _screen->printText(tmpStr.c_str(), x2 + 34 - tmpStr.size() * 3, y2 + 42, 15, 0); + _screen->printText(tmpStr.c_str(), x2 + 34 - tmpStr.size() * 3, y2 + 42, (_configRenderMode == Common::kRenderCGA) ? 12 : 15, 0); } _screen->setCurPage(cp); @@ -256,10 +256,8 @@ void EoBCoreEngine::gui_drawFaceShape(int index) { if (c->hitPointsCur < 1) _screen->drawShape(_screen->_curPage, _disabledCharGrid, x, y, 0); - //if ((c->flags & 2) || (c->flags & 8) || (c->effectFlags & 0x140)) { - _screen->setFadeTableIndex(4); - _screen->setShapeFadeMode(1, false); - //} + _screen->setFadeTableIndex(4); + _screen->setShapeFadeMode(1, false); } void EoBCoreEngine::gui_drawWeaponSlot(int charIndex, int slot) { @@ -323,11 +321,13 @@ void EoBCoreEngine::gui_drawWeaponSlotStatus(int x, int y, int status) { break; } + int textColor= (_configRenderMode == Common::kRenderCGA) ? 2 : 15; + if (!tmpStr2.empty()) { - _screen->printText(tmpStr.c_str(), x + (16 - tmpStr.size() * 3), y + 2, 15, 0); - _screen->printText(tmpStr2.c_str(), x + (16 - tmpStr.size() * 3), y + 9, 15, 0); + _screen->printText(tmpStr.c_str(), x + (16 - tmpStr.size() * 3), y + 2, textColor, 0); + _screen->printText(tmpStr2.c_str(), x + (16 - tmpStr.size() * 3), y + 9, textColor, 0); } else { - _screen->printText(tmpStr.c_str(), x + (16 - tmpStr.size() * 3), y + 5, 15, 0); + _screen->printText(tmpStr.c_str(), x + (16 - tmpStr.size() * 3), y + 5, textColor, 0); } } @@ -408,12 +408,13 @@ void EoBCoreEngine::gui_drawHorizontalBarGraph(int x, int y, int w, int h, int32 } void EoBCoreEngine::gui_drawCharPortraitStatusFrame(int index) { - uint8 redGreenColor = (_partyEffectFlags & 0x20000) ? 4 : 6; + uint8 redGreenColor = (_partyEffectFlags & 0x20000) ? 4 : ((_configRenderMode == Common::kRenderCGA) ? 3 : 6); static const uint8 xCoords[] = { 8, 80 }; static const uint8 yCoords[] = { 2, 54, 106 }; int x = xCoords[index & 1]; int y = yCoords[index >> 1]; + int xOffset = (_configRenderMode == Common::kRenderCGA) ? 0 : 1; if (!_screen->_curPage) x += 176; @@ -467,7 +468,7 @@ void EoBCoreEngine::gui_drawCharPortraitStatusFrame(int index) { } else { _screen->drawClippedLine(x, y, x + 62, y, guiSettings()->colors.frame2); _screen->drawClippedLine(x, y + 49, x + 62, y + 49, guiSettings()->colors.frame1); - _screen->drawClippedLine(x - 1, y, x - 1, y + 50, 12); + _screen->drawClippedLine(x - xOffset, y, x - xOffset, y + 50, 12); _screen->drawClippedLine(x + 63, y, x + 63, y + 50, 12); } } @@ -481,7 +482,15 @@ void EoBCoreEngine::gui_drawInventoryItem(int slot, int special, int pageNum) { if (special) { int wh = (slot == 25 || slot == 26) ? 10 : 18; - gui_drawBox(x - 1, y - 1, wh, wh, guiSettings()->colors.frame1, guiSettings()->colors.frame2, slot == 16 ? -1 : guiSettings()->colors.fill); + + uint8 col1 = guiSettings()->colors.frame1; + uint8 col2 = guiSettings()->colors.frame2; + if (_configRenderMode == Common::kRenderCGA ) { + col1 = 1; + col2 = 3; + } + + gui_drawBox(x - 1, y - 1, wh, wh, col1, col2, slot == 16 ? -1 : guiSettings()->colors.fill); if (slot == 16) { _screen->fillRect(227, 65, 238, 69, 12); @@ -528,14 +537,26 @@ void EoBCoreEngine::gui_drawSpellbook() { _screen->copyRegion(64, 121, 64, 121, 112, 56, 0, 2, Screen::CR_NO_P_CHECK); for (int i = 0; i < numTab; i++) { - int col1 = guiSettings()->colors.inactiveTabFrame1; - int col2 = guiSettings()->colors.inactiveTabFrame2; - int col3 = guiSettings()->colors.inactiveTabFill; - - if (i == _openBookSpellLevel) { - col1 = guiSettings()->colors.frame1; - col2 = guiSettings()->colors.frame2; - col3 = guiSettings()->colors.fill; + int col1 = 0; + int col2 = 1; + int col3 = 2; + + if (_configRenderMode == Common::kRenderCGA) { + if (i == _openBookSpellLevel) { + col1 = 1; + col2 = 2; + col3 = 3; + } + } else { + col1 = guiSettings()->colors.inactiveTabFrame1; + col2 = guiSettings()->colors.inactiveTabFrame2; + col3 = guiSettings()->colors.inactiveTabFill; + + if (i == _openBookSpellLevel) { + col1 = guiSettings()->colors.frame1; + col2 = guiSettings()->colors.frame2; + col3 = guiSettings()->colors.fill; + } } if (_flags.gameID == GI_EOB1) { @@ -558,19 +579,21 @@ void EoBCoreEngine::gui_drawSpellbook() { gui_drawSpellbookScrollArrow(165, 169, 1); } - int textCol1 = 15; + int textCol1 = (_configRenderMode == Common::kRenderCGA) ? 3 : 15; int textCol2 = 8; int textXa = 74; int textXs = 71; int textY = 170; - int col3 = guiSettings()->colors.fill; + int col3 = (_configRenderMode == Common::kRenderCGA) ? 2 : guiSettings()->colors.fill; int col4 = guiSettings()->colors.extraFill; + int col5 = 12; if (_flags.gameID == GI_EOB1) { - textCol2 = 11; + textCol2 = (_configRenderMode == Common::kRenderCGA) ? 12 : 11; textXa = textXs = 73; textY = 168; - col4 = guiSettings()->colors.fill; + col4 = col3; + col5 = textCol1; } for (int i = 0; i < 7; i++) { @@ -587,7 +610,7 @@ void EoBCoreEngine::gui_drawSpellbook() { if (d >= 0 && i < 6 && (i + _openBookSpellListOffset) < 9) _screen->printText(_openBookSpellList[d], textXs, 132 + 6 * i, textCol1, col3); else - _screen->printText(_magicStrings1[0], textXa, textY, 12, col4); + _screen->printText(_magicStrings1[0], textXa, textY, col5, col4); } } @@ -2704,13 +2727,14 @@ bool GUI_EoB::runSaveMenu(int x, int y) { int GUI_EoB::selectSaveSlotDialogue(int x, int y, int id) { _saveSlotX = _saveSlotY = 0; + int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : 15; _screen->setCurPage(2); _savegameOffset = 0; drawMenuButtonBox(0, 0, 176, 144, false, false); const char *title = (id < 2) ? _vm->_saveLoadStrings[2 + id] : _vm->_transferStringsScummVM[id - 1]; - _screen->printShadedText(title, 52, 5, 15, 0); + _screen->printShadedText(title, 52, 5, col1, 0); _screen->copyRegion(0, 0, x, y, 176, 144, 2, 0, Screen::CR_NO_P_CHECK); _screen->setCurPage(0); @@ -2783,12 +2807,12 @@ int GUI_EoB::selectSaveSlotDialogue(int x, int y, int id) { lastHighlight = -1; setupSaveMenuSlots(); for (int i = 0; i < 7; i++) - drawSaveSlotButton(i, 1, 15); + drawSaveSlotButton(i, 1, col1); lastOffset = _savegameOffset; } if (lastHighlight != newHighlight) { - drawSaveSlotButton(lastHighlight, 0, 15); + drawSaveSlotButton(lastHighlight, 0, col1); drawSaveSlotButton(newHighlight, 0, 6); // Display highlighted slot index in the bottom left corner to avoid people getting lost with the 990 save slots @@ -3797,10 +3821,12 @@ void GUI_EoB::drawMenuButton(Button *b, bool clicked, bool highlight, bool noFil yOffs = (b->height - 7) >> 1; } + int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : 15; + if (noFill || clicked) - _screen->printText(s, b->x + xOffs, b->y + yOffs, highlight ? 6 : 15, 0); + _screen->printText(s, b->x + xOffs, b->y + yOffs, highlight ? 6 : col1, 0); else - _screen->printShadedText(s, b->x + xOffs, b->y + yOffs, highlight ? 6 : 15, 0); + _screen->printShadedText(s, b->x + xOffs, b->y + yOffs, highlight ? 6 : col1, 0); } } @@ -3862,13 +3888,14 @@ void GUI_EoB::memorizePrayMenuPrintString(int spellId, int bookPageIndex, int sp return; int y = bookPageIndex * 9 + 50; + int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : 15; if (spellId) { Common::String s(Common::String::format(_vm->_menuStringsMgc[0], spellType ? _vm->_clericSpellList[spellId] : _vm->_mageSpellList[spellId], _numAssignedSpellsOfType[spellId * 2 - 2])); if (noFill) - _screen->printText(s.c_str(), 8, y, highLight ? 6 : 15, 0); + _screen->printText(s.c_str(), 8, y, highLight ? 6 : col1, 0); else - _screen->printShadedText(s.c_str(), 8, y, highLight ? 6 : 15, _vm->guiSettings()->colors.fill); + _screen->printShadedText(s.c_str(), 8, y, highLight ? 6 : col1, _vm->guiSettings()->colors.fill); } else { _screen->fillRect(6, y, 168, y + 8, _vm->guiSettings()->colors.fill); diff --git a/engines/kyra/items_eob.cpp b/engines/kyra/items_eob.cpp index 979b68d34b..5b65887d4b 100644 --- a/engines/kyra/items_eob.cpp +++ b/engines/kyra/items_eob.cpp @@ -462,19 +462,18 @@ void EoBCoreEngine::identifyQueuedItems(Item itemQueue) { void EoBCoreEngine::drawItemIconShape(int pageNum, Item itemId, int x, int y) { int icn = _items[itemId].icon; bool applyBluePal = ((_partyEffectFlags & 2) && (_items[itemId].flags & 0x80)) ? true : false; - - memcpy(_tempIconShape, _itemIconShapes[icn], _itemIconShapes[icn][1] * _itemIconShapes[icn][2] * 4 + 20); + const uint8 *ovl = 0; if (applyBluePal) { - if (_flags.gameID == GI_EOB1) { - _screen->replaceShapePalette(_tempIconShape, &_itemsOverlay[icn << 4]); + if (_flags.gameID == GI_EOB1) { + ovl = (_configRenderMode == Common::kRenderCGA) ? _itemsOverlayCGA : &_itemsOverlay[icn << 4]; } else { _screen->setFadeTableIndex(3); _screen->setShapeFadeMode(1, true); } } - _screen->drawShape(pageNum, _tempIconShape, x, y, 0); + _screen->drawShape(pageNum, _itemIconShapes[icn], x, y, 0, ovl ? 2 : 0, ovl); if (applyBluePal) { _screen->setFadeTableIndex(4); diff --git a/engines/kyra/kyra_rpg.cpp b/engines/kyra/kyra_rpg.cpp index 8c9a1ec835..a885eb9e2d 100644 --- a/engines/kyra/kyra_rpg.cpp +++ b/engines/kyra/kyra_rpg.cpp @@ -44,6 +44,7 @@ KyraRpgEngine::KyraRpgEngine(OSystem *system, const GameFlags &flags) : KyraEngi _vmpPtr = 0; _vcnBlocks = 0; _vcfBlocks = 0; + _vcnTransitionMask = 0; _vcnShift = 0; _vcnColTable = 0; _vmpPtr = 0; @@ -126,6 +127,7 @@ KyraRpgEngine::~KyraRpgEngine() { delete[] _vcnColTable; delete[] _vcnBlocks; delete[] _vcfBlocks; + delete[] _vcnTransitionMask; delete[] _vcnShift; delete[] _blockDrawingBuffer; delete[] _sceneWindowBuffer; diff --git a/engines/kyra/kyra_rpg.h b/engines/kyra/kyra_rpg.h index 6a71239250..aec34fc3c9 100644 --- a/engines/kyra/kyra_rpg.h +++ b/engines/kyra/kyra_rpg.h @@ -224,6 +224,7 @@ protected: uint16 *_vmpPtr; uint8 *_vcnBlocks; uint8 *_vcfBlocks; + uint8 *_vcnTransitionMask; uint8 *_vcnShift; uint8 *_vcnColTable; uint16 *_blockDrawingBuffer; diff --git a/engines/kyra/scene_eob.cpp b/engines/kyra/scene_eob.cpp index 2a59a97cc1..5a06fe7977 100644 --- a/engines/kyra/scene_eob.cpp +++ b/engines/kyra/scene_eob.cpp @@ -279,15 +279,51 @@ 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 *v = _screen->getCPagePtr(3); - uint32 tlen = READ_LE_UINT16(v) << 5; - v += 2; + const uint8 *pos = _screen->getCPagePtr(3); + uint32 tlen = READ_LE_UINT16(pos) << 5; + pos += 2; if (!(_flags.gameID == GI_EOB1 && (_configRenderMode == Common::kRenderEGA || _configRenderMode == Common::kRenderCGA))) - memcpy(_vcnColTable, v, 32); - v += 32; + memcpy(_vcnColTable, pos, 32); + pos += 32; delete[] _vcnBlocks; _vcnBlocks = new uint8[tlen]; - memcpy(_vcnBlocks, v, tlen); + + if (_configRenderMode == Common::kRenderCGA) { + uint8 *tmp = _screen->encodeShape(0, 0, 1, 8, false, cgaMapping); + delete[] tmp; + + delete[] _vcnTransitionMask; + _vcnTransitionMask = new uint8[tlen]; + uint8 tblSwitch = 0; + uint8 *dst = _vcnBlocks; + uint8 *dst2 = _vcnTransitionMask; + + while (dst < _vcnBlocks + tlen) { + 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); + *dst++= ((table[pos[1]] & 0x000f) << 4) | ((table[pos[1]] & 0x0f00) >> 8); + + uint8 msk = 0; + if (pos[0] & 0xf0) + msk |= 0x30; + if (pos[0] & 0x0f) + msk |= 0x03; + *dst2++ = msk ^ 0x33; + + msk = 0; + if (pos[1] & 0xf0) + msk |= 0x30; + if (pos[1] & 0x0f) + msk |= 0x03; + *dst2++ = msk ^ 0x33; + + pos += 2; + } + } + } else { + memcpy(_vcnBlocks, pos, tlen); + } } void EoBCoreEngine::loadBlockProperties(const char *mazFile) { @@ -338,7 +374,7 @@ const uint8 *EoBCoreEngine::getBlockFileData(const char *mazFile) { } void EoBCoreEngine::loadDecorations(const char *cpsFile, const char *decFile) { - _screen->loadShapeSetBitmap(cpsFile, 3, 3); + _screen->loadShapeSetBitmap(cpsFile, 5, 3); Common::SeekableReadStream *s = _res->createReadStream(decFile); _levelDecorationDataSize = s->readUint16LE(); diff --git a/engines/kyra/scene_rpg.cpp b/engines/kyra/scene_rpg.cpp index 55d02d8da1..269a5d3461 100644 --- a/engines/kyra/scene_rpg.cpp +++ b/engines/kyra/scene_rpg.cpp @@ -349,15 +349,14 @@ void KyraRpgEngine::drawVcnBlocks() { for (int y = 0; y < 15; y++) { for (int x = 0; x < 22; x++) { bool horizontalFlip = false; - int remainder = 0; - uint16 vcnOffset = *bdb++; + uint16 vcnExtraOffsetWll = 0; int wllVcnOffset = 0; int wllVcnRmdOffset = 0; if (vcnOffset & 0x8000) { // this renders a wall block over the transparent pixels of a floor/ceiling block - remainder = vcnOffset - 0x8000; + vcnExtraOffsetWll = vcnOffset - 0x8000; vcnOffset = 0; wllVcnRmdOffset = _wllVcnOffset; } @@ -388,9 +387,9 @@ void KyraRpgEngine::drawVcnBlocks() { for (int blockY = 0; blockY < 8; blockY++) { src += 3; for (int blockX = 0; blockX < 4; blockX++) { - uint8 t = *src--; - *d++ = _vcnColTable[((t & 0x0f) + wllVcnOffset) | shift]; - *d++ = _vcnColTable[((t >> 4) + wllVcnOffset) | shift]; + uint8 bl = *src--; + *d++ = _vcnColTable[((bl & 0x0f) + wllVcnOffset) | shift]; + *d++ = _vcnColTable[((bl >> 4) + wllVcnOffset) | shift]; } src += 5; d += 168; @@ -398,54 +397,71 @@ void KyraRpgEngine::drawVcnBlocks() { } else { for (int blockY = 0; blockY < 8; blockY++) { for (int blockX = 0; blockX < 4; blockX++) { - uint8 t = *src++; - *d++ = _vcnColTable[((t >> 4) + wllVcnOffset) | shift]; - *d++ = _vcnColTable[((t & 0x0f) + wllVcnOffset) | shift]; + uint8 bl = *src++; + *d++ = _vcnColTable[((bl >> 4) + wllVcnOffset) | shift]; + *d++ = _vcnColTable[((bl & 0x0f) + wllVcnOffset) | shift]; } d += 168; } } d -= 1400; - if (remainder) { + if (vcnExtraOffsetWll) { d -= 8; horizontalFlip = false; - if (remainder & 0x4000) { - remainder &= 0x3fff; + if (vcnExtraOffsetWll & 0x4000) { + vcnExtraOffsetWll &= 0x3fff; horizontalFlip = true; } - shift = _vcnShift ? _vcnShift[remainder] : _blockBrightness; - src = &_vcnBlocks[remainder << 5]; + shift = _vcnShift ? _vcnShift[vcnExtraOffsetWll] : _blockBrightness; + src = &_vcnBlocks[vcnExtraOffsetWll << 5]; + uint8 *maskTable = _vcnTransitionMask ? &_vcnTransitionMask[vcnExtraOffsetWll << 5] : 0; if (horizontalFlip) { for (int blockY = 0; blockY < 8; blockY++) { src += 3; + maskTable += 3; for (int blockX = 0; blockX < 4; blockX++) { - uint8 t = *src--; - uint8 h = _vcnColTable[((t & 0x0f) + wllVcnRmdOffset) | shift]; - uint8 l = _vcnColTable[((t >> 4) + wllVcnRmdOffset) | shift]; - if (h) + uint8 bl = *src--; + uint8 mask = _vcnTransitionMask ? *maskTable-- : 0; + uint8 h = _vcnColTable[((bl & 0x0f) + wllVcnRmdOffset) | shift]; + uint8 l = _vcnColTable[((bl >> 4) + wllVcnRmdOffset) | shift]; + + if (_vcnTransitionMask) + *d = (*d & (mask & 0x0f)) | h; + else if (h) *d = h; d++; - if (l) + + if (_vcnTransitionMask) + *d = (*d & (mask >> 4)) | l; + else if (l) *d = l; d++; } src += 5; + maskTable += 5; d += 168; } } else { for (int blockY = 0; blockY < 8; blockY++) { for (int blockX = 0; blockX < 4; blockX++) { - uint8 t = *src++; - uint8 h = _vcnColTable[((t >> 4) + wllVcnRmdOffset) | shift]; - uint8 l = _vcnColTable[((t & 0x0f) + wllVcnRmdOffset) | shift]; - if (h) + uint8 bl = *src++; + uint8 mask = _vcnTransitionMask ? *maskTable++ : 0; + uint8 h = _vcnColTable[((bl >> 4) + wllVcnRmdOffset) | shift]; + uint8 l = _vcnColTable[((bl & 0x0f) + wllVcnRmdOffset) | shift]; + + if (_vcnTransitionMask) + *d = (*d & (mask >> 4)) | h; + else if (h) *d = h; d++; - if (l) + + if (_vcnTransitionMask) + *d = (*d & (mask & 0x0f)) | l; + else if (l) *d = l; d++; } diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index ebf7835bfd..d394a86f6f 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -159,8 +159,10 @@ bool Screen::init() { // Setup CGA colors (if CGA mode is selected) if (_renderMode == Common::kRenderCGA) { - Palette pal(4); + Palette pal(5); pal.setCGAPalette(1, Palette::kIntensityHigh); + // create additional black color 4 for use with the mouse cursor manager + pal.fill(4, 1, 0); Screen::setScreenPalette(pal); } @@ -1035,6 +1037,8 @@ void Screen::fillRect(int x1, int y1, int x2, int y2, uint8 color, int pageNum, if (_use16ColorMode) { color &= 0x0F; color |= (color << 4); + } else if (_renderMode == Common::kRenderCGA) { + color &= 3; } if (xored) { @@ -1112,6 +1116,8 @@ void Screen::drawLine(bool vertical, int x, int y, int length, int color) { if (_use16ColorMode) { color &= 0x0F; color |= (color << 4); + } else if (_renderMode == Common::kRenderCGA) { + color &= 3; } if (vertical) { @@ -2086,17 +2092,16 @@ void Screen::decodeFrame1(const uint8 *src, uint8 *dst, uint32 size) { while (dst < dstEnd) { code = decodeEGAGetCode(src, nib); - last = code & 0xff; uint8 cmd = code >> 8; if (cmd--) { - code = (cmd << 8) | last; + code = (cmd << 8) | (code & 0xff); uint8 *tmpDst = dst; - last = *dst; if (code < numPatterns) { const uint8 *tmpSrc = patterns[code].pos; countPrev = patterns[code].len; + last = *tmpSrc; for (int i = 0; i < countPrev; i++) *dst++ = *tmpSrc++; @@ -2118,7 +2123,7 @@ void Screen::decodeFrame1(const uint8 *src, uint8 *dst, uint32 size) { count = countPrev; } else { - *dst++ = last; + *dst++ = last = (code & 0xff); if (numPatterns < 3840) { patterns[numPatterns].pos = dstPrev; @@ -3626,7 +3631,7 @@ void Palette::loadEGAPalette(Common::ReadStream &stream, int startIndex, int col } void Palette::setCGAPalette(int palIndex, CGAIntensity intensity) { - assert(_numColors == _cgaNumColors); + assert(_numColors >= _cgaNumColors); assert(!(palIndex & ~1)); memcpy(_palData, _cgaColors[palIndex * 2 + intensity], _numColors * 3); } diff --git a/engines/kyra/screen_eob.cpp b/engines/kyra/screen_eob.cpp index aa94114dfc..8721c2cc02 100644 --- a/engines/kyra/screen_eob.cpp +++ b/engines/kyra/screen_eob.cpp @@ -48,7 +48,8 @@ Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system, _dsTempPage = 0; _dsDiv = 0; _dsRem = 0; - _dsScaleTmp = 0; + _dsScaleTrans = 0; + _cgaScaleTable = 0; _gfxMaxY = 0; _egaColorMap = 0; _egaPixelValueTable = 0; @@ -60,6 +61,7 @@ Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system, Screen_EoB::~Screen_EoB() { delete[] _fadeData; delete[] _dsTempPage; + delete[] _cgaScaleTable; delete[] _egaColorMap; delete[] _egaPixelValueTable; delete[] _cgaDitheringTables[0]; @@ -71,7 +73,7 @@ bool Screen_EoB::init() { if (Screen::init()) { int temp; _gfxMaxY = _vm->staticres()->loadRawData(kEoBBaseExpObjectY, temp); - + if (_renderMode != Common::kRenderCGA && _renderMode != Common::kRenderEGA) _fadeData = _vm->resource()->fileData("FADING.DAT", 0); @@ -86,7 +88,8 @@ bool Screen_EoB::init() { } } - _dsTempPage = new uint8[6000]; + _dsTempPage = new uint8[12000]; + if (_renderMode == Common::kRenderEGA) { _egaColorMap = new uint8[256]; _egaPixelValueTable = new uint8[256]; @@ -97,18 +100,24 @@ bool Screen_EoB::init() { if (_vm->game() == GI_EOB2) _useHiResEGADithering = true; + } else if (_renderMode == Common::kRenderCGA) { _cgaMappingDefault = _vm->staticres()->loadRawData(kEoB1CgaMappingDefault, temp); _cgaDitheringTables[0] = new uint16[256]; memset(_cgaDitheringTables[0], 0, 256 * sizeof(uint16)); _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++) - WRITE_BE_UINT16(&_cgaDrawCharDitheringTable[i], (bits[i & 3] << 8) | (bits[(i >> 2) & 3] << 12) | (bits[(i >> 4) & 3] << 0) | (bits[(i >> 6) & 3] << 4)); + _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++) + _cgaScaleTable[i] = ((i & 0xf0) >> 2) | (i & 0x03); } return true; @@ -126,15 +135,43 @@ void Screen_EoB::clearCurDim() { } void Screen_EoB::setMouseCursor(int x, int y, const byte *shape) { + setMouseCursor(x, y, shape, 0); +} + +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); + drawShape(8, shape, 0, 0, 0, 2, ovl); CursorMan.showMouse(false); copyRegionToBuffer(8, 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 + // go over the transparency mask again and turn the black pixels to color 4. + if (_renderMode == Common::kRenderCGA) { + const uint8 *maskTbl = shape + 4 + ((mouseW * mouseH) >> 2); + uint8 *dst = cursor; + uint8 trans = 0; + uint8 shift = 6; + + uint16 mH = mouseH; + while (mH--) { + uint16 mW = mouseW; + while (mW--) { + if (shift == 6) + trans = *maskTbl++; + if (!*dst && !((trans >> shift) & 3)) + *dst = 4; + dst++; + shift = (shift - 2) & 7; + } + } + } + CursorMan.replaceCursor(cursor, mouseW, mouseH, x, y, _cursorColorKey); if (isMouseVisible()) CursorMan.showMouse(true); @@ -215,13 +252,14 @@ void Screen_EoB::convertPage(int srcPage, int dstPage, const uint8 *cgaMapping) return; if (_renderMode == Common::kRenderCGA) { - generateCGADitheringTables(cgaMapping); + if (cgaMapping) + generateCGADitheringTables(cgaMapping); uint16 *d = (uint16*)dst; - uint8 tblSwitch = 0; + 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[0] & 0x0f) << 4) | (src[1] & 0x0f)]; + *d++ = table[((src[1] & 0x0f) << 4) | (src[0] & 0x0f)]; src += 2; } } @@ -301,14 +339,53 @@ void Screen_EoB::setScreenPalette(const Palette &pal) { } } -uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool no4bitEncoding, const uint8 *cgaMapping) { +uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool encode8bit, const uint8 *cgaMapping) { uint8 *shp = 0; uint16 shapesize = 0; - uint8 *srcPage = getPagePtr(_curPage | 1) + y * 320 + (x << 3); - uint8 *src = srcPage; + uint8 *srcLineStart = getPagePtr(_curPage | 1) + y * 320 + (x << 3); + uint8 *src = srcLineStart; + + if (_renderMode == Common::kRenderCGA) { + if (cgaMapping) + generateCGADitheringTables(cgaMapping); + shapesize = h * (w << 2) + 4; + shp = new uint8[shapesize]; + memset(shp, 0, shapesize); + uint8 *dst = shp; + + *dst++ = 4; + *dst++ = (h & 0xff); + *dst++ = (w & 0xff); + *dst++ = (h & 0xff); + + uint8 *dst2 = dst + (h * (w << 1)); + + uint8 tblSwitch = 0; + uint16 h1 = h; + while (h1--) { + uint16 w1 = w << 1; + const uint16 *table = _cgaDitheringTables[(tblSwitch++) & 1]; + + while (w1--) { + uint16 p0 = table[((src[1] & 0x0f) << 4) | (src[0] & 0x0f)]; + uint16 p1 = table[((src[3] & 0x0f) << 4) | (src[2] & 0x0f)]; + + *dst++ = ((p0 & 0x0003) << 6) | ((p0 & 0x0300) >> 4) | ((p1 & 0x0003) << 2) | ((p1 & 0x0300) >> 8); + + uint8 msk = 0; + for (int i = 0; i < 4; i++) { + if (!src[3 - i]) + msk |= (3 << (i << 1)); + } + *dst2++ = msk; + src += 4; + } + srcLineStart += SCREEN_W; + src = srcLineStart; + } - if (no4bitEncoding) { + } else if (encode8bit) { uint16 h1 = h; while (h1--) { uint8 *lineEnd = src + (w << 3); @@ -326,8 +403,8 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool no4b shapesize++; } while (src != lineEnd); - srcPage += 320; - src = srcPage; + srcLineStart += SCREEN_W; + src = srcLineStart; } shapesize += 4; @@ -336,13 +413,13 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool no4b memset(shp, 0, shapesize); uint8 *dst = shp; - *dst++ = 0; + *dst++ = 8; *dst++ = (h & 0xff); *dst++ = (w & 0xff); *dst++ = (h & 0xff); - srcPage = getPagePtr(_curPage | 1) + y * 320 + (x << 3); - src = srcPage; + srcLineStart = getPagePtr(_curPage | 1) + y * 320 + (x << 3); + src = srcLineStart; h1 = h; while (h1--) { @@ -367,8 +444,8 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool no4b *dst++ = val; } while (src != lineEnd); - srcPage += 320; - src = srcPage; + srcLineStart += SCREEN_W; + src = srcLineStart; } } else { @@ -381,17 +458,14 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool no4b memset(shp, 0, shapesize); uint8 *dst = shp; - *dst++ = 1; + *dst++ = 2; *dst++ = (h & 0xff); *dst++ = (w & 0xff); *dst++ = (h & 0xff); memset(dst, 0xff, 0x10); uint8 *pal = dst; - dst += 0x10; - - srcPage = getPagePtr(_curPage | 1) + y * 320 + (x << 3); - src = srcPage; + dst += 16; nib = col = 0; uint16 h1 = h; @@ -411,14 +485,13 @@ uint8 *Screen_EoB::encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool no4b } } - if (++nib & 1) { + if (++nib & 1) *dst = c << 4; - } else { + else *dst++ |= c; - } } - srcPage += 320; - src = srcPage; + srcLineStart += SCREEN_W; + src = srcLineStart; } delete [] colorMap; } @@ -449,10 +522,11 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int16 dX = x - (_dsX1 << 3); int16 dY = y; int16 dW = _dsX2 - _dsX1; - uint8 flag = *src++; + uint8 pixelsPerByte = *src++ ; uint16 dH = *src++; uint16 width = (*src++) << 3; + uint16 transOffset = (pixelsPerByte == 4) ? (dH * width) >> 2 : 0; src++; int rX = x; @@ -465,148 +539,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int pixelStep = (flags & 1) ? -1 : 1; - if (flag) { - const uint8 *pal = ovl ? ovl : src; - src += 16; - - if (d < 0) { - d = -d; - if (d >= dH) - return; - src += (d * (width >> 1)); - d = dY + dH - _dsY1; - if (d >= 0) { - dH = d; - dY = _dsY1; - d = _dsY2 - dY; - } - } else { - d = _dsY2 - dY; - } - - if (d < 1) - return; - - if (d < dH) - dH = d; - - int16 cnt1 = 0; - int16 cnt2 = 0; - int16 dXbit1 = dX & 1; - - if (dX < 0) { - width += dX; - d = -dX; - if (flags & 1) - src -= (d >> 1); - else - src += (d >> 1); - - if (d >= w2) - return; - - dX = 0; - cnt1++; - } - - d = (dW << 3) - dX; - - if (d < 1) - return; - - if (d < width) { - width = d; - cnt2++; - } - - dst += (dY * 320 + dX); - - if (pageNum == 0 || pageNum == 1) - addDirtyRect(rX, rY, rW, rH); - - int w3 = w2; - dY = 320 - width; - width >>= 1; - w2 >>= 1; - if (flags & 1) - src += (w2 - 1); - - int16 w1shr = width; - - if (cnt1 && (dXbit1 & 1)) { - w1shr++; - w2++; - if (!cnt2) - dY += 2; - } - - if (cnt2 && (dXbit1 & 1)) - w1shr++; - - int lineSrcStep = (w2 - w1shr); - if (flags & 1) - lineSrcStep = w3 - lineSrcStep; - - while (dH--) { - int16 hpos = width; - uint8 col = 0; - uint8 b = 0; - uint8 nextloop = 0; - - if (cnt1 && dXbit1) { - if (!hpos) - return; - b = *src; - src += pixelStep; - nextloop = 2; - } else { - nextloop = hpos ? 1 : 3; - } - - while (nextloop) { - switch (nextloop) { - case 1: - b = *src; - src += pixelStep; - col = pal[(flags & 1) ? (b & 0x0f) : (b >> 4)]; - if (col) - drawShapeSetPixel(dst, col); - dst++; - - case 2: - col = pal[(flags & 1) ? (b >> 4) : (b & 0x0f)]; - - if (!col) { - nextloop = 4; - break; - } - - drawShapeSetPixel(dst++, col); - nextloop = --hpos ? 1 : 3; - break; - - case 3: - if (cnt2 && dXbit1) { - col = pal[(flags & 1) ? (*src & 0x0f) : (*src >> 4)]; - src += pixelStep; - if (col) - drawShapeSetPixel(dst, col); - dst++; - } - - src += lineSrcStep; - dst += dY; - nextloop = 0; - break; - - case 4: - dst++; - nextloop = --hpos ? 1 : 3; - break; - } - } - } - } else { + if (pixelsPerByte == 8) { uint16 marginLeft = 0; uint16 marginRight = 0; @@ -740,6 +673,127 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, if (flags & 1) src = src2 + 1; } + } else { + const uint8 *pal = 0; + uint8 cgaPal[4]; + memset(cgaPal, 0, 4); + + if (pixelsPerByte == 2) { + pal = ovl ? ovl : src; + src += 16; + } else { + static const uint8 cgaDefOvl[] = { 0x00, 0x55, 0xaa, 0xff }; + pal = ovl ? ovl : cgaDefOvl; + for (int i = 0; i < 4; i++) + cgaPal[i] = pal[i] & 3; + pal = cgaPal; + } + + if (d < 0) { + d = -d; + if (d >= dH) + return; + src += (d * (width / pixelsPerByte)); + d = dY + dH - _dsY1; + if (d >= 0) { + dH = d; + dY = _dsY1; + d = _dsY2 - dY; + } + } else { + d = _dsY2 - dY; + } + + if (d < 1) + return; + + if (d < dH) + dH = d; + + bool trimL = false; + uint8 dXbitAlign = dX & (pixelsPerByte - 1); + + if (dX < 0) { + width += dX; + d = -dX; + if (flags & 1) + src -= (d / pixelsPerByte); + else + src += (d / pixelsPerByte); + + if (d >= w2) + return; + + dX = 0; + trimL = true; + } + + d = (dW << 3) - dX; + + if (d < 1) + return; + + if (d < width) + width = d; + + dst += (dY * 320 + dX); + + if (pageNum == 0 || pageNum == 1) + addDirtyRect(rX, rY, rW, rH); + + int pitch = 320 - width; + int16 lineSrcStep = (w2 - width) / pixelsPerByte; + uint8 lineSrcStepRemainder = (w2 - width) % pixelsPerByte; + + w2 /= pixelsPerByte; + if (flags & 1) + src += (w2 - 1); + + uint8 pixelPacking = 8 / pixelsPerByte; + uint8 pixelPackingMask = 0; + + for (int i = 0; i < pixelPacking; i++) + pixelPackingMask |= (1 << i); + + if (trimL && (dXbitAlign > lineSrcStepRemainder)) + lineSrcStep--; + + uint8 bitShDef = 8 - pixelPacking; + if (flags & 1) { + lineSrcStep = (w2 << 1) - lineSrcStep; + bitShDef = 0; + } + + uint8 bitShLineStart = bitShDef; + if (trimL) + bitShLineStart -= (dXbitAlign * pixelStep * pixelPacking); + + while (dH--) { + int16 wd = width; + uint8 in = 0; + uint8 trans = 0; + uint8 shift = bitShLineStart; + uint8 shSwtch = bitShLineStart; + + while (wd--) { + if (shift == shSwtch) { + in = *src; + trans = src[transOffset]; + src += pixelStep; + shSwtch = bitShDef; + } + if (pixelsPerByte == 2) { + if (pal[(in >> shift) & pixelPackingMask]) + drawShapeSetPixel(dst, pal[(in >> shift) & pixelPackingMask]); + } else { + *dst = (*dst & ((trans >> shift) & (pixelPackingMask))) | pal[(in >> shift) & pixelPackingMask]; + } + dst++; + shift = (shift - (pixelStep * pixelPacking) & 7); + } + src += lineSrcStep; + dst += pitch; + } } } @@ -753,69 +807,75 @@ const uint8 *Screen_EoB::scaleShape(const uint8 *shapeData, int steps) { } const uint8 *Screen_EoB::scaleShapeStep(const uint8 *shp) { - uint8 *d = _dsTempPage; - *d++ = *shp++; + uint8 *dst = (shp != _dsTempPage) ? _dsTempPage : _dsTempPage + 6000; + uint8 *d = dst; + uint8 pixelsPerByte = *d++ = *shp++; + assert (pixelsPerByte > 1); - uint16 h = (*shp++) + 1; + uint16 h = shp[0] + 1; d[0] = d[2] = (h << 1) / 3; - d++; - uint16 w = *shp++; - uint16 w2 = w << 2; + uint16 w = shp[1]; + uint16 w2 = (w << 3) / pixelsPerByte; uint16 t = ((w << 1) % 3) ? 1 : 0; - *d++ = ((w << 1) / 3) + t; - - shp++; - d++; - - int i = 0; - while (i < 16) { - if (!shp[i]) { - i = -i; - break; + d[1] = ((w << 1) / 3) + t; + + uint32 transOffsetSrc = (pixelsPerByte == 4) ? (shp[0] * shp[1]) << 1 : 0; + uint32 transOffsetDst = (pixelsPerByte == 4) ? (d[0] * d[1]) << 1 : 0; + shp += 3; + d += 3; + + if (pixelsPerByte == 2) { + int i = 0; + while (i < 16) { + if (!shp[i]) { + i = -i; + break; + } + i++; } - i++; - } - if (i >= 0) - i = 0; - else - i = -i; + if (i >= 0) + i = 0; + else + i = -i; - _dsScaleTmp = (i << 4) | (i & 0x0f); - for (int ii = 0; ii < 16; ii++) - *d++ = *shp++; + _dsScaleTrans = (i << 4) | (i & 0x0f); + for (int ii = 0; ii < 16; ii++) + *d++ = *shp++; + } _dsDiv = w2 / 3; _dsRem = w2 % 3; while (--h) { - scaleShapeProcessLine(d, shp); + if (pixelsPerByte == 2) + scaleShapeProcessLine4Bit(d, shp); + else + scaleShapeProcessLine2Bit(d, shp, transOffsetDst, transOffsetSrc); if (!--h) break; - scaleShapeProcessLine(d, shp); + if (pixelsPerByte == 2) + scaleShapeProcessLine4Bit(d, shp); + else + scaleShapeProcessLine2Bit(d, shp, transOffsetDst, transOffsetSrc); if (!--h) break; shp += w2; } - return (const uint8 *)_dsTempPage; + return (const uint8*)dst; } -void Screen_EoB::replaceShapePalette(uint8 *shp, const uint8 *pal) { - if (*shp != 1) - return; - shp += 4; - memcpy(shp, pal, 16); -} +const uint8 *Screen_EoB::generateShapeOverlay(const uint8 *shp, int paletteOverlayIndex) { + if (*shp != 2) + return 0; -void Screen_EoB::applyShapeOverlay(uint8 *shp, int ovlIndex) { - if (*shp != 1) - return; shp += 4; - uint8 *ovl = getFadeTable(ovlIndex); + uint8 *ovl = getFadeTable(paletteOverlayIndex); for (int i = 0; i < 16; i++) - shp[i] = ovl[shp[i]]; + _shapeOverlay[i] = ovl[shp[i]]; + return _shapeOverlay; } void Screen_EoB::setShapeFrame(int x1, int y1, int x2, int y2) { @@ -1187,6 +1247,10 @@ uint8 *Screen_EoB::getFadeTable(int index) { return (index >= 0 && index < 5) ? &_fadeData[index << 8] : 0; } +const uint16 *Screen_EoB::getCGADitheringTable(int index) { + return !(index & ~1) ? _cgaDitheringTables[index] : 0; +} + void Screen_EoB::drawShapeSetPixel(uint8 *dst, uint8 c) { if (_shapeFadeMode[0]) { if (_shapeFadeMode[1]) { @@ -1206,7 +1270,35 @@ void Screen_EoB::drawShapeSetPixel(uint8 *dst, uint8 c) { *dst = c; } -void Screen_EoB::scaleShapeProcessLine(uint8 *&dst, const uint8 *&src) { +void Screen_EoB::scaleShapeProcessLine2Bit(uint8 *&shpDst, const uint8 *&shpSrc, uint32 transOffsetDst, uint32 transOffsetSrc) { + for (int i = 0; i < _dsDiv; i++) { + shpDst[0] = (_cgaScaleTable[shpSrc[0]] << 2) | (shpSrc[1] >> 6); + shpDst[1] = ((shpSrc[1] & 0x0f) << 4) | ((shpSrc[2] >> 2) & 0x0f); + shpDst[transOffsetDst] = (_cgaScaleTable[shpSrc[transOffsetSrc]] << 2) | (shpSrc[transOffsetSrc + 1] >> 6); + shpDst[transOffsetDst + 1] = ((shpSrc[transOffsetSrc + 1] & 0x0f) << 4) | ((shpSrc[transOffsetSrc + 2] >> 2) & 0x0f); + shpSrc += 3; + shpDst += 2; + } + + if (_dsRem == 1) { + shpDst[0] = _cgaScaleTable[shpSrc[0]] << 2; + shpDst[1] = 0; + shpDst[transOffsetDst] = (_cgaScaleTable[shpSrc[transOffsetSrc]] << 2) | 3; + shpDst[transOffsetDst + 1] = 0xff; + shpSrc++; + shpDst += 2; + + } else if (_dsRem == 2) { + shpDst[0] = (_cgaScaleTable[shpSrc[0]] << 2) | (shpSrc[1] >> 6); + shpDst[1] = (shpSrc[1] & 0x3f) << 2; + shpDst[transOffsetDst] = (_cgaScaleTable[shpSrc[transOffsetSrc]] << 2) | (shpSrc[transOffsetSrc + 1] >> 6); + shpDst[transOffsetDst + 1] = ((shpSrc[transOffsetSrc + 1] & 0x3f) << 2) | 3; + shpSrc += 2; + shpDst += 2; + } +} + +void Screen_EoB::scaleShapeProcessLine4Bit(uint8 *&dst, const uint8 *&src) { for (int i = 0; i < _dsDiv; i++) { *dst++ = *src++; *dst++ = (READ_BE_UINT16(src) >> 4) & 0xff; @@ -1215,13 +1307,13 @@ void Screen_EoB::scaleShapeProcessLine(uint8 *&dst, const uint8 *&src) { if (_dsRem == 1) { *dst++ = *src++; - *dst++ = _dsScaleTmp; + *dst++ = _dsScaleTrans; } else if (_dsRem == 2) { *dst++ = (src[0] & 0xf0) | (src[1] >> 4); src += 2; - *dst++ = _dsScaleTmp; - *dst++ = _dsScaleTmp; - *dst++ = _dsScaleTmp; + *dst++ = _dsScaleTrans; + *dst++ = _dsScaleTrans; + *dst++ = _dsScaleTrans; } } @@ -1233,8 +1325,8 @@ bool Screen_EoB::posWithinRect(int posX, int posY, int x1, int y1, int x2, int y void Screen_EoB::generateCGADitheringTables(const uint8 *mappingData) { for (int i = 0; i < 256; i++) { - WRITE_BE_UINT16(&_cgaDitheringTables[0][i], (mappingData[i >> 4] << 8) | mappingData[(i & 0x0f) + 16]); - WRITE_BE_UINT16(&_cgaDitheringTables[1][i], (mappingData[(i >> 4) + 16] << 8) | mappingData[i & 0x0f]); + _cgaDitheringTables[0][i] = (mappingData[(i >> 4) + 16] << 8) | mappingData[i & 0x0f]; + _cgaDitheringTables[1][i] = (mappingData[i >> 4] << 8) | mappingData[(i & 0x0f) + 16]; } } @@ -1406,7 +1498,7 @@ void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const { uint8 in = s | last; uint16 cmp1 = 0; uint16 cmp2 = 0; - + if (color1) { in &= m; cmp1 = _cgaDitheringTable[in]; @@ -1418,18 +1510,18 @@ void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch) const { } uint16 cDst = 0; - uint8 sh = 14; + uint8 sh = 6; for (int i = 0; i < _width; i++) { cDst |= ((dst[i] & 3) << sh); - sh -= 2; + sh = (sh - 2) & 0x0f; } uint16 out = (~(cmp1 | cmp2) & cDst) | (cmp1 & cgaMask1) | (cmp2 & cgaMask2); - sh = 14; + sh = 6; for (int i = 0; i < _width; i++) { *dst++ = (out >> sh) & 3; - sh -= 2; + sh = (sh - 2) & 0x0f; } last = s; diff --git a/engines/kyra/screen_eob.h b/engines/kyra/screen_eob.h index 1b55806b8b..dc6c4b200f 100644 --- a/engines/kyra/screen_eob.h +++ b/engines/kyra/screen_eob.h @@ -41,6 +41,7 @@ public: void clearCurDim(); void setMouseCursor(int x, int y, const byte *shape); + void setMouseCursor(int x, int y, const byte *shape, const uint8 *ovl); void loadFileDataToPage(Common::SeekableReadStream *s, int pageNum, uint32 size); @@ -52,12 +53,11 @@ public: void setScreenPalette(const Palette &pal); - uint8 *encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool no4bitEncoding = false, const uint8 *cgaMapping = 0); + uint8 *encodeShape(uint16 x, uint16 y, uint16 w, uint16 h, bool encode8bit = false, const uint8 *cgaMapping = 0); void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd = -1, int flags = 0, ...); const uint8 *scaleShape(const uint8 *shapeData, int blockDistance); const uint8 *scaleShapeStep(const uint8 *shp); - void replaceShapePalette(uint8 *shp, const uint8 *pal); - void applyShapeOverlay(uint8 *shp, int ovlIndex); + const uint8 *generateShapeOverlay(const uint8 *shp, int paletteOverlayIndex); void setShapeFrame(int x1, int y1, int x2, int y2); void setShapeFadeMode (uint8 i, bool b); @@ -75,15 +75,18 @@ public: void setFadeTableIndex(int index); void createFadeTable(uint8 *palData, uint8 *dst, uint8 rootColor, uint8 weight); uint8 *getFadeTable(int index); + const uint16 *getCGADitheringTable(int index); private: void drawShapeSetPixel(uint8 *dst, uint8 c); - void scaleShapeProcessLine(uint8 *&dst, const uint8 *&src); + 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 generateCGADitheringTables(const uint8 *mappingData); - int _dsDiv, _dsRem, _dsScaleTmp; + int _dsDiv, _dsRem, _dsScaleTrans; + uint8 *_cgaScaleTable; int16 _gfxX, _gfxY; uint8 _gfxCol; const uint8 *_gfxMaxY; @@ -93,12 +96,13 @@ private: uint16 _shapeFadeInternal; uint8 *_fadeData; int _fadeDataIndex; + uint8 _shapeOverlay[16]; uint8 *_dsTempPage; uint16 *_cgaDitheringTables[2]; const uint8 *_cgaMappingDefault; - + uint8 *_egaColorMap; uint8 *_egaPixelValueTable; bool _useHiResEGADithering; diff --git a/engines/kyra/sequences_eob.cpp b/engines/kyra/sequences_eob.cpp index 195c44ea2a..aa8d18fe77 100644 --- a/engines/kyra/sequences_eob.cpp +++ b/engines/kyra/sequences_eob.cpp @@ -1099,6 +1099,7 @@ void EoBEngine::seq_xdeath() { _screen->loadShapeSetBitmap("XDEATH3", 5, 3); shapes2 = _screen->encodeShape(22, 0, 16, 95, true, _cgaMappingDefault); _screen->loadEoBBitmap("XDEATH1", _cgaMappingDefault, 5, 3, -1); + _screen->convertPage(3, 2, _cgaMappingDefault); _screen->setCurPage(0); for (int i = 0; i < 10; i++) { diff --git a/engines/kyra/sprites_eob.cpp b/engines/kyra/sprites_eob.cpp index 9e450a5ac7..40fc7c14e9 100644 --- a/engines/kyra/sprites_eob.cpp +++ b/engines/kyra/sprites_eob.cpp @@ -342,9 +342,9 @@ void EoBCoreEngine::drawMonsterShape(const uint8 *shape, int x, int y, int flipp uint8 *ovl = 0; if (flags & 2) - ovl = _monsterOvl1; + ovl = _monsterFlashOverlay; else if (_flags.gameID == GI_EOB2 && flags & 0x20) - ovl = _monsterOvl2; + ovl = _monsterStoneOverlay; else if (palIndex != -1) ovl = _monsterPalettes[palIndex]; diff --git a/engines/kyra/staticres_eob.cpp b/engines/kyra/staticres_eob.cpp index 5e28757978..7a5012f117 100644 --- a/engines/kyra/staticres_eob.cpp +++ b/engines/kyra/staticres_eob.cpp @@ -198,6 +198,10 @@ const uint8 EoBCoreEngine::_charClassModifier[] = { 0x00, 0x00, 0x02 }; +const uint8 EoBCoreEngine::_itemsOverlayCGA[] = { + 0x00, 0x55, 0x55, 0xFF +}; + const uint8 EoBCoreEngine::_teleporterShapeDefs[] = { 0x0C, 0x58, 0x02, 0x0E, 0x0C, 0x67, 0x01, 0x07, @@ -1181,11 +1185,16 @@ void EoBEngine::initSpells() { } } -const KyraRpgGUISettings EoBEngine::_guiSettings = { +const KyraRpgGUISettings EoBEngine::_guiSettingsVGA = { { 9, 15, 95, 9, 7, { 285, 139 }, { 189, 162 }, { 31, 31 } }, { 135, 130, 132, 133, 133, 17, 23, 20, 184, 177, 180, 184, 177, 180 } }; +const KyraRpgGUISettings EoBEngine::_guiSettingsEGA = { + { 9, 15, 95, 9, 7, { 285, 139 }, { 189, 162 }, { 31, 31 } }, + { 13, 9, 2, 133, 2, 6, 13, 8, 13, 15, 14, 13, 15, 14 } +}; + const uint8 EoBEngine::_egaDefaultPalette[] = { 0, 5, 3, 2, 10, 14, 12, 6, 4, 11, 9, 1, 0, 8, 7, 15 }; |