From 69f2e0caaa3b7257318f2e9943d233da45bfab80 Mon Sep 17 00:00:00 2001 From: athrxx Date: Tue, 26 Mar 2019 22:37:50 +0100 Subject: KYRA: (EOB2/Amiga) - fix ingame colors --- engines/kyra/engine/darkmoon.cpp | 3 ++ engines/kyra/engine/eobcommon.cpp | 17 ++++++++- engines/kyra/engine/scene_eob.cpp | 10 ++--- engines/kyra/engine/scene_rpg.cpp | 12 +++--- engines/kyra/engine/sprites_eob.cpp | 3 +- engines/kyra/graphics/screen.cpp | 12 ++++-- engines/kyra/graphics/screen.h | 1 + engines/kyra/graphics/screen_eob.cpp | 57 +++++++++++++++++++++++++--- engines/kyra/graphics/screen_eob.h | 7 ++++ engines/kyra/gui/gui_eob.cpp | 13 +++++-- engines/kyra/script/script_eob.cpp | 3 ++ engines/kyra/sequence/sequences_darkmoon.cpp | 3 +- 12 files changed, 116 insertions(+), 25 deletions(-) diff --git a/engines/kyra/engine/darkmoon.cpp b/engines/kyra/engine/darkmoon.cpp index c7a91c7fd5..8d621b9bc9 100644 --- a/engines/kyra/engine/darkmoon.cpp +++ b/engines/kyra/engine/darkmoon.cpp @@ -153,6 +153,9 @@ void DarkMoonEngine::updateUsedCharacterHandItem(int charIndex, int slot) { } void DarkMoonEngine::generateMonsterPalettes(const char *file, int16 monsterIndex) { + if (_flags.platform == Common::kPlatformAmiga) + return; + int cp = _screen->setCurPage(2); _screen->loadShapeSetBitmap(file, 3, 3); uint8 tmpPal[16]; diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp index 1c75c78d70..798bfb6a93 100644 --- a/engines/kyra/engine/eobcommon.cpp +++ b/engines/kyra/engine/eobcommon.cpp @@ -1639,12 +1639,15 @@ void EoBCoreEngine::drawSequenceBitmap(const char *file, int destRect, int x1, i static const uint8 frameH[] = { 96, 121 }; int page = ((flags & 2) || destRect) ? 0 : 6; + int amigaPalIndex = (x1 ? 1 : 0) + (y1 ? 2 : 0) + 1; if (scumm_stricmp(_dialogueLastBitmap, file)) { _screen->clearPage(2); if (!destRect) { if (!(flags & 1)) { _screen->loadEoBBitmap("BORDER", 0, 3, 3, 2); + if (_flags.platform == Common::kPlatformAmiga) + _screen->copyRegion(0, 0, 0, 0, 320, 122, 2, 0, Screen::CR_NO_P_CHECK); _screen->copyRegion(0, 0, 0, 0, 184, 121, 2, page, Screen::CR_NO_P_CHECK); } else { _screen->copyRegion(0, 0, 0, 0, 184, 121, 0, page, Screen::CR_NO_P_CHECK); @@ -1658,13 +1661,25 @@ void EoBCoreEngine::drawSequenceBitmap(const char *file, int destRect, int x1, i strcpy(_dialogueLastBitmap, file); } + if (_flags.platform == Common::kPlatformAmiga) { + int cp = _screen->setCurPage(0); + if (!_dialogueFieldAmiga) + gui_drawDialogueBox(); + _screen->drawClippedLine(0, 120, 319, 120, 9); + _screen->drawClippedLine(0, 121, 319, 121, guiSettings()->colors.fill); + _screen->setPagePixel(0, 319, 121, 9); + _screen->setCurPage(cp); + _screen->setupDualPalettesSplitScreen(_screen->getPalette(amigaPalIndex), _screen->getPalette(7)); + _dialogueFieldAmiga = true; + } + if (flags & 2) _screen->crossFadeRegion(x1 << 3, y1, frameX[destRect] << 3, frameY[destRect], frameW[destRect] << 3, frameH[destRect], 2, page); else _screen->copyRegion(x1 << 3, y1, frameX[destRect] << 3, frameY[destRect], frameW[destRect] << 3, frameH[destRect], 2, page, Screen::CR_NO_P_CHECK); if (page == 6) - _screen->copyRegion(0, 0, 0, 0, 184, 121, 6, 0, Screen::CR_NO_P_CHECK); + _screen->copyRegion(0, 0, 0, 0, 184, (_flags.platform == Common::kPlatformAmiga) ? 110 : 121, 6, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); } diff --git a/engines/kyra/engine/scene_eob.cpp b/engines/kyra/engine/scene_eob.cpp index 9a2f4e2f93..7f3c464939 100644 --- a/engines/kyra/engine/scene_eob.cpp +++ b/engines/kyra/engine/scene_eob.cpp @@ -96,7 +96,7 @@ void EoBCoreEngine::loadLevel(int level, int sub) { loadVcnData(gfxFile.c_str(), (_flags.gameID == GI_EOB1 && _flags.platform == Common::kPlatformDOS) ? _cgaMappingLevel[_cgaLevelMappingIndex[level - 1]] : 0); _screen->loadEoBBitmap("INVENT", _cgaMappingInv, 5, 3, 2); - if (_flags.platform == Common::kPlatformAmiga) + if (_flags.platform == Common::kPlatformAmiga && _flags.gameID == GI_EOB1) _screen->getPalette(0).copy(_screen->getPalette(1), 1, 5, 1); delayUntil(end); @@ -190,8 +190,8 @@ Common::String EoBCoreEngine::initLevelData(int sub) { _screen->enableShapeBackgroundFading(false); } - if (_flags.platform != Common::kPlatformAmiga && (_flags.gameID == GI_EOB2 || _configRenderMode != Common::kRenderEGA)) - _screen->loadPalette(tmpStr.c_str(), _screen->getPalette(0)); + if (_flags.gameID == GI_EOB2 || (_flags.platform != Common::kPlatformAmiga && _configRenderMode != Common::kRenderCGA && _configRenderMode != Common::kRenderEGA)) + _screen->loadPalette(tmpStr.c_str(), _screen->getPalette(_flags.platform == Common::kPlatformAmiga ? 6 : 0)); if (_flags.platform == Common::kPlatformFMTowns) { uint16 *src = (uint16*)_screen->getPalette(0).getData(); @@ -368,7 +368,7 @@ void EoBCoreEngine::loadVcnData(const char *file, const uint8 *cgaMapping) { } } } else { - if (!(_flags.gameID == GI_EOB1 && _configRenderMode == Common::kRenderEGA)) + if (_flags.platform != Common::kPlatformAmiga && !(_flags.gameID == GI_EOB1 && _configRenderMode == Common::kRenderEGA)) memcpy(_vcnColTable, colMap, 32); memcpy(_vcnBlocks, pos, vcnSize); @@ -546,7 +546,7 @@ void EoBCoreEngine::drawScene(int refresh) { if (_sceneDrawPage2) { if (refresh) - _screen->fillRect(0, 0, 176, 120, 12); + _screen->fillRect(0, 0, 176, 120, guiSettings()->colors.guiColorBlack); if (!_loading) _screen->setScreenPalette(_screen->getPalette(0)); diff --git a/engines/kyra/engine/scene_rpg.cpp b/engines/kyra/engine/scene_rpg.cpp index 4c0a97e7c7..1bb777f51c 100644 --- a/engines/kyra/engine/scene_rpg.cpp +++ b/engines/kyra/engine/scene_rpg.cpp @@ -534,20 +534,20 @@ void KyraRpgEngine::vcnDraw_bw_trans_hiCol(uint8 *&dst, const uint8 *&src) { void KyraRpgEngine::vcnDraw_fw_Amiga(uint8 *&dst, const uint8 *&src) { for (int blockX = 0; blockX < 8; blockX++) { - *dst = 0; + uint8 col = 0; for (int i = 0; i < 5; ++i) - *dst |= (((src[i] & (0x80 >> blockX)) >> (7 - blockX)) << i); - dst++; + col |= (((src[i] & (0x80 >> blockX)) >> (7 - blockX)) << i); + *dst++ = col; } src += 5; } void KyraRpgEngine::vcnDraw_bw_Amiga(uint8 *&dst, const uint8 *&src) { for (int blockX = 7; blockX >= 0; blockX--) { - *dst = 0; + uint8 col = 0; for (int i = 0; i < 5; ++i) - *dst |= (((src[i] & (0x80 >> blockX)) >> (7 - blockX)) << i); - dst++; + col |= (((src[i] & (0x80 >> blockX)) >> (7 - blockX)) << i); + *dst++ = col; } src += 5; } diff --git a/engines/kyra/engine/sprites_eob.cpp b/engines/kyra/engine/sprites_eob.cpp index 5e2e58ea85..f7e65f2133 100644 --- a/engines/kyra/engine/sprites_eob.cpp +++ b/engines/kyra/engine/sprites_eob.cpp @@ -363,6 +363,7 @@ void EoBCoreEngine::drawBlockObject(int flipped, int page, const uint8 *shape, i const ScreenDim *d = _screen->getScreenDim(sd); if (_flags.gameID == GI_EOB1) x &= ~1; + _screen->drawShape(page, shape, x - (d->sx << 3), y - d->sy, sd, flipped | (ovl ? 2 : 0), ovl); } @@ -373,7 +374,7 @@ void EoBCoreEngine::drawMonsterShape(const uint8 *shape, int x, int y, int flipp ovl = _monsterFlashOverlay; else if (_flags.gameID == GI_EOB2 && flags & 0x20) ovl = _monsterStoneOverlay; - else if (palIndex != -1) + else if (palIndex != -1 && _flags.platform != Common::kPlatformAmiga) ovl = _monsterPalettes[palIndex]; drawBlockObject(flipped, 2, shape, x, y, 5, ovl); diff --git a/engines/kyra/graphics/screen.cpp b/engines/kyra/graphics/screen.cpp index ea0871f317..b69cc07e77 100644 --- a/engines/kyra/graphics/screen.cpp +++ b/engines/kyra/graphics/screen.cpp @@ -100,6 +100,8 @@ bool Screen::init() { _useSJIS = false; _use16ColorMode = _vm->gameFlags().use16ColorMode; _isAmiga = (_vm->gameFlags().platform == Common::kPlatformAmiga); + // Amiga copper palette magic requires the use of more than 32 colors for some purposes. + _useAmigaExtraColors = (_isAmiga && _vm->game() == GI_EOB2); // We only check the "render_mode" setting for both Eye of the Beholder // games here, since all the other games do not support the render_mode @@ -174,14 +176,18 @@ bool Screen::init() { const int paletteCount = _isAmiga ? 13 : 4; // We allow 256 color palettes in EGA mode, since original EOB II code does the same and requires it const int numColors = _use16ColorMode ? 16 : (_isAmiga ? 32 : (_renderMode == Common::kRenderCGA ? 4 : 256)); + const int numColorsInternal = _useAmigaExtraColors ? 64 : numColors; _interfacePaletteEnabled = false; - _screenPalette = new Palette(numColors); + _screenPalette = new Palette(numColorsInternal); assert(_screenPalette); _palettes.resize(paletteCount); - for (int i = 0; i < paletteCount; ++i) { + _palettes[0] = new Palette(numColorsInternal); + assert(_palettes[0]); + + for (int i = 1; i < paletteCount; ++i) { _palettes[i] = new Palette(numColors); assert(_palettes[i]); } @@ -195,7 +201,7 @@ bool Screen::init() { Screen::setScreenPalette(pal); } - _internFadePalette = new Palette(numColors); + _internFadePalette = new Palette(numColorsInternal); assert(_internFadePalette); setScreenPalette(getPalette(0)); diff --git a/engines/kyra/graphics/screen.h b/engines/kyra/graphics/screen.h index b6706cd14f..b1b2d86e48 100644 --- a/engines/kyra/graphics/screen.h +++ b/engines/kyra/graphics/screen.h @@ -687,6 +687,7 @@ protected: bool _useHiResEGADithering; bool _useHiColorScreen; bool _isAmiga; + bool _useAmigaExtraColors; Common::RenderMode _renderMode; int _bytesPerPixel; int _screenPageSize; diff --git a/engines/kyra/graphics/screen_eob.cpp b/engines/kyra/graphics/screen_eob.cpp index 2e2674d9dd..0e5596221e 100644 --- a/engines/kyra/graphics/screen_eob.cpp +++ b/engines/kyra/graphics/screen_eob.cpp @@ -62,7 +62,7 @@ Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system, _egaDitheringTempPage = 0; _cgaMappingDefault = 0; _cgaDitheringTables[0] = _cgaDitheringTables[1] = 0; - _useHiResEGADithering = false; + _useHiResEGADithering = _dualPaletteMode = false; } Screen_EoB::~Screen_EoB() { @@ -165,6 +165,13 @@ void Screen_EoB::setMouseCursor(int x, int y, const byte *shape, const uint8 *ov else copyRegionToBuffer(6, 0, 0, mouseW, mouseH, cursor); + // Mouse cursor post processing for EOB II Amiga + if (_dualPaletteMode) { + int len = mouseW * mouseH; + while (--len > -1) + cursor[len] |= 0x20; + } + // 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. @@ -280,7 +287,7 @@ void Screen_EoB::loadEoBBitmap(const char *file, const uint8 *cgaMapping, int te } if (!loadAlternative) - loadBitmap(tmp.c_str(), tempPage, destPage, 0); + loadBitmap(tmp.c_str(), tempPage, destPage, _vm->gameFlags().platform == Common::kPlatformAmiga ? _palettes[0] : 0); } else { loadAlternative = true; @@ -1643,23 +1650,63 @@ void Screen_EoB::loadSpecialAmigaCPS(const char *fileName, int destPage, bool is convertAmigaGfx(_pagePtrs[destPage], 320, 200); } +void Screen_EoB::setupDualPalettesSplitScreen(Palette &top, Palette &bottom) { + // The original supports simultaneous fading of both palettes, but doesn't make any use of that + // feature. The fade rate is always set to 0. So I see no need to implement that. + _palettes[0]->copy(top, 0, 32, 0); + _palettes[0]->copy(bottom, 0, 32, 32); + setScreenPalette(*_palettes[0]); + _dualPaletteMode = _forceFullUpdate = true; +} + +void Screen_EoB::disableDualPalettesSplitScreen() { + _dualPaletteMode = false; + _forceFullUpdate = true; +} + void Screen_EoB::updateDirtyRects() { - if (!_useHiResEGADithering) { + if (!_useHiResEGADithering && !_dualPaletteMode) { Screen::updateDirtyRects(); return; } - if (_forceFullUpdate) { + if (_dualPaletteMode && _forceFullUpdate) { + uint32 *pos = (uint32*)(_pagePtrs[0] + 120 * SCREEN_W); + uint16 h = 80 * (SCREEN_W >> 2); + while (h--) + *pos++ |= 0x20202020; + _system->copyRectToScreen(getCPagePtr(0), SCREEN_W, 0, 0, SCREEN_W, SCREEN_H); + + } else if (_dualPaletteMode) { + Common::List::iterator it; + for (it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) { + if (it->bottom > 119) { + int16 startY = MAX(120, it->top); + int16 h = it->bottom - startY + 1; + int16 w = it->width(); + uint8 *pos = _pagePtrs[0] + startY * SCREEN_W + it->left; + while (h--) { + for (int x = 0; x < w; ++x) + *pos++ |= 0x20; + pos += (SCREEN_W - w); + } + } + _system->copyRectToScreen(_pagePtrs[0] + it->top * SCREEN_W + it->left, SCREEN_W, it->left, it->top, it->width(), it->height()); + } + + } else if (_forceFullUpdate) { ditherRect(getCPagePtr(0), _egaDitheringTempPage, SCREEN_W * 2, SCREEN_W, SCREEN_H); _system->copyRectToScreen(_egaDitheringTempPage, SCREEN_W * 2, 0, 0, SCREEN_W * 2, SCREEN_H * 2); + } else { - const byte *page0 = getCPagePtr(0); + const uint8 *page0 = getCPagePtr(0); Common::List::iterator it; for (it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) { ditherRect(page0 + it->top * SCREEN_W + it->left, _egaDitheringTempPage, SCREEN_W * 2, it->width(), it->height()); _system->copyRectToScreen(_egaDitheringTempPage, SCREEN_W * 2, it->left * 2, it->top * 2, it->width() * 2, it->height() * 2); } } + _forceFullUpdate = false; _dirtyRects.clear(); } diff --git a/engines/kyra/graphics/screen_eob.h b/engines/kyra/graphics/screen_eob.h index 66efc25cc0..5df67df506 100644 --- a/engines/kyra/graphics/screen_eob.h +++ b/engines/kyra/graphics/screen_eob.h @@ -93,6 +93,12 @@ public: // Amiga specific void loadSpecialAmigaCPS(const char *fileName, int destPage, bool isGraphics); + // This is a simple way of emulating the Amiga copper list palette magic for more than 32 colors. + // I use colors 32 to 63 for these extra colors (which the Amiga copper sends to the color + // registers on the fly at vertical beam position 120). + void setupDualPalettesSplitScreen(Palette &top, Palette &bottom); + void disableDualPalettesSplitScreen(); + private: void updateDirtyRects(); void ditherRect(const uint8 *src, uint8 *dst, int dstPitch, int srcW, int srcH, int colorKey = -1); @@ -122,6 +128,7 @@ private: uint8 *_dsTempPage; uint8 *_shpBuffer; uint8 *_convertHiColorBuffer; + bool _dualPaletteMode; uint16 *_cgaDitheringTables[2]; const uint8 *_cgaMappingDefault; diff --git a/engines/kyra/gui/gui_eob.cpp b/engines/kyra/gui/gui_eob.cpp index bfde732ffe..981a33fb52 100644 --- a/engines/kyra/gui/gui_eob.cpp +++ b/engines/kyra/gui/gui_eob.cpp @@ -61,8 +61,15 @@ void EoBCoreEngine::gui_drawPlayField(bool refresh) { _screen->updateScreen(); _screen->loadEoBBitmap("INVENT", _cgaMappingInv, 5, 3, 2); - if (_flags.platform == Common::kPlatformAmiga) - _screen->getPalette(0).copy(_screen->getPalette(1), 1, 5, 1); + + if (_flags.platform == Common::kPlatformAmiga) { + if (_flags.gameID == GI_EOB1) { + _screen->getPalette(0).copy(_screen->getPalette(1), 1, 5, 1); + } else { + _screen->setupDualPalettesSplitScreen(_screen->getPalette(6), _screen->getPalette(1)); + _screen->getPalette(7).copy(_screen->getPalette(1), 0, 32); + } + } } void EoBCoreEngine::gui_restorePlayField() { @@ -3233,7 +3240,7 @@ void GUI_EoB::runMemorizePrayMenu(int charIndex, int spellType) { if (updateDesc) { updateDesc = false; _screen->set16bitShadingLevel(4); - _screen->printShadedText(Common::String::format(_vm->_menuStringsMgc[1], np[lastHighLightButton] - numAssignedSpellsPerBookPage[lastHighLightButton], np[lastHighLightButton]).c_str(), 8, 38, 9, _vm->guiSettings()->colors.fill, _vm->guiSettings()->colors.guiColorBlack); + _screen->printShadedText(Common::String::format(_vm->_menuStringsMgc[1], np[lastHighLightButton] - numAssignedSpellsPerBookPage[lastHighLightButton], np[lastHighLightButton]).c_str(), 8, 38, _vm->guiSettings()->colors.guiColorLightBlue, _vm->guiSettings()->colors.fill, _vm->guiSettings()->colors.guiColorBlack); _screen->set16bitShadingLevel(0); } diff --git a/engines/kyra/script/script_eob.cpp b/engines/kyra/script/script_eob.cpp index b063b08a6e..1c96a53498 100644 --- a/engines/kyra/script/script_eob.cpp +++ b/engines/kyra/script/script_eob.cpp @@ -1319,6 +1319,9 @@ int EoBInfProcessor::oeob_loadNewLevelOrMonsters(int8 *data) { _vm->gui_drawAllCharPortraitsWithStats(); _subroutineStackPos = 0; + if (_vm->_flags.gameID == GI_EOB2 && _vm->_flags.platform == Common::kPlatformAmiga) + _vm->gui_restorePlayField(); + } else { cmd = *pos++; _vm->releaseMonsterShapes(cmd * 18, 18); diff --git a/engines/kyra/sequence/sequences_darkmoon.cpp b/engines/kyra/sequence/sequences_darkmoon.cpp index b92eb74fde..7a581e55ba 100644 --- a/engines/kyra/sequence/sequences_darkmoon.cpp +++ b/engines/kyra/sequence/sequences_darkmoon.cpp @@ -160,6 +160,7 @@ int DarkMoonEngine::mainMenu() { _screen->_curPage = op; _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); _screen->shadeRect(78, 99, 249, 141, 4); + _screen->showMouse(); _screen->updateScreen(); _allowImport = true; menuChoice = mainMenuLoop(); @@ -1201,6 +1202,7 @@ DarkmoonSequenceHelper::DarkmoonSequenceHelper(OSystem *system, DarkMoonEngine * } _screen->enableHiColorMode(false); + _screen->disableDualPalettesSplitScreen(); int numColors = 256; if (_vm->_flags.platform == Common::kPlatformAmiga) { @@ -1296,7 +1298,6 @@ DarkmoonSequenceHelper::~DarkmoonSequenceHelper() { _screen->enableHiColorMode(true); _screen->clearCurPage(); _screen->setFont(_prevFont); - _screen->showMouse(); _screen->updateScreen(); _system->delayMillis(150); -- cgit v1.2.3