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
This commit is contained in:
parent
f2007606a9
commit
ce3cde15a0
10 changed files with 176 additions and 59 deletions
|
@ -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.
|
||||
|
|
|
@ -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 += "/";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -88,6 +88,7 @@ struct VersionSettings {
|
|||
const char *gamename;
|
||||
byte id, major, middle, minor;
|
||||
uint32 features;
|
||||
const char *detectname;
|
||||
};
|
||||
|
||||
extern const VersionSettings version_settings[];
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue