Ticket #8596: AgiSaveGame-09jan2007.patch
File AgiSaveGame-09jan2007.patch, 31.8 KB (added by , 17 years ago) |
---|
-
engines/agi/agi.cpp
531 531 Common::addSpecialDebugLevel(kDebugLevelScripts, "Scripts", "Scripts debugging"); 532 532 Common::addSpecialDebugLevel(kDebugLevelSound, "Sound", "Sound debugging"); 533 533 Common::addSpecialDebugLevel(kDebugLevelText, "Text", "Text output debugging"); 534 Common::addSpecialDebugLevel(kDebugLevelSavegame, "Savegame", "Saving & restoring game debugging"); 534 535 535 536 536 537 memset(&game, 0, sizeof(struct agi_game)); … … 587 588 _sound = new SoundMgr(this, _mixer); 588 589 _picture = new PictureMgr(this, _gfx); 589 590 _sprites = new SpritesMgr(this, _gfx); 590 _saveGameMgr = new SaveGameMgr(this, _sprites, _gfx, _sound, _picture);591 591 592 592 _gfx->initMachine(); 593 593 -
engines/agi/op_cmd.cpp
448 448 } 449 449 450 450 cmd(save_game) { 451 game.simple_save ? g_agi-> _saveGameMgr->savegame_simple() : g_agi->_saveGameMgr->savegame_dialog();451 game.simple_save ? g_agi->saveGameSimple() : g_agi->saveGameDialog(); 452 452 } 453 453 454 454 cmd(load_game) { 455 455 assert(1); 456 game.simple_save ? g_agi-> _saveGameMgr->loadgame_simple() : g_agi->_saveGameMgr->loadgame_dialog();456 game.simple_save ? g_agi->loadGameSimple() : g_agi->loadGameDialog(); 457 457 } 458 458 459 459 cmd(init_disk) { /* do nothing */ -
engines/agi/savegame.cpp
38 38 #include "agi/keyboard.h" 39 39 #include "agi/menu.h" 40 40 41 namespace Agi { 41 #define SAVEGAME_VERSION 2 42 42 43 static const char *strSig = "AGI:";44 45 void SaveGameMgr::write_string(Common::File *f, const char *s) {46 f->writeSint16BE((int16)strlen(s));47 f->write(s, strlen(s));48 }49 50 void SaveGameMgr::read_string(Common::File *f, char *s) {51 int16 size = f->readSint16BE();52 f->read(s, size);53 s[size] = (char)0;54 }55 56 void SaveGameMgr::write_bytes(Common::File *f, const char *s, int16 size) {57 f->write(s, size);58 }59 60 void SaveGameMgr::read_bytes(Common::File *f, char *s, int16 size) {61 f->read(s, size);62 }63 64 43 /* 65 * Version 0: view table has 64 entries 66 * Version 1: view table has 256 entries (needed in KQ3) 44 * Version 0 (Sarien): view table has 64 entries 45 * Version 1 (Sarien): view table has 256 entries (needed in KQ3) 46 * Version 2 (ScummVM): first ScummVM version 67 47 */ 68 #define SAVEGAME_VERSION 169 48 70 int SaveGameMgr::save_game(char *s, const char *d) { 71 int16 i; 72 struct image_stack_element *ptr = _vm->image_stack; 73 Common::File f; 49 namespace Agi { 74 50 75 // FIXME: Do *not* use Common::File to access savegames, it is not portable! 76 f.open(s, Common::File::kFileWriteMode); 51 static const uint32 AGIflag=MKID_BE('AGI:'); 77 52 78 if (!f.isOpen()) 53 int AgiEngine::saveGame(const char *fileName, const char *description) { 54 char gameIDstring[8]="gameIDX"; 55 int i; 56 struct image_stack_element *ptr = image_stack; 57 Common::OutSaveFile *out; 58 59 debugC(3, kDebugLevelMain | kDebugLevelSavegame, "AgiEngine::saveGame(%s, %s)", fileName, description); 60 if (!(out = _saveFileMan->openForSaving(fileName))) { 61 warning("Can't create file '%s', game not saved", fileName); 79 62 return err_BadFileOpen; 63 } else { 64 debugC(3, kDebugLevelMain | kDebugLevelSavegame, "Successfully opened %s for writing", fileName); 65 } 80 66 81 write_bytes(&f, strSig, 8);82 write_string(&f, d);67 out->writeUint32BE(AGIflag); 68 out->write(description, 31); 83 69 84 f.writeByte((uint8)SAVEGAME_VERSION); 85 f.writeByte((uint8)_vm->game.state); 86 /* game.name */ 87 write_string(&f, _vm->game.id); 88 /* game.crc */ 70 out->writeByte(SAVEGAME_VERSION); 71 debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing save game version (%d)", SAVEGAME_VERSION); 89 72 73 out->writeByte(game.state); 74 debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing game state (%d)", game.state); 75 76 strcpy(gameIDstring, game.id); 77 out->write(gameIDstring, 8); 78 debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing game id (%s, %s)", gameIDstring, game.id); 79 90 80 for (i = 0; i < MAX_FLAGS; i++) 91 f.writeByte(_vm->game.flags[i]);81 out->writeByte(game.flags[i]); 92 82 for (i = 0; i < MAX_VARS; i++) 93 f.writeByte(_vm->game.vars[i]);83 out->writeByte(game.vars[i]); 94 84 95 f.writeSint16BE((int8)_vm->game.horizon); 96 f.writeSint16BE((int16)_vm->game.line_status); 97 f.writeSint16BE((int16)_vm->game.line_user_input); 98 f.writeSint16BE((int16)_vm->game.line_min_print); 99 /* game.cursor_pos */ 100 /* game.input_buffer */ 101 /* game.echo_buffer */ 102 /* game.keypress */ 103 f.writeSint16BE((int16)_vm->game.input_mode); 104 f.writeSint16BE((int16)_vm->game.lognum); 85 out->writeSint16BE((int8)game.horizon); 86 out->writeSint16BE((int16)game.line_status); 87 out->writeSint16BE((int16)game.line_user_input); 88 out->writeSint16BE((int16)game.line_min_print); 105 89 106 f.writeSint16BE((int16)_vm->game.player_control); 107 f.writeSint16BE((int16)_vm->game.quit_prog_now); 108 f.writeSint16BE((int16)_vm->game.status_line); 109 f.writeSint16BE((int16)_vm->game.clock_enabled); 110 f.writeSint16BE((int16)_vm->game.exit_all_logics); 111 f.writeSint16BE((int16)_vm->game.picture_shown); 112 f.writeSint16BE((int16)_vm->game.has_prompt); 113 f.writeSint16BE((int16)_vm->game.game_flags); 90 out->writeSint16BE((int16)game.input_mode); 91 out->writeSint16BE((int16)game.lognum); 114 92 115 /* Reversed to keep compatibility with old savegames */ 116 f.writeSint16BE((int16)!_vm->game.input_enabled); 93 out->writeSint16BE((int16)game.player_control); 94 out->writeSint16BE((int16)game.quit_prog_now); 95 out->writeSint16BE((int16)game.status_line); 96 out->writeSint16BE((int16)game.clock_enabled); 97 out->writeSint16BE((int16)game.exit_all_logics); 98 out->writeSint16BE((int16)game.picture_shown); 99 out->writeSint16BE((int16)game.has_prompt); 100 out->writeSint16BE((int16)game.game_flags); 117 101 102 out->writeSint16BE((int16)game.input_enabled); 103 118 104 for (i = 0; i < _HEIGHT; i++) 119 f.writeByte(_vm->game.pri_table[i]); 105 out->writeByte(game.pri_table[i]); 106 107 out->writeSint16BE((int16)game.gfx_mode); 108 out->writeByte(game.cursor_char); 109 out->writeSint16BE((int16)game.color_fg); 110 out->writeSint16BE((int16)game.color_bg); 120 111 121 /* game.msg_box_ticks */122 /* game.block */123 /* game.window */124 /* game.has_window */125 126 f.writeSint16BE((int16)_vm->game.gfx_mode);127 f.writeByte(_vm->game.cursor_char);128 f.writeSint16BE((int16)_vm->game.color_fg);129 f.writeSint16BE((int16)_vm->game.color_bg);130 131 112 /* game.hires */ 132 113 /* game.sbuf */ 133 114 /* game.ego_words */ 134 115 /* game.num_ego_words */ 135 116 136 f.writeSint16BE((int16)_vm->game.num_objects);137 for (i = 0; i < (int16) _vm->game.num_objects; i++)138 f.writeSint16BE((int16)_vm->object_get_location(i));117 out->writeSint16BE((int16)game.num_objects); 118 for (i = 0; i < (int16)game.num_objects; i++) 119 out->writeSint16BE((int16)object_get_location(i)); 139 120 140 121 /* game.ev_keyp */ 141 122 for (i = 0; i < MAX_STRINGS; i++) 142 write_string(&f, _vm->game.strings[i]);123 out->write(game.strings[i], MAX_STRINGLEN); 143 124 144 125 /* record info about loaded resources */ 145 126 for (i = 0; i < MAX_DIRS; i++) { 146 f.writeByte(_vm->game.dir_logic[i].flags);147 f.writeSint16BE((int16)_vm->game.logics[i].sIP);148 f.writeSint16BE((int16)_vm->game.logics[i].cIP);127 out->writeByte(game.dir_logic[i].flags); 128 out->writeSint16BE((int16)game.logics[i].sIP); 129 out->writeSint16BE((int16)game.logics[i].cIP); 149 130 } 150 131 for (i = 0; i < MAX_DIRS; i++) 151 f.writeByte(_vm->game.dir_pic[i].flags);132 out->writeByte(game.dir_pic[i].flags); 152 133 for (i = 0; i < MAX_DIRS; i++) 153 f.writeByte(_vm->game.dir_view[i].flags);134 out->writeByte(game.dir_view[i].flags); 154 135 for (i = 0; i < MAX_DIRS; i++) 155 f.writeByte(_vm->game.dir_sound[i].flags);136 out->writeByte(game.dir_sound[i].flags); 156 137 157 138 /* game.pictures */ 158 139 /* game.logics */ … … 160 141 /* game.sounds */ 161 142 162 143 for (i = 0; i < MAX_VIEWTABLE; i++) { 163 struct vt_entry *v = & _vm->game.view_table[i];144 struct vt_entry *v = &game.view_table[i]; 164 145 165 f.writeByte(v->step_time);166 f.writeByte(v->step_time_count);167 f.writeByte(v->entry);168 f.writeSint16BE(v->x_pos);169 f.writeSint16BE(v->y_pos);170 f.writeByte(v->current_view);146 out->writeByte(v->step_time); 147 out->writeByte(v->step_time_count); 148 out->writeByte(v->entry); 149 out->writeSint16BE(v->x_pos); 150 out->writeSint16BE(v->y_pos); 151 out->writeByte(v->current_view); 171 152 172 153 /* v->view_data */ 173 154 174 f.writeByte(v->current_loop);175 f.writeByte(v->num_loops);155 out->writeByte(v->current_loop); 156 out->writeByte(v->num_loops); 176 157 177 158 /* v->loop_data */ 178 159 179 f.writeByte(v->current_cel);180 f.writeByte(v->num_cels);160 out->writeByte(v->current_cel); 161 out->writeByte(v->num_cels); 181 162 182 163 /* v->cel_data */ 183 164 /* v->cel_data_2 */ 184 165 185 f.writeSint16BE(v->x_pos2);186 f.writeSint16BE(v->y_pos2);166 out->writeSint16BE(v->x_pos2); 167 out->writeSint16BE(v->y_pos2); 187 168 188 169 /* v->s */ 189 170 190 f.writeSint16BE(v->x_size);191 f.writeSint16BE(v->y_size);192 f.writeByte(v->step_size);193 f.writeByte(v->cycle_time);194 f.writeByte(v->cycle_time_count);195 f.writeByte(v->direction);171 out->writeSint16BE(v->x_size); 172 out->writeSint16BE(v->y_size); 173 out->writeByte(v->step_size); 174 out->writeByte(v->cycle_time); 175 out->writeByte(v->cycle_time_count); 176 out->writeByte(v->direction); 196 177 197 f.writeByte(v->motion);198 f.writeByte(v->cycle);199 f.writeByte(v->priority);178 out->writeByte(v->motion); 179 out->writeByte(v->cycle); 180 out->writeByte(v->priority); 200 181 201 f.writeUint16BE(v->flags);182 out->writeUint16BE(v->flags); 202 183 203 f.writeByte(v->parm1);204 f.writeByte(v->parm2);205 f.writeByte(v->parm3);206 f.writeByte(v->parm4);184 out->writeByte(v->parm1); 185 out->writeByte(v->parm2); 186 out->writeByte(v->parm3); 187 out->writeByte(v->parm4); 207 188 } 208 189 209 190 /* Save image stack */ 210 191 211 for (i = 0; i < _vm->image_stack_pointer; i++) {212 ptr = & _vm->image_stack[i];213 f.writeByte(ptr->type);214 f.writeSint16BE(ptr->parm1);215 f.writeSint16BE(ptr->parm2);216 f.writeSint16BE(ptr->parm3);217 f.writeSint16BE(ptr->parm4);218 f.writeSint16BE(ptr->parm5);219 f.writeSint16BE(ptr->parm6);220 f.writeSint16BE(ptr->parm7);192 for (i = 0; i < image_stack_pointer; i++) { 193 ptr = &image_stack[i]; 194 out->writeByte(ptr->type); 195 out->writeSint16BE(ptr->parm1); 196 out->writeSint16BE(ptr->parm2); 197 out->writeSint16BE(ptr->parm3); 198 out->writeSint16BE(ptr->parm4); 199 out->writeSint16BE(ptr->parm5); 200 out->writeSint16BE(ptr->parm6); 201 out->writeSint16BE(ptr->parm7); 221 202 } 222 f.writeByte(0);203 out->writeByte(0); 223 204 224 f.close(); 225 205 out->flush(); 206 if (out->ioFailed()) 207 warning("Can't write file '%s'. (Disk full?)", fileName); 208 else 209 debugC(1, kDebugLevelMain | kDebugLevelSavegame, "Saved game %s in file %s", description, fileName); 210 211 delete out; 212 debugC(3, kDebugLevelMain | kDebugLevelSavegame, "Closed %s", fileName); 226 213 return err_OK; 227 214 } 228 215 229 int SaveGameMgr::load_game(char *s) { 230 int i, ver, vt_entries = MAX_VIEWTABLE; 216 int AgiEngine::loadGame(const char *fileName) { 217 char description[31], saveVersion, loadId[8]; 218 int i, vt_entries = MAX_VIEWTABLE; 231 219 uint8 t; 232 220 int16 parm[7]; 233 char sig[8]; 234 char id[8]; 235 char description[256]; 236 Common::File f; 221 Common::InSaveFile *in; 237 222 238 // FIXME: Do *not* use Common::File to access savegames, it is not portable! 239 f.open(s); 223 debugC(3, kDebugLevelMain | kDebugLevelSavegame, "AgiEngine::loadGame(%s)", fileName); 240 224 241 if (!f.isOpen()) 225 if (!(in = _saveFileMan->openForLoading(fileName))) { 226 warning("Can't open file '%s', game not loaded", fileName); 242 227 return err_BadFileOpen; 243 244 read_bytes(&f, sig, 8); 245 if (strncmp(sig, strSig, 8)) { 246 f.close(); 247 return err_BadFileOpen; 228 } else { 229 debugC(3, kDebugLevelMain | kDebugLevelSavegame, "Successfully opened %s for reading", fileName); 248 230 } 249 231 250 read_string(&f, description); 232 uint32 typea = in->readUint32BE(); 233 if (typea == AGIflag) { 234 debugC(6, kDebugLevelMain | kDebugLevelSavegame, "Has AGI flag, good start"); 235 } else { 236 warning("This doesn't appear to be an AGI savegame, game not restored"); 237 delete in; 238 return err_OK; 239 } 251 240 252 ver = f.readByte(); 253 if (ver == 0) 254 vt_entries = 64; 255 _vm->game.state = f.readByte(); 256 /* game.name - not saved */ 257 read_string(&f, id); 258 if (strcmp(id, _vm->game.id)) { 259 f.close(); 241 in->read(description, 31); 242 243 debugC(6, kDebugLevelMain | kDebugLevelSavegame, "Description is: %s", description); 244 245 saveVersion = in->readByte(); 246 if (saveVersion != SAVEGAME_VERSION) 247 warning("Old save game version (%d, current version is %d). Will try and read anyway, but don't be surprised if bad things happen", saveVersion, SAVEGAME_VERSION); 248 249 game.state = in->readByte(); 250 251 in->read(loadId, 8); 252 if (strcmp(loadId, game.id)) { 253 delete in; 254 warning("This save seems to be from a different AGI game (save from %s, running %s), not loaded", loadId, game.id); 260 255 return err_BadFileOpen; 261 256 } 262 /* game.crc - not saved */263 257 264 258 for (i = 0; i < MAX_FLAGS; i++) 265 _vm->game.flags[i] = f.readByte();259 game.flags[i] = in->readByte(); 266 260 for (i = 0; i < MAX_VARS; i++) 267 _vm->game.vars[i] = f.readByte();261 game.vars[i] = in->readByte(); 268 262 269 _vm->game.horizon = f.readSint16BE();270 _vm->game.line_status = f.readSint16BE();271 _vm->game.line_user_input = f.readSint16BE();272 _vm->game.line_min_print = f.readSint16BE();273 263 game.horizon = in->readSint16BE(); 264 game.line_status = in->readSint16BE(); 265 game.line_user_input = in->readSint16BE(); 266 game.line_min_print = in->readSint16BE(); 267 274 268 /* These are never saved */ 275 _vm->game.cursor_pos = 0;276 _vm->game.input_buffer[0] = 0;277 _vm->game.echo_buffer[0] = 0;278 _vm->game.keypress = 0;269 game.cursor_pos = 0; 270 game.input_buffer[0] = 0; 271 game.echo_buffer[0] = 0; 272 game.keypress = 0; 279 273 280 _vm->game.input_mode = f.readSint16BE();281 _vm->game.lognum = f.readSint16BE();274 game.input_mode = in->readSint16BE(); 275 game.lognum = in->readSint16BE(); 282 276 283 _vm->game.player_control = f.readSint16BE();284 _vm->game.quit_prog_now = f.readSint16BE();285 _vm->game.status_line = f.readSint16BE();286 _vm->game.clock_enabled = f.readSint16BE();287 _vm->game.exit_all_logics = f.readSint16BE();288 _vm->game.picture_shown = f.readSint16BE();289 _vm->game.has_prompt = f.readSint16BE();290 _vm->game.game_flags = f.readSint16BE();291 _vm->game.input_enabled = !f.readSint16BE();277 game.player_control = in->readSint16BE(); 278 game.quit_prog_now = in->readSint16BE(); 279 game.status_line = in->readSint16BE(); 280 game.clock_enabled = in->readSint16BE(); 281 game.exit_all_logics = in->readSint16BE(); 282 game.picture_shown = in->readSint16BE(); 283 game.has_prompt = in->readSint16BE(); 284 game.game_flags = in->readSint16BE(); 285 game.input_enabled = in->readSint16BE(); 292 286 293 287 for (i = 0; i < _HEIGHT; i++) 294 _vm->game.pri_table[i] = f.readByte();288 game.pri_table[i] = in->readByte(); 295 289 296 if ( _vm->game.has_window)297 _vm->close_window();290 if (game.has_window) 291 close_window(); 298 292 299 _vm->game.msg_box_ticks = 0;300 _vm->game.block.active = false;293 game.msg_box_ticks = 0; 294 game.block.active = false; 301 295 /* game.window - fixed by close_window() */ 302 296 /* game.has_window - fixed by close_window() */ 303 297 304 _vm->game.gfx_mode = f.readSint16BE();305 _vm->game.cursor_char = f.readByte();306 _vm->game.color_fg = f.readSint16BE();307 _vm->game.color_bg = f.readSint16BE();298 game.gfx_mode = in->readSint16BE(); 299 game.cursor_char = in->readByte(); 300 game.color_fg = in->readSint16BE(); 301 game.color_bg = in->readSint16BE(); 308 302 309 303 /* game.hires - rebuilt from image stack */ 310 304 /* game.sbuf - rebuilt from image stack */ … … 312 306 /* game.ego_words - fixed by clean_input */ 313 307 /* game.num_ego_words - fixed by clean_input */ 314 308 315 _vm->game.num_objects = f.readSint16BE();316 for (i = 0; i < (int16) _vm->game.num_objects; i++)317 _vm->object_set_location(i, f.readSint16BE());309 game.num_objects = in->readSint16BE(); 310 for (i = 0; i < (int16)game.num_objects; i++) 311 object_set_location(i, in->readSint16BE()); 318 312 319 313 /* Those are not serialized */ 320 314 for (i = 0; i < MAX_DIRS; i++) { 321 _vm->game.ev_keyp[i].occured = false;315 game.ev_keyp[i].occured = false; 322 316 } 323 317 324 318 for (i = 0; i < MAX_STRINGS; i++) 325 read_string(&f, _vm->game.strings[i]);319 in->read(game.strings[i], MAX_STRINGLEN); 326 320 327 321 for (i = 0; i < MAX_DIRS; i++) { 328 if ( f.readByte() & RES_LOADED)329 _vm->agiLoadResource(rLOGIC, i);322 if (in->readByte() & RES_LOADED) 323 agiLoadResource(rLOGIC, i); 330 324 else 331 _vm->agiUnloadResource(rLOGIC, i);332 _vm->game.logics[i].sIP = f.readSint16BE();333 _vm->game.logics[i].cIP = f.readSint16BE();325 agiUnloadResource(rLOGIC, i); 326 game.logics[i].sIP = in->readSint16BE(); 327 game.logics[i].cIP = in->readSint16BE(); 334 328 } 335 329 336 330 for (i = 0; i < MAX_DIRS; i++) { 337 if ( f.readByte() & RES_LOADED)338 _vm->agiLoadResource(rPICTURE, i);331 if (in->readByte() & RES_LOADED) 332 agiLoadResource(rPICTURE, i); 339 333 else 340 _vm->agiUnloadResource(rPICTURE, i);334 agiUnloadResource(rPICTURE, i); 341 335 } 342 336 343 337 for (i = 0; i < MAX_DIRS; i++) { 344 if ( f.readByte() & RES_LOADED)345 _vm->agiLoadResource(rVIEW, i);338 if (in->readByte() & RES_LOADED) 339 agiLoadResource(rVIEW, i); 346 340 else 347 _vm->agiUnloadResource(rVIEW, i);341 agiUnloadResource(rVIEW, i); 348 342 } 349 343 350 344 for (i = 0; i < MAX_DIRS; i++) { 351 if ( f.readByte() & RES_LOADED)352 _vm->agiLoadResource(rSOUND, i);345 if (in->readByte() & RES_LOADED) 346 agiLoadResource(rSOUND, i); 353 347 else 354 _vm->agiUnloadResource(rSOUND, i);348 agiUnloadResource(rSOUND, i); 355 349 } 356 350 357 351 /* game.pictures - loaded above */ … … 360 354 /* game.sounds - loaded above */ 361 355 362 356 for (i = 0; i < vt_entries; i++) { 363 struct vt_entry *v = & _vm->game.view_table[i];357 struct vt_entry *v = &game.view_table[i]; 364 358 365 v->step_time = f.readByte();366 v->step_time_count = f.readByte();367 v->entry = f.readByte();368 v->x_pos = f.readSint16BE();369 v->y_pos = f.readSint16BE();370 v->current_view = f.readByte();359 v->step_time = in->readByte(); 360 v->step_time_count = in->readByte(); 361 v->entry = in->readByte(); 362 v->x_pos = in->readSint16BE(); 363 v->y_pos = in->readSint16BE(); 364 v->current_view = in->readByte(); 371 365 372 366 /* v->view_data - fixed below */ 373 367 374 v->current_loop = f.readByte();375 v->num_loops = f.readByte();368 v->current_loop = in->readByte(); 369 v->num_loops = in->readByte(); 376 370 377 371 /* v->loop_data - fixed below */ 378 372 379 v->current_cel = f.readByte();380 v->num_cels = f.readByte();373 v->current_cel = in->readByte(); 374 v->num_cels = in->readByte(); 381 375 382 376 /* v->cel_data - fixed below */ 383 377 /* v->cel_data_2 - fixed below */ 384 378 385 v->x_pos2 = f.readSint16BE();386 v->y_pos2 = f.readSint16BE();379 v->x_pos2 = in->readSint16BE(); 380 v->y_pos2 = in->readSint16BE(); 387 381 388 382 /* v->s - fixed below */ 389 383 390 v->x_size = f.readSint16BE();391 v->y_size = f.readSint16BE();392 v->step_size = f.readByte();393 v->cycle_time = f.readByte();394 v->cycle_time_count = f.readByte();395 v->direction = f.readByte();384 v->x_size = in->readSint16BE(); 385 v->y_size = in->readSint16BE(); 386 v->step_size = in->readByte(); 387 v->cycle_time = in->readByte(); 388 v->cycle_time_count = in->readByte(); 389 v->direction = in->readByte(); 396 390 397 v->motion = f.readByte();398 v->cycle = f.readByte();399 v->priority = f.readByte();391 v->motion = in->readByte(); 392 v->cycle = in->readByte(); 393 v->priority = in->readByte(); 400 394 401 v->flags = f.readUint16BE();395 v->flags = in->readUint16BE(); 402 396 403 v->parm1 = f.readByte();404 v->parm2 = f.readByte();405 v->parm3 = f.readByte();406 v->parm4 = f.readByte();397 v->parm1 = in->readByte(); 398 v->parm2 = in->readByte(); 399 v->parm3 = in->readByte(); 400 v->parm4 = in->readByte(); 407 401 } 408 402 for (i = vt_entries; i < MAX_VIEWTABLE; i++) { 409 memset(& _vm->game.view_table[i], 0, sizeof(struct vt_entry));403 memset(&game.view_table[i], 0, sizeof(struct vt_entry)); 410 404 } 411 405 412 406 /* Fix some pointers in viewtable */ 413 407 414 408 for (i = 0; i < MAX_VIEWTABLE; i++) { 415 struct vt_entry *v = & _vm->game.view_table[i];409 struct vt_entry *v = &game.view_table[i]; 416 410 417 if ( _vm->game.dir_view[v->current_view].offset == _EMPTY)411 if (game.dir_view[v->current_view].offset == _EMPTY) 418 412 continue; 419 413 420 if (!( _vm->game.dir_view[v->current_view].flags & RES_LOADED))421 _vm->agiLoadResource(rVIEW, v->current_view);414 if (!(game.dir_view[v->current_view].flags & RES_LOADED)) 415 agiLoadResource(rVIEW, v->current_view); 422 416 423 _vm->set_view(v, v->current_view); /* Fix v->view_data */424 _vm->set_loop(v, v->current_loop); /* Fix v->loop_data */425 _vm->set_cel(v, v->current_cel); /* Fix v->cel_data */417 set_view(v, v->current_view); /* Fix v->view_data */ 418 set_loop(v, v->current_loop); /* Fix v->loop_data */ 419 set_cel(v, v->current_cel); /* Fix v->cel_data */ 426 420 v->cel_data_2 = v->cel_data; 427 421 v->s = NULL; /* not sure if it is used... */ 428 422 } … … 431 425 432 426 /* Clear input line */ 433 427 _gfx->clearScreen(0); 434 _vm->write_status();428 write_status(); 435 429 436 430 /* Recreate background from saved image stack */ 437 _vm->clear_image_stack();438 while ((t = f.readByte()) != 0) {431 clear_image_stack(); 432 while ((t = in->readByte()) != 0) { 439 433 for (i = 0; i < 7; i++) 440 parm[i] = f.readSint16BE();441 _vm->replay_image_stack_call(t, parm[0], parm[1], parm[2],434 parm[i] = in->readSint16BE(); 435 replay_image_stack_call(t, parm[0], parm[1], parm[2], 442 436 parm[3], parm[4], parm[5], parm[6]); 443 437 } 444 438 445 f.close(); 439 delete in; 440 debugC(3, kDebugLevelMain | kDebugLevelSavegame, "Closed %s", fileName); 446 441 447 _vm->setflag(F_restore_just_ran, true);442 setflag(F_restore_just_ran, true); 448 443 449 _vm->game.has_prompt = 0; /* force input line repaint if necessary */450 _vm->clean_input();444 game.has_prompt = 0; /* force input line repaint if necessary */ 445 clean_input(); 451 446 452 447 _sprites->erase_both(); 453 448 _sprites->blit_both(); … … 460 455 461 456 #define NUM_SLOTS 12 462 457 463 int SaveGameMgr::select_slot() { 458 const char *AgiEngine::getSavegameFilename(int num) { 459 static char saveLoadSlot[12]; 460 sprintf(saveLoadSlot, "%s.%.3d", _targetName.c_str(), num); 461 return saveLoadSlot; 462 } 463 464 int AgiEngine::selectSlot() { 464 465 int i, key, active = 0; 465 466 int rc = -1; 466 467 int hm = 2, vm = 3; /* box margins */ 467 468 char desc[NUM_SLOTS][40]; 468 469 469 470 for (i = 0; i < NUM_SLOTS; i++) { 470 char name[MAX_PATH];471 Common:: File f;472 char sig[8];473 // FIXME: Do *not* use Common::File to access savegames, it is not portable!474 sprintf( name, "%s/%05X_%s_%02d.sav", _vm->_savePath, _vm->game.crc, _vm->game.id, i);475 f.open(name);476 if (!f.isOpen()) {471 char fileName[MAX_PATH]; 472 Common::InSaveFile *in; 473 474 debugC(4, kDebugLevelMain | kDebugLevelSavegame, "Game id seems to be %s", _targetName.c_str()); 475 sprintf(fileName, "%s", getSavegameFilename(i)); 476 if (!(in = _saveFileMan->openForLoading(fileName))) { 477 debugC(4, kDebugLevelMain | kDebugLevelSavegame, "File %s does not exist", fileName); 477 478 strcpy(desc[i], " (empty slot)"); 478 479 } else { 479 read_bytes(&f, sig, 8); 480 if (strncmp(sig, strSig, 8)) { 480 debugC(4, kDebugLevelMain | kDebugLevelSavegame, "Successfully opened %s for reading", fileName); 481 uint32 type = in->readUint32BE(); 482 if (type == AGIflag) { 483 debugC(6, kDebugLevelMain | kDebugLevelSavegame, "Has AGI flag, good start"); 484 in->read(desc[i], 31); 485 } else { 486 warning("This doesn't appear to be an AGI savegame"); 481 487 strcpy(desc[i], "(corrupt file)"); 482 } else { 483 read_string(&f, desc[i]); 484 } 485 f.close(); 488 } 489 490 delete in; 486 491 } 487 492 } 488 493 … … 490 495 char dstr[64]; 491 496 for (i = 0; i < NUM_SLOTS; i++) { 492 497 sprintf(dstr, "[%-32.32s]", desc[i]); 493 _vm->print_text(dstr, 0, hm + 1, vm + 4 + i,498 print_text(dstr, 0, hm + 1, vm + 4 + i, 494 499 (40 - 2 * hm) - 1, i == active ? MSG_BOX_COLOUR : MSG_BOX_TEXT, 495 500 i == active ? MSG_BOX_TEXT : MSG_BOX_COLOUR); 496 501 497 502 } 498 503 499 504 _gfx->pollTimer(); /* msdos driver -> does nothing */ 500 key = _vm->do_poll_keyboard();505 key = do_poll_keyboard(); 501 506 switch (key) { 502 507 case KEY_ENTER: 503 508 rc = active; 504 strncpy( _vm->game.strings[MAX_STRINGS], desc[i], MAX_STRINGLEN);509 strncpy(game.strings[MAX_STRINGS], desc[i], MAX_STRINGLEN); 505 510 goto press; 506 511 case KEY_ESCAPE: 507 512 rc = -1; … … 525 530 debugC(8, kDebugLevelMain | kDebugLevelInput, "Button pressed: %d", rc); 526 531 527 532 getout: 528 _vm->close_window();533 close_window(); 529 534 return rc; 530 535 } 531 536 532 int SaveGameMgr::savegame_simple() { 533 char path[MAX_PATH]; 534 535 sprintf(path, "%s/%05X_%s_%02d.sav", _vm->_savePath, _vm->game.crc, _vm->game.id, 0); 536 save_game(path, "Default savegame"); 537 538 return err_OK; 539 } 540 541 int SaveGameMgr::savegame_dialog() { 542 char path[MAX_PATH]; 537 int AgiEngine::saveGameDialog() { 538 char fileName[MAX_PATH]; 543 539 char *desc; 544 540 const char *buttons[] = { "Do as I say!", "I regret", NULL }; 545 541 char dstr[200]; 546 542 int rc, slot = 0; 547 int hm, vm, hp, vp; /* box margins */543 int hm, vm, hp, vp; 548 544 int w; 549 545 550 546 hm = 2; … … 553 549 vp = vm * CHAR_LINES; 554 550 w = (40 - 2 * hm) - 1; 555 551 556 sprintf( path, "%s/%05X_%s_%02d.sav", _vm->_savePath, _vm->game.crc, _vm->game.id, slot);552 sprintf(fileName, "%s", getSavegameFilename(slot)); 557 553 558 _vm->draw_window(hp, vp, GFX_WIDTH - hp, GFX_HEIGHT - vp);559 _vm->print_text("Select a slot in which you wish to save the game:",554 draw_window(hp, vp, GFX_WIDTH - hp, GFX_HEIGHT - vp); 555 print_text("Select a slot in which you wish to save the game:", 560 556 0, hm + 1, vm + 1, w, MSG_BOX_TEXT, MSG_BOX_COLOUR); 561 _vm->print_text("Press ENTER to select, ESC cancels",557 print_text("Press ENTER to select, ESC cancels", 562 558 0, hm + 1, vm + 17, w, MSG_BOX_TEXT, MSG_BOX_COLOUR); 563 559 564 slot = select _slot();565 if (slot < 0) /* ESC pressed */560 slot = selectSlot(); 561 if (slot < 0) 566 562 return err_OK; 567 563 568 /* Get savegame description */ 569 _vm->draw_window(hp, vp + 5 * CHAR_LINES, GFX_WIDTH - hp, 564 draw_window(hp, vp + 5 * CHAR_LINES, GFX_WIDTH - hp, 570 565 GFX_HEIGHT - vp - 9 * CHAR_LINES); 571 _vm->print_text("Enter a description for this game:",566 print_text("Enter a description for this game:", 572 567 0, hm + 1, vm + 6, w, MSG_BOX_TEXT, MSG_BOX_COLOUR); 573 568 _gfx->drawRectangle(3 * CHAR_COLS, 11 * CHAR_LINES - 1, 574 569 37 * CHAR_COLS, 12 * CHAR_LINES, MSG_BOX_TEXT); 575 570 _gfx->flushBlock(3 * CHAR_COLS, 11 * CHAR_LINES - 1, 576 571 37 * CHAR_COLS, 12 * CHAR_LINES); 577 572 578 _vm->get_string(2, 11, 33, MAX_STRINGS);579 _gfx->printCharacter(3, 11, _vm->game.cursor_char, MSG_BOX_COLOUR, MSG_BOX_TEXT);573 get_string(2, 11, 33, MAX_STRINGS); 574 _gfx->printCharacter(3, 11, game.cursor_char, MSG_BOX_COLOUR, MSG_BOX_TEXT); 580 575 do { 581 _vm->main_cycle();582 } while ( _vm->game.input_mode == INPUT_GETSTRING);583 _vm->close_window();576 main_cycle(); 577 } while (game.input_mode == INPUT_GETSTRING); 578 close_window(); 584 579 585 desc = _vm->game.strings[MAX_STRINGS];580 desc = game.strings[MAX_STRINGS]; 586 581 sprintf(dstr, "Are you sure you want to save the game " 587 582 "described as:\n\n%s\n\nin slot %d?\n\n\n", desc, slot); 588 583 589 rc = _vm->selection_box(dstr, buttons);584 rc = selection_box(dstr, buttons); 590 585 591 586 if (rc != 0) { 592 _vm->message_box("Game NOT saved.");587 message_box("Game NOT saved."); 593 588 return err_OK; 594 589 } 595 590 596 sprintf( path, "%s/%05X_%s_%02d.sav", _vm->_savePath, _vm->game.crc, _vm->game.id, slot);597 debugC(8, kDebugLevelMain | kDebugLevelResources, "file is [%s]", path);591 sprintf(fileName, "%s", getSavegameFilename(slot)); 592 debugC(8, kDebugLevelMain | kDebugLevelResources, "file is [%s]", fileName); 598 593 599 save _game(path, desc);594 saveGame(fileName, desc); 600 595 601 _vm->message_box("Game saved.");596 message_box("Game saved."); 602 597 603 598 return err_OK; 604 599 } 605 600 606 int SaveGameMgr::loadgame_simple() { 607 char path[MAX_PATH]; 608 int rc = 0; 601 int AgiEngine::saveGameSimple() { 602 char fileName[MAX_PATH]; 609 603 610 sprintf(path, "%s/%05X_%s_%02d.sav", _vm->_savePath, _vm->game.crc, _vm->game.id, 0); 604 sprintf(fileName, "%s", getSavegameFilename(0)); 605 saveGame(fileName, "Default savegame"); 611 606 612 _sprites->erase_both(); 613 _sound->stop_sound(); 614 _vm->close_window(); 615 616 if ((rc = load_game(path)) == err_OK) { 617 _vm->message_box("Game restored."); 618 _vm->game.exit_all_logics = 1; 619 _vm->menu->enable_all(); 620 } else { 621 _vm->message_box("Error restoring game."); 622 } 623 624 return rc; 607 return err_OK; 625 608 } 626 609 627 int SaveGameMgr::loadgame_dialog() {628 char path[MAX_PATH];610 int AgiEngine::loadGameDialog() { 611 char fileName[MAX_PATH]; 629 612 int rc, slot = 0; 630 613 int hm, vm, hp, vp; /* box margins */ 631 614 int w; … … 636 619 vp = vm * CHAR_LINES; 637 620 w = (40 - 2 * hm) - 1; 638 621 639 sprintf( path, "%s/%05X_%s_%02d.sav", _vm->_savePath, _vm->game.crc, _vm->game.id, slot);622 sprintf(fileName, "%s", getSavegameFilename(slot)); 640 623 641 624 _sprites->erase_both(); 642 625 _sound->stop_sound(); 643 626 644 _vm->draw_window(hp, vp, GFX_WIDTH - hp, GFX_HEIGHT - vp);645 _vm->print_text("Select a game which you wish to\nrestore:",627 draw_window(hp, vp, GFX_WIDTH - hp, GFX_HEIGHT - vp); 628 print_text("Select a game which you wish to\nrestore:", 646 629 0, hm + 1, vm + 1, w, MSG_BOX_TEXT, MSG_BOX_COLOUR); 647 _vm->print_text("Press ENTER to select, ESC cancels",630 print_text("Press ENTER to select, ESC cancels", 648 631 0, hm + 1, vm + 17, w, MSG_BOX_TEXT, MSG_BOX_COLOUR); 649 632 650 slot = select _slot();633 slot = selectSlot(); 651 634 652 635 if (slot < 0) { 653 _vm->message_box("Game NOT restored.");636 message_box("Game NOT restored."); 654 637 return err_OK; 655 638 } 656 639 657 sprintf( path, "%s/%05X_%s_%02d.sav", _vm->_savePath, _vm->game.crc, _vm->game.id, slot);640 sprintf(fileName, "%s", getSavegameFilename(slot)); 658 641 659 if ((rc = load _game(path)) == err_OK) {660 _vm->message_box("Game restored.");661 _vm->game.exit_all_logics = 1;662 _vm->menu->enable_all();642 if ((rc = loadGame(fileName)) == err_OK) { 643 message_box("Game restored."); 644 game.exit_all_logics = 1; 645 menu->enable_all(); 663 646 } else { 664 _vm->message_box("Error restoring game.");647 message_box("Error restoring game."); 665 648 } 666 649 667 650 return rc; 668 651 } 669 652 653 int AgiEngine::loadGameSimple() { 654 char fileName[MAX_PATH]; 655 int rc = 0; 656 657 sprintf(fileName, "%s", getSavegameFilename(0)); 658 659 _sprites->erase_both(); 660 _sound->stop_sound(); 661 close_window(); 662 663 if ((rc = loadGame(fileName)) == err_OK) { 664 message_box("Game restored."); 665 game.exit_all_logics = 1; 666 menu->enable_all(); 667 } else { 668 message_box("Error restoring game."); 669 } 670 671 return rc; 672 } 673 670 674 } // End of namespace Agi -
engines/agi/agi.h
152 152 kDebugLevelMenu = 1 << 5, 153 153 kDebugLevelScripts = 1 << 6, 154 154 kDebugLevelSound = 1 << 7, 155 kDebugLevelText = 1 << 8 155 kDebugLevelText = 1 << 8, 156 kDebugLevelSavegame = 1 << 9 156 157 }; 157 158 158 159 /** … … 486 487 class GfxMgr; 487 488 class SpritesMgr; 488 489 class Menu; 489 class SaveGameMgr;490 490 491 491 extern struct Mouse g_mouse; 492 492 … … 557 557 Common::RandomSource *_rnd; 558 558 const char *_savePath; 559 559 560 const char *getSavegameFilename(int num); 561 int selectSlot(); 562 int saveGame(const char *fileName, const char *saveName); 563 int saveGameDialog(); 564 int saveGameSimple(); 565 int loadGame(const char *fileName); 566 int loadGameDialog(); 567 int loadGameSimple(); 568 560 569 volatile uint32 clock_count; 561 570 562 571 uint8 *intobj; … … 569 578 GfxMgr *_gfx; 570 579 SoundMgr *_sound; 571 580 PictureMgr *_picture; 572 SaveGameMgr *_saveGameMgr;573 581 574 582 #define INITIAL_IMAGE_STACK_SIZE 32 575 583 -
engines/agi/savegame.h
27 27 28 28 #include "agi/agi.h" 29 29 30 class Common::File;30 //class Common::File; 31 31 32 32 namespace Agi { 33 33 … … 40 40 class SoundMgr; 41 41 class PictureMgr; 42 42 43 class SaveGameMgr {44 private:45 46 AgiEngine *_vm;47 SpritesMgr *_sprites;48 GfxMgr *_gfx;49 SoundMgr *_sound;50 PictureMgr *_picture;51 52 void write_string(Common::File *f, const char *s);53 void read_string(Common::File *f, char *s);54 void write_bytes(Common::File *f, const char *s, int16 size);55 void read_bytes(Common::File *f, char *s, int16 size);56 int save_game(char *s, const char *d);57 int load_game(char *s);58 int select_slot();59 60 public:61 SaveGameMgr(AgiEngine *agi, SpritesMgr *sprites,62 GfxMgr *gfx,63 SoundMgr *sound, PictureMgr *picture) {64 _vm = agi;65 _sprites = sprites;66 _gfx = gfx;67 _sound = sound;68 _picture = picture;69 }70 71 int savegame_dialog();72 int loadgame_dialog();73 int savegame_simple();74 int loadgame_simple();75 };76 77 43 } // End of namespace Agi 78 44 79 45 #endif /* AGI_SAVEGAME_H */