aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2002-11-19 01:36:47 +0000
committerMax Horn2002-11-19 01:36:47 +0000
commitce3cde15a027fd092d0d27fa165f0166d4ecb927 (patch)
tree6da6d74fef1a1bf25b6380eed687f6fcc1f1068a
parentf2007606a9155190ffe061dfde90fd1711ec73e8 (diff)
downloadscummvm-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.h12
-rw-r--r--backends/fs/posix/posix-fs.cpp10
-rw-r--r--common/gameDetector.cpp13
-rw-r--r--common/gameDetector.h1
-rw-r--r--gui/browser.cpp28
-rw-r--r--gui/browser.h4
-rw-r--r--gui/dialog.cpp5
-rw-r--r--gui/dialog.h7
-rw-r--r--gui/launcher.cpp78
-rw-r--r--gui/message.cpp77
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;
+}
+