diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/advancedDetector.cpp | 125 | ||||
-rw-r--r-- | common/advancedDetector.h | 35 | ||||
-rw-r--r-- | common/events.h | 45 | ||||
-rw-r--r-- | common/scummsys.h | 10 | ||||
-rw-r--r-- | common/str.cpp | 21 | ||||
-rw-r--r-- | common/str.h | 5 | ||||
-rw-r--r-- | common/system.cpp | 5 | ||||
-rw-r--r-- | common/system.h | 50 |
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 ¶ms) { 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 ¶ms) { GameDescriptor findGameID( const char *gameid, - const Common::ADParams ¶ms + 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 ¶ms) { + 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 ¶ms ) { 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 ¶ms ) { 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 ¶ms); * 'gameid' in there. If a match is found, returns a GameDescriptor * with gameid and description set. */ -GameDescriptor findGameID(const char *gameid, const Common::ADParams ¶ms); +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 ¶ms); // FIXME/TODO: Rename this function to something more sensible. -const ADGameDescription *detectBestMatchingGame(const Common::ADParams ¶ms); +EncapsulatedADGameDesc detectBestMatchingGame(const Common::ADParams ¶ms); // 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 ¶ms); 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; |