816 lines
26 KiB
C++
816 lines
26 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
#include "common/hashmap.h"
|
|
#include "common/savefile.h"
|
|
#include "common/translation.h"
|
|
#include "graphics/thumbnail.h"
|
|
#include "gui/message.h"
|
|
|
|
#include "tot/forest.h"
|
|
#include "tot/tot.h"
|
|
|
|
namespace Tot {
|
|
|
|
#define SAVEGAME_CURRENT_VERSION 1
|
|
|
|
bool syncGeneralData(Common::Serializer &s, SavedGame *game) {
|
|
// Uint16
|
|
s.syncAsUint16LE(game->roomCode);
|
|
s.syncAsUint16LE(game->trajectoryLength);
|
|
s.syncAsUint16LE(game->currentTrajectoryIndex);
|
|
s.syncAsUint16LE(game->backpackObjectCode);
|
|
s.syncAsUint16LE(game->rightSfxVol);
|
|
s.syncAsUint16LE(game->leftSfxVol);
|
|
s.syncAsUint16LE(game->musicVolRight);
|
|
s.syncAsUint16LE(game->musicVolLeft);
|
|
s.syncAsUint16LE(game->oldGridX);
|
|
s.syncAsUint16LE(game->oldGridY);
|
|
s.syncAsUint16LE(game->secAnimDepth);
|
|
s.syncAsUint16LE(game->secAnimDir);
|
|
s.syncAsUint16LE(game->secAnimX);
|
|
s.syncAsUint16LE(game->secAnimY);
|
|
s.syncAsUint16LE(game->secAnimIFrame);
|
|
// Bytes
|
|
s.syncAsByte(game->currentZone);
|
|
s.syncAsByte(game->targetZone);
|
|
s.syncAsByte(game->oldTargetZone);
|
|
s.syncAsByte(game->inventoryPosition);
|
|
s.syncAsByte(game->actionCode);
|
|
s.syncAsByte(game->oldActionCode);
|
|
s.syncAsByte(game->steps);
|
|
s.syncAsByte(game->doorIndex);
|
|
s.syncAsByte(game->characterFacingDir);
|
|
s.syncAsByte(game->iframe);
|
|
s.syncAsByte(game->gamePart);
|
|
|
|
// Booleans
|
|
s.syncAsByte(game->isSealRemoved);
|
|
s.syncAsByte(game->obtainedList1);
|
|
s.syncAsByte(game->obtainedList2);
|
|
s.syncAsByte(game->list1Complete);
|
|
s.syncAsByte(game->list2Complete);
|
|
s.syncAsByte(game->isVasePlaced);
|
|
s.syncAsByte(game->isScytheTaken);
|
|
s.syncAsByte(game->isTridentTaken);
|
|
s.syncAsByte(game->isPottersWheelDelivered);
|
|
s.syncAsByte(game->isMudDelivered);
|
|
s.syncAsByte(game->isGreenDevilDelivered);
|
|
s.syncAsByte(game->isRedDevilCaptured);
|
|
s.syncAsByte(game->isPottersManualDelivered);
|
|
s.syncAsByte(game->isCupboardOpen);
|
|
s.syncAsByte(game->isChestOpen);
|
|
s.syncAsByte(game->isTVOn);
|
|
s.syncAsByte(game->isTrapSet);
|
|
|
|
for (int i = 0; i < kInventoryIconCount; i++) {
|
|
s.syncAsUint16LE(game->mobj[i].bitmapIndex);
|
|
s.syncAsUint16LE(game->mobj[i].code);
|
|
s.syncString(game->mobj[i].objectName);
|
|
}
|
|
|
|
// integers
|
|
s.syncAsSint32LE(game->element1);
|
|
s.syncAsSint32LE(game->element2);
|
|
s.syncAsSint32LE(game->characterPosX);
|
|
s.syncAsSint32LE(game->characterPosY);
|
|
s.syncAsSint32LE(game->xframe2);
|
|
s.syncAsSint32LE(game->yframe2);
|
|
|
|
// Strings
|
|
s.syncString(game->oldInventoryObjectName);
|
|
s.syncString(game->objetomoinventoryObjectNamehila);
|
|
s.syncString(game->characterName);
|
|
|
|
for (int i = 0; i < kRoutePointCount; i++) {
|
|
s.syncAsSint16LE(game->mainRoute[i].x);
|
|
s.syncAsSint16LE(game->mainRoute[i].y);
|
|
}
|
|
|
|
for (int i = 0; i < 300; i++) {
|
|
s.syncAsSint16LE(game->trajectory[i].x);
|
|
s.syncAsSint16LE(game->trajectory[i].y);
|
|
}
|
|
|
|
for (int indiaux = 0; indiaux < kCharacterCount; indiaux++) {
|
|
// interleave them just to avoid creating many loops
|
|
s.syncAsByte(game->firstTimeTopicA[indiaux]);
|
|
s.syncAsByte(game->firstTimeTopicB[indiaux]);
|
|
s.syncAsByte(game->firstTimeTopicC[indiaux]);
|
|
s.syncAsByte(game->bookTopic[indiaux]);
|
|
s.syncAsByte(game->mintTopic[indiaux]);
|
|
}
|
|
|
|
for (int indiaux = 0; indiaux < 5; indiaux++) {
|
|
s.syncAsByte(game->caves[indiaux]);
|
|
s.syncAsUint16LE(game->firstList[indiaux]);
|
|
s.syncAsUint16LE(game->secondList[indiaux]);
|
|
}
|
|
|
|
for (int indiaux = 0; indiaux < 4; indiaux++) {
|
|
s.syncAsUint16LE(game->niche[0][indiaux]);
|
|
s.syncAsUint16LE(game->niche[1][indiaux]);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool syncRoomData(Common::Serializer &s, Common::MemorySeekableReadWriteStream *roomStream) {
|
|
if (s.isSaving()) {
|
|
|
|
// Restore trajectory
|
|
g_engine->setRoomTrajectories(g_engine->_secondaryAnimHeight, g_engine->_secondaryAnimWidth, RESTORE);
|
|
// Make sure to save any unsaved changes in the room
|
|
g_engine->saveRoomData(g_engine->_currentRoomData, g_engine->_rooms);
|
|
|
|
// Do not fix screen grids, they will be fixed differently below
|
|
g_engine->setRoomTrajectories(g_engine->_secondaryAnimHeight, g_engine->_secondaryAnimWidth, SET_WITH_ANIM);
|
|
|
|
int size = roomStream->size();
|
|
byte *roomBuf = (byte *)malloc(size);
|
|
roomStream->seek(0, 0);
|
|
roomStream->read(roomBuf, size);
|
|
s.syncBytes(roomBuf, size);
|
|
free(roomBuf);
|
|
}
|
|
if (s.isLoading()) {
|
|
int size = g_engine->_rooms->size();
|
|
delete (g_engine->_rooms);
|
|
byte *roomBuf = (byte *)malloc(size);
|
|
s.syncBytes(roomBuf, size);
|
|
|
|
g_engine->_rooms = new Common::MemorySeekableReadWriteStream(roomBuf, size, DisposeAfterUse::NO);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool syncConversationData(Common::Serializer &s, Common::MemorySeekableReadWriteStream *conversations) {
|
|
|
|
int size = conversations->size();
|
|
if (s.isSaving()) {
|
|
|
|
byte *convBuf = (byte *)malloc(size);
|
|
conversations->seek(0, 0);
|
|
conversations->read(convBuf, size);
|
|
s.syncBytes(convBuf, size);
|
|
free(convBuf);
|
|
}
|
|
if (s.isLoading()) {
|
|
delete (g_engine->_conversationData);
|
|
byte *convBuf = (byte *)malloc(size);
|
|
s.syncBytes(convBuf, size);
|
|
g_engine->_conversationData = new Common::MemorySeekableReadWriteStream(convBuf, size, DisposeAfterUse::NO);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool syncItemData(Common::Serializer &s, Common::MemorySeekableReadWriteStream *sceneObjects) {
|
|
int size = sceneObjects->size();
|
|
if (s.isSaving()) {
|
|
byte *objBuf = (byte *)malloc(size);
|
|
sceneObjects->seek(0, 0);
|
|
sceneObjects->read(objBuf, size);
|
|
s.syncBytes(objBuf, size);
|
|
free(objBuf);
|
|
}
|
|
if (s.isLoading()) {
|
|
delete (g_engine->_sceneObjectsData);
|
|
byte *objBuf = (byte *)malloc(size);
|
|
s.syncBytes(objBuf, size);
|
|
g_engine->_sceneObjectsData = new Common::MemorySeekableReadWriteStream(objBuf, size, DisposeAfterUse::NO);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
Common::Error syncSaveData(Common::Serializer &ser, SavedGame *game) {
|
|
if (!syncGeneralData(ser, game)) {
|
|
warning("Error while synchronizing general data");
|
|
return Common::kUnknownError;
|
|
}
|
|
if (!syncRoomData(ser, g_engine->_rooms)) {
|
|
warning("Error while synchronizing room data");
|
|
return Common::kUnknownError;
|
|
}
|
|
if (!syncItemData(ser, g_engine->_sceneObjectsData)) {
|
|
warning("Error while syncrhonizing object data");
|
|
return Common::kUnknownError;
|
|
}
|
|
if (!syncConversationData(ser, g_engine->_conversationData)) {
|
|
warning("Error while syncrhonizing conversation data");
|
|
return Common::kUnknownError;
|
|
}
|
|
if (ser.err()) {
|
|
warning("Error while synchronizing");
|
|
return Common::kUnknownError;
|
|
}
|
|
|
|
return Common::kNoError;
|
|
}
|
|
|
|
Common::Error TotEngine::syncGame(Common::Serializer &s) {
|
|
Common::Error result;
|
|
|
|
if (s.isLoading()) {
|
|
SavedGame *loadedGame = new SavedGame();
|
|
// Means we are loading from before the game has started
|
|
// if(rooms == nullptr) {
|
|
_graphics->clear();
|
|
displayLoading();
|
|
|
|
loadCharAnimation();
|
|
loadInventory();
|
|
|
|
_graphics->loadPaletteFromFile("DEFAULT");
|
|
initScreenPointers();
|
|
|
|
_graphics->totalFadeOut(0);
|
|
_graphics->clear();
|
|
initializeScreenFile();
|
|
initializeObjectFile();
|
|
readConversationFile();
|
|
|
|
result = syncSaveData(s, loadedGame);
|
|
loadGame(loadedGame);
|
|
} else {
|
|
SavedGame *saveGame = saveGameToRegister();
|
|
result = syncSaveData(s, saveGame);
|
|
free(saveGame);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
Common::Error TotEngine::saveGameStream(Common::WriteStream *stream, bool isAutosave) {
|
|
const byte version = SAVEGAME_CURRENT_VERSION;
|
|
Common::Serializer s(nullptr, stream);
|
|
s.setVersion(version);
|
|
stream->writeByte(version);
|
|
|
|
return syncGame(s);
|
|
}
|
|
Common::Error TotEngine::loadGameStream(Common::SeekableReadStream *stream) {
|
|
byte version = stream->readByte();
|
|
if (version > SAVEGAME_CURRENT_VERSION) {
|
|
GUI::MessageDialog dialog(_("Saved game was created with a newer version of ScummVM. Unable to load."));
|
|
dialog.runModal();
|
|
return Common::kUnknownError;
|
|
}
|
|
|
|
Common::Serializer s(stream, nullptr);
|
|
s.setVersion(version);
|
|
|
|
return syncGame(s);
|
|
}
|
|
|
|
bool TotEngine::canLoadGameStateCurrently(Common::U32String *msg) {
|
|
return true;
|
|
}
|
|
bool TotEngine::canSaveGameStateCurrently(Common::U32String *msg) {
|
|
return _inGame && _saveAllowed;
|
|
}
|
|
|
|
SavedGame *TotEngine::saveGameToRegister() {
|
|
SavedGame *_savedGame = new SavedGame();
|
|
_savedGame->roomCode = _currentRoomData->code;
|
|
_savedGame->trajectoryLength = _trajectoryLength;
|
|
_savedGame->currentTrajectoryIndex = _currentTrajectoryIndex;
|
|
_savedGame->backpackObjectCode = _backpackObjectCode;
|
|
_savedGame->rightSfxVol = _sound->_rightSfxVol;
|
|
_savedGame->leftSfxVol = _sound->_leftSfxVol;
|
|
_savedGame->musicVolRight = _sound->_musicVolRight;
|
|
_savedGame->musicVolLeft = _sound->_musicVolLeft;
|
|
_savedGame->oldGridX = _oldGridX;
|
|
_savedGame->oldGridY = _oldGridY;
|
|
_savedGame->secAnimDepth = _secondaryAnimation.depth;
|
|
_savedGame->secAnimDir = _secondaryAnimation.dir;
|
|
_savedGame->secAnimX = _secondaryAnimation.posx;
|
|
_savedGame->secAnimY = _secondaryAnimation.posy;
|
|
_savedGame->secAnimIFrame = _iframe2;
|
|
|
|
_savedGame->currentZone = _currentZone;
|
|
_savedGame->targetZone = _targetZone;
|
|
_savedGame->oldTargetZone = _oldTargetZone;
|
|
_savedGame->inventoryPosition = _inventoryPosition;
|
|
_savedGame->actionCode = _actionCode;
|
|
_savedGame->oldActionCode = _oldActionCode;
|
|
_savedGame->steps = _trajectorySteps;
|
|
_savedGame->doorIndex = _doorIndex;
|
|
_savedGame->characterFacingDir = _charFacingDirection;
|
|
_savedGame->iframe = _iframe;
|
|
_savedGame->gamePart = _gamePart;
|
|
|
|
_savedGame->isSealRemoved = _isSealRemoved;
|
|
_savedGame->obtainedList1 = _obtainedList1;
|
|
_savedGame->obtainedList2 = _obtainedList2;
|
|
_savedGame->list1Complete = _list1Complete;
|
|
_savedGame->list2Complete = _list2Complete;
|
|
_savedGame->isVasePlaced = _isVasePlaced;
|
|
_savedGame->isScytheTaken = _isScytheTaken;
|
|
_savedGame->isTridentTaken = _isTridentTaken;
|
|
_savedGame->isPottersWheelDelivered = _isPottersWheelDelivered;
|
|
_savedGame->isMudDelivered = _isMudDelivered;
|
|
_savedGame->isGreenDevilDelivered = _isGreenDevilDelivered;
|
|
_savedGame->isRedDevilCaptured = _isRedDevilCaptured;
|
|
_savedGame->isPottersManualDelivered = _isPottersManualDelivered;
|
|
_savedGame->isCupboardOpen = _isCupboardOpen;
|
|
_savedGame->isChestOpen = _isChestOpen;
|
|
_savedGame->isTVOn = _isTVOn;
|
|
_savedGame->isTrapSet = _isTrapSet;
|
|
|
|
for (int i = 0; i < kInventoryIconCount; i++) {
|
|
_savedGame->mobj[i].bitmapIndex = _inventory[i].bitmapIndex;
|
|
_savedGame->mobj[i].code = _inventory[i].code;
|
|
_savedGame->mobj[i].objectName = _inventory[i].objectName;
|
|
}
|
|
|
|
_savedGame->element1 = _element1;
|
|
_savedGame->element2 = _element2;
|
|
_savedGame->characterPosX = _characterPosX;
|
|
_savedGame->characterPosY = _characterPosY;
|
|
_savedGame->xframe2 = _xframe2;
|
|
_savedGame->yframe2 = _yframe2;
|
|
|
|
_savedGame->oldInventoryObjectName = _oldInventoryObjectName;
|
|
_savedGame->objetomoinventoryObjectNamehila = _inventoryObjectName;
|
|
_savedGame->characterName = _characterName;
|
|
|
|
for (int i = 0; i < kRoutePointCount; i++) {
|
|
_savedGame->mainRoute[i].x = _mainRoute[i].x;
|
|
_savedGame->mainRoute[i].y = _mainRoute[i].y;
|
|
}
|
|
|
|
for (int i = 0; i < 300; i++) {
|
|
_savedGame->trajectory[i].x = _trajectory[i].x;
|
|
_savedGame->trajectory[i].y = _trajectory[i].y;
|
|
}
|
|
|
|
for (int i = 0; i < kCharacterCount; i++) {
|
|
_savedGame->firstTimeTopicA[i] = _firstTimeTopicA[i];
|
|
_savedGame->firstTimeTopicB[i] = _firstTimeTopicB[i];
|
|
_savedGame->firstTimeTopicC[i] = _firstTimeTopicC[i];
|
|
_savedGame->bookTopic[i] = _bookTopic[i];
|
|
_savedGame->mintTopic[i] = _mintTopic[i];
|
|
}
|
|
for (int i = 0; i < 5; i++) {
|
|
_savedGame->caves[i] = _caves[i];
|
|
_savedGame->firstList[i] = _firstList[i];
|
|
_savedGame->secondList[i] = _secondList[i];
|
|
}
|
|
for (int i = 0; i < 4; i++) {
|
|
_savedGame->niche[0][i] = _niche[0][i];
|
|
_savedGame->niche[1][i] = _niche[1][i];
|
|
}
|
|
return _savedGame;
|
|
}
|
|
|
|
void TotEngine::loadGame(SavedGame *game) {
|
|
clearAnimation();
|
|
clearScreenLayers();
|
|
|
|
_trajectoryLength = game->trajectoryLength;
|
|
_currentTrajectoryIndex = game->currentTrajectoryIndex;
|
|
_backpackObjectCode = game->backpackObjectCode;
|
|
_sound->_rightSfxVol = game->rightSfxVol;
|
|
_sound->_leftSfxVol = game->leftSfxVol;
|
|
_sound->_musicVolRight = game->musicVolRight;
|
|
_sound->_musicVolLeft = game->musicVolLeft;
|
|
_oldGridX = game->oldGridX;
|
|
_oldGridY = game->oldGridY;
|
|
_secondaryAnimation.depth = game->secAnimDepth;
|
|
_secondaryAnimation.dir = game->secAnimDir;
|
|
_secondaryAnimation.posx = game->secAnimX;
|
|
_secondaryAnimation.posy = game->secAnimY;
|
|
_iframe2 = game->secAnimIFrame;
|
|
_currentZone = game->currentZone;
|
|
_targetZone = game->targetZone;
|
|
_oldTargetZone = game->oldTargetZone;
|
|
_inventoryPosition = game->inventoryPosition;
|
|
_actionCode = game->actionCode;
|
|
_oldActionCode = game->oldActionCode;
|
|
_trajectorySteps = game->steps;
|
|
_doorIndex = game->doorIndex;
|
|
_charFacingDirection = game->characterFacingDir;
|
|
_iframe = game->iframe;
|
|
if (game->gamePart != _gamePart) {
|
|
_gamePart = game->gamePart;
|
|
for (int i = 0; i < kInventoryIconCount; i++) {
|
|
free(_inventoryIconBitmaps[i]);
|
|
}
|
|
loadInventory();
|
|
}
|
|
_isSealRemoved = game->isSealRemoved;
|
|
_obtainedList1 = game->obtainedList1;
|
|
_obtainedList2 = game->obtainedList2;
|
|
_list1Complete = game->list1Complete;
|
|
_list2Complete = game->list2Complete;
|
|
_isVasePlaced = game->isVasePlaced;
|
|
_isScytheTaken = game->isScytheTaken;
|
|
if (_cpCounter > 24)
|
|
showError(274);
|
|
_isTridentTaken = game->isTridentTaken;
|
|
_isPottersWheelDelivered = game->isPottersWheelDelivered;
|
|
_isMudDelivered = game->isMudDelivered;
|
|
_isGreenDevilDelivered = game->isGreenDevilDelivered;
|
|
_isRedDevilCaptured = game->isRedDevilCaptured;
|
|
_isPottersManualDelivered = game->isPottersManualDelivered;
|
|
_isCupboardOpen = game->isCupboardOpen;
|
|
_isChestOpen = game->isChestOpen;
|
|
_isTVOn = game->isTVOn;
|
|
_isTrapSet = game->isTrapSet;
|
|
for (int i = 0; i < kInventoryIconCount; i++) {
|
|
_inventory[i].bitmapIndex = game->mobj[i].bitmapIndex;
|
|
_inventory[i].code = game->mobj[i].code;
|
|
_inventory[i].objectName = game->mobj[i].objectName;
|
|
}
|
|
_element1 = game->element1;
|
|
_element2 = game->element2;
|
|
_characterPosX = game->characterPosX;
|
|
_characterPosY = game->characterPosY;
|
|
_xframe2 = game->xframe2;
|
|
_yframe2 = game->yframe2;
|
|
_oldInventoryObjectName = game->oldInventoryObjectName;
|
|
_inventoryObjectName = game->objetomoinventoryObjectNamehila;
|
|
_characterName = game->characterName;
|
|
for (int i = 0; i < kRoutePointCount; i++) {
|
|
_mainRoute[i].x = game->mainRoute[i].x;
|
|
_mainRoute[i].y = game->mainRoute[i].y;
|
|
}
|
|
for (int indiaux = 0; indiaux < 300; indiaux++) {
|
|
_trajectory[indiaux].x = game->trajectory[indiaux].x;
|
|
_trajectory[indiaux].y = game->trajectory[indiaux].y;
|
|
}
|
|
for (int i = 0; i < kCharacterCount; i++) {
|
|
_firstTimeTopicA[i] = game->firstTimeTopicA[i];
|
|
_firstTimeTopicB[i] = game->firstTimeTopicB[i];
|
|
_firstTimeTopicC[i] = game->firstTimeTopicC[i];
|
|
_bookTopic[i] = game->bookTopic[i];
|
|
_mintTopic[i] = game->mintTopic[i];
|
|
}
|
|
for (int i = 0; i < 5; i++) {
|
|
_caves[i] = game->caves[i];
|
|
_firstList[i] = game->firstList[i];
|
|
_secondList[i] = game->secondList[i];
|
|
}
|
|
for (int i = 0; i < 4; i++) {
|
|
_niche[0][i] = game->niche[0][i];
|
|
_niche[1][i] = game->niche[1][i];
|
|
}
|
|
|
|
_graphics->totalFadeOut(0);
|
|
_screen->clear();
|
|
_graphics->loadPaletteFromFile("DEFAULT");
|
|
loadScreenData(game->roomCode);
|
|
|
|
switch (_currentRoomData->code) {
|
|
case 2: {
|
|
if (_isTVOn)
|
|
_sound->autoPlayVoc("PARASITO", 355778, 20129);
|
|
else
|
|
loadTV();
|
|
_sound->setSfxVolume(_sound->_leftSfxVol, _sound->_rightSfxVol);
|
|
} break;
|
|
case 4: {
|
|
_sound->loadVoc("GOTA", 140972, 1029);
|
|
_sound->setSfxVolume(_sound->_leftSfxVol, _sound->_rightSfxVol);
|
|
} break;
|
|
case 5: {
|
|
_sound->setSfxVolume(_sound->_leftSfxVol, 0);
|
|
_sound->autoPlayVoc("CALDERA", 6433, 15386);
|
|
} break;
|
|
case 6: {
|
|
_sound->setSfxVolume(_sound->_leftSfxVol, _sound->_rightSfxVol);
|
|
_sound->autoPlayVoc("CALDERA", 6433, 15386);
|
|
} break;
|
|
case 17: {
|
|
if (_bookTopic[0] == true && _currentRoomData->animationFlag)
|
|
disableSecondAnimation();
|
|
} break;
|
|
case 20: {
|
|
switch (_niche[0][_niche[0][3]]) {
|
|
case 0:
|
|
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(4);
|
|
break;
|
|
case 561:
|
|
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(5);
|
|
break;
|
|
case 563:
|
|
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(6);
|
|
break;
|
|
case 615:
|
|
_currentRoomData->screenObjectIndex[9]->objectName = getObjectName(7);
|
|
break;
|
|
}
|
|
} break;
|
|
case 23: {
|
|
_sound->autoPlayVoc("Fuente", 0, 0);
|
|
_sound->setSfxVolume(_sound->_leftSfxVol, _sound->_rightSfxVol);
|
|
} break;
|
|
case 24: {
|
|
switch (_niche[1][_niche[1][3]]) {
|
|
case 0:
|
|
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(4);
|
|
break;
|
|
case 561:
|
|
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(5);
|
|
break;
|
|
case 615:
|
|
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(7);
|
|
break;
|
|
case 622:
|
|
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(8);
|
|
break;
|
|
case 623:
|
|
_currentRoomData->screenObjectIndex[8]->objectName = getObjectName(9);
|
|
break;
|
|
}
|
|
if (_isTrapSet) {
|
|
_currentRoomData->animationFlag = true;
|
|
loadAnimation(_currentRoomData->animationName);
|
|
_iframe2 = 0;
|
|
_currentSecondaryTrajectoryIndex = 1;
|
|
_currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].x = 214 - 15;
|
|
_currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].y = 115 - 42;
|
|
_secondaryAnimation.dir = _currentRoomData->secondaryAnimDirections[_currentSecondaryTrajectoryIndex - 1];
|
|
_secondaryAnimation.posx = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].x;
|
|
_secondaryAnimation.posy = _currentRoomData->secondaryAnimTrajectory[_currentSecondaryTrajectoryIndex - 1].y;
|
|
_secondaryAnimation.depth = 14;
|
|
|
|
for (int i = 0; i < _maxXGrid; i++)
|
|
for (int j = 0; j < _maxYGrid; j++) {
|
|
if (_maskGridSecondaryAnim[i][j] > 0)
|
|
_currentRoomData->walkAreasGrid[_oldposx + i][_oldposy + j] = _maskGridSecondaryAnim[i][j];
|
|
if (_maskMouseSecondaryAnim[i][j] > 0)
|
|
_currentRoomData->mouseGrid[_oldposx + i][_oldposy + j] = _maskMouseSecondaryAnim[i][j];
|
|
}
|
|
}
|
|
assembleScreen();
|
|
} break;
|
|
}
|
|
|
|
drawInventoryMask();
|
|
_inventoryPosition = 0;
|
|
drawInventory();
|
|
if (_isRedDevilCaptured == false && _currentRoomData->code == 24 && _isTrapSet == false)
|
|
runaroundRed();
|
|
_graphics->sceneTransition(false, _sceneBackground);
|
|
|
|
_saveAllowed = true;
|
|
}
|
|
|
|
const int kMaxSaveSlots = 100;
|
|
|
|
Common::String drawAndSelectSaves(int pageNumber, const Common::HashMap<int, SaveStateDescriptor> &saveMap, uint selectedSlot) {
|
|
g_engine->_mouse->hide();
|
|
const char *availableText = getHardcodedTextsByCurrentLanguage()[11];
|
|
ExtendedSavegameHeader header;
|
|
int selectedGame = selectedSlot + pageNumber * 6;
|
|
Common::String selectedGameDesc = "";
|
|
for (uint i = 0; i < 6; i++) {
|
|
int saveSlot = i + pageNumber * 6;
|
|
int color = saveSlot == selectedGame ? 255 : 253;
|
|
bar(60, 31 + (i * 15), 259, 39 + (i * 15), 251);
|
|
if (saveSlot >= kMaxSaveSlots) {
|
|
continue;
|
|
;
|
|
}
|
|
Common::String desc = "";
|
|
if (saveMap.contains(saveSlot)) {
|
|
desc = saveMap[saveSlot].getDescription();
|
|
if (saveSlot == selectedGame) {
|
|
selectedGameDesc = saveMap[saveSlot].getDescription();
|
|
}
|
|
}
|
|
if (desc.empty() == false) {
|
|
euroText(65, 29 + (i * 15), desc, color);
|
|
} else {
|
|
euroText(65, 29 + (i * 15), Common::String::format(availableText, saveSlot), color);
|
|
}
|
|
}
|
|
|
|
g_engine->_mouse->show();
|
|
return selectedGameDesc;
|
|
}
|
|
|
|
void TotEngine::originalSaveLoadScreen() {
|
|
uint oldMouseX, oldMouseY;
|
|
int selectedSlot = 1;
|
|
bool modified = false;
|
|
Common::String saveName = "";
|
|
|
|
bool exitSaveLoadMenu = false;
|
|
oldMouseX = _mouse->mouseX;
|
|
oldMouseY = _mouse->mouseY;
|
|
_mouse->hide();
|
|
|
|
uint menuBgSize = imagesize(20, 10, 300, 120);
|
|
byte *menuBgPointer = (byte *)malloc(menuBgSize);
|
|
_graphics->getImg(20, 10, 300, 120, menuBgPointer);
|
|
|
|
for (int i = 0; i < 6; i++) {
|
|
uint textY = i + 1;
|
|
buttonBorder((120 - (textY * 10)), (80 - (textY * 10)), (200 + (textY * 10)), (60 + (textY * 10)), 251, 251, 251, 251, 0);
|
|
}
|
|
drawMenu(2); // 220 x 110 at xmenu = 50;ymenu = 10;
|
|
// 50, 10, 270, 120
|
|
// Arrows are 20, 18
|
|
drawLeftArrow(20, 65);
|
|
line(20, 65, 39, 65, 255);
|
|
line(20, 65, 20, 80, 255);
|
|
line(40, 66, 40, 82, 249);
|
|
line(40, 82, 21, 82, 249);
|
|
drawRightArrow(280, 65);
|
|
line(280, 65, 299, 65, 255);
|
|
line(280, 65, 280, 80, 255);
|
|
line(300, 66, 300, 82, 249);
|
|
line(300, 82, 292, 82, 249);
|
|
|
|
if (!_saveAllowed) {
|
|
bar(61, 15, 122, 23, 253);
|
|
bar(201, 15, 259, 23, 253);
|
|
}
|
|
|
|
int pageNumber = 0;
|
|
SaveStateList listSaves = getMetaEngine()->listSaves(_targetName.c_str());
|
|
|
|
Common::HashMap<int, SaveStateDescriptor> saveMap;
|
|
|
|
// Iterate and populate
|
|
for (const SaveStateDescriptor &desc : listSaves) {
|
|
int slot = desc.getSaveSlot();
|
|
saveMap[slot] = desc;
|
|
}
|
|
|
|
saveName = drawAndSelectSaves(pageNumber, saveMap, selectedSlot);
|
|
|
|
if (_cpCounter2 > 17)
|
|
showError(274);
|
|
_mouse->mouseX = 150;
|
|
_mouse->mouseY = 60;
|
|
_mouse->mouseMaskIndex = 1;
|
|
_mouse->setMouseArea(Common::Rect(13, 13, 293, 105));
|
|
_mouse->warpMouse(1, 150, 60);
|
|
|
|
do {
|
|
bool mouseClicked = false;
|
|
bool keyPressed = false;
|
|
Common::Event lastKeyboardEvent = Common::Event();
|
|
do {
|
|
_chrono->updateChrono();
|
|
if (_chrono->_gameTick) {
|
|
_mouse->animateMouseIfNeeded();
|
|
}
|
|
_events->pollEvent();
|
|
if (_events->_leftMouseButton || _events->_rightMouseButton) {
|
|
mouseClicked = true;
|
|
} else if (_events->_keyPressed) {
|
|
keyPressed = true;
|
|
lastKeyboardEvent = _events->_lastKeyEvent;
|
|
}
|
|
|
|
_screen->update();
|
|
g_system->delayMillis(10);
|
|
} while (!keyPressed && !mouseClicked && !shouldQuit());
|
|
|
|
if (mouseClicked) {
|
|
if (_mouse->mouseX > 13 && _mouse->mouseX < 33 && _mouse->mouseY >= 58 && _mouse->mouseY <= 73) { // Left arrow
|
|
|
|
if (pageNumber > 0)
|
|
pageNumber--;
|
|
else
|
|
_sound->beep(100, 300);
|
|
saveName = drawAndSelectSaves(pageNumber, saveMap, selectedSlot);
|
|
} else if (_mouse->mouseX > 273 && _mouse->mouseX < 293 && _mouse->mouseY >= 58 && _mouse->mouseY <= 73) { // Right arrow
|
|
|
|
if (pageNumber < kMaxSaveSlots / 6)
|
|
pageNumber++;
|
|
else
|
|
_sound->beep(100, 300);
|
|
saveName = drawAndSelectSaves(pageNumber, saveMap, selectedSlot);
|
|
} else if (_mouse->mouseY >= 13 && _mouse->mouseY <= 16) {
|
|
if (_mouse->mouseX >= 54 && _mouse->mouseX <= 124) { // Save
|
|
if (selectedSlot > 0 && _saveAllowed && saveName != "") {
|
|
saveGameState(selectedSlot + pageNumber * 6, saveName, false);
|
|
_graphics->putImg(20, 10, menuBgPointer);
|
|
exitSaveLoadMenu = true;
|
|
selectedSlot = -1;
|
|
} else {
|
|
_sound->beep(100, 300);
|
|
}
|
|
} else if (_mouse->mouseX >= 130 && _mouse->mouseX <= 194) {
|
|
if (selectedSlot >= 0 && !modified) { // Load
|
|
if (selectedSlot < (int)listSaves.size()) {
|
|
_mouse->hide();
|
|
_graphics->putImg(20, 10, menuBgPointer);
|
|
free(menuBgPointer);
|
|
if (_saveAllowed) {
|
|
clearAnimation();
|
|
clearScreenLayers();
|
|
}
|
|
loadGameState(selectedSlot + pageNumber * 6);
|
|
_mouse->mouseX = oldMouseX;
|
|
_mouse->mouseY = oldMouseY;
|
|
|
|
_mouse->show();
|
|
_mouse->setMouseArea(Common::Rect(0, 0, 305, 185));
|
|
exitSaveLoadMenu = true;
|
|
selectedSlot = -1;
|
|
|
|
return;
|
|
} else {
|
|
_sound->beep(100, 300);
|
|
}
|
|
} else {
|
|
_sound->beep(100, 300);
|
|
saveName = drawAndSelectSaves(pageNumber, saveMap, selectedSlot);
|
|
_mouse->show();
|
|
}
|
|
} else if (_mouse->mouseClickX >= 200 && _mouse->mouseClickX <= 250) { // Exit
|
|
if (_inGame && _saveAllowed) {
|
|
_graphics->putImg(20, 10, menuBgPointer);
|
|
exitSaveLoadMenu = true;
|
|
selectedSlot = -1;
|
|
} else {
|
|
_sound->beep(100, 300);
|
|
}
|
|
}
|
|
} else {
|
|
if (_mouse->mouseClickY >= 24 && _mouse->mouseClickY <= 32) {
|
|
if (0 + pageNumber * 6 >= kMaxSaveSlots) {
|
|
_sound->beep(100, 300);
|
|
} else {
|
|
selectedSlot = 0;
|
|
modified = false;
|
|
}
|
|
} else if (_mouse->mouseClickY >= 39 && _mouse->mouseClickY <= 47) {
|
|
if (1 + pageNumber * 6 >= kMaxSaveSlots) {
|
|
_sound->beep(100, 300);
|
|
} else {
|
|
selectedSlot = 1;
|
|
modified = false;
|
|
}
|
|
} else if (_mouse->mouseClickY >= 54 && _mouse->mouseClickY <= 62) {
|
|
if (2 + pageNumber * 6 >= kMaxSaveSlots) {
|
|
_sound->beep(100, 300);
|
|
} else {
|
|
selectedSlot = 2;
|
|
modified = false;
|
|
}
|
|
} else if (_mouse->mouseClickY >= 69 && _mouse->mouseClickY <= 77) {
|
|
if (3 + pageNumber * 6 >= kMaxSaveSlots) {
|
|
_sound->beep(100, 300);
|
|
} else {
|
|
selectedSlot = 3;
|
|
modified = false;
|
|
}
|
|
} else if (_mouse->mouseClickY >= 84 && _mouse->mouseClickY <= 92) {
|
|
if (4 + pageNumber * 6 >= kMaxSaveSlots) {
|
|
_sound->beep(100, 300);
|
|
} else {
|
|
selectedSlot = 4;
|
|
modified = false;
|
|
}
|
|
} else if (_mouse->mouseClickY >= 99 && _mouse->mouseClickY <= 107) {
|
|
if (5 + pageNumber * 6 >= kMaxSaveSlots) {
|
|
_sound->beep(100, 300);
|
|
} else {
|
|
selectedSlot = 5;
|
|
modified = false;
|
|
}
|
|
}
|
|
saveName = drawAndSelectSaves(pageNumber, saveMap, selectedSlot);
|
|
}
|
|
}
|
|
|
|
if (keyPressed && _saveAllowed) {
|
|
_mouse->hide();
|
|
byte ytext = 29 + (selectedSlot * 15);
|
|
readAlphaGraphSmall(saveName, 30, 65, ytext, 251, 254, lastKeyboardEvent);
|
|
modified = true;
|
|
_mouse->show();
|
|
keyPressed = false;
|
|
}
|
|
} while (!exitSaveLoadMenu && !shouldQuit());
|
|
_mouse->mouseX = oldMouseX;
|
|
_mouse->mouseY = oldMouseY;
|
|
_mouse->warpMouse(_mouse->mouseMaskIndex, _mouse->mouseX, _mouse->mouseY);
|
|
free(menuBgPointer);
|
|
_mouse->setMouseArea(Common::Rect(0, 0, 305, 185));
|
|
}
|
|
|
|
} // End of namespace Tot
|