aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorDavid Corrales2007-06-23 18:51:33 +0000
committerDavid Corrales2007-06-23 18:51:33 +0000
commitcacd7a28fd51d960947de88abbf30c487e66529d (patch)
treef3baa59853bfb307e452b86b9d93c4737b1fa6ab /common
parent0ac96302fe9c04df79cb01a77d19535b45fe2db0 (diff)
parent90c2210dae8c91fa8babc6b05564e15c9d445d18 (diff)
downloadscummvm-rg350-cacd7a28fd51d960947de88abbf30c487e66529d.tar.gz
scummvm-rg350-cacd7a28fd51d960947de88abbf30c487e66529d.tar.bz2
scummvm-rg350-cacd7a28fd51d960947de88abbf30c487e66529d.zip
Merged the FSNode branch with trunk r27031:27680
svn-id: r27681
Diffstat (limited to 'common')
-rw-r--r--common/advancedDetector.cpp125
-rw-r--r--common/advancedDetector.h35
-rw-r--r--common/events.h45
-rw-r--r--common/scummsys.h10
-rw-r--r--common/str.cpp21
-rw-r--r--common/str.h5
-rw-r--r--common/system.cpp5
-rw-r--r--common/system.h50
8 files changed, 200 insertions, 96 deletions
diff --git a/common/advancedDetector.cpp b/common/advancedDetector.cpp
index d6b622451a..f3e8671025 100644
--- a/common/advancedDetector.cpp
+++ b/common/advancedDetector.cpp
@@ -87,7 +87,12 @@ static void upgradeTargetIfNecessary(const Common::ADParams &params) {
ConfMan.set("platform", Common::getPlatformCode(o->platform));
warning("Target upgraded from %s to %s", o->from, o->to);
- ConfMan.flushToDisk();
+
+ if (ConfMan.hasKey("id_came_from_command_line")) {
+ warning("Target came from command line. Skipping save");
+ } else {
+ ConfMan.flushToDisk();
+ }
break;
}
}
@@ -95,25 +100,31 @@ static void upgradeTargetIfNecessary(const Common::ADParams &params) {
GameDescriptor findGameID(
const char *gameid,
- const Common::ADParams &params
+ const PlainGameDescriptor *list,
+ const Common::ADObsoleteGameID *obsoleteList
) {
- const PlainGameDescriptor *g = params.list;
- while (g->gameid) {
- if (0 == scumm_stricmp(gameid, g->gameid))
- return GameDescriptor(*g);
- g++;
- }
-
- if (params.obsoleteList != 0) {
- const Common::ADObsoleteGameID *o = params.obsoleteList;
+ // First search the list of supported game IDs for a match.
+ const PlainGameDescriptor *g = findPlainGameDescriptor(gameid, list);
+ if (g)
+ return GameDescriptor(*g);
+
+ // If we didn't find the gameid in the main list, check if it
+ // is an obsolete game id.
+ if (obsoleteList != 0) {
+ const Common::ADObsoleteGameID *o = obsoleteList;
while (o->from) {
if (0 == scumm_stricmp(gameid, o->from)) {
- return GameDescriptor(gameid, "Obsolete game ID");
+ g = findPlainGameDescriptor(o->to, list);
+ if (g && g->description)
+ return GameDescriptor(gameid, "Obsolete game ID (" + Common::String(g->description) + ")");
+ else
+ return GameDescriptor(gameid, "Obsolete game ID");
}
o++;
}
}
+ // No match found
return GameDescriptor();
}
@@ -131,6 +142,24 @@ static GameDescriptor toGameDescriptor(const ADGameDescription &g, const PlainGa
return gd;
}
+// Almost identical to the toGameDescriptor function that takes a ADGameDescription and PlainGameDescriptor.
+// Just a little fine tuning about accessing variables.
+// Used because of fallback detection and the dynamic string content it needs.
+static GameDescriptor toGameDescriptor(const EncapsulatedADGameDesc &g, const PlainGameDescriptor *sg) {
+ const char *title = 0;
+
+ while (sg->gameid) {
+ if (!scumm_stricmp(g.getGameID(), sg->gameid))
+ title = sg->description;
+ sg++;
+ }
+
+ assert(g.realDesc);
+ GameDescriptor gd(g.getGameID(), title, g.realDesc->language, g.realDesc->platform);
+ gd.updateDesc(g.getExtra());
+ return gd;
+}
+
/**
* Generate a preferred target value as
* GAMEID-PLAFORM-LANG
@@ -155,38 +184,49 @@ static String generatePreferredTarget(const String &id, const ADGameDescription
return res;
}
+static void updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *realDesc, const Common::ADParams &params) {
+ if (params.singleid != NULL) {
+ desc["preferredtarget"] = desc["gameid"];
+ desc["gameid"] = params.singleid;
+ }
+
+ if (params.flags & kADFlagAugmentPreferredTarget) {
+ if (!desc.contains("preferredtarget"))
+ desc["preferredtarget"] = desc["gameid"];
+
+ desc["preferredtarget"] = generatePreferredTarget(desc["preferredtarget"], realDesc);
+ }
+}
+
GameList detectAllGames(
const FSList &fslist,
const Common::ADParams &params
) {
ADGameDescList matches = detectGame(&fslist, params, Common::UNK_LANG, Common::kPlatformUnknown);
-
GameList detectedGames;
- for (uint i = 0; i < matches.size(); i++) {
- GameDescriptor desc(toGameDescriptor(*matches[i], params.list));
- if (params.singleid != NULL) {
- desc["preferredtarget"] = desc["gameid"];
- desc["gameid"] = params.singleid;
+ // Use fallback detector if there were no matches by other means
+ if (matches.empty() && params.fallbackDetectFunc != NULL) {
+ EncapsulatedADGameDesc fallbackDesc = (*params.fallbackDetectFunc)(&fslist);
+ if (fallbackDesc.realDesc != 0) {
+ GameDescriptor desc(toGameDescriptor(fallbackDesc, params.list));
+ updateGameDescriptor(desc, fallbackDesc.realDesc, params);
+ detectedGames.push_back(desc);
}
-
- if (params.flags & kADFlagAugmentPreferredTarget) {
- if (!desc.contains("preferredtarget"))
- desc["preferredtarget"] = desc["gameid"];
-
- desc["preferredtarget"] = generatePreferredTarget(desc["preferredtarget"], matches[i]);
- }
-
+ } else for (uint i = 0; i < matches.size(); i++) { // Otherwise use the found matches
+ GameDescriptor desc(toGameDescriptor(*matches[i], params.list));
+ updateGameDescriptor(desc, matches[i], params);
detectedGames.push_back(desc);
}
return detectedGames;
}
-const ADGameDescription *detectBestMatchingGame(
+EncapsulatedADGameDesc detectBestMatchingGame(
const Common::ADParams &params
) {
const ADGameDescription *agdDesc = 0;
+ EncapsulatedADGameDesc result;
Common::Language language = Common::UNK_LANG;
Common::Platform platform = Common::kPlatformUnknown;
@@ -210,11 +250,20 @@ const ADGameDescription *detectBestMatchingGame(
agdDesc = matches[0];
}
- if (agdDesc != 0) {
- debug(2, "Running %s", toGameDescriptor(*agdDesc, params.list).description().c_str());
+ if (agdDesc != 0) { // Check if we found a match without fallback detection
+ result = EncapsulatedADGameDesc(agdDesc);
+ } else if (params.fallbackDetectFunc != NULL) { // Use fallback detector if there were no matches by other means
+ EncapsulatedADGameDesc fallbackDesc = (*params.fallbackDetectFunc)(NULL);
+ if (fallbackDesc.realDesc != 0 && (params.singleid != NULL || fallbackDesc.getGameID() == gameid)) {
+ result = fallbackDesc; // Found a fallback match
+ }
}
- return agdDesc;
+ if (result.realDesc != 0) {
+ debug(2, "Running %s", toGameDescriptor(result, params.list).description().c_str());
+ }
+
+ return result;
}
PluginError detectGameForEngineCreation(
@@ -243,6 +292,14 @@ PluginError detectGameForEngineCreation(
}
}
+ // Use fallback detector if there were no matches by other means
+ if (params.fallbackDetectFunc != NULL) {
+ EncapsulatedADGameDesc fallbackDesc = (*params.fallbackDetectFunc)(&fslist);
+ if (fallbackDesc.realDesc != 0 && (params.singleid != NULL || fallbackDesc.getGameID() == gameid)) {
+ return kNoError;
+ }
+ }
+
return kNoGameDataFoundError;
}
@@ -281,6 +338,9 @@ static ADGameDescList detectGame(const FSList *fslist, const Common::ADParams &p
}
}
+ // TODO/FIXME: Fingolfin says: It's not good that we have two different code paths here,
+ // one using a FSList, one using File::open, as that will lead to discrepancies and subtle
+ // problems caused by those.
if (fslist != 0) {
// Get the information of the existing files
for (FSList::const_iterator file = fslist->begin(); file != fslist->end(); ++file) {
@@ -493,11 +553,6 @@ static ADGameDescList detectGame(const FSList *fslist, const Common::ADParams &p
}
}
- // If we still haven't got a match, try to use the fallback callback :-)
- if (matched.empty() && params.fallbackDetectFunc != 0) {
- matched = (*params.fallbackDetectFunc)(fslist);
- }
-
return matched;
}
diff --git a/common/advancedDetector.h b/common/advancedDetector.h
index fab847e671..5066ba71e9 100644
--- a/common/advancedDetector.h
+++ b/common/advancedDetector.h
@@ -64,6 +64,29 @@ struct ADGameDescription {
};
/**
+ * Encapsulates ADGameDescription and makes gameid and extra strings dynamic.
+ * Used in fallback detection when dynamically creating string content.
+ */
+struct EncapsulatedADGameDesc {
+ Common::String gameid;
+ Common::String extra;
+ const ADGameDescription *realDesc;
+
+ // Constructor for the EncapsulatedADGameDesc
+ EncapsulatedADGameDesc() : realDesc(0) {}
+ EncapsulatedADGameDesc(const ADGameDescription *paramRealDesc,
+ Common::String paramGameID = Common::String(""),
+ Common::String paramExtra = Common::String(""))
+ : realDesc(paramRealDesc), gameid(paramGameID), extra(paramExtra) {
+ assert(paramRealDesc != NULL);
+ }
+
+ // Functions for getting the correct gameid and extra values from the struct
+ const char *getGameID() const { return (gameid.empty() && realDesc != 0) ? realDesc->gameid : gameid.c_str(); }
+ const char *getExtra() const { return (extra.empty() && realDesc != 0) ? realDesc->extra : extra.c_str(); }
+};
+
+/**
* A list of pointers to ADGameDescription structs (or subclasses thereof).
*/
typedef Array<const ADGameDescription*> ADGameDescList;
@@ -177,7 +200,7 @@ struct ADParams {
*
* @todo
*/
- ADGameDescList (*fallbackDetectFunc)(const FSList *fslist);
+ EncapsulatedADGameDesc (*fallbackDetectFunc)(const FSList *fslist);
/**
* A bitmask of flags which can be used to configure the behavior
@@ -201,13 +224,17 @@ GameList gameIDList(const Common::ADParams &params);
* 'gameid' in there. If a match is found, returns a GameDescriptor
* with gameid and description set.
*/
-GameDescriptor findGameID(const char *gameid, const Common::ADParams &params);
+GameDescriptor findGameID(
+ const char *gameid,
+ const PlainGameDescriptor *list,
+ const Common::ADObsoleteGameID *obsoleteList = 0
+ );
// FIXME/TODO: Rename this function to something more sensible.
GameList detectAllGames(const FSList &fslist, const Common::ADParams &params);
// FIXME/TODO: Rename this function to something more sensible.
-const ADGameDescription *detectBestMatchingGame(const Common::ADParams &params);
+EncapsulatedADGameDesc detectBestMatchingGame(const Common::ADParams &params);
// FIXME/TODO: Rename this function to something more sensible.
// Only used by ADVANCED_DETECTOR_DEFINE_PLUGIN_WITH_FUNC
@@ -230,7 +257,7 @@ PluginError detectGameForEngineCreation(const Common::ADParams &params);
return Common::AdvancedDetector::gameIDList(params); \
} \
GameDescriptor Engine_##engine##_findGameID(const char *gameid) { \
- return Common::AdvancedDetector::findGameID(gameid, params); \
+ return Common::AdvancedDetector::findGameID(gameid, params.list, params.obsoleteList); \
} \
GameList Engine_##engine##_detectGames(const FSList &fslist) { \
return Common::AdvancedDetector::detectAllGames(fslist, params); \
diff --git a/common/events.h b/common/events.h
index 9b434e94f9..d5e578a9ce 100644
--- a/common/events.h
+++ b/common/events.h
@@ -26,6 +26,7 @@
#ifndef COMMON_EVENTS_H
#define COMMON_EVENTS_H
+#include "common/keyboard.h"
#include "common/rect.h"
#include "common/system.h"
#include "common/noncopyable.h"
@@ -57,19 +58,17 @@ enum EventType {
EVENT_QUIT = 10,
EVENT_SCREEN_CHANGED = 11,
+ /**
+ * The backend requests the agi engine's predictive dialog to be shown.
+ * TODO: Fingolfin suggests that it would be of better value to expand
+ * on this notion by generalizing its use. For example the backend could
+ * use events to ask for the save game dialog or to pause the engine.
+ * An associated enumerated type can accomplish this.
+ **/
EVENT_PREDICTIVE_DIALOG = 12
};
/**
- * Keyboard modifier flags, used for Event::kbd::flags.
- */
-enum {
- KBD_CTRL = 1 << 0,
- KBD_ALT = 1 << 1,
- KBD_SHIFT = 1 << 2
-};
-
-/**
* Data structure for an event. A pointer to an instance of Event
* can be passed to pollEvent.
* @todo Rework/document this structure. It should be made 100% clear which
@@ -108,33 +107,7 @@ struct Event {
* Keyboard data; only valid for keyboard events (EVENT_KEYDOWN and
* EVENT_KEYUP). For all other event types, content is undefined.
*/
- struct {
- /**
- * Abstract key code (will be the same for any given key regardless
- * of modifiers being held at the same time.
- * For example, this is the same for both 'A' and Shift-'A'.
- * @todo Document which values are to be used for non-ASCII keys
- * like F1-F10. For now, let's just say that our primary backend
- * is the SDL one, and it uses the values SDL uses... so until
- * we fix this, your best bet is to get a copy of SDL_keysym.h
- * and look at that, if you want to find out a key code.
- */
- int keycode;
- /**
- * ASCII-value of the pressed key (if any).
- * This depends on modifiers, i.e. pressing the 'A' key results in
- * different values here depending on the status of shift, alt and
- * caps lock.
- * For the function keys F1-F9, values of 315-323 are used.
- */
- uint16 ascii;
- /**
- * Status of the modifier keys. Bits are set in this for each
- * pressed modifier
- * @see KBD_CTRL, KBD_ALT, KBD_SHIFT
- */
- byte flags;
- } kbd;
+ KeyState kbd;
/**
* The mouse coordinates, in virtual screen coordinates. Only valid
* for mouse events.
diff --git a/common/scummsys.h b/common/scummsys.h
index e4f52295fb..4cb8d5d8e9 100644
--- a/common/scummsys.h
+++ b/common/scummsys.h
@@ -142,11 +142,6 @@
#define SCUMM_LITTLE_ENDIAN
- // FIXME: Do you really need to use 'long' on this port? Please replace
- // this comment with a new comment that states so, and ideally also
- // explains the reasons briefly.
- #define SCUMMVM_USE_LONG_INT
-
#define FORCEINLINE __forceinline
#define NORETURN _declspec(noreturn)
#define PLUGIN_EXPORT __declspec(dllexport)
@@ -240,11 +235,6 @@
#define SCUMM_BIG_ENDIAN
#define SCUMM_NEED_ALIGNMENT
- // FIXME: Do you really need to use 'long' on this port? Please replace
- // this comment with a new comment that states so, and ideally also
- // explains the reasons briefly.
- #define SCUMMVM_USE_LONG_INT
-
#elif defined(__DC__)
#define scumm_stricmp strcasecmp
diff --git a/common/str.cpp b/common/str.cpp
index 01d24c1e75..88aca87bb4 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -86,7 +86,16 @@ String::String(const String &str)
}
assert(_str != 0);
}
+
+String::String(char c)
+: _len(0), _str(_storage) {
+ _storage[0] = c;
+ _storage[1] = 0;
+
+ _len = (c == 0) ? 0 : 1;
+}
+
String::~String() {
decRefCount(_extern._refCount);
}
@@ -437,6 +446,18 @@ String operator +(const String &x, const char *y) {
return temp;
}
+String operator +(char x, const String &y) {
+ String temp(x);
+ temp += y;
+ return temp;
+}
+
+String operator +(const String &x, char y) {
+ String temp(x);
+ temp += y;
+ return temp;
+}
+
char *ltrim(char *t) {
while (isspace(*t))
t++;
diff --git a/common/str.h b/common/str.h
index 509300dd6f..55ff94c51c 100644
--- a/common/str.h
+++ b/common/str.h
@@ -99,6 +99,7 @@ public:
String() : _len(0), _str(_storage) { _storage[0] = 0; }
String(const char *str, uint32 len = 0);
String(const String &str);
+ String(char c);
virtual ~String();
String &operator =(const char *str);
@@ -187,9 +188,13 @@ protected:
// Append two strings to form a new (temp) string
String operator +(const String &x, const String &y);
+
String operator +(const char *x, const String &y);
String operator +(const String &x, const char *y);
+String operator +(const String &x, char y);
+String operator +(char x, const String &y);
+
// Some useful additional comparision operators for Strings
bool operator == (const char *x, const String &y);
bool operator != (const char *x, const String &y);
diff --git a/common/system.cpp b/common/system.cpp
index 2720a19775..f8068d41f5 100644
--- a/common/system.cpp
+++ b/common/system.cpp
@@ -101,3 +101,8 @@ Common::EventManager *OSystem::getEventManager() {
return s_eventManager;
}
+void OSystem::clearScreen() {
+ Graphics::Surface *screen = lockScreen();
+ memset(screen->pixels, 0, screen->h * screen->pitch);
+ unlockScreen();
+}
diff --git a/common/system.h b/common/system.h
index ccca1fb7c7..95f970d956 100644
--- a/common/system.h
+++ b/common/system.h
@@ -125,7 +125,7 @@ public:
kFeatureAutoComputeDirtyRects,
/**
- * This flags determines either cursor can have its own palette or not
+ * This flag determines either cursor can have its own palette or not
* It is currently used only by some Macintosh versions of Humongous
* Entertainment games. If backend doesn't implement this feature then
* engine switches to b/w version of cursors.
@@ -142,7 +142,22 @@ public:
/**
* Set to true to iconify the window.
*/
- kFeatureIconifyWindow
+ kFeatureIconifyWindow,
+
+ /**
+ * This feature, set to true, is a hint toward the backend to disable all
+ * key filtering/mapping, in cases where it would be beneficial to do so.
+ * As an example case, this is used in the agi engine's predictive dialog.
+ * When the dialog is displayed this feature is set so that backends with
+ * phone-like keypad temporarily unmap all user actions which leads to
+ * comfortable word entry. Conversely, when the dialog exits the feature
+ * is set to false.
+ * TODO: Fingolfin suggests that the way the feature is used can be
+ * generalized in this sense: Have a keyboard mapping feature, which the
+ * engine queries for to assign keys to actions ("Here's my default key
+ * map for these actions, what do you want them set to?").
+ */
+ kFeatureDisableKeyFiltering
};
/**
@@ -437,21 +452,34 @@ public:
virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) = 0;
/**
- * Copies the current screen contents to a new surface, with the original
- * bit depth. This will allocate memory for the pixel data.
- * WARNING: surf->free() must be called by the user to avoid leaking.
+ * Lock the active screen framebuffer and return a Graphics::Surface
+ * representing it. The caller can then perform arbitrary graphics
+ * transformations on the framebuffer (blitting, scrolling, etc.).
+ * Must be followed by matching call to unlockScreen(). Calling code
+ * should make sure to only lock the framebuffer for the briefest
+ * periods of time possible, as the whole system is potentially stalled
+ * while the lock is active.
+ * Returns 0 if an error occurred. Otherwise an 8bit surface is returned.
*
- * @param surf the surfce to store the data in it
- * @return true if all went well, false if an error occured
+ * The returned surface must *not* be deleted by the client code.
+ */
+ virtual Graphics::Surface *lockScreen() = 0;
+
+ /**
+ * Unlock the screen framebuffer, and mark it as dirty (i.e. during the
+ * next updateScreen() call, the whole screen will be updated.
*/
- virtual bool grabRawScreen(Graphics::Surface *surf) = 0;
+ virtual void unlockScreen() = 0;
/**
* Clear the screen to black.
*/
- virtual void clearScreen() {}
+ virtual void clearScreen();
- /** Update the dirty areas of the screen. */
+ /**
+ * Flush the whole screen, that is render the current content of the screen
+ * framebuffer (resp. the dirty/changed parts of it) to the display.
+ */
virtual void updateScreen() = 0;
/**
@@ -763,7 +791,7 @@ public:
//@{
/**
- * Returh the audio mixer. For more information, refer to the
+ * Return the audio mixer. For more information, refer to the
* Audio::Mixer documentation.
*/
virtual Audio::Mixer *getMixer() = 0;