diff options
author | Max Horn | 2002-11-19 01:36:47 +0000 |
---|---|---|
committer | Max Horn | 2002-11-19 01:36:47 +0000 |
commit | ce3cde15a027fd092d0d27fa165f0166d4ecb927 (patch) | |
tree | 6da6d74fef1a1bf25b6380eed687f6fcc1f1068a | |
parent | f2007606a9155190ffe061dfde90fd1711ec73e8 (diff) | |
download | scummvm-rg350-ce3cde15a027fd092d0d27fa165f0166d4ecb927.tar.gz scummvm-rg350-ce3cde15a027fd092d0d27fa165f0166d4ecb927.tar.bz2 scummvm-rg350-ce3cde15a027fd092d0d27fa165f0166d4ecb927.zip |
added some preliminary game auto detect code to the launcher; this required a small change to the FS API, Windows/Morphos code will have to be adapted slightly I fear. Also, not all games are detected correctly, and some probably never will be, so we still have to add a dialog for cases where auto detect doesn't work
svn-id: r5600
-rw-r--r-- | backends/fs/fs.h | 12 | ||||
-rw-r--r-- | backends/fs/posix/posix-fs.cpp | 10 | ||||
-rw-r--r-- | common/gameDetector.cpp | 13 | ||||
-rw-r--r-- | common/gameDetector.h | 1 | ||||
-rw-r--r-- | gui/browser.cpp | 28 | ||||
-rw-r--r-- | gui/browser.h | 4 | ||||
-rw-r--r-- | gui/dialog.cpp | 5 | ||||
-rw-r--r-- | gui/dialog.h | 7 | ||||
-rw-r--r-- | gui/launcher.cpp | 78 | ||||
-rw-r--r-- | gui/message.cpp | 77 |
10 files changed, 176 insertions, 59 deletions
diff --git a/backends/fs/fs.h b/backends/fs/fs.h index 47e47d3a9e..7bb63c9671 100644 --- a/backends/fs/fs.h +++ b/backends/fs/fs.h @@ -68,6 +68,16 @@ protected: typedef ScummVM::String String; public: + + /* + * Flag to tell listDir() which kind of files to list. + */ + typedef enum { + kListFilesOnly = 1, + kListDirectoriesOnly = 2, + kListAll = 3 + } ListMode; + /* * The starting point for any file system browsing. Returns a special node * representing the FS root. @@ -110,7 +120,7 @@ public: * List the content of this directory node. * If this node is not a directory, throw an exception or call error(). */ - virtual FSList *listDir() const = 0; + virtual FSList *listDir(ListMode mode = kListDirectoriesOnly) const = 0; /* * The parent node of this directory. diff --git a/backends/fs/posix/posix-fs.cpp b/backends/fs/posix/posix-fs.cpp index 0ea131b3f9..5cdda13bc2 100644 --- a/backends/fs/posix/posix-fs.cpp +++ b/backends/fs/posix/posix-fs.cpp @@ -50,7 +50,7 @@ public: virtual bool isDirectory() const { return _isDirectory; } virtual String path() const { return _path; } - virtual FSList *listDir() const; + virtual FSList *listDir(ListMode mode = kListDirectoriesOnly) const; virtual FilesystemNode *parent() const; virtual FilesystemNode *clone() const { return new POSIXFilesystemNode(this); } }; @@ -85,7 +85,7 @@ POSIXFilesystemNode::POSIXFilesystemNode(const POSIXFilesystemNode *node) { _path = node->_path; } -FSList *POSIXFilesystemNode::listDir() const { +FSList *POSIXFilesystemNode::listDir(ListMode mode) const { assert(_isDirectory); DIR *dirp = opendir(_path.c_str()); struct stat st; @@ -109,8 +109,10 @@ FSList *POSIXFilesystemNode::listDir() const { continue; entry._isDirectory = S_ISDIR(st.st_mode); - // FIXME - skip any non-directories for now - if (!entry._isDirectory) continue; + // Honor the chosen mode + if ((mode == kListFilesOnly && entry._isDirectory) || + (mode == kListDirectoriesOnly && !entry._isDirectory)) + continue; if (entry._isDirectory) entry._path += "/"; diff --git a/common/gameDetector.cpp b/common/gameDetector.cpp index 53938be854..f44d5537b2 100644 --- a/common/gameDetector.cpp +++ b/common/gameDetector.cpp @@ -441,20 +441,18 @@ const VersionSettings version_settings[] = { /* Scumm Version 2 */ // {"maniac", "Maniac Mansion", GID_MANIAC, 2, 0, 0, -// GF_SMALL_HEADER | GF_USE_KEY | GF_SMALL_NAMES | GF_16COLOR | GF_OLD_BUNDLE | -// GF_NO_SCALLING}, +// GF_SMALL_HEADER | GF_USE_KEY | GF_SMALL_NAMES | GF_16COLOR | GF_OLD_BUNDLE | GF_NO_SCALLING, "MANIACEX.EXE"}, // {"zak", "Zak McKracken and the Alien Mindbenders", GID_ZAK, 2, 0, 0, -// GF_SMALL_HEADER | GF_USE_KEY | GF_SMALL_NAMES | GF_16COLOR | GF_OLD_BUNDLE | -// GF_NO_SCALLING}, +// GF_SMALL_HEADER | GF_USE_KEY | GF_SMALL_NAMES | GF_16COLOR | GF_OLD_BUNDLE | GF_NO_SCALLING, "ZAKEXE.EXE"}, // {"indy3", "Indiana Jones and the Last Crusade", GID_INDY3, 2, 0, 0,}, /* Scumm Version 3 */ {"indy3", "Indiana Jones and the Last Crusade (256)", GID_INDY3_256, 3, 0, 22, - GF_SMALL_HEADER | GF_USE_KEY | GF_SMALL_NAMES | GF_OLD256 | GF_NO_SCALLING | GF_ADLIB_DEFAULT}, + GF_SMALL_HEADER | GF_USE_KEY | GF_SMALL_NAMES | GF_OLD256 | GF_NO_SCALLING | GF_ADLIB_DEFAULT, "INDYVGA.EXE"}, {"zak256", "Zak McKracken and the Alien Mindbenders (256)", GID_ZAK256, 3, 0, 0, - GF_SMALL_HEADER | GF_USE_KEY | GF_SMALL_NAMES | GF_OLD256 | GF_AUDIOTRACKS | GF_NO_SCALLING}, + GF_SMALL_HEADER | GF_USE_KEY | GF_SMALL_NAMES | GF_OLD256 | GF_AUDIOTRACKS | GF_NO_SCALLING, "ZAK.EXP"}, {"loom", "Loom", GID_LOOM, 3, 5, 40, - GF_SMALL_HEADER | GF_USE_KEY | GF_SMALL_NAMES | GF_OLD_BUNDLE | GF_16COLOR | GF_NO_SCALLING}, + GF_SMALL_HEADER | GF_USE_KEY | GF_SMALL_NAMES | GF_OLD_BUNDLE | GF_16COLOR | GF_NO_SCALLING, "LOOM.EXE"}, /* Scumm Version 4 */ {"monkeyEGA", "Monkey Island 1 (EGA)", GID_MONKEY_EGA, 4, 0, 67, @@ -520,6 +518,7 @@ const VersionSettings version_settings[] = { {NULL, NULL} }; + bool GameDetector::detectGame() { const VersionSettings *gnl = version_settings; diff --git a/common/gameDetector.h b/common/gameDetector.h index a2f01db6ac..6c5c4eccbf 100644 --- a/common/gameDetector.h +++ b/common/gameDetector.h @@ -88,6 +88,7 @@ struct VersionSettings { const char *gamename; byte id, major, middle, minor; uint32 features; + const char *detectname; }; extern const VersionSettings version_settings[]; diff --git a/gui/browser.cpp b/gui/browser.cpp index 44f1f94e34..0bd16d7c32 100644 --- a/gui/browser.cpp +++ b/gui/browser.cpp @@ -58,6 +58,13 @@ BrowserDialog::BrowserDialog(NewGui *gui) addButton(_w-(kButtonWidth+10), _h-24, "Choose", kChooseCmd, 0); } +BrowserDialog::~BrowserDialog() +{ + delete _node; + delete _nodeContent; + delete _choice; +} + void BrowserDialog::open() { // If no node has been set, or the last used one is now invalid, @@ -71,6 +78,10 @@ void BrowserDialog::open() // Alway refresh file list updateListing(); + // Nothing chosen by default + delete _choice; + _choice = 0; + // Call super implementation Dialog::open(); } @@ -92,11 +103,18 @@ void BrowserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data FilesystemNode *tmp; switch (cmd) { - case kChooseCmd: - // If nothing is selected in the list widget, choose the current dir. - // Else, choose the dir that is selected. - // TODO - close(); + case kChooseCmd: { + // If nothing is selected in the list widget, choose the current dir. + // Else, choose the dir that is selected. + int selection = _fileList->getSelected(); + if (selection >= 0) { + _choice = (*_nodeContent)[selection].clone(); + } else { + _choice = _node->clone(); + } + setResult(1); + close(); + } break; case kGoUpCmd: tmp = _node->parent(); diff --git a/gui/browser.h b/gui/browser.h index 4fda0b1596..139ac3d26a 100644 --- a/gui/browser.h +++ b/gui/browser.h @@ -36,16 +36,20 @@ class BrowserDialog : public Dialog { typedef ScummVM::StringList StringList; public: BrowserDialog(NewGui *gui); + virtual ~BrowserDialog(); virtual void open(); virtual void close(); virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); + + FilesystemNode *getResult() { return _choice; }; protected: ListWidget *_fileList; StaticTextWidget*_currentPath; FilesystemNode *_node; FSList *_nodeContent; + FilesystemNode *_choice; void updateListing(); }; diff --git a/gui/dialog.cpp b/gui/dialog.cpp index 5805e95f2f..d8569d979e 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -58,14 +58,15 @@ int Dialog::runModal() // Start processing events _gui->runLoop(); - // FIXME - for now always return 0.... - return 0; + // Return the result code + return _result; } void Dialog::open() { Widget *w = _firstWidget; + _result = 0; _visible = true; _gui->openDialog(this); diff --git a/gui/dialog.h b/gui/dialog.h index fa74737818..2f8abf58fe 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -45,6 +45,9 @@ protected: Widget *_focusedWidget; bool _visible; +private: + int _result; + public: Dialog(NewGui *gui, int x, int y, int w, int h) : _gui(gui), _x(x), _y(y), _w(w), _h(h), _firstWidget(0), @@ -62,7 +65,7 @@ public: protected: virtual void open(); virtual void close(); - + virtual void draw(); virtual void drawDialog(); @@ -79,6 +82,8 @@ protected: ButtonWidget* addButton(int x, int y, const ScummVM::String &label, uint32 cmd, char hotkey); PushButtonWidget* addPushButton(int x, int y, const ScummVM::String &label, uint32 cmd, char hotkey); + + void setResult(int result) { _result = result; } }; #endif diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 2526d0a6ba..8d3e727b83 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -24,10 +24,12 @@ #include "newgui.h" #include "ListWidget.h" +#include "backends/fs/fs.h" #include "common/config-file.h" #include "common/engine.h" #include "common/gameDetector.h" + enum { kStartCmd = 'STRT', kOptionsCmd = 'OPTN', @@ -118,6 +120,74 @@ LauncherDialog::LauncherDialog(NewGui *gui, GameDetector &detector) bw->setEnabled(false); } +bool findGame(FilesystemNode *dir) +{ + /* + atlantis -> ATLANTIS.000 + dig -> dig.la0 + ft -> ft.la0 + indy3 -> 00.LFL, ??? + indy3vga -> 00.LFL, INDYVGA.EXE + loom -> 00.LFL, LOOMEXE.EXE + loomcd -> 000.LFL, LOOM.EXE + maniac -> 00.LFL, MANIACEX.EXE + monkey -> monkey.000 + monkey2 -> monkey2.000 + monkeyvga -> 000.LFL, MONKEY.EXE + samnmax -> samnmax.000 + tentacle -> tentacle.000 + zak -> 00.LFL, zakexe.exe + zak256 -> 00.LFL, ZAK.EXP + */ + + // TODO - this doesn't deal with Simon games at all yet! + // We may have to offer a choice dialog between win/dos/talkie versions... + + // TODO - if we can't decide which game this supposedly is, we should ask the user. + // We simply can't autodetect all games, e.g. for old games (with 00.LFL), it is + // hard to distinguish them based on file names alone. We do luck for .exe files + // but those could be deleted by the user, or for the Amiga/Mac/... versions + // may not be present at all. + // Or maybe somebody has a better idea? Is there a reliable way to tell from + // the XX.lfl files which game we are dealing with (taking into account that + // for most of the games many variations exist, so we can't just hard code expected + // file sizes or checksums). + +// ScummVM::Map<String, FilesystemNode *file> map; + + FSList *files = dir->listDir(FilesystemNode::kListFilesOnly); + int size = files->size(); + for (int i = 0; i < size; i++) { + const char *filename = (*files)[i].displayName().c_str(); + //printf("%2d. %s\n", i, filename); + + // Check if there is any game matching this file + const VersionSettings *v = version_settings; + while (v->filename && v->gamename) { + char detectName[256]; + if (v->detectname) + strcpy(detectName, v->detectname); + else { + strcpy(detectName, v->filename); + if (v->features & GF_AFTER_V7) + strcat(detectName, ".la0"); + else if (v->features & GF_HUMONGOUS) + strcat(detectName, ".he0"); + else + strcat(detectName, ".000"); + } + if (0 == scumm_stricmp(detectName, filename)) { + printf("Match found, apparently this is '%s'\n", v->gamename); + return true; + } + v++; + } + } + + printf("Unable to autodetect a game in %s\n", dir->displayName().c_str()); + return false; +} + void LauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { int item; @@ -132,7 +202,13 @@ void LauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat // which choices are possible. E.g. if we don't find atlantis.000 in that // directory, then it's not FOA etc. BrowserDialog *browser = new BrowserDialog(_gui); - browser->runModal(); + if (browser->runModal()) { + // User did make a choice... + FilesystemNode *dir = browser->getResult(); + + // ...so let's examine it and try to figure out which game it is + findGame(dir); + } delete browser; } break; diff --git a/gui/message.cpp b/gui/message.cpp index ff678e9dd5..8dc9931a9c 100644 --- a/gui/message.cpp +++ b/gui/message.cpp @@ -23,44 +23,6 @@ #include "newgui.h" -int MessageDialog::addLine(const char *line, int size) -{ - int width = 0, maxWidth = 0; - const char *start = line; - String tmp; - - for (int i = 0; i < size; ++i) { - int w = _gui->getCharWidth(*line); - - // Check if we exceed the maximum line width, if so, split the line - // TODO - we could make this more clever by trying to split at - // non-letters, e.g. at space/slash/dot - if (width + w > 280) { - if (maxWidth < width) - maxWidth = width; - - // Add the substring from intervall [start, i-1] - tmp = String(start, line - start); - _lines.push_back(tmp); - - start = line; - width = w; - } else - width += w; - - line++; - } - - if (maxWidth < width) - maxWidth = width; - - if (start < line) { - tmp = String(start, line - start); - _lines.push_back(tmp); - } - return maxWidth; -} - MessageDialog::MessageDialog(NewGui *gui, const String &message) : Dialog(gui, 30, 20, 260, 124) { @@ -107,3 +69,42 @@ MessageDialog::MessageDialog(NewGui *gui, const String &message) // was selected. addButton((_w - kButtonWidth)/2, _h - 24, "OK", kCloseCmd, '\n'); // Confirm dialog } + +int MessageDialog::addLine(const char *line, int size) +{ + int width = 0, maxWidth = 0; + const char *start = line; + String tmp; + + for (int i = 0; i < size; ++i) { + int w = _gui->getCharWidth(*line); + + // Check if we exceed the maximum line width, if so, split the line + // TODO - we could make this more clever by trying to split at + // non-letters, e.g. at space/slash/dot + if (width + w > 280) { + if (maxWidth < width) + maxWidth = width; + + // Add the substring from intervall [start, i-1] + tmp = String(start, line - start); + _lines.push_back(tmp); + + start = line; + width = w; + } else + width += w; + + line++; + } + + if (maxWidth < width) + maxWidth = width; + + if (start < line) { + tmp = String(start, line - start); + _lines.push_back(tmp); + } + return maxWidth; +} + |