Ticket #8452: scumm_info_v4.patch
File scumm_info_v4.patch, 18.2 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 if (!saveMode) { 235 _removeButton = addButton(this, _x + 10, _h - kButtonHeight - 8, "Remove", kRemoveCmd, 0, GUI::kNormalWidgetSize); 236 _removeButton->setEnabled(false); 237 } else 238 _removeButton = 0; 226 239 } 227 240 228 241 const Common::String &SaveLoadChooser::getResultString() const { … … 241 254 } 242 255 } 243 256 break; 257 case kRemoveCmd: { 258 if (!_saveMode) { 259 GUI::MessageDialog alert("Do you really want to remove this savegame?", "Yes", "No"); 260 if (alert.runModal() == GUI::kMessageOK) { 261 if (_scumm->removeState(selItem)) { 262 GUI::TimedMessageDialog msg("Removed savegame successfully", 1000); 263 msg.runModal(); 264 setList(generateSavegameList(_scumm, false)); 265 } else { 266 GUI::TimedMessageDialog msg("Couldn't remove savegame", 1000); 267 msg.runModal(); 268 } 269 } 270 _list->draw(); 271 _chooseButton->setEnabled(false); 272 _chooseButton->draw(); 273 _removeButton->setEnabled(false); 274 _removeButton->draw(); 275 } 276 } break; 244 277 case GUI::kListSelectionChangedCmd: 245 278 if (_saveMode) { 246 279 _list->startEditMode(); … … 250 283 // because we then just assign a default name. 251 284 _chooseButton->setEnabled(selItem >= 0 && (_saveMode || !getResultString().isEmpty())); 252 285 _chooseButton->draw(); 286 287 if (!_saveMode) { 288 _removeButton->setEnabled(selItem >= 0 && !getResultString().isEmpty()); 289 _removeButton->draw(); 290 } 253 291 break; 254 292 default: 255 293 GUI_ChooserDialog::handleCommand(sender, cmd, data); … … 270 308 bool _saveMode; 271 309 GUI::ListWidget *_list; 272 310 GUI::ButtonWidget *_chooseButton; 311 GUI::ButtonWidget *_removeButton; 273 312 GUI::GraphicsWidget *_gfxWidget; 313 GUI::StaticTextWidget *_date; 314 GUI::StaticTextWidget *_time; 315 GUI::StaticTextWidget *_playtime; 274 316 ScummEngine *_scumm; 275 317 276 318 public: … … 300 342 ((_scumm->_system->getHeight() % 200 && _scumm->_system->getHeight() != 350) ? kThumbnailHeight2 : kThumbnailHeight1) + 8); 301 343 _gfxWidget->setFlags(GUI::WIDGET_BORDER); 302 344 345 int height = 18 + ((_scumm->_system->getHeight() % 200 && _scumm->_system->getHeight() != 350) ? kThumbnailHeight2 : kThumbnailHeight1) + 8; 346 347 _date = new StaticTextWidget(this, 348 _w - (kThumbnailWidth + 22), 349 height, 350 kThumbnailWidth + 8, 351 kLineHeight, 352 "Date: 00.00.0000", 353 kTextAlignCenter); 354 _date->setFlags(GUI::WIDGET_CLEARBG); 355 356 height += kLineHeight; 357 358 _time = new StaticTextWidget(this, 359 _w - (kThumbnailWidth + 22), 360 height, 361 kThumbnailWidth + 8, 362 kLineHeight, 363 "Time: 00:00", 364 kTextAlignCenter); 365 _time->setFlags(GUI::WIDGET_CLEARBG); 366 367 height += kLineHeight; 368 369 _playtime = new StaticTextWidget(this, 370 _w - (kThumbnailWidth + 22), 371 height, 372 kThumbnailWidth + 8, 373 kLineHeight, 374 "Playtime: 00:00", 375 kTextAlignCenter); 376 _playtime->setFlags(GUI::WIDGET_CLEARBG); 377 303 378 // Buttons 379 if (!saveMode) { 380 _removeButton = addButton(this, _x + 10, _h - kBigButtonHeight - 8, "Remove", kRemoveCmd, 0, GUI::kBigWidgetSize); 381 _removeButton->setEnabled(false); 382 } else 383 _removeButton = 0; 304 384 addButton(this, _w - 2 * (kBigButtonWidth + 10), _h - kBigButtonHeight - 8, "Cancel", kCloseCmd, 0, GUI::kBigWidgetSize); 305 385 _chooseButton = addButton(this, _w - (kBigButtonWidth + 10), _h - kBigButtonHeight - 8, buttonLabel, kChooseCmd, 0, GUI::kBigWidgetSize); 306 386 _chooseButton->setEnabled(false); … … 338 418 setResult(selItem); 339 419 close(); 340 420 break; 421 case kRemoveCmd: { 422 if (!_saveMode) { 423 GUI::MessageDialog alert("Do you really want to remove this savegame?", "Yes", "No"); 424 if (alert.runModal() == GUI::kMessageOK) { 425 if (_scumm->removeState(selItem)) { 426 GUI::TimedMessageDialog msg("Removed savegame successfully", 1000); 427 msg.runModal(); 428 setList(generateSavegameList(_scumm, false)); 429 } else { 430 GUI::TimedMessageDialog msg("Couldn't remove savegame", 1000); 431 msg.runModal(); 432 } 433 } 434 _list->draw(); 435 _chooseButton->setEnabled(false); 436 _chooseButton->draw(); 437 _removeButton->setEnabled(false); 438 _removeButton->draw(); 439 } 440 } break; 341 441 case GUI::kListSelectionChangedCmd: { 342 442 Graphics::Surface *thumb; 343 443 thumb = _scumm->loadThumbnailFromSlot(_saveMode ? selItem + 1 : selItem); 344 444 _gfxWidget->setGfx(thumb); 445 if (thumb) 446 thumb->free(); 345 447 delete thumb; 346 448 _gfxWidget->draw(); 347 449 450 InfoStuff infos; 451 memset(&infos, 0, sizeof(InfoStuff)); 452 char buffer[32]; 453 if (_scumm->loadInfosFromSlot(_saveMode ? selItem + 1 : selItem, &infos)) { 454 snprintf(buffer, 32, "Date: %.2d.%.2d.%.4d", 455 (infos.date >> 24) & 0xFF, (infos.date >> 16) & 0xFF, 456 infos.date & 0xFFFF); 457 _date->setLabel(buffer); 458 _date->draw(); 459 460 snprintf(buffer, 32, "Time: %.2d:%.2d", 461 (infos.time >> 8) & 0xFF, infos.time & 0xFF); 462 _time->setLabel(buffer); 463 _time->draw(); 464 465 int minutes = infos.playtime / 60; 466 int hours = minutes / 60; 467 minutes %= 60; 468 469 snprintf(buffer, 32, "Playtime: %.2d:%.2d", 470 hours & 0xFF, minutes & 0xFF); 471 _playtime->setLabel(buffer); 472 _playtime->draw(); 473 } else { 474 snprintf(buffer, 32, "No date saved"); 475 _date->setLabel(buffer); 476 _date->draw(); 477 478 snprintf(buffer, 32, "No time saved"); 479 _time->setLabel(buffer); 480 _time->draw(); 481 482 snprintf(buffer, 32, "No playtime saved"); 483 _playtime->setLabel(buffer); 484 _playtime->draw(); 485 } 486 348 487 if (_saveMode) { 349 488 _list->startEditMode(); 350 489 } … … 353 492 // because we then just assign a default name. 354 493 _chooseButton->setEnabled(selItem >= 0 && (_saveMode || !getResultString().isEmpty())); 355 494 _chooseButton->draw(); 495 // same as above only that in save mode it is also disabled when choosing an 496 // empty savegame. 497 if (!_saveMode) { 498 _removeButton->setEnabled(selItem >= 0 && !getResultString().isEmpty()); 499 _removeButton->draw(); 500 } 356 501 } break; 357 502 case kCloseCmd: 358 503 setResult(-1); … … 452 597 _helpDialog = new HelpDialog(scumm); 453 598 #endif 454 599 if (scumm->_system->getOverlayWidth() <= 320) { 455 _saveDialog = new SaveLoadChooser("Save game:", "Save", true );456 _loadDialog = new SaveLoadChooser("Load game:", "Load", false );600 _saveDialog = new SaveLoadChooser("Save game:", "Save", true, scumm); 601 _loadDialog = new SaveLoadChooser("Load game:", "Load", false, scumm); 457 602 } else { 458 603 _saveDialog = new SaveLoadChooserEx("Save game:", "Save", true, scumm); 459 604 _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 2086 2086 #pragma mark - 2087 2087 2088 2088 int ScummEngine::go() { 2089 _engineStartTime = _system->getMillis() / 1000; 2090 2089 2091 // If requested, load a save game instead of running the boot script 2090 2092 if (_saveLoadFlag != 2 || !loadState(_saveLoadSlot, _saveTemporaryState)) { 2091 2093 int args[16]; … … 2522 2524 #pragma mark - 2523 2525 2524 2526 int ScummEngine::runDialog(Dialog &dialog) { 2527 _dialogStartTime = _system->getMillis() / 1000; 2528 2525 2529 // Pause sound & video 2526 2530 bool old_soundsPaused = _sound->_soundsPaused; 2527 2531 _sound->pauseSounds(true); … … 2537 2541 // Resume sound & video 2538 2542 _sound->pauseSounds(old_soundsPaused); 2539 2543 _smushPaused = oldSmushPaused; 2544 2545 _engineStartTime += (_system->getMillis() / 1000) - _dialogStartTime; 2546 _dialogStartTime = 0; 2540 2547 2541 2548 // Return the result 2542 2549 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 */