scummvm/engines/kyra/gui/gui_mr.cpp
athrxx 5109cd081f KYRA: minor cleanup
(add/rename some constants, whitespace)
2024-11-24 17:06:32 +01:00

1699 lines
46 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "kyra/gui/gui_mr.h"
#include "kyra/engine/kyra_mr.h"
#include "kyra/text/text_mr.h"
#include "kyra/resource/resource.h"
#include "kyra/engine/timer.h"
#include "kyra/sound/sound_digital_mr.h"
#include "kyra/graphics/screen.h"
#include "common/system.h"
#include "graphics/scaler.h"
namespace Kyra {
void KyraEngine_MR::loadButtonShapes() {
_res->exists("BUTTONS.SHP", true);
uint8 *data = _res->fileData("BUTTONS.SHP", nullptr);
assert(data);
for (int i = 0; i <= 10; ++i)
addShapeToPool(data, 0x1C7+i, i);
delete[] data;
Button::Callback callback1 = BUTTON_FUNCTOR(KyraEngine_MR, this, &KyraEngine_MR::callbackButton1);
Button::Callback callback2 = BUTTON_FUNCTOR(KyraEngine_MR, this, &KyraEngine_MR::callbackButton2);
Button::Callback callback3 = BUTTON_FUNCTOR(KyraEngine_MR, this, &KyraEngine_MR::callbackButton3);
_gui->getScrollUpButton()->data0Callback = callback1;
_gui->getScrollUpButton()->data1Callback = callback2;
_gui->getScrollUpButton()->data2Callback = callback3;
_gui->getScrollDownButton()->data0Callback = callback1;
_gui->getScrollDownButton()->data1Callback = callback2;
_gui->getScrollDownButton()->data2Callback = callback3;
_mainButtonData[0].data0Callback = callback1;
_mainButtonData[0].data1Callback = callback2;
_mainButtonData[0].data2Callback = callback3;
}
int KyraEngine_MR::callbackButton1(Button *button) {
const uint8 *shapePtr = nullptr;
if (button->index == 1)
shapePtr = getShapePtr(0x1CD);
else if (button->index == 22)
shapePtr = getShapePtr(0x1C7);
else if (button->index == 23)
shapePtr = getShapePtr(0x1CA);
if (shapePtr)
_screen->drawShape(0, shapePtr, button->x, button->y, 0, 0, 0);
return 0;
}
int KyraEngine_MR::callbackButton2(Button *button) {
const uint8 *shapePtr = nullptr;
if (button->index == 1)
shapePtr = getShapePtr(0x1CE);
else if (button->index == 22)
shapePtr = getShapePtr(0x1C9);
else if (button->index == 23)
shapePtr = getShapePtr(0x1CC);
if (shapePtr)
_screen->drawShape(0, shapePtr, button->x, button->y, 0, 0, 0);
return 0;
}
int KyraEngine_MR::callbackButton3(Button *button) {
const uint8 *shapePtr = nullptr;
if (button->index == 1)
shapePtr = getShapePtr(0x1CE);
else if (button->index == 22)
shapePtr = getShapePtr(0x1C8);
else if (button->index == 23)
shapePtr = getShapePtr(0x1CB);
if (shapePtr)
_screen->drawShape(0, shapePtr, button->x, button->y, 0, 0, 0);
return 0;
}
void KyraEngine_MR::showMessage(const char *string, uint8 c0, uint8 c1) {
_shownMessage = string;
restoreCommandLine();
_restoreCommandLine = false;
if (string) {
int x = _text->getCenterStringX(string, 0, 320);
int pageBackUp = _screen->_curPage;
_screen->_curPage = 0;
int y = _commandLineY;
if (_lang == 3) {
_screen->setFontStyles(_screen->_currentFont, Font::kStyleNone);
y -= 3;
_text->printText(string, x, y, 0, 0, 0);
x++;
}
_text->printText(string, x, y, c0, c1, 0);
if (_lang == 3)
_screen->setFontStyles(_screen->_currentFont, Font::kStyleBorder);
_screen->_curPage = pageBackUp;
_screen->updateScreen();
setCommandLineRestoreTimer(7);
}
}
void KyraEngine_MR::showMessageFromCCode(int string, uint8 c0, int) {
showMessage((const char *)getTableEntry(_cCodeFile, string), c0, 0xF0);
}
void KyraEngine_MR::updateItemCommand(Item item, int str, uint8 c0) {
Common::String buffer;
char *src = (char *)getTableEntry(_itemFile, item);
if (_flags.lang != Common::HE_ISR) {
if (_lang != 3) {
while (*src != ' ')
++src;
++src;
*src = toupper(*src);
}
buffer = src;
if (_lang != 3)
buffer += " ";
buffer += (const char *)getTableEntry(_cCodeFile, str);
} else {
buffer = (const char *)getTableEntry(_cCodeFile, str);
buffer = buffer + " " + src + ".";
}
showMessage(buffer.c_str(), c0, 0xF0);
}
void KyraEngine_MR::updateCommandLine() {
if (_restoreCommandLine) {
restoreCommandLine();
_restoreCommandLine = false;
}
}
void KyraEngine_MR::restoreCommandLine() {
int y = _inventoryState ? _interfaceCommandLineY2 : _interfaceCommandLineY1;
_screen->copyBlockToPage(0, 0, y, 320, _interfaceCommandLineH, _interfaceCommandLine);
}
void KyraEngine_MR::updateCLState() {
if (_inventoryState)
_commandLineY = 145;
else
_commandLineY = 189;
}
void KyraEngine_MR::showInventory() {
if (!_screen->isMouseVisible())
return;
if (queryGameFlag(3))
return;
_screen->copyBlockToPage(3, 0, 0, 320, _interfaceH, _interface);
drawMalcolmsMoodText();
_inventoryState = true;
updateCLState();
redrawInventory(30);
drawMalcolmsMoodPointer(-1, 30);
drawScore(30, 215, 191);
if (queryGameFlag(0x97))
drawJestersStaff(1, 30);
_screen->hideMouse();
if (_itemInHand < 0) {
_mouseState = -1;
_screen->setMouseCursor(0, 0, getShapePtr(0));
}
_screen->copyRegion(0, _interfaceCommandLineY1, 0, 0, 320, _interfaceCommandLineH, 0, 2, Screen::CR_NO_P_CHECK);
if (_inventoryScrollSpeed == -1) {
uint32 endTime = _system->getMillis() + _tickLength * 15;
int times = 0;
while (_system->getMillis() < endTime) {
_screen->copyRegion(0, _interfaceCommandLineY1, 0, 0, 320, _interfaceCommandLineH, 0, 2, Screen::CR_NO_P_CHECK);
_screen->copyRegion(0, _interfaceCommandLineY1, 0, 0, 320, _interfaceCommandLineH, 0, 2, Screen::CR_NO_P_CHECK);
++times;
}
times = MAX(times, 1);
int speed = 60 / times;
if (speed <= 1)
_inventoryScrollSpeed = 1;
else if (speed >= 8)
_inventoryScrollSpeed = 8;
else
_inventoryScrollSpeed = speed;
}
int height = _interfaceCommandLineH;
int y = _interfaceCommandLineY1;
int times = 0;
uint32 waitTill = _system->getMillis() + _tickLength;
while (y > _interfaceCommandLineY2) {
_screen->copyRegion(0, 0, 0, y, 320, height, 2, 0, Screen::CR_NO_P_CHECK);
if (times++ == 0)
_screen->updateScreen();
if (_inventoryScrollSpeed == 1 && times == 3) {
while (waitTill > _system->getMillis())
_system->delayMillis(10);
times = 0;
waitTill = _system->getMillis() + _tickLength;
}
height += _inventoryScrollSpeed;
y -= _inventoryScrollSpeed;
}
_screen->copyRegion(0, 0, 0, _interfaceCommandLineY2, 320, _interfaceH, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
initMainButtonList(false);
restorePage3();
_screen->showMouse();
}
void KyraEngine_MR::hideInventory() {
if (queryGameFlag(3))
return;
_inventoryState = false;
updateCLState();
initMainButtonList(true);
_screen->copyBlockToPage(3, 0, 0, 320, _interfaceH, _interface);
_screen->hideMouse();
restorePage3();
flagAnimObjsForRefresh();
drawAnimObjects();
_screen->copyRegion(0, _interfaceCommandLineY2, 0, 0, 320, _interfaceH, 0, 2, Screen::CR_NO_P_CHECK);
if (_inventoryScrollSpeed == -1) {
uint32 endTime = _system->getMillis() + _tickLength * 15;
int times = 0;
while (_system->getMillis() < endTime) {
_screen->copyRegion(0, _interfaceCommandLineY2, 0, 0, 320, _interfaceCommandLineH, 0, 2, Screen::CR_NO_P_CHECK);
_screen->copyRegion(0, _interfaceCommandLineY2, 0, 0, 320, _interfaceCommandLineH, 0, 2, Screen::CR_NO_P_CHECK);
++times;
}
times = MAX(times, 1);
int speed = 60 / times;
if (speed <= 1)
_inventoryScrollSpeed = 1;
else if (speed >= 8)
_inventoryScrollSpeed = 8;
else
_inventoryScrollSpeed = speed;
}
int y = _interfaceCommandLineY2;
int y2 = _interfaceCommandLineY2 + _inventoryScrollSpeed;
uint32 waitTill = _system->getMillis() + _tickLength;
int times = 0;
while (y2 < _interfaceCommandLineY1) {
_screen->copyRegion(0, 0, 0, y2, 320, _interfaceH, 2, 0, Screen::CR_NO_P_CHECK);
_screen->copyRegion(0, y, 0, y, 320, _inventoryScrollSpeed, 2, 0, Screen::CR_NO_P_CHECK);
if (times++ == 0)
_screen->updateScreen();
if (_inventoryScrollSpeed == 1 && times == 3) {
while (waitTill > _system->getMillis())
_system->delayMillis(10);
times = 0;
waitTill = _system->getMillis() + _tickLength;
}
y += _inventoryScrollSpeed;
y2 += _inventoryScrollSpeed;
}
_screen->copyRegion(0, 0, 0, _interfaceCommandLineY1, 320, _interfaceH, 2, 0, Screen::CR_NO_P_CHECK);
_screen->copyRegion(0, y, 0, y, 320, _interfaceCommandLineY1 - y, 2, 0, Screen::CR_NO_P_CHECK);
_screen->showMouse();
}
void KyraEngine_MR::drawMalcolmsMoodText() {
static const int stringId[] = { 0x32, 0x37, 0x3C };
if (queryGameFlag(0x219))
return;
const char *string = (const char *)getTableEntry(_cCodeFile, stringId[_malcolmsMood]);
Screen::FontId oldFont = _screen->setFont(_lang == 3 ? Screen::FID_CHINESE_FNT : Screen::FID_8_FNT);
_screen->_charSpacing = -2;
int width = _screen->getTextWidth(string);
_screen->_charSpacing = 0;
_screen->setFont(oldFont);
int pageBackUp = _screen->_curPage;
const int x = 280 - (width / 2);
int y = 0;
if (_inventoryState) {
y = _interfaceCommandLineY1 + 1;
_screen->_curPage = 0;
} else {
y = 45;
_screen->_curPage = 2;
}
_screen->drawShape(_screen->_curPage, getShapePtr(432), 244, _interfaceCommandLineY1 + 1, 0, 0);
if (_lang == 3) {
_screen->setFontStyles(_screen->_currentFont, Font::kStyleNone);
_text->printText(string, x, y, 0x00, 0x00, 0x00);
_text->printText(string, x + 1, y, 0xFF, 0x00, 0x00);
_screen->setFontStyles(_screen->_currentFont, Font::kStyleBorder);
} else {
_text->printText(string, x, y + (_flags.extraLang != Common::UNK_LANG ? 3 : 1), 0xFF, 0xF0, 0x00);
}
_screen->_curPage = pageBackUp;
}
void KyraEngine_MR::drawMalcolmsMoodPointer(int frame, int page) {
static const uint8 stateTable[] = {
1, 6, 11
};
if (frame == -1)
frame = stateTable[_malcolmsMood];
if (queryGameFlag(0x219))
frame = 13;
if (page == 0) {
_invWsa->displayFrame(frame, 0, 0, 0, 0, nullptr, nullptr);
_screen->updateScreen();
} else if (page == 30) {
_invWsa->displayFrame(frame, 2, 0, -_interfaceCommandLineY2, 0, nullptr, nullptr);
}
_invWsaFrame = frame;
}
void KyraEngine_MR::drawJestersStaff(int type, int page) {
int y = 155;
if (page == 30) {
page = 2;
y -= _interfaceCommandLineY2;
}
int shape = (type != 0) ? 454 : 453;
_screen->drawShape(page, getShapePtr(shape), 217, y, 0, 0);
}
void KyraEngine_MR::drawScore(int page, int x, int y) {
if (page == 30) {
page = 2;
y -= _interfaceCommandLineY2;
}
int shape1 = _score / 100;
int shape2 = (_score - shape1*100) / 10;
int shape3 = _score % 10;
_screen->drawShape(page, getShapePtr(shape1 + 433), x, y, 0, 0);
x += 8;
_screen->drawShape(page, getShapePtr(shape2 + 433), x, y, 0, 0);
x += 8;
_screen->drawShape(page, getShapePtr(shape3 + 433), x, y, 0, 0);
}
void KyraEngine_MR::drawScoreCounting(int oldScore, int newScore, int drawOld, const int x) {
int y = 189;
if (_inventoryState)
y -= 44;
int old100 = oldScore / 100;
int old010 = (oldScore - old100*100) / 10;
int old001 = oldScore % 10;
int new100 = newScore / 100;
int new010 = (newScore - new100*100) / 10;
int new001 = newScore % 10;
if (drawOld) {
_screen->drawShape(0, getShapePtr(old100+433), x + 0, y, 0, 0);
_screen->drawShape(0, getShapePtr(old010+433), x + 8, y, 0, 0);
_screen->drawShape(0, getShapePtr(old001+433), x + 16, y, 0, 0);
}
if (old100 != new100)
_screen->drawShape(0, getShapePtr(old100+443), x + 0, y, 0, 0);
if (old010 != new010)
_screen->drawShape(0, getShapePtr(old010+443), x + 8, y, 0, 0);
_screen->drawShape(0, getShapePtr(old001+443), x + 16, y, 0, 0);
_screen->updateScreen();
_screen->drawShape(0, getShapePtr(new100+433), x + 0, y, 0, 0);
_screen->drawShape(0, getShapePtr(new010+433), x + 8, y, 0, 0);
_screen->drawShape(0, getShapePtr(new001+433), x + 16, y, 0, 0);
}
int KyraEngine_MR::getScoreX(const char *str) {
Screen::FontId oldFont = _screen->setFont(Screen::FID_8_FNT);
_screen->_charSpacing = -2;
int width = _screen->getTextWidth(str);
int x = 160 + (width / 2) - 32;
if (_flags.lang == Common::HE_ISR)
x = 140 - 32;
_screen->setFont(oldFont);
_screen->_charSpacing = 0;
return x;
}
void KyraEngine_MR::redrawInventory(int page) {
int yOffset = 0;
if (page == 30) {
page = 2;
yOffset = -_interfaceCommandLineY2;
}
int pageBackUp = _screen->_curPage;
_screen->_curPage = page;
for (int i = 0; i < 10; ++i) {
clearInventorySlot(i, page);
if (_mainCharacter.inventory[i] != kItemNone) {
_screen->drawShape(page, getShapePtr(_mainCharacter.inventory[i]+248), _inventoryX[i], _inventoryY[i] + yOffset, 0, 0);
drawInventorySlot(page, _mainCharacter.inventory[i], i);
}
}
_screen->_curPage = pageBackUp;
if (page == 0 || page == 1)
_screen->updateScreen();
}
void KyraEngine_MR::clearInventorySlot(int slot, int page) {
int yOffset = 0;
if (page == 30) {
page = 2;
yOffset = -_interfaceCommandLineY2;
}
_screen->drawShape(page, getShapePtr(slot+422), _inventoryX[slot], _inventoryY[slot] + yOffset, 0, 0);
}
void KyraEngine_MR::drawInventorySlot(int page, Item item, int slot) {
int yOffset = 0;
if (page == 30) {
page = 2;
yOffset = -_interfaceCommandLineY2;
}
_screen->drawShape(page, getShapePtr(item + 248), _inventoryX[slot], _inventoryY[slot] + yOffset, 0, 0);
}
int KyraEngine_MR::buttonInventory(Button *button) {
setNextIdleAnimTimer();
if (!_enableInventory || !_inventoryState || !_screen->isMouseVisible())
return 0;
const int slot = button->index - 5;
const Item slotItem = _mainCharacter.inventory[slot];
if (_itemInHand == kItemNone) {
if (slotItem == kItemNone)
return 0;
clearInventorySlot(slot, 0);
snd_playSoundEffect(0x0B, 0xC8);
setMouseCursor(slotItem);
updateItemCommand(slotItem, (_lang == 1) ? getItemCommandStringPickUp(slotItem) : 0, 0xFF);
_itemInHand = slotItem;
_mainCharacter.inventory[slot] = kItemNone;
} else if (_itemInHand == 27) {
if (!_chatText.empty())
return 0;
return buttonJesterStaff(&_mainButtonData[3]);
} else {
if (slotItem >= 0) {
if (itemInventoryMagic(_itemInHand, slot))
return 0;
snd_playSoundEffect(0x0B, 0xC8);
clearInventorySlot(slot, 0);
drawInventorySlot(0, _itemInHand, slot);
setMouseCursor(slotItem);
updateItemCommand(slotItem, (_lang == 1) ? getItemCommandStringPickUp(slotItem) : 0, 0xFF);
_mainCharacter.inventory[slot] = _itemInHand;
_itemInHand = slotItem;
} else {
snd_playSoundEffect(0x0C, 0xC8);
drawInventorySlot(0, _itemInHand, slot);
_screen->setMouseCursor(0, 0, getShapePtr(0));
updateItemCommand(_itemInHand, (_lang == 1) ? getItemCommandStringInv(_itemInHand) : 2, 0xFF);
_mainCharacter.inventory[slot] = _itemInHand;
_itemInHand = kItemNone;
}
}
return 0;
}
int KyraEngine_MR::buttonMoodChange(Button *button) {
if (queryGameFlag(0x219)) {
snd_playSoundEffect(0x0D, 0xC8);
return 0;
}
static const uint8 frameTable[] = { 1, 6, 11 };
if (_mouseX >= 245 && _mouseX <= 267 && _mouseY >= 159 && _mouseY <= 198)
_malcolmsMood = 0;
else if (_mouseX >= 268 && _mouseX <= 289 && _mouseY >= 159 && _mouseY <= 198)
_malcolmsMood = 1;
else if (_mouseX >= 290 && _mouseX <= 312 && _mouseY >= 159 && _mouseY <= 198)
_malcolmsMood = 2;
int direction = (_invWsaFrame > frameTable[_malcolmsMood]) ? -1 : 1;
if (_invWsaFrame != frameTable[_malcolmsMood]) {
_screen->hideMouse();
setGameFlag(3);
snd_playSoundEffect(0x2E, 0xC8);
while (_invWsaFrame != frameTable[_malcolmsMood]) {
uint32 endTime = _system->getMillis() + 2 * _tickLength;
_invWsaFrame += direction;
drawMalcolmsMoodPointer(_invWsaFrame, 0);
_screen->updateScreen();
while (endTime > _system->getMillis()) {
update();
_system->delayMillis(10);
}
}
resetGameFlag(3);
_screen->showMouse();
drawMalcolmsMoodText();
updateDlgIndex();
EMCData data;
EMCState state;
memset(&data, 0, sizeof(data));
memset(&state, 0, sizeof(state));
_res->exists("_ACTOR.EMC", true);
_emc->load("_ACTOR.EMC", &data, &_opcodes);
_emc->init(&state, &data);
_emc->start(&state, 1);
int vocHigh = _vocHigh;
_vocHigh = 200;
_useActorBuffer = true;
while (_emc->isValid(&state))
_emc->run(&state);
_useActorBuffer = false;
_vocHigh = vocHigh;
_emc->unload(&data);
}
return 0;
}
int KyraEngine_MR::buttonShowScore(Button *button) {
Common::strlcpy(_stringBuffer, (const char *)getTableEntry(_cCodeFile, 18), 500);
char *buffer = _stringBuffer;
while (*buffer != '%')
++buffer;
if (_flags.lang != Common::HE_ISR) {
buffer[0] = (_score / 100) + '0';
buffer[1] = ((_score % 100) / 10) + '0';
buffer[2] = (_score % 10) + '0';
} else {
buffer[0] = (_score % 10) + '0';
buffer[1] = ((_score % 100) / 10) + '0';
buffer[2] = (_score / 100) + '0';
}
while (*buffer != '%')
++buffer;
if (_flags.lang != Common::HE_ISR) {
buffer[0] = (_scoreMax / 100) + '0';
buffer[1] = ((_scoreMax % 100) / 10) + '0';
buffer[2] = (_scoreMax % 10) + '0';
} else {
buffer[0] = (_scoreMax % 10) + '0';
buffer[1] = ((_scoreMax % 100) / 10) + '0';
buffer[2] = (_scoreMax / 100) + '0';
}
showMessage(_stringBuffer, 0xFF, 0xF0);
return 0;
}
int KyraEngine_MR::buttonJesterStaff(Button *button) {
makeCharFacingMouse();
if (_itemInHand == 27) {
removeHandItem();
snd_playSoundEffect(0x0C, 0xC8);
drawJestersStaff(1, 0);
updateItemCommand(27, 2, 0xFF);
setGameFlag(0x97);
} else if (_itemInHand == kItemNone) {
if (queryGameFlag(0x97)) {
snd_playSoundEffect(0x0B, 0xC8);
setHandItem(27);
drawJestersStaff(0, 0);
updateItemCommand(27, 0, 0xFF);
resetGameFlag(0x97);
} else {
if (queryGameFlag(0x2F))
objectChat((const char *)getTableEntry(_cCodeFile, 20), 0, 204, 20);
else
objectChat((const char *)getTableEntry(_cCodeFile, 25), 0, 204, 25);
}
} else {
objectChat((const char *)getTableEntry(_cCodeFile, 30), 0, 204, 30);
}
return 0;
}
void KyraEngine_MR::showAlbum() {
if (!_screen->isMouseVisible() || queryGameFlag(4) || _mouseState != -1)
return;
if (!loadLanguageFile("ALBUM.", _album.file))
error("Couldn't load ALBUM");
if (!queryGameFlag(0x8B))
_album.wsa->open("ALBMGNTH.WSA", 1, nullptr);
_album.backUpRect = new uint8[3100];
assert(_album.backUpRect);
_album.backUpPage = new uint8[64000];
assert(_album.backUpPage);
_album.nextPage = _album.curPage;
_screen->copyRegionToBuffer(0, 0, 0, 320, 200, _screenBuffer);
_screen->copyRegionToBuffer(4, 0, 0, 320, 200, _album.backUpPage);
_screen->copyPalette(1, 0);
_screen->fadeToBlack(9);
int itemInHand = _itemInHand;
removeHandItem();
_screen->loadPalette("ALBUM.COL", _screen->getPalette(0));
loadAlbumPage();
loadAlbumPageWSA();
if (_album.leftPage.wsa->opened())
_album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000, nullptr, nullptr);
if (_album.rightPage.wsa->opened())
_album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000, nullptr, nullptr);
printAlbumPageText();
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
_screen->fadePalette(_screen->getPalette(0), 9);
processAlbum();
_screen->fadeToBlack(9);
_album.wsa->close();
setHandItem(itemInHand);
updateMouse();
restorePage3();
_screen->copyBlockToPage(0, 0, 0, 320, 200, _screenBuffer);
_screen->copyBlockToPage(4, 0, 0, 320, 200, _album.backUpPage);
_screen->copyPalette(0, 1);
_screen->fadePalette(_screen->getPalette(0), 9);
delete[] _album.backUpRect;
_album.backUpRect = nullptr;
delete[] _album.backUpPage;
_album.backUpPage = nullptr;
delete[] _album.file;
_album.file = nullptr;
_eventList.clear();
}
void KyraEngine_MR::loadAlbumPage() {
Common::String filename;
int num = _album.curPage / 2;
if (num == 0) {
filename = "ALBUM0.CPS";
} else if (num >= 1 && num <= 6) {
--num;
num %= 2;
filename = Common::String::format("ALBUM%d.CPS", num+1);
} else {
filename = "ALBUM3.CPS";
}
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 4, Screen::CR_NO_P_CHECK);
_screen->loadBitmap(filename.c_str(), 3, 3, nullptr);
}
void KyraEngine_MR::loadAlbumPageWSA() {
Common::String filename;
_album.leftPage.curFrame = 0;
_album.leftPage.maxFrame = 0;
_album.leftPage.wsa->close();
_album.rightPage.curFrame = 0;
_album.rightPage.maxFrame = 0;
_album.rightPage.wsa->close();
if (_album.curPage) {
filename = Common::String::format("PAGE%x.WSA", _album.curPage);
_album.leftPage.wsa->open(filename.c_str(), 1, nullptr);
_album.leftPage.maxFrame = _album.leftPage.wsa->frames()-1;
}
if (_album.curPage != 14) {
filename = Common::String::format("PAGE%x.WSA", _album.curPage+1);
_album.rightPage.wsa->open(filename.c_str(), 1, nullptr);
_album.rightPage.maxFrame = _album.rightPage.wsa->frames()-1;
}
}
void KyraEngine_MR::printAlbumPageText() {
static const uint8 posY[] = {
0x41, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5A, 0x5A,
0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x3C
};
const int leftY = posY[_album.curPage];
const int rightY = posY[_album.curPage+1];
for (int i = 0; i < 5; ++i) {
const char *str = (const char *)getTableEntry(_album.file, _album.curPage*5+i);
int y = i * (_screen->getFontHeight() + _screen->_lineSpacing) + leftY + 20;
printAlbumText(2, str, 20, y, 10);
}
for (int i = 0; i < 5; ++i) {
const char *str = (const char *)getTableEntry(_album.file, (_album.curPage+1)*5+i);
int y = i * (_screen->getFontHeight() + _screen->_lineSpacing) + rightY + 20;
printAlbumText(2, str, 176, y, 10);
}
albumBackUpRect();
}
void KyraEngine_MR::printAlbumText(int page, const char *str, int x, int y, uint8 c0) {
int oldPage = _screen->_curPage;
_screen->_curPage = page;
static const uint8 colorMap[] = { 0, 0x87, 0xA3, 0 };
_screen->setTextColor(colorMap, 0, 3);
Screen::FontId oldFont = _screen->setFont(Screen::FID_BOOKFONT_FNT);
_screen->_charSpacing = -2;
if (_lang == 3) {
_screen->setFont(Screen::FID_CHINESE_FNT);
_screen->setFontStyles(_screen->_currentFont, Font::kStyleNone);
}
Common::String strr((const char *)str);
Common::String revBuffer;
if (_flags.lang == Common::HE_ISR) {
for (int i = strr.size() - 1; i >= 0; --i)
revBuffer += str[i];
str = revBuffer.c_str();
x += 120 - _screen->getTextWidth(str);
}
_screen->printText(str, x, y, c0, 0);
_screen->setFontStyles(_screen->_currentFont, Font::kStyleBorder);
_screen->_charSpacing = 0;
_screen->setFont(oldFont);
_screen->_curPage = oldPage;
}
void KyraEngine_MR::processAlbum() {
Button albumButtons[5];
GUI_V2_BUTTON(albumButtons[0], 36, 0, 0, 1, 1, 1, 0x4487, 0, 130, 190, 10, 10, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0);
albumButtons[0].buttonCallback = BUTTON_FUNCTOR(KyraEngine_MR, this, &KyraEngine_MR::albumPrevPage);
GUI_V2_BUTTON(albumButtons[1], 37, 0, 0, 1, 1, 1, 0x4487, 0, 177, 190, 10, 10, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0);
albumButtons[1].buttonCallback = BUTTON_FUNCTOR(KyraEngine_MR, this, &KyraEngine_MR::albumNextPage);
GUI_V2_BUTTON(albumButtons[2], 38, 0, 0, 1, 1, 1, 0x4487, 0, 0, 0, 320, 8, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0);
albumButtons[2].buttonCallback = BUTTON_FUNCTOR(KyraEngine_MR, this, &KyraEngine_MR::albumClose);
GUI_V2_BUTTON(albumButtons[3], 39, 0, 0, 1, 1, 1, 0x4487, 0, 8, 8, 144, 180, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0);
albumButtons[3].buttonCallback = BUTTON_FUNCTOR(KyraEngine_MR, this, &KyraEngine_MR::albumPrevPage);
GUI_V2_BUTTON(albumButtons[4], 40, 0, 0, 1, 1, 1, 0x4487, 0, 170, 8, 142, 180, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0);
albumButtons[4].buttonCallback = BUTTON_FUNCTOR(KyraEngine_MR, this, &KyraEngine_MR::albumNextPage);
Button *buttonList = nullptr;
for (int i = 0; i < 5; ++i)
buttonList = _gui->addButtonToList(buttonList, &albumButtons[i]);
_album.leftPage.timer = _album.rightPage.timer = _system->getMillis();
albumNewPage();
_album.running = true;
while (_album.running && !shouldQuit()) {
updateInput();
checkInput(buttonList);
removeInputTop();
if (_album.curPage != _album.nextPage) {
int oldPage = _album.curPage;
_album.curPage = _album.nextPage;
_album.leftPage.wsa->close();
_album.rightPage.wsa->close();
loadAlbumPage();
loadAlbumPageWSA();
if (_album.leftPage.wsa->opened())
_album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000, nullptr, nullptr);
if (_album.rightPage.wsa->opened())
_album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000, nullptr, nullptr);
printAlbumPageText();
snd_playSoundEffect(0x85, 0x80);
albumSwitchPages(oldPage, _album.nextPage, 4);
_album.leftPage.timer = _album.rightPage.timer = 0;
albumNewPage();
_eventList.clear();
}
albumUpdateAnims();
_system->delayMillis(10);
}
_album.leftPage.wsa->close();
_album.rightPage.wsa->close();
}
void KyraEngine_MR::albumNewPage() {
int page = _album.nextPage / 2;
if (!queryGameFlag(0x84+page)) {
albumAnim1();
delayWithTicks(8);
int id = _album.curPage / 2 + 100;
albumChat((const char *)getTableEntry(_album.file, id), 205, id);
if (id == 107) {
_screen->copyRegion(76, 100, 76, 100, 244, 100, 2, 0, Screen::CR_NO_P_CHECK);
albumChat((const char *)getTableEntry(_album.file, 108), 205, 108);
_screen->copyRegion(76, 100, 76, 100, 244, 100, 2, 0, Screen::CR_NO_P_CHECK);
albumChat((const char *)getTableEntry(_album.file, 109), 205, 109);
}
delayWithTicks(5);
albumAnim2();
setGameFlag(0x84+page);
_album.isPage14 = (_album.nextPage == 14);
}
}
void KyraEngine_MR::albumUpdateAnims() {
if (_album.nextPage == 14 && !_album.isPage14)
return;
uint32 nextRun = 0;
nextRun = _album.leftPage.timer + 5 * _tickLength;
if (nextRun < _system->getMillis() && _album.leftPage.wsa->opened()) {
_album.leftPage.wsa->displayFrame(_album.leftPage.curFrame, 2, _albumWSAX[_album.nextPage+0], _albumWSAY[_album.nextPage+0], 0x4000, nullptr, nullptr);
_screen->copyRegion(40, 17, 40, 17, 87, 73, 2, 0, Screen::CR_NO_P_CHECK);
++_album.leftPage.curFrame;
_album.leftPage.timer = _system->getMillis();
if (_album.leftPage.curFrame > _album.leftPage.maxFrame) {
_album.leftPage.curFrame = 0;
if (_album.nextPage == 14) {
_album.isPage14 = false;
_album.leftPage.timer += 100000 * _tickLength;
} else {
_album.leftPage.timer += 180 * _tickLength;
}
}
}
nextRun = _album.rightPage.timer + 5 * _tickLength;
if (nextRun < _system->getMillis() && _album.rightPage.wsa->opened()) {
_album.rightPage.wsa->displayFrame(_album.rightPage.curFrame, 2, _albumWSAX[_album.nextPage+1], _albumWSAY[_album.nextPage+1], 0x4000, nullptr, nullptr);
_screen->copyRegion(194, 20, 194, 20, 85, 69, 2, 0, Screen::CR_NO_P_CHECK);
++_album.rightPage.curFrame;
_album.rightPage.timer = _system->getMillis();
if (_album.rightPage.curFrame > _album.rightPage.maxFrame) {
_album.rightPage.curFrame = 0;
_album.rightPage.timer += 180 * _tickLength;
}
}
_screen->updateScreen();
}
void KyraEngine_MR::albumAnim1() {
for (int i = 6; i >= 3; --i) {
albumRestoreRect();
_album.wsa->displayFrame(i, 2, -100, 90, 0x4000, nullptr, nullptr);
albumUpdateRect();
delayWithTicks(1);
}
albumRestoreRect();
_album.wsa->displayFrame(14, 2, -100, 90, 0x4000, nullptr, nullptr);
albumUpdateRect();
delayWithTicks(1);
}
void KyraEngine_MR::albumAnim2() {
for (int i = 3; i <= 6; ++i) {
albumRestoreRect();
_album.wsa->displayFrame(i, 2, -100, 90, 0x4000, nullptr, nullptr);
albumUpdateRect();
delayWithTicks(1);
}
albumRestoreRect();
_screen->copyRegion(0, 100, 0, 100, 320, 100, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
}
void KyraEngine_MR::albumBackUpRect() {
_screen->copyRegionToBuffer(2, 0, 146, 62, 50, _album.backUpRect);
}
void KyraEngine_MR::albumRestoreRect() {
_screen->copyBlockToPage(2, 0, 146, 62, 50, _album.backUpRect);
}
void KyraEngine_MR::albumUpdateRect() {
_screen->copyRegion(0, 146, 0, 146, 62, 50, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
}
void KyraEngine_MR::albumSwitchPages(int oldPage, int newPage, int srcPage) {
if (newPage > oldPage) {
_screen->wsaFrameAnimationStep(0xA0, 0x07, 0xA0, 0x07, 0x96, 0xBA, 0x64, 0xBA, srcPage, 0, 2);
_screen->copyRegion(260, 7, 260, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
delayWithTicks(2);
_screen->wsaFrameAnimationStep(0xA0, 0x07, 0xA0, 0x07, 0x96, 0xBA, 0x32, 0xBA, srcPage, 0, 2);
_screen->copyRegion(210, 7, 210, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
delayWithTicks(2);
_screen->copyRegion(160, 7, 160, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
delayWithTicks(2);
_screen->wsaFrameAnimationStep(0x10, 0x07, 0x6E, 0x07, 0x96, 0xBA, 0x32, 0xBA, 2, 0, 2);
_screen->updateScreen();
delayWithTicks(2);
_screen->wsaFrameAnimationStep(0x10, 0x07, 0x3C, 0x07, 0x96, 0xBA, 0x64, 0xBA, 2, 0, 2);
_screen->updateScreen();
delayWithTicks(2);
_screen->copyRegion(10, 7, 10, 7, 150, 186, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
} else {
_screen->wsaFrameAnimationStep(0x0A, 0x07, 0x3C, 0x07, 0x96, 0xBA, 0x64, 0xBA, srcPage, 0, 2);
_screen->copyRegion(10, 7, 10, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
delayWithTicks(2);
_screen->wsaFrameAnimationStep(0x0A, 0x07, 0x6E, 0x07, 0x96, 0xBA, 0x32, 0xBA, srcPage, 0, 2);
_screen->copyRegion(60, 7, 60, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
delayWithTicks(2);
_screen->copyRegion(110, 7, 110, 7, 50, 186, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
delayWithTicks(2);
_screen->wsaFrameAnimationStep(0xA0, 0x07, 0xA0, 0x07, 0x96, 0xBA, 0x32, 0xBA, 2, 0, 2);
_screen->updateScreen();
delayWithTicks(2);
_screen->wsaFrameAnimationStep(0xA0, 0x07, 0xA0, 0x07, 0x96, 0xBA, 0x64, 0xBA, 2, 0, 2);
_screen->updateScreen();
delayWithTicks(2);
_screen->copyRegion(160, 7, 160, 7, 150, 186, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
}
}
int KyraEngine_MR::albumNextPage(Button *caller) {
_album.nextPage = _album.curPage + 2;
if (_album.nextPage >= 16) {
_album.nextPage -= 2;
_album.running = false;
}
return 0;
}
int KyraEngine_MR::albumPrevPage(Button *caller) {
_album.nextPage = _album.curPage - 2;
if (_album.nextPage < 0) {
_album.nextPage = 0;
_album.running = false;
}
return 0;
}
int KyraEngine_MR::albumClose(Button *caller) {
_album.running = false;
return 0;
}
#pragma mark -
GUI_MR::GUI_MR(KyraEngine_MR *vm) : GUI_v2(vm), _vm(vm), _screen(vm->_screen) {
}
void GUI_MR::createScreenThumbnail(Graphics::Surface &dst) {
uint8 screenPal[768];
_screen->getRealPalette(0, screenPal);
::createThumbnail(&dst, _vm->_screenBuffer, Screen::SCREEN_W, Screen::SCREEN_H, screenPal);
}
void GUI_MR::flagButtonEnable(Button *button) {
if (!button)
return;
if (button->flags & 8) {
button->flags &= ~8;
processButton(button);
}
}
void GUI_MR::flagButtonDisable(Button *button) {
if (!button)
return;
if (!(button->flags & 8)) {
button->flags |= 8;
processButton(button);
}
}
Common::String GUI_MR::getMenuTitle(const Menu &menu) {
if (!menu.menuNameId)
return Common::String();
return (const char *)_vm->getTableEntry(_vm->_optionsFile, menu.menuNameId);
}
Common::String GUI_MR::getMenuItemTitle(const MenuItem &menuItem) {
if (menuItem.useItemString)
return menuItem.itemString;
if (!menuItem.itemId)
return Common::String();
return (const char *)_vm->getTableEntry(_vm->_optionsFile, menuItem.itemId);
}
Common::String GUI_MR::getMenuItemLabel(const MenuItem &menuItem) {
if (!menuItem.labelId)
return Common::String();
return (const char *)_vm->getTableEntry(_vm->_optionsFile, menuItem.labelId);
}
Common::String GUI_MR::getTableString(int id, bool) {
return Common::String((char *)_vm->getTableEntry(_vm->_optionsFile, id));
}
int GUI_MR::redrawButtonCallback(Button *button) {
if (!_displayMenu)
return 0;
_screen->drawBox(button->x + 1, button->y + 1, button->x + button->width - 1, button->y + button->height - 1, 0xD0);
return 0;
}
int GUI_MR::redrawShadedButtonCallback(Button *button) {
if (!_displayMenu)
return 0;
_screen->drawShadedBox(button->x, button->y, button->x + button->width, button->y + button->height, 0xD1, 0xCF);
return 0;
}
void GUI_MR::resetState(int item) {
_vm->_timer->resetNextRun();
_vm->setNextIdleAnimTimer();
_isDeathMenu = false;
if (!_loadedSave) {
_vm->_itemInHand = kItemNone;
_vm->setHandItem(item);
} else {
_vm->setHandItem(_vm->_itemInHand);
_vm->setCommandLineRestoreTimer(7);
_vm->_shownMessage = " ";
_vm->_restoreCommandLine = false;
}
_buttonListChanged = true;
}
int GUI_MR::quitGame(Button *caller) {
updateMenuButton(caller);
if (choiceDialog(0x0F, 1)) {
_displayMenu = false;
_vm->_runFlag = false;
_vm->fadeOutMusic(60);
_screen->fadeToBlack(60);
_screen->clearCurPage();
}
if (_vm->_runFlag) {
initMenu(*_currentMenu);
updateAllMenuButtons();
}
return 0;
}
int GUI_MR::optionsButton(Button *button) {
PauseTimer pause(*_vm->_timer);
updateButton(&_vm->_mainButtonData[0]);
if (!_vm->_inventoryState && button && !_vm->_menuDirectlyToLoad)
return 0;
_restartGame = false;
_reloadTemporarySave = false;
if (!_screen->isMouseVisible() && button && !_vm->_menuDirectlyToLoad)
return 0;
_screen->setFontStyles(_screen->_currentFont, Font::kStyleNone);
_vm->showMessage(nullptr, 0xF0, 0xF0);
if (_vm->_mouseState < -1) {
_vm->_mouseState = -1;
_screen->setMouseCursor(1, 1, _vm->getShapePtr(0));
return 0;
}
int oldHandItem = _vm->_itemInHand;
_screen->setMouseCursor(0, 0, _vm->getShapePtr(0));
_displayMenu = true;
for (int i = 0; i < 4; ++i) {
if (_vm->_musicSoundChannel != i)
_vm->_soundDigital->stopSound(i);
}
for (uint i = 0; i < ARRAYSIZE(_menuButtons); ++i) {
_menuButtons[i].data0Val1 = _menuButtons[i].data1Val1 = _menuButtons[i].data2Val1 = 4;
_menuButtons[i].data0Callback = _redrawShadedButtonFunctor;
_menuButtons[i].data1Callback = _menuButtons[i].data2Callback = _redrawButtonFunctor;
}
fontBasedMenuResize();
_currentMenu = &_mainMenu;
if (_vm->_menuDirectlyToLoad) {
backUpPage1(_vm->_screenBuffer);
_loadedSave = false;
--_loadMenu.numberOfItems;
loadMenu(nullptr);
++_loadMenu.numberOfItems;
if (_loadedSave) {
if (_restartGame)
_vm->_itemInHand = kItemNone;
} else {
restorePage1(_vm->_screenBuffer);
}
resetState(-1);
_vm->_menuDirectlyToLoad = false;
return 0;
}
if (!button) {
_currentMenu = &_deathMenu;
_isDeathMenu = true;
} else {
_isDeathMenu = false;
}
backUpPage1(_vm->_screenBuffer);
initMenu(*_currentMenu);
_madeSave = false;
_loadedSave = false;
updateAllMenuButtons();
if (_isDeathMenu) {
while (!_screen->isMouseVisible())
_screen->showMouse();
}
while (_displayMenu) {
processHighlights(*_currentMenu);
getInput();
}
if (_vm->_runFlag && !_loadedSave && !_madeSave) {
restorePalette();
restorePage1(_vm->_screenBuffer);
}
if (_vm->_runFlag)
updateMenuButton(&_vm->_mainButtonData[0]);
resetState(oldHandItem);
if (!_loadedSave && _reloadTemporarySave) {
_vm->_unkSceneScreenFlag1 = true;
_vm->loadGameStateCheck(999);
//_vm->_saveFileMan->removeSavefile(_vm->getSavegameFilename(999));
_vm->_unkSceneScreenFlag1 = false;
}
return 0;
}
int GUI_MR::loadMenu(Button *caller) {
updateSaveFileList(_vm->_targetName);
if (!_vm->_menuDirectlyToLoad) {
updateMenuButton(caller);
restorePage1(_vm->_screenBuffer);
backUpPage1(_vm->_screenBuffer);
}
_savegameOffset = 0;
setupSavegameNames(_loadMenu, 5);
initMenu(_loadMenu);
_isLoadMenu = true;
_noLoadProcess = false;
_vm->_gameToLoad = -1;
updateAllMenuButtons();
_screen->updateScreen();
while (_isLoadMenu) {
processHighlights(_loadMenu);
getInput();
}
if (_noLoadProcess) {
if (!_vm->_menuDirectlyToLoad) {
restorePage1(_vm->_screenBuffer);
backUpPage1(_vm->_screenBuffer);
initMenu(*_currentMenu);
updateAllMenuButtons();
}
} else if (_vm->_gameToLoad >= 0) {
restorePage1(_vm->_screenBuffer);
restorePalette();
_vm->_menuDirectlyToLoad = false;
_vm->loadGameStateCheck(_vm->_gameToLoad);
if (_vm->_gameToLoad == 0) {
_restartGame = true;
_vm->runStartupScript(1, 1);
}
_displayMenu = false;
_loadedSave = true;
}
return 0;
}
int GUI_MR::loadSecondChance(Button *button) {
updateMenuButton(button);
_vm->_gameToLoad = 999;
restorePage1(_vm->_screenBuffer);
_vm->loadGameStateCheck(_vm->_gameToLoad);
_displayMenu = false;
_loadedSave = true;
return 0;
}
int GUI_MR::gameOptions(Button *caller) {
updateMenuButton(caller);
restorePage1(_vm->_screenBuffer);
backUpPage1(_vm->_screenBuffer);
bool textEnabled = _vm->textEnabled();
int lang = _vm->_lang;
setupOptionsButtons();
initMenu(_gameOptions);
_isOptionsMenu = true;
while (_isOptionsMenu) {
processHighlights(_gameOptions);
getInput();
}
restorePage1(_vm->_screenBuffer);
backUpPage1(_vm->_screenBuffer);
if (textEnabled && !_vm->textEnabled() && !_vm->speechEnabled()) {
_vm->_configVoice = 1;
_vm->setVolume(KyraEngine_v1::kVolumeSpeech, 75);
choiceDialog(0x1E, 0);
}
if (_vm->_lang != lang) {
_reloadTemporarySave = true;
Graphics::Surface thumb;
createScreenThumbnail(thumb);
_vm->saveGameStateIntern(999, "Autosave", &thumb);
thumb.free();
if (_vm->_lang == 3) {
_screen->setFont(Screen::FID_CHINESE_FNT);
_screen->setFontStyles(Screen::FID_CHINESE_FNT, Font::kStyleNone);
_screen->_lineSpacing = 2;
} else {
_screen->setFont(Screen::FID_8_FNT);
_screen->_lineSpacing = 0;
}
if (!_vm->loadLanguageFile("ITEMS.", _vm->_itemFile))
error("Couldn't load ITEMS");
if (!_vm->loadLanguageFile("SCORE.", _vm->_scoreFile))
error("Couldn't load SCORE");
if (!_vm->loadLanguageFile("C_CODE.", _vm->_cCodeFile))
error("Couldn't load C_CODE");
if (!_vm->loadLanguageFile("SCENES.", _vm->_scenesFile))
error("Couldn't load SCENES");
if (!_vm->loadLanguageFile("OPTIONS.", _vm->_optionsFile))
error("Couldn't load OPTIONS");
if (!_vm->loadLanguageFile("_ACTOR.", _vm->_actorFile))
error("couldn't load _ACTOR");
if (_vm->_lang == 3 || lang == 3)
fontBasedMenuResize();
}
_vm->writeSettings();
initMenu(*_currentMenu);
updateAllMenuButtons();
return 0;
}
void GUI_MR::setupOptionsButtons() {
if (_vm->_configWalkspeed == 3)
_gameOptions.item[0].itemId = 28;
else
_gameOptions.item[0].itemId = 27;
if (_vm->textEnabled())
_gameOptions.item[4].itemId = 18;
else
_gameOptions.item[4].itemId = 17;
switch (_vm->_lang) {
case 0:
_gameOptions.item[1].itemId = 31;
break;
case 1:
_gameOptions.item[1].itemId = 32;
break;
case 2:
_gameOptions.item[1].itemId = 33;
break;
case 3:
_gameOptions.item[1].itemId = 48;
break;
default:
break;
}
if (_vm->_configStudio)
_gameOptions.item[2].itemId = 18;
else
_gameOptions.item[2].itemId = 17;
if (_vm->_configSkip)
_gameOptions.item[3].itemId = 18;
else
_gameOptions.item[3].itemId = 17;
}
void GUI_MR::resizeMenu(Menu &menu, int menuHeight, int menuTitleY, int menuItemYstart, int menuItemYinc, int menuItemHeight, int menuItemYend, int labelYstart, int labelYend) {
menu.x = menu.y = -1;
menu.height = menuHeight;
menu.titleY = menuTitleY;
for (int i = 0; i < menu.numberOfItems - 1; ++i) {
menu.item[i].y = menuItemYstart + i * menuItemYinc;
menu.item[i].height = menuItemHeight;
menu.item[i].labelY = labelYstart ? (labelYstart + i * menuItemYinc) : 0;
}
menu.item[menu.numberOfItems - 1].y = menuItemYend;
menu.item[menu.numberOfItems - 1].height = menuItemHeight;
menu.item[menu.numberOfItems - 1].labelY = labelYend;
initMenuLayout(menu);
}
void GUI_MR::fontBasedMenuResize() {
if (_vm->_lang == 3) {
resizeMenu(_mainMenu, 192, 6, 26, 22, 20, 161, 0, 0);
resizeMenu(_gameOptions, 174, 8, 30, 22, 20, 145, 32, 0);
resizeMenu(_audioOptions, 140, 8, 28, 22, 20, 110, 30, 0);
_audioOptions.item[3].y = 81;
_audioOptions.item[1].labelY = 47;
_audioOptions.item[2].labelY = 64;
_audioOptions.item[3].labelY = 83;
resizeMenu(_choiceMenu, 56, 8, 30, 0, 20, 30, 0, 0);
_loadMenu.numberOfItems = 6;
resizeMenu(_loadMenu, 182, 6, 39, 22, 20, 155, 0, 0);
resizeMenu(_saveMenu, 182, 6, 39, 22, 20, 155, 0, 0);
_loadMenu.scrollDownButtonY = _saveMenu.scrollDownButtonY = 149;
resizeMenu(_savenameMenu, 72, 8, 44, 0, 20, 44, 0, 0);
resizeMenu(_deathMenu, 80, 8, 30, 0, 20, 52, 0, 0);
} else {
resizeMenu(_mainMenu, 172, 8, 30, 17, 15, 144, 0, 0);
resizeMenu(_gameOptions, 154, 8, 30, 17, 15, 127, 32, 0);
resizeMenu(_audioOptions, 136, 8, 30, 17, 15, 110, 32, 0);
resizeMenu(_choiceMenu, 56, 8, 30, 0, 15, 30, 0, 0);
_loadMenu.numberOfItems = 6;
resizeMenu(_loadMenu, 160, 8, 39, 17, 15, 134, 0, 0);
resizeMenu(_saveMenu, 160, 8, 39, 17, 15, 134, 0, 0);
_loadMenu.scrollDownButtonY = _saveMenu.scrollDownButtonY = 124;
resizeMenu(_savenameMenu, 67, 8, 44, 0, 15, 44, 0, 0);
resizeMenu(_deathMenu, 76, 8, 30, 0, 15, 47, 0, 0);
}
}
int GUI_MR::changeLanguage(Button *caller) {
updateMenuButton(caller);
if (!_vm->queryGameFlag(0x1B2)) {
++_vm->_lang;
_vm->_lang %= _vm->_numLang;
setupOptionsButtons();
renewHighlight(_gameOptions);
}
return 0;
}
int GUI_MR::toggleStudioSFX(Button *caller) {
updateMenuButton(caller);
_vm->_configStudio ^= 1;
setupOptionsButtons();
renewHighlight(_gameOptions);
return 0;
}
int GUI_MR::toggleSkipSupport(Button *caller) {
updateMenuButton(caller);
_vm->_configSkip ^= 1;
setupOptionsButtons();
renewHighlight(_gameOptions);
return 0;
}
int GUI_MR::toggleHeliumMode(Button *caller) {
updateMenuButton(caller);
_vm->_configHelium ^= 1;
if (_vm->_configHelium)
_audioOptions.item[3].itemId = 18;
else
_audioOptions.item[3].itemId = 17;
renewHighlight(_audioOptions);
return 0;
}
int GUI_MR::audioOptions(Button *caller) {
updateMenuButton(caller);
restorePage1(_vm->_screenBuffer);
backUpPage1(_vm->_screenBuffer);
if (_vm->_configHelium)
_audioOptions.item[3].itemId = 18;
else
_audioOptions.item[3].itemId = 17;
initMenu(_audioOptions);
const int menuX = _audioOptions.x;
const int menuY = _audioOptions.y;
const int maxButton = 3; // 2 if voc is disabled
for (int i = 0; i < maxButton; ++i) {
int x = menuX + _sliderBarsPosition[i*2+0];
int y = menuY + _sliderBarsPosition[i*2+1];
_screen->drawShape(0, _vm->getShapePtr(0x1CF), x, y, 0, 0);
drawSliderBar(i, _vm->getShapePtr(0x1D0));
_sliderButtons[0][i].buttonCallback = _sliderHandlerFunctor;
_sliderButtons[0][i].x = x;
_sliderButtons[0][i].y = y;
_menuButtonList = addButtonToList(_menuButtonList, &_sliderButtons[0][i]);
_sliderButtons[2][i].buttonCallback = _sliderHandlerFunctor;
_sliderButtons[2][i].x = x + 10;
_sliderButtons[2][i].y = y;
_menuButtonList = addButtonToList(_menuButtonList, &_sliderButtons[2][i]);
_sliderButtons[1][i].buttonCallback = _sliderHandlerFunctor;
_sliderButtons[1][i].x = x + 120;
_sliderButtons[1][i].y = y;
_menuButtonList = addButtonToList(_menuButtonList, &_sliderButtons[1][i]);
}
_isOptionsMenu = true;
updateAllMenuButtons();
bool speechEnabled = _vm->speechEnabled();
while (_isOptionsMenu) {
processHighlights(_audioOptions);
getInput();
}
restorePage1(_vm->_screenBuffer);
backUpPage1(_vm->_screenBuffer);
if (speechEnabled && !_vm->textEnabled() && (!_vm->speechEnabled() || _vm->getVolume(KyraEngine_v1::kVolumeSpeech) == 2)) {
_vm->_configVoice = 0;
choiceDialog(0x1D, 0);
}
_vm->writeSettings();
initMenu(*_currentMenu);
updateAllMenuButtons();
return 0;
}
int GUI_MR::sliderHandler(Button *caller) {
int button = 0;
if (caller->index >= 24 && caller->index <= 27)
button = caller->index - 24;
else if (caller->index >= 28 && caller->index <= 31)
button = caller->index - 28;
else
button = caller->index - 32;
assert(button >= 0 && button <= 3);
const int oldVolume = _vm->getVolume(KyraEngine_v1::kVolumeEntry(button));
int newVolume = oldVolume;
if (caller->index >= 24 && caller->index <= 27)
newVolume -= 10;
else if (caller->index >= 28 && caller->index <= 31)
newVolume += 10;
else
newVolume = _vm->_mouseX - caller->x - 7;
newVolume = CLIP(newVolume, 2, 97);
if (newVolume == oldVolume)
return 0;
int lastMusicCommand = -1;
bool playSoundEffect = false;
drawSliderBar(button, _vm->getShapePtr(0x1D1));
if (button == 2) {
if (_vm->textEnabled())
_vm->_configVoice = 2;
else
_vm->_configVoice = 1;
}
_vm->setVolume(KyraEngine_v1::kVolumeEntry(button), newVolume);
switch (button) {
case 0:
lastMusicCommand = _vm->_lastMusicCommand;
break;
case 1:
playSoundEffect = true;
break;
case 2:
if (_vm->_voiceSoundChannel != _vm->_musicSoundChannel)
_vm->_soundDigital->stopSound(_vm->_voiceSoundChannel);
_vm->playVoice(200, 943);
break;
default:
return 0;
}
drawSliderBar(button, _vm->getShapePtr(0x1D0));
if (playSoundEffect)
_vm->snd_playSoundEffect(0x18, 0xC8);
else if (lastMusicCommand >= 0)
_vm->snd_playWanderScoreViaMap(lastMusicCommand, 0);
_screen->updateScreen();
return 0;
}
void GUI_MR::drawSliderBar(int slider, const uint8 *shape) {
const int menuX = _audioOptions.x;
const int menuY = _audioOptions.y;
int x = menuX + _sliderBarsPosition[slider*2+0] + 10;
int y = menuY + _sliderBarsPosition[slider*2+1];
int position = _vm->getVolume(KyraEngine_v1::kVolumeEntry(slider));
position = CLIP(position, 2, 97);
_screen->drawShape(0, shape, x+position, y, 0, 0);
}
} // End of namespace Kyra