diff options
Diffstat (limited to 'engines/gnap/menu.cpp')
-rw-r--r-- | engines/gnap/menu.cpp | 888 |
1 files changed, 888 insertions, 0 deletions
diff --git a/engines/gnap/menu.cpp b/engines/gnap/menu.cpp new file mode 100644 index 0000000000..2bfe7300df --- /dev/null +++ b/engines/gnap/menu.cpp @@ -0,0 +1,888 @@ +/* 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 "common/config-manager.h" +#include "common/savefile.h" +#include "common/translation.h" + +#include "gui/saveload.h" +#include "graphics/thumbnail.h" + +#include "gnap/gnap.h" +#include "gnap/datarchive.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +void GnapEngine::createMenuSprite() { + _menuBackgroundSurface = _gameSys->createSurface(0x10002); +} + +void GnapEngine::freeMenuSprite() { + _gameSys->removeSpriteDrawItem(_menuBackgroundSurface, 260); + delayTicksCursor(5); + deleteSurface(&_menuBackgroundSurface); +} + +void GnapEngine::initMenuHotspots1() { + int curId = 0; + + for (int i = 0; i < 3; ++i) { + int top = 74 * i + 69; + for (int j = 0; j < 3; ++j) { + int left = 87 * j + 262; + _hotspots[curId]._rect = Common::Rect(left, top, left + 79, top + 66); + _hotspots[curId]._flags = SF_NONE; + ++curId; + } + } + + _hotspots[curId]._rect = Common::Rect(330, 350, 430, 460); + _hotspots[curId]._flags = SF_GRAB_CURSOR; + + ++curId; + _hotspots[curId]._rect = Common::Rect(180, 15, 620, 580); + _hotspots[curId]._flags = SF_NONE; + + ++curId; + _hotspots[curId]._rect = Common::Rect(0, 0, 799, 599); + _hotspots[curId]._flags = SF_NONE; + + _hotspotsCount = curId + 1; +} + +void GnapEngine::initMenuHotspots2() { + int curId = 0; + + for (int i = 0; i < 4; ++i) { + int top = 48 * i + 85; + _hotspots[curId]._rect = Common::Rect(312, top, 465, top + 37); + _hotspots[curId]._flags = SF_GRAB_CURSOR; + ++curId; + } + + _hotspots[curId]._rect = Common::Rect(500, 72, 527, 99); + _hotspots[curId]._flags = SF_DISABLED; + + ++curId; + _hotspots[curId]._rect = Common::Rect(330, 350, 430, 460); + _hotspots[curId]._flags = SF_GRAB_CURSOR; + + ++curId; + _hotspots[curId]._rect = Common::Rect(180, 15, 620, 580); + _hotspots[curId]._flags = SF_NONE; + + ++curId; + _hotspots[curId]._rect = Common::Rect(0, 0, 799, 599); + _hotspots[curId]._flags = SF_NONE; + + _hotspotsCount = curId + 1; +} + +void GnapEngine::initMenuQuitQueryHotspots() { + _hotspots[0]._rect = Common::Rect(311, 197, 377, 237); + _hotspots[0]._flags = SF_GRAB_CURSOR; + + _hotspots[1]._rect = Common::Rect(403, 197, 469, 237); + _hotspots[1]._flags = SF_GRAB_CURSOR; + + _hotspots[2]._rect = Common::Rect(330, 350, 430, 460); + _hotspots[2]._flags = SF_GRAB_CURSOR; + + _hotspots[3]._rect = Common::Rect(180, 15, 620, 580); + _hotspots[3]._flags = SF_NONE; + + _hotspots[4]._rect = Common::Rect(0, 0, 799, 599); + _hotspots[4]._flags = SF_NONE; + + _hotspotsCount = 5; +} + +void GnapEngine::initSaveLoadHotspots() { + int curId = 0; + + for (int i = 0; i < 7; ++i ) { + int top = 31 * i + 74; + _hotspots[curId]._rect = Common::Rect(288, top, 379, top + 22); + _hotspots[curId]._flags = SF_GRAB_CURSOR; + ++curId; + } + + if (_menuStatus == 2) { + _hotspots[curId]._rect = Common::Rect(416, 160, 499, 188); + _hotspots[curId]._flags = SF_GRAB_CURSOR; + ++curId; + } + + _hotspots[curId]._rect = Common::Rect(416, 213, 499, 241); + _hotspots[curId]._flags = SF_GRAB_CURSOR; + + ++curId; + _hotspots[curId]._rect = Common::Rect(330, 350, 430, 460); + _hotspots[curId]._flags = SF_GRAB_CURSOR; + + ++curId; + _hotspots[curId]._rect = Common::Rect(180, 15, 620, 580); + _hotspots[curId]._flags = SF_NONE; + + ++curId; + _hotspots[curId]._rect = Common::Rect(0, 0, 799, 599); + _hotspots[curId]._flags = SF_NONE; + + _hotspotsCount = curId + 1; +} + +void GnapEngine::drawInventoryFrames() { + for (int i = 0; i < 9; ++i) + _gameSys->drawSpriteToSurface(_menuBackgroundSurface, _hotspots[i]._rect.left - 93, _hotspots[i]._rect.top, 0x10001); +} + +void GnapEngine::insertInventorySprites() { + for (int i = 0; i < 9; ++i) { + _menuInventoryIndices[i] = -1; + _gameSys->removeSpriteDrawItem(_menuInventorySprites[_sceneClickedHotspot], 261); + _menuInventorySprites[i] = 0; + } + + _menuSpritesIndex = 0; + + for (int index = 0; index < 30 && _menuSpritesIndex < 9; ++index) { + if (invHas(index)) { + _gameSys->drawSpriteToSurface(_menuBackgroundSurface, + _hotspots[_menuSpritesIndex]._rect.left - 93, _hotspots[_menuSpritesIndex]._rect.top, 0x10000); + _menuInventorySprites[_menuSpritesIndex] = _gameSys->createSurface(getInventoryItemSpriteNum(index) | 0x10000); + if (index != _grabCursorSpriteIndex) { + _menuInventoryIndices[_menuSpritesIndex] = index; + _gameSys->insertSpriteDrawItem(_menuInventorySprites[_menuSpritesIndex], + _hotspots[_menuSpritesIndex]._rect.left + ((79 - _menuInventorySprites[_menuSpritesIndex]->w) / 2), + _hotspots[_menuSpritesIndex]._rect.top + ((66 - _menuInventorySprites[_menuSpritesIndex]->h) / 2), + 261); + } + _hotspots[_menuSpritesIndex]._flags = SF_GRAB_CURSOR; + ++_menuSpritesIndex; + } + } +} + +void GnapEngine::removeInventorySprites() { + for (int i = 0; i < _menuSpritesIndex; ++i) + if (_menuInventorySprites[i]) + _gameSys->removeSpriteDrawItem(_menuInventorySprites[i], 261); + delayTicksCursor(5); + for (int j = 0; j < _menuSpritesIndex; ++j) { + if (_menuInventorySprites[j]) { + deleteSurface(&_menuInventorySprites[j]); + _menuInventorySprites[j] = 0; + _menuInventoryIndices[j] = -1; + } + } + _menuSpritesIndex = 0; +} + +void GnapEngine::runMenu() { + _spriteHandle = nullptr; + _cursorSprite = nullptr; + _menuSprite1 = nullptr; + _menuSprite2 = nullptr; + _menuSaveLoadSprite = nullptr; + _menuQuitQuerySprite = nullptr; + + _menuStatus = 0; + _menuDone = false; + + delete _tempThumbnail; + _tempThumbnail = new Common::MemoryWriteStreamDynamic; + Graphics::saveThumbnail(*_tempThumbnail); + + createMenuSprite(); + insertDeviceIconActive(); + + for (int i = 0; i < 7; ++i) { + _savegameFilenames[i][0] = 0; + _savegameSprites[i] = nullptr; + } + + if (_menuStatus == 0) { + invAdd(kItemMagazine); + setGrabCursorSprite(-1); + hideCursor(); + initMenuHotspots1(); + drawInventoryFrames(); + insertInventorySprites(); + _gameSys->insertSpriteDrawItem(_menuBackgroundSurface, 93, 0, 260); + showCursor(); + // SetCursorPos(400, 300); + setVerbCursor(GRAB_CURSOR); + // pollMessages(); + } + + _timers[2] = 10; + + while (!isKeyStatus1(Common::KEYCODE_BACKSPACE) && !isKeyStatus1(Common::KEYCODE_ESCAPE) && !_sceneDone && !_menuDone) { + updateCursorByHotspot(); + + switch (_menuStatus) { + case 0: + updateMenuStatusInventory(); + break; + case 1: + updateMenuStatusMainMenu(); + break; + case 2: + updateMenuStatusSaveGame(); + break; + case 3: + updateMenuStatusLoadGame(); + break; + case 4: + updateMenuStatusQueryQuit(); + break; + } + + gameUpdateTick(); + } + + removeInventorySprites(); + if (_spriteHandle) + _gameSys->removeSpriteDrawItem(_spriteHandle, 261); + if (_menuSprite1) + _gameSys->removeSpriteDrawItem(_menuSprite1, 262); + if (_menuSprite2) + _gameSys->removeSpriteDrawItem(_menuSprite2, 262); + for (int i = 0; i < 7; ++i) + if (_savegameSprites[i]) + _gameSys->removeSpriteDrawItem(_savegameSprites[i], 263); + if (_cursorSprite) + _gameSys->removeSpriteDrawItem(_cursorSprite, 264); + if (_menuSaveLoadSprite) + _gameSys->removeSpriteDrawItem(_menuSaveLoadSprite, 262); + if (_menuQuitQuerySprite) + _gameSys->removeSpriteDrawItem(_menuQuitQuerySprite, 262); + if (_menuBackgroundSurface) + _gameSys->removeSpriteDrawItem(_menuBackgroundSurface, 260); + + delayTicksCursor(5); + + deleteSurface(&_spriteHandle); + deleteSurface(&_menuSprite1); + deleteSurface(&_menuSprite2); + for (int i = 0; i < 7; ++i) + deleteSurface(&_savegameSprites[i]); + deleteSurface(&_cursorSprite); + deleteSurface(&_menuSaveLoadSprite); + deleteSurface(&_menuQuitQuerySprite); + + _sceneClickedHotspot = -1; + + _timers[2] = getRandom(20) + 30; + _timers[3] = getRandom(200) + 50; + _timers[0] = getRandom(75) + 75; + _timers[1] = getRandom(20) + 30; + + clearAllKeyStatus1(); + + _mouseClickState._left = false; + + removeDeviceIconActive(); + + freeMenuSprite();//??? CHECKME +} + +void GnapEngine::updateMenuStatusInventory() { + static const struct { + int item1, item2, resultItem; + } kCombineItems[] = { + {kItemGrass, kItemMud, kItemDisguise}, + {kItemDice, kItemQuarterWithHole, kItemDiceQuarterHole}, + {kItemPill, kItemBucketWithBeer, kItemBucketWithPill} + }; + + updateGrabCursorSprite(0, 0); + _hotspots[0]._rect = Common::Rect(262, 69, 341, 135); + _sceneClickedHotspot = -1; + if (_timers[2] == 0) + _sceneClickedHotspot = getClickedHotspotId(); + if (_sceneClickedHotspot == -1 || _sceneClickedHotspot >= _menuSpritesIndex) { + if (_sceneClickedHotspot == _hotspotsCount - 3) { + if (_grabCursorSpriteIndex == -1) { + _timers[2] = 10; + playSound(0x108F4, false); + _menuStatus = 1; + Common::Rect dirtyRect(_hotspots[0]._rect.left, _hotspots[0]._rect.top, _hotspots[2]._rect.right, _hotspots[_hotspotsCount - 4]._rect.bottom); + drawInventoryFrames(); + initMenuHotspots2(); + removeInventorySprites(); + if (!_menuSprite1) + _menuSprite1 = _gameSys->createSurface(0x104F8); + _gameSys->insertSpriteDrawItem(_menuSprite1, 288, 79, 262); + _gameSys->insertDirtyRect(dirtyRect); + } else { + playSound(0x108F5, false); + } + } else if (_sceneClickedHotspot == _hotspotsCount - 1) { + _timers[2] = 10; + playSound(0x108F5, false); + _menuDone = true; + } + } else if (_sceneClickedHotspot != -1 && _menuInventoryIndices[_sceneClickedHotspot] != -1 && _grabCursorSpriteIndex == -1) { + _gameSys->removeSpriteDrawItem(_menuInventorySprites[_sceneClickedHotspot], 261); + setGrabCursorSprite(_menuInventoryIndices[_sceneClickedHotspot]); + _menuInventoryIndices[_sceneClickedHotspot] = -1; + } else if (_sceneClickedHotspot != -1 && _menuInventoryIndices[_sceneClickedHotspot] == -1 && _grabCursorSpriteIndex != -1) { + _menuInventoryIndices[_sceneClickedHotspot] = _grabCursorSpriteIndex; + _gameSys->insertSpriteDrawItem(_menuInventorySprites[_sceneClickedHotspot], + _hotspots[_sceneClickedHotspot]._rect.left + ((79 - _menuInventorySprites[_sceneClickedHotspot]->w) / 2), + _hotspots[_sceneClickedHotspot]._rect.top + (66 - _menuInventorySprites[_sceneClickedHotspot]->h) / 2, + 261); + setGrabCursorSprite(-1); + } else if (_sceneClickedHotspot != -1 && _menuInventoryIndices[_sceneClickedHotspot] != -1 && _grabCursorSpriteIndex != -1) { + int combineIndex = -1; + for (int i = 0; i < ARRAYSIZE(kCombineItems); ++i) { + if ((_grabCursorSpriteIndex == kCombineItems[i].item1 && _menuInventoryIndices[_sceneClickedHotspot] == kCombineItems[i].item2) || + (_grabCursorSpriteIndex == kCombineItems[i].item2 && _menuInventoryIndices[_sceneClickedHotspot] == kCombineItems[i].item1)) { + combineIndex = i; + break; + } + } + if (combineIndex >= 0) { + invRemove(kCombineItems[combineIndex].item1); + invRemove(kCombineItems[combineIndex].item2); + invAdd(kCombineItems[combineIndex].resultItem); + playSound(0x108AE, false); + deleteSurface(&_spriteHandle); // CHECKME + _spriteHandle = _gameSys->createSurface(0x10001); + _gameSys->insertSpriteDrawItem(_spriteHandle, _hotspots[_menuSpritesIndex - 1]._rect.left, _hotspots[_menuSpritesIndex - 1]._rect.top, 261); + setGrabCursorSprite(kCombineItems[combineIndex].resultItem); + removeInventorySprites(); + insertInventorySprites(); + delayTicksCursor(5); + } else { + playSound(0x108F5, false); + } + } +} + +void GnapEngine::updateMenuStatusMainMenu() { + _hotspots[0]._rect = Common::Rect(312, 85, 465, 122); + _sceneClickedHotspot = -1; + if (!_timers[2]) + _sceneClickedHotspot = getClickedHotspotId(); + + if (_sceneClickedHotspot != 1 && _sceneClickedHotspot != 0) { + if (_sceneClickedHotspot != 2 && _hotspotsCount - 1 != _sceneClickedHotspot) { + if (_sceneClickedHotspot == 3) { + // Quit + _timers[2] = 10; + playSound(0x108F4, false); + _gameSys->removeSpriteDrawItem(_menuSprite1, 262); + initMenuQuitQueryHotspots(); + _menuStatus = 4; + if (!_menuQuitQuerySprite) + _menuQuitQuerySprite = _gameSys->createSurface(0x104FC); + _gameSys->insertSpriteDrawItem(_menuQuitQuerySprite, 254, 93, 262); + } else if (_sceneClickedHotspot == 4) { + // Pause ? + playSound(0x108F4, false); + Common::Rect dirtyRect(0, 0, 799, 599); + hideCursor(); + _largeSprite = _gameSys->allocSurface(800, 600); + + for (int i = 0; i < 3; ++i) { + _timers[2] = 10; + + if (i == 0) { + _gameSys->drawSpriteToSurface(_largeSprite, 0, 0, 0x1078D); + _gameSys->insertSpriteDrawItem(_largeSprite, 0, 0, 300); + playMidi("pause.mid"); + } else if (i == 1) { + _gameSys->drawSpriteToSurface(_largeSprite, 0, 0, 0x1078E); + _gameSys->insertDirtyRect(dirtyRect); + } else if (i == 2) { + _gameSys->drawSpriteToSurface(_largeSprite, 0, 0, 0x1078F); + _gameSys->insertDirtyRect(dirtyRect); + } + + while (!_mouseClickState._left && !isKeyStatus1(Common::KEYCODE_ESCAPE) && !isKeyStatus1(Common::KEYCODE_RETURN) + && !isKeyStatus1(Common::KEYCODE_SPACE) && !_timers[2] && !_gameDone) + gameUpdateTick(); + + playSound(0x108F5, false); + _mouseClickState._left = false; + clearKeyStatus1(Common::KEYCODE_ESCAPE); + clearKeyStatus1(Common::KEYCODE_RETURN); + clearKeyStatus1(Common::KEYCODE_SPACE); + } + + _gameSys->removeSpriteDrawItem(_largeSprite, 300); + delayTicksCursor(5); + deleteSurface(&_largeSprite); + showCursor(); + } else if (_hotspotsCount - 3 == _sceneClickedHotspot) { + // Button - Return to the inventory + _timers[2] = 10; + playSound(0x108F4, false); + initMenuHotspots1(); + _menuStatus = 0; + if (_menuSprite1) + _gameSys->removeSpriteDrawItem(_menuSprite1, 262); + insertInventorySprites(); + Common::Rect dirtyRect(_hotspots[0]._rect.left, _hotspots[0]._rect.top, _hotspots[2]._rect.right, _hotspots[_hotspotsCount - 4]._rect.bottom); + _gameSys->insertDirtyRect(dirtyRect); + } + } else { + // Resume + playSound(0x108F5, false); + _menuDone = true; + } + } else { + // Save / Load +#if 1 + _timers[2] = 10; + playSound(0x108F4, false); + + if (_sceneClickedHotspot == 1) { + GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); + int16 savegameId = dialog->runModalWithCurrentTarget(); + Common::String savegameDescription = dialog->getResultString(); + delete dialog; + + if (savegameId != -1) { + saveGameState(savegameId, savegameDescription); + } + } else { + GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false); + int16 savegameId = dialog->runModalWithCurrentTarget(); + delete dialog; + + if (savegameId != -1) { + loadGameState(savegameId); + _wasSavegameLoaded = true; + _menuDone = true; + _sceneDone = true; + playSound(0x108F4, false); + } else { + playSound(0x108F5, false); + } + } + } +#else + // NOTE: + // This is the code for the original behavior. + // It's currently not working prolery, but could be + // fixed to replace the ScummVM screens currently + // used. + _timers[2] = 10; + playSound(0x108F4, false); + _gameSys->removeSpriteDrawItem(_menuSprite1, 262); + if (_menuSaveLoadSprite) + deleteSurface(&_menuSaveLoadSprite); + if (_sceneClickedHotspot == 1) { + // Save + _menuStatus = 2; + initSaveLoadHotspots(); + _menuSaveLoadSprite = _gameSys->createSurface(0x104FB); + } else { + // Load + _menuStatus = 3; + initSaveLoadHotspots(); + _menuSaveLoadSprite = _gameSys->createSurface(0x104FA); + } + _gameSys->insertSpriteDrawItem(_menuSaveLoadSprite, 403, 72, 262); + if (!_menuSprite2) + _menuSprite2 = _gameSys->createSurface(0x104F9); + _gameSys->insertSpriteDrawItem(_menuSprite2, 277, 66, 262); + for (int i = 0; i < 7; ++i) { + Common::String savegameDescription; + if (!_savegameSprites[i]) + _savegameSprites[i] = _gameSys->allocSurface(111, 40); + if (readSavegameDescription(i + 1, savegameDescription) == 0) + strncpy(_savegameFilenames[i], savegameDescription.c_str(), 40); + _gameSys->drawTextToSurface(_savegameSprites[i], 0, 0, 255, 0, 0, _savegameFilenames[i]); + _gameSys->insertSpriteDrawItem(_savegameSprites[i], 288, _hotspots[i].top, 263); + } + _savegameIndex = -1; + } +#endif +} + +Common::Error GnapEngine::saveGameState(int slot, const Common::String &desc) { + Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving( + generateSaveName(slot)); + if (!out) + return Common::kCreatingFileFailed; + + GnapSavegameHeader header; + header._saveName = desc; + writeSavegameHeader(out, header); + + Common::Serializer s(nullptr, out); + synchronize(s); + + out->finalize(); + delete out; + + return Common::kNoError; +} + +void GnapEngine::synchronize(Common::Serializer &s) { + if (s.isSaving()) { + s.syncAsSint32LE(_currentSceneNum); + s.syncAsSint32LE(_prevSceneNum); + s.syncAsSint32LE(_cursorValue); + s.syncAsUint32LE(_inventory); + s.syncAsUint32LE(_gameFlags); + } else { + s.syncAsSint32LE(_newSceneNum); + s.syncAsSint32LE(_currentSceneNum); + s.syncAsSint32LE(_newCursorValue); + s.syncAsUint32LE(_inventory); + s.syncAsUint32LE(_gameFlags); + + if (isFlag(kGFUnk24)) + _timers[9] = 600; + } +} + +const char *const SAVEGAME_STR = "GNAP"; +#define SAVEGAME_STR_SIZE 4 +void GnapEngine::writeSavegameHeader(Common::OutSaveFile *out, GnapSavegameHeader &header) { + // Write out a savegame header + out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1); + + out->writeByte(GNAP_SAVEGAME_VERSION); + + // Write savegame name + out->writeString(header._saveName); + out->writeByte('\0'); + + // This implies the menu is used + // If we want to save/load at any time, then a check should be added + out->write(_tempThumbnail->getData(), _tempThumbnail->size()); + + // Write out the save date/time + TimeDate td; + g_system->getTimeAndDate(td); + out->writeSint16LE(td.tm_year + 1900); + out->writeSint16LE(td.tm_mon + 1); + out->writeSint16LE(td.tm_mday); + out->writeSint16LE(td.tm_hour); + out->writeSint16LE(td.tm_min); +} + +bool GnapEngine::readSavegameHeader(Common::InSaveFile *in, GnapSavegameHeader &header) { + char saveIdentBuffer[SAVEGAME_STR_SIZE + 1]; + header._thumbnail = nullptr; + + // Validate the header Id + in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1); + if (strncmp(saveIdentBuffer, SAVEGAME_STR, SAVEGAME_STR_SIZE)) + return false; + + header._version = in->readByte(); + if (header._version > GNAP_SAVEGAME_VERSION) + return false; + + // Read in the string + header._saveName.clear(); + char ch; + while ((ch = (char)in->readByte()) != '\0') + header._saveName += ch; + + // Get the thumbnail, saved in v2 or later + if (header._version == 1) + header._thumbnail = nullptr; + else { + header._thumbnail = Graphics::loadThumbnail(*in); + if (!header._thumbnail) + return false; + } + + // Read in save date/time + header._year = in->readSint16LE(); + header._month = in->readSint16LE(); + header._day = in->readSint16LE(); + header._hour = in->readSint16LE(); + header._minute = in->readSint16LE(); + + return true; +} + +Common::Error GnapEngine::loadGameState(int slot) { + Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading( + generateSaveName(slot)); + if (!saveFile) + return Common::kReadingFailed; + + Common::Serializer s(saveFile, nullptr); + + // Load the savegame header + GnapSavegameHeader header; + if (!readSavegameHeader(saveFile, header)) + error("Invalid savegame"); + + if (header._thumbnail) { + header._thumbnail->free(); + delete header._thumbnail; + } + + synchronize(s); + delete saveFile; + + _loadGameSlot = slot; + return Common::kNoError; +} + +Common::String GnapEngine::generateSaveName(int slot) { + return Common::String::format("%s.%03d", _targetName.c_str(), slot); +} + +void GnapEngine::updateMenuStatusSaveGame() { +#if 0 + // NOTE: + // This is the code for the original screen game. + // It could be eventually fixed and could replace + // the ScummVM screens currently used. + + char v43[30]; + int v46; + v43[0] = '\0'; + _hotspots[0]._x1 = 288; + _hotspots[0]._y1 = 74; + _hotspots[0]._x2 = 379; + _hotspots[0]._y2 = 96; + _sceneClickedHotspot = -1; + + if (!_timers[2]) + _sceneClickedHotspot = getClickedHotspotId(); + + if (_hotspotsCount - 3 == _sceneClickedHotspot) { + // Button + _timers[2] = 10; + playSound(0x108F4, false); + _menuStatus = 1; + warning("writeSavegame(_savegameIndex + 1, (int)&_savegameFilenames[30 * _savegameIndex], 1);"); + } else if (_hotspotsCount - 4 == _sceneClickedHotspot) { + // Cancel + _timers[2] = 10; + playSound(0x108F5, false); + _menuStatus = 1; + if (strcmp(v43, _savegameFilenames[_savegameIndex]) && _savegameIndex != -1) { + strcpy(_savegameFilenames[_savegameIndex], v43); + if (_savegameSprites[_savegameIndex] != nullptr) { + _gameSys->removeSpriteDrawItem(_savegameSprites[_savegameIndex], 263); + delayTicksCursor(5); + warning("memFreeHandle(_savegameSprites[_savegameIndex]);"); + } + int v16 = _gameSys->getSpriteWidthById(0x104F9); + warning("_savegameSprites[_savegameIndex] = allocSprite(v16, 40, 128, 0);"); + } + } else if (_hotspotsCount - 5 == _sceneClickedHotspot) { + // OK + _timers[2] = 10; + playSound(0x108F4, false); + if (_savegameIndex != -1) + warning("writeSavegame(_savegameIndex + 1, (int)&_savegameFilenames[30 * _savegameIndex], 1);"); + _menuStatus = 1; + } else if (_hotspotsCount - 1 == _sceneClickedHotspot) { + // in background + _menuDone = true; + } else if (_sceneClickedHotspot != -1 && _hotspotsCount - 2 != _sceneClickedHotspot) { + // Savegame name + _timers[2] = 10; + playSound(0x108F4, false); + if (strcmp(v43, _savegameFilenames[_savegameIndex]) & (_savegameIndex != -1)) { + strcpy(_savegameFilenames[_savegameIndex], v43); + if (_savegameSprites[_savegameIndex] != nullptr) { + _gameSys->removeSpriteDrawItem(_savegameSprites[_savegameIndex], 263); + delayTicksCursor(5); + warning("memFreeHandle(_savegameSprites[_savegameIndex]);"); + } + int v18 = _gameSys->getSpriteWidthById(0x104F9); + _savegameSprites[_savegameIndex] = _gameSys->allocSurface(v18, 40); + _gameSys->drawTextToSurface(_savegameSprites[_savegameIndex], 0, 0, 255, 0, 0, _savegameFilenames[_savegameIndex]); + _gameSys->insertSpriteDrawItem(_savegameSprites[_savegameIndex], 288, _hotspots[_savegameIndex]._y1, 263); + } + _savegameIndex = _sceneClickedHotspot; + v46 = strlen(_savegameFilenames[_sceneClickedHotspot]); + strcpy(v43, _savegameFilenames[_sceneClickedHotspot]); + if (_cursorSprite == nullptr) { + int v19 = _gameSys->getTextHeight("_"); + int v20 = _gameSys->getTextWidth("_"); + _cursorSprite = _gameSys->allocSurface(v20, v19); + _gameSys->drawTextToSurface(_cursorSprite, 0, 0, 255, 0, 0, "_"); + } else { + _gameSys->removeSpriteDrawItem(_cursorSprite, 264); + } + int v21 = _hotspots[_savegameIndex]._x2; + int v22 = v21 - _gameSys->getTextWidth("_"); + if (v22 > _gameSys->getTextWidth(_savegameFilenames[_savegameIndex]) + 288) { + int v25 = _gameSys->getTextWidth(_savegameFilenames[_savegameIndex]) + 288; + _gameSys->insertSpriteDrawItem(_cursorSprite, v25, _hotspots[_savegameIndex]._y1, 264); + } else { + int v23 = _hotspots[_savegameIndex]._x2; + int v24 = v23 - _gameSys->getTextWidth("_"); + _gameSys->insertSpriteDrawItem(_cursorSprite, v24, _hotspots[_savegameIndex]._y1, 264); + } + } + + updateEvents(); + Common::Event event; + _eventMan->pollEvent(event); + + Common::KeyCode keycode = event.kbd.keycode; + if (_savegameIndex != -1 && keycode) { + if ((keycode < Common::KEYCODE_a || keycode > Common::KEYCODE_z) && (keycode < Common::KEYCODE_0 || keycode > Common::KEYCODE_9) && keycode != Common::KEYCODE_SPACE) { + if (keycode == Common::KEYCODE_BACKSPACE) { + if (v46 > 0) + --v46; + _savegameFilenames[_savegameIndex][v46] = '\0'; + if (_savegameSprites[_savegameIndex] != nullptr) { + _gameSys->removeSpriteDrawItem(_savegameSprites[_savegameIndex], 263); + warning("memFreeHandle(_savegameSprites[_savegameIndex]);"); + } + int v32 = _gameSys->getSpriteWidthById(0x104F9); + _savegameSprites[_savegameIndex] = _gameSys->allocSurface(v32, 40); + _gameSys->drawTextToSurface(_savegameSprites[_savegameIndex], 0, 0, 255, 0, 0, _savegameFilenames[_savegameIndex]); + _gameSys->insertSpriteDrawItem(_savegameSprites[_savegameIndex], 288, _hotspots[_savegameIndex]._y1, 263); + _gameSys->removeSpriteDrawItem(_cursorSprite, 264); + int v33 = _hotspots[_savegameIndex]._y1; + int v34 = _gameSys->getTextWidth(_savegameFilenames[_savegameIndex]); + _gameSys->insertSpriteDrawItem(_cursorSprite, _hotspots[_savegameIndex]._x1 + v34, v33, 264); + } else if (keycode == Common::KEYCODE_RETURN) { + _menuStatus = 1; + warning("writeSavegame(_savegameIndex + 1, (int)&_savegameFilenames[30 * _savegameIndex], 1);"); + } + } else { + _savegameFilenames[_savegameIndex][v46] = event.kbd.ascii; + if (v46 < 28) + ++v46; + _savegameFilenames[_savegameIndex][v46] = '\0'; + if (_gameSys->getTextWidth(_savegameFilenames[_savegameIndex]) > 91) { + --v46; + _savegameFilenames[_savegameIndex][v46] = '\0'; + } + _gameSys->drawTextToSurface(_savegameSprites[_savegameIndex], 0, 0, 255, 0, 0, _savegameFilenames[_savegameIndex]); + int v26 = _gameSys->getTextWidth(_savegameFilenames[_savegameIndex]); + Common::Rect rect; + rect.right = _hotspots[_savegameIndex]._x1 + v26; + int v27 = rect.right; + rect.left = v27 - 2 * _gameSys->getTextWidth("W"); + rect.top = _hotspots[_savegameIndex]._y1; + rect.bottom = _hotspots[_savegameIndex]._y2; + _gameSys->insertDirtyRect(rect); + _gameSys->removeSpriteDrawItem(_cursorSprite, 264); + int v28 = _hotspots[_savegameIndex]._x2; + int v29 = _gameSys->getTextWidth("_"); + if (v28 - v29 > rect.right) + _gameSys->insertSpriteDrawItem(_cursorSprite, rect.right, rect.top, 264); + else { + int v30 = _hotspots[_savegameIndex]._x2; + int v31 = v30 - _gameSys->getTextWidth("_"); + _gameSys->insertSpriteDrawItem(_cursorSprite, v31, rect.top, 264); + } + clearKeyStatus1(8); + } + } + +// warning("keybChar = 0;"); + if (_menuStatus == 1 || _menuDone) { + _gameSys->removeSpriteDrawItem(_menuSprite2, 262); + _gameSys->removeSpriteDrawItem(_menuSaveLoadSprite, 262); + for (int i = 0; i < 7; ++i) + _gameSys->removeSpriteDrawItem(_savegameSprites[i], 263); + _gameSys->removeSpriteDrawItem(_cursorSprite, 264); + if (!_menuDone) { + initMenuHotspots2(); + _gameSys->insertSpriteDrawItem(_menuSprite1, 288, 79, 262); + } + } +#endif +} + +void GnapEngine::updateMenuStatusLoadGame() { + _hotspots[0]._rect = Common::Rect(288, 74, 379, 96); + _sceneClickedHotspot = -1; + if (!_timers[2]) + _sceneClickedHotspot = getClickedHotspotId(); + if (_sceneClickedHotspot != -1 && _hotspotsCount - 2 != _sceneClickedHotspot) { + _timers[2] = 10; + if (_hotspotsCount - 4 <= _sceneClickedHotspot) { + playSound(0x108F5, false); + _gameSys->removeSpriteDrawItem(_menuSprite2, 262); + _gameSys->removeSpriteDrawItem(_menuSaveLoadSprite, 262); + for (int i = 0; i < 7; ++i) + _gameSys->removeSpriteDrawItem(_savegameSprites[i], 263); + if (_hotspotsCount - 1 == _sceneClickedHotspot) { + _menuDone = true; + } else { + _menuStatus = 1; + initMenuHotspots2(); + _gameSys->insertSpriteDrawItem(_menuSprite1, 288, 79, 262); + } + } else if (loadSavegame(_sceneClickedHotspot + 1)) { + playSound(0x108F5, false); + } else { + playSound(0x108F4, false); + _sceneDone = true; + } + } +} + +void GnapEngine::updateMenuStatusQueryQuit() { + _hotspots[0]._rect = Common::Rect(311, 197, 377, 237); + _sceneClickedHotspot = -1; + + if (!_timers[2]) + _sceneClickedHotspot = getClickedHotspotId(); + + /* _sceneClickedHotspot + 0 Yes + 1 No + 2 Button + 3 Display + 4 Background + */ + + if (_sceneClickedHotspot == 0) { + // Quit the game + playSound(0x108F5, false); + _gameSys->removeSpriteDrawItem(_menuQuitQuerySprite, 262); + _sceneDone = true; + _gameDone = true; + } else if (_sceneClickedHotspot == 4) { + // Exit the device + playSound(0x108F4, false); + _gameSys->removeSpriteDrawItem(_menuQuitQuerySprite, 262); + _menuDone = true; + } else if (_sceneClickedHotspot != -1) { + // Return to the main menu + playSound(0x108F4, false); + _gameSys->removeSpriteDrawItem(_menuQuitQuerySprite, 262); + _timers[2] = 10; + _menuStatus = 1; + initMenuHotspots2(); + _gameSys->insertSpriteDrawItem(_menuSprite1, 288, 79, 262); + } +} + +} // End of namespace Gnap |