synced with scummvm

This commit is contained in:
Pawel Kolodziejski 2009-06-18 11:52:26 +00:00
parent 3a2d539f09
commit abaa548181
52 changed files with 874 additions and 158 deletions

View file

@ -137,8 +137,8 @@ DefaultEventManager::DefaultEventManager(EventProvider *boss) :
if (_recordMode == kRecorderRecord) { if (_recordMode == kRecorderRecord) {
_recordCount = 0; _recordCount = 0;
_recordTimeCount = 0; _recordTimeCount = 0;
_recordFile = g_system->getSavefileManager()->openForSaving(_recordTempFileName.c_str()); _recordFile = g_system->getSavefileManager()->openForSaving(_recordTempFileName);
_recordTimeFile = g_system->getSavefileManager()->openForSaving(_recordTimeFileName.c_str()); _recordTimeFile = g_system->getSavefileManager()->openForSaving(_recordTimeFileName);
_recordSubtitles = ConfMan.getBool("subtitles"); _recordSubtitles = ConfMan.getBool("subtitles");
} }
@ -148,8 +148,8 @@ DefaultEventManager::DefaultEventManager(EventProvider *boss) :
if (_recordMode == kRecorderPlayback) { if (_recordMode == kRecorderPlayback) {
_playbackCount = 0; _playbackCount = 0;
_playbackTimeCount = 0; _playbackTimeCount = 0;
_playbackFile = g_system->getSavefileManager()->openForLoading(_recordFileName.c_str()); _playbackFile = g_system->getSavefileManager()->openForLoading(_recordFileName);
_playbackTimeFile = g_system->getSavefileManager()->openForLoading(_recordTimeFileName.c_str()); _playbackTimeFile = g_system->getSavefileManager()->openForLoading(_recordTimeFileName);
if (!_playbackFile) { if (!_playbackFile) {
warning("Cannot open playback file %s. Playback was switched off", _recordFileName.c_str()); warning("Cannot open playback file %s. Playback was switched off", _recordFileName.c_str());
@ -200,6 +200,12 @@ DefaultEventManager::DefaultEventManager(EventProvider *boss) :
} }
DefaultEventManager::~DefaultEventManager() { DefaultEventManager::~DefaultEventManager() {
#ifdef ENABLE_KEYMAPPER
delete _keymapper;
#endif
#ifdef ENABLE_VKEYBD
delete _vk;
#endif
g_system->lockMutex(_timeMutex); g_system->lockMutex(_timeMutex);
g_system->lockMutex(_recorderMutex); g_system->lockMutex(_recorderMutex);
_recordMode = kPassthrough; _recordMode = kPassthrough;
@ -222,11 +228,11 @@ DefaultEventManager::~DefaultEventManager() {
_recordTimeFile->finalize(); _recordTimeFile->finalize();
delete _recordTimeFile; delete _recordTimeFile;
_playbackFile = g_system->getSavefileManager()->openForLoading(_recordTempFileName.c_str()); _playbackFile = g_system->getSavefileManager()->openForLoading(_recordTempFileName);
assert(_playbackFile); assert(_playbackFile);
_recordFile = g_system->getSavefileManager()->openForSaving(_recordFileName.c_str()); _recordFile = g_system->getSavefileManager()->openForSaving(_recordFileName);
_recordFile->writeUint32LE(RECORD_SIGNATURE); _recordFile->writeUint32LE(RECORD_SIGNATURE);
_recordFile->writeUint32LE(RECORD_VERSION); _recordFile->writeUint32LE(RECORD_VERSION);
@ -261,6 +267,13 @@ DefaultEventManager::~DefaultEventManager() {
} }
void DefaultEventManager::init() { void DefaultEventManager::init() {
#ifdef ENABLE_VKEYBD
if (ConfMan.hasKey("vkeybd_pack_name")) {
_vk->loadKeyboardPack(ConfMan.get("vkeybd_pack_name"));
} else {
_vk->loadKeyboardPack("vkeybd_default");
}
#endif
} }
bool DefaultEventManager::playback(Common::Event &event) { bool DefaultEventManager::playback(Common::Event &event) {

View file

@ -31,6 +31,16 @@
#include "common/mutex.h" #include "common/mutex.h"
#include "common/queue.h" #include "common/queue.h"
namespace Common {
#ifdef ENABLE_KEYMAPPER
class Keymapper;
#endif
#ifdef ENABLE_VKEYBD
class VirtualKeyboard;
#endif
}
class EventProvider { class EventProvider {
public: public:
virtual ~EventProvider() {} virtual ~EventProvider() {}

View file

@ -209,6 +209,10 @@ void OSystem_SDL::handleKbdMouse() {
} }
} }
bool OSystem_SDL::showMouse(bool visible) {
return false;
}
void OSystem_SDL::warpMouse(int x, int y) { void OSystem_SDL::warpMouse(int x, int y) {
SDL_WarpMouse(x, y); SDL_WarpMouse(x, y);
} }
@ -516,6 +520,7 @@ OSystem_SDL::OSystem_SDL() {
_soundThreadShouldQuit = false; _soundThreadShouldQuit = false;
#endif #endif
_samplesPerSec = 0; _samplesPerSec = 0;
_cdrom = 0;
memset(&_km, 0, sizeof(_km)); memset(&_km, 0, sizeof(_km));
@ -1127,6 +1132,92 @@ Audio::Mixer *OSystem_SDL::getMixer() {
return _mixer; return _mixer;
} }
bool OSystem_SDL::openCD(int drive) {
if (SDL_InitSubSystem(SDL_INIT_CDROM) == -1)
_cdrom = NULL;
else {
_cdrom = SDL_CDOpen(drive);
// Did it open? Check if _cdrom is NULL
if (!_cdrom) {
warning("Couldn't open drive: %s", SDL_GetError());
} else {
_cdNumLoops = 0;
_cdStopTime = 0;
_cdEndTime = 0;
}
}
return (_cdrom != NULL);
}
void OSystem_SDL::stopCD() { /* Stop CD Audio in 1/10th of a second */
_cdStopTime = SDL_GetTicks() + 100;
_cdNumLoops = 0;
}
void OSystem_SDL::playCD(int track, int num_loops, int start_frame, int duration) {
if (!num_loops && !start_frame)
return;
if (!_cdrom)
return;
if (duration > 0)
duration += 5;
_cdTrack = track;
_cdNumLoops = num_loops;
_cdStartFrame = start_frame;
SDL_CDStatus(_cdrom);
if (start_frame == 0 && duration == 0)
SDL_CDPlayTracks(_cdrom, track, 0, 1, 0);
else
SDL_CDPlayTracks(_cdrom, track, start_frame, 0, duration);
_cdDuration = duration;
_cdStopTime = 0;
_cdEndTime = SDL_GetTicks() + _cdrom->track[track].length * 1000 / CD_FPS;
}
bool OSystem_SDL::pollCD() {
if (!_cdrom)
return false;
return (_cdNumLoops != 0 && (SDL_GetTicks() < _cdEndTime || SDL_CDStatus(_cdrom) == CD_PLAYING));
}
void OSystem_SDL::updateCD() {
if (!_cdrom)
return;
if (_cdStopTime != 0 && SDL_GetTicks() >= _cdStopTime) {
SDL_CDStop(_cdrom);
_cdNumLoops = 0;
_cdStopTime = 0;
return;
}
if (_cdNumLoops == 0 || SDL_GetTicks() < _cdEndTime)
return;
if (_cdNumLoops != 1 && SDL_CDStatus(_cdrom) != CD_STOPPED) {
// Wait another second for it to be done
_cdEndTime += 1000;
return;
}
if (_cdNumLoops > 0)
_cdNumLoops--;
if (_cdNumLoops != 0) {
if (_cdStartFrame == 0 && _cdDuration == 0)
SDL_CDPlayTracks(_cdrom, _cdTrack, 0, 1, 0);
else
SDL_CDPlayTracks(_cdrom, _cdTrack, _cdStartFrame, 0, _cdDuration);
_cdEndTime = SDL_GetTicks() + _cdrom->track[_cdTrack].length * 1000 / CD_FPS;
}
}
#if defined(__SYMBIAN32__) #if defined(__SYMBIAN32__)
#include "SymbianOs.h" #include "SymbianOs.h"
#endif #endif

View file

@ -57,6 +57,9 @@ public:
// Update the dirty areas of the screen // Update the dirty areas of the screen
void updateScreen(); void updateScreen();
// Either show or hide the mouse cursor
bool showMouse(bool visible);
// Warp the mouse cursor. Where set_mouse_pos() only informs the // Warp the mouse cursor. Where set_mouse_pos() only informs the
// backend of the mouse cursor's current position, this function // backend of the mouse cursor's current position, this function
// actually moves the cursor to the specified position. // actually moves the cursor to the specified position.
@ -80,6 +83,19 @@ public:
virtual Audio::Mixer *getMixer(); virtual Audio::Mixer *getMixer();
// Poll CD status
// Returns true if cd audio is playing
bool pollCD();
// Play CD audio track
void playCD(int track, int num_loops, int start_frame, int duration);
// Stop CD audio track
void stopCD();
// Update CD audio status
void updateCD();
// Quit // Quit
virtual void quit(); virtual void quit();
@ -93,6 +109,7 @@ public:
void deleteMutex(MutexRef mutex); void deleteMutex(MutexRef mutex);
virtual void setWindowCaption(const char *caption); virtual void setWindowCaption(const char *caption);
virtual bool openCD(int drive);
virtual bool hasFeature(Feature f); virtual bool hasFeature(Feature f);
virtual void setFeatureState(Feature f, bool enable); virtual void setFeatureState(Feature f, bool enable);
@ -114,6 +131,11 @@ private:
int _samplesPerSec; int _samplesPerSec;
// CD Audio
SDL_CD *_cdrom;
int _cdTrack, _cdNumLoops, _cdStartFrame, _cdDuration;
uint32 _cdEndTime, _cdStopTime;
#ifdef MIXER_DOUBLE_BUFFERING #ifdef MIXER_DOUBLE_BUFFERING
SDL_mutex *_soundMutex; SDL_mutex *_soundMutex;
SDL_cond *_soundCond; SDL_cond *_soundCond;

View file

@ -53,7 +53,7 @@ void DefaultSaveFileManager::checkPath(const Common::FSNode &dir) {
} }
} }
Common::StringList DefaultSaveFileManager::listSavefiles(const char *pattern) { Common::StringList DefaultSaveFileManager::listSavefiles(const Common::String &pattern) {
Common::FSNode savePath(getSavePath()); Common::FSNode savePath(getSavePath());
checkPath(savePath); checkPath(savePath);
if (getError() != Common::kNoError) if (getError() != Common::kNoError)
@ -73,7 +73,7 @@ Common::StringList DefaultSaveFileManager::listSavefiles(const char *pattern) {
return results; return results;
} }
Common::InSaveFile *DefaultSaveFileManager::openForLoading(const char *filename) { Common::InSaveFile *DefaultSaveFileManager::openForLoading(const Common::String &filename) {
// Ensure that the savepath is valid. If not, generate an appropriate error. // Ensure that the savepath is valid. If not, generate an appropriate error.
Common::FSNode savePath(getSavePath()); Common::FSNode savePath(getSavePath());
checkPath(savePath); checkPath(savePath);
@ -90,7 +90,7 @@ Common::InSaveFile *DefaultSaveFileManager::openForLoading(const char *filename)
return Common::wrapCompressedReadStream(sf); return Common::wrapCompressedReadStream(sf);
} }
Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const char *filename) { Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const Common::String &filename) {
// Ensure that the savepath is valid. If not, generate an appropriate error. // Ensure that the savepath is valid. If not, generate an appropriate error.
Common::FSNode savePath(getSavePath()); Common::FSNode savePath(getSavePath());
checkPath(savePath); checkPath(savePath);
@ -105,7 +105,7 @@ Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const char *filename)
return Common::wrapCompressedWriteStream(sf); return Common::wrapCompressedWriteStream(sf);
} }
bool DefaultSaveFileManager::removeSavefile(const char *filename) { bool DefaultSaveFileManager::removeSavefile(const Common::String &filename) {
clearError(); clearError();
Common::FSNode savePath(getSavePath()); Common::FSNode savePath(getSavePath());
@ -139,6 +139,14 @@ Common::String DefaultSaveFileManager::getSavePath() const {
// Try to use game specific savepath from config // Try to use game specific savepath from config
dir = ConfMan.get("savepath"); dir = ConfMan.get("savepath");
// Work around a bug (#999122) in the original 0.6.1 release of
// ScummVM, which would insert a bad savepath value into config files.
if (dir == "None") {
ConfMan.removeKey("savepath", ConfMan.getActiveDomainName());
ConfMan.flushToDisk();
dir = ConfMan.get("savepath");
}
#ifdef _WIN32_WCE #ifdef _WIN32_WCE
if (dir.empty()) if (dir.empty())
dir = ConfMan.get("path"); dir = ConfMan.get("path");

View file

@ -38,10 +38,10 @@ public:
DefaultSaveFileManager(); DefaultSaveFileManager();
DefaultSaveFileManager(const Common::String &defaultSavepath); DefaultSaveFileManager(const Common::String &defaultSavepath);
virtual Common::StringList listSavefiles(const char *pattern); virtual Common::StringList listSavefiles(const Common::String &pattern);
virtual Common::InSaveFile *openForLoading(const char *filename); virtual Common::InSaveFile *openForLoading(const Common::String &filename);
virtual Common::OutSaveFile *openForSaving(const char *filename); virtual Common::OutSaveFile *openForSaving(const Common::String &filename);
virtual bool removeSavefile(const char *filename); virtual bool removeSavefile(const Common::String &filename);
protected: protected:
/** /**

View file

@ -30,7 +30,7 @@
namespace Common { namespace Common {
bool SaveFileManager::renameSavefile(const char *oldFilename, const char *newFilename) { bool SaveFileManager::renameSavefile(const String &oldFilename, const String &newFilename) {
InSaveFile *inFile = 0; InSaveFile *inFile = 0;
OutSaveFile *outFile = 0; OutSaveFile *outFile = 0;

View file

@ -52,8 +52,15 @@ static const EnginePlugin *detectPlugin() {
// Make sure the gameid is set in the config manager, and that it is lowercase. // Make sure the gameid is set in the config manager, and that it is lowercase.
Common::String gameid(ConfMan.getActiveDomainName()); Common::String gameid(ConfMan.getActiveDomainName());
assert(!gameid.empty()); assert(!gameid.empty());
if (ConfMan.hasKey("gameid")) if (ConfMan.hasKey("gameid")) {
gameid = ConfMan.get("gameid"); gameid = ConfMan.get("gameid");
// Set last selected game, that the game will be highlighted
// on RTL
ConfMan.set("lastselectedgame", ConfMan.getActiveDomainName(), Common::ConfigManager::kApplicationDomain);
ConfMan.flushToDisk();
}
gameid.toLowercase(); gameid.toLowercase();
ConfMan.set("gameid", gameid); ConfMan.set("gameid", gameid);

View file

@ -32,7 +32,12 @@ const char *gResidualVersionDate = RESIDUAL_VERSION " (" __DATE__ " " __TIME__ "
const char *gResidualFullVersion = "Residual " RESIDUAL_VERSION " (" __DATE__ " " __TIME__ ")"; const char *gResidualFullVersion = "Residual " RESIDUAL_VERSION " (" __DATE__ " " __TIME__ ")";
const char *gResidualFeatures = "" const char *gResidualFeatures = ""
#ifdef USE_TREMOR #ifdef USE_TREMOR
#ifdef USE_TREMOLO
// libTremolo is used on WinCE for better ogg performance
"Tremolo "
#else
"Tremor " "Tremor "
#endif
#else #else
#ifdef USE_VORBIS #ifdef USE_VORBIS
"Vorbis " "Vorbis "

View file

@ -110,16 +110,16 @@ void SearchSet::add(const String &name, Archive *archive, int priority, bool aut
} }
void SearchSet::addDirectory(const String &name, const String &directory, int priority, int depth) { void SearchSet::addDirectory(const String &name, const String &directory, int priority, int depth, bool flat) {
FSNode dir(directory); FSNode dir(directory);
addDirectory(name, dir, priority, depth); addDirectory(name, dir, priority, depth, flat);
} }
void SearchSet::addDirectory(const String &name, const FSNode &dir, int priority, int depth) { void SearchSet::addDirectory(const String &name, const FSNode &dir, int priority, int depth, bool flat) {
if (!dir.exists() || !dir.isDirectory()) if (!dir.exists() || !dir.isDirectory())
return; return;
add(name, new FSDirectory(dir, depth), priority); add(name, new FSDirectory(dir, depth, flat), priority);
} }

View file

@ -161,12 +161,12 @@ public:
/** /**
* Create and add a FSDirectory by name * Create and add a FSDirectory by name
*/ */
void addDirectory(const String &name, const String &directory, int priority = 0, int depth = 1); void addDirectory(const String &name, const String &directory, int priority = 0, int depth = 1, bool flat = false);
/** /**
* Create and add a FSDirectory by FSNode * Create and add a FSDirectory by FSNode
*/ */
void addDirectory(const String &name, const FSNode &directory, int priority = 0, int depth = 1); void addDirectory(const String &name, const FSNode &directory, int priority = 0, int depth = 1, bool flat = false);
/** /**
* Remove an archive from the searchable set. * Remove an archive from the searchable set.

View file

@ -45,11 +45,19 @@ namespace Common {
const String ConfigManager::kApplicationDomain("residual"); const String ConfigManager::kApplicationDomain("residual");
const String ConfigManager::kTransientDomain("__TRANSIENT"); const String ConfigManager::kTransientDomain("__TRANSIENT");
#ifdef ENABLE_KEYMAPPER
const String ConfigManager::kKeymapperDomain("keymapper");
#endif
#else #else
const char *ConfigManager::kApplicationDomain = "residual"; const char *ConfigManager::kApplicationDomain = "residual";
const char *ConfigManager::kTransientDomain = "__TRANSIENT"; const char *ConfigManager::kTransientDomain = "__TRANSIENT";
#ifdef ENABLE_KEYMAPPER
const char *ConfigManager::kKeymapperDomain = "keymapper";
#endif
#endif #endif
#pragma mark - #pragma mark -
@ -99,6 +107,10 @@ void ConfigManager::loadFromStream(SeekableReadStream &stream) {
_transientDomain.clear(); _transientDomain.clear();
_domainSaveOrder.clear(); _domainSaveOrder.clear();
#ifdef ENABLE_KEYMAPPER
_keymapperDomain.clear();
#endif
// TODO: Detect if a domain occurs multiple times (or likewise, if // TODO: Detect if a domain occurs multiple times (or likewise, if
// a key occurs multiple times inside one domain). // a key occurs multiple times inside one domain).
@ -139,6 +151,10 @@ void ConfigManager::loadFromStream(SeekableReadStream &stream) {
// Store domain comment // Store domain comment
if (domain == kApplicationDomain) { if (domain == kApplicationDomain) {
_appDomain.setDomainComment(comment); _appDomain.setDomainComment(comment);
#ifdef ENABLE_KEYMAPPER
} else if (domain == kKeymapperDomain) {
_keymapperDomain.setDomainComment(comment);
#endif
} else { } else {
_gameDomains[domain].setDomainComment(comment); _gameDomains[domain].setDomainComment(comment);
} }
@ -181,6 +197,10 @@ void ConfigManager::loadFromStream(SeekableReadStream &stream) {
// Store comment // Store comment
if (domain == kApplicationDomain) { if (domain == kApplicationDomain) {
_appDomain.setKVComment(key, comment); _appDomain.setKVComment(key, comment);
#ifdef ENABLE_KEYMAPPER
} else if (domain == kKeymapperDomain) {
_keymapperDomain.setKVComment(key, comment);
#endif
} else { } else {
_gameDomains[domain].setKVComment(key, comment); _gameDomains[domain].setKVComment(key, comment);
} }
@ -219,6 +239,10 @@ void ConfigManager::flushToDisk() {
for (i = _domainSaveOrder.begin(); i != _domainSaveOrder.end(); ++i) { for (i = _domainSaveOrder.begin(); i != _domainSaveOrder.end(); ++i) {
if (kApplicationDomain == *i) { if (kApplicationDomain == *i) {
writeDomain(*stream, *i, _appDomain); writeDomain(*stream, *i, _appDomain);
#ifdef ENABLE_KEYMAPPER
} else if (kKeymapperDomain == *i) {
writeDomain(*stream, *i, _keymapperDomain);
#endif
} else if (_gameDomains.contains(*i)) { } else if (_gameDomains.contains(*i)) {
writeDomain(*stream, *i, _gameDomains[*i]); writeDomain(*stream, *i, _gameDomains[*i]);
} }
@ -230,6 +254,10 @@ void ConfigManager::flushToDisk() {
// Now write the domains which haven't been written yet // Now write the domains which haven't been written yet
if (find(_domainSaveOrder.begin(), _domainSaveOrder.end(), kApplicationDomain) == _domainSaveOrder.end()) if (find(_domainSaveOrder.begin(), _domainSaveOrder.end(), kApplicationDomain) == _domainSaveOrder.end())
writeDomain(*stream, kApplicationDomain, _appDomain); writeDomain(*stream, kApplicationDomain, _appDomain);
#ifdef ENABLE_KEYMAPPER
if (find(_domainSaveOrder.begin(), _domainSaveOrder.end(), kKeymapperDomain) == _domainSaveOrder.end())
writeDomain(*stream, kKeymapperDomain, _keymapperDomain);
#endif
for (d = _gameDomains.begin(); d != _gameDomains.end(); ++d) { for (d = _gameDomains.begin(); d != _gameDomains.end(); ++d) {
if (find(_domainSaveOrder.begin(), _domainSaveOrder.end(), d->_key) == _domainSaveOrder.end()) if (find(_domainSaveOrder.begin(), _domainSaveOrder.end(), d->_key) == _domainSaveOrder.end())
writeDomain(*stream, d->_key, d->_value); writeDomain(*stream, d->_key, d->_value);
@ -309,6 +337,10 @@ const ConfigManager::Domain *ConfigManager::getDomain(const String &domName) con
return &_transientDomain; return &_transientDomain;
if (domName == kApplicationDomain) if (domName == kApplicationDomain)
return &_appDomain; return &_appDomain;
#ifdef ENABLE_KEYMAPPER
if (domName == kKeymapperDomain)
return &_keymapperDomain;
#endif
if (_gameDomains.contains(domName)) if (_gameDomains.contains(domName))
return &_gameDomains[domName]; return &_gameDomains[domName];
@ -323,6 +355,10 @@ ConfigManager::Domain *ConfigManager::getDomain(const String &domName) {
return &_transientDomain; return &_transientDomain;
if (domName == kApplicationDomain) if (domName == kApplicationDomain)
return &_appDomain; return &_appDomain;
#ifdef ENABLE_KEYMAPPER
if (domName == kKeymapperDomain)
return &_keymapperDomain;
#endif
if (_gameDomains.contains(domName)) if (_gameDomains.contains(domName))
return &_gameDomains[domName]; return &_gameDomains[domName];

View file

@ -74,11 +74,23 @@ public:
/** The transient (pseudo) domain. */ /** The transient (pseudo) domain. */
static const String kTransientDomain; static const String kTransientDomain;
#ifdef ENABLE_KEYMAPPER
/** The name of keymapper domain used to store the key maps */
static const String kKeymapperDomain;
#endif
#else #else
static const char *kApplicationDomain; static const char *kApplicationDomain;
static const char *kTransientDomain; static const char *kTransientDomain;
const String _emptyString; const String _emptyString;
#ifdef ENABLE_KEYMAPPER
/** The name of keymapper domain used to store the key maps */
static const char *kKeymapperDomain;
#endif
#endif #endif
void loadDefaultConfigFile(); void loadDefaultConfigFile();
@ -143,6 +155,7 @@ public:
void renameGameDomain(const String &oldName, const String &newName); void renameGameDomain(const String &oldName, const String &newName);
bool hasGameDomain(const String &domName) const; bool hasGameDomain(const String &domName) const;
const DomainMap & getGameDomains() const { return _gameDomains; } const DomainMap & getGameDomains() const { return _gameDomains; }
DomainMap & getGameDomains() { return _gameDomains; }
private: private:
friend class Singleton<SingletonBaseType>; friend class Singleton<SingletonBaseType>;
@ -156,6 +169,10 @@ private:
Domain _appDomain; Domain _appDomain;
Domain _defaultsDomain; Domain _defaultsDomain;
#ifdef ENABLE_KEYMAPPER
Domain _keymapperDomain;
#endif
StringList _domainSaveOrder; StringList _domainSaveOrder;
String _activeDomainName; String _activeDomainName;

View file

@ -123,15 +123,15 @@ DebugChannelList listDebugChannels() {
} }
bool isDebugChannelEnabled(uint32 level) { bool isDebugChannelEnabled(uint32 level) {
// FIXME: Seems gDebugLevel 11 has a special meaning? Document that! // Debug level 11 turns on all special debug level messages
if (gDebugLevel == 11) if (gDebugLevel == 11)
return true; return true;
// return gDebugLevelsEnabled & (1 << level); // return gDebugLevelsEnabled & (1 << level);
return (gDebugLevelsEnabled & level) != 0; return gDebugLevelsEnabled & level;
} }
bool isDebugChannelEnabled(const String &name) { bool isDebugChannelEnabled(const String &name) {
// FIXME: Seems gDebugLevel 11 has a special meaning? Document that! // Debug level 11 turns on all special debug level messages
if (gDebugLevel == 11) if (gDebugLevel == 11)
return true; return true;
@ -211,7 +211,7 @@ void debugN(int level, const char *s, ...) {
void debugC(int level, uint32 debugChannels, const char *s, ...) { void debugC(int level, uint32 debugChannels, const char *s, ...) {
va_list va; va_list va;
// FIXME: Seems gDebugLevel 11 has a special meaning? Document that! // Debug level 11 turns on all special debug level messages
if (gDebugLevel != 11) if (gDebugLevel != 11)
if (level > gDebugLevel || !(Common::gDebugLevelsEnabled & debugChannels)) if (level > gDebugLevel || !(Common::gDebugLevelsEnabled & debugChannels))
return; return;
@ -221,10 +221,23 @@ void debugC(int level, uint32 debugChannels, const char *s, ...) {
va_end(va); va_end(va);
} }
void debugCN(int level, uint32 debugChannels, const char *s, ...) {
va_list va;
// Debug level 11 turns on all special debug level messages
if (gDebugLevel != 11)
if (level > gDebugLevel || !(Common::gDebugLevelsEnabled & debugChannels))
return;
va_start(va, s);
debugHelper(s, va, false);
va_end(va);
}
void debugC(uint32 debugChannels, const char *s, ...) { void debugC(uint32 debugChannels, const char *s, ...) {
va_list va; va_list va;
// FIXME: Seems gDebugLevel 11 has a special meaning? Document that! // Debug level 11 turns on all special debug level messages
if (gDebugLevel != 11) if (gDebugLevel != 11)
if (!(Common::gDebugLevelsEnabled & debugChannels)) if (!(Common::gDebugLevelsEnabled & debugChannels))
return; return;
@ -234,4 +247,17 @@ void debugC(uint32 debugChannels, const char *s, ...) {
va_end(va); va_end(va);
} }
void debugCN(uint32 debugChannels, const char *s, ...) {
va_list va;
// Debug level 11 turns on all special debug level messages
if (gDebugLevel != 11)
if (!(Common::gDebugLevelsEnabled & debugChannels))
return;
va_start(va, s);
debugHelper(s, va, false);
va_end(va);
}
#endif #endif

View file

@ -29,7 +29,7 @@
#include "common/sys.h" #include "common/sys.h"
#include "common/list.h" #include "common/list.h"
#include "common/str.h" #include "common/str.h"
enum enDebugLevels { DEBUG_NONE, DEBUG_NORMAL, DEBUG_WARN, DEBUG_ERROR, DEBUG_LUA, DEBUG_BITMAPS, DEBUG_MODEL, DEBUG_STUB, DEBUG_SMUSH, DEBUG_IMUSE, DEBUG_CHORES, DEBUG_ALL};
namespace Common { namespace Common {
@ -107,6 +107,8 @@ inline void debug(int level, const char *s, ...) {}
inline void debugN(int level, const char *s, ...) {} inline void debugN(int level, const char *s, ...) {}
inline void debugC(int level, uint32 engine_level, const char *s, ...) {} inline void debugC(int level, uint32 engine_level, const char *s, ...) {}
inline void debugC(uint32 engine_level, const char *s, ...) {} inline void debugC(uint32 engine_level, const char *s, ...) {}
inline void debugCN(int level, uint32 engine_level, const char *s, ...) {}
inline void debugCN(uint32 engine_level, const char *s, ...) {}
#else #else
@ -136,7 +138,7 @@ void debugN(int level, const char *s, ...) GCC_PRINTF(2, 3);
/** /**
* Print a debug message to the text console (stdout), but only if * Print a debug message to the text console (stdout), but only if
* the specified level does not exceed the value of gDebugLevel OR * the specified level does not exceed the value of gDebugLevel AND
* if the specified special debug level is active. * if the specified special debug level is active.
* As a rule of thumb, the more important the message, the lower the level. * As a rule of thumb, the more important the message, the lower the level.
* Automatically appends a newline. * Automatically appends a newline.
@ -145,6 +147,17 @@ void debugN(int level, const char *s, ...) GCC_PRINTF(2, 3);
*/ */
void debugC(int level, uint32 debugChannels, const char *s, ...) GCC_PRINTF(3, 4); void debugC(int level, uint32 debugChannels, const char *s, ...) GCC_PRINTF(3, 4);
/**
* Print a debug message to the text console (stdout), but only if
* the specified level does not exceed the value of gDebugLevel AND
* if the specified special debug level is active.
* As a rule of thumb, the more important the message, the lower the level.
* Does not append a newline automatically.
*
* @see enableDebugChannel
*/
void debugCN(int level, uint32 debugChannels, const char *s, ...) GCC_PRINTF(3, 4);
/** /**
* Print a debug message to the text console (stdout), but only if * Print a debug message to the text console (stdout), but only if
* the specified special debug level is active. * the specified special debug level is active.
@ -154,6 +167,14 @@ void debugC(int level, uint32 debugChannels, const char *s, ...) GCC_PRINTF(3, 4
*/ */
void debugC(uint32 debugChannels, const char *s, ...) GCC_PRINTF(2, 3); void debugC(uint32 debugChannels, const char *s, ...) GCC_PRINTF(2, 3);
/**
* Print a debug message to the text console (stdout), but only if
* the specified special debug level is active.
* Does not append a newline automatically.
*
* @see enableDebugChannel
*/
void debugCN(uint32 debugChannels, const char *s, ...) GCC_PRINTF(2, 3);
#endif #endif

View file

@ -60,6 +60,8 @@ enum EventType {
EVENT_MBUTTONUP = 14, EVENT_MBUTTONUP = 14,
EVENT_MAINMENU = 15, EVENT_MAINMENU = 15,
EVENT_RTL = 16,
EVENT_MUTE = 17,
EVENT_QUIT = 10, EVENT_QUIT = 10,
EVENT_SCREEN_CHANGED = 11, EVENT_SCREEN_CHANGED = 11,
@ -147,7 +149,6 @@ public:
* @note called after graphics system has been set up * @note called after graphics system has been set up
*/ */
virtual void init() {} virtual void init() {}
/** /**
* Get the next event in the event queue. * Get the next event in the event queue.
* @param event point to an Event struct, which will be filled with the event data. * @param event point to an Event struct, which will be filled with the event data.
@ -184,6 +185,17 @@ public:
*/ */
virtual int shouldQuit() const = 0; virtual int shouldQuit() const = 0;
/**
* Should we return to the launcher?
*/
virtual int shouldRTL() const = 0;
/**
* Reset the "return to launcher" flag (as returned shouldRTL()) to false.
* Used when we have returned to the launcher.
*/
virtual void resetRTL() = 0;
// Optional: check whether a given key is currently pressed ???? // Optional: check whether a given key is currently pressed ????
//virtual bool isKeyPressed(int keycode) = 0; //virtual bool isKeyPressed(int keycode) = 0;
@ -191,6 +203,9 @@ public:
// TODO: Consider removing OSystem::getScreenChangeID and // TODO: Consider removing OSystem::getScreenChangeID and
// replacing it by a generic getScreenChangeID method here // replacing it by a generic getScreenChangeID method here
#ifdef ENABLE_KEYMAPPER
virtual Common::Keymapper *getKeymapper() = 0;
#endif
protected: protected:

View file

@ -164,22 +164,22 @@ Common::WriteStream *FSNode::createWriteStream() const {
return _realNode->createWriteStream(); return _realNode->createWriteStream();
} }
FSDirectory::FSDirectory(const FSNode &node, int depth) FSDirectory::FSDirectory(const FSNode &node, int depth, bool flat)
: _node(node), _cached(false), _depth(depth) { : _node(node), _cached(false), _depth(depth), _flat(flat) {
} }
FSDirectory::FSDirectory(const String &prefix, const FSNode &node, int depth) FSDirectory::FSDirectory(const String &prefix, const FSNode &node, int depth, bool flat)
: _node(node), _cached(false), _depth(depth) { : _node(node), _cached(false), _depth(depth), _flat(flat) {
setPrefix(prefix); setPrefix(prefix);
} }
FSDirectory::FSDirectory(const String &name, int depth) FSDirectory::FSDirectory(const String &name, int depth, bool flat)
: _node(name), _cached(false), _depth(depth) { : _node(name), _cached(false), _depth(depth), _flat(flat) {
} }
FSDirectory::FSDirectory(const String &prefix, const String &name, int depth) FSDirectory::FSDirectory(const String &prefix, const String &name, int depth, bool flat)
: _node(name), _cached(false), _depth(depth) { : _node(name), _cached(false), _depth(depth), _flat(flat) {
setPrefix(prefix); setPrefix(prefix);
} }
@ -249,11 +249,11 @@ SeekableReadStream *FSDirectory::createReadStreamForMember(const String &name) c
return stream; return stream;
} }
FSDirectory *FSDirectory::getSubDirectory(const String &name, int depth) { FSDirectory *FSDirectory::getSubDirectory(const String &name, int depth, bool flat) {
return getSubDirectory(String::emptyString, name, depth); return getSubDirectory(String::emptyString, name, depth, flat);
} }
FSDirectory *FSDirectory::getSubDirectory(const String &prefix, const String &name, int depth) { FSDirectory *FSDirectory::getSubDirectory(const String &prefix, const String &name, int depth, bool flat) {
if (name.empty() || !_node.isDirectory()) if (name.empty() || !_node.isDirectory())
return 0; return 0;
@ -261,7 +261,7 @@ FSDirectory *FSDirectory::getSubDirectory(const String &prefix, const String &na
if (!node) if (!node)
return 0; return 0;
return new FSDirectory(prefix, *node, depth); return new FSDirectory(prefix, *node, depth, flat);
} }
void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const String& prefix) const { void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const String& prefix) const {
@ -281,10 +281,13 @@ void FSDirectory::cacheDirectoryRecursive(FSNode node, int depth, const String&
// since the hashmap is case insensitive, we need to check for clashes when caching // since the hashmap is case insensitive, we need to check for clashes when caching
if (it->isDirectory()) { if (it->isDirectory()) {
if (_subDirCache.contains(lowercaseName)) { if (!_flat && _subDirCache.contains(lowercaseName)) {
warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring sub-directory '%s'", name.c_str()); warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring sub-directory '%s'", name.c_str());
} else { } else {
cacheDirectoryRecursive(*it, depth - 1, lowercaseName + "/"); if (_subDirCache.contains(lowercaseName)) {
warning("FSDirectory::cacheDirectory: name clash when building subDirCache with subdirectory '%s'", name.c_str());
}
cacheDirectoryRecursive(*it, depth - 1, _flat ? prefix : lowercaseName + "/");
_subDirCache[lowercaseName] = *it; _subDirCache[lowercaseName] = *it;
} }
} else { } else {

View file

@ -233,8 +233,8 @@ public:
* *
* FSDirectory can represent a single directory, or a tree with specified depth, * FSDirectory can represent a single directory, or a tree with specified depth,
* depending on the value passed to the 'depth' parameter in the constructors. * depending on the value passed to the 'depth' parameter in the constructors.
* Filenames are cached with their relative path, with elements separated by * In the default mode, filenames are cached with their relative path,
* slashes, e.g.: * with elements separated by slashes, e.g.:
* *
* c:\my\data\file.ext * c:\my\data\file.ext
* *
@ -248,11 +248,16 @@ public:
* hasFile(), listMatchingMembers() and listMembers(). Please see the function * hasFile(), listMatchingMembers() and listMembers(). Please see the function
* specific comments for more information. * specific comments for more information.
* *
* If the 'flat' argument to the constructor is true, files in subdirectories
* are cached without the relative path, so in the example above
* c:\my\data\file.ext would be cached as file.ext.
*
* Client code can customize cache by using the constructors with the 'prefix' * Client code can customize cache by using the constructors with the 'prefix'
* parameter. In this case, the prefix is prepended to each entry in the cache, * parameter. In this case, the prefix is prepended to each entry in the cache,
* and effectively treated as a 'virtual' parent subdirectory. FSDirectory adds * and effectively treated as a 'virtual' parent subdirectory. FSDirectory adds
* a trailing slash to prefix if needed. Following on with the previous example * a trailing slash to prefix if needed. Following on with the previous example
* and using 'your' as prefix, the cache entry would have been 'your/data/file.ext'. * and using 'your' as prefix, the cache entry would have been 'your/data/file.ext'.
* This is done both in non-flat and flat mode.
* *
*/ */
class FSDirectory : public Archive { class FSDirectory : public Archive {
@ -267,6 +272,7 @@ class FSDirectory : public Archive {
mutable NodeCache _fileCache, _subDirCache; mutable NodeCache _fileCache, _subDirCache;
mutable bool _cached; mutable bool _cached;
mutable int _depth; mutable int _depth;
mutable bool _flat;
// look for a match // look for a match
FSNode *lookupCache(NodeCache &cache, const String &name) const; FSNode *lookupCache(NodeCache &cache, const String &name) const;
@ -283,15 +289,17 @@ public:
* unbound FSDirectory if name is not found on the filesystem or if the node is not a * unbound FSDirectory if name is not found on the filesystem or if the node is not a
* valid directory. * valid directory.
*/ */
FSDirectory(const String &name, int depth = 1); FSDirectory(const String &name, int depth = 1, bool flat = false);
FSDirectory(const FSNode &node, int depth = 1); FSDirectory(const FSNode &node, int depth = 1, bool flat = false);
/** /**
* Create a FSDirectory representing a tree with the specified depth. The parameter * Create a FSDirectory representing a tree with the specified depth. The parameter
* prefix is prepended to the keys in the cache. See class comment. * prefix is prepended to the keys in the cache. See class comment.
*/ */
FSDirectory(const String &prefix, const String &name, int depth = 1); FSDirectory(const String &prefix, const String &name, int depth = 1,
FSDirectory(const String &prefix, const FSNode &node, int depth = 1); bool flat = false);
FSDirectory(const String &prefix, const FSNode &node, int depth = 1,
bool flat = false);
virtual ~FSDirectory(); virtual ~FSDirectory();
@ -305,8 +313,8 @@ public:
* for an explanation of the prefix parameter. * for an explanation of the prefix parameter.
* @return a new FSDirectory instance * @return a new FSDirectory instance
*/ */
FSDirectory *getSubDirectory(const String &name, int depth = 1); FSDirectory *getSubDirectory(const String &name, int depth = 1, bool flat = false);
FSDirectory *getSubDirectory(const String &prefix, const String &name, int depth = 1); FSDirectory *getSubDirectory(const String &prefix, const String &name, int depth = 1, bool flat = false);
/** /**
* Checks for existence in the cache. A full match of relative path and filename is needed * Checks for existence in the cache. A full match of relative path and filename is needed

View file

@ -58,6 +58,7 @@ uint hashit_lower(const char *p) {
#ifdef DEBUG_HASH_COLLISIONS #ifdef DEBUG_HASH_COLLISIONS
static double static double
g_collisions = 0, g_collisions = 0,
g_dummyHits = 0,
g_lookups = 0, g_lookups = 0,
g_collPerLook = 0, g_collPerLook = 0,
g_capacity = 0, g_capacity = 0,
@ -66,9 +67,10 @@ static int g_max_capacity = 0, g_max_size = 0;
static int g_totalHashmaps = 0; static int g_totalHashmaps = 0;
static int g_stats[4] = {0,0,0,0}; static int g_stats[4] = {0,0,0,0};
void updateHashCollisionStats(int collisions, int lookups, int arrsize, int nele) { void updateHashCollisionStats(int collisions, int dummyHits, int lookups, int arrsize, int nele) {
g_collisions += collisions; g_collisions += collisions;
g_lookups += lookups; g_lookups += lookups;
g_dummyHits += dummyHits;
if (lookups) if (lookups)
g_collPerLook += (double)collisions / (double)lookups; g_collPerLook += (double)collisions / (double)lookups;
g_capacity += arrsize; g_capacity += arrsize;
@ -87,9 +89,10 @@ void updateHashCollisionStats(int collisions, int lookups, int arrsize, int nele
g_max_capacity = MAX(g_max_capacity, arrsize); g_max_capacity = MAX(g_max_capacity, arrsize);
g_max_size = MAX(g_max_size, nele); g_max_size = MAX(g_max_size, nele);
fprintf(stdout, "%d hashmaps: colls %.1f; lookups %.1f; ratio %.3f%%; size %f (max: %d); capacity %f (max: %d)\n", fprintf(stdout, "%d hashmaps: colls %.1f; dummies hit %.1f, lookups %.1f; ratio %.3f%%; size %f (max: %d); capacity %f (max: %d)\n",
g_totalHashmaps, g_totalHashmaps,
g_collisions / g_totalHashmaps, g_collisions / g_totalHashmaps,
g_dummyHits / g_totalHashmaps,
g_lookups / g_totalHashmaps, g_lookups / g_totalHashmaps,
100 * g_collPerLook / g_totalHashmaps, 100 * g_collPerLook / g_totalHashmaps,
g_size / g_totalHashmaps, g_max_size, g_size / g_totalHashmaps, g_max_size,

View file

@ -24,8 +24,7 @@
*/ */
// The hash map (associative array) implementation in this file is // The hash map (associative array) implementation in this file is
// based on the PyDict implementation of CPython. The erase() method // based on the PyDict implementation of CPython.
// is based on example code in the Wikipedia article on Hash tables.
#ifndef COMMON_HASHMAP_H #ifndef COMMON_HASHMAP_H
#define COMMON_HASHMAP_H #define COMMON_HASHMAP_H
@ -72,7 +71,8 @@ public:
struct Node { struct Node {
const Key _key; const Key _key;
Val _value; Val _value;
Node(const Key &key) : _key(key), _value() {} explicit Node(const Key &key) : _key(key), _value() {}
Node() : _key(), _value() {}
}; };
enum { enum {
@ -98,12 +98,14 @@ public:
} }
void freeNode(Node *node) { void freeNode(Node *node) {
if (node && node != &_dummyNode)
_nodePool.deleteChunk(node); _nodePool.deleteChunk(node);
} }
Node **_storage; // hashtable of size arrsize. Node **_storage; // hashtable of size arrsize.
uint _mask; /**< Capacity of the HashMap minus one; must be a power of two of minus one */ uint _mask; /**< Capacity of the HashMap minus one; must be a power of two of minus one */
uint _size; uint _size;
uint _deleted; ///< Number of deleted elements (_dummyNodes)
HashFunc _hash; HashFunc _hash;
EqualFunc _equal; EqualFunc _equal;
@ -111,8 +113,11 @@ public:
// Default value, returned by the const getVal. // Default value, returned by the const getVal.
const Val _defaultVal; const Val _defaultVal;
// Dummy node, used as marker for erased objects.
Node _dummyNode;
#ifdef DEBUG_HASH_COLLISIONS #ifdef DEBUG_HASH_COLLISIONS
mutable int _collisions, _lookups; mutable int _collisions, _lookups, _dummyHits;
#endif #endif
void assign(const HM_t &map); void assign(const HM_t &map);
@ -269,7 +274,7 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap()
#ifdef __PLAYSTATION2__ #ifdef __PLAYSTATION2__
{ {
#else #else
: _defaultVal() { : _defaultVal(), _dummyNode() {
#endif #endif
_mask = HASHMAP_MIN_CAPACITY - 1; _mask = HASHMAP_MIN_CAPACITY - 1;
_storage = new Node *[HASHMAP_MIN_CAPACITY]; _storage = new Node *[HASHMAP_MIN_CAPACITY];
@ -277,10 +282,12 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap()
memset(_storage, 0, HASHMAP_MIN_CAPACITY * sizeof(Node *)); memset(_storage, 0, HASHMAP_MIN_CAPACITY * sizeof(Node *));
_size = 0; _size = 0;
_deleted = 0;
#ifdef DEBUG_HASH_COLLISIONS #ifdef DEBUG_HASH_COLLISIONS
_collisions = 0; _collisions = 0;
_lookups = 0; _lookups = 0;
_dummyHits = 0;
#endif #endif
} }
@ -291,7 +298,12 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap()
*/ */
template<class Key, class Val, class HashFunc, class EqualFunc> template<class Key, class Val, class HashFunc, class EqualFunc>
HashMap<Key, Val, HashFunc, EqualFunc>::HashMap(const HM_t &map) : HashMap<Key, Val, HashFunc, EqualFunc>::HashMap(const HM_t &map) :
_defaultVal() { _defaultVal(), _dummyNode() {
#ifdef DEBUG_HASH_COLLISIONS
_collisions = 0;
_lookups = 0;
_dummyHits = 0;
#endif
assign(map); assign(map);
} }
@ -301,13 +313,12 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap(const HM_t &map) :
template<class Key, class Val, class HashFunc, class EqualFunc> template<class Key, class Val, class HashFunc, class EqualFunc>
HashMap<Key, Val, HashFunc, EqualFunc>::~HashMap() { HashMap<Key, Val, HashFunc, EqualFunc>::~HashMap() {
for (uint ctr = 0; ctr <= _mask; ++ctr) for (uint ctr = 0; ctr <= _mask; ++ctr)
if (_storage[ctr] != NULL)
freeNode(_storage[ctr]); freeNode(_storage[ctr]);
delete[] _storage; delete[] _storage;
#ifdef DEBUG_HASH_COLLISIONS #ifdef DEBUG_HASH_COLLISIONS
extern void updateHashCollisionStats(int, int, int, int); extern void updateHashCollisionStats(int, int, int, int, int);
updateHashCollisionStats(_collisions, _lookups, _mask+1, _size); updateHashCollisionStats(_collisions, _dummyHits, _lookups, _mask+1, _size);
#endif #endif
} }
@ -327,8 +338,12 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::assign(const HM_t &map) {
// Simply clone the map given to us, one by one. // Simply clone the map given to us, one by one.
_size = 0; _size = 0;
_deleted = 0;
for (uint ctr = 0; ctr <= _mask; ++ctr) { for (uint ctr = 0; ctr <= _mask; ++ctr) {
if (map._storage[ctr] != NULL) { if (map._storage[ctr] == &map._dummyNode) {
_storage[ctr] = &_dummyNode;
_deleted++;
} else if (map._storage[ctr] != NULL) {
_storage[ctr] = allocNode(map._storage[ctr]->_key); _storage[ctr] = allocNode(map._storage[ctr]->_key);
_storage[ctr]->_value = map._storage[ctr]->_value; _storage[ctr]->_value = map._storage[ctr]->_value;
_size++; _size++;
@ -336,17 +351,16 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::assign(const HM_t &map) {
} }
// Perform a sanity check (to help track down hashmap corruption) // Perform a sanity check (to help track down hashmap corruption)
assert(_size == map._size); assert(_size == map._size);
assert(_deleted == map._deleted);
} }
template<class Key, class Val, class HashFunc, class EqualFunc> template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) { void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) {
for (uint ctr = 0; ctr <= _mask; ++ctr) { for (uint ctr = 0; ctr <= _mask; ++ctr) {
if (_storage[ctr] != NULL) {
freeNode(_storage[ctr]); freeNode(_storage[ctr]);
_storage[ctr] = NULL; _storage[ctr] = NULL;
} }
}
#ifdef USE_HASHMAP_MEMORY_POOL #ifdef USE_HASHMAP_MEMORY_POOL
_nodePool.freeUnusedPages(); _nodePool.freeUnusedPages();
@ -362,6 +376,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) {
} }
_size = 0; _size = 0;
_deleted = 0;
} }
template<class Key, class Val, class HashFunc, class EqualFunc> template<class Key, class Val, class HashFunc, class EqualFunc>
@ -374,6 +389,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) {
// allocate a new array // allocate a new array
_size = 0; _size = 0;
_deleted = 0;
_mask = newCapacity - 1; _mask = newCapacity - 1;
_storage = new Node *[newCapacity]; _storage = new Node *[newCapacity];
assert(_storage != NULL); assert(_storage != NULL);
@ -381,7 +397,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) {
// rehash all the old elements // rehash all the old elements
for (uint ctr = 0; ctr <= old_mask; ++ctr) { for (uint ctr = 0; ctr <= old_mask; ++ctr) {
if (old_storage[ctr] == NULL) if (old_storage[ctr] == NULL || old_storage[ctr] == &_dummyNode)
continue; continue;
// Insert the element from the old table into the new table. // Insert the element from the old table into the new table.
@ -390,7 +406,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) {
// don't have to call _equal(). // don't have to call _equal().
const uint hash = _hash(old_storage[ctr]->_key); const uint hash = _hash(old_storage[ctr]->_key);
uint idx = hash & _mask; uint idx = hash & _mask;
for (uint perturb = hash; _storage[idx] != NULL; perturb >>= HASHMAP_PERTURB_SHIFT) { for (uint perturb = hash; _storage[idx] != NULL && _storage[idx] != &_dummyNode; perturb >>= HASHMAP_PERTURB_SHIFT) {
idx = (5 * idx + perturb + 1) & _mask; idx = (5 * idx + perturb + 1) & _mask;
} }
@ -412,7 +428,13 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const {
const uint hash = _hash(key); const uint hash = _hash(key);
uint ctr = hash & _mask; uint ctr = hash & _mask;
for (uint perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) { for (uint perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) {
if (_storage[ctr] == NULL || _equal(_storage[ctr]->_key, key)) if (_storage[ctr] == NULL)
break;
if (_storage[ctr] == &_dummyNode) {
#ifdef DEBUG_HASH_COLLISIONS
_dummyHits++;
#endif
} else if (_equal(_storage[ctr]->_key, key))
break; break;
ctr = (5 * ctr + perturb + 1) & _mask; ctr = (5 * ctr + perturb + 1) & _mask;
@ -424,8 +446,8 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const {
#ifdef DEBUG_HASH_COLLISIONS #ifdef DEBUG_HASH_COLLISIONS
_lookups++; _lookups++;
fprintf(stderr, "collisions %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d\n", fprintf(stderr, "collisions %d, dummies hit %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d\n",
_collisions, _lookups, ((double) _collisions / (double)_lookups), _collisions, _dummyHits, _lookups, ((double) _collisions / (double)_lookups),
(const void *)this, _mask+1, _size); (const void *)this, _mask+1, _size);
#endif #endif
@ -434,16 +456,54 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const {
template<class Key, class Val, class HashFunc, class EqualFunc> template<class Key, class Val, class HashFunc, class EqualFunc>
int HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key &key) { int HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key &key) {
uint ctr = lookup(key); const uint hash = _hash(key);
uint ctr = hash & _mask;
const uint NONE_FOUND = _mask + 1;
uint first_free = NONE_FOUND;
bool found = false;
for (uint perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) {
if (_storage[ctr] == NULL)
break;
if (_storage[ctr] == &_dummyNode) {
#ifdef DEBUG_HASH_COLLISIONS
_dummyHits++;
#endif
if (first_free != _mask + 1)
first_free = ctr;
} else if (_equal(_storage[ctr]->_key, key)) {
found = true;
break;
}
if (_storage[ctr] == NULL) { ctr = (5 * ctr + perturb + 1) & _mask;
#ifdef DEBUG_HASH_COLLISIONS
_collisions++;
#endif
}
#ifdef DEBUG_HASH_COLLISIONS
_lookups++;
fprintf(stderr, "collisions %d, dummies hit %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d\n",
_collisions, _dummyHits, _lookups, ((double) _collisions / (double)_lookups),
(const void *)this, _mask+1, _size);
#endif
if (!found && first_free != _mask + 1)
ctr = first_free;
if (!found) {
if (_storage[ctr])
_deleted--;
_storage[ctr] = allocNode(key); _storage[ctr] = allocNode(key);
assert(_storage[ctr] != NULL); assert(_storage[ctr] != NULL);
_size++; _size++;
// Keep the load factor below a certain threshold. // Keep the load factor below a certain threshold.
// Deleted nodes are also counted
uint capacity = _mask + 1; uint capacity = _mask + 1;
if (_size * HASHMAP_LOADFACTOR_DENOMINATOR > capacity * HASHMAP_LOADFACTOR_NUMERATOR) { if ((_size + _deleted) * HASHMAP_LOADFACTOR_DENOMINATOR >
capacity * HASHMAP_LOADFACTOR_NUMERATOR) {
capacity = capacity < 500 ? (capacity * 4) : (capacity * 2); capacity = capacity < 500 ? (capacity * 4) : (capacity * 2);
expandStorage(capacity); expandStorage(capacity);
ctr = lookup(key); ctr = lookup(key);
@ -496,44 +556,16 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::setVal(const Key &key, const Val &v
template<class Key, class Val, class HashFunc, class EqualFunc> template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::erase(const Key &key) { void HashMap<Key, Val, HashFunc, EqualFunc>::erase(const Key &key) {
// This is based on code in the Wikipedia article on Hash tables.
const uint hash = _hash(key); uint ctr = lookup(key);
uint i = hash & _mask; if (_storage[ctr] == NULL)
uint perturb; return;
for (perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) { // If we remove a key, we replace it with a dummy node.
if (_storage[i] == NULL || _equal(_storage[i]->_key, key)) freeNode(_storage[ctr]);
break; _storage[ctr] = &_dummyNode;
i = (5 * i + perturb + 1) & _mask;
}
if (_storage[i] == NULL)
return; // key wasn't present, so no work has to be done
// If we remove a key, we must check all subsequent keys and possibly
// reinsert them.
uint j = i;
freeNode(_storage[i]);
_storage[i] = NULL;
for (perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) {
// Look at the next table slot
j = (5 * j + perturb + 1) & _mask;
// If the next slot is empty, we are done
if (_storage[j] == NULL)
break;
// Compute the slot where the content of the next slot should normally be,
// assuming an empty table, and check whether we have to move it.
uint k = _hash(_storage[j]->_key) & _mask;
if ((j > i && (k <= i || k > j)) ||
(j < i && (k <= i && k > j)) ) {
_storage[i] = _storage[j];
i = j;
}
}
_storage[i] = NULL;
_size--; _size--;
_deleted++;
return; return;
} }

View file

@ -110,21 +110,21 @@ public:
* @param name the name of the savefile * @param name the name of the savefile
* @return pointer to an OutSaveFile, or NULL if an error occured. * @return pointer to an OutSaveFile, or NULL if an error occured.
*/ */
virtual OutSaveFile *openForSaving(const char *name) = 0; virtual OutSaveFile *openForSaving(const String &name) = 0;
/** /**
* Open the file with the specified name in the given directory for loading. * Open the file with the specified name in the given directory for loading.
* @param name the name of the savefile * @param name the name of the savefile
* @return pointer to an InSaveFile, or NULL if an error occured. * @return pointer to an InSaveFile, or NULL if an error occured.
*/ */
virtual InSaveFile *openForLoading(const char *name) = 0; virtual InSaveFile *openForLoading(const String &name) = 0;
/** /**
* Removes the given savefile from the system. * Removes the given savefile from the system.
* @param name the name of the savefile to be removed. * @param name the name of the savefile to be removed.
* @return true if no error occurred, false otherwise. * @return true if no error occurred, false otherwise.
*/ */
virtual bool removeSavefile(const char *name) = 0; virtual bool removeSavefile(const String &name) = 0;
/** /**
* Renames the given savefile. * Renames the given savefile.
@ -132,7 +132,7 @@ public:
* @param newName New name. * @param newName New name.
* @return true if no error occurred. false otherwise. * @return true if no error occurred. false otherwise.
*/ */
virtual bool renameSavefile(const char *oldName, const char *newName); virtual bool renameSavefile(const String &oldName, const String &newName);
/** /**
* Request a list of available savegames with a given DOS-style pattern, * Request a list of available savegames with a given DOS-style pattern,
@ -142,7 +142,7 @@ public:
* @return list of strings for all present file names. * @return list of strings for all present file names.
* @see Common::matchString() * @see Common::matchString()
*/ */
virtual Common::StringList listSavefiles(const char *pattern) = 0; virtual StringList listSavefiles(const String &pattern) = 0;
}; };
} // End of namespace Common } // End of namespace Common

View file

@ -265,6 +265,9 @@ String& String::operator =(char c) {
} }
String &String::operator +=(const char *str) { String &String::operator +=(const char *str) {
if (_str <= str && str <= _str + _size)
return operator+=(Common::String(str));
int len = strlen(str); int len = strlen(str);
if (len > 0) { if (len > 0) {
ensureCapacity(_size + len, true); ensureCapacity(_size + len, true);
@ -276,6 +279,9 @@ String &String::operator +=(const char *str) {
} }
String &String::operator +=(const String &str) { String &String::operator +=(const String &str) {
if (&str == this)
return operator+=(Common::String(str));
int len = str._size; int len = str._size;
if (len > 0) { if (len > 0) {
ensureCapacity(_size + len, true); ensureCapacity(_size + len, true);
@ -295,6 +301,10 @@ String &String::operator +=(char c) {
return *this; return *this;
} }
bool String::hasPrefix(const String &x) const {
return hasPrefix(x.c_str());
}
bool String::hasPrefix(const char *x) const { bool String::hasPrefix(const char *x) const {
assert(x != 0); assert(x != 0);
// Compare x with the start of _str. // Compare x with the start of _str.
@ -308,6 +318,10 @@ bool String::hasPrefix(const char *x) const {
return *x == 0; return *x == 0;
} }
bool String::hasSuffix(const String &x) const {
return hasSuffix(x.c_str());
}
bool String::hasSuffix(const char *x) const { bool String::hasSuffix(const char *x) const {
assert(x != 0); assert(x != 0);
// Compare x with the end of _str. // Compare x with the end of _str.
@ -324,6 +338,10 @@ bool String::hasSuffix(const char *x) const {
return *x == 0; return *x == 0;
} }
bool String::contains(const String &x) const {
return strstr(c_str(), x.c_str()) != NULL;
}
bool String::contains(const char *x) const { bool String::contains(const char *x) const {
assert(x != 0); assert(x != 0);
return strstr(c_str(), x) != NULL; return strstr(c_str(), x) != NULL;

View file

@ -144,9 +144,13 @@ public:
int compareTo(const char *x) const; // strcmp clone int compareTo(const char *x) const; // strcmp clone
int compareToIgnoreCase(const char *x) const; // stricmp clone int compareToIgnoreCase(const char *x) const; // stricmp clone
bool hasSuffix(const String &x) const;
bool hasSuffix(const char *x) const; bool hasSuffix(const char *x) const;
bool hasPrefix(const String &x) const;
bool hasPrefix(const char *x) const; bool hasPrefix(const char *x) const;
bool contains(const String &x) const;
bool contains(const char *x) const; bool contains(const char *x) const;
bool contains(char x) const; bool contains(char x) const;

View file

@ -44,6 +44,7 @@
#pragma warning( disable : 4068 ) // turn off "unknown pragma" warning #pragma warning( disable : 4068 ) // turn off "unknown pragma" warning
#pragma warning( disable : 4244 ) // turn off "conversion type" warning #pragma warning( disable : 4244 ) // turn off "conversion type" warning
#pragma warning( disable : 4250 ) // turn off "inherits via dominance" warning #pragma warning( disable : 4250 ) // turn off "inherits via dominance" warning
#pragma warning( disable : 4800 ) // turn off "forcing value to bool 'true' or 'false' (performance warning)"
// vsnprintf is already defined in Visual Studio 2008 // vsnprintf is already defined in Visual Studio 2008
#if (_MSC_VER < 1500) #if (_MSC_VER < 1500)

View file

@ -25,10 +25,18 @@
#include "common/system.h" #include "common/system.h"
OSystem *g_system = NULL; OSystem *g_system = 0;
OSystem::OSystem() { OSystem::OSystem() {
} }
OSystem::~OSystem() { OSystem::~OSystem() {
} }
bool OSystem::openCD(int drive) {
return false;
}
bool OSystem::pollCD() {
return false;
}

View file

@ -30,6 +30,8 @@
#include "common/noncopyable.h" #include "common/noncopyable.h"
#include "common/rect.h" #include "common/rect.h"
#include "graphics/pixelformat.h"
namespace Audio { namespace Audio {
class Mixer; class Mixer;
} }
@ -162,6 +164,9 @@ public:
/** @name Mouse */ /** @name Mouse */
//@{ //@{
/** Show or hide the mouse cursor. */
virtual bool showMouse(bool visible) = 0;
/** /**
* Move ("warp") the mouse cursor to the specified position in virtual * Move ("warp") the mouse cursor to the specified position in virtual
* screen coordinates. * screen coordinates.
@ -274,6 +279,51 @@ public:
/**
* @name Audio CD
* The methods in this group deal with Audio CD playback.
* The default implementation simply does nothing.
* This is the lower level implementation as provided by the
* backends. The engines should use the Audio::AudioCDManager
* class instead of using it directly.
*/
//@{
/**
* Initialise the specified CD drive for audio playback.
* @return true if the CD drive was inited succesfully
*/
virtual bool openCD(int drive);
/**
* Poll CD status.
* @return true if CD audio is playing
*/
virtual bool pollCD();
/**
* Start audio CD playback.
* @param track the track to play.
* @param num_loops how often playback should be repeated (-1 = infinitely often).
* @param start_frame the frame at which playback should start (75 frames = 1 second).
* @param duration the number of frames to play.
*/
virtual void playCD(int track, int num_loops, int start_frame, int duration) {}
/**
* Stop audio CD playback.
*/
virtual void stopCD() {}
/**
* Update cdrom audio status.
*/
virtual void updateCD() {}
//@}
/** @name Miscellaneous */ /** @name Miscellaneous */
//@{ //@{
/** Quit (exit) the application. */ /** Quit (exit) the application. */

View file

@ -188,6 +188,9 @@ uint RandomSource::getRandomNumberRng(uint min, uint max) {
} }
#pragma mark -
const LanguageDescription g_languages[] = { const LanguageDescription g_languages[] = {
{"zh", "Chinese (Taiwan)", ZH_TWN}, {"zh", "Chinese (Taiwan)", ZH_TWN},
{"cz", "Czech", CZ_CZE}, {"cz", "Czech", CZ_CZE},
@ -243,6 +246,9 @@ const char *getLanguageDescription(Language id) {
} }
#pragma mark -
const PlatformDescription g_platforms[] = { const PlatformDescription g_platforms[] = {
{"2gs", "2gs", "2gs", "Apple IIgs", kPlatformApple2GS }, {"2gs", "2gs", "2gs", "Apple IIgs", kPlatformApple2GS },
{"3do", "3do", "3do", "3DO", kPlatform3DO}, {"3do", "3do", "3do", "3DO", kPlatform3DO},
@ -253,6 +259,7 @@ const PlatformDescription g_platforms[] = {
{"pc", "dos", "ibm", "DOS", kPlatformPC}, {"pc", "dos", "ibm", "DOS", kPlatformPC},
{"pc98", "pc98", "pc98", "PC-98", kPlatformPC98}, {"pc98", "pc98", "pc98", "PC-98", kPlatformPC98},
{"wii", "wii", "wii", "Nintendo Wii", kPlatformWii}, {"wii", "wii", "wii", "Nintendo Wii", kPlatformWii},
{"coco3", "coco3", "coco3", "CoCo3", kPlatformCoCo3},
// The 'official' spelling seems to be "FM-TOWNS" (e.g. in the Indy4 demo). // The 'official' spelling seems to be "FM-TOWNS" (e.g. in the Indy4 demo).
// However, on the net many variations can be seen, like "FMTOWNS", // However, on the net many variations can be seen, like "FMTOWNS",
@ -265,7 +272,7 @@ const PlatformDescription g_platforms[] = {
{"nes", "nes", "nes", "NES", kPlatformNES}, {"nes", "nes", "nes", "NES", kPlatformNES},
{"segacd", "segacd", "sega", "SegaCD", kPlatformSegaCD}, {"segacd", "segacd", "sega", "SegaCD", kPlatformSegaCD},
{"windows", "win", "win", "Windows", kPlatformWindows}, {"windows", "win", "win", "Windows", kPlatformWindows},
{"playstation", "psx", "PSX", "Playstation", kPlatformPSX}, {"playstation", "psx", "psx", "Sony PlayStation", kPlatformPSX},
{0, 0, 0, "Default", kPlatformUnknown} {0, 0, 0, "Default", kPlatformUnknown}
@ -322,6 +329,96 @@ const char *getPlatformDescription(Platform id) {
} }
#pragma mark -
const RenderModeDescription g_renderModes[] = {
{"hercGreen", "Hercules Green", kRenderHercG},
{"hercAmber", "Hercules Amber", kRenderHercA},
{"cga", "CGA", kRenderCGA},
{"ega", "EGA", kRenderEGA},
{"amiga", "Amiga", kRenderAmiga},
{0, 0, kRenderDefault}
};
RenderMode parseRenderMode(const String &str) {
if (str.empty())
return kRenderDefault;
const RenderModeDescription *l = g_renderModes;
for (; l->code; ++l) {
if (str.equalsIgnoreCase(l->code))
return l->id;
}
return kRenderDefault;
}
const char *getRenderModeCode(RenderMode id) {
const RenderModeDescription *l = g_renderModes;
for (; l->code; ++l) {
if (l->id == id)
return l->code;
}
return 0;
}
const char *getRenderModeDescription(RenderMode id) {
const RenderModeDescription *l = g_renderModes;
for (; l->code; ++l) {
if (l->id == id)
return l->description;
}
return 0;
}
const struct GameOpt {
uint32 option;
const char *desc;
} g_gameOptions[] = {
{ GUIO_NOSUBTITLES, "sndNoSubs" },
{ GUIO_NOMUSIC, "sndNoMusic" },
{ GUIO_NOSPEECH, "sndNoSpeech" },
{ GUIO_NOSFX, "sndNoSFX" },
{ GUIO_NOMIDI, "sndNoMIDI" },
{ GUIO_NOLAUNCHLOAD, "launchNoLoad" },
{ GUIO_NONE, 0 }
};
bool checkGameGUIOption(GameGUIOption option, const String &str) {
for (int i = 0; g_gameOptions[i].desc; i++) {
if (g_gameOptions[i].option & option) {
if (str.contains(g_gameOptions[i].desc))
return true;
else
return false;
}
}
return false;
}
uint32 parseGameGUIOptions(const String &str) {
uint32 res = 0;
for (int i = 0; g_gameOptions[i].desc; i++)
if (str.contains(g_gameOptions[i].desc))
res |= g_gameOptions[i].option;
return res;
}
String getGameGUIOptionsDescription(uint32 options) {
String res = "";
for (int i = 0; g_gameOptions[i].desc; i++)
if (options & g_gameOptions[i].option)
res += String(g_gameOptions[i].desc) + " ";
res.trim();
return res;
}
} // End of namespace Common } // End of namespace Common

View file

@ -216,6 +216,7 @@ enum Platform {
kPlatformWindows, kPlatformWindows,
kPlatformNES, kPlatformNES,
kPlatformC64, kPlatformC64,
kPlatformCoCo3,
kPlatformLinux, kPlatformLinux,
kPlatformAcorn, kPlatformAcorn,
kPlatformSegaCD, kPlatformSegaCD,
@ -246,6 +247,52 @@ extern const char *getPlatformCode(Platform id);
extern const char *getPlatformAbbrev(Platform id); extern const char *getPlatformAbbrev(Platform id);
extern const char *getPlatformDescription(Platform id); extern const char *getPlatformDescription(Platform id);
/**
* List of render modes. It specifies which original graphics mode
* to use. Some targets used postprocessing dithering routines for
* reducing color depth of final image which let it to be rendered on
* such low-level adapters as CGA or Hercules.
*/
enum RenderMode {
kRenderDefault = 0,
kRenderEGA = 1,
kRenderCGA = 2,
kRenderHercG = 3,
kRenderHercA = 4,
kRenderAmiga = 5
};
enum HerculesDimensions {
kHercW = 720,
kHercH = 350
};
struct RenderModeDescription {
const char *code;
const char *description;
Common::RenderMode id;
};
extern const RenderModeDescription g_renderModes[];
/** Convert a string containing a render mode name into a RenderingMode enum value. */
extern RenderMode parseRenderMode(const String &str);
extern const char *getRenderModeCode(RenderMode id);
extern const char *getRenderModeDescription(RenderMode id);
enum GameGUIOption {
GUIO_NONE = 0,
GUIO_NOSUBTITLES = (1 << 0),
GUIO_NOMUSIC = (1 << 1),
GUIO_NOSPEECH = (1 << 2),
GUIO_NOSFX = (1 << 3),
GUIO_NOMIDI = (1 << 4),
GUIO_NOLAUNCHLOAD = (1 << 5)
};
bool checkGameGUIOption(GameGUIOption option, const String &str);
uint32 parseGameGUIOptions(const String &str);
String getGameGUIOptionsDescription(uint32 options);
} // End of namespace Common } // End of namespace Common

61
configure vendored
View file

@ -227,6 +227,9 @@ get_system_exe_extension() {
arm-riscos) arm-riscos)
_exeext=",ff8" _exeext=",ff8"
;; ;;
gp2xwiz-linux)
_exeext=".wiz"
;;
gp2x-linux) gp2x-linux)
_exeext=".gp2x" _exeext=".gp2x"
;; ;;
@ -671,6 +674,11 @@ ppc-amigaos)
_host_os=amigaos _host_os=amigaos
_host_cpu=ppc _host_cpu=ppc
;; ;;
gp2xwiz)
_host_os=gp2xwiz-linux
_host_cpu=arm
_host_alias=arm-open2x-linux
;;
gp2x) gp2x)
_host_os=gp2x-linux _host_os=gp2x-linux
_host_cpu=arm _host_cpu=arm
@ -1101,9 +1109,27 @@ if test -n "$_host"; then
_ranlib=$_host-ranlib _ranlib=$_host-ranlib
_strip=$_host-strip _strip=$_host-strip
;; ;;
gp2xwiz)
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
DEFINES="$DEFINES -DUNIX -DGP2XWIZ -DNDEBUG -DUSE_ARM_SMUSH_ASM"
CXXFLAGS="$CXXFLAGS -mcpu=arm926ej-s -mtune=arm926ej-s"
LDFLAGS="$LDFLAGS"
_endian=little
_need_memalign=yes
type_1_byte='char'
type_2_byte='short'
type_4_byte='int'
_ar="$_host_alias-ar cru"
_ranlib=$_host_alias-ranlib
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
_backend="gp2xwiz"
_build_hq_scalers="no"
_mt32emu="no"
;;
gp2x) gp2x)
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes" echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
DEFINES="$DEFINES -DUNIX -DGP2X -DNDEBUG -DUSE_ARM_SOUND_ASM" DEFINES="$DEFINES -DUNIX -DGP2X -DNDEBUG -DUSE_ARM_SMUSH_ASM"
CXXFLAGS="$CXXFLAGS -march=armv4t" CXXFLAGS="$CXXFLAGS -march=armv4t"
LDFLAGS="$LDFLAGS -static" LDFLAGS="$LDFLAGS -static"
_endian=little _endian=little
@ -1115,6 +1141,8 @@ if test -n "$_host"; then
_ranlib=$_host_alias-ranlib _ranlib=$_host_alias-ranlib
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1' add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
_backend="gp2x" _backend="gp2x"
_build_hq_scalers="no"
_mt32emu="no"
;; ;;
neuros) neuros)
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes" echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
@ -1195,7 +1223,9 @@ if test -n "$_host"; then
type_4_byte='int' type_4_byte='int'
_ar="$_host_alias-ar cru" _ar="$_host_alias-ar cru"
_ranlib=$_host_alias-ranlib _ranlib=$_host_alias-ranlib
_strip=$_host_alias-strip
_backend="wii" _backend="wii"
add_line_to_config_mk 'GAMECUBE = 0'
add_line_to_config_mk 'include $(srcdir)/backends/platform/wii/wii.mk' add_line_to_config_mk 'include $(srcdir)/backends/platform/wii/wii.mk'
add_line_to_config_h "#define DEBUG_WII_USBGECKO" add_line_to_config_h "#define DEBUG_WII_USBGECKO"
add_line_to_config_h "/* #define DEBUG_WII_MEMSTATS */" add_line_to_config_h "/* #define DEBUG_WII_MEMSTATS */"
@ -1212,8 +1242,11 @@ if test -n "$_host"; then
type_4_byte='int' type_4_byte='int'
_ar="$_host_alias-ar cru" _ar="$_host_alias-ar cru"
_ranlib=$_host_alias-ranlib _ranlib=$_host_alias-ranlib
_strip=$_host_alias-strip
_backend="wii" _backend="wii"
add_line_to_config_mk 'GAMECUBE = 1'
add_line_to_config_mk 'include $(srcdir)/backends/platform/wii/wii.mk' add_line_to_config_mk 'include $(srcdir)/backends/platform/wii/wii.mk'
add_line_to_config_h '#define GAMECUBE'
add_line_to_config_h "/* #define DEBUG_WII_USBGECKO */" add_line_to_config_h "/* #define DEBUG_WII_USBGECKO */"
add_line_to_config_h "/* #define DEBUG_WII_MEMSTATS */" add_line_to_config_h "/* #define DEBUG_WII_MEMSTATS */"
add_line_to_config_h "/* #define DEBUG_WII_GDB */" add_line_to_config_h "/* #define DEBUG_WII_GDB */"
@ -1382,6 +1415,24 @@ CXXFLAGS += -DDYNAMIC_MODULES
PLUGIN_LDFLAGS := -Wl,--enable-auto-import -shared ./libresidual.a PLUGIN_LDFLAGS := -Wl,--enable-auto-import -shared ./libresidual.a
PRE_OBJS_FLAGS := -Wl,--whole-archive PRE_OBJS_FLAGS := -Wl,--whole-archive
POST_OBJS_FLAGS := -Wl,--export-all-symbols -Wl,--no-whole-archive -Wl,--out-implib,./libresidual.a POST_OBJS_FLAGS := -Wl,--export-all-symbols -Wl,--no-whole-archive -Wl,--out-implib,./libresidual.a
'
;;
gp2xwiz*)
_def_plugin='
#define PLUGIN_PREFIX ""
#define PLUGIN_SUFFIX ".plugin"
'
_mak_plugins='
DYNAMIC_MODULES := 1
PLUGIN_PREFIX :=
PLUGIN_SUFFIX := .plugin
PLUGIN_EXTRA_DEPS = $(EXECUTABLE)
CXXFLAGS += -DDYNAMIC_MODULES
CXXFLAGS += -fpic
PLUGIN_LDFLAGS += -shared
PRE_OBJS_FLAGS := -Wl,-export-dynamic -Wl,-whole-archive
POST_OBJS_FLAGS := -Wl,-no-whole-archive
LIBS += -ldl
' '
;; ;;
dreamcast) dreamcast)
@ -1584,6 +1635,13 @@ case $_backend in
LDFLAGS="$LDFLAGS -static" LDFLAGS="$LDFLAGS -static"
CXXFLAGS="$CXXFLAGS -march=armv4t" CXXFLAGS="$CXXFLAGS -march=armv4t"
;; ;;
gp2xwiz)
find_sdlconfig
INCLUDES="$INCLUDES `$_sdlconfig --prefix="$_sdlpath" --cflags`"
LIBS="$LIBS `$_sdlconfig --prefix="$_sdlpath" --libs`"
LDFLAGS="$LDFLAGS"
CXXFLAGS="$CXXFLAGS -mcpu=arm926ej-s -mtune=arm926ej-s"
;;
iphone) iphone)
OBJCFLAGS="$OBJCFLAGS --std=c99" OBJCFLAGS="$OBJCFLAGS --std=c99"
LIBS="$LIBS -lobjc -framework UIKit -framework CoreGraphics -framework OpenGLES -framework QuartzCore -framework GraphicsServices -framework CoreFoundation -framework Foundation -framework AudioToolbox -framework CoreAudio" LIBS="$LIBS -lobjc -framework UIKit -framework CoreGraphics -framework OpenGLES -framework QuartzCore -framework GraphicsServices -framework CoreFoundation -framework Foundation -framework AudioToolbox -framework CoreAudio"
@ -1597,7 +1655,6 @@ case $_backend in
DEFINES="$DEFINES -D__WII__ -DGEKKO" DEFINES="$DEFINES -D__WII__ -DGEKKO"
case $_host_os in case $_host_os in
gamecube) gamecube)
DEFINES="$DEFINES -DGAMECUBE"
LIBS="$LIBS -lfat -logc -ldb" LIBS="$LIBS -lfat -logc -ldb"
;; ;;
*) *)

View file

@ -197,6 +197,8 @@ static void updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *
if (params.flags & kADFlagUseExtraAsHint) if (params.flags & kADFlagUseExtraAsHint)
desc["extra"] = realDesc->extra; desc["extra"] = realDesc->extra;
desc.setGUIOptions(realDesc->guioptions | params.guioptions);
} }
GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const { GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const {

View file

@ -63,6 +63,8 @@ struct ADGameDescription {
* code. * code.
*/ */
uint32 flags; uint32 flags;
uint32 guioptions;
}; };
/** /**
@ -70,7 +72,7 @@ struct ADGameDescription {
* terminate a list to be passed to the AdvancedDetector API. * terminate a list to be passed to the AdvancedDetector API.
*/ */
#define AD_TABLE_END_MARKER \ #define AD_TABLE_END_MARKER \
{ NULL, NULL, { { NULL, 0, NULL, 0 } }, Common::UNK_LANG, Common::kPlatformUnknown, ADGF_NO_FLAGS } { NULL, NULL, { { NULL, 0, NULL, 0 } }, Common::UNK_LANG, Common::kPlatformUnknown, ADGF_NO_FLAGS, Common::GUIO_NONE }
struct ADObsoleteGameID { struct ADObsoleteGameID {
@ -171,6 +173,13 @@ struct ADParams {
* that can be ORed together and passed here. * that can be ORed together and passed here.
*/ */
uint32 flags; uint32 flags;
/**
* A bitmask of game GUI options which will be added to each
* entry in addition to per-game options. Refer to GameGUIOption
* enum for the list.
*/
uint32 guioptions;
}; };

View file

@ -101,9 +101,25 @@ void Engine::syncSoundSettings() {
int soundVolumeSFX = ConfMan.getInt("sfx_volume"); int soundVolumeSFX = ConfMan.getInt("sfx_volume");
int soundVolumeSpeech = ConfMan.getInt("speech_volume"); int soundVolumeSpeech = ConfMan.getInt("speech_volume");
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, soundVolumeMusic); bool mute = false;
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, soundVolumeSFX); if (ConfMan.hasKey("mute"))
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, soundVolumeSpeech); mute = ConfMan.getBool("mute");
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, (mute ? 0 : soundVolumeMusic));
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, (mute ? 0 : soundVolumeSFX));
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, (mute ? 0 : soundVolumeSpeech));
}
void Engine::flipMute() {
bool mute = false;
if (ConfMan.hasKey("mute")) {
mute = !ConfMan.getBool("mute");
}
ConfMan.setBool("mute", mute);
syncSoundSettings();
} }
Common::Error Engine::loadGameState(int slot) { Common::Error Engine::loadGameState(int slot) {
@ -133,6 +149,11 @@ void Engine::quitGame() {
g_system->getEventManager()->pushEvent(event); g_system->getEventManager()->pushEvent(event);
} }
bool Engine::shouldQuit() {
Common::EventManager *eventMan = g_system->getEventManager();
return (eventMan->shouldQuit());
}
/* /*
EnginePlugin *Engine::getMetaEnginePlugin() const { EnginePlugin *Engine::getMetaEnginePlugin() const {

View file

@ -135,6 +135,11 @@ public:
*/ */
virtual void syncSoundSettings(); virtual void syncSoundSettings();
/**
* Flip mute all sound option.
*/
virtual void flipMute();
/** /**
* Load a game state. * Load a game state.
* @param slot the slot from which a savestate should be loaded * @param slot the slot from which a savestate should be loaded
@ -179,6 +184,12 @@ public:
*/ */
static void quitGame(); static void quitGame();
/**
* Return whether the ENGINE should quit respectively should return to the
* launcher.
*/
static bool shouldQuit();
/** /**
* Pause or resume the engine. This should stop/resume any audio playback * Pause or resume the engine. This should stop/resume any audio playback
* and other stuff. Called right before the system runs a global dialog * and other stuff. Called right before the system runs a global dialog
@ -196,9 +207,15 @@ public:
* Return whether the engine is currently paused or not. * Return whether the engine is currently paused or not.
*/ */
bool isPaused() const { return _pauseLevel != 0; } bool isPaused() const { return _pauseLevel != 0; }
inline Common::TimerManager *getTimerManager() { return _timer; }
inline Common::EventManager *getEventManager() { return _eventMan; }
inline Common::SaveFileManager *getSaveFileManager() { return _saveFileMan; }
public: public:
/** On some systems, check if the game appears to be run from CD. */
void checkCD();
protected: protected:
/** /**

View file

@ -47,13 +47,30 @@ GameDescriptor::GameDescriptor(const PlainGameDescriptor &pgd) {
setVal("description", pgd.description); setVal("description", pgd.description);
} }
GameDescriptor::GameDescriptor(const Common::String &g, const Common::String &d, Common::Language l, Common::Platform p) { GameDescriptor::GameDescriptor(const PlainGameDescriptorGUIOpts &pgd) {
setVal("gameid", pgd.gameid);
setVal("description", pgd.description);
if (pgd.guioptions != 0)
setVal("guioptions", Common::getGameGUIOptionsDescription(pgd.guioptions));
}
GameDescriptor::GameDescriptor(const Common::String &g, const Common::String &d, Common::Language l, Common::Platform p, uint32 guioptions) {
setVal("gameid", g); setVal("gameid", g);
setVal("description", d); setVal("description", d);
if (l != Common::UNK_LANG) if (l != Common::UNK_LANG)
setVal("language", Common::getLanguageCode(l)); setVal("language", Common::getLanguageCode(l));
if (p != Common::kPlatformUnknown) if (p != Common::kPlatformUnknown)
setVal("platform", Common::getPlatformCode(p)); setVal("platform", Common::getPlatformCode(p));
if (guioptions != 0)
setVal("guioptions", Common::getGameGUIOptionsDescription(guioptions));
}
void GameDescriptor::setGUIOptions(uint32 guioptions) {
if (guioptions != 0)
setVal("guioptions", Common::getGameGUIOptionsDescription(guioptions));
else
erase("guioptions");
} }
void GameDescriptor::updateDesc(const char *extra) { void GameDescriptor::updateDesc(const char *extra) {

View file

@ -43,6 +43,17 @@ struct PlainGameDescriptor {
const char *description; const char *description;
}; };
/**
* Same as PlainGameDsscriptor except it adds Game GUI options parameter
* This is a plain struct to make it possible to declare NULL-terminated C arrays
* consisting of PlainGameDescriptors.
*/
struct PlainGameDescriptorGUIOpts {
const char *gameid;
const char *description;
uint32 guioptions;
};
/** /**
* Given a list of PlainGameDescriptors, returns the first PlainGameDescriptor * Given a list of PlainGameDescriptors, returns the first PlainGameDescriptor
* matching the given gameid. If not match is found return 0. * matching the given gameid. If not match is found return 0.
@ -61,16 +72,20 @@ class GameDescriptor : public Common::StringMap {
public: public:
GameDescriptor(); GameDescriptor();
GameDescriptor(const PlainGameDescriptor &pgd); GameDescriptor(const PlainGameDescriptor &pgd);
GameDescriptor(const PlainGameDescriptorGUIOpts &pgd);
GameDescriptor(const Common::String &gameid, GameDescriptor(const Common::String &gameid,
const Common::String &description, const Common::String &description,
Common::Language language = Common::UNK_LANG, Common::Language language = Common::UNK_LANG,
Common::Platform platform = Common::kPlatformUnknown); Common::Platform platform = Common::kPlatformUnknown,
uint32 guioptions = 0);
/** /**
* Update the description string by appending (LANG/PLATFORM/EXTRA) to it. * Update the description string by appending (LANG/PLATFORM/EXTRA) to it.
*/ */
void updateDesc(const char *extra = 0); void updateDesc(const char *extra = 0);
void setGUIOptions(uint32 options);
Common::String &gameid() { return getVal("gameid"); } Common::String &gameid() { return getVal("gameid"); }
Common::String &description() { return getVal("description"); } Common::String &description() { return getVal("description"); }
const Common::String &gameid() const { return getVal("gameid"); } const Common::String &gameid() const { return getVal("gameid"); }

View file

@ -25,6 +25,7 @@
#include "common/endian.h" #include "common/endian.h"
#include "engines/grim/grim.h"
#include "engines/grim/bitmap.h" #include "engines/grim/bitmap.h"
#include "engines/grim/gfx_base.h" #include "engines/grim/gfx_base.h"

View file

@ -25,6 +25,7 @@
#include "common/endian.h" #include "common/endian.h"
#include "engines/grim/grim.h"
#include "engines/grim/font.h" #include "engines/grim/font.h"
namespace Grim { namespace Grim {

View file

@ -35,6 +35,11 @@ namespace Grim {
class Actor; class Actor;
class SaveGame; class SaveGame;
enum enDebugLevels {
DEBUG_NONE, DEBUG_NORMAL, DEBUG_WARN, DEBUG_ERROR, DEBUG_LUA, DEBUG_BITMAPS, DEBUG_MODEL, DEBUG_STUB,
DEBUG_SMUSH, DEBUG_IMUSE, DEBUG_CHORES, DEBUG_ALL
};
#define ENGINE_MODE_IDLE 0 #define ENGINE_MODE_IDLE 0
#define ENGINE_MODE_PAUSE 1 #define ENGINE_MODE_PAUSE 1
#define ENGINE_MODE_NORMAL 2 #define ENGINE_MODE_NORMAL 2

View file

@ -23,6 +23,7 @@
* *
*/ */
#include "engines/grim/grim.h"
#include "engines/grim/imuse/imuse.h" #include "engines/grim/imuse/imuse.h"
#include "engines/grim/imuse/imuse_tables.h" #include "engines/grim/imuse/imuse_tables.h"

View file

@ -24,6 +24,7 @@
*/ */
#include "engines/grim/imuse/imuse.h" #include "engines/grim/imuse/imuse.h"
#include "engines/grim/grim.h"
namespace Grim { namespace Grim {

View file

@ -23,6 +23,7 @@
* *
*/ */
#include "engines/grim/grim.h"
#include "engines/grim/imuse/imuse.h" #include "engines/grim/imuse/imuse.h"
namespace Grim { namespace Grim {

View file

@ -25,6 +25,7 @@
#include "common/endian.h" #include "common/endian.h"
#include "engines/grim/grim.h"
#include "engines/grim/keyframe.h" #include "engines/grim/keyframe.h"
#include "engines/grim/textsplit.h" #include "engines/grim/textsplit.h"

View file

@ -7,6 +7,7 @@
#include "common/endian.h" #include "common/endian.h"
#include "engines/grim/actor.h" #include "engines/grim/actor.h"
#include "engines/grim/grim.h"
#include "engines/grim/lua/lbuiltin.h" #include "engines/grim/lua/lbuiltin.h"
#include "engines/grim/lua/ldo.h" #include "engines/grim/lua/ldo.h"

View file

@ -25,6 +25,7 @@
#include "common/endian.h" #include "common/endian.h"
#include "engines/grim/grim.h"
#include "engines/grim/material.h" #include "engines/grim/material.h"
#include "engines/grim/gfx_base.h" #include "engines/grim/gfx_base.h"

View file

@ -25,6 +25,7 @@
#include "common/endian.h" #include "common/endian.h"
#include "engines/grim/grim.h"
#include "engines/grim/model.h" #include "engines/grim/model.h"
#include "engines/grim/actor.h" #include "engines/grim/actor.h"
#include "engines/grim/material.h" #include "engines/grim/material.h"

View file

@ -23,6 +23,7 @@
* *
*/ */
#include "engines/grim/grim.h"
#include "engines/grim/textobject.h" #include "engines/grim/textobject.h"
namespace Grim { namespace Grim {

View file

@ -25,6 +25,7 @@
#include "common/util.h" #include "common/util.h"
#include "engines/grim/grim.h"
#include "engines/grim/walkplane.h" #include "engines/grim/walkplane.h"
#include "engines/grim/textsplit.h" #include "engines/grim/textsplit.h"

View file

@ -4,19 +4,19 @@
* are too numerous to list here. Please refer to the AUTHORS * are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution. * file distributed with this source distribution.
* *
* This library is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU General Public License
* License as published by the Free Software Foundation; either * as published by the Free Software Foundation; either version 2
* version 2.1 of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Lesser General Public License for more details. * GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU General Public License
* License along with this library; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
* $URL$ * $URL$
* $Id$ * $Id$

View file

@ -4,19 +4,19 @@
* are too numerous to list here. Please refer to the AUTHORS * are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution. * file distributed with this source distribution.
* *
* This library is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU General Public License
* License as published by the Free Software Foundation; either * as published by the Free Software Foundation; either version 2
* version 2.1 of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Lesser General Public License for more details. * GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU General Public License
* License along with this library; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
* $URL$ * $URL$
* $Id$ * $Id$

View file

@ -193,4 +193,26 @@ aos4dist: $(EXECUTABLE)
cp $(srcdir)/README $(AOS4PATH)/README.txt cp $(srcdir)/README $(AOS4PATH)/README.txt
cp $(srcdir)/TODO $(AOS4PATH)/TODO.txt cp $(srcdir)/TODO $(AOS4PATH)/TODO.txt
#
# Wii/Gamecube specific
#
# Special target to create an Wii snapshot
wiidist: $(EXECUTABLE)
$(MKDIR) wiidist/residual
ifeq ($(GAMECUBE),1)
$(DEVKITPPC)/bin/elf2dol $(EXECUTABLE) wiidist/residual/residual.dol
else
$(STRIP) $(EXECUTABLE) -o wiidist/residual/boot.elf
$(CP) $(srcdir)/dists/wii/icon.png wiidist/residual/
sed "s/@REVISION@/$(VER_SVNREV)/;s/@TIMESTAMP@/`date +%Y%m%d%H%M%S`/" < $(srcdir)/dists/wii/meta.xml > wiidist/residual/meta.xml
endif
$(CP) $(srcdir)/dists/wii/READMII wiidist/residual/
$(CP) $(srcdir)/AUTHORS wiidist/residual/AUTHORS.txt
$(CP) $(srcdir)/COPYING.GPL wiidist/residual/COPYING.GPL.txt
$(CP) $(srcdir)/COPYING.LGPL wiidist/residual/COPYING.LGPL.txt
$(CP) $(srcdir)/NEWS wiidist/residual/NEWS.txt
$(CP) $(srcdir)/README wiidist/residual/README.txt
sed -i 's/$$/\r/' wiidist/residual/*.txt
.PHONY: deb bundle osxsnap win32dist install uninstall .PHONY: deb bundle osxsnap win32dist install uninstall

View file

@ -31,14 +31,11 @@
* improvments over the original code were made. * improvments over the original code were made.
*/ */
#include "common/sys.h"
#include "common/util.h"
#include "common/debug.h"
#include "common/frac.h"
#include "sound/audiostream.h" #include "sound/audiostream.h"
#include "sound/rate.h" #include "sound/rate.h"
#include "sound/mixer.h" #include "sound/mixer.h"
#include "common/frac.h"
#include "common/util.h"
namespace Audio { namespace Audio {

View file

@ -27,6 +27,7 @@
#define SOUND_RATE_H #define SOUND_RATE_H
#include "common/sys.h" #include "common/sys.h"
#include "engines/engine.h"
class AudioStream; class AudioStream;