Ticket #8452: scumm_info_v3.patch
File scumm_info_v3.patch, 18.0 KB (added by , 19 years ago) |
---|
-
common/file.cpp
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/common/file.cpp ./scummvm/common/file.cpp
old new 100 100 return file; 101 101 } 102 102 103 static bool removeNoCase(const char *filename, const char *directory) { 104 char buf[512]; 105 char *ptr; 106 107 assert(directory); 108 strcpy(buf, directory); 109 110 #if !defined(__GP32__) && !defined(__PALM_OS__) 111 // Add a trailing slash, if necessary. 112 if (buf[0] != 0) { 113 const int dirLen = strlen(buf); 114 if (buf[dirLen-1] != ':' && buf[dirLen-1] != '/' && buf[dirLen-1] != '\\') 115 strcat(buf, "/"); 116 } 117 #endif 118 119 // Append the filename to the path string 120 const int offsetToFileName = strlen(buf); 121 strcat(buf, filename); 122 123 // 124 // Try to remove the file normally 125 // 126 if (remove(buf) == 0) 127 return true; 128 129 // 130 // Try again, with file name converted to upper case 131 // 132 ptr = buf + offsetToFileName; 133 while (*ptr) { 134 *ptr = toupper(*ptr); 135 ptr++; 136 } 137 if (remove(buf) == 0) 138 return true; 139 140 // 141 // Try again, with file name converted to lower case 142 // 143 ptr = buf + offsetToFileName; 144 while (*ptr) { 145 *ptr = tolower(*ptr); 146 ptr++; 147 } 148 if (remove(buf) == 0) 149 return true; 150 151 // 152 // Try again, with file name capitalized 153 // 154 ptr = buf + offsetToFileName; 155 *ptr = toupper(*ptr); 156 if (remove(buf) == 0) 157 return true; 158 159 return false; 160 } 161 103 162 void File::addDefaultDirectory(const String &directory) { 104 163 _defaultDirectories.push_back(directory); 105 164 } … … 186 245 // FIXME: Ugly ugly hack! 187 246 File tmp; 188 247 return tmp.open(filename, kFileReadMode, directory); 248 } 249 250 bool File::remove(const char *filename, const char *directory) { 251 if (!exists(filename, directory)) 252 return false; 253 254 bool removed = false; 255 256 if (directory) { 257 if (removeNoCase(filename, directory)) 258 removed = true; 259 } else { 260 // removes all files with this name in the standard directories 261 StringList::const_iterator x; 262 for (x = _defaultDirectories.begin(); x != _defaultDirectories.end(); ++x) { 263 if (removeNoCase(filename, x->c_str())) 264 removed = true; 265 } 266 } 267 268 if (!removed) { 269 debug(2, "Coudln't remove file '%s' (specified directory: '%s')", filename, directory); 270 } 271 272 return removed; 189 273 } 190 274 191 275 void File::close() { -
common/file.h
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/common/file.h ./scummvm/common/file.h
old new 63 63 64 64 virtual bool open(const char *filename, AccessMode mode = kFileReadMode, const char *directory = NULL); 65 65 static bool exists(const char *filename, const char *directory = NULL); 66 // this COULD remove whole directories, so use with caution 67 static bool remove(const char *filename, const char *directory = NULL); 66 68 67 69 virtual void close(); 68 70 bool isOpen() const; -
scumm/dialogs.cpp
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/scumm/dialogs.cpp ./scummvm/scumm/dialogs.cpp
old new 21 21 #include "common/stdafx.h" 22 22 23 23 #include "common/config-manager.h" 24 #include "common/savefile.h" 24 25 #include "common/system.h" 25 26 #include "common/scaler.h" 26 27 … … 28 29 #include "gui/chooser.h" 29 30 #include "gui/newgui.h" 30 31 #include "gui/ListWidget.h" 32 #include "gui/message.h" 31 33 32 34 #include "scumm/dialogs.h" 33 35 #include "scumm/sound.h" … … 193 195 194 196 #pragma mark - 195 197 198 Common::StringList generateSavegameList(ScummEngine *scumm, bool saveMode); 199 196 200 enum { 197 201 kSaveCmd = 'SAVE', 198 202 kLoadCmd = 'LOAD', 203 kRemoveCmd = 'REM ', 199 204 kPlayCmd = 'PLAY', 200 205 kOptionsCmd = 'OPTN', 201 206 kHelpCmd = 'HELP', … … 208 213 typedef Common::StringList StringList; 209 214 protected: 210 215 bool _saveMode; 216 GUI::ButtonWidget *_removeButton; 217 ScummEngine *_scumm; 211 218 212 219 public: 213 SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode );220 SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode, ScummEngine* scumm); 214 221 215 222 virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); 216 223 const String &getResultString() const; … … 218 225 int runModal() { return GUI_ChooserDialog::runModal(); } 219 226 }; 220 227 221 SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode )222 : GUI::ChooserDialog(title, buttonLabel, 182), _saveMode(saveMode) {228 SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode, ScummEngine* scumm) 229 : GUI::ChooserDialog(title, buttonLabel, 182), _saveMode(saveMode), _scumm(scumm) { 223 230 224 231 _list->setEditable(saveMode); 225 232 _list->setNumberingMode(saveMode ? GUI::kListNumberingOne : GUI::kListNumberingZero); 233 234 _removeButton = addButton(this, _x + 10, _h - kButtonHeight - 8, "Remove", kRemoveCmd, 0, GUI::kNormalWidgetSize); 235 _removeButton->setEnabled(false); 226 236 } 227 237 228 238 const Common::String &SaveLoadChooser::getResultString() const { … … 241 251 } 242 252 } 243 253 break; 254 case kRemoveCmd: { 255 GUI::MessageDialog alert("Do you really want to remove this savegame?", "Yes", "No"); 256 if (alert.runModal() == GUI::kMessageOK) { 257 if (_scumm->removeState(_saveMode ? selItem + 1 : selItem)) { 258 GUI::TimedMessageDialog msg("Removed savegame successfully", 1000); 259 msg.runModal(); 260 setList(generateSavegameList(_scumm, _saveMode)); 261 } else { 262 GUI::TimedMessageDialog msg("Couldn't remove savegame", 1000); 263 msg.runModal(); 264 } 265 } 266 _list->draw(); 267 _chooseButton->setEnabled(false); 268 _chooseButton->draw(); 269 _removeButton->setEnabled(false); 270 _removeButton->draw(); 271 } break; 244 272 case GUI::kListSelectionChangedCmd: 245 273 if (_saveMode) { 246 274 _list->startEditMode(); … … 250 278 // because we then just assign a default name. 251 279 _chooseButton->setEnabled(selItem >= 0 && (_saveMode || !getResultString().isEmpty())); 252 280 _chooseButton->draw(); 281 282 _removeButton->setEnabled(selItem >= 0 && !getResultString().isEmpty()); 283 _removeButton->draw(); 253 284 break; 254 285 default: 255 286 GUI_ChooserDialog::handleCommand(sender, cmd, data); … … 270 301 bool _saveMode; 271 302 GUI::ListWidget *_list; 272 303 GUI::ButtonWidget *_chooseButton; 304 GUI::ButtonWidget *_removeButton; 273 305 GUI::GraphicsWidget *_gfxWidget; 306 GUI::StaticTextWidget *_date; 307 GUI::StaticTextWidget *_time; 308 GUI::StaticTextWidget *_playtime; 274 309 ScummEngine *_scumm; 275 310 276 311 public: … … 300 335 ((_scumm->_system->getHeight() % 200 && _scumm->_system->getHeight() != 350) ? kThumbnailHeight2 : kThumbnailHeight1) + 8); 301 336 _gfxWidget->setFlags(GUI::WIDGET_BORDER); 302 337 338 int height = 18 + ((_scumm->_system->getHeight() % 200 && _scumm->_system->getHeight() != 350) ? kThumbnailHeight2 : kThumbnailHeight1) + 8; 339 340 _date = new StaticTextWidget(this, 341 _w - (kThumbnailWidth + 22), 342 height, 343 kThumbnailWidth + 8, 344 kLineHeight, 345 "Date: 00.00.0000", 346 kTextAlignCenter); 347 _date->setFlags(GUI::WIDGET_CLEARBG); 348 349 height += kLineHeight; 350 351 _time = new StaticTextWidget(this, 352 _w - (kThumbnailWidth + 22), 353 height, 354 kThumbnailWidth + 8, 355 kLineHeight, 356 "Time: 00:00", 357 kTextAlignCenter); 358 _time->setFlags(GUI::WIDGET_CLEARBG); 359 360 height += kLineHeight; 361 362 _playtime = new StaticTextWidget(this, 363 _w - (kThumbnailWidth + 22), 364 height, 365 kThumbnailWidth + 8, 366 kLineHeight, 367 "Playtime: 00:00", 368 kTextAlignCenter); 369 _playtime->setFlags(GUI::WIDGET_CLEARBG); 370 303 371 // Buttons 372 _removeButton = addButton(this, _x + 10, _h - kBigButtonHeight - 8, "Remove", kRemoveCmd, 0, GUI::kBigWidgetSize); 373 _removeButton->setEnabled(false); 304 374 addButton(this, _w - 2 * (kBigButtonWidth + 10), _h - kBigButtonHeight - 8, "Cancel", kCloseCmd, 0, GUI::kBigWidgetSize); 305 375 _chooseButton = addButton(this, _w - (kBigButtonWidth + 10), _h - kBigButtonHeight - 8, buttonLabel, kChooseCmd, 0, GUI::kBigWidgetSize); 306 376 _chooseButton->setEnabled(false); … … 338 408 setResult(selItem); 339 409 close(); 340 410 break; 411 case kRemoveCmd: { 412 GUI::MessageDialog alert("Do you really want to remove this savegame?", "Yes", "No"); 413 if (alert.runModal() == GUI::kMessageOK) { 414 if (_scumm->removeState(_saveMode ? selItem + 1 : selItem)) { 415 GUI::TimedMessageDialog msg("Removed savegame successfully", 1000); 416 msg.runModal(); 417 setList(generateSavegameList(_scumm, _saveMode)); 418 } else { 419 GUI::TimedMessageDialog msg("Couldn't remove savegame", 1000); 420 msg.runModal(); 421 } 422 } 423 _list->draw(); 424 _chooseButton->setEnabled(false); 425 _chooseButton->draw(); 426 _removeButton->setEnabled(false); 427 _removeButton->draw(); 428 } break; 341 429 case GUI::kListSelectionChangedCmd: { 342 430 Graphics::Surface *thumb; 343 431 thumb = _scumm->loadThumbnailFromSlot(_saveMode ? selItem + 1 : selItem); 344 432 _gfxWidget->setGfx(thumb); 433 if (thumb) 434 thumb->free(); 345 435 delete thumb; 346 436 _gfxWidget->draw(); 347 437 438 InfoStuff infos; 439 memset(&infos, 0, sizeof(InfoStuff)); 440 char buffer[32]; 441 if (_scumm->loadInfosFromSlot(_saveMode ? selItem + 1 : selItem, &infos)) { 442 snprintf(buffer, 32, "Date: %.2d.%.2d.%.4d", 443 (infos.date >> 24) & 0xFF, (infos.date >> 16) & 0xFF, 444 infos.date & 0xFFFF); 445 _date->setLabel(buffer); 446 _date->draw(); 447 448 snprintf(buffer, 32, "Time: %.2d:%.2d", 449 (infos.time >> 8) & 0xFF, infos.time & 0xFF); 450 _time->setLabel(buffer); 451 _time->draw(); 452 453 int minutes = infos.playtime / 60; 454 int hours = minutes / 60; 455 minutes %= 60; 456 457 snprintf(buffer, 32, "Playtime: %.2d:%.2d", 458 hours & 0xFF, minutes & 0xFF); 459 _playtime->setLabel(buffer); 460 _playtime->draw(); 461 } else { 462 snprintf(buffer, 32, "No date saved"); 463 _date->setLabel(buffer); 464 _date->draw(); 465 466 snprintf(buffer, 32, "No time saved"); 467 _time->setLabel(buffer); 468 _time->draw(); 469 470 snprintf(buffer, 32, "No playtime saved"); 471 _playtime->setLabel(buffer); 472 _playtime->draw(); 473 } 474 348 475 if (_saveMode) { 349 476 _list->startEditMode(); 350 477 } … … 353 480 // because we then just assign a default name. 354 481 _chooseButton->setEnabled(selItem >= 0 && (_saveMode || !getResultString().isEmpty())); 355 482 _chooseButton->draw(); 483 // same as above only that in save mode it is also disabled when choosing an 484 // empty savegame. 485 _removeButton->setEnabled(selItem >= 0 && !getResultString().isEmpty()); 486 _removeButton->draw(); 356 487 } break; 357 488 case kCloseCmd: 358 489 setResult(-1); … … 452 583 _helpDialog = new HelpDialog(scumm); 453 584 #endif 454 585 if (scumm->_system->getOverlayWidth() <= 320) { 455 _saveDialog = new SaveLoadChooser("Save game:", "Save", true );456 _loadDialog = new SaveLoadChooser("Load game:", "Load", false );586 _saveDialog = new SaveLoadChooser("Save game:", "Save", true, scumm); 587 _loadDialog = new SaveLoadChooser("Load game:", "Load", false, scumm); 457 588 } else { 458 589 _saveDialog = new SaveLoadChooserEx("Save game:", "Save", true, scumm); 459 590 _loadDialog = new SaveLoadChooserEx("Load game:", "Load", false, scumm); -
scumm/saveload.cpp
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/scumm/saveload.cpp ./scummvm/scumm/saveload.cpp
old new 51 51 char name[32]; 52 52 }; 53 53 54 struct SaveInfoHeader { 55 uint32 type; 56 uint32 size; 57 byte version; 58 59 uint32 date; 60 uint16 time; 61 uint32 playtime; 62 }; 63 64 #define INFOHEADER_VERSION 1 54 65 55 66 void ScummEngine::requestSave(int slot, const char *name, bool temporary) { 56 67 _saveLoadSlot = slot; … … 84 95 85 96 out->write(&hdr, sizeof(hdr)); 86 97 saveThumbnail(out); 98 saveInfos(out); 87 99 88 100 Serializer ser(0, out, CURRENT_VER); 89 101 saveOrLoad(&ser, CURRENT_VER); … … 111 123 } 112 124 113 125 // In older versions of ScummVM, the header version was not endian safe. 114 // We account for that by retrying once wi th swapped byte order.126 // We account for that by retrying once wi_system->getMillis() / 1000th swapped byte order. 115 127 if (hdr.ver > CURRENT_VER) 116 128 hdr.ver = SWAP_BYTES_32(hdr.ver); 117 129 if (hdr.ver < VER(7) || hdr.ver > CURRENT_VER) … … 144 156 in->skip(size - 8); 145 157 } 146 158 159 // Since version 56 we have informations about the creating of the save game and the save time here 160 if (hdr.ver >= VER(56)) { 161 InfoStuff infos; 162 if (!loadInfos(in, &infos)) { 163 delete in; 164 return false; 165 } 166 167 _engineStartTime = _system->getMillis() / 1000 - infos.playtime; 168 } else { 169 // start time counting 170 _engineStartTime = _system->getMillis() / 1000; 171 } 172 173 _dialogStartTime = _system->getMillis() / 1000; 174 147 175 // Due to a bug in scummvm up to and including 0.3.0, save games could be saved 148 176 // in the V8/V9 format but were tagged with a V7 mark. Ouch. So we just pretend V7 == V8 here 149 177 if (hdr.ver == VER(7)) … … 359 387 360 388 _sound->pauseSounds(false); 361 389 390 _engineStartTime += _system->getMillis() / 1000 - _dialogStartTime; 391 _dialogStartTime = 0; 392 362 393 return true; 363 394 } 364 395 … … 438 469 439 470 delete in; 440 471 return thumb; 472 } 473 474 bool ScummEngine::loadInfosFromSlot(int slot, InfoStuff *stuff) { 475 char filename[256]; 476 Common::InSaveFile *in; 477 SaveGameHeader hdr; 478 int len; 479 480 makeSavegameName(filename, slot, false); 481 if (!(in = _saveFileMan->openForLoading(filename))) { 482 return false; 483 } 484 len = in->read(&hdr, sizeof(hdr)); 485 486 if (len != sizeof(hdr) || hdr.type != MKID('SCVM')) { 487 delete in; 488 return false; 489 } 490 491 if (hdr.ver > CURRENT_VER) 492 hdr.ver = TO_LE_32(hdr.ver); 493 if (hdr.ver < VER(56)) { 494 delete in; 495 return false; 496 } 497 498 uint32 type; 499 in->read(&type, 4); 500 501 // Check for the THMB header. Also, work around a bug which caused 502 // the chunk type (incorrectly) to be written in LE on LE machines. 503 if (! (type == MKID('THMB') || (hdr.ver < VER(55) && type == MKID('BMHT')))){ 504 delete in; 505 return false; 506 } 507 uint32 size = in->readUint32BE(); 508 in->skip(size - 8); 509 510 if (!loadInfos(in, stuff)) { 511 delete in; 512 return false; 513 } 514 515 delete in; 516 return true; 517 } 518 519 bool ScummEngine::removeState(int slot) { 520 const char* savePath = _saveFileMan->getSavePath(); 521 char filename[256]; 522 makeSavegameName(filename, slot, false); 523 return Common::File::remove(filename, savePath); 524 } 525 526 bool ScummEngine::loadInfos(Common::InSaveFile *file, InfoStuff *stuff) { 527 SaveInfoHeader header; 528 file->read(&header.type, 4); 529 if (header.type != MKID('INFO')) { 530 warning("Couldn't load info section"); 531 return false; 532 } 533 534 header.version = file->readByte(); 535 if (header.version > INFOHEADER_VERSION) { 536 warning("Infoheader version is too high"); 537 return false; 538 } 539 540 header.size = file->readUint32BE(); 541 542 header.date = file->readUint32BE(); 543 header.time = file->readUint16BE(); 544 header.playtime = file->readUint32BE(); 545 546 stuff->date = header.date; 547 stuff->time = header.time; 548 stuff->playtime = header.playtime; 549 550 return true; 551 } 552 553 void ScummEngine::saveInfos(Common::OutSaveFile* file) { 554 SaveInfoHeader header; 555 header.type = MKID('INFO'); 556 header.version = INFOHEADER_VERSION; 557 header.size = sizeof(SaveInfoHeader); 558 559 time_t curTime_ = time(0); 560 tm *curTime = localtime(&curTime_); 561 header.date = (curTime->tm_mday & 0xFF) << 24 | ((curTime->tm_mon + 1) & 0xFF) << 16 | (curTime->tm_year + 1900) & 0xFFFF; 562 header.time = (curTime->tm_hour & 0xFF) << 8 | curTime->tm_min & 0xFF; 563 header.playtime = _system->getMillis() / 1000 - _engineStartTime; 564 565 file->write(&header.type, 4); 566 file->writeByte(header.version); 567 file->writeUint32BE(header.size); 568 file->writeUint32BE(header.date); 569 file->writeUint16BE(header.time); 570 file->writeUint32BE(header.playtime); 441 571 } 442 572 443 573 void ScummEngine::saveOrLoad(Serializer *s, uint32 savegameVersion) { -
scumm/saveload.h
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/scumm/saveload.h ./scummvm/scumm/saveload.h
old new 45 45 * only saves/loads those which are valid for the version of the savegame 46 46 * which is being loaded/saved currently. 47 47 */ 48 #define CURRENT_VER 5 548 #define CURRENT_VER 56 49 49 50 50 /** 51 51 * An auxillary macro, used to specify savegame versions. We use this instead -
scumm/scumm.cpp
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/scumm/scumm.cpp ./scummvm/scumm/scumm.cpp
old new 2012 2012 #pragma mark - 2013 2013 2014 2014 int ScummEngine::go() { 2015 _engineStartTime = _system->getMillis() / 1000; 2016 2015 2017 // If requested, load a save game instead of running the boot script 2016 2018 if (_saveLoadFlag != 2 || !loadState(_saveLoadSlot, _saveTemporaryState)) { 2017 2019 int args[16]; … … 2448 2450 #pragma mark - 2449 2451 2450 2452 int ScummEngine::runDialog(Dialog &dialog) { 2453 _dialogStartTime = _system->getMillis() / 1000; 2454 2451 2455 // Pause sound & video 2452 2456 bool old_soundsPaused = _sound->_soundsPaused; 2453 2457 _sound->pauseSounds(true); … … 2463 2467 // Resume sound & video 2464 2468 _sound->pauseSounds(old_soundsPaused); 2465 2469 _smushPaused = oldSmushPaused; 2470 2471 _engineStartTime += (_system->getMillis() / 1000) - _dialogStartTime; 2472 _dialogStartTime = 0; 2466 2473 2467 2474 // Return the result 2468 2475 return result; -
scumm/scumm.h
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/scumm/scumm.h ./scummvm/scumm/scumm.h
old new 309 309 int subIndex; 310 310 }; 311 311 312 struct InfoStuff { 313 uint32 date; 314 uint16 time; 315 uint32 playtime; 316 }; 317 312 318 class ResourceManager { 313 319 friend class ScummDebugger; 314 320 friend class ScummEngine; … … 582 588 void requestSave(int slot, const char *name, bool temporary = false); 583 589 void requestLoad(int slot); 584 590 585 // thumbnail stuff 591 bool removeState(int slot); 592 593 // thumbnail + info stuff 586 594 public: 587 595 Graphics::Surface *loadThumbnailFromSlot(int slot); 596 bool loadInfosFromSlot(int slot, InfoStuff *stuff); 588 597 589 598 protected: 590 599 Graphics::Surface *loadThumbnail(Common::InSaveFile *file); 600 bool loadInfos(Common::InSaveFile *file, InfoStuff *stuff); 591 601 void saveThumbnail(Common::OutSaveFile *file); 602 void saveInfos(Common::OutSaveFile* file); 603 604 int32 _engineStartTime; 605 int32 _dialogStartTime; 592 606 593 607 protected: 594 608 /* Script VM - should be in Script class */