/* 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(DisposeAfterUse::YES); 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; default: 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); } WARN_UNUSED_RESULT bool GnapEngine::readSavegameHeader(Common::InSaveFile *in, GnapSavegameHeader &header, bool skipThumbnail) { char saveIdentBuffer[SAVEGAME_STR_SIZE + 1]; // 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 { if (!Graphics::loadThumbnail(*in, header._thumbnail, skipThumbnail)) { 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