aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/engine/kfile.cpp162
-rw-r--r--engines/sci/engine/kgraphics.cpp1
-rw-r--r--engines/sci/engine/selector.cpp3
-rw-r--r--engines/sci/engine/selector.h4
-rw-r--r--engines/sci/engine/state.cpp2
-rw-r--r--engines/sci/engine/state.h12
-rw-r--r--engines/sci/sci.cpp21
-rw-r--r--engines/sci/sci.h6
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);