diff options
Diffstat (limited to 'simon/saveload.cpp')
-rw-r--r-- | simon/saveload.cpp | 614 |
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 |