diff options
-rw-r--r-- | engines/sci/engine/kfile.cpp | 162 | ||||
-rw-r--r-- | engines/sci/engine/kgraphics.cpp | 1 | ||||
-rw-r--r-- | engines/sci/engine/selector.cpp | 3 | ||||
-rw-r--r-- | engines/sci/engine/selector.h | 4 | ||||
-rw-r--r-- | engines/sci/engine/state.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/state.h | 12 | ||||
-rw-r--r-- | engines/sci/sci.cpp | 21 | ||||
-rw-r--r-- | engines/sci/sci.h | 6 |
8 files changed, 131 insertions, 80 deletions
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index a76c96cfea..2eb4580f4f 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -101,13 +101,9 @@ enum { -reg_t file_open(EngineState *s, const char *filename, int mode) { - // QfG3 character import prepends /\ to the filenames. - if (filename[0] == '/' && filename[1] == '\\') - filename += 2; - +reg_t file_open(EngineState *s, const char *filename, int mode, bool unwrapFilename) { Common::String englishName = g_sci->getSciLanguageString(filename, K_LANG_ENGLISH); - const Common::String wrappedName = g_sci->wrapFilename(englishName); + Common::String wrappedName = unwrapFilename ? g_sci->wrapFilename(englishName) : englishName; Common::SeekableReadStream *inFile = 0; Common::WriteStream *outFile = 0; Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); @@ -183,7 +179,7 @@ reg_t kFOpen(EngineState *s, int argc, reg_t *argv) { int mode = argv[1].toUint16(); debugC(2, kDebugLevelFile, "kFOpen(%s,0x%x)", name.c_str(), mode); - return file_open(s, name.c_str(), mode); + return file_open(s, name.c_str(), mode, true); } static FileHandle *getFileFromHandle(EngineState *s, uint handle) { @@ -739,45 +735,6 @@ reg_t kValidPath(EngineState *s, int argc, reg_t *argv) { return make_reg(0, 1); } -reg_t DirSeeker::firstFile(const Common::String &mask, reg_t buffer, SegManager *segMan) { - // Verify that we are given a valid buffer - if (!buffer.segment) { - error("DirSeeker::firstFile('%s') invoked with invalid buffer", mask.c_str()); - return NULL_REG; - } - _outbuffer = buffer; - - // Prefix the mask - const Common::String wrappedMask = g_sci->wrapFilename(mask); - - // Obtain a list of all savefiles matching the given mask - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); - _savefiles = saveFileMan->listSavefiles(wrappedMask); - - // Reset the list iterator and write the first match to the output buffer, - // if any. - _iter = _savefiles.begin(); - return nextFile(segMan); -} - -reg_t DirSeeker::nextFile(SegManager *segMan) { - if (_iter == _savefiles.end()) { - return NULL_REG; - } - - const Common::String wrappedString = *_iter; - - // Strip the prefix - Common::String string = g_sci->unwrapFilename(wrappedString); - if (string.size() > 12) - string = Common::String(string.c_str(), 12); - segMan->strcpy(_outbuffer, string.c_str()); - - // Return the result and advance the list iterator :) - ++_iter; - return _outbuffer; -} - reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { if (!s) return make_reg(0, getSciVersion()); @@ -790,6 +747,7 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { // SCI32 can call K_FILEIO_OPEN with only one argument. It seems to // just be checking if it exists. int mode = (argc < 2) ? (int)_K_FILE_MODE_OPEN_OR_FAIL : argv[1].toUint16(); + bool unwrapFilename = true; // SQ4 floppy prepends /\ to the filenames if (name.hasPrefix("/\\")) { @@ -813,6 +771,12 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { } debugC(2, kDebugLevelFile, "kFileIO(open): %s, 0x%x", name.c_str(), mode); + // QFG import rooms get a virtual filelisting instead of an actual one + if (g_sci->inQfGImportRoom()) { + // we need to find out what the user actually selected, "savedHeroes" is already destroyed + // when we get here. That's why we need to remember selection via kDrawControl + name = s->_dirseeker.getVirtualFilename(s->_chosenQfGImportItem); + unwrapFilename = false; // Since we're not wrapping/unwrapping save files for QFG import screens, // the name of the save file will almost certainly be over 12 characters in // length. Compensate for that fact here, by cutting off the last character @@ -835,7 +799,7 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) { } } - return file_open(s, name.c_str(), mode); + return file_open(s, name.c_str(), mode, unwrapFilename); } reg_t kFileIOClose(EngineState *s, int argc, reg_t *argv) { @@ -962,24 +926,104 @@ reg_t kFileIOSeek(EngineState *s, int argc, reg_t *argv) { return SIGNAL_REG; } +void DirSeeker::addAsVirtualFiles(Common::String title, Common::String fileMask) { + Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + Common::StringArray foundFiles = saveFileMan->listSavefiles(fileMask); + if (!foundFiles.empty()) { + _files.push_back(title); + _virtualFiles.push_back(""); + Common::StringArray::iterator it; + Common::StringArray::iterator it_end = foundFiles.end(); + for (it = foundFiles.begin(); it != it_end; it++) { + Common::String regularFilename = *it; + Common::String wrappedFilename = Common::String(regularFilename.c_str() + fileMask.size() - 1); + // We need to remove the prefix for display purposes + _files.push_back(wrappedFilename); + // but remember the actual name as well + _virtualFiles.push_back(regularFilename); + } + } +} + +Common::String DirSeeker::getVirtualFilename(uint fileNumber) { + if (fileNumber >= _virtualFiles.size()) + error("invalid virtual filename access"); + return _virtualFiles[fileNumber]; +} + +reg_t DirSeeker::firstFile(const Common::String &mask, reg_t buffer, SegManager *segMan) { + // Verify that we are given a valid buffer + if (!buffer.segment) { + error("DirSeeker::firstFile('%s') invoked with invalid buffer", mask.c_str()); + return NULL_REG; + } + _outbuffer = buffer; + _files.clear(); + _virtualFiles.clear(); + + int QfGImport = g_sci->inQfGImportRoom(); + if (QfGImport) { + _files.clear(); + addAsVirtualFiles("-QfG1-", "qfg1-*"); + addAsVirtualFiles("-QfG1VGA-", "qfg1vga-*"); + if (QfGImport > 2) + addAsVirtualFiles("-QfG2-", "qfg2-*"); + if (QfGImport > 3) + addAsVirtualFiles("-QfG3-", "qfg3-*"); + + if (QfGImport == 3) { + // QfG3 sorts the filelisting itself, we can't let that happen otherwise our + // virtual list would go out-of-sync + SegManager *segMan = g_sci->getEngineState()->_segMan; + reg_t savedHeros = segMan->findObjectByName("savedHeros"); + if (!savedHeros.isNull()) + writeSelectorValue(segMan, savedHeros, SELECTOR(sort), 0); + } + + } else { + // Prefix the mask + const Common::String wrappedMask = g_sci->wrapFilename(mask); + + // Obtain a list of all files matching the given mask + Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + _files = saveFileMan->listSavefiles(wrappedMask); + } + + // Reset the list iterator and write the first match to the output buffer, + // if any. + _iter = _files.begin(); + return nextFile(segMan); +} + +reg_t DirSeeker::nextFile(SegManager *segMan) { + if (_iter == _files.end()) { + return NULL_REG; + } + + Common::String string; + + if (_virtualFiles.empty()) { + // Strip the prefix, if we don't got a virtual filelisting + const Common::String wrappedString = *_iter; + string = g_sci->unwrapFilename(wrappedString); + } else { + string = *_iter; + } + if (string.size() > 12) + string = Common::String(string.c_str(), 12); + segMan->strcpy(_outbuffer, string.c_str()); + + // Return the result and advance the list iterator :) + ++_iter; + return _outbuffer; +} + reg_t kFileIOFindFirst(EngineState *s, int argc, reg_t *argv) { Common::String mask = s->_segMan->getString(argv[0]); reg_t buf = argv[1]; int attr = argv[2].toUint16(); // We won't use this, Win32 might, though... debugC(2, kDebugLevelFile, "kFileIO(findFirst): %s, 0x%x", mask.c_str(), attr); - // Change the file mask in QFG character import screens. The game - // is looking for *.*, but that may well include other files as well, - // thus limit the file mask to only include exported characters. - if (g_sci->isQFGImportScreen()) - mask = "qfg*.sav"; - - // QfG3 uses "/\*.*" for the character import, QfG4 uses "/\*" - if (mask.hasPrefix("/\\")) { - mask.deleteChar(0); - mask.deleteChar(0); - } - // We remove ".*". mask will get prefixed, so we will return all additional files for that gameid if (mask == "*.*") mask = "*"; diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 4e0306106b..e19a51b525 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -944,6 +944,7 @@ reg_t kDrawControl(EngineState *s, int argc, reg_t *argv) { "for Quest for Glory 2. Example: 'qfg2-thief.sav'."); } } + s->_chosenQfGImportItem = readSelectorValue(s->_segMan, controlObject, SELECTOR(mark)); } _k_GenericDrawControl(s, controlObject, false); diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index f5eb9eb73a..436a4b98ff 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -86,7 +86,8 @@ void Kernel::mapSelectors() { // window FIND_SELECTOR(cursor); FIND_SELECTOR(max); - // mark + FIND_SELECTOR(mark); + FIND_SELECTOR(sort); // who FIND_SELECTOR(message); // edit diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h index 661290f58c..63ec11fab1 100644 --- a/engines/sci/engine/selector.h +++ b/engines/sci/engine/selector.h @@ -58,7 +58,9 @@ struct SelectorCache { Selector state, font, type;///< Used by controls // window Selector cursor, max; ///< Used by EditControl - // mark, who + Selector mark; //< Used by list controls + Selector sort; //< Used by list controls (script internal, is needed by us for QfG3 import room) + // who Selector message; ///< Used by GetEvent // edit Selector play; ///< Play function (first function to be called) diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 5e0e7e21d5..bbdab6f7f0 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -110,6 +110,8 @@ void EngineState::reset(bool isRestoring) { _lastSaveVirtualId = SAVEGAMEID_OFFICIALRANGE_START; _lastSaveNewId = 0; + _chosenQfGImportItem = 0; + scriptStepCounter = 0; scriptGCInterval = GC_INTERVAL; } diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index ca5232022e..42294fa08c 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -59,17 +59,23 @@ enum AbortGameState { class DirSeeker { protected: reg_t _outbuffer; - Common::StringArray _savefiles; + Common::StringArray _files; + Common::StringArray _virtualFiles; Common::StringArray::const_iterator _iter; public: DirSeeker() { _outbuffer = NULL_REG; - _iter = _savefiles.begin(); + _iter = _files.begin(); } reg_t firstFile(const Common::String &mask, reg_t buffer, SegManager *segMan); reg_t nextFile(SegManager *segMan); + + Common::String getVirtualFilename(uint fileNumber); + +private: + void addAsVirtualFiles(Common::String title, Common::String fileMask); }; enum { @@ -139,6 +145,8 @@ public: int16 _lastSaveVirtualId; // last virtual id fed to kSaveGame, if no kGetSaveFiles was called inbetween int16 _lastSaveNewId; // last newly created filename-id by kSaveGame + uint _chosenQfGImportItem; // Remembers the item selected in QfG import rooms + public: /* VM Information */ diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index cb36ebd0f5..f9f89ea1ae 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -641,34 +641,27 @@ Common::String SciEngine::getFilePrefix() const { } Common::String SciEngine::wrapFilename(const Common::String &name) const { - // Do not wrap the game prefix when reading files in QFG import screens. - // That way, we can read exported characters from all QFG games, as - // intended. - return !isQFGImportScreen() ? getFilePrefix() + "-" + name : name; + return getFilePrefix() + "-" + name; } Common::String SciEngine::unwrapFilename(const Common::String &name) const { Common::String prefix = getFilePrefix() + "-"; - // Do not unwrap the file name when reading files in QFG import screens. - // We don't wrap the game ID prefix in these screens in order to read - // save states from all QFG games. - if (name.hasPrefix(prefix.c_str()) && !isQFGImportScreen()) + if (name.hasPrefix(prefix.c_str())) return Common::String(name.c_str() + prefix.size()); return name; } -bool SciEngine::isQFGImportScreen() const { +int SciEngine::inQfGImportRoom() const { if (_gameId == GID_QFG2 && _gamestate->currentRoomNumber() == 805) { // QFG2 character import screen - return true; + return 2; } else if (_gameId == GID_QFG3 && _gamestate->currentRoomNumber() == 54) { // QFG3 character import screen - return true; + return 3; } else if (_gameId == GID_QFG4 && _gamestate->currentRoomNumber() == 54) { - return true; - } else { - return false; + return 4; } + return 0; } void SciEngine::pauseEngineIntern(bool pause) { diff --git a/engines/sci/sci.h b/engines/sci/sci.h index aaa53367a7..a620f6cd09 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -251,10 +251,10 @@ public: Common::String unwrapFilename(const Common::String &name) const; /** - * Checks if we are in a QFG import screen, where special handling - * of save states is performed. + * Checks if we are in a QfG import screen, where special handling + * of file-listings is performed. */ - bool isQFGImportScreen() const; + int inQfGImportRoom() const; void sleep(uint32 msecs); |