mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-28 04:34:50 +00:00
34c5751948
This fixes some slowdowns in Kyra2 with the OpenGL backend for me. Most of the updateScreen calls saved were introduced by us implementing the original behavior of hiding the mouse before drawing onto the screen and showing it again afterwards, since the mouse cursor is not drawn on the game screen in our implementation (and unlike in the original) this is not necessary.
1134 lines
30 KiB
C++
1134 lines
30 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "kyra/gui_lok.h"
|
|
#include "kyra/kyra_lok.h"
|
|
#include "kyra/animator_lok.h"
|
|
#include "kyra/text.h"
|
|
#include "kyra/timer.h"
|
|
#include "kyra/util.h"
|
|
|
|
#include "common/savefile.h"
|
|
#include "common/system.h"
|
|
|
|
#include "graphics/scaler.h"
|
|
|
|
namespace Kyra {
|
|
|
|
void KyraEngine_LoK::initMainButtonList() {
|
|
_buttonList = &_buttonData[0];
|
|
for (int i = 0; _buttonDataListPtr[i]; ++i)
|
|
_buttonList = _gui->addButtonToList(_buttonList, _buttonDataListPtr[i]);
|
|
}
|
|
|
|
int KyraEngine_LoK::buttonInventoryCallback(Button *caller) {
|
|
int itemOffset = caller->index - 2;
|
|
Item inventoryItem = (int8)_currentCharacter->inventoryItems[itemOffset];
|
|
if (_itemInHand == kItemNone) {
|
|
if (inventoryItem == kItemNone) {
|
|
snd_playSoundEffect(0x36);
|
|
return 0;
|
|
} else {
|
|
_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[getItemListIndex(inventoryItem)], _takenList[0], 179);
|
|
_itemInHand = inventoryItem;
|
|
_currentCharacter->inventoryItems[itemOffset] = kItemNone;
|
|
}
|
|
} else {
|
|
if (inventoryItem != kItemNone) {
|
|
snd_playSoundEffect(0x35);
|
|
_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);
|
|
// 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);
|
|
_currentCharacter->inventoryItems[itemOffset] = _itemInHand;
|
|
_itemInHand = inventoryItem;
|
|
} else {
|
|
snd_playSoundEffect(0x32);
|
|
_screen->drawShape(0, _shapes[216 + _itemInHand], _itemPosX[itemOffset], _itemPosY[itemOffset], 0, 0);
|
|
_screen->setMouseCursor(1, 1, _shapes[0]);
|
|
updateSentenceCommand(_itemList[getItemListIndex(_itemInHand)], _placedList[0], 179);
|
|
_currentCharacter->inventoryItems[itemOffset] = _itemInHand;
|
|
_itemInHand = kItemNone;
|
|
}
|
|
}
|
|
_screen->updateScreen();
|
|
return 0;
|
|
}
|
|
|
|
int KyraEngine_LoK::buttonAmuletCallback(Button *caller) {
|
|
if (!(_deathHandler & 8))
|
|
return 1;
|
|
int jewel = caller->index - 0x14;
|
|
if (_currentCharacter->sceneId == 210) {
|
|
if (_beadStateVar == 4 || _beadStateVar == 6)
|
|
return 1;
|
|
}
|
|
if (!queryGameFlag(0x2D))
|
|
return 1;
|
|
if (_itemInHand != kItemNone) {
|
|
assert(_putDownFirst);
|
|
characterSays(2000, _putDownFirst[0], 0, -2);
|
|
return 1;
|
|
}
|
|
if (queryGameFlag(0xF1)) {
|
|
assert(_waitForAmulet);
|
|
characterSays(2001, _waitForAmulet[0], 0, -2);
|
|
return 1;
|
|
}
|
|
if (!queryGameFlag(0x55 + jewel)) {
|
|
assert(_blackJewel);
|
|
_animator->makeBrandonFaceMouse();
|
|
drawJewelPress(jewel, 1);
|
|
characterSays(2002, _blackJewel[0], 0, -2);
|
|
return 1;
|
|
}
|
|
drawJewelPress(jewel, 0);
|
|
drawJewelsFadeOutStart();
|
|
drawJewelsFadeOutEnd(jewel);
|
|
|
|
_emc->init(&_scriptClick, &_scriptClickData);
|
|
_scriptClick.regs[3] = 0;
|
|
_scriptClick.regs[6] = jewel;
|
|
_emc->start(&_scriptClick, 4);
|
|
|
|
while (_emc->isValid(&_scriptClick))
|
|
_emc->run(&_scriptClick);
|
|
|
|
if (_scriptClick.regs[3])
|
|
return 1;
|
|
|
|
_unkAmuletVar = 1;
|
|
switch (jewel - 1) {
|
|
case 0:
|
|
if (_brandonStatusBit & 1) {
|
|
seq_brandonHealing2();
|
|
} else if (_brandonStatusBit == 0) {
|
|
seq_brandonHealing();
|
|
assert(_healingTip);
|
|
characterSays(2003, _healingTip[0], 0, -2);
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
seq_makeBrandonInv();
|
|
break;
|
|
|
|
case 2:
|
|
if (_brandonStatusBit & 1) {
|
|
assert(_wispJewelStrings);
|
|
characterSays(2004, _wispJewelStrings[0], 0, -2);
|
|
} else {
|
|
if (_brandonStatusBit & 2) {
|
|
// XXX
|
|
seq_makeBrandonNormal2();
|
|
// XXX
|
|
} else {
|
|
// do not check for item in hand again as in the original since some strings are missing
|
|
// in the cd version
|
|
if (_currentCharacter->sceneId >= 109 && _currentCharacter->sceneId <= 198) {
|
|
snd_playWanderScoreViaMap(1, 0);
|
|
seq_makeBrandonWisp();
|
|
snd_playWanderScoreViaMap(17, 0);
|
|
} else {
|
|
seq_makeBrandonWisp();
|
|
}
|
|
setGameFlag(0x9E);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
seq_dispelMagicAnimation();
|
|
assert(_magicJewelString);
|
|
characterSays(2007, _magicJewelString[0], 0, -2);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
_unkAmuletVar = 0;
|
|
return 1;
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
GUI_LoK::GUI_LoK(KyraEngine_LoK *vm, Screen_LoK *screen) : GUI_v1(vm), _vm(vm), _screen(screen) {
|
|
_lastScreenUpdate = 0;
|
|
_menu = 0;
|
|
_pressFlag = false;
|
|
initStaticResource();
|
|
_scrollUpFunctor = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::scrollUp);
|
|
_scrollDownFunctor = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::scrollDown);
|
|
}
|
|
|
|
GUI_LoK::~GUI_LoK() {
|
|
delete[] _menu;
|
|
}
|
|
|
|
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];
|
|
|
|
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;
|
|
}
|
|
|
|
int GUI_LoK::processButtonList(Button *list, uint16 inputFlag, int8 mouseWheel) {
|
|
if ((inputFlag & 0xFF) == 199)
|
|
_pressFlag = true;
|
|
else if ((inputFlag & 0xFF) == 200)
|
|
_pressFlag = false;
|
|
|
|
int returnValue = 0;
|
|
while (list) {
|
|
if (list->flags & 8) {
|
|
list = list->nextButton;
|
|
continue;
|
|
}
|
|
|
|
if (mouseWheel && list->mouseWheel == mouseWheel && list->buttonCallback) {
|
|
if ((*list->buttonCallback)(list))
|
|
break;
|
|
}
|
|
|
|
int x = list->x;
|
|
int y = list->y;
|
|
assert(_screen->getScreenDim(list->dimTableIndex) != 0);
|
|
|
|
if (x < 0)
|
|
x += _screen->getScreenDim(list->dimTableIndex)->w << 3;
|
|
x += _screen->getScreenDim(list->dimTableIndex)->sx << 3;
|
|
|
|
if (y < 0)
|
|
y += _screen->getScreenDim(list->dimTableIndex)->h;
|
|
y += _screen->getScreenDim(list->dimTableIndex)->sy;
|
|
|
|
if (_vm->_mouseX >= x && _vm->_mouseY >= y && x + list->width >= _vm->_mouseX && y + list->height >= _vm->_mouseY) {
|
|
int processMouseClick = 0;
|
|
if (list->flags & 0x400) {
|
|
if ((inputFlag & 0xFF) == 199 || _pressFlag) {
|
|
if (!(list->flags2 & 1)) {
|
|
list->flags2 |= 1;
|
|
list->flags2 |= 4;
|
|
processButton(list);
|
|
_screen->updateScreen();
|
|
inputFlag = 0;
|
|
}
|
|
} else if ((inputFlag & 0xFF) == 200) {
|
|
if (list->flags2 & 1) {
|
|
list->flags2 &= 0xFFFE;
|
|
processButton(list);
|
|
processMouseClick = 1;
|
|
inputFlag = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (processMouseClick) {
|
|
if (list->buttonCallback) {
|
|
if ((*list->buttonCallback)(list))
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
if (list->flags2 & 1) {
|
|
list->flags2 &= 0xFFFE;
|
|
processButton(list);
|
|
}
|
|
|
|
if (list->flags2 & 4) {
|
|
list->flags2 &= 0xFFFB;
|
|
processButton(list);
|
|
_screen->updateScreen();
|
|
}
|
|
}
|
|
|
|
list = list->nextButton;
|
|
}
|
|
|
|
if (!returnValue)
|
|
returnValue = inputFlag & 0xFF;
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
void GUI_LoK::processButton(Button *button) {
|
|
if (!button)
|
|
return;
|
|
|
|
int processType = 0;
|
|
const uint8 *shape = 0;
|
|
Button::Callback callback;
|
|
|
|
int flags = (button->flags2 & 5);
|
|
if (flags == 1) {
|
|
processType = button->data2Val1;
|
|
if (processType == 1)
|
|
shape = button->data2ShapePtr;
|
|
else if (processType == 4)
|
|
callback = button->data2Callback;
|
|
} else if (flags == 4 || flags == 5) {
|
|
processType = button->data1Val1;
|
|
if (processType == 1)
|
|
shape = button->data1ShapePtr;
|
|
else if (processType == 4)
|
|
callback = button->data1Callback;
|
|
} else {
|
|
processType = button->data0Val1;
|
|
if (processType == 1)
|
|
shape = button->data0ShapePtr;
|
|
else if (processType == 4)
|
|
callback = button->data0Callback;
|
|
}
|
|
|
|
int x = button->x;
|
|
int y = button->y;
|
|
assert(_screen->getScreenDim(button->dimTableIndex) != 0);
|
|
if (x < 0)
|
|
x += _screen->getScreenDim(button->dimTableIndex)->w << 3;
|
|
|
|
if (y < 0)
|
|
y += _screen->getScreenDim(button->dimTableIndex)->h;
|
|
|
|
if (processType == 1 && shape)
|
|
_screen->drawShape(_screen->_curPage, shape, x, y, button->dimTableIndex, 0x10);
|
|
else if (processType == 4 && callback)
|
|
(*callback)(button);
|
|
}
|
|
|
|
void GUI_LoK::setGUILabels() {
|
|
int offset = 0;
|
|
int offsetOptions = 0;
|
|
int offsetMainMenu = 0;
|
|
int offsetOn = 0;
|
|
int offsetPC98 = 0;
|
|
|
|
int walkspeedGarbageOffset = 36;
|
|
int menuLabelGarbageOffset = 0;
|
|
|
|
if (_vm->gameFlags().isTalkie) {
|
|
if (_vm->gameFlags().lang == Common::EN_ANY)
|
|
offset = 52;
|
|
else if (_vm->gameFlags().lang == Common::DE_DEU)
|
|
offset = 30;
|
|
else if (_vm->gameFlags().lang == Common::FR_FRA || _vm->gameFlags().lang == Common::IT_ITA)
|
|
offset = 6;
|
|
offsetOn = offsetMainMenu = offsetOptions = offset;
|
|
walkspeedGarbageOffset = 48;
|
|
} else if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
|
|
if (_vm->gameFlags().lang == Common::EN_ANY) {
|
|
offset = offsetOn = 23;
|
|
offsetOptions = 32;
|
|
walkspeedGarbageOffset = 2;
|
|
offsetMainMenu = 23;
|
|
} else if (_vm->gameFlags().lang == Common::DE_DEU) {
|
|
offset = offsetOn = 12;
|
|
offsetOptions = 21;
|
|
walkspeedGarbageOffset = 3;
|
|
offsetMainMenu = 12;
|
|
}
|
|
} else if (_vm->gameFlags().lang == Common::ES_ESP) {
|
|
offsetOn = offsetMainMenu = offsetOptions = offset = -4;
|
|
menuLabelGarbageOffset = 72;
|
|
} else if (_vm->gameFlags().lang == Common::IT_ITA) {
|
|
offsetOn = offsetMainMenu = offsetOptions = offset = 32;
|
|
} else if (_vm->gameFlags().lang == Common::DE_DEU) {
|
|
offset = offsetMainMenu = offsetOn = offsetOptions = 24;
|
|
} else if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
|
|
offset = 1;
|
|
offsetOptions = 10;
|
|
offsetOn = 0;
|
|
walkspeedGarbageOffset = 0;
|
|
} else if (_vm->gameFlags().platform == Common::kPlatformPC98) {
|
|
offsetMainMenu = offsetOptions = offsetOn = offset = 47;
|
|
offsetPC98 = 1;
|
|
}
|
|
|
|
assert(offset + (_vm->gameFlags().isTalkie ? 28 : 23) < _vm->_guiStringsSize);
|
|
assert(offsetOptions + 27 < _vm->_guiStringsSize);
|
|
assert(offsetMainMenu + 19 < _vm->_guiStringsSize);
|
|
|
|
// The Legend of Kyrandia
|
|
_menu[0].menuNameString = _vm->_guiStrings[0];
|
|
// Load a Game
|
|
_menu[0].item[0].itemString = _vm->_guiStrings[1];
|
|
// Save a Game
|
|
_menu[0].item[1].itemString = _vm->_guiStrings[2];
|
|
// Game controls
|
|
_menu[0].item[2].itemString = _vm->_guiStrings[3];
|
|
// Quit playing
|
|
_menu[0].item[3].itemString = _vm->_guiStrings[4];
|
|
// Resume game
|
|
_menu[0].item[4].itemString = _vm->_guiStrings[5];
|
|
|
|
// Cancel
|
|
_menu[2].item[5].itemString = _vm->_guiStrings[10 + offsetPC98];
|
|
|
|
// Enter a description of your saved game:
|
|
_menu[3].menuNameString = _vm->_guiStrings[11 + offsetPC98];
|
|
// Save
|
|
_menu[3].item[0].itemString = _vm->_guiStrings[12 + offsetPC98];
|
|
// Cancel
|
|
_menu[3].item[1].itemString = _vm->_guiStrings[10 + offsetPC98];
|
|
|
|
// Rest in peace, Brandon
|
|
_menu[4].menuNameString = _vm->_guiStrings[13 + offsetPC98];
|
|
// Load a game
|
|
_menu[4].item[0].itemString = _vm->_guiStrings[1];
|
|
// Quit playing
|
|
_menu[4].item[1].itemString = _vm->_guiStrings[4];
|
|
|
|
// Game Controls
|
|
_menu[5].menuNameString = _vm->_guiStrings[6];
|
|
// Yes
|
|
_menu[1].item[0].itemString = _vm->_guiStrings[22 + offset];
|
|
// No
|
|
_menu[1].item[1].itemString = _vm->_guiStrings[23 + offset];
|
|
|
|
// Music is
|
|
_menu[5].item[0].labelString = _vm->_guiStrings[26 + offsetOptions];
|
|
// Sounds are
|
|
_menu[5].item[1].labelString = _vm->_guiStrings[27 + offsetOptions];
|
|
// Walk speed
|
|
_menu[5].item[2].labelString = &_vm->_guiStrings[24 + offsetOptions][walkspeedGarbageOffset];
|
|
// Text speed
|
|
_menu[5].item[4].labelString = _vm->_guiStrings[25 + offsetOptions];
|
|
// Main Menu
|
|
_menu[5].item[5].itemString = &_vm->_guiStrings[19 + offsetMainMenu][menuLabelGarbageOffset];
|
|
|
|
if (_vm->gameFlags().isTalkie)
|
|
// Text & Voice
|
|
_voiceTextString = _vm->_guiStrings[28 + offset];
|
|
|
|
_textSpeedString = _vm->_guiStrings[25 + offsetOptions];
|
|
_onString = _vm->_guiStrings[20 + offsetOn];
|
|
_offString = _vm->_guiStrings[21 + offset];
|
|
_onCDString = _vm->_guiStrings[21];
|
|
}
|
|
|
|
int GUI_LoK::buttonMenuCallback(Button *caller) {
|
|
PauseTimer pause(*_vm->_timer);
|
|
|
|
_displayMenu = true;
|
|
|
|
assert(_vm->_guiStrings);
|
|
assert(_vm->_configStrings);
|
|
|
|
/*
|
|
for (int i = 0; i < _vm->_guiStringsSize; i++)
|
|
debug("GUI string %i: %s", i, _vm->_guiStrings[i]);
|
|
|
|
for (int i = 0; i < _vm->_configStringsSize; i++)
|
|
debug("Config string %i: %s", i, _vm->_configStrings[i]);
|
|
*/
|
|
|
|
setGUILabels();
|
|
if (_vm->_currentCharacter->sceneId == 210 && _vm->_deathHandler == -1) {
|
|
_vm->snd_playSoundEffect(0x36);
|
|
return 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;
|
|
_menuButtonData[i].data1Callback = _redrawButtonFunctor;
|
|
_menuButtonData[i].data2Callback = _redrawButtonFunctor;
|
|
}
|
|
|
|
_screen->savePageToDisk("SEENPAGE.TMP", 0);
|
|
fadePalette();
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
initMenuLayout(_menu[i]);
|
|
|
|
_menuRestoreScreen = true;
|
|
_keyPressed.reset();
|
|
|
|
_toplevelMenu = 0;
|
|
if (_vm->_menuDirectlyToLoad) {
|
|
loadGameMenu(0);
|
|
} else {
|
|
if (!caller)
|
|
_toplevelMenu = 4;
|
|
|
|
initMenu(_menu[_toplevelMenu]);
|
|
updateAllMenuButtons();
|
|
}
|
|
|
|
while (_displayMenu && !_vm->shouldQuit()) {
|
|
processHighlights(_menu[_toplevelMenu]);
|
|
getInput();
|
|
}
|
|
|
|
if (_menuRestoreScreen) {
|
|
restorePalette();
|
|
_screen->loadPageFromDisk("SEENPAGE.TMP", 0);
|
|
} else {
|
|
_screen->deletePageFromDisk(0);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void GUI_LoK::getInput() {
|
|
uint32 now = _vm->_system->getMillis();
|
|
|
|
_vm->checkInput(_menuButtonList);
|
|
_vm->removeInputTop();
|
|
|
|
if (now - _lastScreenUpdate > 50) {
|
|
_vm->_system->updateScreen();
|
|
_lastScreenUpdate = now;
|
|
}
|
|
|
|
_vm->_system->delayMillis(3);
|
|
}
|
|
|
|
int GUI_LoK::resumeGame(Button *button) {
|
|
updateMenuButton(button);
|
|
_displayMenu = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void GUI_LoK::setupSavegames(Menu &menu, int num) {
|
|
Common::InSaveFile *in;
|
|
uint8 startSlot;
|
|
assert(num <= 5);
|
|
|
|
if (_savegameOffset == 0) {
|
|
menu.item[0].itemString = _specialSavegameString;
|
|
menu.item[0].enabled = 1;
|
|
menu.item[0].saveSlot = 0;
|
|
startSlot = 1;
|
|
} else {
|
|
startSlot = 0;
|
|
}
|
|
|
|
for (int i = startSlot; i < num; ++i)
|
|
menu.item[i].enabled = 0;
|
|
|
|
KyraEngine_LoK::SaveHeader header;
|
|
for (int i = startSlot; i < num && uint(_savegameOffset + i) < _saveSlots.size(); i++) {
|
|
if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header))) {
|
|
Common::strlcpy(_savegameNames[i], header.description.c_str(), ARRAYSIZE(_savegameNames[0]));
|
|
|
|
// Trim long GMM save descriptions to fit our save slots
|
|
_screen->_charWidth = -2;
|
|
int fC = _screen->getTextWidth(_savegameNames[i]);
|
|
while (_savegameNames[i][0] && (fC > 240)) {
|
|
_savegameNames[i][strlen(_savegameNames[i]) - 1] = 0;
|
|
fC = _screen->getTextWidth(_savegameNames[i]);
|
|
}
|
|
_screen->_charWidth = 0;
|
|
|
|
Util::convertISOToDOS(_savegameNames[i]);
|
|
|
|
menu.item[i].itemString = _savegameNames[i];
|
|
menu.item[i].enabled = 1;
|
|
menu.item[i].saveSlot = _saveSlots[i + _savegameOffset];
|
|
delete in;
|
|
}
|
|
}
|
|
}
|
|
|
|
int GUI_LoK::saveGameMenu(Button *button) {
|
|
updateSaveFileList(_vm->_targetName);
|
|
|
|
updateMenuButton(button);
|
|
_menu[2].item[5].enabled = true;
|
|
|
|
_screen->loadPageFromDisk("SEENPAGE.TMP", 0);
|
|
_screen->savePageToDisk("SEENPAGE.TMP", 0);
|
|
|
|
_menu[2].menuNameString = _vm->_guiStrings[8]; // Select a position to save to:
|
|
_specialSavegameString = _vm->_guiStrings[_vm->gameFlags().platform == Common::kPlatformPC98 ? 10 : 9]; // [ EMPTY SLOT ]
|
|
for (int i = 0; i < 5; i++)
|
|
_menu[2].item[i].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::saveGame);
|
|
|
|
_savegameOffset = 0;
|
|
setupSavegames(_menu[2], 5);
|
|
|
|
initMenu(_menu[2]);
|
|
updateAllMenuButtons();
|
|
|
|
_displaySubMenu = true;
|
|
_cancelSubMenu = false;
|
|
|
|
while (_displaySubMenu && !_vm->shouldQuit()) {
|
|
processHighlights(_menu[2]);
|
|
getInput();
|
|
}
|
|
|
|
_screen->loadPageFromDisk("SEENPAGE.TMP", 0);
|
|
_screen->savePageToDisk("SEENPAGE.TMP", 0);
|
|
|
|
if (_cancelSubMenu) {
|
|
initMenu(_menu[0]);
|
|
updateAllMenuButtons();
|
|
} else {
|
|
_displayMenu = false;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int GUI_LoK::loadGameMenu(Button *button) {
|
|
updateSaveFileList(_vm->_targetName);
|
|
|
|
if (_vm->_menuDirectlyToLoad) {
|
|
_menu[2].item[5].enabled = false;
|
|
} else {
|
|
updateMenuButton(button);
|
|
_menu[2].item[5].enabled = true;
|
|
}
|
|
|
|
_screen->loadPageFromDisk("SEENPAGE.TMP", 0);
|
|
_screen->savePageToDisk("SEENPAGE.TMP", 0);
|
|
|
|
_specialSavegameString = _vm->_newGameString[0]; //[ START A NEW GAME ]
|
|
_menu[2].menuNameString = _vm->_guiStrings[7]; // Which game would you like to reload?
|
|
for (int i = 0; i < 5; i++)
|
|
_menu[2].item[i].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::loadGame);
|
|
|
|
_savegameOffset = 0;
|
|
setupSavegames(_menu[2], 5);
|
|
|
|
initMenu(_menu[2]);
|
|
updateAllMenuButtons();
|
|
|
|
_displaySubMenu = true;
|
|
_cancelSubMenu = false;
|
|
|
|
_vm->_gameToLoad = -1;
|
|
|
|
while (_displaySubMenu && !_vm->shouldQuit()) {
|
|
processHighlights(_menu[2]);
|
|
getInput();
|
|
}
|
|
|
|
_screen->loadPageFromDisk("SEENPAGE.TMP", 0);
|
|
_screen->savePageToDisk("SEENPAGE.TMP", 0);
|
|
|
|
if (_cancelSubMenu) {
|
|
initMenu(_menu[_toplevelMenu]);
|
|
updateAllMenuButtons();
|
|
} else {
|
|
restorePalette();
|
|
if (_vm->_gameToLoad != -1)
|
|
_vm->loadGameStateCheck(_vm->_gameToLoad);
|
|
_displayMenu = false;
|
|
_menuRestoreScreen = false;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void GUI_LoK::redrawTextfield() {
|
|
_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, _vm->gameFlags().platform == Common::kPlatformAmiga ? 31 : 254);
|
|
_screen->_charWidth = 0;
|
|
|
|
_screen->updateScreen();
|
|
}
|
|
|
|
void GUI_LoK::updateSavegameString() {
|
|
int length;
|
|
|
|
if (_keyPressed.keycode) {
|
|
length = strlen(_savegameName);
|
|
_screen->_charWidth = -2;
|
|
int width = _screen->getTextWidth(_savegameName) + 7;
|
|
_screen->_charWidth = 0;
|
|
|
|
char inputKey = _keyPressed.ascii;
|
|
Util::convertISOToDOS(inputKey);
|
|
|
|
if ((uint8)inputKey > 31 && (uint8)inputKey < (_vm->gameFlags().lang == Common::JA_JPN ? 128 : 226)) {
|
|
if ((length < ARRAYSIZE(_savegameName) - 1) && (width <= 240)) {
|
|
_savegameName[length] = inputKey;
|
|
_savegameName[length + 1] = 0;
|
|
redrawTextfield();
|
|
}
|
|
} else if (_keyPressed.keycode == Common::KEYCODE_BACKSPACE ||
|
|
_keyPressed.keycode == Common::KEYCODE_DELETE) {
|
|
if (length > 0) {
|
|
_savegameName[length - 1] = 0;
|
|
redrawTextfield();
|
|
}
|
|
} else if (_keyPressed.keycode == Common::KEYCODE_RETURN ||
|
|
_keyPressed.keycode == Common::KEYCODE_KP_ENTER) {
|
|
_displaySubMenu = false;
|
|
}
|
|
}
|
|
|
|
_keyPressed.reset();
|
|
}
|
|
|
|
int GUI_LoK::saveGame(Button *button) {
|
|
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
|
|
updateMenuButton(button);
|
|
_vm->_gameToLoad = _menu[2].item[button->index - 0xC].saveSlot;
|
|
|
|
_screen->loadPageFromDisk("SEENPAGE.TMP", 0);
|
|
_screen->savePageToDisk("SEENPAGE.TMP", 0);
|
|
|
|
initMenu(_menu[3]);
|
|
updateAllMenuButtons();
|
|
|
|
_displaySubMenu = true;
|
|
_cancelSubMenu = false;
|
|
|
|
Screen::FontId cf = _screen->setFont(Screen::FID_8_FNT);
|
|
|
|
if (_savegameOffset == 0 && _vm->_gameToLoad == 0) {
|
|
_savegameName[0] = 0;
|
|
} else {
|
|
for (int i = 0; i < 5; i++) {
|
|
if (_menu[2].item[i].saveSlot == _vm->_gameToLoad) {
|
|
Common::strlcpy(_savegameName, _menu[2].item[i].itemString, 31);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
redrawTextfield();
|
|
|
|
_screen->setFont(cf);
|
|
|
|
while (_displaySubMenu && !_vm->shouldQuit()) {
|
|
checkTextfieldInput();
|
|
cf = _screen->setFont(Screen::FID_8_FNT);
|
|
updateSavegameString();
|
|
_screen->setFont(cf);
|
|
processHighlights(_menu[3]);
|
|
}
|
|
|
|
if (_cancelSubMenu) {
|
|
_displaySubMenu = true;
|
|
_cancelSubMenu = false;
|
|
initMenu(_menu[2]);
|
|
updateAllMenuButtons();
|
|
} else {
|
|
if (_savegameOffset == 0 && _vm->_gameToLoad == 0)
|
|
_vm->_gameToLoad = getNextSavegameSlot();
|
|
if (_vm->_gameToLoad > 0) {
|
|
Util::convertDOSToISO(_savegameName);
|
|
|
|
Graphics::Surface thumb;
|
|
createScreenThumbnail(thumb);
|
|
_vm->saveGameStateIntern(_vm->_gameToLoad, _savegameName, &thumb);
|
|
thumb.free();
|
|
}
|
|
}
|
|
|
|
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
|
|
return 0;
|
|
}
|
|
|
|
int GUI_LoK::savegameConfirm(Button *button) {
|
|
updateMenuButton(button);
|
|
_displaySubMenu = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUI_LoK::loadGame(Button *button) {
|
|
updateMenuButton(button);
|
|
_displaySubMenu = false;
|
|
_vm->_gameToLoad = _menu[2].item[button->index - 0xC].saveSlot;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUI_LoK::cancelSubMenu(Button *button) {
|
|
updateMenuButton(button);
|
|
_displaySubMenu = false;
|
|
_cancelSubMenu = true;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUI_LoK::quitPlaying(Button *button) {
|
|
updateMenuButton(button);
|
|
|
|
if (quitConfirm(_vm->_guiStrings[_vm->gameFlags().platform == Common::kPlatformPC98 ? 15 : 14])) { // Are you sure you want to quit playing?
|
|
_vm->quitGame();
|
|
} else {
|
|
initMenu(_menu[_toplevelMenu]);
|
|
updateAllMenuButtons();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool GUI_LoK::quitConfirm(const char *str) {
|
|
_screen->loadPageFromDisk("SEENPAGE.TMP", 0);
|
|
_screen->savePageToDisk("SEENPAGE.TMP", 0);
|
|
|
|
_menu[1].menuNameString = str;
|
|
initMenuLayout(_menu[1]);
|
|
initMenu(_menu[1]);
|
|
|
|
_displaySubMenu = true;
|
|
_cancelSubMenu = true;
|
|
|
|
while (_displaySubMenu && !_vm->shouldQuit()) {
|
|
processHighlights(_menu[1]);
|
|
getInput();
|
|
}
|
|
|
|
_screen->loadPageFromDisk("SEENPAGE.TMP", 0);
|
|
_screen->savePageToDisk("SEENPAGE.TMP", 0);
|
|
|
|
return !_cancelSubMenu;
|
|
}
|
|
|
|
int GUI_LoK::quitConfirmYes(Button *button) {
|
|
updateMenuButton(button);
|
|
_displaySubMenu = false;
|
|
_cancelSubMenu = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUI_LoK::quitConfirmNo(Button *button) {
|
|
updateMenuButton(button);
|
|
_displaySubMenu = false;
|
|
_cancelSubMenu = true;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUI_LoK::gameControlsMenu(Button *button) {
|
|
_vm->readSettings();
|
|
|
|
_screen->loadPageFromDisk("SEENPAGE.TMP", 0);
|
|
_screen->savePageToDisk("SEENPAGE.TMP", 0);
|
|
|
|
if (_vm->gameFlags().isTalkie) {
|
|
//_menu[5].width = 230;
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
//_menu[5].item[i].labelX = 24;
|
|
//_menu[5].item[i].x = 115;
|
|
//_menu[5].item[i].width = 94;
|
|
}
|
|
|
|
_menu[5].item[3].labelString = _voiceTextString; //"Voice / Text "
|
|
_menu[5].item[3].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::controlsChangeVoice);
|
|
|
|
} else {
|
|
//_menu[5].height = 136;
|
|
//_menu[5].item[5].y = 110;
|
|
_menu[5].item[4].enabled = 0;
|
|
_menu[5].item[3].labelString = _textSpeedString; // "Text speed "
|
|
_menu[5].item[3].callback = BUTTON_FUNCTOR(GUI_LoK, this, &GUI_LoK::controlsChangeText);
|
|
}
|
|
|
|
setupControls(_menu[5]);
|
|
|
|
updateAllMenuButtons();
|
|
|
|
_displaySubMenu = true;
|
|
_cancelSubMenu = false;
|
|
|
|
while (_displaySubMenu && !_vm->shouldQuit()) {
|
|
processHighlights(_menu[5]);
|
|
getInput();
|
|
}
|
|
|
|
_screen->loadPageFromDisk("SEENPAGE.TMP", 0);
|
|
_screen->savePageToDisk("SEENPAGE.TMP", 0);
|
|
|
|
if (_cancelSubMenu) {
|
|
initMenu(_menu[_toplevelMenu]);
|
|
updateAllMenuButtons();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void GUI_LoK::setupControls(Menu &menu) {
|
|
switch (_vm->_configMusic) {
|
|
case 0:
|
|
menu.item[0].itemString = _offString; //"Off"
|
|
break;
|
|
case 1:
|
|
menu.item[0].itemString = _onString; //"On"
|
|
break;
|
|
case 2:
|
|
menu.item[0].itemString = _onCDString; //"On + CD"
|
|
break;
|
|
}
|
|
|
|
if (_vm->_configSounds)
|
|
menu.item[1].itemString = _onString; //"On"
|
|
else
|
|
menu.item[1].itemString = _offString; //"Off"
|
|
|
|
|
|
switch (_vm->_configWalkspeed) {
|
|
case 0:
|
|
menu.item[2].itemString = _vm->_configStrings[0]; //"Slowest"
|
|
break;
|
|
case 1:
|
|
menu.item[2].itemString = _vm->_configStrings[1]; //"Slow"
|
|
break;
|
|
case 2:
|
|
menu.item[2].itemString = _vm->_configStrings[2]; //"Normal"
|
|
break;
|
|
case 3:
|
|
menu.item[2].itemString = _vm->_configStrings[3]; //"Fast"
|
|
break;
|
|
case 4:
|
|
menu.item[2].itemString = _vm->_configStrings[4]; //"Fastest"
|
|
break;
|
|
default:
|
|
menu.item[2].itemString = "ERROR";
|
|
}
|
|
|
|
int textControl = 3;
|
|
int clickableOffset = 8;
|
|
if (_vm->gameFlags().isTalkie) {
|
|
textControl = 4;
|
|
clickableOffset = 11;
|
|
|
|
if (_vm->_configVoice == 0) {
|
|
menu.item[4].enabled = 1;
|
|
menu.item[4].labelString = _textSpeedString;
|
|
} else {
|
|
menu.item[4].enabled = 0;
|
|
menu.item[4].labelString = 0;
|
|
}
|
|
|
|
switch (_vm->_configVoice) {
|
|
case 0:
|
|
menu.item[3].itemString = _vm->_configStrings[5]; //"Text only"
|
|
break;
|
|
case 1:
|
|
menu.item[3].itemString = _vm->_configStrings[6]; //"Voice only"
|
|
break;
|
|
case 2:
|
|
menu.item[3].itemString = _vm->_configStrings[7]; //"Voice & Text"
|
|
break;
|
|
default:
|
|
menu.item[3].itemString = "ERROR";
|
|
}
|
|
} else {
|
|
if (_vm->gameFlags().platform == Common::kPlatformAmiga)
|
|
clickableOffset = 5;
|
|
|
|
menu.item[4].enabled = 0;
|
|
menu.item[4].labelString = 0;
|
|
}
|
|
|
|
switch (_vm->_configTextspeed) {
|
|
case 0:
|
|
menu.item[textControl].itemString = _vm->_configStrings[1]; //"Slow"
|
|
break;
|
|
case 1:
|
|
menu.item[textControl].itemString = _vm->_configStrings[2]; //"Normal"
|
|
break;
|
|
case 2:
|
|
menu.item[textControl].itemString = _vm->_configStrings[3]; //"Fast"
|
|
break;
|
|
case 3:
|
|
menu.item[textControl].itemString = _vm->_configStrings[clickableOffset]; //"Clickable"
|
|
break;
|
|
default:
|
|
menu.item[textControl].itemString = "ERROR";
|
|
}
|
|
|
|
initMenuLayout(menu);
|
|
initMenu(menu);
|
|
}
|
|
|
|
int GUI_LoK::controlsChangeMusic(Button *button) {
|
|
updateMenuButton(button);
|
|
|
|
_vm->_configMusic = (_vm->_configMusic + 1) % ((_vm->gameFlags().platform == Common::kPlatformFMTowns) ? 3 : 2);
|
|
setupControls(_menu[5]);
|
|
return 0;
|
|
}
|
|
|
|
int GUI_LoK::controlsChangeSounds(Button *button) {
|
|
updateMenuButton(button);
|
|
|
|
_vm->_configSounds = !_vm->_configSounds;
|
|
setupControls(_menu[5]);
|
|
return 0;
|
|
}
|
|
|
|
int GUI_LoK::controlsChangeWalk(Button *button) {
|
|
updateMenuButton(button);
|
|
|
|
_vm->_configWalkspeed = (_vm->_configWalkspeed + 1) % 5;
|
|
_vm->setWalkspeed(_vm->_configWalkspeed);
|
|
setupControls(_menu[5]);
|
|
return 0;
|
|
}
|
|
|
|
int GUI_LoK::controlsChangeText(Button *button) {
|
|
updateMenuButton(button);
|
|
|
|
_vm->_configTextspeed = (_vm->_configTextspeed + 1) % 4;
|
|
setupControls(_menu[5]);
|
|
return 0;
|
|
}
|
|
|
|
int GUI_LoK::controlsChangeVoice(Button *button) {
|
|
updateMenuButton(button);
|
|
|
|
_vm->_configVoice = (_vm->_configVoice + 1) % 3;
|
|
setupControls(_menu[5]);
|
|
return 0;
|
|
}
|
|
|
|
int GUI_LoK::controlsApply(Button *button) {
|
|
_vm->writeSettings();
|
|
return cancelSubMenu(button);
|
|
}
|
|
|
|
int GUI_LoK::scrollUp(Button *button) {
|
|
updateMenuButton(button);
|
|
|
|
if (_savegameOffset > 0) {
|
|
_savegameOffset--;
|
|
setupSavegames(_menu[2], 5);
|
|
initMenu(_menu[2]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int GUI_LoK::scrollDown(Button *button) {
|
|
updateMenuButton(button);
|
|
|
|
_savegameOffset++;
|
|
if (uint(_savegameOffset + 5) >= _saveSlots.size())
|
|
_savegameOffset = MAX<int>(_saveSlots.size() - 5, 0);
|
|
setupSavegames(_menu[2], 5);
|
|
initMenu(_menu[2]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void GUI_LoK::fadePalette() {
|
|
if (_vm->gameFlags().platform == Common::kPlatformAmiga)
|
|
return;
|
|
|
|
static const int16 menuPalIndexes[] = {248, 249, 250, 251, 252, 253, 254, -1};
|
|
int index = 0;
|
|
|
|
_screen->copyPalette(2, 0);
|
|
|
|
for (int i = 0; i < 768; i++)
|
|
_screen->getPalette(0)[i] >>= 1;
|
|
|
|
while (menuPalIndexes[index] != -1) {
|
|
_screen->getPalette(0).copy(_screen->getPalette(2), menuPalIndexes[index], 1);
|
|
++index;
|
|
}
|
|
|
|
_screen->fadePalette(_screen->getPalette(0), 2);
|
|
}
|
|
|
|
void GUI_LoK::restorePalette() {
|
|
if (_vm->gameFlags().platform == Common::kPlatformAmiga)
|
|
return;
|
|
|
|
_screen->copyPalette(0, 2);
|
|
_screen->fadePalette(_screen->getPalette(0), 2);
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
void KyraEngine_LoK::drawAmulet() {
|
|
static const int16 amuletTable1[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x150, 0x155, 0x15A, 0x15F, 0x164, 0x145, -1};
|
|
static const int16 amuletTable3[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x14F, 0x154, 0x159, 0x15E, 0x163, 0x144, -1};
|
|
static const int16 amuletTable2[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x152, 0x157, 0x15C, 0x161, 0x166, 0x147, -1};
|
|
static const int16 amuletTable4[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x151, 0x156, 0x15B, 0x160, 0x165, 0x146, -1};
|
|
|
|
resetGameFlag(0xF1);
|
|
_screen->hideMouse();
|
|
|
|
int i = 0;
|
|
while (amuletTable1[i] != -1) {
|
|
if (queryGameFlag(87))
|
|
_screen->drawShape(0, _shapes[amuletTable1[i]], _amuletX[0], _amuletY[0], 0, 0);
|
|
|
|
if (queryGameFlag(89))
|
|
_screen->drawShape(0, _shapes[amuletTable2[i]], _amuletX[1], _amuletY[1], 0, 0);
|
|
|
|
if (queryGameFlag(86))
|
|
_screen->drawShape(0, _shapes[amuletTable3[i]], _amuletX[2], _amuletY[2], 0, 0);
|
|
|
|
if (queryGameFlag(88))
|
|
_screen->drawShape(0, _shapes[amuletTable4[i]], _amuletX[3], _amuletY[3], 0, 0);
|
|
|
|
_screen->updateScreen();
|
|
delayWithTicks(3);
|
|
i++;
|
|
}
|
|
_screen->showMouse();
|
|
}
|
|
|
|
} // End of namespace Kyra
|