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.
880 lines
22 KiB
C++
880 lines
22 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_v2.h"
|
|
#include "kyra/screen_v2.h"
|
|
#include "kyra/text.h"
|
|
#include "kyra/util.h"
|
|
|
|
#include "common/savefile.h"
|
|
#include "common/system.h"
|
|
|
|
namespace Kyra {
|
|
|
|
GUI_v2::GUI_v2(KyraEngine_v2 *vm) : GUI_v1(vm), _vm(vm), _screen(vm->screen_v2()) {
|
|
_backUpButtonList = _specialProcessButton = 0;
|
|
_buttonListChanged = false;
|
|
_lastScreenUpdate = 0;
|
|
_flagsModifier = 0;
|
|
|
|
_currentMenu = 0;
|
|
_isDeathMenu = false;
|
|
_isSaveMenu = false;
|
|
_isLoadMenu = false;
|
|
_scrollUpFunctor = BUTTON_FUNCTOR(GUI_v2, this, &GUI_v2::scrollUpButton);
|
|
_scrollDownFunctor = BUTTON_FUNCTOR(GUI_v2, this, &GUI_v2::scrollDownButton);
|
|
_sliderHandlerFunctor = BUTTON_FUNCTOR(GUI_v2, this, &GUI_v2::sliderHandler);
|
|
_savegameOffset = 0;
|
|
_isDeleteMenu = false;
|
|
}
|
|
|
|
Button *GUI_v2::addButtonToList(Button *list, Button *newButton) {
|
|
list = GUI_v1::addButtonToList(list, newButton);
|
|
_buttonListChanged = true;
|
|
return list;
|
|
}
|
|
|
|
void GUI_v2::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->drawShape(_screen->_curPage, dataPtr, x, y, button->dimTableIndex, 0x10);
|
|
break;
|
|
|
|
case 1:
|
|
_screen->printText((const char *)dataPtr, x, y, val2, val3);
|
|
break;
|
|
|
|
case 3:
|
|
if (callback)
|
|
(*callback)(button);
|
|
break;
|
|
|
|
case 4:
|
|
_screen->drawBox(x, y, x2, y2, val2);
|
|
break;
|
|
|
|
case 5:
|
|
_screen->fillRect(x, y, x2, y2, val2, -1, true);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
int GUI_v2::processButtonList(Button *buttonList, uint16 inputFlag, int8 mouseWheel) {
|
|
if (!buttonList)
|
|
return inputFlag & 0x7FFF;
|
|
|
|
if (_backUpButtonList != buttonList || _buttonListChanged) {
|
|
_specialProcessButton = 0;
|
|
//flagsModifier |= 0x2200;
|
|
_backUpButtonList = buttonList;
|
|
_buttonListChanged = false;
|
|
|
|
while (buttonList) {
|
|
processButton(buttonList);
|
|
buttonList = buttonList->nextButton;
|
|
}
|
|
}
|
|
|
|
Common::Point p = _vm->getMousePos();
|
|
int mouseX = _vm->_mouseX = p.x;
|
|
int mouseY = _vm->_mouseY = p.y;
|
|
|
|
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 (_specialProcessButton) {
|
|
buttonList = _specialProcessButton;
|
|
if (_specialProcessButton->flags & 8)
|
|
_specialProcessButton = 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->keyCode == inFlags) {
|
|
progress = true;
|
|
flags = buttonList->flags & 0x0F00;
|
|
buttonList->flags2 |= 0x80;
|
|
inputFlag = 0;
|
|
_specialProcessButton = buttonList;
|
|
} else if (buttonList->keyCode2 == inFlags) {
|
|
flags = buttonList->flags & 0xF000;
|
|
if (!flags)
|
|
flags = buttonList->flags & 0x0F00;
|
|
progress = true;
|
|
buttonList->flags2 |= 0x80;
|
|
inputFlag = 0;
|
|
_specialProcessButton = buttonList;
|
|
}
|
|
}
|
|
|
|
bool unk1 = false;
|
|
|
|
if (mouseWheel && buttonList->mouseWheel == mouseWheel) {
|
|
progress = true;
|
|
unk1 = true;
|
|
}
|
|
|
|
if (!progress)
|
|
buttonList->flags2 &= ~6;
|
|
|
|
if ((flags & 0x3300) && (buttonList->flags & 4) && progress && (buttonList == _specialProcessButton || !_specialProcessButton)) {
|
|
buttonList->flags |= 6;
|
|
if (!_specialProcessButton)
|
|
_specialProcessButton = buttonList;
|
|
} else if ((flags & 0x8800) && !(buttonList->flags & 4) && progress) {
|
|
buttonList->flags2 |= 6;
|
|
} else {
|
|
buttonList->flags2 &= ~6;
|
|
}
|
|
|
|
bool progressSwitch = false;
|
|
if (!_specialProcessButton) {
|
|
progressSwitch = progress;
|
|
} else {
|
|
if (_specialProcessButton->flags & 0x40)
|
|
progressSwitch = (_specialProcessButton == buttonList);
|
|
else
|
|
progressSwitch = progress;
|
|
}
|
|
|
|
if (progressSwitch) {
|
|
if ((flags & 0x1100) && progress && !_specialProcessButton) {
|
|
inputFlag = 0;
|
|
_specialProcessButton = 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) && _specialProcessButton == 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;
|
|
}
|
|
_specialProcessButton = buttonList;
|
|
}
|
|
}
|
|
}
|
|
|
|
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) {
|
|
_specialProcessButton = 0;
|
|
if (!progress || (buttonList->flags & 4))
|
|
buttonList->flags2 &= ~6;
|
|
}
|
|
|
|
if (!progress && buttonList == _specialProcessButton && !(buttonList->flags & 0x40))
|
|
_specialProcessButton = 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)(buttonList))
|
|
break;
|
|
}
|
|
|
|
if (buttonList->flags & 0x20)
|
|
break;
|
|
}
|
|
|
|
if (_specialProcessButton == buttonList && (buttonList->flags & 0x40))
|
|
break;
|
|
|
|
buttonList = buttonList->nextButton;
|
|
}
|
|
|
|
if (!returnValue)
|
|
returnValue = inputFlag & 0x7FFF;
|
|
return returnValue;
|
|
}
|
|
|
|
void GUI_v2::updateButton(Button *button) {
|
|
if (!button || (button->flags & 8))
|
|
return;
|
|
|
|
if (button->flags2 & 1)
|
|
button->flags2 |= 8;
|
|
else
|
|
button->flags2 |= ~8;
|
|
|
|
button->flags2 &= ~1;
|
|
|
|
if (button->flags2 & 4)
|
|
button->flags2 |= 0x10;
|
|
else
|
|
button->flags2 &= ~0x10;
|
|
|
|
button->flags2 &= ~4;
|
|
|
|
processButton(button);
|
|
}
|
|
|
|
void GUI_v2::getInput() {
|
|
if (!_displayMenu)
|
|
return;
|
|
|
|
_vm->checkInput(_menuButtonList);
|
|
_vm->removeInputTop();
|
|
if (_vm->shouldQuit()) {
|
|
_displayMenu = false;
|
|
_isLoadMenu = false;
|
|
_isSaveMenu = false;
|
|
_isOptionsMenu = false;
|
|
_isDeleteMenu = false;
|
|
}
|
|
|
|
_vm->delay(10);
|
|
}
|
|
|
|
void GUI_v2::renewHighlight(Menu &menu) {
|
|
if (!_displayMenu)
|
|
return;
|
|
|
|
MenuItem &item = menu.item[menu.highlightedItem];
|
|
int x = item.x + menu.x; int y = item.y + menu.y;
|
|
int x2 = x + item.width - 1; int y2 = y + item.height - 1;
|
|
redrawText(menu);
|
|
_screen->fillRect(x + 2, y + 2, x2 - 2, y2 - 2, item.bkgdColor);
|
|
redrawHighlight(menu);
|
|
_screen->updateScreen();
|
|
}
|
|
|
|
void GUI_v2::backUpPage1(uint8 *buffer) {
|
|
_screen->copyRegionToBuffer(1, 0, 0, 320, 200, buffer);
|
|
}
|
|
|
|
void GUI_v2::restorePage1(const uint8 *buffer) {
|
|
_screen->copyBlockToPage(1, 0, 0, 320, 200, buffer);
|
|
}
|
|
|
|
void GUI_v2::setupSavegameNames(Menu &menu, int num) {
|
|
for (int i = 0; i < num; ++i) {
|
|
strcpy(getTableString(menu.item[i].itemId), "");
|
|
menu.item[i].saveSlot = -1;
|
|
menu.item[i].enabled = false;
|
|
}
|
|
|
|
int startSlot = 0;
|
|
if (_isSaveMenu && _savegameOffset == 0)
|
|
startSlot = 1;
|
|
|
|
KyraEngine_v2::SaveHeader header;
|
|
Common::InSaveFile *in;
|
|
for (int i = startSlot; i < num && uint(_savegameOffset + i) < _saveSlots.size(); ++i) {
|
|
if ((in = _vm->openSaveForReading(_vm->getSavegameFilename(_saveSlots[i + _savegameOffset]), header)) != 0) {
|
|
char *s = getTableString(menu.item[i].itemId);
|
|
Common::strlcpy(s, header.description.c_str(), 80);
|
|
Util::convertISOToDOS(s);
|
|
|
|
// Trim long GMM save descriptions to fit our save slots
|
|
_screen->_charWidth = -2;
|
|
int fC = _screen->getTextWidth(s);
|
|
while (s[0] && fC > 240) {
|
|
s[strlen(s) - 1] = 0;
|
|
fC = _screen->getTextWidth(s);
|
|
}
|
|
_screen->_charWidth = 0;
|
|
|
|
menu.item[i].saveSlot = _saveSlots[i + _savegameOffset];
|
|
menu.item[i].enabled = true;
|
|
delete in;
|
|
}
|
|
}
|
|
|
|
if (_savegameOffset == 0) {
|
|
if (_isSaveMenu) {
|
|
char *dst = getTableString(menu.item[0].itemId);
|
|
const char *src = getTableString(_vm->gameFlags().isTalkie ? 10 : 18);
|
|
strcpy(dst, src);
|
|
menu.item[0].saveSlot = -2;
|
|
menu.item[0].enabled = true;
|
|
} else {
|
|
char *dst = getTableString(menu.item[0].itemId);
|
|
const char *src = getTableString(_vm->gameFlags().isTalkie ? 34 : 42);
|
|
strcpy(dst, src);
|
|
}
|
|
}
|
|
}
|
|
|
|
int GUI_v2::scrollUpButton(Button *button) {
|
|
updateMenuButton(button);
|
|
|
|
if (_savegameOffset == (_isDeleteMenu ? 1 : 0))
|
|
return 0;
|
|
|
|
--_savegameOffset;
|
|
if (_isLoadMenu) {
|
|
setupSavegameNames(_loadMenu, 5);
|
|
// original calls something different here...
|
|
initMenu(_loadMenu);
|
|
} else if (_isSaveMenu || _isDeleteMenu) {
|
|
setupSavegameNames(_saveMenu, 5);
|
|
// original calls something different here...
|
|
initMenu(_saveMenu);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUI_v2::scrollDownButton(Button *button) {
|
|
updateMenuButton(button);
|
|
++_savegameOffset;
|
|
|
|
if (uint(_savegameOffset + 5) >= _saveSlots.size())
|
|
_savegameOffset = MAX<int>(_saveSlots.size() - 5, _isDeleteMenu ? 1 : 0);
|
|
|
|
if (_isLoadMenu) {
|
|
setupSavegameNames(_loadMenu, 5);
|
|
// original calls something different here...
|
|
initMenu(_loadMenu);
|
|
} else if (_isSaveMenu || _isDeleteMenu) {
|
|
setupSavegameNames(_saveMenu, 5);
|
|
// original calls something different here...
|
|
initMenu(_saveMenu);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUI_v2::resumeGame(Button *caller) {
|
|
updateMenuButton(caller);
|
|
_displayMenu = false;
|
|
return 0;
|
|
}
|
|
|
|
int GUI_v2::quitOptionsMenu(Button *caller) {
|
|
updateMenuButton(caller);
|
|
_isOptionsMenu = false;
|
|
return 0;
|
|
}
|
|
|
|
int GUI_v2::toggleWalkspeed(Button *caller) {
|
|
updateMenuButton(caller);
|
|
if (_vm->_configWalkspeed == 5)
|
|
_vm->_configWalkspeed = 3;
|
|
else
|
|
_vm->_configWalkspeed = 5;
|
|
_vm->setWalkspeed(_vm->_configWalkspeed);
|
|
setupOptionsButtons();
|
|
renewHighlight(_gameOptions);
|
|
return 0;
|
|
}
|
|
|
|
int GUI_v2::toggleText(Button *caller) {
|
|
updateMenuButton(caller);
|
|
|
|
if (_vm->textEnabled()) {
|
|
if (_vm->speechEnabled())
|
|
_vm->_configVoice = 1;
|
|
else
|
|
_vm->_configVoice = 3;
|
|
} else {
|
|
if (_vm->speechEnabled())
|
|
_vm->_configVoice = 2;
|
|
else
|
|
_vm->_configVoice = 0;
|
|
}
|
|
|
|
setupOptionsButtons();
|
|
renewHighlight(_gameOptions);
|
|
return 0;
|
|
}
|
|
|
|
int GUI_v2::clickLoadSlot(Button *caller) {
|
|
updateMenuButton(caller);
|
|
|
|
int index = caller->index - _menuButtons[0].index;
|
|
assert(index >= 0 && index <= 6);
|
|
MenuItem &item = _loadMenu.item[index];
|
|
|
|
if (item.saveSlot >= 0) {
|
|
_vm->_gameToLoad = item.saveSlot;
|
|
_isLoadMenu = false;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUI_v2::cancelLoadMenu(Button *caller) {
|
|
updateMenuButton(caller);
|
|
_isLoadMenu = false;
|
|
_noLoadProcess = true;
|
|
return 0;
|
|
}
|
|
|
|
int GUI_v2::saveMenu(Button *caller) {
|
|
updateSaveFileList(_vm->_targetName);
|
|
|
|
updateMenuButton(caller);
|
|
|
|
restorePage1(_vm->_screenBuffer);
|
|
backUpPage1(_vm->_screenBuffer);
|
|
|
|
_isSaveMenu = true;
|
|
_noSaveProcess = false;
|
|
_saveSlot = -1;
|
|
_savegameOffset = 0;
|
|
setupSavegameNames(_saveMenu, 5);
|
|
initMenu(_saveMenu);
|
|
|
|
updateAllMenuButtons();
|
|
|
|
while (_isSaveMenu) {
|
|
processHighlights(_saveMenu);
|
|
getInput();
|
|
}
|
|
|
|
if (_noSaveProcess) {
|
|
restorePage1(_vm->_screenBuffer);
|
|
backUpPage1(_vm->_screenBuffer);
|
|
initMenu(*_currentMenu);
|
|
updateAllMenuButtons();
|
|
return 0;
|
|
} else if (_saveSlot <= -1) {
|
|
return 0;
|
|
}
|
|
|
|
restorePage1(_vm->_screenBuffer);
|
|
restorePalette();
|
|
|
|
Graphics::Surface thumb;
|
|
createScreenThumbnail(thumb);
|
|
Util::convertDOSToISO(_saveDescription);
|
|
_vm->saveGameStateIntern(_saveSlot, _saveDescription, &thumb);
|
|
thumb.free();
|
|
|
|
_displayMenu = false;
|
|
_madeSave = true;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUI_v2::clickSaveSlot(Button *caller) {
|
|
updateMenuButton(caller);
|
|
|
|
int index = caller->index - _menuButtons[0].index;
|
|
assert(index >= 0 && index <= 6);
|
|
MenuItem &item = _saveMenu.item[index];
|
|
|
|
if (item.saveSlot >= 0) {
|
|
if (_isDeleteMenu) {
|
|
_slotToDelete = item.saveSlot;
|
|
_isDeleteMenu = false;
|
|
return 0;
|
|
} else {
|
|
_saveSlot = item.saveSlot;
|
|
strcpy(_saveDescription, getTableString(item.itemId));
|
|
}
|
|
} else if (item.saveSlot == -2) {
|
|
_saveSlot = getNextSavegameSlot();
|
|
memset(_saveDescription, 0, sizeof(_saveDescription));
|
|
}
|
|
|
|
restorePage1(_vm->_screenBuffer);
|
|
backUpPage1(_vm->_screenBuffer);
|
|
|
|
initMenu(_savenameMenu);
|
|
_screen->fillRect(0x26, 0x5B, 0x11F, 0x66, textFieldColor2());
|
|
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
|
|
const char *desc = nameInputProcess(_saveDescription, 0x27, 0x5C, textFieldColor1(), textFieldColor2(), textFieldColor3(), 0x50);
|
|
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
|
|
restorePage1(_vm->_screenBuffer);
|
|
backUpPage1(_vm->_screenBuffer);
|
|
if (desc) {
|
|
_isSaveMenu = false;
|
|
_isDeleteMenu = false;
|
|
} else {
|
|
initMenu(_saveMenu);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GUI_v2::cancelSaveMenu(Button *caller) {
|
|
updateMenuButton(caller);
|
|
_isSaveMenu = false;
|
|
_isDeleteMenu = false;
|
|
_noSaveProcess = true;
|
|
return 0;
|
|
}
|
|
|
|
int GUI_v2::deleteMenu(Button *caller) {
|
|
updateSaveFileList(_vm->_targetName);
|
|
|
|
updateMenuButton(caller);
|
|
if (_saveSlots.size() < 2) {
|
|
_vm->snd_playSoundEffect(0x0D);
|
|
return 0;
|
|
}
|
|
|
|
do {
|
|
restorePage1(_vm->_screenBuffer);
|
|
backUpPage1(_vm->_screenBuffer);
|
|
_savegameOffset = 1;
|
|
_saveMenu.menuNameId = _vm->gameFlags().isTalkie ? 35 : 1;
|
|
setupSavegameNames(_saveMenu, 5);
|
|
initMenu(_saveMenu);
|
|
_isDeleteMenu = true;
|
|
_slotToDelete = -1;
|
|
updateAllMenuButtons();
|
|
|
|
while (_isDeleteMenu) {
|
|
processHighlights(_saveMenu);
|
|
getInput();
|
|
}
|
|
|
|
if (_slotToDelete < 1) {
|
|
restorePage1(_vm->_screenBuffer);
|
|
backUpPage1(_vm->_screenBuffer);
|
|
initMenu(*_currentMenu);
|
|
updateAllMenuButtons();
|
|
_saveMenu.menuNameId = _vm->gameFlags().isTalkie ? 9 : 17;
|
|
return 0;
|
|
}
|
|
} while (choiceDialog(_vm->gameFlags().isTalkie ? 0x24 : 2, 1) == 0);
|
|
|
|
restorePage1(_vm->_screenBuffer);
|
|
backUpPage1(_vm->_screenBuffer);
|
|
initMenu(*_currentMenu);
|
|
updateAllMenuButtons();
|
|
_vm->_saveFileMan->removeSavefile(_vm->getSavegameFilename(_slotToDelete));
|
|
Common::Array<int>::iterator i = Common::find(_saveSlots.begin(), _saveSlots.end(), _slotToDelete);
|
|
while (i != _saveSlots.end()) {
|
|
++i;
|
|
if (i == _saveSlots.end())
|
|
break;
|
|
// We are only renaming all savefiles until we get some slots missing
|
|
// Also not rename quicksave slot filenames
|
|
if (*(i - 1) != *i || *i >= 990)
|
|
break;
|
|
Common::String oldName = _vm->getSavegameFilename(*i);
|
|
Common::String newName = _vm->getSavegameFilename(*i - 1);
|
|
_vm->_saveFileMan->renameSavefile(oldName, newName);
|
|
}
|
|
_saveMenu.menuNameId = _vm->gameFlags().isTalkie ? 9 : 17;
|
|
return 0;
|
|
}
|
|
|
|
const char *GUI_v2::nameInputProcess(char *buffer, int x, int y, uint8 c1, uint8 c2, uint8 c3, int bufferSize) {
|
|
bool running = true;
|
|
int curPos = strlen(buffer);
|
|
|
|
int x2 = x, y2 = y;
|
|
Screen::FontId of = _screen->setFont(Screen::FID_8_FNT);
|
|
_text->printText(buffer, x, y, c1, c2, c2);
|
|
|
|
for (int i = 0; i < curPos; ++i)
|
|
x2 += getCharWidth(buffer[i]);
|
|
|
|
drawTextfieldBlock(x2, y2, c3);
|
|
_screen->setFont(of);
|
|
|
|
_keyPressed.reset();
|
|
_cancelNameInput = _finishNameInput = false;
|
|
while (running && !_vm->shouldQuit()) {
|
|
of = _screen->setFont(Screen::FID_8_FNT);
|
|
checkTextfieldInput();
|
|
_screen->setFont(of);
|
|
processHighlights(_savenameMenu);
|
|
|
|
char inputKey = _keyPressed.ascii;
|
|
Util::convertISOToDOS(inputKey);
|
|
|
|
if (_keyPressed.keycode == Common::KEYCODE_RETURN || _keyPressed.keycode == Common::KEYCODE_KP_ENTER || _finishNameInput) {
|
|
if (checkSavegameDescription(buffer, curPos)) {
|
|
buffer[curPos] = 0;
|
|
running = false;
|
|
} else {
|
|
_finishNameInput = false;
|
|
}
|
|
} else if (_keyPressed.keycode == Common::KEYCODE_ESCAPE || _cancelNameInput) {
|
|
running = false;
|
|
return 0;
|
|
} else if ((_keyPressed.keycode == Common::KEYCODE_BACKSPACE || _keyPressed.keycode == Common::KEYCODE_DELETE) && curPos > 0) {
|
|
drawTextfieldBlock(x2, y2, c2);
|
|
--curPos;
|
|
x2 -= getCharWidth(buffer[curPos]);
|
|
drawTextfieldBlock(x2, y2, c3);
|
|
_screen->updateScreen();
|
|
_lastScreenUpdate = _vm->_system->getMillis();
|
|
} else if ((uint8)inputKey > 31 && (uint8)inputKey < (_vm->gameFlags().lang == Common::JA_JPN ? 128 : 226) && curPos < bufferSize) {
|
|
of = _screen->setFont(Screen::FID_8_FNT);
|
|
if (x2 + getCharWidth(inputKey) + 7 < 0x11F) {
|
|
buffer[curPos] = inputKey;
|
|
const char text[2] = { buffer[curPos], 0 };
|
|
_text->printText(text, x2, y2, c1, c2, c2);
|
|
x2 += getCharWidth(inputKey);
|
|
drawTextfieldBlock(x2, y2, c3);
|
|
++curPos;
|
|
_screen->updateScreen();
|
|
_lastScreenUpdate = _vm->_system->getMillis();
|
|
}
|
|
_screen->setFont(of);
|
|
}
|
|
|
|
_keyPressed.reset();
|
|
}
|
|
|
|
return buffer;
|
|
}
|
|
|
|
int GUI_v2::finishSavename(Button *caller) {
|
|
updateMenuButton(caller);
|
|
_finishNameInput = true;
|
|
return 0;
|
|
}
|
|
|
|
int GUI_v2::cancelSavename(Button *caller) {
|
|
updateMenuButton(caller);
|
|
_cancelNameInput = true;
|
|
return 0;
|
|
}
|
|
|
|
bool GUI_v2::checkSavegameDescription(const char *buffer, int size) {
|
|
if (!buffer || !size)
|
|
return false;
|
|
if (buffer[0] == 0)
|
|
return false;
|
|
for (int i = 0; i < size; ++i) {
|
|
if (buffer[i] != 0x20)
|
|
return true;
|
|
else if (buffer[i] == 0x00)
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int GUI_v2::getCharWidth(uint8 c) {
|
|
Screen::FontId old = _screen->setFont(Screen::FID_8_FNT);
|
|
_screen->_charWidth = -2;
|
|
int width = _screen->getCharWidth(c);
|
|
_screen->_charWidth = 0;
|
|
_screen->setFont(old);
|
|
return width;
|
|
}
|
|
|
|
void GUI_v2::drawTextfieldBlock(int x, int y, uint8 c) {
|
|
_screen->fillRect(x + 1, y + 1, x + 7, y + 8, c);
|
|
}
|
|
|
|
bool GUI_v2::choiceDialog(int name, bool type) {
|
|
_choiceMenu.highlightedItem = 0;
|
|
restorePage1(_vm->_screenBuffer);
|
|
backUpPage1(_vm->_screenBuffer);
|
|
if (type)
|
|
_choiceMenu.numberOfItems = 2;
|
|
else
|
|
_choiceMenu.numberOfItems = 1;
|
|
_choiceMenu.menuNameId = name;
|
|
|
|
initMenu(_choiceMenu);
|
|
_isChoiceMenu = true;
|
|
_choice = false;
|
|
|
|
while (_isChoiceMenu) {
|
|
processHighlights(_choiceMenu);
|
|
getInput();
|
|
}
|
|
|
|
restorePage1(_vm->_screenBuffer);
|
|
backUpPage1(_vm->_screenBuffer);
|
|
return _choice;
|
|
}
|
|
|
|
int GUI_v2::choiceYes(Button *caller) {
|
|
updateMenuButton(caller);
|
|
_choice = true;
|
|
_isChoiceMenu = false;
|
|
return 0;
|
|
}
|
|
|
|
int GUI_v2::choiceNo(Button *caller) {
|
|
updateMenuButton(caller);
|
|
_choice = false;
|
|
_isChoiceMenu = false;
|
|
return 0;
|
|
}
|
|
|
|
} // End of namespace Kyra
|