ScummVM
saveload_mr.cpp
Go to the documentation of this file.
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "common/endian.h"
24 #include "common/savefile.h"
25 #include "common/substream.h"
26 #include "common/system.h"
27 
28 #include "kyra/engine/kyra_mr.h"
29 #include "kyra/engine/timer.h"
30 
31 namespace Kyra {
32 
33 Common::Error KyraEngine_MR::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumb) {
34  const char *fileName = getSavegameFilename(slot);
35 
36  Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb);
37  if (!out)
38  return _saveFileMan->getError();
39 
40  _timer->saveDataToFile(*out);
41 
42  out->writeUint32BE(sizeof(_flagsTable));
43  out->write(_flagsTable, sizeof(_flagsTable));
44 
48  out->writeByte(_album.curPage);
49  out->writeSint16BE(_score);
52  for (int i = 0; i < 30; ++i)
53  out->write(_conversationState[i], 30);
54  out->write(_newSceneDlgState, 40);
55  for (int i = 0; i < 100; ++i)
56  out->writeSint16BE(_hiddenItems[i]);
57  out->write(_scoreFlagTable, 26);
58 
65  for (int i = 0; i < 10; ++i)
73 
74  for (int i = 0; i < 50; ++i) {
75  out->writeSint16BE(_itemList[i].id);
76  out->writeUint16BE(_itemList[i].sceneId);
77  out->writeSint16BE(_itemList[i].x);
78  out->writeSint16BE(_itemList[i].y);
79  }
80 
81  for (int i = 0; i < 88; ++i) {
82  out->write(_talkObjectList[i].filename, 13);
83  out->writeByte(_talkObjectList[i].sceneAnim);
84  out->writeByte(_talkObjectList[i].sceneScript);
87  out->writeByte(_talkObjectList[i].color);
88  out->writeByte(_talkObjectList[i].sceneId);
89  }
90 
91  for (int i = 0; i < 98; ++i) {
92  out->write(_sceneList[i].filename1, 10);
93  out->write(_sceneList[i].filename2, 10);
95  out->writeUint16BE(_sceneList[i].exit2);
96  out->writeUint16BE(_sceneList[i].exit3);
97  out->writeUint16BE(_sceneList[i].exit4);
98  out->writeByte(_sceneList[i].flags);
99  out->writeByte(_sceneList[i].sound);
100  }
101 
107 
108  out->finalize();
109 
110  // check for errors
111  if (out->err()) {
112  warning("Can't write file '%s'. (Disk full?)", fileName);
113  return Common::kUnknownError;
114  } else {
115  debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName);
116  }
117 
118  delete out;
119  return Common::kNoError;
120 }
121 
123  const char *fileName = getSavegameFilename(slot);
124 
126  Common::InSaveFile *saveFile = openSaveForReading(fileName, header);
127  if (!saveFile) {
128  showMessageFromCCode(17, 0xB3, 0);
129  snd_playSoundEffect(0x0D, 0xC8);
130  return Common::kUnknownError;
131  }
132 
133  if (header.originalSave)
134  warning("Trying to load savegame from original interpreter, while this is possible, it is not officially supported");
135 
136  if (_inventoryState) {
138  restorePage3();
139  drawAnimObjects();
140  _inventoryState = true;
142  hideInventory();
143  }
144 
145  _deathHandler = -1;
147  _lastMusicCommand = -1;
148 
149  int curShapes = _characterShapeFile;
150 
151  Common::SeekableSubReadStreamEndian in(saveFile, saveFile->pos(), saveFile->size(), !header.originalSave, DisposeAfterUse::YES);
152 
153  _screen->hideMouse();
154 
155  if (!header.originalSave) {
156  _timer->loadDataFromFile(in, header.version);
157 
158  uint32 flagsSize = in.readUint32BE();
159  assert(flagsSize <= sizeof(_flagsTable));
160  in.read(_flagsTable, flagsSize);
161  }
162 
163  _lastMusicCommand = in.readSint16();
164  _currentChapter = in.readByte();
165  _characterShapeFile = in.readByte();
166 
167  if (header.version >= 12 || header.originalSave)
168  _album.curPage = in.readByte();
169  if (header.originalSave)
170  in.readByte();
171 
172  _score = in.readSint16();
173  _scoreMax = in.readSint16();
174  _malcolmsMood = in.readByte();
175 
176  if (header.originalSave)
177  in.seek(8, SEEK_CUR);
178 
179  for (int i = 0; i < 30; ++i)
180  in.read(_conversationState[i], 30);
181 
182  if (!header.originalSave) {
183  in.read(_newSceneDlgState, 40);
184  } else {
185  for (int i = 0; i < 40; ++i)
186  _newSceneDlgState[i] = in.readUint16();
187  }
188 
189  for (int i = 0; i < 100; ++i)
190  _hiddenItems[i] = in.readSint16();
191 
192  if (header.originalSave)
193  in.read(_flagsTable, 69);
194  in.read(_scoreFlagTable, 26);
195 
196  _mainCharacter.sceneId = in.readUint16();
197  _mainCharacter.dlgIndex = in.readSint16();
198  _mainCharacter.height = in.readByte();
199  _mainCharacter.facing = in.readByte();
200  _mainCharacter.animFrame = in.readUint16();
201  if (!header.originalSave) {
202  _mainCharacter.walkspeed = in.readByte();
203  } else {
204  in.seek(2, SEEK_CUR);
205  _mainCharacter.walkspeed = in.readUint32();
206  }
207  for (int i = 0; i < 10; ++i)
208  _mainCharacter.inventory[i] = in.readUint16();
209  _mainCharacter.x1 = in.readSint16();
210  _mainCharacter.y1 = in.readSint16();
211  _mainCharacter.x2 = in.readSint16();
212  _mainCharacter.y2 = in.readSint16();
213  _mainCharacter.x3 = in.readSint16();
214  _mainCharacter.y3 = in.readSint16();
215 
216  for (int i = 0; i < 50; ++i) {
217  _itemList[i].id = in.readSint16();
218  _itemList[i].sceneId = in.readUint16();
219  _itemList[i].x = in.readSint16();
220  _itemList[i].y = in.readSint16();
221  if (header.version <= 9 || header.originalSave)
222  in.readUint16();
223  }
224 
225  for (int i = 0; i < 88; ++i) {
226  in.read(_talkObjectList[i].filename, 13);
227  _talkObjectList[i].sceneAnim = in.readByte();
228  _talkObjectList[i].sceneScript = in.readByte();
229  _talkObjectList[i].x = in.readSint16();
230  _talkObjectList[i].y = in.readSint16();
231  _talkObjectList[i].color = in.readByte();
232  if (header.version >= 13 || header.originalSave)
233  _talkObjectList[i].sceneId = in.readByte();
234  }
235 
236  for (int i = 0; i < 98; ++i) {
237  if (!header.originalSave) {
238  in.read(_sceneList[i].filename1, 10);
239  } else {
240  in.read(_sceneList[i].filename1, 9);
241  _sceneList[i].filename1[9] = 0;
242  }
243 
244  if (!header.originalSave) {
245  in.read(_sceneList[i].filename2, 10);
246  } else {
247  in.read(_sceneList[i].filename2, 9);
248  _sceneList[i].filename2[9] = 0;
249  }
250 
251  _sceneList[i].exit1 = in.readUint16();
252  _sceneList[i].exit2 = in.readUint16();
253  _sceneList[i].exit3 = in.readUint16();
254  _sceneList[i].exit4 = in.readUint16();
255  _sceneList[i].flags = in.readByte();
256  _sceneList[i].sound = in.readByte();
257  }
258 
259  _itemInHand = in.readSint16();
260 
261  if (header.originalSave) {
262  uint32 currentTime = _system->getMillis();
263 
264  for (int i = 0; i < 6; ++i)
265  _timer->setDelay(i, in.readSint32LE());
266 
267  for (int i = 0; i < 6; ++i) {
268  if (in.readUint16LE())
269  _timer->enable(i);
270  else
271  _timer->disable(i);
272  }
273 
274  for (int i = 0; i < 6; ++i)
275  _timer->setNextRun(i, currentTime + (in.readUint32LE() * _tickLength));
276 
277  _timer->resetNextRun();
278  }
279 
280  _sceneExit1 = in.readUint16();
281  _sceneExit2 = in.readUint16();
282  _sceneExit3 = in.readUint16();
283  _sceneExit4 = in.readUint16();
284 
285  if (saveFile->err() || saveFile->eos()) {
286  warning("Load failed ('%s', '%s').", fileName, header.description.c_str());
287  return Common::kUnknownError;
288  } else {
289  debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str());
290  }
291 
292  _loadingState = true;
294  _loadingState = false;
295 
296  if (curShapes != _characterShapeFile)
298 
302  _badConscienceShown = false;
303  _badConsciencePosition = false;
304  _goodConscienceShown = false;
305  _goodConsciencePosition = false;
306 
309 
312  else if (_lastMusicCommand == -1)
314 
315  while (!_screen->isMouseVisible())
316  _screen->showMouse();
317 
319  _shownMessage = " ";
320  _restoreCommandLine = false;
321 
322  // We didn't explicitly set the walk speed, but it's saved as part of
323  // the _timers array, so we need to re-sync it with _configWalkspeed.
325 
326  return Common::kNoError;
327 }
328 
329 } // End of namespace Kyra
void resetNextRun()
Definition: timer.cpp:139
bool _unkSceneScreenFlag1
Definition: kyra_v2.h:361
void exit1(L9BYTE *d4, L9BYTE *d5p, L9BYTE d6, L9BYTE d7)
void saveDataToFile(Common::WriteStream &file) const
Definition: timer.cpp:292
bool _badConsciencePosition
Definition: kyra_mr.h:477
Character _mainCharacter
Definition: kyra_v2.h:330
virtual uint32 write(const void *dataPtr, uint32 dataSize)
Write data into the stream.
Definition: savefile.cpp:51
Abool in(Aword obj, Aword cnt)
Definition: exe.cpp:705
This is a SeekableSubReadStream subclass which adds non-endian read methods whose endianness is set o...
Definition: substream.h:89
unsigned int uint32
Definition: cdtypes.h:26
Common::SeekableReadStream * openSaveForReading(const char *filename, SaveHeader &header, bool checkID=true)
Definition: saveload.cpp:138
Common::String description
Definition: kyra_v1.h:402
bool _goodConsciencePosition
Definition: kyra_mr.h:486
#define SEEK_CUR
Definition: gba_nds_fat.h:77
A class which allows game engines to save game state data.
Definition: savefile.h:47
Screen_MR * _screen
Definition: kyra_mr.h:82
uint8 _configWalkspeed
Definition: kyra_v1.h:299
#define assert(s)
Definition: portdefs.h:77
debug level for common "KyraEngine(_v#)" functions && "TextDisplayer" functions
Definition: kyra_v1.h:154
bool isMouseVisible() const
Definition: screen.cpp:3048
virtual bool eos() const =0
Returns true if a read failed because the stream end has been reached.
void warning(const char *s,...)
Definition: textconsole.cpp:49
void setWalkspeed(uint8)
Definition: timer_mr.cpp:82
u16 flags
Definition: zipreader.h:215
SceneDesc * _sceneList
Definition: kyra_v2.h:174
void disable(uint8 id)
Definition: timer.cpp:238
int y
Definition: dialogs.cpp:409
FORCEINLINE void writeSint16BE(int16 value)
Definition: stream.h:168
Sound * sound()
Definition: kyra_v1.h:199
uint16 _sceneExit1
Definition: kyra_v2.h:178
const char * saveFile
Definition: savegame.cpp:45
struct Kyra::KyraEngine_MR::Album _album
void debugC(int level, uint32 debugChannels, const char *s,...)
Definition: debug.cpp:205
bool _goodConscienceShown
Definition: kyra_mr.h:484
int16 _lastMusicCommand
Definition: kyra_v1.h:360
void setDelay(uint8 id, int32 countdown)
Definition: timer.cpp:162
virtual bool err() const
Returns true if an I/O failure occurred.
Definition: stream.h:49
virtual bool err() const
Returns true if an I/O failure occurred.
Definition: savefile.cpp:38
const char * getSavegameFilename(int num)
Definition: saveload.cpp:232
bool _badConscienceShown
Definition: kyra_mr.h:475
void setNextRun(uint8 id, uint32 nextRun)
Definition: timer.cpp:179
byte _newSceneDlgState[40]
Definition: kyra_mr.h:439
Common::OutSaveFile * openSaveForWriting(const char *filename, const char *saveName, const Graphics::Surface *thumbnail) const
Definition: saveload.cpp:187
void writeUint16BE(uint16 value)
Definition: stream.h:141
AcdHdr * header
Definition: main.cpp:50
Item _hiddenItems[100]
Definition: kyra_v2.h:294
TimerManager * _timer
Definition: kyra_v1.h:268
OSystem * _system
Definition: engine.h:59
Common::SaveFileManager * _saveFileMan
Definition: engine.h:65
void showMessageFromCCode(int string, uint8 c0, int)
Definition: gui_mr.cpp:122
virtual uint32 getMillis(bool skipRecord=false)=0
Get the number of milliseconds since the program was started.
const char * c_str() const
Definition: str.h:208
void snd_playWanderScoreViaMap(int track, int force)
Definition: kyra_mr.cpp:405
Endian conversion and byteswap conversion functions or macros.
Catch-all error, used if no other error code matches.
Definition: error.h:68
void hideMouse()
Definition: screen.cpp:3029
const char * _shownMessage
Definition: kyra_mr.h:242
void loadDataFromFile(Common::SeekableReadStream &file, int version)
Definition: timer.cpp:246
void refreshAnimObjects(int force)
void showMouse()
Definition: screen.cpp:3034
uint16 _sceneExit4
Definition: kyra_v2.h:178
void setCommandLineRestoreTimer(int secs)
Definition: timer_mr.cpp:91
void writeByte(byte value)
Definition: stream.h:118
Common::String filename
Definition: action.cpp:479
No error occurred.
Definition: error.h:45
virtual Error getError()
Returns the last occurred error code.
Definition: savefile.h:108
Common::Error saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail)
Definition: saveload_mr.cpp:33
An Error instance pairs an error code with string description providing more details about the error...
Definition: error.h:77
ItemDefinition * _itemList
Definition: kyra_v2.h:296
void enterNewScene(uint16 scene, int facing, int unk1, int unk2, int unk3)
Definition: scene_mr.cpp:32
This is the namespace of the Kyra engine.
Definition: chargen.cpp:37
virtual int32 size() const =0
Obtains the total size of the stream, measured in bytes.
An arbitrary graphics surface, which can be the target (or source) of blit operations, font rendering, etc.
Definition: surface.h:42
void loadCharacterShapes(int newShapes)
Definition: kyra_mr.cpp:720
void hideInventory()
Definition: gui_mr.cpp:240
void enable(uint8 id)
Definition: timer.cpp:230
void setHandItem(Item item)
Definition: items_v2.cpp:84
uint16 _sceneExit3
Definition: kyra_v2.h:178
uint16 _tickLength
Definition: kyra_v1.h:311
uint16 _sceneExit2
Definition: kyra_v2.h:178
virtual int32 pos() const =0
Obtains the current value of the stream position indicator of the stream.
virtual void finalize()
Finalize and close this stream.
Definition: savefile.cpp:42
void writeUint32BE(uint32 value)
Definition: stream.h:146
Common::Error loadGameState(int slot)
Load a game state.
bool _restoreCommandLine
Definition: kyra_mr.h:243
int8 _scoreFlagTable[26]
Definition: kyra_mr.h:529
Interface for a seekable & readable data stream.
Definition: stream.h:561
int8 _conversationState[30][30]
Definition: kyra_mr.h:440
void updateCharacterAnim(int charId)
void snd_playSoundEffect(int item, int volume)
Definition: kyra_mr.cpp:441
uint8 _flagsTable[100]
Definition: kyra_v1.h:353
TalkObject * _talkObjectList
Definition: kyra_mr.h:412