mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-26 03:37:53 +00:00
26ee630756
svn-id: r20582
1302 lines
36 KiB
C++
1302 lines
36 KiB
C++
/* ScummVM - Scumm Interpreter
|
||
* Copyright (C) 2003-2006 The ScummVM project
|
||
*
|
||
* 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 "common/stdafx.h"
|
||
#include "common/file.h"
|
||
#include "common/util.h"
|
||
#include "common/savefile.h"
|
||
#include "common/system.h"
|
||
|
||
#include "gui/message.h"
|
||
|
||
#include "sword1/control.h"
|
||
#include "sword1/logic.h"
|
||
#include "sword1/mouse.h"
|
||
#include "sword1/music.h"
|
||
#include "sword1/objectman.h"
|
||
#include "sword1/resman.h"
|
||
#include "sword1/sound.h"
|
||
#include "sword1/sword1.h"
|
||
#include "sword1/sworddefs.h"
|
||
#include "sword1/swordres.h"
|
||
|
||
namespace Sword1 {
|
||
|
||
enum {
|
||
kKeyRepeatInitialDelay = 400,
|
||
kKeyRepeatSustainDelay = 100
|
||
};
|
||
|
||
enum LangStrings {
|
||
STR_PAUSED = 0,
|
||
STR_INSERT_CD_A,
|
||
STR_INSERT_CD_B,
|
||
STR_INCORRECT_CD,
|
||
STR_SAVE,
|
||
STR_RESTORE,
|
||
STR_RESTART,
|
||
STR_START,
|
||
STR_QUIT,
|
||
STR_SPEED,
|
||
STR_VOLUME,
|
||
STR_TEXT,
|
||
STR_DONE,
|
||
STR_OK,
|
||
STR_CANCEL,
|
||
STR_MUSIC,
|
||
STR_SPEECH,
|
||
STR_FX,
|
||
STR_THE_END,
|
||
STR_DRIVE_FULL
|
||
};
|
||
|
||
enum ButtonIds {
|
||
BUTTON_DONE = 1,
|
||
BUTTON_MAIN_PANEL,
|
||
BUTTON_SAVE_PANEL,
|
||
BUTTON_RESTORE_PANEL,
|
||
BUTTON_RESTART,
|
||
BUTTON_QUIT,
|
||
BUTTON_SPEED,
|
||
BUTTON_VOLUME_PANEL,
|
||
BUTTON_TEXT,
|
||
BUTTON_CONFIRM,
|
||
//-
|
||
BUTTON_SCROLL_UP_FAST,
|
||
BUTTON_SCROLL_UP_SLOW,
|
||
BUTTON_SCROLL_DOWN_SLOW,
|
||
BUTTON_SCROLL_DOWN_FAST,
|
||
BUTTON_SAVE_SELECT1,
|
||
BUTTON_SAVE_SELECT2,
|
||
BUTTON_SAVE_SELECT3,
|
||
BUTTON_SAVE_SELECT4,
|
||
BUTTON_SAVE_SELECT5,
|
||
BUTTON_SAVE_SELECT6,
|
||
BUTTON_SAVE_SELECT7,
|
||
BUTTON_SAVE_SELECT8,
|
||
BUTTON_SAVE_RESTORE_OKAY,
|
||
BUTTON_SAVE_CANCEL,
|
||
//-
|
||
CONFIRM_OKAY,
|
||
CONFIRM_CANCEL
|
||
};
|
||
|
||
enum TextModes {
|
||
TEXT_LEFT_ALIGN = 0,
|
||
TEXT_CENTER,
|
||
TEXT_RIGHT_ALIGN,
|
||
TEXT_RED_FONT = 128
|
||
};
|
||
|
||
ControlButton::ControlButton(uint16 x, uint16 y, uint32 resId, uint8 id, uint8 flag, ResMan *pResMan, uint8 *screenBuf, OSystem *system) {
|
||
_x = x;
|
||
_y = y;
|
||
_id = id;
|
||
_flag = flag;
|
||
_resId = resId;
|
||
_resMan = pResMan;
|
||
_frameIdx = 0;
|
||
_resMan->resOpen(_resId);
|
||
FrameHeader *tmp = _resMan->fetchFrame(_resMan->fetchRes(_resId), 0);
|
||
_width = FROM_LE_16(tmp->width);
|
||
_height = FROM_LE_16(tmp->height);
|
||
if ((x == 0) && (y == 0)) { // center the frame (used for panels);
|
||
_x = (640 - _width) / 2;
|
||
_y = (480 - _height) / 2;
|
||
}
|
||
_dstBuf = screenBuf + _y * SCREEN_WIDTH + _x;
|
||
_system = system;
|
||
}
|
||
|
||
ControlButton::~ControlButton(void) {
|
||
_resMan->resClose(_resId);
|
||
}
|
||
|
||
bool ControlButton::isSaveslot(void) {
|
||
return ((_resId >= SR_SLAB1) && (_resId <= SR_SLAB4));
|
||
}
|
||
|
||
void ControlButton::draw(void) {
|
||
FrameHeader *fHead = _resMan->fetchFrame(_resMan->fetchRes(_resId), _frameIdx);
|
||
uint8 *src = (uint8*)fHead + sizeof(FrameHeader);
|
||
uint8 *dst = _dstBuf;
|
||
for (uint16 cnt = 0; cnt < FROM_LE_16(fHead->height); cnt++) {
|
||
for (uint16 cntx = 0; cntx < FROM_LE_16(fHead->width); cntx++)
|
||
if (src[cntx])
|
||
dst[cntx] = src[cntx];
|
||
dst += SCREEN_WIDTH;
|
||
src += FROM_LE_16(fHead->width);
|
||
}
|
||
_system->copyRectToScreen(_dstBuf, SCREEN_WIDTH, _x, _y, _width, _height);
|
||
}
|
||
|
||
bool ControlButton::wasClicked(uint16 mouseX, uint16 mouseY) {
|
||
if ((_x <= mouseX) && (_y <= mouseY) && (_x + _width >= mouseX) && (_y + _height >= mouseY))
|
||
return true;
|
||
else
|
||
return false;
|
||
}
|
||
|
||
void ControlButton::setSelected(uint8 selected) {
|
||
_frameIdx = selected;
|
||
draw();
|
||
}
|
||
|
||
Control::Control(Common::SaveFileManager *saveFileMan, ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, Mouse *pMouse, Sound *pSound, Music *pMusic) {
|
||
_saveFileMan = saveFileMan;
|
||
_resMan = pResMan;
|
||
_objMan = pObjMan;
|
||
_system = system;
|
||
_mouse = pMouse;
|
||
_music = pMusic;
|
||
_sound = pSound;
|
||
_lStrings = _languageStrings + SwordEngine::_systemVars.language * 20;
|
||
_keyRepeat = 0;
|
||
_keyRepeatTime = 0;
|
||
}
|
||
|
||
void Control::askForCd(void) {
|
||
_screenBuf = (uint8*)malloc(640 * 480);
|
||
uint32 fontId = SR_FONT;
|
||
if (SwordEngine::_systemVars.language == BS1_CZECH)
|
||
fontId = CZECH_SR_FONT;
|
||
_font = (uint8*)_resMan->openFetchRes(fontId);
|
||
uint8 *pal = (uint8*)_resMan->openFetchRes(SR_PALETTE);
|
||
uint8 *palOut = (uint8*)malloc(256 * 4);
|
||
for (uint16 cnt = 1; cnt < 256; cnt++) {
|
||
palOut[cnt * 4 + 0] = pal[cnt * 3 + 0] << 2;
|
||
palOut[cnt * 4 + 1] = pal[cnt * 3 + 1] << 2;
|
||
palOut[cnt * 4 + 2] = pal[cnt * 3 + 2] << 2;
|
||
}
|
||
palOut[0] = palOut[1] = palOut[2] = palOut[3] = 0;
|
||
_resMan->resClose(SR_PALETTE);
|
||
_system->setPalette(palOut, 0, 256);
|
||
free(palOut);
|
||
|
||
Common::File test;
|
||
char fName[10];
|
||
uint8 textA[50];
|
||
sprintf(fName, "cd%d.id", SwordEngine::_systemVars.currentCD);
|
||
sprintf((char*)textA, "%s%d", _lStrings[STR_INSERT_CD_A], SwordEngine::_systemVars.currentCD);
|
||
bool notAccepted = true;
|
||
bool refreshText = true;
|
||
do {
|
||
if (refreshText) {
|
||
memset(_screenBuf, 0, 640 * 480);
|
||
renderText(textA, 320, 220, TEXT_CENTER);
|
||
renderText(_lStrings[STR_INSERT_CD_B], 320, 240, TEXT_CENTER);
|
||
_system->copyRectToScreen(_screenBuf, 640, 0, 0, 640, 480);
|
||
_system->updateScreen();
|
||
}
|
||
delay(300);
|
||
if (_keyPressed) {
|
||
test.open(fName);
|
||
if (!test.isOpen()) {
|
||
memset(_screenBuf, 0, 640 * 480);
|
||
renderText(_lStrings[STR_INCORRECT_CD], 320, 230, TEXT_CENTER);
|
||
_system->copyRectToScreen(_screenBuf, 640, 0, 0, 640, 480);
|
||
_system->updateScreen();
|
||
delay(2000);
|
||
refreshText = true;
|
||
} else {
|
||
test.close();
|
||
notAccepted = false;
|
||
}
|
||
}
|
||
} while (notAccepted && (!SwordEngine::_systemVars.engineQuit));
|
||
|
||
_resMan->resClose(fontId);
|
||
free(_screenBuf);
|
||
}
|
||
|
||
uint8 Control::runPanel(void) {
|
||
_mouseDown = false;
|
||
_restoreBuf = NULL;
|
||
_keyPressed = _numButtons = 0;
|
||
_screenBuf = (uint8*)malloc(640 * 480);
|
||
memset(_screenBuf, 0, 640 * 480);
|
||
_system->copyRectToScreen(_screenBuf, 640, 0, 0, 640, 480);
|
||
_sound->quitScreen();
|
||
|
||
uint32 fontId = SR_FONT, redFontId = SR_REDFONT;
|
||
if (SwordEngine::_systemVars.language == BS1_CZECH) {
|
||
fontId = CZECH_SR_FONT;
|
||
redFontId = CZECH_SR_REDFONT;
|
||
}
|
||
_font = (uint8*)_resMan->openFetchRes(fontId);
|
||
_redFont = (uint8*)_resMan->openFetchRes(redFontId);
|
||
|
||
uint8 *pal = (uint8*)_resMan->openFetchRes(SR_PALETTE);
|
||
uint8 *palOut = (uint8*)malloc(256 * 4);
|
||
for (uint16 cnt = 1; cnt < 256; cnt++) {
|
||
palOut[cnt * 4 + 0] = pal[cnt * 3 + 0] << 2;
|
||
palOut[cnt * 4 + 1] = pal[cnt * 3 + 1] << 2;
|
||
palOut[cnt * 4 + 2] = pal[cnt * 3 + 2] << 2;
|
||
}
|
||
palOut[0] = palOut[1] = palOut[2] = palOut[3] = 0;
|
||
_resMan->resClose(SR_PALETTE);
|
||
_system->setPalette(palOut, 0, 256);
|
||
free(palOut);
|
||
uint8 mode = 0, newMode = BUTTON_MAIN_PANEL;
|
||
bool fullRefresh = false;
|
||
_mouse->controlPanel(true);
|
||
uint8 retVal = CONTROL_NOTHING_DONE;
|
||
_music->startMusic(61, 1);
|
||
|
||
do {
|
||
if (newMode) {
|
||
mode = newMode;
|
||
fullRefresh = true;
|
||
destroyButtons();
|
||
memset(_screenBuf, 0, 640 * 480);
|
||
if (mode != BUTTON_SAVE_PANEL)
|
||
_cursorVisible = false;
|
||
}
|
||
switch (mode) {
|
||
case BUTTON_MAIN_PANEL:
|
||
if (fullRefresh)
|
||
setupMainPanel();
|
||
break;
|
||
case BUTTON_SAVE_PANEL:
|
||
if (fullRefresh) {
|
||
setupSaveRestorePanel(true);
|
||
}
|
||
if (_selectedSavegame < 255) {
|
||
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
|
||
bool visible = _cursorVisible;
|
||
_cursorTick++;
|
||
if (_cursorTick == 7)
|
||
_cursorVisible = true;
|
||
else if (_cursorTick == 14) {
|
||
_cursorVisible = false;
|
||
_cursorTick = 0;
|
||
}
|
||
if (_keyPressed)
|
||
handleSaveKey(_keyPressed);
|
||
else if (_cursorVisible != visible)
|
||
showSavegameNames();
|
||
} else {
|
||
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
|
||
}
|
||
break;
|
||
case BUTTON_RESTORE_PANEL:
|
||
if (fullRefresh)
|
||
setupSaveRestorePanel(false);
|
||
break;
|
||
case BUTTON_VOLUME_PANEL:
|
||
if (fullRefresh)
|
||
setupVolumePanel();
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
if (fullRefresh) {
|
||
fullRefresh = false;
|
||
_system->copyRectToScreen(_screenBuf, SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, 480);
|
||
}
|
||
_system->updateScreen();
|
||
delay(1000 / 12);
|
||
newMode = getClicks(mode, &retVal);
|
||
} while ((newMode != BUTTON_DONE) && (retVal == 0) && (!SwordEngine::_systemVars.engineQuit));
|
||
destroyButtons();
|
||
_resMan->resClose(fontId);
|
||
_resMan->resClose(redFontId);
|
||
memset(_screenBuf, 0, 640 * 480);
|
||
_system->copyRectToScreen(_screenBuf, 640, 0, 0, 640, 480);
|
||
free(_screenBuf);
|
||
_mouse->controlPanel(false);
|
||
_music->startMusic(Logic::_scriptVars[CURRENT_MUSIC], 1);
|
||
return retVal;
|
||
}
|
||
|
||
uint8 Control::getClicks(uint8 mode, uint8 *retVal) {
|
||
uint8 checkButtons = _numButtons;
|
||
if (mode == BUTTON_VOLUME_PANEL) {
|
||
handleVolumeClicks();
|
||
checkButtons = 1;
|
||
}
|
||
|
||
uint8 flag = 0;
|
||
if (_keyPressed == 27)
|
||
flag = kButtonCancel;
|
||
else if (_keyPressed == '\r' || _keyPressed == '\n')
|
||
flag = kButtonOk;
|
||
|
||
if (flag) {
|
||
for (uint8 cnt = 0; cnt < checkButtons; cnt++)
|
||
if (_buttons[cnt]->_flag == flag)
|
||
return handleButtonClick(_buttons[cnt]->_id, mode, retVal);
|
||
}
|
||
|
||
if (!_mouseState)
|
||
return 0;
|
||
if (_mouseState & BS1L_BUTTON_DOWN)
|
||
for (uint8 cnt = 0; cnt < checkButtons; cnt++)
|
||
if (_buttons[cnt]->wasClicked(_mouseX, _mouseY)) {
|
||
_selectedButton = cnt;
|
||
_buttons[cnt]->setSelected(1);
|
||
if (_buttons[cnt]->isSaveslot())
|
||
showSavegameNames();
|
||
}
|
||
if (_mouseState & BS1L_BUTTON_UP) {
|
||
for (uint8 cnt = 0; cnt < checkButtons; cnt++)
|
||
if (_buttons[cnt]->wasClicked(_mouseX, _mouseY))
|
||
if (_selectedButton == cnt) {
|
||
// saveslots stay selected after clicking
|
||
if (!_buttons[cnt]->isSaveslot())
|
||
_buttons[cnt]->setSelected(0);
|
||
_selectedButton = 255;
|
||
return handleButtonClick(_buttons[cnt]->_id, mode, retVal);
|
||
}
|
||
if (_selectedButton < checkButtons) {
|
||
_buttons[_selectedButton]->setSelected(0);
|
||
if (_buttons[_selectedButton]->isSaveslot())
|
||
showSavegameNames();
|
||
}
|
||
_selectedButton = 255;
|
||
}
|
||
if (_mouseState & BS1_WHEEL_UP) {
|
||
for (uint8 cnt = 0; cnt < checkButtons; cnt++)
|
||
if (_buttons[cnt]->_id == BUTTON_SCROLL_UP_SLOW)
|
||
return handleButtonClick(_buttons[cnt]->_id, mode, retVal);
|
||
}
|
||
if (_mouseState & BS1_WHEEL_DOWN) {
|
||
for (uint8 cnt = 0; cnt < checkButtons; cnt++)
|
||
if (_buttons[cnt]->_id == BUTTON_SCROLL_DOWN_SLOW)
|
||
return handleButtonClick(_buttons[cnt]->_id, mode, retVal);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
uint8 Control::handleButtonClick(uint8 id, uint8 mode, uint8 *retVal) {
|
||
switch (mode) {
|
||
case BUTTON_MAIN_PANEL:
|
||
if (id == BUTTON_RESTART) {
|
||
if (SwordEngine::_systemVars.controlPanelMode) // if player is dead or has just started, don't ask for confirmation
|
||
*retVal |= CONTROL_RESTART_GAME;
|
||
else if (getConfirm(_lStrings[STR_RESTART]))
|
||
*retVal |= CONTROL_RESTART_GAME;
|
||
else
|
||
return mode;
|
||
} else if ((id == BUTTON_RESTORE_PANEL) || (id == BUTTON_SAVE_PANEL) ||
|
||
(id == BUTTON_DONE) || (id == BUTTON_VOLUME_PANEL))
|
||
return id;
|
||
else if (id == BUTTON_TEXT) {
|
||
SwordEngine::_systemVars.showText ^= 1;
|
||
_buttons[5]->setSelected(SwordEngine::_systemVars.showText);
|
||
} else if (id == BUTTON_QUIT) {
|
||
if (getConfirm(_lStrings[STR_QUIT]))
|
||
SwordEngine::_systemVars.engineQuit = true;
|
||
return mode;
|
||
}
|
||
break;
|
||
case BUTTON_SAVE_PANEL:
|
||
case BUTTON_RESTORE_PANEL:
|
||
if ((id >= BUTTON_SCROLL_UP_FAST) && (id <= BUTTON_SCROLL_DOWN_FAST))
|
||
saveNameScroll(id, mode == BUTTON_SAVE_PANEL);
|
||
else if ((id >= BUTTON_SAVE_SELECT1) && (id <= BUTTON_SAVE_SELECT8))
|
||
saveNameSelect(id, mode == BUTTON_SAVE_PANEL);
|
||
else if (id == BUTTON_SAVE_RESTORE_OKAY) {
|
||
if (mode == BUTTON_SAVE_PANEL) {
|
||
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
|
||
if (saveToFile()) // don't go back to main panel if save fails.
|
||
return BUTTON_DONE;
|
||
} else {
|
||
if (restoreFromFile()) { // don't go back to main panel if restore fails.
|
||
*retVal |= CONTROL_GAME_RESTORED;
|
||
return BUTTON_MAIN_PANEL;
|
||
}
|
||
}
|
||
} else if (id == BUTTON_SAVE_CANCEL) {
|
||
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
|
||
return BUTTON_MAIN_PANEL; // mode down to main panel
|
||
}
|
||
break;
|
||
case BUTTON_VOLUME_PANEL:
|
||
return id;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
void Control::deselectSaveslots(void) {
|
||
for (uint8 cnt = 0; cnt < 8; cnt++)
|
||
_buttons[cnt]->setSelected(0);
|
||
}
|
||
|
||
void Control::setupMainPanel(void) {
|
||
uint32 panelId;
|
||
|
||
if (SwordEngine::_systemVars.controlPanelMode == CP_DEATHSCREEN)
|
||
panelId = SR_DEATHPANEL;
|
||
else {
|
||
if (SwordEngine::_systemVars.language <= BS1_SPANISH)
|
||
panelId = SR_PANEL_ENGLISH + SwordEngine::_systemVars.language;
|
||
else
|
||
panelId = SR_PANEL_ENGLISH;
|
||
}
|
||
|
||
ControlButton *panel = new ControlButton(0, 0, panelId, 0, 0, _resMan, _screenBuf, _system);
|
||
panel->draw();
|
||
delete panel;
|
||
|
||
if (SwordEngine::_systemVars.controlPanelMode != CP_NORMAL)
|
||
createButtons(_deathButtons, 3);
|
||
else {
|
||
createButtons(_panelButtons, 7);
|
||
_buttons[5]->setSelected(SwordEngine::_systemVars.showText);
|
||
}
|
||
|
||
if (SwordEngine::_systemVars.controlPanelMode == CP_THEEND) // end of game
|
||
renderText(_lStrings[STR_THE_END], 480, 188 + 40, TEXT_RIGHT_ALIGN);
|
||
|
||
if (SwordEngine::_systemVars.controlPanelMode == CP_NORMAL) { // normal panel
|
||
renderText(_lStrings[STR_SAVE], 180, 188 + 40, TEXT_LEFT_ALIGN);
|
||
renderText(_lStrings[STR_DONE], 460, 332 + 40, TEXT_RIGHT_ALIGN);
|
||
renderText(_lStrings[STR_RESTORE], 180, 224 + 40, TEXT_LEFT_ALIGN);
|
||
renderText(_lStrings[STR_RESTART], 180, 260 + 40, TEXT_LEFT_ALIGN);
|
||
renderText(_lStrings[STR_QUIT], 180, 296 + 40, TEXT_LEFT_ALIGN);
|
||
|
||
renderText(_lStrings[STR_VOLUME], 460, 188 + 40, TEXT_RIGHT_ALIGN);
|
||
renderText(_lStrings[STR_TEXT], 460, 224 + 40, TEXT_RIGHT_ALIGN);
|
||
} else {
|
||
renderText(_lStrings[STR_RESTORE], 285, 224 + 40, TEXT_LEFT_ALIGN);
|
||
if (SwordEngine::_systemVars.controlPanelMode == CP_NEWGAME) // just started game
|
||
renderText(_lStrings[STR_START], 285, 260 + 40, TEXT_LEFT_ALIGN);
|
||
else
|
||
renderText(_lStrings[STR_RESTART], 285, 260 + 40, TEXT_LEFT_ALIGN);
|
||
renderText(_lStrings[STR_QUIT], 285, 296 + 40, TEXT_LEFT_ALIGN);
|
||
}
|
||
}
|
||
|
||
void Control::setupSaveRestorePanel(bool saving) {
|
||
FrameHeader *savePanel = _resMan->fetchFrame(_resMan->openFetchRes(SR_WINDOW), 0);
|
||
uint16 panelX = (640 - FROM_LE_16(savePanel->width)) / 2;
|
||
uint16 panelY = (480 - FROM_LE_16(savePanel->height)) / 2;
|
||
ControlButton *panel = new ControlButton(panelX, panelY, SR_WINDOW, 0, 0, _resMan, _screenBuf, _system);
|
||
panel->draw();
|
||
delete panel;
|
||
_resMan->resClose(SR_WINDOW);
|
||
createButtons(_saveButtons, 14);
|
||
renderText(_lStrings[STR_CANCEL], _saveButtons[13].x - 10, _saveButtons[13].y, TEXT_RIGHT_ALIGN);
|
||
if (saving) {
|
||
renderText(_lStrings[STR_SAVE], _saveButtons[12].x + 30, _saveButtons[13].y, TEXT_LEFT_ALIGN);
|
||
} else {
|
||
renderText(_lStrings[STR_RESTORE], _saveButtons[12].x + 30, _saveButtons[13].y, TEXT_LEFT_ALIGN);
|
||
}
|
||
readSavegameDescriptions();
|
||
_selectedSavegame = 255;
|
||
showSavegameNames();
|
||
}
|
||
|
||
void Control::setupVolumePanel(void) {
|
||
ControlButton *panel = new ControlButton(0, 0, SR_VOLUME, 0, 0, _resMan, _screenBuf, _system);
|
||
panel->draw();
|
||
delete panel;
|
||
|
||
renderText(_lStrings[STR_MUSIC], 149, 39 + 40, TEXT_LEFT_ALIGN);
|
||
renderText(_lStrings[STR_SPEECH], 320, 39 + 40, TEXT_CENTER);
|
||
renderText(_lStrings[STR_FX], 438, 39 + 40, TEXT_LEFT_ALIGN);
|
||
|
||
createButtons(_volumeButtons, 4);
|
||
renderText(_lStrings[STR_DONE], _volumeButtons[0].x - 10, _volumeButtons[0].y, TEXT_RIGHT_ALIGN);
|
||
|
||
uint8 volL, volR;
|
||
_music->giveVolume(&volL, &volR);
|
||
renderVolumeBar(1, volL, volR);
|
||
_sound->giveSpeechVol(&volL, &volR);
|
||
renderVolumeBar(2, volL, volR);
|
||
_sound->giveSfxVol(&volL, &volR);
|
||
renderVolumeBar(3, volL, volR);
|
||
}
|
||
|
||
void Control::handleVolumeClicks(void) {
|
||
if (_mouseDown) {
|
||
uint8 clickedId = 0;
|
||
for (uint8 cnt = 1; cnt < 4; cnt++)
|
||
if (_buttons[cnt]->wasClicked(_mouseX, _mouseY))
|
||
clickedId = cnt;
|
||
if (clickedId) { // these are circle shaped, so check again if it was clicked.
|
||
uint8 clickDest = 0;
|
||
int16 mouseDiffX = _mouseX - (_volumeButtons[clickedId].x + 48);
|
||
int16 mouseDiffY = _mouseY - (_volumeButtons[clickedId].y + 48);
|
||
int16 mouseOffs = (int16)sqrt((double)(mouseDiffX * mouseDiffX + mouseDiffY * mouseDiffY));
|
||
// check if the player really hit the button (but not the center).
|
||
if ((mouseOffs <= 42) && (mouseOffs >= 8)) {
|
||
if (mouseDiffX > 8) { // right part
|
||
if (mouseDiffY < -8) // upper right
|
||
clickDest = 2;
|
||
else if (ABS(mouseDiffY) <= 8) // right
|
||
clickDest = 3;
|
||
else // lower right
|
||
clickDest = 4;
|
||
} else if (mouseDiffX < -8) { // left part
|
||
if (mouseDiffY < -8) // upper left
|
||
clickDest = 8;
|
||
else if (ABS(mouseDiffY) <= 8) // left
|
||
clickDest = 7;
|
||
else // lower left
|
||
clickDest = 6;
|
||
} else { // middle
|
||
if (mouseDiffY < -8)
|
||
clickDest = 1; // upper
|
||
else if (mouseDiffY > 8)
|
||
clickDest = 5; // lower
|
||
}
|
||
}
|
||
_buttons[clickedId]->setSelected(clickDest);
|
||
changeVolume(clickedId, clickDest);
|
||
}
|
||
} else if (_mouseState & BS1L_BUTTON_UP) {
|
||
_buttons[1]->setSelected(0);
|
||
_buttons[2]->setSelected(0);
|
||
_buttons[3]->setSelected(0);
|
||
}
|
||
}
|
||
|
||
void Control::changeVolume(uint8 id, uint8 action) {
|
||
// ids: 1 = music, 2 = speech, 3 = sfx
|
||
uint8 volL = 0, volR = 0;
|
||
if (id == 1)
|
||
_music->giveVolume(&volL, &volR);
|
||
else if (id == 2)
|
||
_sound->giveSpeechVol(&volL, &volR);
|
||
else if (id == 3)
|
||
_sound->giveSfxVol(&volL, &volR);
|
||
|
||
int8 direction = 0;
|
||
if ((action >= 4) && (action <= 6)) // lower part of the button => decrease volume
|
||
direction = -1;
|
||
else if ((action == 8) || (action == 1) || (action == 2)) // upper part => increase volume
|
||
direction = 1;
|
||
else if ((action == 3) || (action == 7)) // middle part => pan volume
|
||
direction = 1;
|
||
int8 factorL = 8, factorR = 8;
|
||
if ((action >= 6) && (action <= 8)) { // left part => left pan
|
||
factorL = 8;
|
||
factorR = (action == 7) ? -8 : 0;
|
||
} else if ((action >= 2) && (action <= 4)) { // right part
|
||
factorR = 8;
|
||
factorL = (action == 3) ? -8 : 0;
|
||
}
|
||
int16 resVolL = volL + direction * factorL;
|
||
int16 resVolR = volR + direction * factorR;
|
||
|
||
volL = (uint8)MAX((int16)0, MIN(resVolL, (int16)255));
|
||
volR = (uint8)MAX((int16)0, MIN(resVolR, (int16)255));
|
||
|
||
if (id == 1)
|
||
_music->setVolume(volL, volR);
|
||
else if (id == 2)
|
||
_sound->setSpeechVol(volL, volR);
|
||
else if (id == 3)
|
||
_sound->setSfxVol(volL, volR);
|
||
|
||
renderVolumeBar(id, volL, volR);
|
||
}
|
||
|
||
bool Control::getConfirm(const uint8 *title) {
|
||
ControlButton *panel = new ControlButton(0, 0, SR_CONFIRM, 0, 0, _resMan, _screenBuf, _system);
|
||
panel->draw();
|
||
delete panel;
|
||
renderText(title, 320, 160, TEXT_CENTER);
|
||
ControlButton *buttons[2];
|
||
buttons[0] = new ControlButton(260, 192 + 40, SR_BUTTON, 0, 0, _resMan, _screenBuf, _system);
|
||
renderText(_lStrings[STR_OK], 640 - 260, 192 + 40, TEXT_RIGHT_ALIGN);
|
||
buttons[1] = new ControlButton(260, 256 + 40, SR_BUTTON, 0, 0, _resMan, _screenBuf, _system);
|
||
renderText(_lStrings[STR_CANCEL], 640 - 260, 256 + 40, TEXT_RIGHT_ALIGN);
|
||
uint8 retVal = 0;
|
||
uint8 clickVal = 0;
|
||
do {
|
||
buttons[0]->draw();
|
||
buttons[1]->draw();
|
||
_system->updateScreen();
|
||
delay(1000 / 12);
|
||
if (_keyPressed == 27)
|
||
retVal = 2;
|
||
else if (_keyPressed == '\r' || _keyPressed == '\n')
|
||
retVal = 1;
|
||
if (_mouseState & BS1L_BUTTON_DOWN) {
|
||
if (buttons[0]->wasClicked(_mouseX, _mouseY))
|
||
clickVal = 1;
|
||
else if (buttons[1]->wasClicked(_mouseX, _mouseY))
|
||
clickVal = 2;
|
||
else
|
||
clickVal = 0;
|
||
if (clickVal)
|
||
buttons[clickVal - 1]->setSelected(1);
|
||
}
|
||
if ((_mouseState & BS1L_BUTTON_UP) && (clickVal)) {
|
||
if (buttons[clickVal - 1]->wasClicked(_mouseX, _mouseY))
|
||
retVal = clickVal;
|
||
else
|
||
buttons[clickVal - 1]->setSelected(0);
|
||
clickVal = 0;
|
||
}
|
||
} while (!retVal);
|
||
delete buttons[0];
|
||
delete buttons[1];
|
||
return retVal == 1;
|
||
}
|
||
|
||
bool Control::keyAccepted(uint8 key) {
|
||
// this routine needs changes for Czech keys... No idea how to do that, though.
|
||
// FIXME: It is not a good idea to put non-ASCII chars into a C source file,
|
||
// since there is no way to specify which encoding you are using.
|
||
// It is better to encode them as hex/octal. Although in this particular
|
||
// case, it seems questionable to do this at all, since we currently
|
||
// do not at all specify which encoding keyboard events use, so this
|
||
// check here is probably not portable anyway...
|
||
static const char allowedSpecials[] = "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,.:-()?! \"\'";
|
||
if (((key >= 'A') && (key <= 'Z')) ||
|
||
((key >= 'a') && (key <= 'z')) ||
|
||
((key >= '0') && (key <= '9')) ||
|
||
strchr(allowedSpecials, key))
|
||
return true;
|
||
else
|
||
return false;
|
||
}
|
||
|
||
void Control::handleSaveKey(uint8 key) {
|
||
if (_selectedSavegame < 255) {
|
||
uint8 len = strlen((char*)_saveNames[_selectedSavegame]);
|
||
if ((key == 8) && len) // backspace
|
||
_saveNames[_selectedSavegame][len - 1] = '\0';
|
||
else if (keyAccepted(key) && (len < 31)) {
|
||
_saveNames[_selectedSavegame][len] = key;
|
||
_saveNames[_selectedSavegame][len + 1] = '\0';
|
||
}
|
||
showSavegameNames();
|
||
}
|
||
}
|
||
|
||
bool Control::saveToFile(void) {
|
||
if ((_selectedSavegame == 255) || !strlen((char*)_saveNames[_selectedSavegame]))
|
||
return false; // no saveslot selected or no name entered
|
||
saveGameToFile(_selectedSavegame);
|
||
writeSavegameDescriptions();
|
||
return true;
|
||
}
|
||
|
||
bool Control::restoreFromFile(void) {
|
||
if (_selectedSavegame < 255) {
|
||
return restoreGameFromFile(_selectedSavegame);
|
||
} else
|
||
return false;
|
||
}
|
||
|
||
void Control::readSavegameDescriptions(void) {
|
||
Common::InSaveFile *inf;
|
||
inf = _saveFileMan->openForLoading("SAVEGAME.INF");
|
||
_saveScrollPos = _saveFiles = 0;
|
||
_selectedSavegame = 255;
|
||
if (inf) {
|
||
uint8 curFileNum = 0;
|
||
uint8 ch;
|
||
do {
|
||
uint8 pos = 0;
|
||
do {
|
||
ch = inf->readByte();
|
||
if ((ch == 10) || (ch == 255))
|
||
_saveNames[curFileNum][pos] = '\0';
|
||
else
|
||
_saveNames[curFileNum][pos] = ch;
|
||
pos++;
|
||
} while ((ch != 10) && (ch != 255));
|
||
curFileNum++;
|
||
} while (ch != 255);
|
||
_saveFiles = curFileNum;
|
||
for (uint8 cnt = _saveFiles; cnt < 64; cnt++)
|
||
_saveNames[cnt][0] = '\0';
|
||
} else
|
||
for (uint8 cnt = 0; cnt < 64; cnt++)
|
||
_saveNames[cnt][0] = '\0';
|
||
delete inf;
|
||
}
|
||
|
||
int Control::displayMessage(const char *altButton, const char *message, ...) {
|
||
char buf[STRINGBUFLEN];
|
||
va_list va;
|
||
|
||
va_start(va, message);
|
||
vsnprintf(buf, STRINGBUFLEN, message, va);
|
||
va_end(va);
|
||
|
||
GUI::MessageDialog dialog(buf, "OK", altButton);
|
||
int result = dialog.runModal();
|
||
_mouse->setPointer(MSE_POINTER, 0);
|
||
return result;
|
||
}
|
||
|
||
void Control::writeSavegameDescriptions(void) {
|
||
Common::OutSaveFile *outf;
|
||
outf = _saveFileMan->openForSaving("SAVEGAME.INF");
|
||
|
||
if (!outf) {
|
||
// Display an error message, and do nothing
|
||
displayMessage(0, "Can't create SAVEGAME.INF in directory '%s'", _saveFileMan->getSavePath());
|
||
return;
|
||
}
|
||
|
||
// if the player accidently clicked the last slot and then deselected it again,
|
||
// we'd still have _saveFiles == 64, so get rid of the empty end.
|
||
while (strlen((char*)_saveNames[_saveFiles - 1]) == 0)
|
||
_saveFiles--;
|
||
for (uint8 cnt = 0; cnt < _saveFiles; cnt++) {
|
||
int len = strlen((char*)_saveNames[cnt]);
|
||
if (len > 0)
|
||
outf->write(_saveNames[cnt], len);
|
||
if (cnt < _saveFiles - 1)
|
||
outf->writeByte(10);
|
||
else
|
||
outf->writeByte(255);
|
||
}
|
||
outf->flush();
|
||
if (outf->ioFailed())
|
||
displayMessage(0, "Can't write to SAVEGAME.INF in directory '%s'. Device full?", _saveFileMan->getSavePath());
|
||
delete outf;
|
||
}
|
||
|
||
bool Control::savegamesExist(void) {
|
||
bool retVal = false;
|
||
Common::InSaveFile *inf;
|
||
inf = _saveFileMan->openForLoading("SAVEGAME.INF");
|
||
if (inf)
|
||
retVal = true;
|
||
delete inf;
|
||
return retVal;
|
||
}
|
||
|
||
void Control::showSavegameNames(void) {
|
||
for (uint8 cnt = 0; cnt < 8; cnt++) {
|
||
_buttons[cnt]->draw();
|
||
uint8 textMode = TEXT_LEFT_ALIGN;
|
||
uint16 ycoord = _saveButtons[cnt].y + 2;
|
||
uint8 str[40];
|
||
sprintf((char*)str, "%d. %s", cnt + _saveScrollPos + 1, _saveNames[cnt + _saveScrollPos]);
|
||
if (cnt + _saveScrollPos == _selectedSavegame) {
|
||
textMode |= TEXT_RED_FONT;
|
||
ycoord += 2;
|
||
if (_cursorVisible)
|
||
strcat((char*)str, "_");
|
||
}
|
||
renderText(str, _saveButtons[cnt].x + 6, ycoord, textMode);
|
||
}
|
||
}
|
||
|
||
void Control::saveNameSelect(uint8 id, bool saving) {
|
||
deselectSaveslots();
|
||
_buttons[id - BUTTON_SAVE_SELECT1]->setSelected(1);
|
||
uint8 num = (id - BUTTON_SAVE_SELECT1) + _saveScrollPos;
|
||
if (saving && (_selectedSavegame != 255)) // the player may have entered something, clear it again
|
||
strcpy((char*)_saveNames[_selectedSavegame], (char*)_oldName);
|
||
if (num < _saveFiles) {
|
||
_selectedSavegame = num;
|
||
strcpy((char*)_oldName, (char*)_saveNames[num]); // save for later
|
||
} else {
|
||
if (!saving)
|
||
_buttons[id - BUTTON_SAVE_SELECT1]->setSelected(0); // no save in slot, deselect it
|
||
else {
|
||
if (_saveFiles <= num)
|
||
_saveFiles = num + 1;
|
||
_selectedSavegame = num;
|
||
_oldName[0] = '\0';
|
||
}
|
||
}
|
||
if (_selectedSavegame < 255)
|
||
_cursorTick = 0;
|
||
showSavegameNames();
|
||
}
|
||
|
||
void Control::saveNameScroll(uint8 scroll, bool saving) {
|
||
uint16 maxScroll;
|
||
if (saving)
|
||
maxScroll = 64;
|
||
else
|
||
maxScroll = _saveFiles; // for loading, we can only scroll as far as there are savegames
|
||
if (scroll == BUTTON_SCROLL_UP_FAST) {
|
||
if (_saveScrollPos >= 8)
|
||
_saveScrollPos -= 8;
|
||
else
|
||
_saveScrollPos = 0;
|
||
} else if (scroll == BUTTON_SCROLL_UP_SLOW) {
|
||
if (_saveScrollPos >= 1)
|
||
_saveScrollPos--;
|
||
} else if (scroll == BUTTON_SCROLL_DOWN_SLOW) {
|
||
if (_saveScrollPos + 8 < maxScroll)
|
||
_saveScrollPos++;
|
||
} else if (scroll == BUTTON_SCROLL_DOWN_FAST) {
|
||
if (_saveScrollPos + 16 < maxScroll)
|
||
_saveScrollPos += 8;
|
||
else {
|
||
if (maxScroll >= 8)
|
||
_saveScrollPos = maxScroll - 8;
|
||
else
|
||
_saveScrollPos = 0;
|
||
}
|
||
}
|
||
_selectedSavegame = 255; // deselect savegame
|
||
deselectSaveslots();
|
||
showSavegameNames();
|
||
}
|
||
|
||
void Control::createButtons(const ButtonInfo *buttons, uint8 num) {
|
||
for (uint8 cnt = 0; cnt < num; cnt++) {
|
||
_buttons[cnt] = new ControlButton(buttons[cnt].x, buttons[cnt].y, buttons[cnt].resId, buttons[cnt].id, buttons[cnt].flag, _resMan, _screenBuf, _system);
|
||
_buttons[cnt]->draw();
|
||
}
|
||
_numButtons = num;
|
||
}
|
||
|
||
void Control::destroyButtons(void) {
|
||
for (uint8 cnt = 0; cnt < _numButtons; cnt++)
|
||
delete _buttons[cnt];
|
||
_numButtons = 0;
|
||
}
|
||
|
||
uint16 Control::getTextWidth(const uint8 *str) {
|
||
uint16 width = 0;
|
||
while (*str) {
|
||
width += FROM_LE_16(_resMan->fetchFrame(_font, *str - 32)->width) - 3;
|
||
str++;
|
||
}
|
||
return width;
|
||
}
|
||
|
||
void Control::renderText(const uint8 *str, uint16 x, uint16 y, uint8 mode) {
|
||
uint8 *font = _font;
|
||
if (mode & TEXT_RED_FONT) {
|
||
mode &= ~TEXT_RED_FONT;
|
||
font = _redFont;
|
||
}
|
||
|
||
if (mode == TEXT_RIGHT_ALIGN) // negative x coordinate means right-aligned.
|
||
x -= getTextWidth(str);
|
||
else if (mode == TEXT_CENTER)
|
||
x -= getTextWidth(str) / 2;
|
||
|
||
uint16 destX = x;
|
||
while (*str) {
|
||
uint8 *dst = _screenBuf + y * SCREEN_WIDTH + destX;
|
||
|
||
FrameHeader *chSpr = _resMan->fetchFrame(font, *str - 32);
|
||
uint8 *sprData = (uint8*)chSpr + sizeof(FrameHeader);
|
||
for (uint16 cnty = 0; cnty < FROM_LE_16(chSpr->height); cnty++) {
|
||
for (uint16 cntx = 0; cntx < FROM_LE_16(chSpr->width); cntx++) {
|
||
if (sprData[cntx])
|
||
dst[cntx] = sprData[cntx];
|
||
}
|
||
sprData += FROM_LE_16(chSpr->width);
|
||
dst += SCREEN_WIDTH;
|
||
}
|
||
destX += FROM_LE_16(chSpr->width) - 3;
|
||
str++;
|
||
}
|
||
_system->copyRectToScreen(_screenBuf + y * SCREEN_WIDTH + x, SCREEN_WIDTH, x, y, (destX - x) + 3, 28);
|
||
}
|
||
|
||
void Control::renderVolumeBar(uint8 id, uint8 volL, uint8 volR) {
|
||
uint16 destX = _volumeButtons[id].x + 20;
|
||
uint16 destY = _volumeButtons[id].y + 116;
|
||
|
||
for (uint8 chCnt = 0; chCnt < 2; chCnt++) {
|
||
uint8 vol = (chCnt == 0) ? volL : volR;
|
||
FrameHeader *frHead = _resMan->fetchFrame(_resMan->openFetchRes(SR_VLIGHT), (vol + 15) >> 4);
|
||
uint8 *destMem = _screenBuf + destY * SCREEN_WIDTH + destX;
|
||
uint8 *srcMem = (uint8*)frHead + sizeof(FrameHeader);
|
||
for (uint16 cnty = 0; cnty < FROM_LE_16(frHead->height); cnty++) {
|
||
memcpy(destMem, srcMem, FROM_LE_16(frHead->width));
|
||
srcMem += FROM_LE_16(frHead->width);
|
||
destMem += SCREEN_WIDTH;
|
||
}
|
||
_system->copyRectToScreen(_screenBuf + destY * SCREEN_WIDTH + destX, SCREEN_WIDTH, destX, destY, FROM_LE_16(frHead->width), FROM_LE_16(frHead->height));
|
||
_resMan->resClose(SR_VLIGHT);
|
||
destX += 32;
|
||
}
|
||
}
|
||
|
||
void Control::saveGameToFile(uint8 slot) {
|
||
char fName[15];
|
||
uint16 cnt;
|
||
sprintf(fName, "SAVEGAME.%03d", slot);
|
||
uint16 liveBuf[TOTAL_SECTIONS];
|
||
Common::OutSaveFile *outf;
|
||
outf = _saveFileMan->openForSaving(fName);
|
||
if (!outf) {
|
||
// Display an error message and do nothing
|
||
displayMessage(0, "Unable to create file '%s' in directory '%s'", fName, _saveFileMan->getSavePath());
|
||
return;
|
||
}
|
||
|
||
_objMan->saveLiveList(liveBuf);
|
||
for (cnt = 0; cnt < TOTAL_SECTIONS; cnt++)
|
||
outf->writeUint16LE(liveBuf[cnt]);
|
||
|
||
Object *cpt = _objMan->fetchObject(PLAYER);
|
||
Logic::_scriptVars[CHANGE_DIR] = cpt->o_dir;
|
||
Logic::_scriptVars[CHANGE_X] = cpt->o_xcoord;
|
||
Logic::_scriptVars[CHANGE_Y] = cpt->o_ycoord;
|
||
Logic::_scriptVars[CHANGE_STANCE] = STAND;
|
||
Logic::_scriptVars[CHANGE_PLACE] = cpt->o_place;
|
||
|
||
for (cnt = 0; cnt < NUM_SCRIPT_VARS; cnt++)
|
||
outf->writeUint32LE(Logic::_scriptVars[cnt]);
|
||
|
||
uint32 playerSize = (sizeof(Object) - 12000) / 4;
|
||
uint32 *playerRaw = (uint32*)cpt;
|
||
for (uint32 cnt2 = 0; cnt2 < playerSize; cnt2++)
|
||
outf->writeUint32LE(playerRaw[cnt2]);
|
||
outf->flush();
|
||
if (outf->ioFailed())
|
||
displayMessage(0, "Couldn't write to file '%s' in directory '%s'. Device full?", fName, _saveFileMan->getSavePath());
|
||
delete outf;
|
||
}
|
||
|
||
bool Control::restoreGameFromFile(uint8 slot) {
|
||
char fName[15];
|
||
uint16 cnt;
|
||
sprintf(fName, "SAVEGAME.%03d", slot);
|
||
Common::InSaveFile *inf;
|
||
inf = _saveFileMan->openForLoading(fName);
|
||
if (!inf) {
|
||
// Display an error message, and do nothing
|
||
displayMessage(0, "Can't open file '%s' in directory '%s'", fName, _saveFileMan->getSavePath());
|
||
return false;
|
||
}
|
||
|
||
_restoreBuf = (uint8*)malloc(
|
||
TOTAL_SECTIONS * 2 +
|
||
NUM_SCRIPT_VARS * 4 +
|
||
(sizeof(Object) - 12000));
|
||
|
||
uint16 *liveBuf = (uint16*)_restoreBuf;
|
||
uint32 *scriptBuf = (uint32*)(_restoreBuf + 2 * TOTAL_SECTIONS);
|
||
uint32 *playerBuf = (uint32*)(_restoreBuf + 2 * TOTAL_SECTIONS + 4 * NUM_SCRIPT_VARS);
|
||
|
||
for (cnt = 0; cnt < TOTAL_SECTIONS; cnt++)
|
||
liveBuf[cnt] = inf->readUint16LE();
|
||
|
||
for (cnt = 0; cnt < NUM_SCRIPT_VARS; cnt++)
|
||
scriptBuf[cnt] = inf->readUint32LE();
|
||
|
||
uint32 playerSize = (sizeof(Object) - 12000) / 4;
|
||
for (uint32 cnt2 = 0; cnt2 < playerSize; cnt2++)
|
||
playerBuf[cnt2] = inf->readUint32LE();
|
||
|
||
if (inf->ioFailed()) {
|
||
displayMessage(0, "Can't read from file '%s' in directory '%s'", fName, _saveFileMan->getSavePath());
|
||
delete inf;
|
||
free(_restoreBuf);
|
||
_restoreBuf = NULL;
|
||
return false;
|
||
}
|
||
delete inf;
|
||
return true;
|
||
}
|
||
|
||
void Control::doRestore(void) {
|
||
uint8 *bufPos = _restoreBuf;
|
||
_objMan->loadLiveList((uint16*)bufPos);
|
||
bufPos += TOTAL_SECTIONS * 2;
|
||
for (uint16 cnt = 0; cnt < NUM_SCRIPT_VARS; cnt++) {
|
||
Logic::_scriptVars[cnt] = *(uint32*)bufPos;
|
||
bufPos += 4;
|
||
}
|
||
uint32 playerSize = (sizeof(Object) - 12000) / 4;
|
||
uint32 *playerRaw = (uint32*)_objMan->fetchObject(PLAYER);
|
||
Object *cpt = _objMan->fetchObject(PLAYER);
|
||
for (uint32 cnt2 = 0; cnt2 < playerSize; cnt2++) {
|
||
*playerRaw = *(uint32*)bufPos;
|
||
playerRaw++;
|
||
bufPos += 4;
|
||
}
|
||
free(_restoreBuf);
|
||
Logic::_scriptVars[CHANGE_DIR] = cpt->o_dir;
|
||
Logic::_scriptVars[CHANGE_X] = cpt->o_xcoord;
|
||
Logic::_scriptVars[CHANGE_Y] = cpt->o_ycoord;
|
||
Logic::_scriptVars[CHANGE_STANCE] = STAND;
|
||
Logic::_scriptVars[CHANGE_PLACE] = cpt->o_place;
|
||
SwordEngine::_systemVars.justRestoredGame = 1;
|
||
if (SwordEngine::_systemVars.isDemo)
|
||
Logic::_scriptVars[PLAYINGDEMO] = 1;
|
||
}
|
||
|
||
void Control::delay(uint32 msecs) {
|
||
OSystem::Event event;
|
||
|
||
uint32 now = _system->getMillis();
|
||
uint32 endTime = now + msecs;
|
||
_keyPressed = 0; //reset
|
||
_mouseState = 0;
|
||
|
||
do {
|
||
while (_system->pollEvent(event)) {
|
||
switch (event.type) {
|
||
case OSystem::EVENT_KEYDOWN:
|
||
|
||
// Make sure backspace works right (this fixes a small issue on OS X)
|
||
if (event.kbd.keycode == 8)
|
||
_keyPressed = 8;
|
||
else
|
||
_keyPressed = (byte)event.kbd.ascii;
|
||
_keyRepeatTime = now + kKeyRepeatInitialDelay;
|
||
_keyRepeat = _keyPressed;
|
||
// we skip the rest of the delay and return immediately
|
||
// to handle keyboard input
|
||
return;
|
||
case OSystem::EVENT_KEYUP:
|
||
_keyRepeatTime = 0;
|
||
_keyRepeat = 0;
|
||
break;
|
||
case OSystem::EVENT_MOUSEMOVE:
|
||
_mouseX = event.mouse.x;
|
||
_mouseY = event.mouse.y;
|
||
break;
|
||
case OSystem::EVENT_LBUTTONDOWN:
|
||
_mouseDown = true;
|
||
_mouseState |= BS1L_BUTTON_DOWN;
|
||
#if defined(_WIN32_WCE) || defined(PALMOS_MODE)
|
||
_mouseX = event.mouse.x;
|
||
_mouseY = event.mouse.y;
|
||
#endif
|
||
break;
|
||
case OSystem::EVENT_LBUTTONUP:
|
||
_mouseDown = false;
|
||
_mouseState |= BS1L_BUTTON_UP;
|
||
break;
|
||
case OSystem::EVENT_WHEELUP:
|
||
_mouseDown = false;
|
||
_mouseState |= BS1_WHEEL_UP;
|
||
break;
|
||
case OSystem::EVENT_WHEELDOWN:
|
||
_mouseDown = false;
|
||
_mouseState |= BS1_WHEEL_DOWN;
|
||
break;
|
||
case OSystem::EVENT_QUIT:
|
||
SwordEngine::_systemVars.engineQuit = true;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
if (_keyRepeatTime && now > _keyRepeatTime) {
|
||
_keyRepeatTime += kKeyRepeatSustainDelay;
|
||
_keyPressed = _keyRepeat;
|
||
}
|
||
|
||
_system->delayMillis(10);
|
||
} while (_system->getMillis() < endTime);
|
||
}
|
||
|
||
const ButtonInfo Control::_deathButtons[3] = {
|
||
{250, 224 + 40, SR_BUTTON, BUTTON_RESTORE_PANEL, 0 },
|
||
{250, 260 + 40, SR_BUTTON, BUTTON_RESTART, kButtonOk },
|
||
{250, 296 + 40, SR_BUTTON, BUTTON_QUIT, kButtonCancel }
|
||
};
|
||
|
||
const ButtonInfo Control::_panelButtons[7] = {
|
||
{145, 188 + 40, SR_BUTTON, BUTTON_SAVE_PANEL, 0 },
|
||
{145, 224 + 40, SR_BUTTON, BUTTON_RESTORE_PANEL, 0 },
|
||
{145, 260 + 40, SR_BUTTON, BUTTON_RESTART, 0 },
|
||
{145, 296 + 40, SR_BUTTON, BUTTON_QUIT, kButtonCancel },
|
||
{475, 188 + 40, SR_BUTTON, BUTTON_VOLUME_PANEL, 0 },
|
||
{475, 224 + 40, SR_TEXT_BUTTON, BUTTON_TEXT, 0 },
|
||
{475, 332 + 40, SR_BUTTON, BUTTON_DONE, kButtonOk }
|
||
};
|
||
|
||
const ButtonInfo Control::_saveButtons[16] = {
|
||
{114, 32 + 40, SR_SLAB1, BUTTON_SAVE_SELECT1, 0 },
|
||
{114, 68 + 40, SR_SLAB2, BUTTON_SAVE_SELECT2, 0 },
|
||
{114, 104 + 40, SR_SLAB3, BUTTON_SAVE_SELECT3, 0 },
|
||
{114, 140 + 40, SR_SLAB4, BUTTON_SAVE_SELECT4, 0 },
|
||
{114, 176 + 40, SR_SLAB1, BUTTON_SAVE_SELECT5, 0 },
|
||
{114, 212 + 40, SR_SLAB2, BUTTON_SAVE_SELECT6, 0 },
|
||
{114, 248 + 40, SR_SLAB3, BUTTON_SAVE_SELECT7, 0 },
|
||
{114, 284 + 40, SR_SLAB4, BUTTON_SAVE_SELECT8, 0 },
|
||
|
||
{516, 25 + 40, SR_BUTUF, BUTTON_SCROLL_UP_FAST, 0 },
|
||
{516, 45 + 40, SR_BUTUS, BUTTON_SCROLL_UP_SLOW, 0 },
|
||
{516, 289 + 40, SR_BUTDS, BUTTON_SCROLL_DOWN_SLOW, 0 },
|
||
{516, 310 + 40, SR_BUTDF, BUTTON_SCROLL_DOWN_FAST, 0 },
|
||
|
||
{125, 338 + 40, SR_BUTTON, BUTTON_SAVE_RESTORE_OKAY, kButtonOk},
|
||
{462, 338 + 40, SR_BUTTON, BUTTON_SAVE_CANCEL, kButtonCancel }
|
||
};
|
||
|
||
const ButtonInfo Control::_volumeButtons[4] = {
|
||
{ 478, 338 + 40, SR_BUTTON, BUTTON_MAIN_PANEL, kButtonOk },
|
||
{ 138, 135, SR_VKNOB, 0, 0 },
|
||
{ 273, 135, SR_VKNOB, 0, 0 },
|
||
{ 404, 135, SR_VKNOB, 0, 0 },
|
||
};
|
||
|
||
const uint8 Control::_languageStrings[8 * 20][43] = {
|
||
// BS1_ENGLISH:
|
||
"PAUSED",
|
||
"PLEASE INSERT CD-",
|
||
"THEN PRESS A KEY",
|
||
"INCORRECT CD",
|
||
"Save",
|
||
"Restore",
|
||
"Restart",
|
||
"Start",
|
||
"Quit",
|
||
"Speed",
|
||
"Volume",
|
||
"Text",
|
||
"Done",
|
||
"OK",
|
||
"Cancel",
|
||
"Music",
|
||
"Speech",
|
||
"Fx",
|
||
"The End",
|
||
"DRIVE FULL!",
|
||
// BS1_FRENCH:
|
||
"PAUSE",
|
||
"INS\xC9REZ LE CD-",
|
||
"ET APPUYES SUR UNE TOUCHE",
|
||
"CD INCORRECT",
|
||
"Sauvegarder",
|
||
"Recharger",
|
||
"Recommencer",
|
||
"Commencer",
|
||
"Quitter",
|
||
"Vitesse",
|
||
"Volume",
|
||
"Texte",
|
||
"Termin\xE9",
|
||
"OK",
|
||
"Annuler",
|
||
"Musique",
|
||
"Voix",
|
||
"Fx",
|
||
"Fin",
|
||
"DISQUE PLEIN!",
|
||
//BS1_GERMAN:
|
||
"PAUSE",
|
||
"BITTE LEGEN SIE CD-",
|
||
"EIN UND DR\xDC CKEN SIE EINE BELIEBIGE TASTE",
|
||
"FALSCHE CD",
|
||
"Speichern",
|
||
"Laden",
|
||
"Neues Spiel",
|
||
"Start",
|
||
"Beenden",
|
||
"Geschwindigkeit",
|
||
"Lautst\xE4rke",
|
||
"Text",
|
||
"Fertig",
|
||
"OK",
|
||
"Abbrechen",
|
||
"Musik",
|
||
"Sprache",
|
||
"Fx",
|
||
"Ende",
|
||
"DRIVE FULL!",
|
||
//BS1_ITALIAN:
|
||
"PAUSA",
|
||
"INSERITE IL CD-",
|
||
"E PREMETE UN TASTO",
|
||
"CD ERRATO",
|
||
"Salva",
|
||
"Ripristina",
|
||
"Ricomincia",
|
||
"Inizio",
|
||
"Esci",
|
||
"Velocit\xE0",
|
||
"Volume",
|
||
"Testo",
|
||
"Fatto",
|
||
"OK",
|
||
"Annula",
|
||
"Musica",
|
||
"Parlato",
|
||
"Fx",
|
||
"Fine",
|
||
"DISCO PIENO!",
|
||
//BS1_SPANISH:
|
||
"PAUSA",
|
||
"POR FAVOR INTRODUCE EL CD-",
|
||
"Y PULSA UNA TECLA",
|
||
"CD INCORRECTO",
|
||
"Guardar",
|
||
"Recuperar",
|
||
"Reiniciar",
|
||
"Empezar",
|
||
"Abandonar",
|
||
"Velocidad",
|
||
"Volumen",
|
||
"Texto",
|
||
"Hecho",
|
||
"OK",
|
||
"Cancelar",
|
||
"M\xFAsica",
|
||
"Di\xE1logo",
|
||
"Fx",
|
||
"Fin",
|
||
"DISCO LLENO",
|
||
// BS1_CZECH:
|
||
"\xAC\x41S SE ZASTAVIL",
|
||
"VLO\xA6TE DO MECHANIKY CD DISK",
|
||
"PAK STISKN\xB7TE LIBOVOLNOU KL\xB5VESU",
|
||
"TO NEBUDE TO SPR\xB5VN\x90 CD",
|
||
"Ulo\xA7it pozici",
|
||
"Nahr\xA0t pozici",
|
||
"Za\x9F\xA1t znovu",
|
||
"Start",
|
||
"Ukon\x9Fit hru",
|
||
"Rychlost",
|
||
"Hlasitost",
|
||
"Titulky",
|
||
"Souhlas\xA1m",
|
||
"Ano",
|
||
"Ne",
|
||
"Hudba",
|
||
"Mluven, slovo",
|
||
"Zvuky",
|
||
"Konec",
|
||
"Disk pln\xEC",
|
||
//BS1_PORTUGESE:
|
||
"PAUSA",
|
||
"FAVOR INSERIR CD",
|
||
"E DIGITAR UMA TECLA",
|
||
"CD INCORRETO",
|
||
"Salvar",
|
||
"Restaurar",
|
||
"Reiniciar",
|
||
"Iniciar",
|
||
"Sair",
|
||
"Velocidade",
|
||
"Volume",
|
||
"Texto",
|
||
"Feito",
|
||
"OK",
|
||
"Cancelar",
|
||
"M\xFAsica",
|
||
"Voz",
|
||
"Efeitos",
|
||
"Fim",
|
||
"UNIDADE CHEIA!",
|
||
};
|
||
|
||
} // End of namespace Sword1
|