PageRenderTime 63ms CodeModel.GetById 40ms RepoModel.GetById 1ms app.codeStats 0ms

/engines/trecision/saveload.cpp

https://github.com/athrxx/scummvm
C++ | 467 lines | 337 code | 103 blank | 27 comment | 56 complexity | e7dc46189256f9fb55089f1604155ed8 MD5 | raw 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 modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. #include "gui/saveload.h"
  20. #include "common/config-manager.h"
  21. #include "common/savefile.h"
  22. #include "common/translation.h"
  23. #include "trecision/actor.h"
  24. #include "trecision/animmanager.h"
  25. #include "trecision/dialog.h"
  26. #include "trecision/graphics.h"
  27. #include "trecision/logic.h"
  28. #include "trecision/pathfinding3d.h"
  29. #include "trecision/sound.h"
  30. #include "trecision/trecision.h"
  31. #include "trecision/video.h"
  32. namespace Trecision {
  33. void TrecisionEngine::loadSaveSlots(Common::StringArray &saveNames) {
  34. for (uint i = 0; i < ICONSHOWN; ++i) {
  35. SaveStateDescriptor saveState = getMetaEngine()->querySaveMetaInfos(_targetName.c_str(), i + 1);
  36. if (saveState.getSaveSlot() == -1) {
  37. saveNames.push_back(_sysText[kMessageEmptySpot]);
  38. _inventory.push_back(EMPTYSLOT);
  39. } else {
  40. saveNames.push_back(saveState.getDescription());
  41. _inventory.push_back(EMPTYSLOT + i + 1);
  42. _graphicsMgr->setSaveSlotThumbnail(i, saveState.getThumbnail());
  43. }
  44. }
  45. refreshInventory(0, 0);
  46. }
  47. bool TrecisionEngine::dataSave() {
  48. const Common::Array<byte> savedInventory = _inventory;
  49. const uint8 savedIconBase = _iconBase;
  50. Common::StringArray saveNames;
  51. saveNames.reserve(MAXSAVEFILE);
  52. uint16 posx, LenText;
  53. bool ret = true;
  54. _actor->actorStop();
  55. _pathFind->nextStep();
  56. if (!ConfMan.getBool("originalsaveload")) {
  57. GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
  58. int saveSlot = dialog->runModalWithCurrentTarget();
  59. Common::String saveName = dialog->getResultString();
  60. bool skipSave = saveSlot == -1;
  61. delete dialog;
  62. // Remove the mouse click event from the save/load dialog
  63. eventLoop();
  64. _mouseLeftBtn = _mouseRightBtn = false;
  65. if (!skipSave)
  66. saveGameState(saveSlot, saveName);
  67. return skipSave;
  68. }
  69. _graphicsMgr->clearScreenBufferTop();
  70. SDText drawText;
  71. drawText.set(
  72. Common::Rect(0, TOP - 20, MAXX, CARHEI + (TOP - 20)),
  73. Common::Rect(0, 0, MAXX, CARHEI),
  74. MOUSECOL,
  75. _sysText[kMessageSavePosition]);
  76. drawText.draw(this);
  77. _graphicsMgr->copyToScreen(0, 0, MAXX, TOP);
  78. _graphicsMgr->clearScreenBufferInventory();
  79. _graphicsMgr->copyToScreen(0, TOP + AREA, MAXX, TOP);
  80. _scheduler->resetQueues();
  81. freeKey();
  82. // Reset the inventory and turn it into save slots
  83. _inventory.clear();
  84. _iconBase = 0;
  85. insave:
  86. int8 CurPos = -1;
  87. int8 OldPos = -1;
  88. bool skipSave = false;
  89. loadSaveSlots(saveNames);
  90. for (;;) {
  91. checkSystem();
  92. getKey();
  93. int16 mx = _mousePos.x;
  94. int16 my = _mousePos.y;
  95. if (my >= FIRSTLINE &&
  96. my < FIRSTLINE + ICONDY &&
  97. mx >= ICONMARGSX &&
  98. mx < MAXX - ICONMARGDX) {
  99. OldPos = CurPos;
  100. CurPos = ((mx - ICONMARGSX) / ICONDX);
  101. if (OldPos != CurPos) {
  102. _graphicsMgr->clearScreenBufferSaveSlotDescriptions();
  103. posx = ICONMARGSX + ((CurPos) * (ICONDX)) + ICONDX / 2;
  104. LenText = textLength(saveNames[CurPos]);
  105. posx = CLIP(posx - (LenText / 2), 2, MAXX - 2 - LenText);
  106. drawText.set(
  107. Common::Rect(posx, FIRSTLINE + ICONDY + 10, LenText + posx, CARHEI + (FIRSTLINE + ICONDY + 10)),
  108. Common::Rect(0, 0, LenText, CARHEI),
  109. MOUSECOL,
  110. saveNames[CurPos].c_str());
  111. drawText.draw(this);
  112. _graphicsMgr->copyToScreen(0, FIRSTLINE + ICONDY + 10, MAXX, CARHEI);
  113. }
  114. if (_mouseLeftBtn) {
  115. _mouseLeftBtn = false;
  116. break;
  117. }
  118. } else {
  119. if (OldPos != -1) {
  120. _graphicsMgr->clearScreenBufferSaveSlotDescriptions();
  121. _graphicsMgr->copyToScreen(0, FIRSTLINE + ICONDY + 10, MAXX, CARHEI);
  122. }
  123. OldPos = -1;
  124. CurPos = -1;
  125. if (_mouseLeftBtn || _mouseRightBtn) {
  126. _mouseLeftBtn = _mouseRightBtn = false;
  127. skipSave = true;
  128. break;
  129. }
  130. }
  131. }
  132. if (!skipSave) {
  133. if (_inventory[CurPos] == EMPTYSLOT) {
  134. saveNames[CurPos].clear();
  135. _graphicsMgr->clearScreenBufferSaveSlotDescriptions();
  136. _graphicsMgr->copyToScreen(0, FIRSTLINE + ICONDY + 10, MAXX, CARHEI);
  137. }
  138. for (;;) {
  139. _keybInput = true;
  140. checkSystem();
  141. uint16 ch = getKey();
  142. freeKey();
  143. _keybInput = false;
  144. if (ch == 0x1B) {
  145. ch = 0;
  146. _graphicsMgr->clearScreenBufferSaveSlotDescriptions();
  147. _graphicsMgr->copyToScreen(0, FIRSTLINE + ICONDY + 10, MAXX, CARHEI);
  148. goto insave;
  149. }
  150. if (ch == 8) // Backspace
  151. saveNames[CurPos].deleteLastChar();
  152. else if (ch == 13) // Enter
  153. break;
  154. else if (saveNames[CurPos].size() < 39 && Common::isPrint(ch))
  155. saveNames[CurPos] += ch;
  156. _graphicsMgr->clearScreenBufferSaveSlotDescriptions();
  157. saveNames[CurPos] += '_'; // add blinking cursor
  158. posx = ICONMARGSX + ((CurPos) * (ICONDX)) + ICONDX / 2;
  159. LenText = textLength(saveNames[CurPos]);
  160. posx = CLIP(posx - (LenText / 2), 2, MAXX - 2 - LenText);
  161. drawText.set(
  162. Common::Rect(posx, FIRSTLINE + ICONDY + 10, LenText + posx, CARHEI + (FIRSTLINE + ICONDY + 10)),
  163. Common::Rect(0, 0, LenText, CARHEI),
  164. MOUSECOL,
  165. saveNames[CurPos].c_str());
  166. const bool hideLastChar = (readTime() / 8) & 1;
  167. drawText.draw(this, hideLastChar);
  168. saveNames[CurPos].deleteLastChar(); // remove blinking cursor
  169. _graphicsMgr->copyToScreen(0, FIRSTLINE + ICONDY + 10, MAXX, CARHEI);
  170. }
  171. _graphicsMgr->clearScreenBufferInventory();
  172. ret = false;
  173. // Restore the inventory
  174. _inventory = savedInventory;
  175. _curInventory = 0;
  176. _iconBase = savedIconBase;
  177. saveGameState(CurPos + 1, saveNames[CurPos]);
  178. }
  179. _graphicsMgr->clearScreenBufferInventory();
  180. _graphicsMgr->copyToScreen(0, FIRSTLINE, MAXX, TOP);
  181. _graphicsMgr->clearScreenBufferTop();
  182. _graphicsMgr->copyToScreen(0, 0, MAXX, TOP);
  183. // Restore the inventory
  184. _inventory = savedInventory;
  185. _curInventory = 0;
  186. _iconBase = savedIconBase;
  187. return ret;
  188. }
  189. bool TrecisionEngine::dataLoad() {
  190. const Common::Array<byte> savedInventory = _inventory;
  191. const uint8 savedIconBase = _iconBase;
  192. Common::StringArray saveNames;
  193. saveNames.reserve(MAXSAVEFILE);
  194. bool retval = true;
  195. if (!ConfMan.getBool("originalsaveload")) {
  196. GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Load game:"), _("Load"), false);
  197. int saveSlot = dialog->runModalWithCurrentTarget();
  198. bool skipLoad = saveSlot == -1;
  199. delete dialog;
  200. // Remove the mouse click event from the save/load dialog
  201. eventLoop();
  202. _mouseLeftBtn = _mouseRightBtn = false;
  203. if (!skipLoad)
  204. loadGameState(saveSlot);
  205. return !skipLoad;
  206. }
  207. _graphicsMgr->clearScreenBufferTop();
  208. _graphicsMgr->showCursor();
  209. SDText drawText;
  210. drawText.set(
  211. Common::Rect(0, TOP - 20, MAXX, CARHEI + (TOP - 20)),
  212. Common::Rect(0, 0, MAXX, CARHEI),
  213. MOUSECOL,
  214. _sysText[kMessageLoadPosition]);
  215. drawText.draw(this);
  216. _graphicsMgr->copyToScreen(0, 0, MAXX, TOP);
  217. _graphicsMgr->clearScreenBufferInventory();
  218. _graphicsMgr->copyToScreen(0, TOP + AREA, MAXX, TOP);
  219. _scheduler->resetQueues();
  220. freeKey();
  221. // Reset the inventory and turn it into save slots
  222. _inventory.clear();
  223. _iconBase = 0;
  224. loadSaveSlots(saveNames);
  225. bool skipLoad = false;
  226. int8 curPos = -1;
  227. int8 oldPos = -1;
  228. for (;;) {
  229. checkSystem();
  230. getKey();
  231. if (_mousePos.y >= FIRSTLINE &&
  232. _mousePos.y < (FIRSTLINE + ICONDY) &&
  233. _mousePos.x >= ICONMARGSX &&
  234. (_mousePos.x < (MAXX - ICONMARGDX))) {
  235. oldPos = curPos;
  236. curPos = (_mousePos.x - ICONMARGSX) / ICONDX;
  237. if (oldPos != curPos) {
  238. _graphicsMgr->clearScreenBufferSaveSlotDescriptions();
  239. uint16 posX = ICONMARGSX + ((curPos) * (ICONDX)) + ICONDX / 2;
  240. uint16 lenText = textLength(saveNames[curPos]);
  241. if (posX - (lenText / 2) < 2)
  242. posX = 2;
  243. else
  244. posX = posX - (lenText / 2);
  245. if (posX + lenText > MAXX - 2)
  246. posX = MAXX - 2 - lenText;
  247. drawText.set(
  248. Common::Rect(posX, FIRSTLINE + ICONDY + 10, lenText + posX, CARHEI + (FIRSTLINE + ICONDY + 10)),
  249. Common::Rect(0, 0, lenText, CARHEI),
  250. MOUSECOL,
  251. saveNames[curPos].c_str());
  252. drawText.draw(this);
  253. _graphicsMgr->copyToScreen(0, FIRSTLINE + ICONDY + 10, MAXX, CARHEI);
  254. }
  255. if (_mouseLeftBtn && (_inventory[curPos] != EMPTYSLOT)) {
  256. _mouseLeftBtn = false;
  257. break;
  258. }
  259. } else {
  260. if (oldPos != -1) {
  261. _graphicsMgr->clearScreenBufferSaveSlotDescriptions();
  262. _graphicsMgr->copyToScreen(0, FIRSTLINE + ICONDY + 10, MAXX, CARHEI);
  263. }
  264. oldPos = -1;
  265. curPos = -1;
  266. if (_mouseLeftBtn || _mouseRightBtn) {
  267. _mouseLeftBtn = _mouseRightBtn = false;
  268. retval = false;
  269. skipLoad = true;
  270. break;
  271. }
  272. }
  273. }
  274. if (!skipLoad) {
  275. loadGameState(curPos + 1);
  276. } else {
  277. _actor->actorStop();
  278. _pathFind->nextStep();
  279. checkSystem();
  280. _graphicsMgr->clearScreenBufferInventory();
  281. _graphicsMgr->copyToScreen(0, FIRSTLINE, MAXX, TOP);
  282. _graphicsMgr->clearScreenBufferTop();
  283. _graphicsMgr->copyToScreen(0, 0, MAXX, TOP);
  284. if (_flagScriptActive) {
  285. _graphicsMgr->hideCursor();
  286. }
  287. // Restore the inventory
  288. _inventory = savedInventory;
  289. _curInventory = 0;
  290. _iconBase = savedIconBase;
  291. }
  292. return retval;
  293. }
  294. Common::Error TrecisionEngine::loadGameStream(Common::SeekableReadStream *stream) {
  295. const byte version = stream->readByte();
  296. Common::Serializer ser(stream, nullptr);
  297. ser.setVersion(version);
  298. syncGameStream(ser);
  299. _graphicsMgr->clearScreenBufferInventory();
  300. _flagNoPaintScreen = true;
  301. _curStack = 0;
  302. _flagScriptActive = false;
  303. _oldRoom = _curRoom;
  304. changeRoom(_curRoom);
  305. _actor->actorStop();
  306. _pathFind->nextStep();
  307. checkSystem();
  308. _graphicsMgr->clearScreenBufferInventory();
  309. _graphicsMgr->copyToScreen(0, FIRSTLINE, MAXX, TOP);
  310. _graphicsMgr->clearScreenBufferTop();
  311. _graphicsMgr->copyToScreen(0, 0, MAXX, TOP);
  312. if (_flagScriptActive) {
  313. _graphicsMgr->hideCursor();
  314. }
  315. return Common::kNoError;
  316. }
  317. Common::Error TrecisionEngine::saveGameStream(Common::WriteStream *stream, bool isAutosave) {
  318. const byte version = SAVE_VERSION_SCUMMVM;
  319. Common::Serializer ser(nullptr, stream);
  320. ser.setVersion(version);
  321. stream->writeByte(version);
  322. syncGameStream(ser);
  323. return Common::kNoError;
  324. }
  325. bool TrecisionEngine::syncGameStream(Common::Serializer &ser) {
  326. uint16 unused = 0;
  327. if (ser.isLoading()) {
  328. ser.skip(40, SAVE_VERSION_ORIGINAL_MIN, SAVE_VERSION_ORIGINAL_MAX); // description
  329. ser.skip(ICONDX * ICONDY * sizeof(uint16), SAVE_VERSION_ORIGINAL_MIN, SAVE_VERSION_ORIGINAL_MAX); // thumbnail
  330. }
  331. ser.syncAsUint16LE(_curRoom);
  332. ser.syncAsByte(unused, SAVE_VERSION_ORIGINAL_MIN, SAVE_VERSION_ORIGINAL_MAX); // _inventorySize
  333. ser.syncAsByte(unused, SAVE_VERSION_ORIGINAL_MIN, SAVE_VERSION_ORIGINAL_MAX); // _cyberInventorySize
  334. ser.syncAsByte(_iconBase);
  335. ser.syncAsSint16LE(_flagSkipTalk);
  336. ser.syncAsSint16LE(unused, SAVE_VERSION_ORIGINAL_MIN, SAVE_VERSION_ORIGINAL_MAX); // _flagSkipEnable
  337. ser.syncAsSint16LE(unused, SAVE_VERSION_ORIGINAL_MIN, SAVE_VERSION_ORIGINAL_MAX); // _flagMouseEnabled
  338. ser.syncAsSint16LE(unused, SAVE_VERSION_ORIGINAL_MIN, SAVE_VERSION_ORIGINAL_MAX); // _flagScreenRefreshed
  339. ser.syncAsSint16LE(_flagPaintCharacter);
  340. ser.syncAsSint16LE(_flagSomeoneSpeaks);
  341. ser.syncAsSint16LE(_flagCharacterSpeak);
  342. ser.syncAsSint16LE(_flagInventoryLocked);
  343. ser.syncAsSint16LE(_flagUseWithStarted);
  344. ser.syncAsSint16LE(unused, SAVE_VERSION_ORIGINAL_MIN, SAVE_VERSION_ORIGINAL_MAX); // _flagMousePolling
  345. ser.syncAsSint16LE(unused, SAVE_VERSION_ORIGINAL_MIN, SAVE_VERSION_ORIGINAL_MAX); // _flagDialogSolitaire
  346. ser.syncAsSint16LE(unused); // _flagCharacterExists
  347. syncInventory(ser);
  348. _actor->syncGameStream(ser);
  349. _pathFind->syncGameStream(ser);
  350. for (int i = 0; i < MAXROOMS; i++)
  351. _room[i].syncGameStream(ser);
  352. for (int i = 0; i < MAXOBJ; i++)
  353. _obj[i].syncGameStream(ser);
  354. for (int i = 0; i < MAXINVENTORY; i++)
  355. _inventoryObj[i].syncGameStream(ser);
  356. _animMgr->syncGameStream(ser);
  357. ser.skip(NUMSAMPLES * 2, SAVE_VERSION_ORIGINAL_MIN, SAVE_VERSION_ORIGINAL_MAX); // SoundManager::syncGameStream()
  358. _dialogMgr->syncGameStream(ser);
  359. _logicMgr->syncGameStream(ser);
  360. return true;
  361. }
  362. } // End of namespace Trecision