diff options
author | Norbert Lange | 2009-08-11 22:35:56 +0000 |
---|---|---|
committer | Norbert Lange | 2009-08-11 22:35:56 +0000 |
commit | 0836cf6d9b9222255273a9c6f9d91203b13c3bd9 (patch) | |
tree | 714c59161aaf7dbc36d7cb6b4e8fcaa9c467e8f9 /engines/kyra | |
parent | 8cb42dd6896925106282abd23ce23812d6031989 (diff) | |
parent | 65e9ae163ff757ca15af78da4a753a7ee1d25a16 (diff) | |
download | scummvm-rg350-0836cf6d9b9222255273a9c6f9d91203b13c3bd9.tar.gz scummvm-rg350-0836cf6d9b9222255273a9c6f9d91203b13c3bd9.tar.bz2 scummvm-rg350-0836cf6d9b9222255273a9c6f9d91203b13c3bd9.zip |
merged from trunk (Amiga LoK supposedly completeable!)
fixed a bug I introduced in one of the last cleanups
svn-id: r43291
Diffstat (limited to 'engines/kyra')
-rw-r--r-- | engines/kyra/gui.cpp | 26 | ||||
-rw-r--r-- | engines/kyra/gui_lok.cpp | 62 | ||||
-rw-r--r-- | engines/kyra/items_lok.cpp | 67 | ||||
-rw-r--r-- | engines/kyra/kyra_lok.cpp | 5 | ||||
-rw-r--r-- | engines/kyra/kyra_lok.h | 65 | ||||
-rw-r--r-- | engines/kyra/lol.cpp | 7 | ||||
-rw-r--r-- | engines/kyra/lol.h | 4 | ||||
-rw-r--r-- | engines/kyra/saveload_lok.cpp | 27 | ||||
-rw-r--r-- | engines/kyra/scene_lok.cpp | 64 | ||||
-rw-r--r-- | engines/kyra/screen.cpp | 655 | ||||
-rw-r--r-- | engines/kyra/screen.h | 131 | ||||
-rw-r--r-- | engines/kyra/screen_lok.cpp | 19 | ||||
-rw-r--r-- | engines/kyra/screen_lok.h | 3 | ||||
-rw-r--r-- | engines/kyra/script_lok.cpp | 127 | ||||
-rw-r--r-- | engines/kyra/seqplayer.cpp | 3 | ||||
-rw-r--r-- | engines/kyra/sequences_lok.cpp | 269 | ||||
-rw-r--r-- | engines/kyra/sound_amiga.cpp | 4 | ||||
-rw-r--r-- | engines/kyra/sprites_lol.cpp | 29 | ||||
-rw-r--r-- | engines/kyra/staticres.cpp | 27 | ||||
-rw-r--r-- | engines/kyra/text.cpp | 122 | ||||
-rw-r--r-- | engines/kyra/text.h | 6 | ||||
-rw-r--r-- | engines/kyra/text_lok.cpp | 32 | ||||
-rw-r--r-- | engines/kyra/wsamovie.cpp | 13 | ||||
-rw-r--r-- | engines/kyra/wsamovie.h | 1 |
24 files changed, 1326 insertions, 442 deletions
diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp index d9924d233b..cc1add9ce7 100644 --- a/engines/kyra/gui.cpp +++ b/engines/kyra/gui.cpp @@ -95,7 +95,8 @@ void GUI::initMenu(Menu &menu) { if (_vm->gameFlags().gameID == GI_LOL) { printMenuText(getMenuTitle(menu), textX, textY, menu.textColor, 0, 9); } else { - printMenuText(getMenuTitle(menu), textX - 1, textY + 1, defaultColor1(), defaultColor2(), 0); + if (_vm->gameFlags().platform != Common::kPlatformAmiga) + printMenuText(getMenuTitle(menu), textX - 1, textY + 1, defaultColor1(), defaultColor2(), 0); printMenuText(getMenuTitle(menu), textX, textY, menu.textColor, 0, 0); } @@ -142,7 +143,9 @@ void GUI::initMenu(Menu &menu) { else printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 8); } else { - printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); + if (_vm->gameFlags().platform != Common::kPlatformAmiga) + printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); + if (i == menu.highlightedItem) printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0); else @@ -158,7 +161,8 @@ void GUI::initMenu(Menu &menu) { menu.item[i].labelY = menu.item[i].y + 3; printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX, menu.y + menu.item[i].labelY, menu.item[i].textColor, 0, 10); } else { - printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX - 1, menu.y + menu.item[i].labelY + 1, defaultColor1(), 0, 0); + if (_vm->gameFlags().platform != Common::kPlatformAmiga) + printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX - 1, menu.y + menu.item[i].labelY + 1, defaultColor1(), 0, 0); printMenuText(getMenuItemLabel(menu.item[i]), menu.x + menu.item[i].labelX, menu.y + menu.item[i].labelY, menu.item[i].textColor, 0, 0); } } @@ -253,7 +257,8 @@ void GUI::redrawText(const Menu &menu) { textY++; printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 8); } else { - printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); + if (_vm->gameFlags().platform != Common::kPlatformAmiga) + printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].textColor, 0, 0); } } @@ -278,7 +283,8 @@ void GUI::redrawHighlight(const Menu &menu) { textY++; printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 8); } else { - printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); + if (_vm->gameFlags().platform != Common::kPlatformAmiga) + printMenuText(getMenuItemTitle(menu.item[i]), textX - 1, textY + 1, defaultColor1(), 0, 0); printMenuText(getMenuItemTitle(menu.item[i]), textX, textY, menu.item[i].highlightColor, 0, 0); } } @@ -324,7 +330,10 @@ int GUI::redrawButtonCallback(Button *button) { return 0; _screen->hideMouse(); - _screen->drawBox(button->x + 1, button->y + 1, button->x + button->width - 1, button->y + button->height - 1, 0xF8); + if (_vm->gameFlags().platform == Common::kPlatformAmiga) + _screen->drawBox(button->x + 1, button->y + 1, button->x + button->width - 1, button->y + button->height - 1, 17); + else + _screen->drawBox(button->x + 1, button->y + 1, button->x + button->width - 1, button->y + button->height - 1, 0xF8); _screen->showMouse(); return 0; @@ -335,7 +344,10 @@ int GUI::redrawShadedButtonCallback(Button *button) { return 0; _screen->hideMouse(); - _screen->drawShadedBox(button->x, button->y, button->x + button->width, button->y + button->height, 0xF9, 0xFA); + if (_vm->gameFlags().platform == Common::kPlatformAmiga) + _screen->drawShadedBox(button->x, button->y, button->x + button->width, button->y + button->height, 31, 18); + else + _screen->drawShadedBox(button->x, button->y, button->x + button->width, button->y + button->height, 0xF9, 0xFA); _screen->showMouse(); return 0; diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp index 4624aced90..e9c71f511d 100644 --- a/engines/kyra/gui_lok.cpp +++ b/engines/kyra/gui_lok.cpp @@ -56,10 +56,10 @@ int KyraEngine_LoK::buttonInventoryCallback(Button *caller) { return 0; } else { _screen->hideMouse(); - _screen->fillRect(_itemPosX[itemOffset], _itemPosY[itemOffset], _itemPosX[itemOffset] + 15, _itemPosY[itemOffset] + 15, 12); + _screen->fillRect(_itemPosX[itemOffset], _itemPosY[itemOffset], _itemPosX[itemOffset] + 15, _itemPosY[itemOffset] + 15, _flags.platform == Common::kPlatformAmiga ? 19 : 12); snd_playSoundEffect(0x35); setMouseItem(inventoryItem); - updateSentenceCommand(_itemList[inventoryItem], _takenList[0], 179); + updateSentenceCommand(_itemList[getItemListIndex(inventoryItem)], _takenList[0], 179); _itemInHand = inventoryItem; _screen->showMouse(); _currentCharacter->inventoryItems[itemOffset] = 0xFF; @@ -68,10 +68,14 @@ int KyraEngine_LoK::buttonInventoryCallback(Button *caller) { if (inventoryItem != 0xFF) { snd_playSoundEffect(0x35); _screen->hideMouse(); - _screen->fillRect(_itemPosX[itemOffset], _itemPosY[itemOffset], _itemPosX[itemOffset] + 15, _itemPosY[itemOffset] + 15, 12); + _screen->fillRect(_itemPosX[itemOffset], _itemPosY[itemOffset], _itemPosX[itemOffset] + 15, _itemPosY[itemOffset] + 15, _flags.platform == Common::kPlatformAmiga ? 19 : 12); _screen->drawShape(0, _shapes[216+_itemInHand], _itemPosX[itemOffset], _itemPosY[itemOffset], 0, 0); setMouseItem(inventoryItem); - updateSentenceCommand(_itemList[inventoryItem], _takenList[1], 179); + // TODO: Proper support for both taken strings in Amiga version + if (_flags.platform == Common::kPlatformAmiga) + updateSentenceCommand(_itemList[getItemListIndex(inventoryItem)], _takenList[0], 179); + else + updateSentenceCommand(_itemList[getItemListIndex(inventoryItem)], _takenList[1], 179); _screen->showMouse(); _currentCharacter->inventoryItems[itemOffset] = _itemInHand; _itemInHand = inventoryItem; @@ -80,7 +84,7 @@ int KyraEngine_LoK::buttonInventoryCallback(Button *caller) { _screen->hideMouse(); _screen->drawShape(0, _shapes[216+_itemInHand], _itemPosX[itemOffset], _itemPosY[itemOffset], 0, 0); _screen->setMouseCursor(1, 1, _shapes[0]); - updateSentenceCommand(_itemList[_itemInHand], _placedList[0], 179); + updateSentenceCommand(_itemList[getItemListIndex(_itemInHand)], _placedList[0], 179); _screen->showMouse(); _currentCharacter->inventoryItems[itemOffset] = _itemInHand; _itemInHand = -1; @@ -204,9 +208,29 @@ void GUI_LoK::createScreenThumbnail(Graphics::Surface &dst) { uint8 *screen = new uint8[Screen::SCREEN_W*Screen::SCREEN_H]; if (screen) { _screen->queryPageFromDisk("SEENPAGE.TMP", 0, screen); - uint8 screenPal[768]; - _screen->getRealPalette(2, screenPal); + + if (_vm->gameFlags().platform == Common::kPlatformAmiga) { + _screen->getRealPalette(0, &screenPal[ 0]); + _screen->getRealPalette(1, &screenPal[96]); + + // Set the interface palette text color to white + screenPal[96 + 16 * 3 + 0] = 0xFF; + screenPal[96 + 16 * 3 + 1] = 0xFF; + screenPal[96 + 16 * 3 + 2] = 0xFF; + + if (_screen->isInterfacePaletteEnabled()) { + for (int y = 0; y < 64; ++y) { + for (int x = 0; x < 320; ++x) { + screen[(y + 136) * Screen::SCREEN_W + x] += 32; + } + } + } + + } else { + _screen->getRealPalette(2, screenPal); + } + ::createThumbnail(&dst, screen, Screen::SCREEN_W, Screen::SCREEN_H, screenPal); } delete[] screen; @@ -365,6 +389,13 @@ void GUI_LoK::setGUILabels() { offsetOptions = 10; offsetOn = 0; walkspeedGarbageOffset = 0; + } else if (_vm->gameFlags().platform == Common::kPlatformAmiga) { + // English Amiga version + offset = 23; + offsetOn = 23; + offsetOptions = 32; + walkspeedGarbageOffset = 2; + offsetMainMenu = 23; } assert(offset + 27 < _vm->_guiStringsSize); @@ -448,8 +479,14 @@ int GUI_LoK::buttonMenuCallback(Button *caller) { _vm->snd_playSoundEffect(0x36); return 0; } - // XXX - _screen->setPaletteIndex(0xFE, 60, 60, 0); + + if (_vm->gameFlags().platform == Common::kPlatformAmiga) { + _screen->setPaletteIndex(0x10, 0x3F, 0x3F, 0x3F); + _screen->setInterfacePalette(_screen->getPalette(1), 0x3F, 0x3F, 0x3F); + } else { + _screen->setPaletteIndex(0xFE, 60, 60, 0); + } + for (int i = 0; i < 6; i++) { _menuButtonData[i].data0Val1 = _menuButtonData[i].data1Val1 = _menuButtonData[i].data2Val1 = 4; _menuButtonData[i].data0Callback = _redrawShadedButtonFunctor; @@ -639,12 +676,12 @@ int GUI_LoK::loadGameMenu(Button *button) { } void GUI_LoK::redrawTextfield() { - _screen->fillRect(38, 91, 287, 102, 250); + _screen->fillRect(38, 91, 287, 102, _vm->gameFlags().platform == Common::kPlatformAmiga ? 18 : 250); _text->printText(_savegameName, 38, 92, 253, 0, 0); _screen->_charWidth = -2; int width = _screen->getTextWidth(_savegameName); - _screen->fillRect(39 + width, 93, 45 + width, 100, 254); + _screen->fillRect(39 + width, 93, 45 + width, 100, _vm->gameFlags().platform == Common::kPlatformAmiga ? 31 : 254); _screen->_charWidth = 0; _screen->updateScreen(); @@ -923,6 +960,9 @@ void GUI_LoK::setupControls(Menu &menu) { menu.item[3].itemString = "ERROR"; } } else { + if (_vm->gameFlags().platform == Common::kPlatformAmiga) + clickableOffset = 5; + menu.item[4].enabled = 0; menu.item[4].labelString = 0; } diff --git a/engines/kyra/items_lok.cpp b/engines/kyra/items_lok.cpp index aef5ba5f13..bc490d9764 100644 --- a/engines/kyra/items_lok.cpp +++ b/engines/kyra/items_lok.cpp @@ -414,7 +414,7 @@ int KyraEngine_LoK::processItemDrop(uint16 sceneId, uint8 item, int x, int y, in if (unk1 == 0 && unk2 != 0) { assert(_itemList && _droppedList); - updateSentenceCommand(_itemList[item], _droppedList[0], 179); + updateSentenceCommand(_itemList[getItemListIndex(item)], _droppedList[0], 179); } return 1; @@ -434,7 +434,7 @@ void KyraEngine_LoK::exchangeItemWithMouseItem(uint16 sceneId, int itemIndex) { setMouseItem(_itemInHand); assert(_itemList && _takenList); - updateSentenceCommand(_itemList[_itemInHand], _takenList[1], 179); + updateSentenceCommand(_itemList[getItemListIndex(_itemInHand)], _takenList[1], 179); _screen->showMouse(); clickEventHandler2(); } @@ -693,7 +693,7 @@ void KyraEngine_LoK::magicOutMouseItem(int animIndex, int itemPos) { if (itemPos != -1) { restoreItemRect1(x, y); - _screen->fillRect(_itemPosX[itemPos], _itemPosY[itemPos], _itemPosX[itemPos] + 15, _itemPosY[itemPos] + 15, 12, 0); + _screen->fillRect(_itemPosX[itemPos], _itemPosY[itemPos], _itemPosX[itemPos] + 15, _itemPosY[itemPos] + 15, _flags.platform == Common::kPlatformAmiga ? 19 : 12, 0); backUpItemRect1(x, y); } @@ -715,7 +715,7 @@ void KyraEngine_LoK::magicOutMouseItem(int animIndex, int itemPos) { } else { _characterList[0].inventoryItems[itemPos] = 0xFF; _screen->hideMouse(); - _screen->fillRect(_itemPosX[itemPos], _itemPosY[itemPos], _itemPosX[itemPos] + 15, _itemPosY[itemPos] + 15, 12, 0); + _screen->fillRect(_itemPosX[itemPos], _itemPosY[itemPos], _itemPosX[itemPos] + 15, _itemPosY[itemPos] + 15, _flags.platform == Common::kPlatformAmiga ? 19 : 12, 0); _screen->showMouse(); } _screen->showMouse(); @@ -879,7 +879,7 @@ void KyraEngine_LoK::redrawInventory(int page) { _screen->_curPage = page; _screen->hideMouse(); for (int i = 0; i < 10; ++i) { - _screen->fillRect(_itemPosX[i], _itemPosY[i], _itemPosX[i] + 15, _itemPosY[i] + 15, 12, page); + _screen->fillRect(_itemPosX[i], _itemPosY[i], _itemPosX[i] + 15, _itemPosY[i] + 15, _flags.platform == Common::kPlatformAmiga ? 19 : 12, page); if (_currentCharacter->inventoryItems[i] != 0xFF) { uint8 item = _currentCharacter->inventoryItems[i]; _screen->drawShape(page, _shapes[216+item], _itemPosX[i], _itemPosY[i], 0, 0); @@ -910,5 +910,62 @@ void KyraEngine_LoK::restoreItemRect1(int xpos, int ypos) { _screen->copyBlockToPage(_screen->_curPage, xpos, ypos, 4<<3, 32, _itemBkgBackUp[1]); } +int KyraEngine_LoK::getItemListIndex(uint16 item) { + if (_flags.platform != Common::kPlatformAmiga) + return item; + + // "Unknown item" is at 81. + if (item == 0xFFFF || item == 0xFF) + return 81; + // The first item names are mapped directly + else if (item <= 28) + return item; + // There's only one string for "Fireberries" + else if (item >= 29 && item <= 33) + return 29; + // Correct offsets + else if (item >= 34 && item <= 59) + return item - 4; + // There's only one string for "Red Potion" + else if (item >= 60 && item <= 61) + return 56; + // There's only one string for "Blue Potion" + else if (item >= 62 && item <= 63) + return 57; + // There's only one string for "Yellow Potion" + else if (item >= 64 && item <= 65) + return 58; + // Correct offsets + else if (item >= 66 && item <= 69) + return item - 7; + // There's only one string for "Fresh Water" + else if (item >= 70 && item <= 71) + return 63; + // There's only one string for "Salt Water" + else if (item >= 72 && item <= 73) + return 64; + // There's only one string for "Mineral Water" + else if (item >= 74 && item <= 75) + return 65; + // There's only one string for "Magical Water" + else if (item >= 76 && item <= 77) + return 66; + // There's only one string for "Empty Flask" + else if (item >= 78 && item <= 79) + return 67; + // There's only one string for "Scroll" + else if (item >= 80 && item <= 89) + return 68; + // There's only one string for "Parchment scrap" + else if (item >= 90 && item <= 94) + return 69; + // Correct offsets + else if (item >= 95) + return item - 25; + + // This should never happen, but still GCC warns about it. + return 81; +} + } // end of namespace Kyra diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index 3863cad251..fc19b2fb65 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -368,6 +368,9 @@ void KyraEngine_LoK::startup() { loadMainScreen(); _screen->loadPalette("PALETTE.COL", _screen->getPalette(0)); + if (_flags.platform == Common::kPlatformAmiga) + _screen->loadPaletteTable("PALETTE.DAT", 6); + // XXX _animator->initAnimStateList(); setCharactersInDefaultScene(); @@ -669,7 +672,7 @@ int KyraEngine_LoK::processInputHelper(int xpos, int ypos) { currentRoom->itemsTable[item] = 0xFF; setMouseItem(item2); assert(_itemList && _takenList); - updateSentenceCommand(_itemList[item2], _takenList[0], 179); + updateSentenceCommand(_itemList[getItemListIndex(item2)], _takenList[0], 179); _itemInHand = item2; _screen->showMouse(); clickEventHandler2(); diff --git a/engines/kyra/kyra_lok.h b/engines/kyra/kyra_lok.h index 4d99ed11af..2783e92aee 100644 --- a/engines/kyra/kyra_lok.h +++ b/engines/kyra/kyra_lok.h @@ -289,6 +289,8 @@ protected: void removeHandItem(); void setMouseItem(uint16 item); + int getItemListIndex(uint16 item); + // -> graphics effects void wipeDownMouseItem(int xpos, int ypos); void itemSpecialFX(int x, int y, int item); @@ -523,35 +525,35 @@ protected: const uint8 *_seq_Demo4; const uint8 *_seq_Reunion; - const char * const*_seq_WSATable; - const char * const*_seq_CPSTable; - const char * const*_seq_COLTable; - const char * const*_seq_textsTable; + const char * const *_seq_WSATable; + const char * const *_seq_CPSTable; + const char * const *_seq_COLTable; + const char * const *_seq_textsTable; int _seq_WSATable_Size; int _seq_CPSTable_Size; int _seq_COLTable_Size; int _seq_textsTable_Size; - const char * const*_itemList; - const char * const*_takenList; - const char * const*_placedList; - const char * const*_droppedList; - const char * const*_noDropList; - const char * const*_putDownFirst; - const char * const*_waitForAmulet; - const char * const*_blackJewel; - const char * const*_poisonGone; - const char * const*_healingTip; - const char * const*_thePoison; - const char * const*_fluteString; - const char * const*_wispJewelStrings; - const char * const*_magicJewelString; - const char * const*_flaskFull; - const char * const*_fullFlask; - const char * const*_veryClever; - const char * const*_homeString; - const char * const*_newGameString; + const char * const *_itemList; + const char * const *_takenList; + const char * const *_placedList; + const char * const *_droppedList; + const char * const *_noDropList; + const char * const *_putDownFirst; + const char * const *_waitForAmulet; + const char * const *_blackJewel; + const char * const *_poisonGone; + const char * const *_healingTip; + const char * const *_thePoison; + const char * const *_fluteString; + const char * const *_wispJewelStrings; + const char * const *_magicJewelString; + const char * const *_flaskFull; + const char * const *_fullFlask; + const char * const *_veryClever; + const char * const *_homeString; + const char * const *_newGameString; int _itemList_Size; int _takenList_Size; @@ -573,13 +575,13 @@ protected: int _homeString_Size; int _newGameString_Size; - const char * const*_characterImageTable; + const char * const *_characterImageTable; int _characterImageTableSize; - const char * const*_guiStrings; + const char * const *_guiStrings; int _guiStringsSize; - const char * const*_configStrings; + const char * const *_configStrings; int _configStringsSize; Shape *_defaultShapeTable; @@ -617,16 +619,16 @@ protected: Room *_roomTable; int _roomTableSize; - const char * const*_roomFilenameTable; + const char * const *_roomFilenameTable; int _roomFilenameTableSize; const uint8 *_amuleteAnim; - const uint8 * const*_specialPalettes; + const uint8 * const *_specialPalettes; - const char *const *_soundFiles; + const char * const *_soundFiles; int _soundFilesSize; - const char *const *_soundFilesIntro; + const char * const *_soundFilesIntro; int _soundFilesIntroSize; const int32 *_cdaTrackTable; int _cdaTrackTableSize; @@ -649,6 +651,9 @@ protected: static const uint16 _amuletY[]; static const uint16 _amuletX2[]; static const uint16 _amuletY2[]; + + // special palette handling for AMIGA + void setupZanthiaPalette(int pal); protected: void setupOpcodeTable(); diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index d2c8be9556..e3d28163a8 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -160,7 +160,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _flyingObjects = 0; _monsters = 0; _lastMouseRegion = 0; - _objectLastDirection = _monsterCountUnk = _monsterShiftAlt = 0; + _objectLastDirection = _monsterStepCounter = _monsterStepMode = 0; _monsterCurBlock = 0; _seqWindowX1 = _seqWindowY1 = _seqWindowX2 = _seqWindowY2 = _seqTrigger = 0; _spsWindowX = _spsWindowY = _spsWindowW = _spsWindowH = 0; @@ -730,7 +730,7 @@ int LoLEngine::mainMenu() { // 16 color mode { { 0, 0, 0, 0, 0 }, - { 0x01, 0x04, 0x0C, 0x03, 0x00, 0xC1, 0xE1 }, + { 0x01, 0x04, 0x0C, 0x04, 0x00, 0xC1, 0xE1 }, { 0xCC, 0xDD, 0xDD, 0xDD }, Screen::FID_9_FNT, 1 } @@ -738,6 +738,9 @@ int LoLEngine::mainMenu() { int dataIndex = _flags.use16ColorMode ? 1 : 0; + if (!_flags.isTalkie) + --data[dataIndex].menuTable[3]; + if (hasSave) ++data[dataIndex].menuTable[3]; diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index f4ac597b5c..06950779b1 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -1296,8 +1296,8 @@ private: uint8 _monsterAnimType[3]; uint16 _monsterCurBlock; int _objectLastDirection; - int _monsterCountUnk; - int _monsterShiftAlt; + int _monsterStepCounter; + int _monsterStepMode; const uint16 *_monsterModifiers; int _monsterModifiersSize; diff --git a/engines/kyra/saveload_lok.cpp b/engines/kyra/saveload_lok.cpp index c59f2bebf6..13f08715fd 100644 --- a/engines/kyra/saveload_lok.cpp +++ b/engines/kyra/saveload_lok.cpp @@ -177,15 +177,32 @@ Common::Error KyraEngine_LoK::loadGameState(int slot) { seq_createAmuletJewel(i-0x55, 10, 1, 1); } } - _screen->copyRegion(0, 0, 0, 0, 320, 200, 10, 8); - _screen->copyRegion(0, 0, 0, 0, 320, 200, 8, 0); + + _screen->copyRegion(8, 8, 8, 8, 304, 212, 10, 0); } setHandItem(_itemInHand); - _animator->setBrandonAnimSeqSize(3, 48); + + // Will-O-Wisp uses a different shape size than Brandon's usual + // shape, thus we need to setup the correct size depending on + // his state over here. This fixes graphics glitches when loading + // saves, where Brandon is transformed into the Will-O-Wisp. + if (_brandonStatusBit & 2) + _animator->setBrandonAnimSeqSize(5, 48); + else + _animator->setBrandonAnimSeqSize(3, 48); + redrawInventory(0); - _brandonPosX = brandonX; - _brandonPosY = brandonY; + + _brandonPosX = _brandonPosY = -1; + + // Unlike the original we did restore Brandon's position in the scene screen on load. + // This appereantly caused graphics gliches in some scenes. For example bug #2835715 + // ("KYRA: GFX glitch in Amiga version at the bridge") is caused by this feature. + // Thus we disable that for now. + //_brandonPosX = brandonX; + //_brandonPosY = brandonY; + enterNewScene(_currentCharacter->sceneId, _currentCharacter->facing, 0, 0, 1); _animator->animRefreshNPC(0); diff --git a/engines/kyra/scene_lok.cpp b/engines/kyra/scene_lok.cpp index fc1ca41189..e7f4ecbae0 100644 --- a/engines/kyra/scene_lok.cpp +++ b/engines/kyra/scene_lok.cpp @@ -778,10 +778,10 @@ void KyraEngine_LoK::initSceneScreen(int brandonAlive) { if (_unkScreenVar2 == 1) _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false); else - _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); + _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0, Screen::CR_NO_P_CHECK); if (_unkScreenVar1 && !queryGameFlag(0xA0)) { - if (_currentCharacter->sceneId == 45 && _paletteChanged) + if (_currentCharacter->sceneId == 45 && _cauldronState) _screen->getPalette(0).copy(_screen->getPalette(4), 12, 1); if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245 && (_brandonStatusBit & 1)) @@ -1203,6 +1203,66 @@ bool KyraEngine_LoK::lineIsPassable(int x, int y) { #pragma mark - +void KyraEngine_LoK::setupZanthiaPalette(int pal) { + uint8 r, g, b; + + switch (pal - 17) { + case 0: + // 0x88F + r = 33; + g = 33; + b = 63; + break; + + case 1: + // 0x00F + r = 0; + g = 0; + b = 63; + break; + + case 2: + // 0xF88 + r = 63; + g = 33; + b = 33; + break; + + case 3: + // 0xF00 + r = 63; + g = 0; + b = 0; + break; + + case 4: + // 0xFF9 + r = 63; + g = 63; + b = 37; + break; + + case 5: + // 0xFF1 + r = 63; + g = 63; + b = 4; + break; + + default: + // 0xFFF + r = 63; + g = 63; + b = 63; + } + + _screen->getPalette(4)[12 * 3 + 0] = r; + _screen->getPalette(4)[12 * 3 + 1] = g; + _screen->getPalette(4)[12 * 3 + 2] = b; +} + +#pragma mark - + void KyraEngine_LoK::setupSceneResource(int sceneId) { if (!_flags.isTalkie) return; diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 7a7544a589..8d4ea7e022 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -48,6 +48,7 @@ Screen::Screen(KyraEngine_v1 *vm, OSystem *system) _drawShapeVar5 = 0; _sjisFont = 0; + memset(_fonts, 0, sizeof(_fonts)); } Screen::~Screen() { @@ -56,10 +57,8 @@ Screen::~Screen() { delete[] _pagePtrs[0]; - for (int f = 0; f < ARRAYSIZE(_fonts); ++f) { - delete[] _fonts[f].fontData; - _fonts[f].fontData = NULL; - } + for (int f = 0; f < ARRAYSIZE(_fonts); ++f) + delete _fonts[f]; delete _sjisFont; delete _screenPalette; @@ -80,6 +79,7 @@ bool Screen::init() { _useOverlays = false; _useSJIS = false; _use16ColorMode = _vm->gameFlags().use16ColorMode; + _isAmiga = (_vm->gameFlags().platform == Common::kPlatformAmiga); if (_vm->gameFlags().useHiResOverlay) { _useOverlays = true; @@ -103,7 +103,6 @@ bool Screen::init() { } } - _curPage = 0; uint8 *pagePtr = new uint8[SCREEN_PAGE_SIZE * 8]; for (int pageNum = 0; pageNum < SCREEN_PAGE_NUM; pageNum += 2) @@ -112,8 +111,10 @@ bool Screen::init() { memset(_shapePages, 0, sizeof(_shapePages)); - const int paletteCount = (_vm->gameFlags().platform == Common::kPlatformAmiga) ? 12 : 4; - const int numColors = _use16ColorMode ? 16 : ((_vm->gameFlags().platform == Common::kPlatformAmiga) ? 32 : 256); + const int paletteCount = _isAmiga ? 13 : 4; + const int numColors = _use16ColorMode ? 16 : (_isAmiga ? 32 : 256); + + _interfacePaletteEnabled = false; _screenPalette = new Palette(numColors); assert(_screenPalette); @@ -205,6 +206,8 @@ void Screen::setResolution() { void Screen::updateScreen() { if (_useOverlays) updateDirtyRectsOvl(); + else if (_isAmiga && _interfacePaletteEnabled) + updateDirtyRectsAmiga(); else updateDirtyRects(); @@ -232,6 +235,77 @@ void Screen::updateDirtyRects() { _dirtyRects.clear(); } +void Screen::updateDirtyRectsAmiga() { + if (_forceFullUpdate) { + _system->copyRectToScreen(getCPagePtr(0), SCREEN_W, 0, 0, SCREEN_W, 136); + + // Page 8 is not used by Kyra 1 AMIGA, thus we can use it to adjust the colors + copyRegion(0, 136, 0, 0, 320, 64, 0, 8, CR_NO_P_CHECK); + + uint8 *dst = getPagePtr(8); + for (int y = 0; y < 64; ++y) + for (int x = 0; x < 320; ++x) + *dst++ += 32; + + _system->copyRectToScreen(getCPagePtr(8), SCREEN_W, 0, 136, SCREEN_W, 64); + } else { + const byte *page0 = getCPagePtr(0); + Common::List<Common::Rect>::iterator it; + + for (it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) { + if (it->bottom <= 136) { + _system->copyRectToScreen(page0 + it->top * SCREEN_W + it->left, SCREEN_W, it->left, it->top, it->width(), it->height()); + } else { + // Check whether the rectangle is part of both the screen and the interface + if (it->top < 136) { + // The rectangle covers both screen part and interface part + + const int screenHeight = 136 - it->top; + const int interfaceHeight = it->bottom - 136; + + const int width = it->width(); + const int lineAdd = SCREEN_W - width; + + // Copy the screen part verbatim + _system->copyRectToScreen(page0 + it->top * SCREEN_W + it->left, SCREEN_W, it->left, it->top, width, screenHeight); + + // Adjust the interface part + copyRegion(it->left, 136, 0, 0, width, interfaceHeight, 0, 8, Screen::CR_NO_P_CHECK); + + uint8 *dst = getPagePtr(8); + for (int y = 0; y < interfaceHeight; ++y) { + for (int x = 0; x < width; ++x) + *dst++ += 32; + dst += lineAdd; + } + + _system->copyRectToScreen(getCPagePtr(8), SCREEN_W, it->left, 136, width, interfaceHeight); + } else { + // The rectangle only covers the interface part + + const int width = it->width(); + const int height = it->height(); + const int lineAdd = SCREEN_W - width; + + copyRegion(it->left, it->top, 0, 0, width, height, 0, 8, Screen::CR_NO_P_CHECK); + + uint8 *dst = getPagePtr(8); + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) + *dst++ += 32; + dst += lineAdd; + } + + _system->copyRectToScreen(getCPagePtr(8), SCREEN_W, it->left, it->top, width, height); + } + } + } + } + + _forceFullUpdate = false; + _dirtyRects.clear(); +} + void Screen::updateDirtyRectsOvl() { if (_forceFullUpdate) { const byte *src = getCPagePtr(0); @@ -591,7 +665,7 @@ void Screen::setPaletteIndex(uint8 index, uint8 red, uint8 green, uint8 blue) { } void Screen::getRealPalette(int num, uint8 *dst) { - const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256); + const int colors = _isAmiga ? 32 : 256; const uint8 *palData = getPalette(num).getData(); if (!palData) { @@ -622,6 +696,41 @@ void Screen::setScreenPalette(const Palette &pal) { _system->setPalette(screenPal, 0, pal.getNumColors()); } +void Screen::enableInterfacePalette(bool e) { + _interfacePaletteEnabled = e; + + _forceFullUpdate = true; + _dirtyRects.clear(); + + // TODO: We might need to reset the mouse cursor + + updateScreen(); +} + +void Screen::setInterfacePalette(const Palette &pal, uint8 r, uint8 g, uint8 b) { + if (!_isAmiga) + return; + + uint8 screenPal[32 * 4]; + + assert(32 <= pal.getNumColors()); + + for (int i = 0; i < pal.getNumColors(); ++i) { + if (i != 0x10) { + screenPal[4 * i + 0] = (pal[i * 3 + 0] * 0xFF) / 0x3F; + screenPal[4 * i + 1] = (pal[i * 3 + 1] * 0xFF) / 0x3F; + screenPal[4 * i + 2] = (pal[i * 3 + 2] * 0xFF) / 0x3F; + } else { + screenPal[4 * i + 0] = (r * 0xFF) / 0x3F; + screenPal[4 * i + 1] = (g * 0xFF) / 0x3F; + screenPal[4 * i + 2] = (b * 0xFF) / 0x3F; + } + screenPal[4 * i + 3] = 0; + } + + _system->setPalette(screenPal, 32, pal.getNumColors()); +} + void Screen::copyToPage0(int y, int h, uint8 page, uint8 *seqBuf) { assert(y + h <= SCREEN_H); const uint8 *src = getPagePtr(page) + y * SCREEN_W; @@ -948,81 +1057,52 @@ void Screen::setTextColor(const uint8 *cmap, int a, int b) { } bool Screen::loadFont(FontId fontId, const char *filename) { - Font *fnt = &_fonts[fontId]; - - // FIXME: add font support for amiga version - if (_vm->gameFlags().platform == Common::kPlatformAmiga) - return true; - - if (!fnt) - error("fontId %d is invalid", fontId); - - if (fnt->fontData) - delete[] fnt->fontData; - - uint32 sz = 0; - uint8 *fontData = fnt->fontData = _vm->resource()->fileData(filename, &sz); - - if (!fontData || !sz) - error("Couldn't load font file '%s'", filename); + Font *&fnt = _fonts[fontId]; - uint16 fontSig = READ_LE_UINT16(fontData + 2); - - if (fontSig != 0x500) - error("Invalid font data (file '%s', fontSig: %.04X)", filename, fontSig); + if (!fnt) { + if (_isAmiga) + fnt = new AMIGAFont(); + else + fnt = new DOSFont(); - fnt->charWidthTable = fontData + READ_LE_UINT16(fontData + 8); - fnt->fontDescOffset = READ_LE_UINT16(fontData + 4); - fnt->charBitmapOffset = READ_LE_UINT16(fontData + 6); - fnt->charWidthTableOffset = READ_LE_UINT16(fontData + 8); - fnt->charHeightTableOffset = READ_LE_UINT16(fontData + 0xC); + assert(fnt); + } - fnt->lastGlyph = *(fnt->fontData + fnt->fontDescOffset + 3); + Common::SeekableReadStream *file = _vm->resource()->createReadStream(filename); + if (!file) + error("Font file '%s' is missing", filename); - return true; + bool ret = fnt->load(*file); + fnt->setColorMap(_textColorsMap); + delete file; + return ret; } Screen::FontId Screen::setFont(FontId fontId) { FontId prev = _currentFont; _currentFont = fontId; + + assert(_fonts[_currentFont]); + return prev; } int Screen::getFontHeight() const { - // FIXME: add font support for amiga version - if (_vm->gameFlags().platform == Common::kPlatformAmiga) - return 0; - - return *(_fonts[_currentFont].fontData + _fonts[_currentFont].fontDescOffset + 4); + return _fonts[_currentFont]->getHeight(); } int Screen::getFontWidth() const { - // FIXME: add font support for amiga version - if (_vm->gameFlags().platform == Common::kPlatformAmiga) - return 0; - - return *(_fonts[_currentFont].fontData + _fonts[_currentFont].fontDescOffset + 5); + return _fonts[_currentFont]->getWidth(); } int Screen::getCharWidth(uint16 c) const { - // FIXME: add font support for amiga version - if (_vm->gameFlags().platform == Common::kPlatformAmiga) - return 0; - if ((c & 0xFF00) && _sjisFont) return _sjisFont->getFontWidth() >> 1; - if (_fonts[_currentFont].lastGlyph < c) - return 0; - else - return (int)_fonts[_currentFont].charWidthTable[c] + _charWidth; + return _fonts[_currentFont]->getCharWidth(c) + _charWidth; } int Screen::getTextWidth(const char *str) const { - // FIXME: add font support for amiga version - if (_vm->gameFlags().platform == Common::kPlatformAmiga) - return 0; - int curLineLen = 0; int maxLineLen = 0; while (1) { @@ -1050,9 +1130,6 @@ int Screen::getTextWidth(const char *str) const { } void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2) { - // FIXME: add font support for amiga version - if (_vm->gameFlags().platform == Common::kPlatformAmiga) - return; uint8 cmap[2]; cmap[0] = color2; cmap[1] = color1; @@ -1107,73 +1184,19 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2 } void Screen::drawCharANSI(uint8 c, int x, int y) { - Font *fnt = &_fonts[_currentFont]; - - if (c > fnt->lastGlyph) - return; + Font *fnt = _fonts[_currentFont]; + assert(fnt); - uint8 *dst = getPagePtr(_curPage) + y * SCREEN_W + x; - - uint16 bitmapOffset = READ_LE_UINT16(fnt->fontData + fnt->charBitmapOffset + c * 2); - if (bitmapOffset == 0) - return; - - uint8 charWidth = *(fnt->fontData + fnt->charWidthTableOffset + c); - if (!charWidth || charWidth + x > SCREEN_W) - return; + const int charWidth = fnt->getCharWidth(c); + const int charHeight = fnt->getHeight(); - uint8 charH0 = getFontHeight(); - if (!charH0 || charH0 + y > SCREEN_H) + if (x + charWidth > SCREEN_W || y + charHeight > SCREEN_H) return; - uint8 charH1 = *(fnt->fontData + fnt->charHeightTableOffset + c * 2); - uint8 charH2 = *(fnt->fontData + fnt->charHeightTableOffset + c * 2 + 1); - - charH0 -= charH1 + charH2; - - const uint8 *src = fnt->fontData + bitmapOffset; - const int pitch = SCREEN_W - charWidth; - - while (charH1--) { - uint8 col = _textColorsMap[0]; - for (int i = 0; i < charWidth; ++i) { - if (col != 0) - *dst = col; - ++dst; - } - dst += pitch; - } - - while (charH2--) { - uint8 b = 0; - for (int i = 0; i < charWidth; ++i) { - uint8 col; - if (i & 1) { - col = _textColorsMap[b >> 4]; - } else { - b = *src++; - col = _textColorsMap[b & 0xF]; - } - if (col != 0) { - *dst = col; - } - ++dst; - } - dst += pitch; - } - - while (charH0--) { - uint8 col = _textColorsMap[0]; - for (int i = 0; i < charWidth; ++i) { - if (col != 0) - *dst = col; - ++dst; - } - dst += pitch; - } + fnt->drawChar(c, getPagePtr(_curPage) + y * SCREEN_W + x, SCREEN_W); if (_curPage == 0 || _curPage == 1) - addDirtyRect(x, y, charWidth, getFontHeight()); + addDirtyRect(x, y, charWidth, charHeight); } void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...) { @@ -2068,85 +2091,94 @@ void Screen::decodeFrameDeltaPage(uint8 *dst, const uint8 *src, int pitch, bool wrapped_decodeFrameDeltaPage<false>(dst, src, pitch); } -void Screen::convertAmigaGfx(uint8 *data, int w, int h, bool offscreen) { - static uint8 tmp[320*200]; - - if (offscreen) { - uint8 *curLine = tmp; - const uint8 *src = data; - int hC = h; - while (hC--) { - uint8 *dst1 = curLine; - uint8 *dst2 = dst1 + 8000; - uint8 *dst3 = dst2 + 8000; - uint8 *dst4 = dst3 + 8000; - uint8 *dst5 = dst4 + 8000; - - int width = w >> 3; - while (width--) { - *dst1++ = *src++; - *dst2++ = *src++; - *dst3++ = *src++; - *dst4++ = *src++; - *dst5++ = *src++; - } - - curLine += 40; +void Screen::convertAmigaGfx(uint8 *data, int w, int h, int depth, bool wsa, int bytesPerPlane) { + const int planeWidth = (bytesPerPlane == -1) ? (w + 7) / 8 : bytesPerPlane; + const int planeSize = planeWidth * h; + const uint imageSize = planeSize * depth; + + // Our static buffer which holds the plane data. We need this + // because the "data" pointer is both source and destination pointer. + // The buffer has enough space to fit the AMIGA MSC files, which are + // the biggest graphics files found in the AMIGA version. + static uint8 temp[40320]; + assert(imageSize <= sizeof(temp)); + + // WSA files store their graphics data in a little different format, than + // the usual AMIGA graphics format used in BitMaps. Thus we need to do + // some special handling for them here. Means we convert them into + // the usual format. + // + // TODO: We might think of moving this conversion into the WSAMovieAmiga + // class. + if (wsa) { + const byte *src = data; + for (int y = 0; y < h; ++y) { + for (int x = 0; x < planeWidth; ++x) + for (int i = 0; i < depth; ++i) + temp[y * planeWidth + x + planeSize * i] = *src++; } } else { - memcpy(tmp, data, w*h); + memcpy(temp, data, imageSize); } for (int y = 0; y < h; ++y) { for (int x = 0; x < w; ++x) { - int bytePos = x/8+y*40; - int bitPos = 7-(x&7); - - byte colorIndex = 0; - colorIndex |= (((tmp[bytePos + 8000 * 0] & (1 << bitPos)) >> bitPos) & 0x1) << 0; - colorIndex |= (((tmp[bytePos + 8000 * 1] & (1 << bitPos)) >> bitPos) & 0x1) << 1; - colorIndex |= (((tmp[bytePos + 8000 * 2] & (1 << bitPos)) >> bitPos) & 0x1) << 2; - colorIndex |= (((tmp[bytePos + 8000 * 3] & (1 << bitPos)) >> bitPos) & 0x1) << 3; - colorIndex |= (((tmp[bytePos + 8000 * 4] & (1 << bitPos)) >> bitPos) & 0x1) << 4; - *data++ = colorIndex; + const int bytePos = x / 8 + y * planeWidth; + const int bitPos = 7 - (x & 7); // x & 7 == x % 8 + + byte col = 0; + + for (int i = 0; i < depth; ++i) + col |= ((temp[bytePos + planeSize * i] >> bitPos) & 1) << i; + + *data++ = col; } } } void Screen::convertAmigaMsc(uint8 *data) { - byte *plane1 = data + 5760 * 1; - byte *plane2 = data + 5760 * 2; - byte *plane3 = data + 5760 * 3; - byte *plane4 = data + 5760 * 4; - byte *plane5 = data + 5760 * 5; - byte *plane6 = data + 5760 * 6; - for (int i = 0; i < 5760; ++i) { - byte d = plane6[i]; - d = (plane5[i] |= d); - d = (plane4[i] |= d); - d = (plane3[i] |= d); - d = (plane2[i] |= d); - d = (plane1[i] |= d); - } - byte dst[320*144]; - memset(dst, 0, sizeof(dst)); - static const byte flagTable[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; - for (int y = 0; y < 144; ++y) { - for (int x = 0; x < 320; ++x) { - if (!(flagTable[x&7] & data[y*40+(x>>3)])) - dst[y*320+x] |= 0x80; - - int layer = 0; - for (int i = 0; i < 7; ++i) { - if (flagTable[x&7] & data[y*40+(x>>3)+i*5760]) - layer = i; - } + // MSC files are always 320x144, thus we can safely assume + // this to be correct. Also they contain 7 planes instead + // of the normal 5 planes, which is used in 32 color mode. + // The need for 7 planes can be explained, because the MSC + // files have 6 bits for the layer number (bits 1 to 6) + // and one bit for the "blocked" flag (bit 0), and every + // plane contains one bit per pixel. + convertAmigaGfx(data, 320, 144, 7); + + // We need to do some post conversion, since + // the AMIGA MSC format is different from the DOS + // one we use internally for our code.That is even + // after converting it from the AMIGA plane based + // approach to one byte per pixel approach. + for (int i = 0; i < 320 * 144; ++i) { + // The lowest bit indicates, whether the position + // is walkable or not. If the bit is set, the + // position is walkable, elsewise it is blocked. + if (data[i] & 1) + data[i] &= 0xFE; + else + data[i] |= 0x80; - if (layer) - dst[y*320+x] |= (layer+1); - } + // The graphics layer for the pixel is saved + // in the following format: + // The highest bit set indicates the number of + // the graphics layer. We count the first + // bit as 0 here, thus we need to add one, + // to get the correct number. + // + // Funnily since the first bit (bit 0) is + // resevered for testing whether the position + // is walkable or not, there is no possibility + // for layer 1 to be present. + int layer = 0; + for (int k = 0; k < 7; ++k) + if (data[i] & (1 << k)) + layer = k + 1; + + data[i] &= 0x80; + data[i] |= layer; } - memcpy(data, dst, 320*144); } template<bool noXor> @@ -2794,6 +2826,7 @@ void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, Palette uint8 *srcPtr = srcData + 10 + palSize; uint8 *dstData = getPagePtr(dstPage); + memset(dstData, 0, SCREEN_PAGE_SIZE); if (dstPage == 0 || tempPage == 0) _forceFullUpdate = true; @@ -2811,11 +2844,11 @@ void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, Palette error("Unhandled bitmap compression %d", compType); } - if (_vm->gameFlags().platform == Common::kPlatformAmiga) { + if (_isAmiga) { if (!scumm_stricmp(ext, "MSC")) Screen::convertAmigaMsc(dstData); else - Screen::convertAmigaGfx(dstData, 320, 200, false); + Screen::convertAmigaGfx(dstData, 320, 200); } if (skip) @@ -2832,7 +2865,7 @@ bool Screen::loadPalette(const char *filename, Palette &pal) { debugC(3, kDebugLevelScreen, "Screen::loadPalette('%s', %p)", filename, (const void *)&pal); - if (_vm->gameFlags().platform == Common::kPlatformAmiga) + if (_isAmiga) pal.loadAmigaPalette(*stream, 0, stream->size() / Palette::kAmigaBytesPerColor); else if (_vm->gameFlags().platform == Common::kPlatformPC98 && _use16ColorMode) pal.loadPC98Palette(*stream, 0, stream->size() / Palette::kPC98BytesPerColor); @@ -2851,7 +2884,7 @@ bool Screen::loadPaletteTable(const char *filename, int firstPalette) { debugC(3, kDebugLevelScreen, "Screen::loadPaletteTable('%s', %d)", filename, firstPalette); - if (_vm->gameFlags().platform == Common::kPlatformAmiga) { + if (_isAmiga) { const int numColors = getPalette(firstPalette).getNumColors(); const int palSize = getPalette(firstPalette).getNumColors() * Palette::kAmigaBytesPerColor; const int numPals = stream->size() / palSize; @@ -2874,7 +2907,7 @@ bool Screen::loadPaletteTable(const char *filename, int firstPalette) { void Screen::loadPalette(const byte *data, Palette &pal, int bytes) { Common::MemoryReadStream stream(data, bytes, false); - if (_vm->gameFlags().platform == Common::kPlatformAmiga) + if (_isAmiga) pal.loadAmigaPalette(stream, 0, stream.size() / Palette::kAmigaBytesPerColor); else if (_vm->gameFlags().platform == Common::kPlatformPC98 && _use16ColorMode) pal.loadPC98Palette(stream, 0, stream.size() / Palette::kPC98BytesPerColor); @@ -3026,6 +3059,230 @@ void Screen::drawCharSJIS(uint16 c, int x, int y) { #pragma mark - +DOSFont::DOSFont() { + _data = _widthTable = _heightTable = 0; + _colorMap = 0; + _width = _height = _numGlyphs = 0; + _bitmapOffsets = 0; +} + +bool DOSFont::load(Common::SeekableReadStream &file) { + unload(); + + _data = new uint8[file.size()]; + assert(_data); + + file.read(_data, file.size()); + if (file.err()) + return false; + + const uint16 fontSig = READ_LE_UINT16(_data + 2); + + if (fontSig != 0x0500) { + warning("DOSFont: invalid font: %.04X)", fontSig); + return false; + } + + const uint16 descOffset = READ_LE_UINT16(_data + 4); + + _width = _data[descOffset + 5]; + _height = _data[descOffset + 4]; + _numGlyphs = _data[descOffset + 3] + 1; + + _bitmapOffsets = (uint16 *)(_data + READ_LE_UINT16(_data + 6)); + _widthTable = _data + READ_LE_UINT16(_data + 8); + _heightTable = _data + READ_LE_UINT16(_data + 12); + + for (int i = 0; i < _numGlyphs; ++i) + _bitmapOffsets[i] = READ_LE_UINT16(&_bitmapOffsets[i]); + + return true; +} + +int DOSFont::getCharWidth(uint8 c) const { + if (c >= _numGlyphs) + return 0; + return _widthTable[c]; +} + +void DOSFont::drawChar(uint8 c, byte *dst, int pitch) const { + if (c >= _numGlyphs) + return; + + if (!_bitmapOffsets[c]) + return; + + const uint8 *src = _data + _bitmapOffsets[c]; + const uint8 charWidth = _widthTable[c]; + + if (!charWidth) + return; + + pitch -= charWidth; + + uint8 charH1 = _heightTable[c * 2 + 0]; + uint8 charH2 = _heightTable[c * 2 + 1]; + uint8 charH0 = _height - (charH1 + charH2); + + while (charH1--) { + uint8 col = _colorMap[0]; + for (int i = 0; i < charWidth; ++i) { + if (col != 0) + *dst = col; + ++dst; + } + dst += pitch; + } + + while (charH2--) { + uint8 b = 0; + for (int i = 0; i < charWidth; ++i) { + uint8 col; + if (i & 1) { + col = _colorMap[b >> 4]; + } else { + b = *src++; + col = _colorMap[b & 0xF]; + } + if (col != 0) { + *dst = col; + } + ++dst; + } + dst += pitch; + } + + while (charH0--) { + uint8 col = _colorMap[0]; + for (int i = 0; i < charWidth; ++i) { + if (col != 0) + *dst = col; + ++dst; + } + dst += pitch; + } +} + +void DOSFont::unload() { + delete[] _data; + _data = _widthTable = _heightTable = 0; + _colorMap = 0; + _width = _height = _numGlyphs = 0; + _bitmapOffsets = 0; +} + + +AMIGAFont::AMIGAFont() { + _width = _height = 0; + memset(_chars, 0, sizeof(_chars)); +} + +bool AMIGAFont::load(Common::SeekableReadStream &file) { + const uint16 dataSize = file.readUint16BE(); + if (dataSize + 2 != file.size()) + return false; + + _width = file.readByte(); + _height = file.readByte(); + + // Read the character definition offset table + uint16 offsets[ARRAYSIZE(_chars)]; + for (int i = 0; i < ARRAYSIZE(_chars); ++i) + offsets[i] = file.readUint16BE() + 4; + + if (file.err()) + return false; + + for (int i = 0; i < ARRAYSIZE(_chars); ++i) { + file.seek(offsets[i], SEEK_SET); + + _chars[i].yOffset = file.readByte(); + _chars[i].xOffset = file.readByte(); + _chars[i].width = file.readByte(); + file.readByte(); // unused + + // If the y offset is 255, then the character + // does not have any bitmap representation + if (_chars[i].yOffset != 255) { + Character::Graphics &g = _chars[i].graphics; + + g.width = file.readUint16BE(); + g.height = file.readUint16BE(); + + int depth = file.readByte(); + int specialWidth = file.readByte(); + int flags = file.readByte(); + int bytesPerPlane = file.readByte(); + + assert(depth != 0 && specialWidth == 0 && flags == 0 && bytesPerPlane != 0); + + // Allocate a temporary buffer to store the plane data + const int planesSize = bytesPerPlane * g.height * depth; + uint8 *tempData = new uint8[MAX(g.width * g.height, planesSize)]; + assert(tempData); + + file.read(tempData, planesSize); + + // Convert the plane based graphics to our graphic format + Screen::convertAmigaGfx(tempData, g.width, g.height, depth, false, bytesPerPlane); + + // Create a buffer perfectly fitting the character + g.bitmap = new uint8[g.width * g.height]; + assert(g.bitmap); + + memcpy(g.bitmap, tempData, g.width * g.height); + delete[] tempData; + } + + if (file.err()) + return false; + } + + return !file.err(); +} + +int AMIGAFont::getCharWidth(uint8 c) const { + if (c >= 255) + return 0; + return _chars[c].width; +} + +void AMIGAFont::drawChar(uint8 c, byte *dst, int pitch) const { + if (c >= 255) + return; + + if (_chars[c].yOffset == 255) + return; + + dst += _chars[c].yOffset * pitch; + dst += _chars[c].xOffset; + + pitch -= _chars[c].graphics.width; + + const uint8 *src = _chars[c].graphics.bitmap; + assert(src); + + for (int y = 0; y < _chars[c].graphics.height; ++y) { + for (int x = 0; x < _chars[c].graphics.width; ++x) { + if (*src) + *dst = *src; + ++src; + ++dst; + } + + dst += pitch; + } +} + +void AMIGAFont::unload() { + _width = _height = 0; + for (int i = 0; i < ARRAYSIZE(_chars); ++i) + delete[] _chars[i].graphics.bitmap; + memset(_chars, 0, sizeof(_chars)); +} + +#pragma mark - + Palette::Palette(const int numColors) : _palData(0), _numColors(numColors) { _palData = new uint8[numColors * 3]; assert(_palData); @@ -3049,9 +3306,9 @@ void Palette::loadAmigaPalette(Common::ReadStream &stream, int startIndex, int c for (int i = 0; i < colors; ++i) { uint16 col = stream.readUint16BE(); - _palData[(i + startIndex) * 3 + 2] = ((col & 0xF) * 0xFF) / 0x3F; col >>= 4; - _palData[(i + startIndex) * 3 + 1] = ((col & 0xF) * 0xFF) / 0x3F; col >>= 4; - _palData[(i + startIndex) * 3 + 0] = ((col & 0xF) * 0xFF) / 0x3F; col >>= 4; + _palData[(i + startIndex) * 3 + 2] = ((col & 0xF) * 0x3F) / 0xF; col >>= 4; + _palData[(i + startIndex) * 3 + 1] = ((col & 0xF) * 0x3F) / 0xF; col >>= 4; + _palData[(i + startIndex) * 3 + 0] = ((col & 0xF) * 0x3F) / 0xF; col >>= 4; } } @@ -3061,9 +3318,9 @@ void Palette::loadPC98Palette(Common::ReadStream &stream, int startIndex, int co for (int i = 0; i < colors; ++i) { const byte g = stream.readByte(), r = stream.readByte(), b = stream.readByte(); - _palData[(i + startIndex) * 3 + 0] = ((r & 0x0F) * 0x3F) / 0x0F; - _palData[(i + startIndex) * 3 + 1] = ((g & 0x0F) * 0x3F) / 0x0F; - _palData[(i + startIndex) * 3 + 2] = ((b & 0x0F) * 0x3F) / 0x0F; + _palData[(i + startIndex) * 3 + 0] = ((r & 0xF) * 0x3F) / 0xF; + _palData[(i + startIndex) * 3 + 1] = ((g & 0xF) * 0x3F) / 0xF; + _palData[(i + startIndex) * 3 + 2] = ((b & 0xF) * 0x3F) / 0xF; } } diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h index d8380d104d..73a29ee2c7 100644 --- a/engines/kyra/screen.h +++ b/engines/kyra/screen.h @@ -56,15 +56,114 @@ struct ScreenDim { uint16 unkE; }; -struct Font { - uint8 *fontData; - uint8 *charWidthTable; - uint16 fontDescOffset; - uint16 charBitmapOffset; - uint16 charWidthTableOffset; - uint16 charHeightTableOffset; - - uint8 lastGlyph; +/** + * A class that handles KYRA fonts. + */ +class Font { +public: + virtual ~Font() {} + + /** + * Tries to load a file from the given stream + */ + virtual bool load(Common::SeekableReadStream &file) = 0; + + /** + * The font height. + */ + virtual int getHeight() const = 0; + + /** + * The font width, this is the maximal character + * width. + */ + virtual int getWidth() const = 0; + + /** + * Gets the width of a specific character. + */ + virtual int getCharWidth(uint8 c) const = 0; + + /** + * Sets a text palette map. The map contains 16 entries. + */ + virtual void setColorMap(const uint8 *src) = 0; + + /** + * Draws a specific character. + * + * TODO/FIXME: Replace this with a nicer API. Currently + * the user has to assure that the character fits. + * We use this API, since it's hard to assure dirty rect + * handling from outside Screen. + */ + virtual void drawChar(uint8 c, byte *dst, int pitch) const = 0; +}; + +/** + * Implementation of the Font interface for DOS fonts. + * + * TODO: Clean up the implementation. For example we might be able + * to not to keep the whole font in memory. + */ +class DOSFont : public Font { +public: + DOSFont(); + ~DOSFont() { unload(); } + + bool load(Common::SeekableReadStream &file); + int getHeight() const { return _height; } + int getWidth() const { return _width; } + int getCharWidth(uint8 c) const; + void setColorMap(const uint8 *src) { _colorMap = src; } + void drawChar(uint8 c, byte *dst, int pitch) const; + +private: + void unload(); + + const uint8 *_colorMap; + + uint8 *_data; + + int _width, _height; + + uint8 _numGlyphs; + + uint8 *_widthTable; + uint8 *_heightTable; + uint16 *_bitmapOffsets; +}; + +/** + * Implementation of the Font interface for AMIGA fonts. + */ +class AMIGAFont : public Font { +public: + AMIGAFont(); + ~AMIGAFont() { unload(); } + + bool load(Common::SeekableReadStream &file); + int getHeight() const { return _height; } + int getWidth() const { return _width; } + int getCharWidth(uint8 c) const; + void setColorMap(const uint8 *src) {} + void drawChar(uint8 c, byte *dst, int pitch) const; + +private: + void unload(); + + int _width, _height; + + struct Character { + uint8 yOffset, xOffset, width; + + struct Graphics { + uint16 width, height; + uint8 *bitmap; + } graphics; + }; + + Character _chars[255]; }; /** @@ -256,6 +355,11 @@ public: void setPaletteIndex(uint8 index, uint8 red, uint8 green, uint8 blue); virtual void setScreenPalette(const Palette &pal); + // AMIGA version only + bool isInterfacePaletteEnabled() const { return _interfacePaletteEnabled; } + void enableInterfacePalette(bool e); + void setInterfacePalette(const Palette &pal, uint8 r, uint8 g, uint8 b); + void getRealPalette(int num, uint8 *dst); Palette &getPalette(int num); void copyPalette(const int dst, const int src); @@ -342,12 +446,13 @@ public: static void decodeFrameDelta(uint8 *dst, const uint8 *src, bool noXor = false); static void decodeFrameDeltaPage(uint8 *dst, const uint8 *src, const int pitch, bool noXor); - static void convertAmigaGfx(uint8 *data, int w, int h, bool offscreen = true); + static void convertAmigaGfx(uint8 *data, int w, int h, int depth = 5, bool wsa = false, int bytesPerPlane = -1); static void convertAmigaMsc(uint8 *data); protected: uint8 *getPagePtr(int pageNum); void updateDirtyRects(); + void updateDirtyRectsAmiga(); void updateDirtyRectsOvl(); void scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h); @@ -374,6 +479,7 @@ protected: bool _useOverlays; bool _useSJIS; bool _use16ColorMode; + bool _isAmiga; Graphics::FontSJIS *_sjisFont; uint8 _sjisInvisibleColor; @@ -382,7 +488,7 @@ protected: Common::Array<Palette *> _palettes; Palette *_internFadePalette; - Font _fonts[FID_NUM]; + Font *_fonts[FID_NUM]; uint8 _textColorsMap[16]; uint8 *_decodeShapeBuffer; @@ -469,6 +575,9 @@ protected: int _drawShapeVar4; int _drawShapeVar5; + // AMIGA version + bool _interfacePaletteEnabled; + // debug bool _debugEnabled; }; diff --git a/engines/kyra/screen_lok.cpp b/engines/kyra/screen_lok.cpp index 9fdeae1398..ed7bef0178 100644 --- a/engines/kyra/screen_lok.cpp +++ b/engines/kyra/screen_lok.cpp @@ -80,6 +80,9 @@ const ScreenDim *Screen_LoK::getScreenDim(int dim) { } void Screen_LoK::fadeSpecialPalette(int palIndex, int startIndex, int size, int fadeTime) { + if (_vm->gameFlags().platform == Common::kPlatformAmiga) + return; + assert(_vm->palTable1()[palIndex]); Palette tempPal(getPalette(0).getNumColors()); @@ -240,6 +243,22 @@ int Screen_LoK::getRectSize(int x, int y) { return ((x*y) << 3); } +void Screen_LoK::postProcessCursor(uint8 *data, int width, int height, int pitch) { + if (_vm->gameFlags().platform == Common::kPlatformAmiga && _interfacePaletteEnabled) { + pitch -= width; + + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + if (*data != _cursorColorKey) + *data += 32; + ++data; + } + + data += pitch; + } + } +} + #pragma mark - Screen_LoK_16::Screen_LoK_16(KyraEngine_LoK *vm, OSystem *system) : Screen_LoK(vm, system) { diff --git a/engines/kyra/screen_lok.h b/engines/kyra/screen_lok.h index 4eb22df374..ae1d85c0a7 100644 --- a/engines/kyra/screen_lok.h +++ b/engines/kyra/screen_lok.h @@ -59,6 +59,9 @@ public: void addBitBlitRect(int x, int y, int w, int h); void bitBlitRects(); + // AMIGA specific + virtual void postProcessCursor(uint8 *data, int width, int height, int pitch); + protected: enum { kNumBitBlitRects = 10 diff --git a/engines/kyra/script_lok.cpp b/engines/kyra/script_lok.cpp index 849c6b776d..a778a2066b 100644 --- a/engines/kyra/script_lok.cpp +++ b/engines/kyra/script_lok.cpp @@ -231,12 +231,13 @@ int KyraEngine_LoK::o1_fadeSpecialPalette(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_fadeSpecialPalette(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); if (_currentCharacter->sceneId != 45) { if (stackPos(0) == 13) { - // TODO: Check this! _screen->copyPalette(0, 12); _screen->setScreenPalette(_screen->getPalette(0)); } } else { - warning("KyraEngine_LoK::o1_fadeSpecialPalette not implemented"); + setupZanthiaPalette(stackPos(0)); + _screen->getPalette(0).copy(_screen->getPalette(4), 12, 1); + _screen->fadePalette(_screen->getPalette(0), 2); } } else { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_fadeSpecialPalette(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); @@ -579,7 +580,17 @@ int KyraEngine_LoK::o1_restoreAllObjectBackgrounds(EMCState *script) { int KyraEngine_LoK::o1_setCustomPaletteRange(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setCustomPaletteRange(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); - _screen->getPalette(1).copy(_specialPalettes[stackPos(0)], 0, stackPos(2), stackPos(1)); + if (_flags.platform == Common::kPlatformAmiga) { + if (_currentCharacter->sceneId == 45) { + setupZanthiaPalette(stackPos(0)); + } else if (stackPos(0) == 29) { + _screen->copyPalette(0, 11); + } else if (stackPos(0) == 13) { + _screen->copyPalette(0, 12); + } + } else { + _screen->getPalette(1).copy(_specialPalettes[stackPos(0)], 0, stackPos(2), stackPos(1)); + } return 0; } @@ -1081,7 +1092,9 @@ int KyraEngine_LoK::o1_specialEventDisplayBrynnsNote(EMCState *script) { _screen->copyRegion(63, 8, 63, 8, 194, 128, 2, 0); _screen->updateScreen(); _screen->showMouse(); - _screen->setFont(Screen::FID_6_FNT); + + if (_flags.platform != Common::kPlatformAmiga && !_flags.isTalkie) + _screen->setFont(Screen::FID_6_FNT); return 0; } @@ -1092,7 +1105,9 @@ int KyraEngine_LoK::o1_specialEventRemoveBrynnsNote(EMCState *script) { _screen->loadPageFromDisk("HIDPAGE.TMP", 2); _screen->updateScreen(); _screen->showMouse(); - _screen->setFont(Screen::FID_8_FNT); + + if (_flags.platform != Common::kPlatformAmiga && !_flags.isTalkie) + _screen->setFont(Screen::FID_8_FNT); return 0; } @@ -1213,37 +1228,77 @@ int KyraEngine_LoK::o1_findBrightestFireberry(EMCState *script) { int KyraEngine_LoK::o1_setFireberryGlowPalette(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_setFireberryGlowPalette(%p) (%d)", (const void *)script, stackPos(0)); - int palIndex = 0; - switch (stackPos(0)) { - case 0x1E: - palIndex = 9; - break; - case 0x1F: - palIndex = 10; - break; + if (_flags.platform == Common::kPlatformAmiga) { + int palIndex = 0; + + switch (stackPos(0)) { + case -1: + // The original seemed to draw some lines on page 2 here, which looks strange... + //if (!(_brandonStatusBit & 2)) + // warning("Unimplemented case for o1_setFireberryGlowPalette"); + palIndex = 9; + break; - case 0x20: - palIndex = 11; - break; + case 30: + palIndex = 7; + break; - case 0x21: - case -1: - palIndex = 12; - break; + case 31: + palIndex = 8; + break; - default: - palIndex = 8; - } - if (_brandonStatusBit & 2) { - if (_currentCharacter->sceneId != 133 && _currentCharacter->sceneId != 137 && - _currentCharacter->sceneId != 165 && _currentCharacter->sceneId != 173 && - (_currentCharacter->sceneId < 187 || _currentCharacter->sceneId > 198)) { - palIndex = 14; + case 32: + case 33: + palIndex = 9; + break; + + case 28: case 29: default: + palIndex = 6; + } + + if (_brandonStatusBit & 2) { + if (_currentCharacter->sceneId < 187 || _currentCharacter->sceneId > 198) + palIndex = 10; } + + _screen->copyPalette(0, palIndex); + } else { + int palIndex = 0; + + switch (stackPos(0)) { + case 0x1E: + palIndex = 9; + break; + + case 0x1F: + palIndex = 10; + break; + + case 0x20: + palIndex = 11; + break; + + case 0x21: + case -1: + palIndex = 12; + break; + + default: + palIndex = 8; + } + + if (_brandonStatusBit & 2) { + if (_currentCharacter->sceneId != 133 && _currentCharacter->sceneId != 137 && + _currentCharacter->sceneId != 165 && _currentCharacter->sceneId != 173 && + (_currentCharacter->sceneId < 187 || _currentCharacter->sceneId > 198)) { + palIndex = 14; + } + } + + _screen->getPalette(1).copy(_specialPalettes[palIndex], 0, 15, 228); } - _screen->getPalette(1).copy(_specialPalettes[palIndex], 0, 15, 228); return 0; } @@ -1255,9 +1310,11 @@ int KyraEngine_LoK::o1_drinkPotionAnimation(EMCState *script) { int KyraEngine_LoK::o1_makeAmuletAppear(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_makeAmuletAppear(%p) ()", (const void *)script); - WSAMovie_v1 amulet(this); - amulet.open("AMULET.WSA", 1, 0); - if (amulet.opened()) { + Movie *amulet = createWSAMovie(); + assert(amulet); + amulet->open("AMULET.WSA", 1, 0); + + if (amulet->opened()) { assert(_amuleteAnim); _screen->hideMouse(); snd_playSoundEffect(0x70); @@ -1275,7 +1332,7 @@ int KyraEngine_LoK::o1_makeAmuletAppear(EMCState *script) { if (code == 14) snd_playSoundEffect(0x73); - amulet.displayFrame(code, 0, 224, 152, 0, 0, 0); + amulet->displayFrame(code, 0, 224, 152, 0, 0, 0); _animator->_updateScreen = true; while (_system->getMillis() < nextTime) { @@ -1287,6 +1344,8 @@ int KyraEngine_LoK::o1_makeAmuletAppear(EMCState *script) { } _screen->showMouse(); } + + delete amulet; setGameFlag(0x2D); return 0; } @@ -1335,7 +1394,7 @@ int KyraEngine_LoK::o1_waitForConfirmationMouseClick(EMCState *script) { updateInput(); - int input = checkInput(_buttonList, false) & 0xFF; + int input = checkInput(0, false) & 0xFF; removeInputTop(); if (input == 200) break; diff --git a/engines/kyra/seqplayer.cpp b/engines/kyra/seqplayer.cpp index aeac4ce9df..4086d06c00 100644 --- a/engines/kyra/seqplayer.cpp +++ b/engines/kyra/seqplayer.cpp @@ -389,7 +389,8 @@ void SeqPlayer::s1_copyRegionSpecial() { const int x = (Screen::SCREEN_W - _screen->getTextWidth(copyStr)) / 2; const int y = 179; _screen->setTextColorMap(colorMap); - _screen->printText(copyStr, x + 1, y + 1, 0xB, 0xC); + if (_vm->gameFlags().platform != Common::kPlatformAmiga) + _screen->printText(copyStr, x + 1, y + 1, 0xB, 0xC); _screen->printText(copyStr, x, y, 0xF, 0xC); } break; diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp index b5ae7a50ec..206f8f0a87 100644 --- a/engines/kyra/sequences_lok.cpp +++ b/engines/kyra/sequences_lok.cpp @@ -555,7 +555,9 @@ void KyraEngine_LoK::seq_winterScroll1() { _animator->sprites()[0].active = 0; _sprites->_anims[1].play = true; _animator->sprites()[1].active = 1; - setGameFlag(0xA2); + + if (_flags.platform != Common::kPlatformAmiga) + setGameFlag(0xA2); } for (int i = midpoint; i < 123 + numFrames; ++i) { @@ -569,10 +571,15 @@ void KyraEngine_LoK::seq_winterScroll1() { _sprites->_anims[i].play = false; _animator->sprites()[i].active = 0; } - _screen->getPalette(0).copy(palTable2()[0], 0, 20, 228); - _screen->fadePalette(_screen->getPalette(0), 72); - _screen->setScreenPalette(_screen->getPalette(0)); - setGameFlag(0xB3); + + if (_flags.platform == Common::kPlatformAmiga) { + _screen->copyPalette(0, 11); + } else { + _screen->getPalette(0).copy(palTable2()[0], 0, 20, 228); + _screen->fadePalette(_screen->getPalette(0), 72); + _screen->setScreenPalette(_screen->getPalette(0)); + setGameFlag(0xB3); + } } else { delayWithTicks(120); } @@ -673,7 +680,7 @@ void KyraEngine_LoK::seq_makeBrandonNormal2() { _animator->animRefreshNPC(0); delayWithTicks(8); } - _animator->setBrandonAnimSeqSize(4, 48); + _animator->setBrandonAnimSeqSize(3, 48); _currentCharacter->currentAnimFrame = 7; _animator->animRefreshNPC(0); @@ -718,10 +725,16 @@ void KyraEngine_LoK::seq_makeBrandonWisp() { _animator->animRefreshNPC(0); _animator->updateAllObjectShapes(); - if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245) - _screen->fadeSpecialPalette(30, 234, 13, 4); - else if (_currentCharacter->sceneId >= 118 && _currentCharacter->sceneId <= 186) - _screen->fadeSpecialPalette(14, 228, 15, 4); + if (_flags.platform == Common::kPlatformAmiga) { + if ((_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245) || + (_currentCharacter->sceneId >= 118 && _currentCharacter->sceneId <= 186)) + _screen->fadePalette(_screen->getPalette(10), 0x54); + } else { + if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245) + _screen->fadeSpecialPalette(30, 234, 13, 4); + else if (_currentCharacter->sceneId >= 118 && _currentCharacter->sceneId <= 186) + _screen->fadeSpecialPalette(14, 228, 15, 4); + } freeShapes123(); _screen->showMouse(); @@ -770,6 +783,7 @@ void KyraEngine_LoK::seq_dispelMagicAnimation() { void KyraEngine_LoK::seq_fillFlaskWithWater(int item, int type) { int newItem = -1; + static const uint8 flaskTable1[] = { 0x46, 0x48, 0x4A, 0x4C }; static const uint8 flaskTable2[] = { 0x47, 0x49, 0x4B, 0x4D }; @@ -791,63 +805,135 @@ void KyraEngine_LoK::seq_fillFlaskWithWater(int item, int type) { setMouseItem(newItem); _screen->showMouse(); _itemInHand = newItem; + assert(_fullFlask); assert(type < _fullFlask_Size && type >= 0); + static const uint16 voiceEntries[] = { 0x1F40, 0x1F41, 0x1F42, 0x1F45 }; assert(type < ARRAYSIZE(voiceEntries)); + characterSays(voiceEntries[type], _fullFlask[type], 0, -2); } void KyraEngine_LoK::seq_playDrinkPotionAnim(int item, int unk2, int flags) { - uint8 red, green, blue; + if (_flags.platform == Common::kPlatformAmiga) { + uint8 r, g, b; + + switch (item) { + case 60: case 61: + // 0xC22 + r = 50; + g = 8; + b = 8; + break; - switch (item) { - case 60: - case 61: - red = 63; - green = blue = 6; - break; - case 62: - case 63: - red = green = 0; - blue = 67; - break; - case 64: - case 65: - red = 84; - green = 78; - blue = 14; - break; - case 66: - red = blue = 0; - green = 48; - break; - case 67: - red = 100; - green = 48; - blue = 23; - break; - case 68: - red = 73; - green = 0; - blue = 89; - break; - case 69: - red = green = 73; - blue = 86; - break; - default: - red = 33; - green = 66; - blue = 100; - } - red = (uint8)((double)red * 0.63); - green = (uint8)((double)green * 0.63); - blue = (uint8)((double)blue * 0.63); + case 62: case 63: case 76: + case 77: + // 0x00E + r = 0; + g = 0; + b = 58; + break; + + case 64: case 65: + // 0xFF5 + r = 63; + g = 63; + b = 21; + break; + + case 66: + // 0x090 + r = 0; + g = 37; + b = 0; + break; + + case 67: + // 0xC61 + r = 50; + g = 25; + b = 4; + break; + + case 68: + // 0xE2E + r = 58; + g = 8; + b = 58; + break; + + case 69: + // 0xBBB + r = 46; + g = 46; + b = 46; + break; + + default: + // 0xFFF + r = 63; + g = 63; + b = 63; + } + + _screen->setPaletteIndex(16, r, g, b); + } else { + uint8 red, green, blue; + + switch (item) { + case 60: case 61: + red = 63; + green = blue = 6; + break; + + case 62: case 63: + red = green = 0; + blue = 67; + break; + + case 64: case 65: + red = 84; + green = 78; + blue = 14; + break; + + case 66: + red = blue = 0; + green = 48; + break; + + case 67: + red = 100; + green = 48; + blue = 23; + break; + + case 68: + red = 73; + green = 0; + blue = 89; + break; - _screen->setPaletteIndex(0xFE, red, green, blue); + case 69: + red = green = 73; + blue = 86; + break; + + default: + red = 33; + green = 66; + blue = 100; + } + + red = red * 0x3F / 100; + green = green * 0x3F / 100; + blue = blue * 0x3F / 100; + + _screen->setPaletteIndex(0xFE, red, green, blue); + } _screen->hideMouse(); checkAmuletAnimFlags(); @@ -862,7 +948,9 @@ void KyraEngine_LoK::seq_playDrinkPotionAnim(int item, int unk2, int flags) { _animator->animRefreshNPC(0); delayWithTicks(5); } + snd_playSoundEffect(0x34); + for (int i = 0; i < 2; ++i) { _currentCharacter->currentAnimFrame = 130; _animator->animRefreshNPC(0); @@ -886,7 +974,10 @@ void KyraEngine_LoK::seq_playDrinkPotionAnim(int item, int unk2, int flags) { _currentCharacter->currentAnimFrame = 7; _animator->animRefreshNPC(0); freeShapes123(); - _screen->setPaletteIndex(0xFE, 30, 30, 30); + + if (_flags.platform != Common::kPlatformAmiga) + _screen->setPaletteIndex(0xFE, 30, 30, 30); + _screen->showMouse(); } @@ -901,20 +992,25 @@ int KyraEngine_LoK::seq_playEnd() { if (_endSequenceNeedLoading) { snd_playWanderScoreViaMap(50, 1); setupPanPages(); - _finalA = new WSAMovie_v1(this); + + _finalA = createWSAMovie(); assert(_finalA); _finalA->open("finala.wsa", 1, 0); - _finalB = new WSAMovie_v1(this); + + _finalB = createWSAMovie(); assert(_finalB); _finalB->open("finalb.wsa", 1, 0); - _finalC = new WSAMovie_v1(this); + + _finalC = createWSAMovie(); assert(_finalC); _endSequenceNeedLoading = 0; _finalC->open("finalc.wsa", 1, 0); + _screen->_curPage = 0; _beadStateVar = 0; _malcolmFlag = 0; _unkEndSeqVar2 = _system->getMillis() + 600 * _tickLength; + _screen->copyRegion(312, 0, 312, 0, 8, 136, 0, 2); } @@ -943,17 +1039,25 @@ int KyraEngine_LoK::seq_playEnd() { _endSequenceSkipFlag = 1; if (_text->printed()) _text->restoreTalkTextMessageBkgd(2, 0); + _screen->_curPage = 0; _screen->hideMouse(); - _screen->fadeSpecialPalette(32, 228, 20, 60); + + if (_flags.platform != Common::kPlatformAmiga) + _screen->fadeSpecialPalette(32, 228, 20, 60); + delay(60 * _tickLength); + _screen->loadBitmap("GEMHEAL.CPS", 3, 3, &_screen->getPalette(0)); _screen->setScreenPalette(_screen->getPalette(0)); _screen->shuffleScreen(8, 8, 304, 128, 2, 0, 1, 0); + uint32 nextTime = _system->getMillis() + 120 * _tickLength; - _finalA = new WSAMovie_v1(this); + + _finalA = createWSAMovie(); assert(_finalA); _finalA->open("finald.wsa", 1, 0); + delayUntil(nextTime); snd_playSoundEffect(0x40); for (int i = 0; i < 22; ++i) { @@ -967,6 +1071,7 @@ int KyraEngine_LoK::seq_playEnd() { _screen->updateScreen(); } delete _finalA; + _finalA = 0; seq_playEnding(); return 1; @@ -985,11 +1090,13 @@ void KyraEngine_LoK::seq_brandonToStone() { assert(_brandonStoneTable); setupShapes123(_brandonStoneTable, 14, 0); _animator->setBrandonAnimSeqSize(5, 51); + for (int i = 123; i <= 136; ++i) { _currentCharacter->currentAnimFrame = i; _animator->animRefreshNPC(0); delayWithTicks(8); } + _animator->resetBrandonAnimSeqSize(); freeShapes123(); _screen->showMouse(); @@ -1001,8 +1108,17 @@ void KyraEngine_LoK::seq_playEnding() { _screen->hideMouse(); _screen->_curPage = 0; _screen->fadeToBlack(); - _screen->loadBitmap("REUNION.CPS", 3, 3, &_screen->getPalette(0)); - _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); + + if (_flags.platform == Common::kPlatformAmiga) { + _screen->loadBitmap("GEMCUT.CPS", 3, 3, &_screen->getPalette(0)); + _screen->copyRegion(232, 136, 176, 56, 56, 56, 2, 2); + _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); + _screen->copyRegion(0, 0, 0, 0, 320, 200, 0, 2, Screen::CR_NO_P_CHECK); + } else { + _screen->loadBitmap("REUNION.CPS", 3, 3, &_screen->getPalette(0)); + _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); + } + _screen->_curPage = 0; // XXX assert(_homeString); @@ -1035,8 +1151,10 @@ void KyraEngine_LoK::seq_playCredits() { memset(strings, 0, sizeof(strings)); + _screen->enableInterfacePalette(false); + _screen->hideMouse(); - if (!_flags.isTalkie) { + if (!_flags.isTalkie && _flags.platform != Common::kPlatformAmiga) { _screen->loadFont(Screen::FID_CRED6_FNT, "CREDIT6.FNT"); _screen->loadFont(Screen::FID_CRED8_FNT, "CREDIT8.FNT"); } else @@ -1056,7 +1174,8 @@ void KyraEngine_LoK::seq_playCredits() { uint8 *buffer = 0; uint32 size = 0; - if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) { + if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98 + || _flags.platform == Common::kPlatformAmiga) { int sizeTmp = 0; const uint8 *bufferTmp = _staticres->loadRawData(k1CreditsStrings, sizeTmp); buffer = new uint8[sizeTmp]; @@ -1094,12 +1213,12 @@ void KyraEngine_LoK::seq_playCredits() { if (*currentString == 1) { currentString++; - if (!_flags.isTalkie) + if (!_flags.isTalkie && _flags.platform != Common::kPlatformAmiga) _screen->setFont(Screen::FID_CRED6_FNT); } else { if (*currentString == 2) currentString++; - if (!_flags.isTalkie) + if (!_flags.isTalkie && _flags.platform != Common::kPlatformAmiga) _screen->setFont(Screen::FID_CRED8_FNT); } strings[i].font = _screen->_currentFont; @@ -1122,6 +1241,9 @@ void KyraEngine_LoK::seq_playCredits() { _screen->getPalette(2).clear(); _screen->setScreenPalette(_screen->getPalette(2)); + if (_flags.platform == Common::kPlatformAmiga) + _screen->setPaletteIndex(16, 63, 63, 63); + _screen->copyRegion(8, 32, 8, 32, 312, 128, 4, 0, Screen::CR_NO_P_CHECK); _screen->fadePalette(_screen->getPalette(0), 0x5A); @@ -1473,7 +1595,7 @@ int KyraEngine_LoK::handleBeadState() { _beadStateVar = 0; } } else { - _screen->copyBlockToPage(_screen->_curPage, beadState1.x >> 3, beadState1.y, beadState1.width, beadState1.height, _endSequenceBackUpRect); + _screen->copyBlockToPage(_screen->_curPage, beadState1.x, beadState1.y, beadState1.width << 3, beadState1.height, _endSequenceBackUpRect); _screen->addBitBlitRect(beadState1.x, beadState1.y, beadState1.width2, beadState1.height); beadState1.x = x; beadState1.y = y; @@ -1663,6 +1785,14 @@ void KyraEngine_LoK::closeFinalWsa() { } void KyraEngine_LoK::updateKyragemFading() { + if (_flags.platform == Common::kPlatformAmiga) { + // The AMIGA version seems to have no fading for the Kyragem. The code does not + // alter the screen palette. + // + // TODO: Check this in the original. + return; + } + static const uint8 kyraGemPalette[0x28] = { 0x3F, 0x3B, 0x38, 0x34, 0x32, 0x2F, 0x2C, 0x29, 0x25, 0x22, 0x1F, 0x1C, 0x19, 0x16, 0x12, 0x0F, 0x0C, 0x0A, 0x06, 0x03, @@ -1674,14 +1804,17 @@ void KyraEngine_LoK::updateKyragemFading() { return; _kyragemFadingState.timerCount = _system->getMillis() + 4 * _tickLength; + int palPos = 684; for (int i = 0; i < 20; ++i) { _screen->getPalette(0)[palPos++] = kyraGemPalette[i + _kyragemFadingState.rOffset]; _screen->getPalette(0)[palPos++] = kyraGemPalette[i + _kyragemFadingState.gOffset]; _screen->getPalette(0)[palPos++] = kyraGemPalette[i + _kyragemFadingState.bOffset]; } + _screen->setScreenPalette(_screen->getPalette(0)); _animator->_updateScreen = true; + switch (_kyragemFadingState.nextOperation) { case 0: --_kyragemFadingState.bOffset; diff --git a/engines/kyra/sound_amiga.cpp b/engines/kyra/sound_amiga.cpp index 3d552fda0e..6c4c2b19a5 100644 --- a/engines/kyra/sound_amiga.cpp +++ b/engines/kyra/sound_amiga.cpp @@ -156,8 +156,8 @@ void SoundAmiga::playTrack(uint8 track) { case kFileGame: if (track >= 11 && track < ARRAYSIZE(tempoIngame) + 11) { score = track - 11; - loop = loopIngame[track] != 0; - tempo = tempoIngame[track]; + loop = loopIngame[score] != 0; + tempo = tempoIngame[score]; } break; diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp index f644feeb65..9877ceebc4 100644 --- a/engines/kyra/sprites_lol.cpp +++ b/engines/kyra/sprites_lol.cpp @@ -496,9 +496,8 @@ int LoLEngine::checkBlockForWallsAndSufficientSpace(int block, int x, int y, int _monsterCurBlock = block; if (testWallFlag(block, -1, wallFlag)) return 1; - } - - _monsterCurBlock = 0; + _monsterCurBlock = 0; + } if (!(testFlag & 2)) return 0; @@ -1372,12 +1371,12 @@ int LoLEngine::walkMonsterCalcNextStep(MonsterInPlay *monster) { static const int8 walkMonsterTable1[] = { 7, -6, 5, -4, 3, -2, 1, 0 }; static const int8 walkMonsterTable2[] = { -7, 6, -5, 4, -3, 2, -1, 0 }; - if (++_monsterCountUnk > 10) { - _monsterCountUnk = 0; - _monsterShiftAlt ^= 1; + if (++_monsterStepCounter > 10) { + _monsterStepCounter = 0; + _monsterStepMode ^= 1; } - const int8 *tbl = _monsterShiftAlt ? walkMonsterTable2 : walkMonsterTable1; + const int8 *tbl = _monsterStepMode ? walkMonsterTable2 : walkMonsterTable1; int sx = monster->x; int sy = monster->y; @@ -1411,8 +1410,10 @@ int LoLEngine::walkMonsterCalcNextStep(MonsterInPlay *monster) { uint8 w = _levelBlockProperties[_monsterCurBlock].walls[(s >> 1) ^ 2]; if (_wllWallFlags[w] & 0x20) { - if (_wllBuffer3[w] == 5) + if (_wllBuffer3[w] == 5) { openCloseDoor(_monsterCurBlock, 1); + return -1; + } } if (_wllWallFlags[w] & 8) @@ -1423,10 +1424,10 @@ int LoLEngine::walkMonsterCalcNextStep(MonsterInPlay *monster) { } int LoLEngine::getMonsterDistance(uint16 block1, uint16 block2) { - int8 b1x = block1 & 0x1f; - int8 b1y = block1 >> 5; - int8 b2x = block2 & 0x1f; - int8 b2y = block2 >> 5; + int b1x = block1 & 0x1f; + int b1y = block1 >> 5; + int b2x = block2 & 0x1f; + int b2y = block2 >> 5; uint8 dy = ABS(b2y - b1y); uint8 dx = ABS(b2x - b1x); @@ -1434,7 +1435,7 @@ int LoLEngine::getMonsterDistance(uint16 block1, uint16 block2) { if (dx > dy) SWAP(dx, dy); - return (dx << 1) + dy; + return (dx >> 1) + dy; } int LoLEngine::checkForPossibleDistanceAttack(uint16 monsterBlock, int direction, int distance, uint16 curBlock) { @@ -1444,7 +1445,7 @@ int LoLEngine::checkForPossibleDistanceAttack(uint16 monsterBlock, int direction return 5; int dir = calcMonsterDirection(monsterBlock & 0x1f, monsterBlock >> 5, curBlock & 0x1f, curBlock >> 5); - if ((dir & 1) || (dir != direction << 1)) + if ((dir & 1) || (dir != (direction << 1))) return 5; if (((monsterBlock & 0x1f) != (curBlock & 0x1f)) && ((monsterBlock & 0xffe0) != (curBlock & 0xffe0))) diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index c7bef26d61..83f4b22b6d 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -44,7 +44,7 @@ namespace Kyra { -#define RESFILE_VERSION 48 +#define RESFILE_VERSION 49 namespace { bool checkKyraDat(Common::SeekableReadStream *file) { @@ -1598,10 +1598,15 @@ void KyraEngine_LoK::loadMainScreen(int page) { else warning("no main graphics file found"); - if (_flags.platform == Common::kPlatformAmiga) + _screen->copyRegion(0, 0, 0, 0, 320, 200, page, 0, Screen::CR_NO_P_CHECK); + + if (_flags.platform == Common::kPlatformAmiga) { _screen->copyPalette(1, 0); + _screen->setInterfacePalette(_screen->getPalette(1), 0x3F, 0x3F, 0x3F); - _screen->copyRegion(0, 0, 0, 0, 320, 200, page, 0); + // TODO: Move this to a better place + _screen->enableInterfacePalette(true); + } } void KyraEngine_HoF::initStaticResource() { @@ -2249,6 +2254,22 @@ void GUI_LoK::initStaticResource() { _menu[5].item[2].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::controlsChangeWalk); _menu[5].item[4].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::controlsChangeText); _menu[5].item[5].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::controlsApply); + + // The AMIGA version uses different colors, due to its 32 color nature. We did setup the 256 color version + // colors above, so we need to overwrite those with the correct values over here. + if (_vm->gameFlags().platform == Common::kPlatformAmiga) { + for (int i = 0; i < 6; ++i) { + _menu[i].bkgdColor = 17; + _menu[i].color1 = 31; + _menu[i].color2 = 18; + + for (int j = 0; j < _menu[i].numberOfItems; ++j) { + _menu[i].item[j].bkgdColor = 17; + _menu[i].item[j].color1 = 31; + _menu[i].item[j].color2 = 18; + } + } + } } void KyraEngine_LoK::setupButtonData() { diff --git a/engines/kyra/text.cpp b/engines/kyra/text.cpp index 4d511eae01..20094a45ab 100644 --- a/engines/kyra/text.cpp +++ b/engines/kyra/text.cpp @@ -179,7 +179,7 @@ void TextDisplayer::calcWidestLineBounds(int &x1, int &x2, int w, int cx) { void TextDisplayer::restoreTalkTextMessageBkgd(int srcPage, int dstPage) { if (_talkMessagePrinted) { _talkMessagePrinted = false; - _screen->copyRegion(_talkCoords.x, _talkCoords.y, _talkCoords.x, _talkMessageY, _talkCoords.w, _talkMessageH, srcPage, dstPage); + _screen->copyRegion(_talkCoords.x, _talkCoords.y, _talkCoords.x, _talkMessageY, _talkCoords.w, _talkMessageH, srcPage, dstPage, Screen::CR_NO_P_CHECK); } } @@ -200,37 +200,15 @@ void TextDisplayer::printTalkTextMessage(const char *text, int x, int y, uint8 c _screen->copyRegion(_talkCoords.x, _talkMessageY, _talkCoords.x, _talkCoords.y, _talkCoords.w, _talkMessageH, srcPage, dstPage, Screen::CR_NO_P_CHECK); int curPage = _screen->_curPage; _screen->_curPage = srcPage; - for (int i = 0; i < lineCount; ++i) { - top = i * 10 + _talkMessageY; - char *msg = &_talkSubstrings[i * TALK_SUBSTRING_LEN]; - int left = getCenterStringX(msg, x1, x2); - printText(msg, left, top, color, 0xC, 0); - } - _screen->_curPage = curPage; - _talkMessagePrinted = true; -} -void TextDisplayer::printIntroTextMessage(const char *text, int x, int y, uint8 col1, uint8 col2, uint8 col3, int dstPage, Screen::FontId font) { - char *str = preprocessString(text); - int lineCount = buildMessageSubstrings(str); - int top = y - lineCount * 10; - if (top < 0) { - top = 0; - } - _talkMessageY = top; - _talkMessageH = lineCount * 10; - int w = getWidestLineWidth(lineCount); - int x1, x2; - calcWidestLineBounds(x1, x2, w, x); - _talkCoords.x = x1; - _talkCoords.w = w + 2; - int curPage = _screen->setCurPage(dstPage); + if (_vm->gameFlags().platform == Common::kPlatformAmiga) + setTextColor(color); for (int i = 0; i < lineCount; ++i) { top = i * 10 + _talkMessageY; char *msg = &_talkSubstrings[i * TALK_SUBSTRING_LEN]; int left = getCenterStringX(msg, x1, x2); - printText(msg, left, top, col1, col2, col3, font); + printText(msg, left, top, color, 0xC, 0); } _screen->_curPage = curPage; _talkMessagePrinted = true; @@ -248,7 +226,7 @@ void TextDisplayer::printText(const char *str, int x, int y, uint8 c0, uint8 c1, } void TextDisplayer::printCharacterText(const char *text, int8 charNum, int charX) { - uint8 colorTable[] = {0x0F, 0x9, 0x0C9, 0x80, 0x5, 0x81, 0x0E, 0xD8, 0x55, 0x3A, 0x3a}; + uint8 colorTable[] = {0x0F, 0x09, 0xC9, 0x80, 0x5, 0x81, 0x0E, 0xD8, 0x55, 0x3A, 0x3a}; int top, left, x1, x2, w, x; char *msg; @@ -259,6 +237,9 @@ void TextDisplayer::printCharacterText(const char *text, int8 charNum, int charX x = charX; calcWidestLineBounds(x1, x2, w, x); + if (_vm->gameFlags().platform == Common::kPlatformAmiga) + setTextColor(color); + for (int i = 0; i < lineCount; ++i) { top = i * 10 + _talkMessageY; msg = &_talkSubstrings[i * TALK_SUBSTRING_LEN]; @@ -266,4 +247,91 @@ void TextDisplayer::printCharacterText(const char *text, int8 charNum, int charX printText(msg, left, top, color, 0xC, 0); } } + +void TextDisplayer::setTextColor(uint8 color) { + byte r, g, b; + + switch (color) { + case 4: + // 0x09E + r = 0; + g = 37; + b = 58; + break; + + case 5: + // 0xFF5 + r = 63; + g = 63; + b = 21; + break; + + case 27: + // 0x5FF + r = 21; + g = 63; + b = 63; + break; + + case 34: + // 0x8E5 + r = 33; + g = 58; + b = 21; + break; + + case 58: + // 0x9FB + r = 37; + g = 63; + b = 46; + break; + + case 85: + // 0x7CF + r = 29; + g = 50; + b = 63; + break; + + case 114: + case 117: + // 0xFAF + r = 63; + g = 42; + b = 63; + break; + + case 128: + case 129: + // 0xFCC + r = 63; + g = 50; + b = 50; + break; + + case 201: + // 0xFD8 + r = 63; + g = 54; + b = 33; + break; + + case 216: + // 0xFC6 + r = 63; + g = 50; + b = 25; + break; + + default: + // 0xEEE + r = 58; + g = 58; + b = 58; + } + + _screen->setPaletteIndex(0x10, r, g, b); +} + } // end of namespace Kyra diff --git a/engines/kyra/text.h b/engines/kyra/text.h index d45e5f9242..73d77dcb4c 100644 --- a/engines/kyra/text.h +++ b/engines/kyra/text.h @@ -50,8 +50,6 @@ public: virtual void calcWidestLineBounds(int &x1, int &x2, int w, int cx); virtual void restoreTalkTextMessageBkgd(int srcPage, int dstPage); void printTalkTextMessage(const char *text, int x, int y, uint8 color, int srcPage, int dstPage); - void printIntroTextMessage(const char *text, int x, int y, uint8 col1, uint8 col2, uint8 col3, - int dstPage, Screen::FontId font=Screen::FID_8_FNT); virtual void printText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2, Screen::FontId font=Screen::FID_8_FNT); void printCharacterText(const char *text, int8 charNum, int charX); @@ -66,6 +64,9 @@ protected: uint16 y, x, w; }; + // TODO: AMIGA and LoK specific, move to a better location + void setTextColor(uint8 color); + enum { TALK_SUBSTRING_LEN = 80, TALK_SUBSTRING_NUM = 6 @@ -76,6 +77,7 @@ protected: TalkCoords _talkCoords; bool _talkMessagePrinted; }; + } // end of namespace Kyra #endif diff --git a/engines/kyra/text_lok.cpp b/engines/kyra/text_lok.cpp index 3f4bfb65ac..d2128b7037 100644 --- a/engines/kyra/text_lok.cpp +++ b/engines/kyra/text_lok.cpp @@ -322,18 +322,27 @@ void KyraEngine_LoK::characterSays(int vocFile, const char *chatStr, int8 charNu void KyraEngine_LoK::drawSentenceCommand(const char *sentence, int color) { _screen->hideMouse(); - _screen->fillRect(8, 143, 311, 152, 12); + _screen->fillRect(8, 143, 311, 152, _flags.platform == Common::kPlatformAmiga ? 19 : 12); - if (_startSentencePalIndex != color || _fadeText != false) { - _currSentenceColor[0] = _screen->getPalette(0)[765] = _screen->getPalette(0)[color*3]; + if (_flags.platform == Common::kPlatformAmiga) { + if (color != 19) { + _currSentenceColor[0] = 0x3F; + _currSentenceColor[1] = 0x3F; + _currSentenceColor[2] = 0x3F; + + _screen->setInterfacePalette(_screen->getPalette(1), + _currSentenceColor[0], _currSentenceColor[1], _currSentenceColor[2]); + } + } else if (_startSentencePalIndex != color || _fadeText != false) { + _currSentenceColor[0] = _screen->getPalette(0)[765] = _screen->getPalette(0)[color*3+0]; _currSentenceColor[1] = _screen->getPalette(0)[766] = _screen->getPalette(0)[color*3+1]; _currSentenceColor[2] = _screen->getPalette(0)[767] = _screen->getPalette(0)[color*3+2]; _screen->setScreenPalette(_screen->getPalette(0)); - _startSentencePalIndex = 0; + _startSentencePalIndex = color; } - _text->printText(sentence, 8, 143, 0xFF, 12, 0); + _text->printText(sentence, 8, 143, 0xFF, _flags.platform == Common::kPlatformAmiga ? 19 : 12, 0); _screen->showMouse(); setTextFadeTimerCountdown(15); _fadeText = false; @@ -364,10 +373,15 @@ void KyraEngine_LoK::updateTextFade() { } } - _screen->getPalette(0)[765] = _currSentenceColor[0]; - _screen->getPalette(0)[766] = _currSentenceColor[1]; - _screen->getPalette(0)[767] = _currSentenceColor[2]; - _screen->setScreenPalette(_screen->getPalette(0)); + if (_flags.platform == Common::kPlatformAmiga) { + _screen->setInterfacePalette(_screen->getPalette(1), + _currSentenceColor[0], _currSentenceColor[1], _currSentenceColor[2]); + } else { + _screen->getPalette(0)[765] = _currSentenceColor[0]; + _screen->getPalette(0)[766] = _currSentenceColor[1]; + _screen->getPalette(0)[767] = _currSentenceColor[2]; + _screen->setScreenPalette(_screen->getPalette(0)); + } if (finished) { _fadeText = false; diff --git a/engines/kyra/wsamovie.cpp b/engines/kyra/wsamovie.cpp index ef3fd1a966..b221f869b7 100644 --- a/engines/kyra/wsamovie.cpp +++ b/engines/kyra/wsamovie.cpp @@ -75,11 +75,10 @@ int WSAMovie_v1::open(const char *filename, int offscreenDecode, Palette *palBuf } if (_numFrames & 0x8000) { - // This is used in the Amiga version, the wsa playing code - // doesn't include any handling of it though, so we disable - // this warning for now. - //warning("Unhandled wsa flags 0x80"); - _flags |= 0x80; + // This is used in the Amiga version. + if (_vm->gameFlags().platform != Common::kPlatformAmiga) + warning("Unhandled wsa flags 0x8000"); + _flags |= WF_FLIPPED; _numFrames &= 0x7FFF; } _currentFrame = _numFrames; @@ -262,7 +261,7 @@ void WSAMovieAmiga::displayFrame(int frameNum, int pageNum, int x, int y, uint16 if (_currentFrame == _numFrames) { if (!(_flags & WF_NO_FIRST_FRAME)) { Screen::decodeFrameDelta(dst, _deltaBuffer, true); - Screen::convertAmigaGfx(dst, _width, _height); + Screen::convertAmigaGfx(dst, _width, _height, 5, (_flags & WF_FLIPPED) != 0); if (_flags & WF_OFFSCREEN_DECODE) { dst = _offscreenBuffer; @@ -341,7 +340,7 @@ void WSAMovieAmiga::processFrame(int frameNum, uint8 *dst) { const uint8 *src = _frameData + _frameOffsTable[frameNum]; Screen::decodeFrame4(src, _deltaBuffer, _deltaBufferSize); Screen::decodeFrameDelta(dst, _deltaBuffer, true); - Screen::convertAmigaGfx(dst, _width, _height); + Screen::convertAmigaGfx(dst, _width, _height, 5, (_flags & WF_FLIPPED) != 0); src = dst; dst = 0; diff --git a/engines/kyra/wsamovie.h b/engines/kyra/wsamovie.h index 49ac5a28fe..957ee386ef 100644 --- a/engines/kyra/wsamovie.h +++ b/engines/kyra/wsamovie.h @@ -85,6 +85,7 @@ public: WF_OFFSCREEN_DECODE = 0x10, WF_NO_LAST_FRAME = 0x20, WF_NO_FIRST_FRAME = 0x40, + WF_FLIPPED = 0x80, WF_HAS_PALETTE = 0x100, WF_XOR = 0x200 }; |