aboutsummaryrefslogtreecommitdiff
path: root/simon/saveload.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'simon/saveload.cpp')
-rw-r--r--simon/saveload.cpp614
1 files changed, 614 insertions, 0 deletions
diff --git a/simon/saveload.cpp b/simon/saveload.cpp
new file mode 100644
index 0000000000..34c8903722
--- /dev/null
+++ b/simon/saveload.cpp
@@ -0,0 +1,614 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001-2004 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include "stdafx.h"
+
+#include "gui/about.h"
+#include "gui/message.h"
+
+#include "simon/simon.h"
+#include "simon/intern.h"
+
+namespace Simon {
+
+void SimonEngine::o_save_game() {
+ save_or_load_dialog(false);
+}
+
+void SimonEngine::o_load_game() {
+ save_or_load_dialog(true);
+}
+
+int SimonEngine::count_savegames() {
+ SaveFile *f;
+ uint i = 1;
+ bool marks[256];
+
+ char *prefix = gen_savename(999);
+ prefix[strlen(prefix)-3] = '\0';
+ _saveFileMan->listSavefiles(prefix, marks, 256);
+
+ while (i < 256) {
+ if (marks[i] &&
+ (f = _saveFileMan->openSavefile(gen_savename(i), false))) {
+ i++;
+ delete f;
+ } else
+ break;
+ }
+ return i;
+}
+
+int SimonEngine::display_savegame_list(int curpos, bool load, char *dst) {
+ int slot, last_slot;
+ SaveFile *in;
+
+ showMessageFormat("\xC");
+
+ memset(dst, 0, 18 * 6);
+
+ slot = curpos;
+
+ while (curpos + 6 > slot) {
+ if(!(in = _saveFileMan->openSavefile(gen_savename(slot), false)))
+ break;
+
+ in->read(dst, 18);
+ delete in;
+ last_slot = slot;
+ if (slot < 10)
+ showMessageFormat(" ");
+ showMessageFormat("%d", slot);
+ showMessageFormat(".%s\n", dst);
+ dst += 18;
+ slot++;
+ }
+ // while_break
+ if (!load) {
+ if (curpos + 6 == slot)
+ slot++;
+ else {
+ if (slot < 10)
+ showMessageFormat(" ");
+ showMessageFormat("%d.\n", slot);
+ }
+ } else {
+ if (curpos + 6 == slot) {
+ if((in = _saveFileMan->openSavefile(gen_savename(slot), false))) {
+ slot++;
+ delete in;
+ }
+ }
+ }
+
+ return slot - curpos;
+}
+
+void SimonEngine::quick_load_or_save() {
+ // simon1demo subroutines are missing too many segments
+ // original demo didn't allow load or save either.
+ if (_game == GAME_SIMON1DEMO)
+ return;
+
+ bool success;
+ char buf[50];
+
+ char *filename = gen_savename(_saveLoadSlot);
+ if (_saveLoadFlag == 2) {
+ Subroutine *sub;
+ success = load_game(_saveLoadSlot);
+ if (!success) {
+ sprintf(buf, "Failed to load game state to file:\n\n%s", filename);
+ } else {
+ // Redraw Inventory
+ lock();
+ fcs_unk_proc_1(2, getItem1Ptr(), 0, 0);
+ unlock();
+ // Reset engine?
+ vc_set_bit_to(97, true);
+ sub = getSubroutineByID(100);
+ startSubroutine(sub);
+ }
+ } else {
+ success = save_game(_saveLoadSlot, _saveLoadName);
+ if (!success)
+ sprintf(buf, "Failed to save game state to file:\n\n%s", filename);
+ }
+
+ if (!success) {
+ GUI::MessageDialog dialog(buf, "OK");
+ dialog.runModal();
+
+ } else if (_saveLoadFlag == 1) {
+ sprintf(buf, "Successfully saved game state in file:\n\n%s", filename);
+ GUI::TimedMessageDialog dialog(buf, 1500);
+ dialog.runModal();
+
+ }
+
+ _saveLoadFlag = 0;
+}
+
+void SimonEngine::savegame_dialog(char *buf) {
+ int i;
+
+ o_unk_132_helper_3();
+
+ i = display_savegame_list(_saveload_row_curpos, _save_or_load, buf);
+
+ _savedialog_flag = true;
+
+ if (i != 7) {
+ i++;
+ if (!_save_or_load)
+ i++;
+ _savedialog_flag = false;
+ }
+
+ if (!--i)
+ return;
+
+ do {
+ clear_hitarea_bit_0x40(0xd0 + i - 1);
+ } while (--i);
+}
+
+void SimonEngine::save_or_load_dialog(bool load) {
+ time_t save_time;
+ int number_of_savegames;
+ int i;
+ int unk132_result;
+ FillOrCopyStruct *fcs;
+ char *name;
+ int name_len;
+ bool b;
+ char buf[108];
+
+ _save_or_load = load;
+
+ save_time = time(NULL);
+
+ _copy_partial_mode = 1;
+
+ number_of_savegames = count_savegames();
+ if (!load)
+ number_of_savegames++;
+ number_of_savegames -= 6;
+ if (number_of_savegames < 0)
+ number_of_savegames = 0;
+ number_of_savegames++;
+ _num_savegame_rows = number_of_savegames;
+
+ _saveload_row_curpos = 1;
+ if (!load)
+ _saveload_row_curpos = number_of_savegames;
+
+ _saveload_flag = false;
+
+restart:;
+ do {
+ i = o_unk_132_helper(&b, buf);
+ } while (!b);
+
+ if (i == 205)
+ goto get_out;
+ if (!load) {
+ // if_1
+ if_1:;
+ unk132_result = i;
+
+ set_hitarea_bit_0x40(0xd0 + i);
+ leaveHitAreaById(0xd0 + i);
+
+ // some code here
+
+ fcs = _fcs_ptr_array_3[5];
+
+ fcs->textRow = unk132_result;
+
+ if (_language == 20) { //Hebrew
+ // init x offset with a 2 character savegame number + a period (18 pix)
+ fcs->textColumn = 3;
+ fcs->textColumnOffset = 6;
+ fcs->textLength = 3;
+ } else {
+ // init x offset with a 2 character savegame number + a period (18 pix)
+ fcs->textColumn = 2;
+ fcs->textColumnOffset = 2;
+ fcs->textLength = 3;
+ }
+
+ name = buf + i * 18;
+
+ // now process entire savegame name to get correct x offset for cursor
+ name_len = 0;
+ while (name[name_len]) {
+ if (_language == 20) { //Hebrew
+ byte width = 6;
+ if (name[name_len] >= 64 && name[name_len] < 91)
+ width = _hebrew_char_widths [name[name_len] - 64];
+ fcs->textLength++;
+ fcs->textColumnOffset -= width;
+ if (fcs->textColumnOffset < width) {
+ fcs->textColumnOffset += 8;
+ fcs->textColumn++;
+ }
+ } else {
+ fcs->textLength++;
+ fcs->textColumnOffset += 6;
+ if (name[name_len] == 'i' || name[name_len] == 'l')
+ fcs->textColumnOffset -= 2;
+ if (fcs->textColumnOffset >= 8) {
+ fcs->textColumnOffset -= 8;
+ fcs->textColumn++;
+ }
+ }
+ name_len++;
+ }
+ // while_1_end
+
+ // do_3_start
+ for (;;) {
+ video_putchar(fcs, 0x7f);
+
+ _saveload_flag = true;
+
+ // do_2
+ do {
+ i = o_unk_132_helper(&b, buf);
+
+ if (b) {
+ if (i == 205)
+ goto get_out;
+ clear_hitarea_bit_0x40(0xd0 + unk132_result);
+ if (_saveload_flag) {
+ o_clear_character(_fcs_ptr_array_3[5], 8);
+ // move code
+ }
+ goto if_1;
+ }
+
+ // is_not_b
+ if (!_saveload_flag) {
+ clear_hitarea_bit_0x40(0xd0 + unk132_result);
+ goto restart;
+ }
+ } while (i >= 0x80 || i == 0);
+
+ // after_do_2
+ o_clear_character(_fcs_ptr_array_3[5], 8);
+ if (i == 10 || i == 13)
+ break;
+ if (i == 8) {
+ // do_backspace
+ if (name_len != 0) {
+ int x;
+ byte m;
+
+ name_len--;
+ m = name[name_len];
+
+ if (_language == 20) //Hebrew
+ x = 8;
+ else
+ x = (name[name_len] == 'i' || name[name_len] == 'l') ? 1 : 8;
+
+ name[name_len] = 0;
+
+ o_clear_character(_fcs_ptr_array_3[5], x, m);
+ }
+ } else if (i >= 32 && name_len != 17) {
+ name[name_len++] = i;
+
+ video_putchar(_fcs_ptr_array_3[5], i);
+ }
+ }
+
+ // do_save
+ if (!save_game(_saveload_row_curpos + unk132_result, buf + unk132_result * 18))
+ o_file_error(_fcs_ptr_array_3[5], true);
+ } else {
+ if (!load_game(_saveload_row_curpos + i))
+ o_file_error(_fcs_ptr_array_3[5], false);
+ }
+
+get_out:;
+ o_unk_132_helper_3();
+
+ _base_time = time(NULL) - save_time + _base_time;
+ _copy_partial_mode = 0;
+
+ dx_copy_rgn_from_3_to_2(94, 208, 46, 80);
+
+ i = _timer_4;
+ do {
+ delay(10);
+ } while (i == _timer_4);
+
+ g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
+}
+
+void SimonEngine::o_file_error(FillOrCopyStruct *fcs, bool save_error) {
+ HitArea *ha;
+ const char *string, *string2;
+
+ if (save_error) {
+ string = "\r Save failed.";
+ string2 = "\r Disk error.";
+ } else {
+ string = "\r Load failed.";
+ string2 = "\r File not found.";
+ }
+
+ video_putchar(fcs, 0xC);
+ for (; *string; string++)
+ video_putchar(fcs, *string);
+ for (; *string2; string2++)
+ video_putchar(fcs, *string2);
+
+ fcs->textColumn = (fcs->width >> 1) - 3;
+ fcs->textRow = fcs->height - 1;
+ fcs->textLength = 0;
+
+ string = "[ OK ]";
+ for (; *string; string++)
+ video_putchar(fcs, *string);
+
+ ha = findEmptyHitArea();
+ ha->x = ((fcs->width >> 1) + (fcs->x - 3)) << 3;
+ ha->y = (fcs->height << 3) + fcs->y - 8;
+ ha->width = 48;
+ ha->height = 8;
+ ha->flags = 0x20;
+ ha->id = 0x7FFF;
+ ha->layer = 0x3EF;
+
+loop:;
+ _last_hitarea = _last_hitarea_3 = 0;
+
+ do {
+ delay(1);
+ } while (_last_hitarea_3 == 0);
+
+ ha = _last_hitarea;
+ if (ha == NULL || ha->id != 0x7FFF)
+ goto loop;
+
+ // Return
+ delete_hitarea(0x7FFF);
+}
+
+bool SimonEngine::save_game(uint slot, char *caption) {
+ SaveFile *f;
+ uint item_index, num_item, i, j;
+ TimeEvent *te;
+
+ _lock_word |= 0x100;
+
+#ifndef _WIN32_WCE
+ errno = 0;
+#endif
+
+
+ f = _saveFileMan->openSavefile(gen_savename(slot), true);
+ if (f == NULL) {
+ _lock_word &= ~0x100;
+ return false;
+ }
+
+ f->write(caption, 0x12);
+
+ f->writeUint32BE(_itemarray_inited - 1);
+ f->writeUint32BE(0xFFFFFFFF);
+ f->writeUint32BE(0);
+ f->writeUint32BE(0);
+
+ i = 0;
+ for (te = _first_time_struct; te; te = te->next)
+ i++;
+ f->writeUint32BE(i);
+
+ for (te = _first_time_struct; te; te = te->next) {
+ f->writeUint32BE(te->time + _base_time);
+ f->writeUint16BE(te->subroutine_id);
+ }
+
+ item_index = 1;
+ for (num_item = _itemarray_inited - 1; num_item; num_item--) {
+ Item *item = _itemarray_ptr[item_index++];
+
+ f->writeUint16BE(item->parent);
+ f->writeUint16BE(item->sibling);
+ f->writeUint16BE(item->unk3);
+ f->writeUint16BE(item->unk4);
+
+ Child1 *child1 = (Child1 *)findChildOfType(item, 1);
+ if (child1) {
+ f->writeUint16BE(child1->fr2);
+ }
+
+ Child2 *child2 = (Child2 *)findChildOfType(item, 2);
+ if (child2) {
+ f->writeUint32BE(child2->avail_props);
+ i = child2->avail_props & 1;
+
+ for (j = 1; j < 16; j++) {
+ if ((1 << j) & child2->avail_props) {
+ f->writeUint16BE(child2->array[i++]);
+ }
+ }
+ }
+
+ Child9 *child9 = (Child9 *) findChildOfType(item, 9);
+ if (child9) {
+ for (i = 0; i != 4; i++) {
+ f->writeUint16BE(child9->array[i]);
+ }
+ }
+ }
+
+ // write the 255 variables
+ for (i = 0; i != 255; i++) {
+ f->writeUint16BE(readVariable(i));
+ }
+
+ // write the items in array 6
+ for (i = 0; i != 10; i++) {
+ f->writeUint16BE(itemPtrToID(_item_array_6[i]));
+ }
+
+ // Write the bits in array 1 & 2
+ for (i = 0; i != 32; i++)
+ f->writeUint16BE(_bit_array[i]);
+
+ delete f;
+
+ _lock_word &= ~0x100;
+
+ return true;
+}
+
+char *SimonEngine::gen_savename(int slot) {
+ static char buf[15];
+
+ if (_game & GF_SIMON2) {
+ sprintf(buf, "simon2.%.3d", slot);
+ } else {
+ sprintf(buf, "simon1.%.3d", slot);
+ }
+ return buf;
+}
+
+bool SimonEngine::load_game(uint slot) {
+ char ident[18];
+ SaveFile *f;
+ uint num, item_index, i, j;
+
+ _lock_word |= 0x100;
+
+#ifndef _WIN32_WCE
+ errno = 0;
+#endif
+
+
+ f = _saveFileMan->openSavefile(gen_savename(slot), false);
+ if (f == NULL) {
+ _lock_word &= ~0x100;
+ return false;
+ }
+
+ f->read(ident, 18);
+
+ num = f->readUint32BE();
+
+ if (f->readUint32BE() != 0xFFFFFFFF || num != _itemarray_inited - 1) {
+ delete f;
+ _lock_word &= ~0x100;
+ return false;
+ }
+
+ f->readUint32BE();
+ f->readUint32BE();
+ _no_parent_notify = true;
+
+
+ // add all timers
+ killAllTimers();
+ for (num = f->readUint32BE(); num; num--) {
+ uint32 timeout = f->readUint32BE();
+ uint16 func_to_call = f->readUint16BE();
+ addTimeEvent(timeout, func_to_call);
+ }
+
+ item_index = 1;
+ for (num = _itemarray_inited - 1; num; num--) {
+ Item *item = _itemarray_ptr[item_index++], *parent_item;
+
+ uint parent = f->readUint16BE();
+ uint sibling = f->readUint16BE();
+
+ parent_item = derefItem(parent);
+
+ setItemParent(item, parent_item);
+
+ if (parent_item == NULL) {
+ item->parent = parent;
+ item->sibling = sibling;
+ }
+
+ item->unk3 = f->readUint16BE();
+ item->unk4 = f->readUint16BE();
+
+ Child1 *child1 = (Child1 *)findChildOfType(item, 1);
+ if (child1 != NULL) {
+ child1->fr2 = f->readUint16BE();
+ }
+
+ Child2 *child2 = (Child2 *)findChildOfType(item, 2);
+ if (child2 != NULL) {
+ child2->avail_props = f->readUint32BE();
+ i = child2->avail_props & 1;
+
+ for (j = 1; j < 16; j++) {
+ if ((1 << j) & child2->avail_props) {
+ child2->array[i++] = f->readUint16BE();
+ }
+ }
+ }
+
+ Child9 *child9 = (Child9 *) findChildOfType(item, 9);
+ if (child9) {
+ for (i = 0; i != 4; i++) {
+ child9->array[i] = f->readUint16BE();
+ }
+ }
+ }
+
+
+ // read the 255 variables
+ for (i = 0; i != 255; i++) {
+ writeVariable(i, f->readUint16BE());
+ }
+
+ // write the items in array 6
+ for (i = 0; i != 10; i++) {
+ _item_array_6[i] = derefItem(f->readUint16BE());
+ }
+
+ // Write the bits in array 1 & 2
+ for (i = 0; i != 32; i++)
+ _bit_array[i] = f->readUint16BE();
+
+ delete f;
+
+ _no_parent_notify = false;
+
+ _lock_word &= ~0x100;
+
+#ifndef _WIN32_WCE
+ if (errno != 0)
+ error("load failed");
+#endif
+
+ return true;
+}
+
+} // End of namespace Simon