aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra
diff options
context:
space:
mode:
authorathrxx2012-02-13 17:04:05 +0100
committerathrxx2012-02-21 21:48:41 +0100
commit151d314912b08d7d598a3995524d89c8b4ab0371 (patch)
tree3900afdabb806c3fb6e46c947c672e369eeaf952 /engines/kyra
parent86a817beb5eef248c5f5e28f18133db802a59c2e (diff)
downloadscummvm-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.cpp5
-rw-r--r--engines/kyra/eob.h3
-rw-r--r--engines/kyra/eobcommon.cpp34
-rw-r--r--engines/kyra/eobcommon.h6
-rw-r--r--engines/kyra/gui_eob.cpp89
-rw-r--r--engines/kyra/items_eob.cpp9
-rw-r--r--engines/kyra/kyra_rpg.cpp2
-rw-r--r--engines/kyra/kyra_rpg.h1
-rw-r--r--engines/kyra/scene_eob.cpp50
-rw-r--r--engines/kyra/scene_rpg.cpp64
-rw-r--r--engines/kyra/screen.cpp17
-rw-r--r--engines/kyra/screen_eob.cpp540
-rw-r--r--engines/kyra/screen_eob.h16
-rw-r--r--engines/kyra/sequences_eob.cpp1
-rw-r--r--engines/kyra/sprites_eob.cpp4
-rw-r--r--engines/kyra/staticres_eob.cpp11
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
};