mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-15 14:18:37 +00:00
170e57593d
These are flagged by GCC if -Wswitch-default is enabled.
890 lines
28 KiB
C++
890 lines
28 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "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
|