aboutsummaryrefslogtreecommitdiff
path: root/sword1
diff options
context:
space:
mode:
authorRobert Göffringmann2003-12-20 09:18:43 +0000
committerRobert Göffringmann2003-12-20 09:18:43 +0000
commitda3eed35b5817303170e42c21132b29f20183d71 (patch)
tree0f63de7ec5119465c856dfd9751bba5d8508048c /sword1
parent59654b17191b99c23486f6a41076b9ed05a1c38f (diff)
downloadscummvm-rg350-da3eed35b5817303170e42c21132b29f20183d71.tar.gz
scummvm-rg350-da3eed35b5817303170e42c21132b29f20183d71.tar.bz2
scummvm-rg350-da3eed35b5817303170e42c21132b29f20183d71.zip
forgot these. :)
svn-id: r11776
Diffstat (limited to 'sword1')
-rw-r--r--sword1/control.cpp840
-rw-r--r--sword1/control.h125
2 files changed, 965 insertions, 0 deletions
diff --git a/sword1/control.cpp b/sword1/control.cpp
new file mode 100644
index 0000000000..8617c70f8e
--- /dev/null
+++ b/sword1/control.cpp
@@ -0,0 +1,840 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include "stdafx.h"
+#include "control.h"
+#include "common/util.h"
+#include "common/file.h"
+#include "logic.h"
+#include "sworddefs.h"
+#include "swordres.h"
+#include "resman.h"
+#include "objectman.h"
+#include "sword1.h"
+#include "common/util.h"
+#include "mouse.h"
+
+#define SAVEFILE_WRITE true
+#define SAVEFILE_READ false
+
+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,
+ BUTTON_TEXT,
+//-
+ 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,
+};
+
+ControlButton::ControlButton(uint16 x, uint16 y, uint32 resId, uint8 id, ResMan *pResMan, uint8 *screenBuf, OSystem *system) {
+ _x = x;
+ _y = y;
+ _id = id;
+ _resId = resId;
+ _resMan = pResMan;
+ _dstBuf = screenBuf + y * SCREEN_WIDTH + x;
+ _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);
+ _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->copy_rect(_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();
+}
+
+SwordControl::SwordControl(ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, SwordMouse *pMouse, const char *savePath) {
+ _resMan = pResMan;
+ _objMan = pObjMan;
+ _system = system;
+ _mouse = pMouse;
+ strcpy(_savePath, savePath);
+}
+
+uint8 SwordControl::runPanel(void) {
+ _restoreBuf = NULL;
+ _lStrings = _languageStrings + MIN(SwordEngine::_systemVars.language, (uint8)BS1_SPANISH) * 20;
+ _keyPressed = _numButtons = 0;
+ _screenBuf = (uint8*)malloc(640 * 480);
+ _font = (uint8*)_resMan->openFetchRes(GAME_FONT); // todo: czech support
+ _resMan->resOpen(SR_BUTTON);
+ 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->set_palette(palOut, 0, 256);
+ free(palOut);
+ uint8 mode = 0, newMode = BUTTON_MAIN_PANEL;
+ bool fullRefresh = false;
+ _mouse->controlPanel(true);
+ uint8 retVal = CONTROL_NOTHING_DONE;
+
+ do {
+ if (newMode) {
+ mode = newMode;
+ fullRefresh = true;
+ destroyButtons();
+ memset(_screenBuf, 0, 640 * 480);
+ }
+ switch (mode) {
+ case BUTTON_MAIN_PANEL:
+ if (fullRefresh)
+ setupMainPanel();
+ break;
+ case BUTTON_SAVE_PANEL:
+ if (fullRefresh)
+ setupSaveRestorePanel(true);
+ if (_keyPressed)
+ handleSaveKey(_keyPressed);
+ break;
+ case BUTTON_RESTORE_PANEL:
+ if (fullRefresh)
+ setupSaveRestorePanel(false);
+ break;
+
+ }
+ if (fullRefresh) {
+ fullRefresh = false;
+ _system->copy_rect(_screenBuf, SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, 480);
+ }
+ _system->update_screen();
+ delay(1000 / 12);
+ newMode = getClicks(mode, &retVal);
+ } while ((newMode != 1) && (retVal == 0));
+ _resMan->resClose(SR_BUTTON);
+ memset(_screenBuf, 0, 640 * 480);
+ _system->copy_rect(_screenBuf, 640, 0, 0, 640, 480);
+ free(_screenBuf);
+ _mouse->controlPanel(false);
+ return retVal;
+}
+
+uint8 SwordControl::getClicks(uint8 mode, uint8 *retVal) {
+ if (!_mouseState)
+ return 0;
+ if (_mouseState & BS1L_BUTTON_DOWN)
+ for (uint8 cnt = 0; cnt < _numButtons; cnt++)
+ if (_buttons[cnt]->wasClicked(_mouseX, _mouseY)) {
+ _selectedButton = cnt;
+ _buttons[cnt]->setSelected(1);
+ }
+ if (_mouseState & BS1L_BUTTON_UP) {
+ for (uint8 cnt = 0; cnt < _numButtons; 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 < _numButtons)
+ _buttons[_selectedButton]->setSelected(0);
+ _selectedButton = 255;
+ }
+ return 0;
+}
+
+uint8 SwordControl::handleButtonClick(uint8 id, uint8 mode, uint8 *retVal) {
+ switch(mode) {
+ case BUTTON_MAIN_PANEL:
+ if (id == BUTTON_RESTART)
+ *retVal |= CONTROL_RESTART_GAME;
+ else if ((id == BUTTON_RESTORE_PANEL) || (id == BUTTON_SAVE_PANEL) ||
+ (id == BUTTON_DONE))
+ return id;
+ else
+ return 0;
+ 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) {
+ if (saveToFile()) // don't go back to main panel if save fails.
+ return BUTTON_MAIN_PANEL;
+ } 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)
+ return BUTTON_MAIN_PANEL; // mode down to main panel
+ }
+ return 0;
+}
+
+void SwordControl::deselectSaveslots(void) {
+ for (uint8 cnt = 0; cnt < 8; cnt++)
+ _buttons[cnt]->setSelected(0);
+}
+
+void SwordControl::setupMainPanel(void) {
+ uint32 panelId;
+ uint8 langCode = MIN(SwordEngine::_systemVars.language, (uint8)BS1_SPANISH);
+
+ if (SwordEngine::_systemVars.deathScreenFlag == 1)
+ panelId = SR_DEATHPANEL;
+ else
+ panelId = SR_PANEL_ENGLISH + langCode;
+
+ FrameHeader *frameHead = _resMan->fetchFrame(_resMan->openFetchRes(panelId), 0);
+ uint16 panelX = (640 - FROM_LE_16(frameHead->width)) / 2;
+ uint16 panelY = (400 - FROM_LE_16(frameHead->height)) / 2;
+
+ ControlButton *panel = new ControlButton(panelX, panelY, panelId, 0, _resMan, _screenBuf, _system);
+ panel->draw();
+ delete panel;
+ _resMan->resClose(panelId);
+
+ if (SwordEngine::_systemVars.deathScreenFlag)
+ createButtons(_deathButtons, 3);
+ else
+ createButtons(_panelButtons, 8);
+
+ if (SwordEngine::_systemVars.deathScreenFlag == 2) // end of game
+ renderText(_lStrings[STR_THE_END], -480, 188);
+
+ if (SwordEngine::_systemVars.deathScreenFlag == 0) { // normal panel
+ renderText(_lStrings[STR_SAVE], 180, 188);
+ renderText(_lStrings[STR_DONE], -460, 332);
+ renderText(_lStrings[STR_RESTORE], 180, 224);
+ renderText(_lStrings[STR_RESTART], 180, 260);
+ renderText(_lStrings[STR_QUIT], 180, 296);
+
+ renderText(_lStrings[STR_SPEED], -460, 188);
+ renderText(_lStrings[STR_VOLUME], -460, 224);
+ renderText(_lStrings[STR_TEXT], -460, 260);
+ } else {
+ renderText(_lStrings[STR_RESTORE], 285, 224);
+ if (SwordEngine::_systemVars.deathScreenFlag == 3) // just started game
+ renderText(_lStrings[STR_START], 285, 260);
+ else
+ renderText(_lStrings[STR_RESTART], 285, 260);
+ renderText(_lStrings[STR_QUIT], 285, 296);
+ }
+}
+
+void SwordControl::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, _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);
+ if (saving) {
+ renderText(_lStrings[STR_SAVE], _saveButtons[12].x + 30, _saveButtons[13].y);
+ } else {
+ renderText(_lStrings[STR_RESTORE], _saveButtons[12].x + 30, _saveButtons[13].y);
+ }
+ readSavegameDescriptions();
+ _selectedSavegame = 255;
+ showSavegameNames();
+}
+
+bool SwordControl::keyAccepted(uint8 key) {
+ // this routine needs changes for Czech keys... No idea how to do that, though.
+ static const char allowedSpecials[] = "éèáàúùäöüÄÖÜß,.:-()?! \"\'";
+ if (((key >= 'A') && (key <= 'Z')) ||
+ ((key >= 'a') && (key <= 'z')) ||
+ ((key >= '0') && (key <= '9')) ||
+ strchr(allowedSpecials, key))
+ return true;
+ else
+ return false;
+}
+
+void SwordControl::handleSaveKey(uint8 key) {
+ if (_selectedSavegame < 255) {
+ uint8 len = strlen(_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 SwordControl::saveToFile(void) {
+ if ((_selectedSavegame == 255) || !strlen(_saveNames[_selectedSavegame]))
+ return false; // no saveslot selected or no name entered
+ saveGameToFile(_selectedSavegame);
+ writeSavegameDescriptions();
+ return true;
+}
+
+bool SwordControl::restoreFromFile(void) {
+ if (_selectedSavegame < 255) {
+ restoreGameFromFile(_selectedSavegame);
+ return true;
+ } else
+ return false;
+}
+
+void SwordControl::readSavegameDescriptions(void) {
+ SaveFileManager *mgr = _system->get_savefile_manager();
+ SaveFile *inf;
+ inf = mgr->open_savefile("SAVEGAME.INF", _savePath, SAVEFILE_READ);
+ _saveScrollPos = _saveFiles = 0;
+ _selectedSavegame = 255;
+ if (inf && inf->isOpen()) {
+ 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;
+ delete mgr;
+}
+
+void SwordControl::writeSavegameDescriptions(void) {
+ SaveFileManager *mgr = _system->get_savefile_manager();
+ SaveFile *outf;
+ outf = mgr->open_savefile("SAVEGAME.INF", _savePath, SAVEFILE_WRITE);
+ // 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(_saveNames[_saveFiles] - 1) == 0)
+ _saveFiles--;
+ for (uint8 cnt = 0; cnt < _saveFiles; cnt++) {
+ outf->write(_saveNames[cnt], strlen(_saveNames[cnt]));
+ if (cnt < _saveFiles - 1)
+ outf->writeByte(10);
+ else
+ outf->writeByte(255);
+ }
+ delete outf;
+ delete mgr;
+}
+
+void SwordControl::showSavegameNames(void) {
+ for (uint8 cnt = 0; cnt < 8; cnt++) {
+ _buttons[cnt]->draw();
+ renderText(_saveNames[cnt + _saveScrollPos], _saveButtons[cnt].x + 6, _saveButtons[cnt].y + 2);
+ }
+}
+
+void SwordControl::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(_saveNames[_selectedSavegame], _oldName);
+ if (num < _saveFiles) {
+ _selectedSavegame = num;
+ strcpy(_oldName, _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';
+ }
+ }
+ showSavegameNames();
+}
+
+void SwordControl::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 < maxScroll - 8)
+ _saveScrollPos++;
+ } else if (scroll == BUTTON_SCROLL_DOWN_FAST) {
+ if (_saveScrollPos < maxScroll - 16)
+ _saveScrollPos += 8;
+ else
+ _saveScrollPos = maxScroll - 8;
+ }
+ _selectedSavegame = 255; // deselect savegame
+ deselectSaveslots();
+ showSavegameNames();
+}
+
+void SwordControl::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, _resMan, _screenBuf, _system);
+ _buttons[cnt]->draw();
+ }
+ _numButtons = num;
+}
+
+void SwordControl::destroyButtons(void) {
+ for (uint8 cnt = 0; cnt < _numButtons; cnt++)
+ delete _buttons[cnt];
+ _numButtons = 0;
+}
+
+uint16 SwordControl::getTextWidth(const char *str) {
+ uint16 width = 0;
+ while (*str) {
+ width += FROM_LE_16(_resMan->fetchFrame(_font, *str - 32)->width) - 3;
+ str++;
+ }
+ return width;
+}
+
+void SwordControl::renderText(const char *str, int16 x, uint16 y) {
+ if (x < 0) // negative x coordinate means rightbound.
+ x = (-x) - getTextWidth(str);
+
+ 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->copy_rect(_screenBuf + y * SCREEN_WIDTH + x, SCREEN_WIDTH, x, y, (destX - x) + 3, 28);
+}
+
+// I can hardly believe this is all it takes for loading and saving...
+void SwordControl::saveGameToFile(uint8 slot) {
+ char fName[15];
+ sprintf(fName, "SAVEGAME.%03d", slot);
+ uint16 liveBuf[TOTAL_SECTIONS];
+ SaveFileManager *mgr = _system->get_savefile_manager();
+ SaveFile *outf;
+ outf = mgr->open_savefile(fName, _savePath, SAVEFILE_WRITE);
+ if (!outf->isOpen())
+ error("unable to create file %s", fName);
+
+ _objMan->saveLiveList(liveBuf);
+ for (uint16 cnt = 0; cnt < TOTAL_SECTIONS; cnt++)
+ outf->writeUint16LE(liveBuf[cnt]);
+
+ BsObject *cpt = _objMan->fetchObject(PLAYER);
+ SwordLogic::_scriptVars[CHANGE_DIR] = cpt->o_dir;
+ SwordLogic::_scriptVars[CHANGE_X] = cpt->o_xcoord;
+ SwordLogic::_scriptVars[CHANGE_Y] = cpt->o_ycoord;
+ SwordLogic::_scriptVars[CHANGE_STANCE] = STAND;
+ SwordLogic::_scriptVars[CHANGE_PLACE] = cpt->o_place;
+
+ for (uint16 cnt = 0; cnt < NUM_SCRIPT_VARS; cnt++)
+ outf->writeUint32LE(SwordLogic::_scriptVars[cnt]);
+
+ uint32 playerSize = (sizeof(BsObject) - 12000) / 4;
+ uint32 *playerRaw = (uint32*)cpt;
+ for (uint32 cnt = 0; cnt < playerSize; cnt++)
+ outf->writeUint32LE(playerRaw[cnt]);
+ delete outf;
+ delete mgr;
+}
+
+void SwordControl::restoreGameFromFile(uint8 slot) {
+ char fName[15];
+ sprintf(fName, "SAVEGAME.%03d", slot);
+ SaveFileManager *mgr = _system->get_savefile_manager();
+ SaveFile *inf;
+ inf = mgr->open_savefile(fName, _savePath, SAVEFILE_READ);
+ if ((!inf) || (!inf->isOpen()))
+ error("Unable to open file %s", fName);
+
+ _restoreBuf = (uint8*)malloc(
+ TOTAL_SECTIONS * 2 +
+ NUM_SCRIPT_VARS * 4 +
+ (sizeof(BsObject) - 12000));
+
+ uint16 *liveBuf = (uint16*)_restoreBuf;
+ uint32 *scriptBuf = (uint32*)(_restoreBuf + 2 * TOTAL_SECTIONS);
+ uint32 *playerBuf = (uint32*)(_restoreBuf + 2 * TOTAL_SECTIONS + 4 * NUM_SCRIPT_VARS);
+
+ for (uint16 cnt = 0; cnt < TOTAL_SECTIONS; cnt++)
+ liveBuf[cnt] = inf->readUint16LE();
+
+ for (uint16 cnt = 0; cnt < NUM_SCRIPT_VARS; cnt++)
+ scriptBuf[cnt] = inf->readUint32LE();
+
+ uint32 playerSize = (sizeof(BsObject) - 12000) / 4;
+ for (uint32 cnt = 0; cnt < playerSize; cnt++)
+ playerBuf[cnt] = inf->readUint32LE();
+
+ delete inf;
+ delete mgr;
+}
+
+void SwordControl::doRestore(void) {
+ uint8 *bufPos = _restoreBuf;
+ _objMan->loadLiveList((uint16*)bufPos);
+ bufPos += TOTAL_SECTIONS * 2;
+ for (uint16 cnt = 0; cnt < NUM_SCRIPT_VARS; cnt++) {
+ SwordLogic::_scriptVars[cnt] = *(uint32*)bufPos;
+ bufPos += 4;
+ }
+ uint32 playerSize = (sizeof(BsObject) - 12000) / 4;
+ uint32 *playerRaw = (uint32*)_objMan->fetchObject(PLAYER);
+ for (uint32 cnt = 0; cnt < playerSize; cnt++) {
+ *playerRaw = *(uint32*)bufPos;
+ playerRaw++;
+ bufPos += 4;
+ }
+ free(_restoreBuf);
+}
+
+void SwordControl::delay(uint32 msecs) {
+ OSystem::Event event;
+
+ uint32 endTime = _system->get_msecs() + msecs;
+ _keyPressed = 0; //reset
+ _mouseState = 0;
+
+ do {
+ while (_system->poll_event(&event)) {
+ switch (event.event_code) {
+ 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;
+ break;
+ case OSystem::EVENT_MOUSEMOVE:
+ _mouseX = event.mouse.x;
+ _mouseY = event.mouse.y;
+ break;
+ case OSystem::EVENT_LBUTTONDOWN:
+ _mouseState |= BS1L_BUTTON_DOWN;
+#ifdef _WIN32_WCE
+ _mouseX = event.mouse.x;
+ _mouseY = event.mouse.y;
+#endif
+ break;
+ case OSystem::EVENT_LBUTTONUP:
+ _mouseState |= BS1L_BUTTON_UP;
+ break;
+ case OSystem::EVENT_QUIT:
+ _system->quit();
+ break;
+ default:
+ break;
+ }
+ }
+ _system->delay_msecs(10);
+ } while (_system->get_msecs() < endTime);
+}
+
+const ButtonInfo SwordControl::_deathButtons[3] = {
+ {250, 224, SR_BUTTON, BUTTON_RESTORE_PANEL },
+ {250, 260, SR_BUTTON, BUTTON_RESTART },
+ {250, 296, SR_BUTTON, BUTTON_QUIT }
+};
+
+const ButtonInfo SwordControl::_panelButtons[8] = {
+ {145, 188, SR_BUTTON, BUTTON_SAVE_PANEL },
+ {145, 224, SR_BUTTON, BUTTON_RESTORE_PANEL },
+ {145, 260, SR_BUTTON, BUTTON_RESTART },
+ {145, 296, SR_BUTTON, BUTTON_QUIT },
+ {475, 188, SR_BUTTON, BUTTON_SPEED },
+ {475, 224, SR_BUTTON, BUTTON_VOLUME },
+ {475, 260, SR_BUTTON, BUTTON_TEXT },
+ {475, 332, SR_BUTTON, BUTTON_DONE }
+};
+
+const ButtonInfo SwordControl::_saveButtons[16] = {
+ {114, 32 + 40, SR_SLAB1, BUTTON_SAVE_SELECT1 },
+ {114, 68 + 40, SR_SLAB2, BUTTON_SAVE_SELECT2 },
+ {114, 104 + 40, SR_SLAB3, BUTTON_SAVE_SELECT3 },
+ {114, 140 + 40, SR_SLAB4, BUTTON_SAVE_SELECT4 },
+ {114, 176 + 40, SR_SLAB1, BUTTON_SAVE_SELECT5 },
+ {114, 212 + 40, SR_SLAB2, BUTTON_SAVE_SELECT6 },
+ {114, 248 + 40, SR_SLAB3, BUTTON_SAVE_SELECT7 },
+ {114, 284 + 40, SR_SLAB4, BUTTON_SAVE_SELECT8 },
+
+ {516, 25 + 40, SR_BUTUF, BUTTON_SCROLL_UP_FAST },
+ {516, 45 + 40, SR_BUTUS, BUTTON_SCROLL_UP_SLOW },
+ {516, 289 + 40, SR_BUTDS, BUTTON_SCROLL_DOWN_SLOW },
+ {516, 310 + 40, SR_BUTDF, BUTTON_SCROLL_DOWN_FAST },
+
+ {125, 338 + 40, SR_BUTTON, BUTTON_SAVE_RESTORE_OKAY},
+ {462, 338 + 40, SR_BUTTON, BUTTON_SAVE_CANCEL}
+};
+
+const char SwordControl::_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",
+ "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",
+ "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!",
+};
diff --git a/sword1/control.h b/sword1/control.h
new file mode 100644
index 0000000000..4b0a1699b7
--- /dev/null
+++ b/sword1/control.h
@@ -0,0 +1,125 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef BSCONTROL_H
+#define BSCONTROL_H
+
+#include "scummsys.h"
+#include "sworddefs.h"
+
+class ObjectMan;
+class ResMan;
+class OSystem;
+class SwordMouse;
+class SwordEngine;
+
+#define MAX_BUTTONS 16
+
+#define CONTROL_NOTHING_DONE 0
+#define CONTROL_GAME_RESTORED 1
+#define CONTROL_RESTART_GAME 2
+
+class ControlButton {
+public:
+ ControlButton(uint16 x, uint16 y, uint32 resId, uint8 id, ResMan *pResMan, uint8 *screenBuf, OSystem *system);
+ ~ControlButton(void);
+ void draw(void);
+ bool wasClicked(uint16 mouseX, uint16 mouseY);
+ void setSelected(uint8 selected);
+ bool isSaveslot(void);
+ uint8 _id;
+private:
+ int _frameIdx;
+ uint16 _x, _y;
+ uint16 _width, _height;
+ uint32 _resId;
+ ResMan *_resMan;
+ uint8 *_dstBuf;
+ OSystem *_system;
+};
+
+struct ButtonInfo {
+ uint16 x, y;
+ uint32 resId, id;
+};
+
+class SwordControl {
+public:
+ SwordControl(ResMan *pResMan, ObjectMan *pObjMan, OSystem *system, SwordMouse *pMouse, const char *savePath);
+ ~SwordControl(void);
+ uint8 runPanel(void);
+ void doRestore(void);
+private:
+ void initData(void);
+ void closeData(void);
+
+ void saveGameToFile(uint8 slot);
+ void restoreGameFromFile(uint8 slot);
+ void readSavegameDescriptions(void);
+ void writeSavegameDescriptions(void);
+ void showSavegameNames(void);
+ void deselectSaveslots(void);
+ uint8 *_restoreBuf;
+ uint8 _saveFiles;
+ uint8 _saveScrollPos;
+ uint8 _selectedSavegame;
+ char _saveNames[64][32];
+ char _oldName[32];
+
+ uint8 getClicks(uint8 mode, uint8 *retVal);
+ uint8 handleButtonClick(uint8 id, uint8 mode, uint8 *retVal);
+
+ void setupMainPanel(void);
+ void setupSaveRestorePanel(bool saving);
+ void saveNameScroll(uint8 scroll, bool saving);
+ void saveNameSelect(uint8 id, bool saving);
+ bool saveToFile(void);
+ bool restoreFromFile(void);
+ bool keyAccepted(uint8 key);
+ void handleSaveKey(uint8 key);
+
+ uint16 getTextWidth(const char *str);
+ void renderText(const char *str, int16 x, uint16 y);
+ uint8 _numButtons;
+ uint8 _selectedButton;
+ void createButtons(const ButtonInfo *buttons, uint8 num);
+ void destroyButtons(void);
+ ControlButton *_buttons[MAX_BUTTONS];
+ static const ButtonInfo _deathButtons[3], _panelButtons[8], _saveButtons[16];
+ static const char _languageStrings[8 * 20][43];
+ const char (*_lStrings)[43];
+ ObjectMan *_objMan;
+ ResMan *_resMan;
+ OSystem *_system;
+ SwordMouse *_mouse;
+ SwordEngine *_engine;
+ char _savePath[256];
+ uint8 *_font;
+ uint32 _fontId;
+ uint8 *_screenBuf;
+ uint8 _keyPressed;
+ void delay(uint32 msecs);
+ uint16 _mouseX, _mouseY, _mouseState;
+};
+
+
+#endif //BSCONTROL_H
+