aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra
diff options
context:
space:
mode:
authorNorbert Lange2009-08-11 22:35:56 +0000
committerNorbert Lange2009-08-11 22:35:56 +0000
commit0836cf6d9b9222255273a9c6f9d91203b13c3bd9 (patch)
tree714c59161aaf7dbc36d7cb6b4e8fcaa9c467e8f9 /engines/kyra
parent8cb42dd6896925106282abd23ce23812d6031989 (diff)
parent65e9ae163ff757ca15af78da4a753a7ee1d25a16 (diff)
downloadscummvm-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.cpp26
-rw-r--r--engines/kyra/gui_lok.cpp62
-rw-r--r--engines/kyra/items_lok.cpp67
-rw-r--r--engines/kyra/kyra_lok.cpp5
-rw-r--r--engines/kyra/kyra_lok.h65
-rw-r--r--engines/kyra/lol.cpp7
-rw-r--r--engines/kyra/lol.h4
-rw-r--r--engines/kyra/saveload_lok.cpp27
-rw-r--r--engines/kyra/scene_lok.cpp64
-rw-r--r--engines/kyra/screen.cpp655
-rw-r--r--engines/kyra/screen.h131
-rw-r--r--engines/kyra/screen_lok.cpp19
-rw-r--r--engines/kyra/screen_lok.h3
-rw-r--r--engines/kyra/script_lok.cpp127
-rw-r--r--engines/kyra/seqplayer.cpp3
-rw-r--r--engines/kyra/sequences_lok.cpp269
-rw-r--r--engines/kyra/sound_amiga.cpp4
-rw-r--r--engines/kyra/sprites_lol.cpp29
-rw-r--r--engines/kyra/staticres.cpp27
-rw-r--r--engines/kyra/text.cpp122
-rw-r--r--engines/kyra/text.h6
-rw-r--r--engines/kyra/text_lok.cpp32
-rw-r--r--engines/kyra/wsamovie.cpp13
-rw-r--r--engines/kyra/wsamovie.h1
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
};