965 lines
24 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.
*
* $URL$
* $Id$
*
*/
#include "kyra/gui_v3.h"
#include "kyra/kyra_mr.h"
#include "kyra/text_mr.h"
#include "kyra/wsamovie.h"
#include "kyra/resource.h"
namespace Kyra {
void KyraEngine_MR::showMessage(const char *string, uint8 c0, uint8 c1) {
debugC(9, kDebugLevelMain, "KyraEngine_MR::showMessage('%s', %d, %d)", string, c0, c1);
_shownMessage = string;
_screen->hideMouse();
restoreCommandLine();
_restoreCommandLine = false;
if (string) {
int x = _text->getCenterStringX(string, 0, 320);
int pageBackUp = _screen->_curPage;
_screen->_curPage = 0;
_text->printText(string, x, _commandLineY, c0, c1, 0);
_screen->_curPage = pageBackUp;
_screen->updateScreen();
setCommandLineRestoreTimer(7);
}
_screen->showMouse();
}
void KyraEngine_MR::showMessageFromCCode(int string, uint8 c0, int) {
debugC(9, kDebugLevelMain, "KyraEngine_MR::showMessageFromCCode(%d, %d, -)", string, c0);
showMessage((const char*)getTableEntry(_cCodeFile, string), c0, 0xF0);
}
void KyraEngine_MR::updateItemCommand(int item, int str, uint8 c0) {
debugC(9, kDebugLevelMain, "KyraEngine_MR::updateItemCommand(%d, %d, %d)", item, str, c0);
char buffer[100];
char *src = (char*)getTableEntry(_itemFile, item);
while (*src != ' ')
++src;
++src;
*src = toupper(*src);
strcpy(buffer, src);
strcat(buffer, " ");
strcat(buffer, (const char*)getTableEntry(_cCodeFile, str));
showMessage(buffer, c0, 0xF0);
}
void KyraEngine_MR::updateCommandLine() {
debugC(9, kDebugLevelMain, "KyraEngine_MR::updateCommandLine()");
if (_restoreCommandLine) {
restoreCommandLine();
_restoreCommandLine = false;
}
}
void KyraEngine_MR::restoreCommandLine() {
debugC(9, kDebugLevelMain, "KyraEngine_MR::restoreCommandLine()");
int y = _inventoryState ? 144 : 188;
_screen->copyBlockToPage(0, 0, y, 320, 12, _interfaceCommandLine);
}
void KyraEngine_MR::updateCLState() {
debugC(9, kDebugLevelMain, "KyraEngine_MR::updateCLState()");
if (_inventoryState)
_commandLineY = 145;
else
_commandLineY = 189;
}
void KyraEngine_MR::showInventory() {
debugC(9, kDebugLevelMain, "KyraEngine_MR::showInventory()");
if (!_screen->isMouseVisible())
return;
if (queryGameFlag(3))
return;
_screen->copyBlockToPage(3, 0, 0, 320, 56, _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) {
_handItemSet = -1;
_screen->setMouseCursor(0, 0, getShapePtr(0));
}
_screen->copyRegion(0, 188, 0, 0, 320, 12, 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, 188, 0, 0, 320, 12, 0, 2, Screen::CR_NO_P_CHECK);
_screen->copyRegion(0, 188, 0, 0, 320, 12, 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 = 12;
int y = 188;
int times = 0;
uint32 waitTill = _system->getMillis() + _tickLength;
while (y > 144) {
_screen->copyRegion(0, 0, 0, y, 320, height, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
++times;
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, 144, 320, 56, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
initMainButtonList(false);
restorePage3();
_screen->showMouse();
}
void KyraEngine_MR::hideInventory() {
debugC(9, kDebugLevelMain, "KyraEngine_MR::hideInventory()");
if (queryGameFlag(3))
return;
_inventoryState = false;
updateCLState();
initMainButtonList(true);
_screen->copyBlockToPage(3, 0, 0, 320, 56, _interface);
_screen->hideMouse();
restorePage3();
flagAnimObjsForRefresh();
drawAnimObjects();
_screen->copyRegion(0, 144, 0, 0, 320, 56, 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, 144, 0, 0, 320, 12, 0, 2, Screen::CR_NO_P_CHECK);
_screen->copyRegion(0, 144, 0, 0, 320, 12, 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 = 144;
int y2 = 144 + _inventoryScrollSpeed;
uint32 waitTill = _system->getMillis() + _tickLength;
int times = 0;
while (y2 < 188) {
_screen->copyRegion(0, 0, 0, y2, 320, 56, 2, 0, Screen::CR_NO_P_CHECK);
_screen->copyRegion(0, y, 0, y, 320, _inventoryScrollSpeed, 2, 0, Screen::CR_NO_P_CHECK);
_screen->updateScreen();
++times;
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, 188, 320, 56, 2, 0, Screen::CR_NO_P_CHECK);
_screen->copyRegion(0, y, 0, y, 320, 188-y, 2, 0, Screen::CR_NO_P_CHECK);
_screen->showMouse();
}
void KyraEngine_MR::drawMalcolmsMoodText() {
debugC(9, kDebugLevelMain, "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(Screen::FID_8_FNT);
_screen->_charWidth = -2;
int width = _screen->getTextWidth(string);
_screen->_charWidth = 0;
_screen->setFont(oldFont);
int pageBackUp = _screen->_curPage;
const int x = 280 - (width / 2);
int y = 0;
if (_inventoryState) {
y = 189;
_screen->_curPage = 0;
} else {
y = 45;
_screen->_curPage = 2;
}
_screen->hideMouse();
_screen->drawShape(_screen->_curPage, getShapePtr(432), 244, 189, 0, 0);
_text->printText(string, x, y+1, 0xFF, 0xF0, 0x00);
_screen->showMouse();
_screen->_curPage = pageBackUp;
}
void KyraEngine_MR::drawMalcolmsMoodPointer(int frame, int page) {
debugC(9, kDebugLevelMain, "KyraEngine_MR::drawMalcolmsMoodPointer(%d, %d)", frame, page);
static const uint8 stateTable[] = {
1, 6, 11
};
if (frame == -1)
frame = stateTable[_malcolmsMood];
if (queryGameFlag(0x219))
frame = 13;
if (page == 0) {
_invWsa->setX(0);
_invWsa->setY(0);
_invWsa->setDrawPage(0);
_invWsa->displayFrame(frame, 0);
_screen->updateScreen();
} else if (page == 30) {
_invWsa->setX(0);
_invWsa->setY(-144);
_invWsa->setDrawPage(2);
_invWsa->displayFrame(frame, 0);
}
_invWsaFrame = frame;
}
void KyraEngine_MR::drawJestersStaff(int type, int page) {
debugC(9, kDebugLevelMain, "KyraEngine_MR::drawJestersStaff(%d, %d)", type, page);
int y = 155;
if (page == 30) {
page = 2;
y -= 144;
}
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) {
debugC(9, kDebugLevelMain, "KyraEngine_MR::drawScore(%d, %d, %d)", page, x, y);
if (page == 30) {
page = 2;
y -= 144;
}
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) {
debugC(9, kDebugLevelMain, "KyraEngine_MR::drawScoreCounting(%d, %d, %d, %d)", oldScore, newScore, drawOld, 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) {
debugC(9, kDebugLevelMain, "KyraEngine_MR::getScoreX('%s')", str);
Screen::FontId oldFont = _screen->setFont(Screen::FID_8_FNT);
_screen->_charWidth = -2;
int width = _screen->getTextWidth(str);
int x = 160 + (width / 2) - 32;
_screen->setFont(oldFont);
_screen->_charWidth = 0;
return x;
}
void KyraEngine_MR::redrawInventory(int page) {
debugC(9, kDebugLevelMain, "KyraEngine_MR::redrawInventory(%d)", page);
int yOffset = 0;
if (page == 30) {
page = 2;
yOffset = -144;
}
int pageBackUp = _screen->_curPage;
_screen->_curPage = page;
_screen->hideMouse();
for (int i = 0; i < 10; ++i) {
clearInventorySlot(i, page);
if (_mainCharacter.inventory[i] != 0xFFFF) {
_screen->drawShape(page, getShapePtr(_mainCharacter.inventory[i]+248), _inventoryX[i], _inventoryY[i] + yOffset, 0, 0);
drawInventorySlot(page, _mainCharacter.inventory[i], i);
}
}
_screen->showMouse();
_screen->_curPage = pageBackUp;
if (page == 0 || page == 1)
_screen->updateScreen();
}
void KyraEngine_MR::clearInventorySlot(int slot, int page) {
debugC(9, kDebugLevelMain, "KyraEngine_MR::clearInventorySlot(%d, %d)", slot, page);
int yOffset = 0;
if (page == 30) {
page = 2;
yOffset = -144;
}
_screen->drawShape(page, getShapePtr(slot+422), _inventoryX[slot], _inventoryY[slot] + yOffset, 0, 0);
}
void KyraEngine_MR::drawInventorySlot(int page, int item, int slot) {
debugC(9, kDebugLevelMain, "KyraEngine_MR::drawInventorySlot(%d, %d, %d)", page, item, slot);
int yOffset = 0;
if (page == 30) {
page = 2;
yOffset = -144;
}
_screen->drawShape(page, getShapePtr(item+248), _inventoryX[slot], _inventoryY[slot] + yOffset, 0, 0);
}
int KyraEngine_MR::buttonInventory(Button *button) {
debugC(9, kDebugLevelMain, "KyraEngine_MR::buttonInventory(%p)", (const void*)button);
setNextIdleAnimTimer();
if (!_enableInventory || !_inventoryState || !_screen->isMouseVisible())
return 0;
const int slot = button->index - 5;
const int16 slotItem = (int16)_mainCharacter.inventory[slot];
if (_itemInHand == -1) {
if (slotItem == -1)
return 0;
_screen->hideMouse();
clearInventorySlot(slot, 0);
snd_playSoundEffect(0x0B, 0xC8);
setMouseCursor(slotItem);
updateItemCommand(slotItem, (_lang == 1) ? getItemCommandStringPickUp(slotItem) : 0, 0xFF);
_itemInHand = slotItem;
_mainCharacter.inventory[slot] = 0xFFFF;
_screen->showMouse();
} else if (_itemInHand == 27) {
if (_chatText)
return 0;
return buttonJesterStaff(&_mainButtonData[3]);
} else {
if (slotItem >= 0) {
if (itemInventoryMagic(_itemInHand, slot))
return 0;
snd_playSoundEffect(0x0B, 0xC8);
_screen->hideMouse();
clearInventorySlot(slot, 0);
drawInventorySlot(0, _itemInHand, slot);
setMouseCursor(slotItem);
updateItemCommand(slotItem, (_lang == 1) ? getItemCommandStringPickUp(slotItem) : 0, 0xFF);
_mainCharacter.inventory[slot] = _itemInHand;
_itemInHand = slotItem;
_screen->showMouse();
} else {
snd_playSoundEffect(0x0C, 0xC8);
_screen->hideMouse();
drawInventorySlot(0, _itemInHand, slot);
_screen->setMouseCursor(0, 0, getShapePtr(0));
updateItemCommand(_itemInHand, (_lang == 1) ? getItemCommandStringInv(_itemInHand) : 2, 0xFF);
_screen->showMouse();
_mainCharacter.inventory[slot] = _itemInHand;
_itemInHand = -1;
}
}
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) {
strcpy(_stringBuffer, (const char*)getTableEntry(_cCodeFile, 18));
char *buffer = _stringBuffer;
while (*buffer != '%')
++buffer;
buffer[0] = (_score / 100) + '0';
buffer[1] = ((_score % 100) / 10) + '0';
buffer[2] = (_score % 10) + '0';
while (*buffer != '%')
++buffer;
buffer[0] = (_scoreMax / 100) + '0';
buffer[1] = ((_scoreMax % 100) / 10) + '0';
buffer[2] = (_scoreMax % 10) + '0';
showMessage(_stringBuffer, 0xFF, 0xF0);
return 0;
}
int KyraEngine_MR::buttonJesterStaff(Button *button) {
makeCharFacingMouse();
if (_itemInHand == 27) {
_screen->hideMouse();
removeHandItem();
snd_playSoundEffect(0x0C, 0xC8);
drawJestersStaff(1, 0);
updateItemCommand(27, 2, 0xFF);
setGameFlag(0x97);
_screen->showMouse();
} else if (_itemInHand == -1) {
if (queryGameFlag(0x97)) {
_screen->hideMouse();
snd_playSoundEffect(0x0B, 0xC8);
setHandItem(27);
drawJestersStaff(0, 0);
updateItemCommand(27, 0, 0xFF);
resetGameFlag(0x97);
_screen->showMouse();
} 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;
}
#pragma mark -
GUI_v3::GUI_v3(KyraEngine_MR *vm) : GUI(vm), _vm(vm), _screen(vm->_screen) {
_backUpButtonList = _unknownButtonList = 0;
_buttonListChanged = false;
}
Button *GUI_v3::addButtonToList(Button *list, Button *newButton) {
list = GUI::addButtonToList(list, newButton);
_buttonListChanged = true;
return list;
}
void GUI_v3::processButton(Button *button) {
if (!button)
return;
if (button->flags & 8) {
if (button->flags & 0x10) {
// XXX
}
return;
}
int entry = button->flags2 & 5;
byte val1 = 0, val2 = 0, val3 = 0;
const uint8 *dataPtr = 0;
Button::Callback callback;
if (entry == 1) {
val1 = button->data1Val1;
dataPtr = button->data1ShapePtr;
callback = button->data1Callback;
val2 = button->data1Val2;
val3 = button->data1Val3;
} else if (entry == 4 || entry == 5) {
val1 = button->data2Val1;
dataPtr = button->data2ShapePtr;
callback = button->data2Callback;
val2 = button->data2Val2;
val3 = button->data2Val3;
} else {
val1 = button->data0Val1;
dataPtr = button->data0ShapePtr;
callback = button->data0Callback;
val2 = button->data0Val2;
val3 = button->data0Val3;
}
int x = 0, y = 0, x2 = 0, y2 = 0;
x = button->x;
if (x < 0)
x += _screen->getScreenDim(button->dimTableIndex)->w << 3;
x += _screen->getScreenDim(button->dimTableIndex)->sx << 3;
x2 = x + button->width - 1;
y = button->y;
if (y < 0)
y += _screen->getScreenDim(button->dimTableIndex)->h << 3;
y += _screen->getScreenDim(button->dimTableIndex)->sy << 3;
y2 = y + button->height - 1;
switch (val1 - 1) {
case 0:
_screen->hideMouse();
_screen->drawShape(_screen->_curPage, dataPtr, x, y, button->dimTableIndex, 0x10);
_screen->showMouse();
break;
case 1:
_screen->hideMouse();
_screen->printText((const char*)dataPtr, x, y, val2, val3);
_screen->showMouse();
break;
case 3:
if (callback)
(*callback)(button);
break;
case 4:
_screen->hideMouse();
_screen->drawBox(x, y, x2, y2, val2);
_screen->showMouse();
break;
case 5:
_screen->hideMouse();
_screen->fillRect(x, y, x2, y2, val2, -1, true);
_screen->showMouse();
break;
default:
break;
}
_screen->updateScreen();
}
int GUI_v3::processButtonList(Button *buttonList, uint16 inputFlag) {
static uint16 flagsModifier = 0;
if (!buttonList)
return inputFlag & 0x7FFF;
if (_backUpButtonList != buttonList || _buttonListChanged) {
_unknownButtonList = 0;
//flagsModifier |= 0x2200;
_backUpButtonList = buttonList;
_buttonListChanged = false;
while (buttonList) {
processButton(buttonList);
buttonList = buttonList->nextButton;
}
}
int mouseX = _vm->_mouseX;
int mouseY = _vm->_mouseY;
uint16 flags = 0;
if (1/*!_screen_cursorDisable*/) {
uint16 inFlags = inputFlag & 0xFF;
uint16 temp = 0;
// HACK: inFlags == 200 is our left button (up)
if (inFlags == 199 || inFlags == 200)
temp = 0x1000;
if (inFlags == 198)
temp = 0x100;
if (inputFlag & 0x800)
temp <<= 2;
flags |= temp;
flagsModifier &= ~((temp & 0x4400) >> 1);
flagsModifier |= (temp & 0x1100) * 2;
flags |= flagsModifier;
flags |= (flagsModifier << 2) ^ 0x8800;
}
buttonList = _backUpButtonList;
if (_unknownButtonList) {
buttonList = _unknownButtonList;
if (_unknownButtonList->flags & 8)
_unknownButtonList = 0;
}
int returnValue = 0;
while (buttonList) {
if (buttonList->flags & 8) {
buttonList = buttonList->nextButton;
continue;
}
buttonList->flags2 &= ~0x18;
buttonList->flags2 |= (buttonList->flags2 & 3) << 3;
int x = buttonList->x;
if (x < 0)
x += _screen->getScreenDim(buttonList->dimTableIndex)->w << 3;
x += _screen->getScreenDim(buttonList->dimTableIndex)->sx << 3;
int y = buttonList->y;
if (y < 0)
y += _screen->getScreenDim(buttonList->dimTableIndex)->h;
y += _screen->getScreenDim(buttonList->dimTableIndex)->sy;
bool progress = false;
if (mouseX >= x && mouseY >= y && mouseX <= x+buttonList->width && mouseY <= y+buttonList->height)
progress = true;
buttonList->flags2 &= ~0x80;
uint16 inFlags = inputFlag & 0x7FFF;
if (inFlags) {
if (buttonList->unk6 == inFlags) {
progress = true;
flags = buttonList->flags & 0x0F00;
buttonList->flags2 |= 0x80;
inputFlag = 0;
_unknownButtonList = buttonList;
} else if (buttonList->unk8 == inFlags) {
flags = buttonList->flags & 0xF000;
if (!flags)
flags = buttonList->flags & 0x0F00;
progress = true;
buttonList->flags2 |= 0x80;
inputFlag = 0;
_unknownButtonList = buttonList;
}
}
bool unk1 = false;
if (!progress)
buttonList->flags2 &= ~6;
if ((flags & 0x3300) && (buttonList->flags & 4) && progress && (buttonList == _unknownButtonList || !_unknownButtonList)) {
buttonList->flags |= 6;
if (!_unknownButtonList)
_unknownButtonList = buttonList;
} else if ((flags & 0x8800) && !(buttonList->flags & 4) && progress) {
buttonList->flags2 |= 6;
} else {
buttonList->flags2 &= ~6;
}
bool progressSwitch = false;
if (!_unknownButtonList) {
progressSwitch = progress;
} else {
if (_unknownButtonList->flags & 0x40)
progressSwitch = (_unknownButtonList == buttonList);
else
progressSwitch = progress;
}
if (progressSwitch) {
if ((flags & 0x1100) && progress && !_unknownButtonList) {
inputFlag = 0;
_unknownButtonList = buttonList;
}
if ((buttonList->flags & flags) && (progress || !(buttonList->flags & 1))) {
uint16 combinedFlags = (buttonList->flags & flags);
combinedFlags = ((combinedFlags & 0xF000) >> 4) | (combinedFlags & 0x0F00);
combinedFlags >>= 8;
static const uint16 flagTable[] = {
0x000, 0x100, 0x200, 0x100, 0x400, 0x100, 0x400, 0x100, 0x800, 0x100,
0x200, 0x100, 0x400, 0x100, 0x400, 0x100
};
assert(combinedFlags < ARRAYSIZE(flagTable));
switch (flagTable[combinedFlags]) {
case 0x400:
if (!(buttonList->flags & 1) || ((buttonList->flags & 1) && _unknownButtonList == buttonList)) {
buttonList->flags2 ^= 1;
returnValue = buttonList->index | 0x8000;
unk1 = true;
}
if (!(buttonList->flags & 4)) {
buttonList->flags2 &= ~4;
buttonList->flags2 &= ~2;
}
break;
case 0x800:
if (!(buttonList->flags & 4)) {
buttonList->flags2 |= 4;
buttonList->flags2 |= 2;
}
if (!(buttonList->flags & 1))
unk1 = true;
break;
case 0x200:
if (buttonList->flags & 4) {
buttonList->flags2 |= 4;
buttonList->flags2 |= 2;
}
if (!(buttonList->flags & 1))
unk1 = true;
break;
case 0x100:
default:
buttonList->flags2 ^= 1;
returnValue = buttonList->index | 0x8000;
unk1 = true;
if (buttonList->flags & 4) {
buttonList->flags2 |= 4;
buttonList->flags2 |= 2;
}
_unknownButtonList = buttonList;
break;
}
}
}
bool unk2 = false;
if ((flags & 0x2200) && progress) {
buttonList->flags2 |= 6;
if (!(buttonList->flags & 4) && !(buttonList->flags2 & 1)) {
unk2 = true;
buttonList->flags2 |= 1;
}
}
if ((flags & 0x8800) == 0x8800) {
_unknownButtonList = 0;
if (!progress || (buttonList->flags & 4))
buttonList->flags2 &= ~6;
}
if (!progress && buttonList == _unknownButtonList && !(buttonList->flags & 0x40))
_unknownButtonList = 0;
if ((buttonList->flags2 & 0x18) != ((buttonList->flags2 & 3) << 3))
processButton(buttonList);
if (unk2)
buttonList->flags2 &= ~1;
if (unk1) {
buttonList->flags2 &= 0xFF;
buttonList->flags2 |= flags;
if (buttonList->buttonCallback) {
_vm->removeInputTop();
if ((*buttonList->buttonCallback.get())(buttonList))
break;
}
if (buttonList->flags & 0x20)
break;
}
if (_unknownButtonList == buttonList && (buttonList->flags & 0x40))
break;
buttonList = buttonList->nextButton;
}
if (!returnValue)
returnValue = inputFlag & 0x7FFF;
return returnValue;
}
void GUI_v3::flagButtonEnable(Button *button) {
if (!button)
return;
if (button->flags & 8) {
button->flags &= ~8;
processButton(button);
}
}
void GUI_v3::flagButtonDisable(Button *button) {
if (!button)
return;
if (!(button->flags & 8)) {
button->flags |= 8;
processButton(button);
}
}
} // end of namespace Kyra