synced with scummvm rev svn 49000

This commit is contained in:
Pawel Kolodziejski 2011-04-10 21:59:04 +02:00
parent 786721e347
commit e3a475ff7b
157 changed files with 5758 additions and 3811 deletions

View file

@ -36,12 +36,10 @@ ifeq "$(HAVE_GCC)" "1"
# Disable RTTI, and enable checking of pointers returned by "new"
CXXFLAGS+= -fno-exceptions -fcheck-new
endif
# There is a nice extra warning that flags variables that are potentially
# used before being initialized. Very handy to catch a certain kind of
# bugs. Unfortunately, it only works when optimizations are turned on,
# which is why we normally don't use it.
#CXXFLAGS+= -O -Wuninitialized
ifeq "$(HAVE_CLANG)" "1"
CXXFLAGS+= -Wno-conversion -Wno-shorten-64-to-32 -Wno-sign-compare -Wno-four-char-constants
endif
#######################################################################

View file

@ -22,11 +22,11 @@ MODULES := base $(MODULES)
# After the game specific modules follow the shared modules
MODULES += \
engines \
gui \
graphics \
sound \
backends \
engines \
graphics \
common \
ifdef USE_MT32EMU
@ -103,13 +103,24 @@ ifdef CXX_UPDATE_DEP_FLAG
$(QUIET)$(MKDIR) $(*D)/$(DEPDIR)
$(QUIET_CXX)$(CXX) $(CXX_UPDATE_DEP_FLAG) $(OBJCFLAGS) -c $(<) -o $*.o
# Build rule for assembler files with preprocessing
%.o: %.S
$(QUIET)$(MKDIR) $(*D)/$(DEPDIR)
$(QUIET_AS)$(CXX) $(CXX_UPDATE_DEP_FLAG) $(ASFLAGS) -c $(<) -o $*.o
else
# Dumb compile rule, for C++ compilers that don't allow dependency tracking or
# where it is broken (such as GCC 2.95).
.cpp.o:
$(QUIET)$(MKDIR) $(*D)
$(QUIET_CXX)$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
# Build rule for assembler files with preprocessing
%.o: %.S
$(QUIET)$(MKDIR) $(*D)
$(QUIET_AS)$(CXX) $(ASFLAGS) -c $(<) -o $*.o
endif
# Build rule for assembler files
@ -117,16 +128,11 @@ endif
$(QUIET)$(MKDIR) $(*D)
$(QUIET_AS)$(AS) $(ASFLAGS) $(<) -o $*.o
# Build rule for assembler files with preprocessing
%.o: %.S
$(QUIET)$(MKDIR) $(*D)/$(DEPDIR)
$(QUIET_AS)$(CXX) $(CXX_UPDATE_DEP_FLAG) $(ASFLAGS) -c $(<) -o $*.o
ifdef HAVE_NASM
ifdef USE_NASM
# Build rule for NASM assembler files
%.o: %.asm
$(QUIET)$(MKDIR) $(*D)
$(QUIET_NASM)$(NASM) -O1 $(NASMFLAGS) -g -o $*.o $(<)
$(QUIET_NASM)$(NASM) $(NASMFLAGS) -o $*.o $(<)
endif
# Include the dependency tracking files.
@ -154,9 +160,9 @@ VER_EXTRA = $(shell echo $(VERSION) | cut -d. -f 3 | cut -c2-)
# Get Subversion's working copy information
######################################################################
ifeq ($(shell LANG=C svn stat $(srcdir) 2>&1 | grep "is not a working copy"),)
ifneq ($(shell svn info $(srcdir) 1>/dev/null 2>&1 || echo "error"),error)
SVNROOT := $(srcdir)
ifeq ($(origin SVNREV), undefined)
ifeq ($(origin VER_SVNREV), undefined)
# Get the working copy base revision
VER_SVNREV := $(shell LANG=C svn info $(SVNROOT) | grep "^Revision" | cut -d ' ' -f 2)
endif

View file

@ -103,7 +103,7 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
_keyRepeatTime = time + kKeyRepeatInitialDelay;
#endif
// Global Main Menu
if (event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == Common::KEYCODE_F5) {
if (event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_F5) {
if (g_engine && !g_engine->isPaused()) {
Common::Event menuEvent;
menuEvent.type = Common::EVENT_MAINMENU;
@ -135,7 +135,7 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
}
}
#ifdef ENABLE_VKEYBD
else if (event.kbd.keycode == Common::KEYCODE_F7 && event.kbd.flags == 0) {
else if (event.kbd.keycode == Common::KEYCODE_F7 && event.kbd.hasFlags(0)) {
if (_vk->isDisplaying()) {
_vk->close(true);
} else {
@ -149,7 +149,7 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
}
#endif
#ifdef ENABLE_KEYMAPPER
else if (event.kbd.keycode == Common::KEYCODE_F8 && event.kbd.flags == 0) {
else if (event.kbd.keycode == Common::KEYCODE_F8 && event.kbd.hasFlags(0)) {
if (!_remap) {
_remap = true;
Common::RemapDialog _remapDialog;

View file

@ -38,7 +38,7 @@ Action::Action(Keymap *boss, const char *i, String des, ActionType typ,
assert(i);
assert(_boss);
strncpy(id, i, ACTION_ID_SIZE);
Common::strlcpy(id, i, ACTION_ID_SIZE);
_boss->addAction(this);
}

View file

@ -60,7 +60,7 @@ struct HardwareKey {
KeyType typ = kGenericKeyType, ActionType prefAct = kGenericActionType)
: key(ky), description(desc), type(typ), preferredAction(prefAct) {
assert(i);
strncpy(hwKeyId, i, HWKEY_ID_SIZE);
Common::strlcpy(hwKeyId, i, HWKEY_ID_SIZE);
}
};

View file

@ -211,7 +211,7 @@ void RemapDialog::startRemapping(uint i) {
if (_topAction + i >= _currentActions.size())
return;
_remapTimeout = getMillis() + kRemapTimeoutDelay;
_remapTimeout = g_system->getMillis() + kRemapTimeoutDelay;
_activeRemapAction = _currentActions[_topAction + i].action;
_keymapWidgets[i].keyButton->setLabel("...");
_keymapWidgets[i].keyButton->draw();
@ -261,7 +261,7 @@ void RemapDialog::handleMouseDown(int x, int y, int button, int clickCount) {
}
void RemapDialog::handleTickle() {
if (_activeRemapAction && getMillis() > _remapTimeout)
if (_activeRemapAction && g_system->getMillis() > _remapTimeout)
stopRemapping();
Dialog::handleTickle();
}

View file

@ -142,7 +142,7 @@ int MidiDriver_CORE::open() {
}
if (err != noErr)
warning("Failed loading custom sound font '%s' (error %ld)\n", soundfont, err);
warning("Failed loading custom sound font '%s' (error %ld)\n", soundfont, (long)err);
}
#ifdef COREAUDIO_DISABLE_REVERB

View file

@ -109,8 +109,8 @@ void MidiDriver_CoreMIDI::close() {
}
void MidiDriver_CoreMIDI::send(uint32 b) {
assert(mOutPort != NULL);
assert(mDest != NULL);
assert(mOutPort != 0);
assert(mDest != 0);
// Extract the MIDI data
byte status_byte = (b & 0x000000FF);
@ -153,8 +153,8 @@ void MidiDriver_CoreMIDI::send(uint32 b) {
}
void MidiDriver_CoreMIDI::sysEx(const byte *msg, uint16 length) {
assert(mOutPort != NULL);
assert(mDest != NULL);
assert(mOutPort != 0);
assert(mDest != 0);
byte buf[384];
MIDIPacketList *packetList = (MIDIPacketList *)buf;

View file

@ -38,6 +38,7 @@
#include "common/util.h"
#include "common/endian.h"
#include "common/str.h"
#include "sound/musicplugin.h"
#include "sound/mpu401.h"
@ -154,11 +155,9 @@ int MidiDriver_TIMIDITY::open() {
/* get server hostname; if not specified in env, use default */
if ((res = getenv("TIMIDITY_HOST")) == NULL)
strncpy(timidity_host, DEFAULT_TIMIDITY_HOST, MAXHOSTNAMELEN);
Common::strlcpy(timidity_host, DEFAULT_TIMIDITY_HOST, sizeof(timidity_host));
else
strncpy(timidity_host, res, sizeof(timidity_host));
timidity_host[sizeof(timidity_host) - 1] = '\0';
Common::strlcpy(timidity_host, res, sizeof(timidity_host));
/* extract control port */
if ((res = strrchr(timidity_host, ':')) != NULL) {

View file

@ -153,23 +153,29 @@ void OSystem_SDL::handleKbdMouse() {
}
}
static byte SDLModToOSystemKeyFlags(SDLMod mod) {
byte b = 0;
static void SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) {
event.kbd.flags = 0;
#ifdef LINUPY
// Yopy has no ALT key, steal the SHIFT key
// (which isn't used much anyway)
if (mod & KMOD_SHIFT)
b |= Common::KBD_ALT;
event.kbd.flags |= Common::KBD_ALT;
#else
if (mod & KMOD_SHIFT)
b |= Common::KBD_SHIFT;
event.kbd.flags |= Common::KBD_SHIFT;
if (mod & KMOD_ALT)
b |= Common::KBD_ALT;
event.kbd.flags |= Common::KBD_ALT;
#endif
if (mod & KMOD_CTRL)
b |= Common::KBD_CTRL;
event.kbd.flags |= Common::KBD_CTRL;
return b;
// Sticky flags
if (mod & KMOD_NUM)
event.kbd.flags |= Common::KBD_NUM;
if (mod & KMOD_CAPS)
event.kbd.flags |= Common::KBD_CAPS;
}
bool OSystem_SDL::pollEvent(Common::Event &event) {
@ -227,13 +233,19 @@ bool OSystem_SDL::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) {
bool OSystem_SDL::handleKeyDown(SDL_Event &ev, Common::Event &event) {
byte b = 0;
b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState());
/* Residual doesn't support this
SDLModToOSystemKeyFlags(SDL_GetModState(), event);
// Handle scroll lock as a key modifier
if (ev.key.keysym.sym == SDLK_SCROLLOCK)
_scrollLock = !_scrollLock;
if (_scrollLock)
event.kbd.flags |= Common::KBD_SCRL;
// Alt-Return and Alt-Enter toggle full screen mode
if (b == Common::KBD_ALT && (ev.key.keysym.sym == SDLK_RETURN
|| ev.key.keysym.sym == SDLK_KP_ENTER)) {
/* Residual doesn't support this
if (event.kbd.hasFlags(Common::KBD_ALT) && (ev.key.keysym.sym == SDLK_RETURN || ev.key.keysym.sym == SDLK_KP_ENTER)) {
beginGFXTransaction();
setFullscreenMode(!_videoMode.fullscreen);
endGFXTransaction();
@ -243,12 +255,11 @@ bool OSystem_SDL::handleKeyDown(SDL_Event &ev, Common::Event &event) {
else
displayMessageOnOSD("Windowed mode");
#endif
return false;
}
}*/
// Alt-S: Create a screenshot
if (b == Common::KBD_ALT && ev.key.keysym.sym == 's') {
/* // Alt-S: Create a screenshot
if (event.kbd.hasFlags(Common::KBD_ALT) && ev.key.keysym.sym == 's') {
char filename[20];
for (int n = 0;; n++) {
@ -268,7 +279,7 @@ bool OSystem_SDL::handleKeyDown(SDL_Event &ev, Common::Event &event) {
}
*/
// Ctrl-m toggles mouse capture
if (b == Common::KBD_CTRL && ev.key.keysym.sym == 'm') {
if (event.kbd.hasFlags(Common::KBD_CTRL) && ev.key.keysym.sym == 'm') {
toggleMouseGrab();
return false;
}
@ -287,7 +298,7 @@ bool OSystem_SDL::handleKeyDown(SDL_Event &ev, Common::Event &event) {
}
#else
// Ctrl-z and Alt-X quit
if ((b == Common::KBD_CTRL && ev.key.keysym.sym == 'z') || (b == Common::KBD_ALT && ev.key.keysym.sym == 'x')) {
if ((event.kbd.hasFlags(Common::KBD_CTRL) && ev.key.keysym.sym == 'z') || (event.kbd.hasFlags(Common::KBD_ALT) && ev.key.keysym.sym == 'x')) {
event.type = Common::EVENT_QUIT;
return true;
}
@ -299,7 +310,7 @@ bool OSystem_SDL::handleKeyDown(SDL_Event &ev, Common::Event &event) {
}
/* Residual doesn't support this
// Ctrl-Alt-<key> will change the GFX mode
if ((b & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) {
if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) {
if (handleScalerHotkeys(ev.key))
return false;
}*/
@ -323,11 +334,11 @@ bool OSystem_SDL::handleKeyUp(SDL_Event &ev, Common::Event &event) {
event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode);
// Ctrl-Alt-<key> will change the GFX mode
byte b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState());
if ((b & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) {
// Swallow these key up events
return false;
}
SDLModToOSystemKeyFlags(SDL_GetModState(), event);
// Set the scroll lock sticky flag
if (_scrollLock)
event.kbd.flags |= Common::KBD_SCRL;
return true;
}

View file

@ -177,7 +177,6 @@ OSystem_SDL::OSystem_SDL()
#ifdef USE_OPENGL
_overlayTexIds(0),
#endif
_samplesPerSec(0),
_cdrom(0),
_joystick(0),
@ -629,46 +628,44 @@ void OSystem_SDL::setupMixer() {
SDL_AudioSpec desired;
// Determine the desired output sampling frequency.
_samplesPerSec = 0;
uint32 samplesPerSec = 0;
if (ConfMan.hasKey("output_rate"))
_samplesPerSec = ConfMan.getInt("output_rate");
if (_samplesPerSec <= 0)
_samplesPerSec = SAMPLES_PER_SEC;
samplesPerSec = ConfMan.getInt("output_rate");
if (samplesPerSec <= 0)
samplesPerSec = SAMPLES_PER_SEC;
// Determine the sample buffer size. We want it to store enough data for
// at least 1/16th of a second (though at maximum 8192 samples). Note
// at least 1/16th of a second (though at most 8192 samples). Note
// that it must be a power of two. So e.g. at 22050 Hz, we request a
// sample buffer size of 2048.
int samples = 8192;
while (samples * 16 > _samplesPerSec * 2)
uint32 samples = 8192;
while (samples * 16 > samplesPerSec * 2)
samples >>= 1;
memset(&desired, 0, sizeof(desired));
desired.freq = _samplesPerSec;
desired.freq = samplesPerSec;
desired.format = AUDIO_S16SYS;
desired.channels = 2;
desired.samples = (uint16)samples;
desired.callback = mixCallback;
desired.userdata = this;
// Create the mixer instance
assert(!_mixer);
_mixer = new Audio::MixerImpl(this);
assert(_mixer);
if (SDL_OpenAudio(&desired, &_obtainedRate) != 0) {
warning("Could not open audio device: %s", SDL_GetError());
_samplesPerSec = 0;
_mixer = new Audio::MixerImpl(this, samplesPerSec);
assert(_mixer);
_mixer->setReady(false);
} else {
// Note: This should be the obtained output rate, but it seems that at
// least on some platforms SDL will lie and claim it did get the rate
// even if it didn't. Probably only happens for "weird" rates, though.
_samplesPerSec = _obtainedRate.freq;
debug(1, "Output sample rate: %d Hz", _samplesPerSec);
samplesPerSec = _obtainedRate.freq;
debug(1, "Output sample rate: %d Hz", samplesPerSec);
// Tell the mixer that we are ready and start the sound processing
_mixer->setOutputRate(_samplesPerSec);
// Create the mixer instance and start the sound processing
_mixer = new Audio::MixerImpl(this, samplesPerSec);
assert(_mixer);
_mixer->setReady(true);
#if MIXER_DOUBLE_BUFFERING

View file

@ -163,7 +163,7 @@ public:
virtual bool hasFeature(Feature f);
virtual void setFeatureState(Feature f, bool enable);
virtual bool getFeatureState(Feature f);
virtual void preprocessEvents(SDL_Event *event) {};
virtual void preprocessEvents(SDL_Event *event) {}
virtual Common::SaveFileManager *getSavefileManager();
virtual FilesystemFactory *getFilesystemFactory();
@ -196,9 +196,6 @@ protected:
void closeOverlay();
// Audio
int _samplesPerSec;
// CD Audio
SDL_CD *_cdrom;
int _cdTrack, _cdNumLoops, _cdStartFrame, _cdDuration;
@ -213,6 +210,9 @@ protected:
};
// mouse
KbdMouse _km;
// Scroll lock state - since SDL doesn't track it
bool _scrollLock;
// joystick
SDL_Joystick *_joystick;
#ifdef MIXER_DOUBLE_BUFFERING

View file

@ -97,5 +97,4 @@ bool DCPluginProvider::isPluginFilename(const Common::FSNode &node) const {
return true;
}
#endif // defined(DYNAMIC_MODULES) && defined(__DC__)

View file

@ -35,10 +35,6 @@ protected:
Plugin* createPlugin(const Common::FSNode &node) const;
bool isPluginFilename(const Common::FSNode &node) const;
virtual void addCustomDirectories(Common::StringList &dirs) const {
dirs.push_back("/");
}
};
#endif // defined(DYNAMIC_MODULES) && defined(__DC__)

View file

@ -35,8 +35,6 @@ protected:
Plugin* createPlugin(const Common::FSNode &node) const;
bool isPluginFilename(const Common::FSNode &node) const;
virtual void addCustomDirectories(Common::StringList &dirs) const {}
};
#endif // defined(DYNAMIC_MODULES) && defined(_WIN32)

View file

@ -54,18 +54,18 @@ void DefaultSaveFileManager::checkPath(const Common::FSNode &dir) {
}
}
Common::StringList DefaultSaveFileManager::listSavefiles(const Common::String &pattern) {
Common::StringArray DefaultSaveFileManager::listSavefiles(const Common::String &pattern) {
Common::String savePathName = getSavePath();
checkPath(Common::FSNode(savePathName));
if (getError() != Common::kNoError)
return Common::StringList();
return Common::StringArray();
// recreate FSNode since checkPath may have changed/created the directory
Common::FSNode savePath(savePathName);
Common::FSDirectory dir(savePath);
Common::ArchiveMemberList savefiles;
Common::StringList results;
Common::StringArray results;
Common::String search(pattern);
if (dir.listMatchingMembers(savefiles, search) > 0) {

View file

@ -39,7 +39,7 @@ public:
DefaultSaveFileManager();
DefaultSaveFileManager(const Common::String &defaultSavepath);
virtual Common::StringList listSavefiles(const Common::String &pattern);
virtual Common::StringArray listSavefiles(const Common::String &pattern);
virtual Common::InSaveFile *openForLoading(const Common::String &filename);
virtual Common::OutSaveFile *openForSaving(const Common::String &filename);
virtual bool removeSavefile(const Common::String &filename);

View file

@ -33,6 +33,7 @@
#include "common/util.h"
#include "common/system.h"
#include "common/archive.h"
#include "common/tokenizer.h"
#include "graphics/imagedec.h"

View file

@ -93,8 +93,8 @@ bool VirtualKeyboard::openPack(const String &packName, const FSNode &node) {
#ifdef USE_ZLIB
if (node.getChild(packName + ".zip").exists()) {
// compressed keyboard pack
_fileArchive = new ZipArchive(node.getChild(packName + ".zip"));
if (_fileArchive->hasFile(packName + ".xml")) {
_fileArchive = makeZipArchive(node.getChild(packName + ".zip"));
if (_fileArchive && _fileArchive->hasFile(packName + ".xml")) {
if (!_parser->loadStream(_fileArchive->createReadStreamForMember(packName + ".xml"))) {
delete _fileArchive;
_fileArchive = 0;

View file

@ -61,12 +61,9 @@ static const char HELP_STRING[] =
" -h, --help Display a brief help text and exit\n"
" -z, --list-games Display list of supported games and exit\n"
" -t, --list-targets Display list of configured targets and exit\n"
"\n"
" -c, --config=CONFIG Use alternate configuration file\n"
" -p, --path=PATH Path to where the game is installed\n"
" -f, --fullscreen Force full-screen mode\n"
" -F, --no-fullscreen Force windowed mode\n"
" --gui-theme=THEME Select GUI theme\n"
" --themepath=PATH Path to where GUI themes are stored\n"
" --list-themes Display list of all usable GUI themes\n"
@ -125,7 +122,6 @@ void registerDefaults() {
// Graphics
ConfMan.registerDefault("fullscreen", false);
ConfMan.registerDefault("soft_renderer", "true");
ConfMan.registerDefault("fullscreen", "false");
ConfMan.registerDefault("show_fps", "false");
// Sound & Music
@ -137,6 +133,7 @@ void registerDefaults() {
ConfMan.registerDefault("native_mt32", false);
ConfMan.registerDefault("enable_gs", false);
ConfMan.registerDefault("midi_gain", 100);
ConfMan.registerDefault("cdrom", 0);
// Game specific
ConfMan.registerDefault("path", "");
@ -144,14 +141,8 @@ void registerDefaults() {
ConfMan.registerDefault("language", "en");
ConfMan.registerDefault("autosave_period", 5 * 60); // By default, trigger autosave every 5 minutes
ConfMan.registerDefault("dimuse_tempo", 10);
// Miscellaneous
ConfMan.registerDefault("confirm_exit", false);
ConfMan.registerDefault("disable_sdl_parachute", false);
@ -300,9 +291,6 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
DO_LONG_OPTION_INT("output-rate")
END_OPTION
DO_OPTION_BOOL('f', "fullscreen")
END_OPTION
DO_LONG_OPTION("opl-driver")
END_OPTION
@ -340,10 +328,10 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
settings.erase("joystick");
END_OPTION
DO_LONG_OPTION("show-fps")
END_OPTION
DO_LONG_OPTION("soft-renderer")
DO_LONG_OPTION("platform")
int platform = Common::parsePlatform(option);
if (platform == Common::kPlatformUnknown)
usage("Unrecognized platform '%s'", option);
END_OPTION
DO_LONG_OPTION("soundfont")
@ -376,6 +364,12 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
DO_LONG_OPTION("gamma")
END_OPTION
DO_LONG_OPTION("soft-renderer")
END_OPTION
DO_LONG_OPTION("show-fps")
END_OPTION
DO_LONG_OPTION("savepath")
Common::FSNode path(option);
if (!path.exists()) {
@ -474,7 +468,7 @@ static void listTargets() {
ConfigManager::DomainMap::const_iterator iter;
for (iter = domains.begin(); iter != domains.end(); ++iter) {
Common::String name(iter->_key);
Common::String description(iter->_value.get("description"));
Common::String description(iter->_value.getVal("description"));
if (description.empty()) {
// FIXME: At this point, we should check for a "gameid" override
@ -517,8 +511,8 @@ static void runDetectorTest() {
int success = 0, failure = 0;
for (iter = domains.begin(); iter != domains.end(); ++iter) {
Common::String name(iter->_key);
Common::String gameid(iter->_value.get("gameid"));
Common::String path(iter->_value.get("path"));
Common::String gameid(iter->_value.getVal("gameid"));
Common::String path(iter->_value.getVal("path"));
printf("Looking at target '%s', gameid '%s', path '%s' ...\n",
name.c_str(), gameid.c_str(), path.c_str());
if (path.empty()) {
@ -591,8 +585,8 @@ void upgradeTargets() {
for (iter = domains.begin(); iter != domains.end(); ++iter) {
Common::ConfigManager::Domain &dom = iter->_value;
Common::String name(iter->_key);
Common::String gameid(dom.get("gameid"));
Common::String path(dom.get("path"));
Common::String gameid(dom.getVal("gameid"));
Common::String path(dom.getVal("path"));
printf("Looking at target '%s', gameid '%s' ...\n",
name.c_str(), gameid.c_str());
if (path.empty()) {
@ -611,9 +605,9 @@ void upgradeTargets() {
continue;
}
Common::Language lang = Common::parseLanguage(dom.get("language"));
Common::Platform plat = Common::parsePlatform(dom.get("platform"));
Common::String desc(dom.get("description"));
Common::Language lang = Common::parseLanguage(dom.getVal("language"));
Common::Platform plat = Common::parsePlatform(dom.getVal("platform"));
Common::String desc(dom.getVal("description"));
GameList candidates(EngineMan.detectGames(files));
GameDescriptor *g = 0;

View file

@ -40,14 +40,17 @@
#include "common/archive.h"
#include "common/config-manager.h"
#include "common/debug.h"
#include "common/debug-channels.h"
#include "common/events.h"
#include "common/EventRecorder.h"
#include "common/file.h"
#include "common/fs.h"
#include "common/system.h"
#include "common/tokenizer.h"
#include "gui/GuiManager.h"
#include "gui/message.h"
#include "gui/error.h"
#include "sound/audiocd.h"
@ -133,21 +136,12 @@ static Common::Error runGame(const EnginePlugin *plugin, OSystem &system, const
// Check for errors
if (!engine || err != Common::kNoError) {
// TODO: Show an error dialog or so?
// TODO: Also take 'err' into consideration...
//GUI::MessageDialog alert("ScummVM could not find any game in the specified directory!");
//alert.runModal();
const char *errMsg = 0;
switch (err) {
case Common::kInvalidPathError:
errMsg = "Invalid game path";
break;
case Common::kNoGameDataFoundError:
errMsg = "Unable to locate game data";
break;
default:
errMsg = "Unknown error";
}
// TODO: An errorDialog for this and engine related errors is displayed already in the scummvm_main function
// Is a separate dialog here still required?
//GUI::displayErrorDialog("ScummVM could not find any game in the specified directory!");
const char *errMsg = Common::errorToString(err);
warning("%s failed to instantiate engine: %s (target '%s', path '%s')",
plugin->getName(),
@ -205,7 +199,7 @@ static Common::Error runGame(const EnginePlugin *plugin, OSystem &system, const
Common::StringTokenizer tokenizer(edebuglevels, " ,");
while (!tokenizer.empty()) {
Common::String token = tokenizer.nextToken();
if (!enableDebugChannel(token))
if (!DebugMan.enableDebugChannel(token))
warning("Engine does not support debug level '%s'", token.c_str());
}
@ -219,7 +213,7 @@ static Common::Error runGame(const EnginePlugin *plugin, OSystem &system, const
system.engineDone();
// We clear all debug levels again even though the engine should do it
Common::clearAllDebugChannels();
DebugMan.clearAllDebugChannels();
// Free up memory
delete engine;
@ -376,7 +370,8 @@ extern "C" int residual_main(int argc, const char * const argv[]) {
// Did an error occur ?
if (result != Common::kNoError) {
// TODO: Show an informative error dialog if starting the selected game failed.
// Shows an informative error dialog if starting the selected game failed.
GUI::displayErrorDialog(result, "Error running game:");
}
// Quit unless an error occurred, or Return to launcher was requested
@ -403,6 +398,7 @@ extern "C" int residual_main(int argc, const char * const argv[]) {
// A dialog would be nicer, but we don't have any
// screen to draw on yet.
warning("Could not find any engine capable of running the selected game");
GUI::displayErrorDialog("Could not find any engine capable of running the selected game");
}
// We will destroy the AudioCDManager singleton here to save some memory.

View file

@ -166,7 +166,7 @@ void FilePluginProvider::addCustomDirectories(Common::FSList &dirs) const {
#pragma mark -
DECLARE_SINGLETON(PluginManager);
DECLARE_SINGLETON(PluginManager)
PluginManager::PluginManager() {
// Always add the static plugin provider.
@ -258,7 +258,7 @@ bool PluginManager::tryLoadPlugin(Plugin *plugin) {
#include "engines/metaengine.h"
DECLARE_SINGLETON(EngineManager);
DECLARE_SINGLETON(EngineManager)
GameDescriptor EngineManager::findGame(const Common::String &gameName, const EnginePlugin **plugin) const {
// Find the GameDescriptor for this target
@ -304,7 +304,7 @@ const EnginePlugin::List &EngineManager::getPlugins() const {
#include "sound/musicplugin.h"
DECLARE_SINGLETON(MusicManager);
DECLARE_SINGLETON(MusicManager)
const MusicPlugin::List &MusicManager::getPlugins() const {
return (const MusicPlugin::List &)PluginManager::instance().getPlugins(PLUGIN_TYPE_MUSIC);

View file

@ -26,6 +26,7 @@
#ifndef BASE_PLUGINS_H
#define BASE_PLUGINS_H
#include "common/array.h"
#include "common/error.h"
#include "common/singleton.h"
#include "common/util.h"

View file

@ -26,8 +26,9 @@
#include "common/EventRecorder.h"
#include "common/config-manager.h"
#include "common/random.h"
DECLARE_SINGLETON(Common::EventRecorder);
DECLARE_SINGLETON(Common::EventRecorder)
namespace Common {

View file

@ -37,6 +37,8 @@
namespace Common {
class RandomSource;
/**
* Our generic event recorder.
*

View file

@ -27,6 +27,7 @@
#include "common/sys.h"
#include "common/func.h"
#include "common/util.h"
namespace Common {

View file

@ -270,8 +270,6 @@ SeekableReadStream *SearchSet::createReadStreamForMember(const String &name) con
}
DECLARE_SINGLETON(SearchManager);
SearchManager::SearchManager() {
clear(); // Force a reset
}
@ -291,3 +289,6 @@ void SearchManager::clear() {
}
} // namespace Common
DECLARE_SINGLETON(Common::SearchManager)

View file

@ -29,7 +29,7 @@
#include "common/util.h"
#include "common/system.h"
DECLARE_SINGLETON(Common::ConfigManager);
DECLARE_SINGLETON(Common::ConfigManager)
static bool isValidDomainName(const Common::String &domName) {
const char *p = domName.c_str();
@ -61,14 +61,19 @@ void ConfigManager::loadDefaultConfigFile() {
_filename.clear(); // clear the filename to indicate that we are using the default config file
// ... load it, if available ...
if (stream)
if (stream) {
loadFromStream(*stream);
// ... and close it again.
delete stream;
} else {
// No config file -> create new one!
printf("Default configuration file missing, creating a new one\n");
flushToDisk();
}
}
void ConfigManager::loadConfigFile(const String &filename) {
_filename = filename;
@ -221,7 +226,7 @@ void ConfigManager::flushToDisk() {
// First write the domains in _domainSaveOrder, in that order.
// Note: It's possible for _domainSaveOrder to list domains which
// are not present anymore.
StringList::const_iterator i;
Array<String>::const_iterator i;
for (i = _domainSaveOrder.begin(); i != _domainSaveOrder.end(); ++i) {
if (kApplicationDomain == *i) {
writeDomain(*stream, *i, _appDomain);
@ -409,10 +414,8 @@ const String & ConfigManager::get(const String &key) const {
return (*_activeDomain)[key];
else if (_appDomain.contains(key))
return _appDomain[key];
else if (_defaultsDomain.contains(key))
return _defaultsDomain[key];
return _emptyString;
return _defaultsDomain.getVal(key);
}
const String & ConfigManager::get(const String &key, const String &domName) const {
@ -431,18 +434,7 @@ const String & ConfigManager::get(const String &key, const String &domName) cons
if (domain->contains(key))
return (*domain)[key];
return _defaultsDomain.get(key);
if (!domain->contains(key)) {
#if 1
return _emptyString;
#else
error("ConfigManager::get(%s,%s) called on non-existent key",
key.c_str(), domName.c_str());
#endif
}
return (*domain)[key];
return _defaultsDomain.getVal(key);
}
int ConfigManager::getInt(const String &key, const String &domName) const {
@ -476,7 +468,6 @@ bool ConfigManager::getBool(const String &key, const String &domName) const {
error("ConfigManager::getBool(%s,%s): '%s' is not a valid bool",
key.c_str(), domName.c_str(), value.c_str());
return false;
}
@ -634,14 +625,6 @@ bool ConfigManager::hasGameDomain(const String &domName) const {
#pragma mark -
const String &ConfigManager::Domain::get(const String &key) const {
const_iterator iter(find(key));
if (iter != end())
return iter->_value;
return ConfMan._emptyString;
}
void ConfigManager::Domain::setDomainComment(const String &comment) {
_domainComment = comment;
}

View file

@ -56,8 +56,6 @@ public:
String _domainComment;
public:
const String &get(const String &key) const;
void setDomainComment(const String &comment);
const String &getDomainComment() const;
@ -159,14 +157,12 @@ private:
Domain _keymapperDomain;
#endif
StringList _domainSaveOrder;
Array<String> _domainSaveOrder;
String _activeDomainName;
Domain * _activeDomain;
String _filename;
const String _emptyString;
};
} // End of namespace Common

132
common/debug-channels.h Normal file
View file

@ -0,0 +1,132 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#ifndef COMMON_DEBUG_CHANNELS_H
#define COMMON_DEBUG_CHANNELS_H
#include "common/sys.h"
#include "common/hashmap.h"
#include "common/hash-str.h"
#include "common/list.h"
#include "common/singleton.h"
#include "common/str.h"
namespace Common {
// TODO: Find a better name for this
class DebugManager : public Singleton<DebugManager> {
public:
struct DebugChannel {
DebugChannel() : channel(0), enabled(false) {}
DebugChannel(uint32 c, const String &n, const String &d)
: name(n), description(d), channel(c), enabled(false) {}
String name;
String description;
uint32 channel;
bool enabled;
};
/**
* Adds a debug channel.
*
* A debug channel is considered roughly similar to what our debug levels described by
* gDebugLevel try to achieve:
*
* Debug channels should only affect the display of additional debug output, based on
* their state. That is if they are enabled, channel specific debug messages should
* be shown. If they are disabled on the other hand, those messages will be hidden.
*
* @see gDebugLevel.
*
* Note that we have debug* functions which depend both on the debug level set and
* specific debug channels. Those functions will only show output, when *both* criteria
* are satisfied.
*
* @param channel the channel flag (should be OR-able i.e. first one should be 1 then 2, 4, etc.)
* @param name the option name which is used in the debugger/on the command line to enable
* this special debug level (case will be ignored)
* @param description the description which shows up in the debugger
* @return true on success false on failure
*/
bool addDebugChannel(uint32 channel, const String &name, const String &description);
/**
* Resets all engine specific debug channels.
*/
void clearAllDebugChannels();
/**
* Enables an debug channel.
*
* @param name the name of the debug channel to enable
* @return true on success, false on failure
*/
bool enableDebugChannel(const String &name);
/**
* Disables an debug channel.
*
* @param name the name of the debug channel to disable
* @return true on success, false on failure
*/
bool disableDebugChannel(const String &name);
typedef List<DebugChannel> DebugChannelList;
/**
* Lists all engine specific debug channels.
*
* @return returns an array with all debug channels
*/
DebugChannelList listDebugChannels();
/**
* Test whether the given debug channel is enabled.
*/
bool isDebugChannelEnabled(uint32 channel);
private:
typedef HashMap<String, DebugChannel, IgnoreCase_Hash, IgnoreCase_EqualTo> DebugChannelMap;
DebugChannelMap gDebugChannels;
uint32 gDebugChannelsEnabled;
friend class Singleton<SingletonBaseType>;
DebugManager() : gDebugChannelsEnabled(0) {}
};
/** Shortcut for accessing the debug manager. */
#define DebugMan Common::DebugManager::instance()
} // End of namespace Common
#endif

View file

@ -23,9 +23,8 @@
*/
#include "common/debug.h"
#include "common/debug-channels.h"
#include "common/util.h"
#include "common/hashmap.h"
#include "common/hash-str.h"
#include <stdarg.h> // For va_list etc.
@ -48,24 +47,21 @@
// TODO: Move gDebugLevel into namespace Common.
int gDebugLevel = -1;
DECLARE_SINGLETON(Common::DebugManager)
namespace Common {
namespace {
typedef HashMap<String, DebugChannel, IgnoreCase_Hash, IgnoreCase_EqualTo> DebugChannelMap;
static DebugChannelMap gDebugChannels;
static uint32 gDebugChannelsEnabled = 0;
struct DebugLevelComperator {
bool operator()(const DebugChannel &l, const DebugChannel &r) {
bool operator()(const DebugManager::DebugChannel &l, const DebugManager::DebugChannel &r) {
return (l.name.compareToIgnoreCase(r.name) < 0);
}
};
} // end of anonymous namespace
bool addDebugChannel(uint32 channel, const String &name, const String &description) {
bool DebugManager::addDebugChannel(uint32 channel, const String &name, const String &description) {
if (gDebugChannels.contains(name))
warning("Duplicate declaration of engine debug channel '%s'", name.c_str());
@ -74,12 +70,12 @@ bool addDebugChannel(uint32 channel, const String &name, const String &descripti
return true;
}
void clearAllDebugChannels() {
void DebugManager::clearAllDebugChannels() {
gDebugChannelsEnabled = 0;
gDebugChannels.clear();
}
bool enableDebugChannel(const String &name) {
bool DebugManager::enableDebugChannel(const String &name) {
DebugChannelMap::iterator i = gDebugChannels.find(name);
if (i != gDebugChannels.end()) {
@ -92,7 +88,7 @@ bool enableDebugChannel(const String &name) {
}
}
bool disableDebugChannel(const String &name) {
bool DebugManager::disableDebugChannel(const String &name) {
DebugChannelMap::iterator i = gDebugChannels.find(name);
if (i != gDebugChannels.end()) {
@ -106,7 +102,7 @@ bool disableDebugChannel(const String &name) {
}
DebugChannelList listDebugChannels() {
DebugManager::DebugChannelList DebugManager::listDebugChannels() {
DebugChannelList tmp;
for (DebugChannelMap::iterator i = gDebugChannels.begin(); i != gDebugChannels.end(); ++i)
tmp.push_back(i->_value);
@ -115,7 +111,7 @@ DebugChannelList listDebugChannels() {
return tmp;
}
bool isDebugChannelEnabled(uint32 channel) {
bool DebugManager::isDebugChannelEnabled(uint32 channel) {
// Debug level 11 turns on all special debug level messages
if (gDebugLevel == 11)
return true;
@ -123,19 +119,6 @@ bool isDebugChannelEnabled(uint32 channel) {
return (gDebugChannelsEnabled & channel) != 0;
}
bool isDebugChannelEnabled(const String &name) {
// Debug level 11 turns on all special debug level messages
if (gDebugLevel == 11)
return true;
// Search for the debug level with the given name and check if it is enabled
DebugChannelMap::iterator i = gDebugChannels.find(name);
if (i != gDebugChannels.end())
return i->_value.enabled;
else
return false;
}
static OutputFormatter s_debugOutputFormatter = 0;
@ -156,7 +139,7 @@ static void debugHelper(const char *s, va_list va, bool caret = true) {
// Next, give the active engine (if any) a chance to augment the message,
// but only if not used from debugN.
if (Common::s_debugOutputFormatter) {
if (caret && Common::s_debugOutputFormatter) {
(*Common::s_debugOutputFormatter)(buf, in_buf, STRINGBUFLEN);
} else {
strncpy(buf, in_buf, STRINGBUFLEN);
@ -219,7 +202,7 @@ void debugC(int level, uint32 debugChannels, const char *s, ...) {
// Debug level 11 turns on all special debug level messages
if (gDebugLevel != 11)
if (level > gDebugLevel || !(Common::gDebugChannelsEnabled & debugChannels))
if (level > gDebugLevel || !(DebugMan.isDebugChannelEnabled(debugChannels)))
return;
va_start(va, s);
@ -232,7 +215,7 @@ void debugCN(int level, uint32 debugChannels, const char *s, ...) {
// Debug level 11 turns on all special debug level messages
if (gDebugLevel != 11)
if (level > gDebugLevel || !(Common::gDebugChannelsEnabled & debugChannels))
if (level > gDebugLevel || !(DebugMan.isDebugChannelEnabled(debugChannels)))
return;
va_start(va, s);
@ -245,7 +228,7 @@ void debugC(uint32 debugChannels, const char *s, ...) {
// Debug level 11 turns on all special debug level messages
if (gDebugLevel != 11)
if (!(Common::gDebugChannelsEnabled & debugChannels))
if (!(DebugMan.isDebugChannelEnabled(debugChannels)))
return;
va_start(va, s);
@ -258,7 +241,7 @@ void debugCN(uint32 debugChannels, const char *s, ...) {
// Debug level 11 turns on all special debug level messages
if (gDebugLevel != 11)
if (!(Common::gDebugChannelsEnabled & debugChannels))
if (!(DebugMan.isDebugChannelEnabled(debugChannels)))
return;
va_start(va, s);

View file

@ -27,93 +27,9 @@
#include "common/sys.h"
#include "common/textconsole.h"
#include "common/list.h"
#include "common/str.h"
namespace Common {
struct DebugChannel {
DebugChannel() : channel(0), enabled(false) {}
DebugChannel(uint32 c, const String &n, const String &d)
: name(n), description(d), channel(c), enabled(false) {}
String name;
String description;
uint32 channel;
bool enabled;
};
/**
* Adds a debug channel.
*
* A debug channel is considered roughly similar to what our debug levels described by
* gDebugLevel try to achieve:
*
* Debug channels should only affect the display of additional debug output, based on
* their state. That is if they are enabled, channel specific debug messages should
* be shown. If they are disabled on the other hand, those messages will be hidden.
*
* @see gDebugLevel.
*
* Note that we have debug* functions which depend both on the debug level set and
* specific debug channels. Those functions will only show output, when *both* criteria
* are satisfied.
*
* @param channel the channel flag (should be OR-able i.e. first one should be 1 then 2, 4, etc.)
* @param name the option name which is used in the debugger/on the command line to enable
* this special debug level (case will be ignored)
* @param description the description which shows up in the debugger
* @return true on success false on failure
*/
bool addDebugChannel(uint32 channel, const String &name, const String &description);
/**
* Resets all engine specific debug channels.
*/
void clearAllDebugChannels();
/**
* Enables an debug channel.
*
* @param name the name of the debug channel to enable
* @return true on success, false on failure
*/
bool enableDebugChannel(const String &name);
/**
* Disables an debug channel.
*
* @param name the name of the debug channel to disable
* @return true on success, false on failure
*/
bool disableDebugChannel(const String &name);
typedef List<DebugChannel> DebugChannelList;
/**
* Lists all engine specific debug channels.
*
* @return returns a arry with all debug channels
*/
DebugChannelList listDebugChannels();
/**
* Test whether the given debug channel is enabled.
*/
bool isDebugChannelEnabled(uint32 channel);
/**
* Test whether the given debug channel is enabled.
*/
bool isDebugChannelEnabled(const String &name);
/**
* Set the output formatter used by debug() and related functions.
*/
@ -145,7 +61,7 @@ void debug(const char *s, ...) GCC_PRINTF(1, 2);
/**
* Print a debug message to the text console (stdout), but only if
* the specified level does not exceed the value of gDebugLevel.
* the gDebugLevel equals at least the specified level.
* As a rule of thumb, the more important the message, the lower the level.
* Automatically appends a newline.
*/
@ -153,7 +69,7 @@ void debug(int level, const char *s, ...) GCC_PRINTF(2, 3);
/**
* Print a debug message to the text console (stdout), but only if
* the specified level does not exceed the value of gDebugLevel.
* the gDebugLevel equals at least the specified level.
* As a rule of thumb, the more important the message, the lower the level.
* Does not append a newline.
*/
@ -161,7 +77,7 @@ void debugN(int level, const char *s, ...) GCC_PRINTF(2, 3);
/**
* Print a debug message to the text console (stdout), but only if
* the specified level does not exceed the value of gDebugLevel AND
* the gDebugLevel equals at least the specified level AND
* if the specified special debug level is active.
* As a rule of thumb, the more important the message, the lower the level.
* Automatically appends a newline.
@ -172,7 +88,7 @@ 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
* the gDebugLevel equals at least the specified level 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.

72
common/error.cpp Normal file
View file

@ -0,0 +1,72 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/error.h"
#include "common/util.h"
namespace Common {
/**
* Error Table: Maps error codes to their default descriptions
*/
struct ErrorMessage {
Error error;
const char *errMsg;
};
static const ErrorMessage _errMsgTable[] = {
{ kInvalidPathError, "Invalid Path" },
{ kNoGameDataFoundError, "Game Data not found" },
{ kUnsupportedGameidError, "Game Id not supported" },
{ kUnsupportedColorMode, "Unsupported Color Mode" },
{ kReadPermissionDenied, "Read permission denied" },
{ kWritePermissionDenied, "Write permission denied" },
// The following three overlap a bit with kInvalidPathError and each other. Which to keep?
{ kPathDoesNotExist, "Path not exists" },
{ kPathNotDirectory, "Path not a directory" },
{ kPathNotFile, "Path not a file" },
{ kCreatingFileFailed, "Cannot create file" },
{ kReadingFailed, "Reading failed" },
{ kWritingFailed, "Writing data failed" },
{ kUnknownError, "Unknown Error" }
};
const char *errorToString(Error error) {
for (int i = 0; i < ARRAYSIZE(_errMsgTable); i++) {
if (error == _errMsgTable[i].error) {
return _errMsgTable[i].errMsg;
}
}
return "Unknown Error";
}
} // End of namespace Common

View file

@ -66,6 +66,14 @@ enum Error {
kUnknownError ///< Catch-all error, used if no other error code matches
};
/**
* Maps an error code to equivalent string description.
*
* @param error error code to be converted
* @return a pointer to string description of the error
*/
const char *errorToString(Error error);
} // End of namespace Common
#endif //COMMON_ERROR_H

View file

@ -52,9 +52,8 @@ public:
virtual ~File();
/**
* Checks if a given file exists in any of the current default paths
* (those were/are added by addDefaultDirectory and/or
* addDefaultDirectoryRecursive).
* Checks if a given file exists in any of the current default paths,
* as defined by SearchMan.
*
* @param filename the file to check for
* @return true if the file exists, false otherwise

View file

@ -49,17 +49,17 @@ FSNode::FSNode(const Common::String &p) {
}
bool FSNode::operator<(const FSNode& node) const {
// Directories come before files, i.e., are "lower".
if (isDirectory() != node.isDirectory())
return isDirectory();
// If both nodes are of the same type (two files or two dirs),
// then sort by name, ignoring case.
return getDisplayName().compareToIgnoreCase(node.getDisplayName()) < 0;
}
bool FSNode::exists() const {
if (_realNode == 0)
return false;
return _realNode->exists();
return _realNode && _realNode->exists();
}
FSNode FSNode::getChild(const Common::String &n) const {
@ -116,24 +116,15 @@ Common::String FSNode::getPath() const {
}
bool FSNode::isDirectory() const {
if (_realNode == 0)
return false;
return _realNode->isDirectory();
return _realNode && _realNode->isDirectory();
}
bool FSNode::isReadable() const {
if (_realNode == 0)
return false;
return _realNode->isReadable();
return _realNode && _realNode->isReadable();
}
bool FSNode::isWritable() const {
if (_realNode == 0)
return false;
return _realNode->isWritable();
return _realNode && _realNode->isWritable();
}
Common::SeekableReadStream *FSNode::createReadStream() const {
@ -141,10 +132,10 @@ Common::SeekableReadStream *FSNode::createReadStream() const {
return 0;
if (!_realNode->exists()) {
warning("FSNode::createReadStream: FSNode does not exist");
warning("FSNode::createReadStream: '%s' does not exist", getName().c_str());
return false;
} else if (_realNode->isDirectory()) {
warning("FSNode::createReadStream: FSNode is a directory");
warning("FSNode::createReadStream: '%s' is a directory", getName().c_str());
return false;
}
@ -156,7 +147,7 @@ Common::WriteStream *FSNode::createWriteStream() const {
return 0;
if (_realNode->isDirectory()) {
warning("FSNode::createWriteStream: FSNode is a directory");
warning("FSNode::createWriteStream: '%s' is a directory", getName().c_str());
return 0;
}
@ -224,10 +215,10 @@ ArchiveMemberPtr FSDirectory::getMember(const String &name) {
FSNode *node = lookupCache(_fileCache, name);
if (!node || !node->exists()) {
warning("FSDirectory::getMember: FSNode does not exist");
warning("FSDirectory::getMember: '%s' does not exist", name.c_str());
return ArchiveMemberPtr();
} else if (node->isDirectory()) {
warning("FSDirectory::getMember: FSNode is a directory");
warning("FSDirectory::getMember: '%s' is a directory", name.c_str());
return ArchiveMemberPtr();
}

View file

@ -101,7 +101,7 @@ public:
*
* @return bool true if the node exists, false otherwise.
*/
virtual bool exists() const;
bool exists() const;
/**
* Create a new node referring to a child node of the current node, which
@ -128,7 +128,7 @@ public:
*
* @return true if successful, false otherwise (e.g. when the directory does not exist).
*/
virtual bool getChildren(FSList &fslist, ListMode mode = kListDirectoriesOnly, bool hidden = false) const;
bool getChildren(FSList &fslist, ListMode mode = kListDirectoriesOnly, bool hidden = false) const;
/**
* Return a human readable string for this node, usable for display (e.g.
@ -161,7 +161,7 @@ public:
*
* @return the 'path' represented by this filesystem node
*/
virtual String getPath() const;
String getPath() const;
/**
* Get the parent node of this node. If this node has no parent node,
@ -178,7 +178,7 @@ public:
* Or even replace isDirectory by a getType() method that can return values like
* kDirNodeType, kFileNodeType, kInvalidNodeType.
*/
virtual bool isDirectory() const;
bool isDirectory() const;
/**
* Indicates whether the object referred by this node can be read from or not.
@ -191,7 +191,7 @@ public:
*
* @return true if the object can be read, false otherwise.
*/
virtual bool isReadable() const;
bool isReadable() const;
/**
* Indicates whether the object referred by this node can be written to or not.
@ -204,7 +204,7 @@ public:
*
* @return true if the object can be written to, false otherwise.
*/
virtual bool isWritable() const;
bool isWritable() const;
/**
* Creates a SeekableReadStream instance corresponding to the file
@ -222,7 +222,7 @@ public:
*
* @return pointer to the stream object, 0 in case of a failure
*/
virtual WriteStream *createWriteStream() const;
WriteStream *createWriteStream() const;
};
/**

View file

@ -49,15 +49,15 @@ enum KeyCode {
KEYCODE_PAUSE = 19,
KEYCODE_ESCAPE = 27,
KEYCODE_SPACE = 32,
KEYCODE_EXCLAIM = 33,
KEYCODE_QUOTEDBL = 34,
KEYCODE_HASH = 35,
KEYCODE_DOLLAR = 36,
KEYCODE_AMPERSAND = 38,
KEYCODE_QUOTE = 39,
KEYCODE_EXCLAIM = 33, // !
KEYCODE_QUOTEDBL = 34, // "
KEYCODE_HASH = 35, // #
KEYCODE_DOLLAR = 36, // $
KEYCODE_AMPERSAND = 38, // &
KEYCODE_QUOTE = 39, // '
KEYCODE_LEFTPAREN = 40,
KEYCODE_RIGHTPAREN = 41,
KEYCODE_ASTERISK = 42,
KEYCODE_ASTERISK = 42, // *
KEYCODE_PLUS = 43,
KEYCODE_COMMA = 44,
KEYCODE_MINUS = 45,
@ -114,6 +114,7 @@ enum KeyCode {
KEYCODE_y = 121,
KEYCODE_z = 122,
KEYCODE_DELETE = 127,
KEYCODE_TILDE = 176, // ~
// Numeric keypad
KEYCODE_KP0 = 256,
@ -222,9 +223,15 @@ enum {
* Keyboard modifier flags, used for Event::kbd::flags.
*/
enum {
// Non-sticky modifier flags
KBD_CTRL = 1 << 0,
KBD_ALT = 1 << 1,
KBD_SHIFT = 1 << 2
KBD_SHIFT = 1 << 2,
// Sticky modifier flags
KBD_NUM = 1 << 3,
KBD_CAPS = 1 << 4,
KBD_SCRL = 1 << 5
};
/**
@ -234,12 +241,6 @@ struct KeyState {
/**
* 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.
*/
KeyCode keycode;
@ -253,8 +254,14 @@ struct KeyState {
/**
* Status of the modifier keys. Bits are set in this for each
* pressed modifier
* @see KBD_CTRL, KBD_ALT, KBD_SHIFT
* pressed modifier.
* We distinguish 'non-sticky' and 'sticky' modifiers flags. The former
* are only set while certain keys (ctrl, alt, shift) are pressed by the
* user; the latter (num lock, caps lock, scroll lock) are activated when
* certain keys are pressed and released; and deactivated when that key
* is pressed and released a second time.
*
* @see KBD_CTRL, KBD_ALT, KBD_SHIFT, KBD_NUM, KBD_CAPS, KBD_SCRL
*/
byte flags;
@ -275,6 +282,18 @@ struct KeyState {
ascii = flags = 0;
}
/**
* Check whether the non-sticky flags are *exactly* as specified by f.
* This ignors the sticky flags (KBD_NUM, KBD_CAPS, KBD_SCRL).
* If you just want to check whether a modifier flag is set, just bit-and
* the flag. E.g. to check whether the control key modifier is set,
* you can write
* if (keystate.flags & KBD_CTRL) { ... }
*/
bool hasFlags(byte f) {
return f == (flags & ~(KBD_NUM|KBD_CAPS|KBD_SCRL));
}
bool operator ==(const KeyState &x) const {
return keycode == x.keycode && ascii == x.ascii && flags == x.flags;
}

573
common/macresman.cpp Normal file
View file

@ -0,0 +1,573 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/sys.h"
#include "common/debug.h"
#include "common/util.h"
#include "common/file.h"
#include "common/fs.h"
#include "common/macresman.h"
#include "common/md5.h"
#ifdef MACOSX
#include "common/config-manager.h"
#include "backends/fs/stdiostream.h"
#endif
namespace Common {
#define MBI_INFOHDR 128
#define MBI_ZERO1 0
#define MBI_NAMELEN 1
#define MBI_ZERO2 74
#define MBI_ZERO3 82
#define MBI_DFLEN 83
#define MBI_RFLEN 87
#define MAXNAMELEN 63
MacResManager::MacResManager() {
memset(this, 0, sizeof(MacResManager));
close();
}
MacResManager::~MacResManager() {
close();
}
void MacResManager::close() {
_resForkOffset = -1;
_mode = kResForkNone;
for (int i = 0; i < _resMap.numTypes; i++) {
for (int j = 0; j < _resTypes[i].items; j++) {
if (_resLists[i][j].nameOffset != -1) {
delete _resLists[i][j].name;
}
}
delete _resLists[i];
}
delete _resLists; _resLists = 0;
delete _resTypes; _resTypes = 0;
delete _stream; _stream = 0;
}
bool MacResManager::hasDataFork() {
return !_baseFileName.empty();
}
bool MacResManager::hasResFork() {
return !_baseFileName.empty() && _mode != kResForkNone;
}
uint32 MacResManager::getResForkSize() {
if (!hasResFork())
return 0;
return _resForkSize;
}
bool MacResManager::getResForkMD5(char *md5str, uint32 length) {
if (!hasResFork())
return false;
ReadStream *stream = new SeekableSubReadStream(_stream, _resForkOffset, _resForkOffset + _resForkSize);
bool retVal = md5_file_string(*stream, md5str, MIN<uint32>(length, _resForkSize));
delete stream;
return retVal;
}
bool MacResManager::open(Common::String filename) {
close();
#ifdef MACOSX
// Check the actual fork on a Mac computer
Common::String fullPath = ConfMan.get("path") + "/" + filename + "/..namedfork/rsrc";
Common::SeekableReadStream *macResForkRawStream = StdioStream::makeFromPath(fullPath, false);
if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) {
_baseFileName = filename;
return true;
}
#endif
Common::File *file = new Common::File();
// First, let's try to see if the Mac converted name exists
if (file->open("._" + filename) && loadFromAppleDouble(*file)) {
_baseFileName = filename;
return true;
}
// Check .bin too
if (file->open(filename + ".bin") && loadFromMacBinary(*file)) {
_baseFileName = filename;
return true;
}
// Maybe we have a dumped fork?
if (file->open(filename + ".rsrc") && loadFromRawFork(*file)) {
_baseFileName = filename;
return true;
}
// Fine, what about just the data fork?
if (file->open(filename)) {
_baseFileName = filename;
_stream = file;
return true;
}
delete file;
// The file doesn't exist
return false;
}
bool MacResManager::open(Common::FSNode path, Common::String filename) {
close();
#ifdef MACOSX
// Check the actual fork on a Mac computer
Common::String fullPath = path.getPath() + "/" + filename + "/..namedfork/rsrc";
Common::SeekableReadStream *macResForkRawStream = StdioStream::makeFromPath(fullPath, false);
if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) {
_baseFileName = filename;
return true;
}
#endif
// First, let's try to see if the Mac converted name exists
Common::FSNode fsNode = path.getChild("._" + filename);
if (fsNode.exists() && !fsNode.isDirectory() && loadFromAppleDouble(*fsNode.createReadStream())) {
_baseFileName = filename;
return true;
}
// Check .bin too
fsNode = path.getChild(filename + ".bin");
if (fsNode.exists() && !fsNode.isDirectory() && loadFromMacBinary(*fsNode.createReadStream())) {
_baseFileName = filename;
return true;
}
// Maybe we have a dumped fork?
fsNode = path.getChild(filename + ".rsrc");
if (fsNode.exists() && !fsNode.isDirectory() && loadFromRawFork(*fsNode.createReadStream())) {
_baseFileName = filename;
return true;
}
// Fine, what about just the data fork?
fsNode = path.getChild(filename);
if (fsNode.exists() && !fsNode.isDirectory()) {
_baseFileName = filename;
_stream = fsNode.createReadStream();
return true;
}
// The file doesn't exist
return false;
}
bool MacResManager::loadFromAppleDouble(Common::SeekableReadStream &stream) {
if (stream.readUint32BE() != 0x00051607) // tag
return false;
stream.skip(20); // version + home file system
uint16 entryCount = stream.readUint16BE();
for (uint16 i = 0; i < entryCount; i++) {
uint32 id = stream.readUint32BE();
uint32 offset = stream.readUint32BE();
uint32 length = stream.readUint32BE(); // length
if (id == 1) {
// Found the data fork!
_resForkOffset = offset;
_mode = kResForkAppleDouble;
_resForkSize = length;
return load(stream);
}
}
return false;
}
bool MacResManager::loadFromMacBinary(Common::SeekableReadStream &stream) {
byte infoHeader[MBI_INFOHDR];
stream.read(infoHeader, MBI_INFOHDR);
// Maybe we have MacBinary?
if (infoHeader[MBI_ZERO1] == 0 && infoHeader[MBI_ZERO2] == 0 &&
infoHeader[MBI_ZERO3] == 0 && infoHeader[MBI_NAMELEN] <= MAXNAMELEN) {
// Pull out fork lengths
uint32 dataSize = READ_BE_UINT32(infoHeader + MBI_DFLEN);
uint32 rsrcSize = READ_BE_UINT32(infoHeader + MBI_RFLEN);
uint32 dataSizePad = (((dataSize + 127) >> 7) << 7);
uint32 rsrcSizePad = (((rsrcSize + 127) >> 7) << 7);
// Length check
if (MBI_INFOHDR + dataSizePad + rsrcSizePad == (uint32)stream.size()) {
_resForkOffset = MBI_INFOHDR + dataSizePad;
_resForkSize = rsrcSize;
}
}
if (_resForkOffset < 0)
return false;
_mode = kResForkMacBinary;
return load(stream);
}
bool MacResManager::loadFromRawFork(Common::SeekableReadStream &stream) {
_mode = kResForkRaw;
_resForkOffset = 0;
_resForkSize = stream.size();
return load(stream);
}
bool MacResManager::load(Common::SeekableReadStream &stream) {
if (_mode == kResForkNone)
return false;
stream.seek(_resForkOffset);
_dataOffset = stream.readUint32BE() + _resForkOffset;
_mapOffset = stream.readUint32BE() + _resForkOffset;
_dataLength = stream.readUint32BE();
_mapLength = stream.readUint32BE();
// do sanity check
if (_dataOffset >= (uint32)stream.size() || _mapOffset >= (uint32)stream.size() ||
_dataLength + _mapLength > (uint32)stream.size()) {
_resForkOffset = -1;
_mode = kResForkNone;
return false;
}
debug(7, "got header: data %d [%d] map %d [%d]",
_dataOffset, _dataLength, _mapOffset, _mapLength);
_stream = &stream;
readMap();
return true;
}
Common::SeekableReadStream *MacResManager::getDataFork() {
if (!_stream)
return NULL;
if (_mode == kResForkMacBinary) {
_stream->seek(MBI_DFLEN);
uint32 dataSize = _stream->readUint32BE();
return new SeekableSubReadStream(_stream, MBI_INFOHDR, MBI_INFOHDR + dataSize);
}
Common::File *file = new Common::File();
if (file->open(_baseFileName))
return file;
delete file;
return NULL;
}
MacResIDArray MacResManager::getResIDArray(uint32 typeID) {
int typeNum = -1;
MacResIDArray res;
for (int i = 0; i < _resMap.numTypes; i++)
if (_resTypes[i].id == typeID) {
typeNum = i;
break;
}
if (typeNum == -1)
return res;
res.resize(_resTypes[typeNum].items);
for (int i = 0; i < _resTypes[typeNum].items; i++)
res[i] = _resLists[typeNum][i].id;
return res;
}
MacResTagArray MacResManager::getResTagArray() {
MacResTagArray tagArray;
if (!hasResFork())
return tagArray;
tagArray.resize(_resMap.numTypes);
for (uint32 i = 0; i < _resMap.numTypes; i++)
tagArray[i] = _resTypes[i].id;
return tagArray;
}
Common::String MacResManager::getResName(uint32 typeID, uint16 resID) {
int typeNum = -1;
for (int i = 0; i < _resMap.numTypes; i++)
if (_resTypes[i].id == typeID) {
typeNum = i;
break;
}
if (typeNum == -1)
return "";
for (int i = 0; i < _resTypes[typeNum].items; i++)
if (_resLists[typeNum][i].id == resID)
return _resLists[typeNum][i].name;
return "";
}
Common::SeekableReadStream *MacResManager::getResource(uint32 typeID, uint16 resID) {
int typeNum = -1;
int resNum = -1;
for (int i = 0; i < _resMap.numTypes; i++)
if (_resTypes[i].id == typeID) {
typeNum = i;
break;
}
if (typeNum == -1)
return NULL;
for (int i = 0; i < _resTypes[typeNum].items; i++)
if (_resLists[typeNum][i].id == resID) {
resNum = i;
break;
}
if (resNum == -1)
return NULL;
_stream->seek(_dataOffset + _resLists[typeNum][resNum].dataOffset);
uint32 len = _stream->readUint32BE();
return _stream->readStream(len);
}
void MacResManager::readMap() {
_stream->seek(_mapOffset + 22);
_resMap.resAttr = _stream->readUint16BE();
_resMap.typeOffset = _stream->readUint16BE();
_resMap.nameOffset = _stream->readUint16BE();
_resMap.numTypes = _stream->readUint16BE();
_resMap.numTypes++;
_stream->seek(_mapOffset + _resMap.typeOffset + 2);
_resTypes = new ResType[_resMap.numTypes];
for (int i = 0; i < _resMap.numTypes; i++) {
_resTypes[i].id = _stream->readUint32BE();
_resTypes[i].items = _stream->readUint16BE();
_resTypes[i].offset = _stream->readUint16BE();
_resTypes[i].items++;
debug(8, "resType: <%s> items: %d offset: %d (0x%x)", tag2str(_resTypes[i].id), _resTypes[i].items, _resTypes[i].offset, _resTypes[i].offset);
}
_resLists = new ResPtr[_resMap.numTypes];
for (int i = 0; i < _resMap.numTypes; i++) {
_resLists[i] = new Resource[_resTypes[i].items];
_stream->seek(_resTypes[i].offset + _mapOffset + _resMap.typeOffset);
for (int j = 0; j < _resTypes[i].items; j++) {
ResPtr resPtr = _resLists[i] + j;
resPtr->id = _stream->readUint16BE();
resPtr->nameOffset = _stream->readUint16BE();
resPtr->dataOffset = _stream->readUint32BE();
_stream->readUint32BE();
resPtr->name = 0;
resPtr->attr = resPtr->dataOffset >> 24;
resPtr->dataOffset &= 0xFFFFFF;
}
for (int j = 0; j < _resTypes[i].items; j++) {
if (_resLists[i][j].nameOffset != -1) {
_stream->seek(_resLists[i][j].nameOffset + _mapOffset + _resMap.nameOffset);
byte len = _stream->readByte();
_resLists[i][j].name = new char[len + 1];
_resLists[i][j].name[len] = 0;
_stream->read(_resLists[i][j].name, len);
}
}
}
}
void MacResManager::convertCrsrCursor(byte *data, int datasize, byte **cursor, int *w, int *h,
int *hotspot_x, int *hotspot_y, int *keycolor, bool colored, byte **palette, int *palSize) {
Common::MemoryReadStream dis(data, datasize);
int i, b;
byte imageByte;
byte *iconData;
int numBytes;
int pixelsPerByte, bpp;
int ctSize;
byte bitmask;
int iconRowBytes, iconBounds[4];
int ignored;
int iconDataSize;
dis.readUint16BE(); // type
dis.readUint32BE(); // offset to pixel map
dis.readUint32BE(); // offset to pixel data
dis.readUint32BE(); // expanded cursor data
dis.readUint16BE(); // expanded data depth
dis.readUint32BE(); // reserved
// Grab B/W icon data
*cursor = (byte *)malloc(16 * 16);
for (i = 0; i < 32; i++) {
imageByte = dis.readByte();
for (b = 0; b < 8; b++)
cursor[0][i*8+b] = (byte)((imageByte & (0x80 >> b)) > 0? 0x0F: 0x00);
}
// Apply mask data
for (i = 0; i < 32; i++) {
imageByte = dis.readByte();
for (b = 0; b < 8; b++)
if ((imageByte & (0x80 >> b)) == 0)
cursor[0][i*8+b] = 0xff;
}
*hotspot_y = dis.readUint16BE();
*hotspot_x = dis.readUint16BE();
*w = *h = 16;
// Use b/w cursor on backends which don't support cursor palettes
if (!colored)
return;
dis.readUint32BE(); // reserved
dis.readUint32BE(); // cursorID
// Color version of cursor
dis.readUint32BE(); // baseAddr
// Keep only lowbyte for now
dis.readByte();
iconRowBytes = dis.readByte();
if (!iconRowBytes)
return;
iconBounds[0] = dis.readUint16BE();
iconBounds[1] = dis.readUint16BE();
iconBounds[2] = dis.readUint16BE();
iconBounds[3] = dis.readUint16BE();
dis.readUint16BE(); // pmVersion
dis.readUint16BE(); // packType
dis.readUint32BE(); // packSize
dis.readUint32BE(); // hRes
dis.readUint32BE(); // vRes
dis.readUint16BE(); // pixelType
dis.readUint16BE(); // pixelSize
dis.readUint16BE(); // cmpCount
dis.readUint16BE(); // cmpSize
dis.readUint32BE(); // planeByte
dis.readUint32BE(); // pmTable
dis.readUint32BE(); // reserved
// Pixel data for cursor
iconDataSize = iconRowBytes * (iconBounds[3] - iconBounds[1]);
iconData = (byte *)malloc(iconDataSize);
dis.read(iconData, iconDataSize);
// Color table
dis.readUint32BE(); // ctSeed
dis.readUint16BE(); // ctFlag
ctSize = dis.readUint16BE() + 1;
*palette = (byte *)malloc(ctSize * 4);
// Read just high byte of 16-bit color
for (int c = 0; c < ctSize; c++) {
// We just use indices 0..ctSize, so ignore color ID
dis.readUint16BE(); // colorID[c]
palette[0][c * 4 + 0] = dis.readByte();
ignored = dis.readByte();
palette[0][c * 4 + 1] = dis.readByte();
ignored = dis.readByte();
palette[0][c * 4 + 2] = dis.readByte();
ignored = dis.readByte();
palette[0][c * 4 + 3] = 0;
}
*palSize = ctSize;
numBytes = (iconBounds[2] - iconBounds[0]) * (iconBounds[3] - iconBounds[1]);
pixelsPerByte = (iconBounds[2] - iconBounds[0]) / iconRowBytes;
bpp = 8 / pixelsPerByte;
// build a mask to make sure the pixels are properly shifted out
bitmask = 0;
for (int m = 0; m < bpp; m++) {
bitmask <<= 1;
bitmask |= 1;
}
// Extract pixels from bytes
for (int j = 0; j < iconDataSize; j++)
for (b = 0; b < pixelsPerByte; b++) {
int idx = j * pixelsPerByte + (pixelsPerByte - 1 - b);
if (cursor[0][idx] != 0xff) // if mask is not there
cursor[0][idx] = (byte)((iconData[j] >> (b * bpp)) & bitmask);
}
free(iconData);
assert(datasize - dis.pos() == 0);
}
} // End of namespace Common

155
common/macresman.h Normal file
View file

@ -0,0 +1,155 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/array.h"
#include "common/file.h"
#ifndef COMMON_MACRESMAN_H
#define COMMON_MACRESMAN_H
namespace Common {
class FSNode;
typedef Common::Array<uint16> MacResIDArray;
typedef Common::Array<uint32> MacResTagArray;
/**
* Class for reading Mac Binary files.
* Is able to read dumped resource forks too.
*/
class MacResManager {
public:
MacResManager();
~MacResManager();
bool open(Common::String filename);
bool open(Common::FSNode path, Common::String filename);
void close();
bool hasDataFork();
bool hasResFork();
/**
* Read resource from the Mac Binary file
* @param typeID FourCC with type ID
* @param resID Resource ID to fetch
* @return Pointer to a SeekableReadStream with loaded resource
*/
Common::SeekableReadStream *getResource(uint32 typeID, uint16 resID);
Common::SeekableReadStream *getDataFork();
Common::String getResName(uint32 typeID, uint16 resID);
uint32 getResForkSize();
bool getResForkMD5(char *md5str, uint32 length);
/**
* Convert cursor from crsr format to format suitable for feeding to CursorMan
* @param data Pointer to the cursor data
* @param datasize Size of the cursor data
* @param cursor Pointer to memory where result cursor will be stored. The memory
* block will be malloc()'ed
* @param w Pointer to int where the cursor width will be stored
* @param h Pointer to int where the cursor height will be stored
* @param hotspot_x Storage for cursor hotspot X coordinate
* @param hotspot_Y Storage for cursor hotspot Y coordinate
* @param keycolor Pointer to int where the transpared color value will be stored
* @param colored If set to true then colored cursor will be returned (if any).
* b/w version will be used otherwise
* @param palette Pointer to memory where the cursor palette will be stored.
* The memory will be malloc()'ed
* @param palSize Pointer to integer where the palette size will be stored.
*/
void convertCrsrCursor(byte *data, int datasize, byte **cursor, int *w, int *h,
int *hotspot_x, int *hotspot_y, int *keycolor, bool colored, byte **palette, int *palSize);
/**
* Return list of resource IDs with specified type ID
*/
MacResIDArray getResIDArray(uint32 typeID);
/**
* Return list of resource tags
*/
MacResTagArray getResTagArray();
private:
Common::SeekableReadStream *_stream;
Common::String _baseFileName;
bool load(Common::SeekableReadStream &stream);
bool loadFromRawFork(Common::SeekableReadStream &stream);
bool loadFromMacBinary(Common::SeekableReadStream &stream);
bool loadFromAppleDouble(Common::SeekableReadStream &stream);
enum {
kResForkNone = 0,
kResForkRaw,
kResForkMacBinary,
kResForkAppleDouble
} _mode;
void readMap();
struct ResMap {
uint16 resAttr;
uint16 typeOffset;
uint16 nameOffset;
uint16 numTypes;
};
struct ResType {
uint32 id;
uint16 items;
uint16 offset;
};
struct Resource {
uint16 id;
int16 nameOffset;
byte attr;
uint32 dataOffset;
char *name;
};
typedef Resource *ResPtr;
int32 _resForkOffset;
uint32 _resForkSize;
uint32 _dataOffset;
uint32 _dataLength;
uint32 _mapOffset;
uint32 _mapLength;
ResMap _resMap;
ResType *_resTypes;
ResPtr *_resLists;
};
} // End of namespace Common
#endif

View file

@ -82,11 +82,10 @@ void MemoryPool::allocPage() {
}
void MemoryPool::addPageToPool(const Page &page) {
// Add all chunks of the new page to the linked list (pool) of free chunks
void *current = page.start;
for (size_t i = 1; i < page.numChunks; ++i) {
void *next = ((char*)current + _chunkSize);
void *next = (byte *)current + _chunkSize;
*(void **)current = next;
current = next;
@ -100,7 +99,8 @@ void MemoryPool::addPageToPool(const Page &page) {
}
void *MemoryPool::allocChunk() {
if (!_next) // No free chunks left? Allocate a new page
// No free chunks left? Allocate a new page
if (!_next)
allocPage();
assert(_next);
@ -138,6 +138,7 @@ void MemoryPool::freeUnusedPages() {
break;
}
}
iterator = *(void **)iterator;
}
@ -153,6 +154,7 @@ void MemoryPool::freeUnusedPages() {
else
iter2 = *(void ***)iter2;
}
::free(_pages[i].start);
++freedPagesCount;
_pages[i].start = NULL;

View file

@ -4,21 +4,25 @@ MODULE_OBJS := \
archive.o \
config-file.o \
config-manager.o \
textconsole.o \
debug.o \
error.o \
EventDispatcher.o \
EventRecorder.o \
file.o \
fs.o \
hashmap.o \
macresman.o \
memorypool.o \
md5.o \
mutex.o \
random.o \
str.o \
stream.o \
util.o \
system.o \
textconsole.o \
tokenizer.o \
unzip.o \
util.o \
xmlparser.o \
zlib.o

View file

@ -26,6 +26,7 @@
#define COMMON_PTR_H
#include "common/sys.h"
#include "common/noncopyable.h"
namespace Common {
@ -110,14 +111,20 @@ class SharedPtr {
public:
typedef int RefValue;
typedef T ValueType;
typedef T *Pointer;
typedef T *PointerType;
typedef T &ReferenceType;
SharedPtr() : _refCount(0), _deletion(0), _pointer(0) {}
template<class T2> explicit SharedPtr(T2 *p) : _refCount(new RefValue(1)), _deletion(new SharedPtrDeletionImpl<T2>(p)), _pointer(p) {}
template<class T2, class D> SharedPtr(T2 *p, D d) : _refCount(new RefValue(1)), _deletion(new SharedPtrDeletionDeleterImpl<T2, D>(p, d)), _pointer(p) {}
template<class T2>
explicit SharedPtr(T2 *p) : _refCount(new RefValue(1)), _deletion(new SharedPtrDeletionImpl<T2>(p)), _pointer(p) {}
template<class T2, class D>
SharedPtr(T2 *p, D d) : _refCount(new RefValue(1)), _deletion(new SharedPtrDeletionDeleterImpl<T2, D>(p, d)), _pointer(p) {}
SharedPtr(const SharedPtr &r) : _refCount(r._refCount), _deletion(r._deletion), _pointer(r._pointer) { if (_refCount) ++(*_refCount); }
template<class T2> SharedPtr(const SharedPtr<T2> &r) : _refCount(r._refCount), _deletion(r._deletion), _pointer(r._pointer) { if (_refCount) ++(*_refCount); }
template<class T2>
SharedPtr(const SharedPtr<T2> &r) : _refCount(r._refCount), _deletion(r._deletion), _pointer(r._pointer) { if (_refCount) ++(*_refCount); }
~SharedPtr() { decRef(); }
@ -146,8 +153,8 @@ public:
return *this;
}
ValueType &operator*() const { assert(_pointer); return *_pointer; }
Pointer operator->() const { assert(_pointer); return _pointer; }
ReferenceType operator*() const { assert(_pointer); return *_pointer; }
PointerType operator->() const { assert(_pointer); return _pointer; }
/**
* Returns the plain pointer value. Be sure you know what you
@ -155,7 +162,7 @@ public:
*
* @return the pointer the SharedPtr object manages
*/
Pointer get() const { return _pointer; }
PointerType get() const { return _pointer; }
/**
* Implicit conversion operator to bool for convenience, to make
@ -213,9 +220,64 @@ private:
RefValue *_refCount;
SharedPtrDeletionInternal *_deletion;
T *_pointer;
PointerType _pointer;
};
template<typename T>
class ScopedPtr : NonCopyable {
public:
typedef T ValueType;
typedef T *PointerType;
typedef T &ReferenceType;
explicit ScopedPtr(PointerType o = 0) : _pointer(o) {}
ReferenceType operator*() const { return *_pointer; }
PointerType operator->() const { return _pointer; }
operator PointerType() const { return _pointer; }
/**
* Implicit conversion operator to bool for convenience, to make
* checks like "if (scopedPtr) ..." possible.
*/
operator bool() const { return _pointer != 0; }
~ScopedPtr() {
delete _pointer;
}
/**
* Resets the pointer with the new value. Old object will be destroyed
*/
void reset(PointerType o = 0) {
delete _pointer;
_pointer = o;
}
/**
* Returns the plain pointer value.
*
* @return the pointer the ScopedPtr manages
*/
PointerType get() const { return _pointer; }
/**
* Returns the plain pointer value and releases ScopedPtr.
* After release() call you need to delete object yourself
*
* @return the pointer the ScopedPtr manages
*/
PointerType release() {
PointerType r = _pointer;
_pointer = 0;
return r;
}
private:
PointerType _pointer;
};
} // End of namespace Common
#endif

59
common/random.cpp Normal file
View file

@ -0,0 +1,59 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#include "common/random.h"
#include "common/system.h"
namespace Common {
RandomSource::RandomSource() {
// Use system time as RNG seed. Normally not a good idea, if you are using
// a RNG for security purposes, but good enough for our purposes.
assert(g_system);
uint32 seed = g_system->getMillis();
setSeed(seed);
}
void RandomSource::setSeed(uint32 seed) {
_randSeed = seed;
}
uint RandomSource::getRandomNumber(uint max) {
_randSeed = 0xDEADBF03 * (_randSeed + 1);
_randSeed = (_randSeed >> 13) | (_randSeed << 19);
return _randSeed % (max + 1);
}
uint RandomSource::getRandomBit() {
_randSeed = 0xDEADBF03 * (_randSeed + 1);
_randSeed = (_randSeed >> 13) | (_randSeed << 19);
return _randSeed & 1;
}
uint RandomSource::getRandomNumberRng(uint min, uint max) {
return getRandomNumber(max - min) + min;
}
} // End of namespace Common

71
common/random.h Normal file
View file

@ -0,0 +1,71 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#ifndef COMMON_RANDOM_H
#define COMMON_RANDOM_H
#include "common/sys.h"
namespace Common {
/**
* Simple random number generator. Although it is definitely not suitable for
* cryptographic purposes, it serves our purposes just fine.
*/
class RandomSource {
private:
uint32 _randSeed;
public:
RandomSource();
void setSeed(uint32 seed);
uint32 getSeed() {
return _randSeed;
}
/**
* Generates a random unsigned integer in the interval [0, max].
* @param max the upper bound
* @return a random number in the interval [0, max]
*/
uint getRandomNumber(uint max);
/**
* Generates a random bit, i.e. either 0 or 1.
* Identical to getRandomNumber(1), but faster, hopefully.
* @return a random bit, either 0 or 1
*/
uint getRandomBit();
/**
* Generates a random unsigned integer in the interval [min, max].
* @param min the lower bound
* @param max the upper bound
* @return a random number in the interval [min, max]
*/
uint getRandomNumberRng(uint min, uint max);
};
} // End of namespace Common
#endif

View file

@ -41,8 +41,8 @@ struct Point {
Point() : x(0), y(0) {}
Point(int16 x1, int16 y1) : x(x1), y(y1) {}
bool operator==(const Point &p) const { return x == p.x && y == p.y; };
bool operator!=(const Point &p) const { return x != p.x || y != p.y; };
bool operator==(const Point &p) const { return x == p.x && y == p.y; }
bool operator!=(const Point &p) const { return x != p.x || y != p.y; }
/**
* Return the square of the distance between this point and the point p.

View file

@ -29,11 +29,12 @@
#include "common/noncopyable.h"
#include "common/sys.h"
#include "common/stream.h"
#include "common/str.h"
#include "common/str-array.h"
#include "common/error.h"
namespace Common {
/**
* A class which allows game engines to load game state data.
* That typically means "save games", but also includes things like the
@ -142,7 +143,7 @@ public:
* @return list of strings for all present file names.
* @see Common::matchString()
*/
virtual StringList listSavefiles(const String &pattern) = 0;
virtual StringArray listSavefiles(const String &pattern) = 0;
};
} // End of namespace Common

View file

@ -91,7 +91,18 @@ protected:
typedef T SingletonBaseType;
};
#define DECLARE_SINGLETON(T) template<> T *Common::Singleton<T>::_singleton = 0
/**
* Note that you need to use this macro from the global namespace.
*
* This is because C++ requires initial explicit specialization
* to be placed in the same namespace as the template.
* It has to be put in the global namespace to assure the correct
* namespace Common is referenced.
*/
#define DECLARE_SINGLETON(T) \
namespace Common { \
template<> T *Singleton<T>::_singleton = 0; \
} // End of namespace Common
} // End of namespace Common

42
common/str-array.h Normal file
View file

@ -0,0 +1,42 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef COMMON_STRING_ARRAY_H
#define COMMON_STRING_ARRAY_H
#include "common/array.h"
#include "common/str.h"
namespace Common {
/**
* An array of of strings.
*/
typedef Array<String> StringArray;
} // End of namespace Common
#endif

View file

@ -724,4 +724,99 @@ bool matchString(const char *str, const char *pat, bool ignoreCase, bool pathMod
}
}
String tag2string(uint32 tag) {
char str[5];
str[0] = (char)(tag >> 24);
str[1] = (char)(tag >> 16);
str[2] = (char)(tag >> 8);
str[3] = (char)tag;
str[4] = '\0';
// Replace non-printable chars by dot
for (int i = 0; i < 4; ++i) {
if (!isprint((unsigned char)str[i]))
str[i] = '.';
}
return Common::String(str);
}
size_t strlcpy(char *dst, const char *src, size_t size) {
// Our backup of the source's start, we need this
// to calculate the source's length.
const char * const srcStart = src;
// In case a non-empty size was specified we
// copy over (size - 1) bytes at max.
if (size != 0) {
// Copy over (size - 1) bytes at max.
while (--size != 0) {
if ((*dst++ = *src) == 0)
break;
++src;
}
// In case the source string was longer than the
// destination, we need to add a terminating
// zero.
if (size == 0)
*dst = 0;
}
// Move to the terminating zero of the source
// string, we need this to determin the length
// of the source string.
while (*src)
++src;
// Return the source string's length.
return src - srcStart;
}
size_t strlcat(char *dst, const char *src, size_t size) {
// In case the destination buffer does not contain
// space for at least 1 character, we will just
// return the source string's length.
if (size == 0)
return strlen(src);
// Our backup of the source's start, we need this
// to calculate the source's length.
const char * const srcStart = src;
// Our backup of the destination's start, we need
// this to calculate the destination's length.
const char * const dstStart = dst;
// Search the end of the destination, but do not
// move past the terminating zero.
while (size-- != 0 && *dst != 0)
++dst;
// Calculate the destination's length;
const size_t dstLength = dst - dstStart;
// In case we reached the end of the destination
// buffer before we had a chance to append any
// characters we will just return the destination
// length plus the source string's length.
if (size == 0)
return dstLength + strlen(srcStart);
// Copy over all of the source that fits
// the destination buffer. We also need
// to take the terminating zero we will
// add into consideration.
while (size-- != 0 && *src != 0)
*dst++ = *src++;
*dst = 0;
// Move to the terminating zero of the source
// string, we need this to determin the length
// of the source string.
while (*src)
++src;
// Return the total length of the result string
return dstLength + (src - srcStart);
}
} // End of namespace Common

View file

@ -26,7 +26,6 @@
#define COMMON_STRING_H
#include "common/sys.h"
#include "common/array.h"
namespace Common {
@ -319,7 +318,57 @@ Common::String normalizePath(const Common::String &path, const char sep);
bool matchString(const char *str, const char *pat, bool ignoreCase = false, bool pathMode = false);
typedef Array<String> StringList;
/**
* Take a 32 bit value and turn it into a four character string, where each of
* the four bytes is turned into one character. Most significant byte is printed
* first.
*/
String tag2string(uint32 tag);
/**
* Copy up to size - 1 characters from src to dst and also zero terminate the
* result. Note that src must be a zero terminated string.
*
* In case size is zero this function just returns the length of the source
* string.
*
* @note This is modeled after OpenBSD's strlcpy. See the manpage here:
* http://www.openbsd.org/cgi-bin/man.cgi?query=strlcpy
*
* @param dst The destination buffer.
* @param src The source string.
* @param size The size of the destination buffer.
* @return The length of the (non-truncated) result, i.e. strlen(src).
*/
size_t strlcpy(char *dst, const char *src, size_t size);
/**
* Append the string src to the string dst. Note that both src and dst must be
* zero terminated. The result will be zero terminated. At most
* "size - strlen(dst) - 1" bytes will be appended.
*
* In case the dst string does not contain a zero within the first "size" bytes
* the dst string will not be changed and size + strlen(src) is returned.
*
* @note This is modeled after OpenBSD's strlcat. See the manpage here:
* http://www.openbsd.org/cgi-bin/man.cgi?query=strlcat
*
* @param dst The string the source string should be appended to.
* @param src The source string.
* @param size The (total) size of the destination buffer.
* @return The length of the (non-truncated) result. That is
* strlen(dst) + strlen(src). In case strlen(dst) > size
* size + strlen(src) is returned.
*/
size_t strlcat(char *dst, const char *src, size_t size);
/**
* Convenience wrapper for tag2string which "returns" a C string.
* Note: It is *NOT* safe to do anything with the return value other than directly
* copying or printing it.
*/
#define tag2str(x) Common::tag2string(x).c_str()
} // End of namespace Common

View file

@ -29,6 +29,7 @@
#include "common/sys.h"
#include "common/noncopyable.h"
#include "common/rect.h"
#include "common/list.h" // For OSystem::getSupportedFormats()
#include "graphics/pixelformat.h"

View file

@ -25,6 +25,24 @@
#include "common/textconsole.h"
#include "common/system.h"
#ifdef _WIN32_WCE
// This is required for the debugger attachment
extern bool isSmartphone();
#endif
#ifdef __PLAYSTATION2__
// for those replaced fopen/fread/etc functions
#include "backends/platform/ps2/fileio.h"
#define fputs(str, file) ps2_fputs(str, file)
#endif
#ifdef __DS__
#include "backends/fs/ds/ds-fs.h"
#define fputs(str, file) DS::std_fwrite(str, strlen(str), 1, file)
#endif
namespace Common {
static OutputFormatter s_errorOutputFormatter = 0;

59
common/tokenizer.cpp Normal file
View file

@ -0,0 +1,59 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#include "common/tokenizer.h"
namespace Common {
StringTokenizer::StringTokenizer(const String &str, const String &delimiters) : _str(str), _delimiters(delimiters) {
reset();
}
void StringTokenizer::reset() {
_tokenBegin = _tokenEnd = 0;
}
bool StringTokenizer::empty() const {
// Search for the next token's start (i.e. the next non-delimiter character)
for (uint i = _tokenEnd; i < _str.size(); i++) {
if (!_delimiters.contains(_str[i]))
return false; // Found a token so the tokenizer is not empty
}
// Didn't find any more tokens so the tokenizer is empty
return true;
}
String StringTokenizer::nextToken() {
// Seek to next token's start (i.e. jump over the delimiters before next token)
for (_tokenBegin = _tokenEnd; _tokenBegin < _str.size() && _delimiters.contains(_str[_tokenBegin]); _tokenBegin++)
;
// Seek to the token's end (i.e. jump over the non-delimiters)
for (_tokenEnd = _tokenBegin; _tokenEnd < _str.size() && !_delimiters.contains(_str[_tokenEnd]); _tokenEnd++)
;
// Return the found token
return String(_str.c_str() + _tokenBegin, _tokenEnd - _tokenBegin);
}
} // End of namespace Common

61
common/tokenizer.h Normal file
View file

@ -0,0 +1,61 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#ifndef COMMON_TOKENIZER_H
#define COMMON_TOKENIZER_H
#include "common/sys.h"
#include "common/str.h"
namespace Common {
/**
* A simple non-optimized string tokenizer.
*
* Example of use:
* StringTokenizer("Now, this is a test!", " ,!") gives tokens "Now", "this", "is", "a" and "test" using nextToken().
*/
class StringTokenizer {
public:
/**
* Creates a StringTokenizer.
* @param str The string to be tokenized.
* @param delimiters String containing all the delimiter characters (i.e. the characters to be ignored).
* @note Uses space, horizontal tab, carriage return, newline, form feed and vertical tab as delimiters by default.
*/
StringTokenizer(const String &str, const String &delimiters = " \t\r\n\f\v");
void reset(); ///< Resets the tokenizer to its initial state
bool empty() const; ///< Returns true if there are no more tokens left in the string, false otherwise
String nextToken(); ///< Returns the next token from the string (Or an empty string if there are no more tokens)
private:
const String _str; ///< The string to be tokenized
const String _delimiters; ///< String containing all the delimiter characters
uint _tokenBegin; ///< Latest found token's begin (Valid after a call to nextToken(), zero otherwise)
uint _tokenEnd; ///< Latest found token's end (Valid after a call to nextToken(), zero otherwise)
};
} // End of namespace Common
#endif

View file

@ -1357,6 +1357,21 @@ int unzGetGlobalComment(unzFile file, char *szComment, uLong uSizeBuf) {
namespace Common {
class ZipArchive : public Archive {
unzFile _zipFile;
public:
ZipArchive(unzFile zipFile);
~ZipArchive();
virtual bool hasFile(const String &name);
virtual int listMembers(ArchiveMemberList &list);
virtual ArchiveMemberPtr getMember(const String &name);
virtual SeekableReadStream *createReadStreamForMember(const String &name) const;
};
/*
class ZipArchiveMember : public ArchiveMember {
unzFile _zipFile;
@ -1375,36 +1390,19 @@ public:
};
*/
ZipArchive::ZipArchive(const Common::String &name) {
SeekableReadStream *stream = SearchMan.createReadStreamForMember(name);
_zipFile = unzOpen(stream);
}
ZipArchive::ZipArchive(const Common::FSNode &node) {
SeekableReadStream *stream = node.createReadStream();
_zipFile = unzOpen(stream);
}
ZipArchive::ZipArchive(Common::SeekableReadStream *stream) {
_zipFile = unzOpen(stream);
ZipArchive::ZipArchive(unzFile zipFile) : _zipFile(zipFile) {
assert(_zipFile);
}
ZipArchive::~ZipArchive() {
unzClose(_zipFile);
}
bool ZipArchive::isOpen() const {
return _zipFile != 0;
}
bool ZipArchive::hasFile(const Common::String &name) {
return (_zipFile && unzLocateFile(_zipFile, name.c_str(), 2) == UNZ_OK);
return (unzLocateFile(_zipFile, name.c_str(), 2) == UNZ_OK);
}
int ZipArchive::listMembers(Common::ArchiveMemberList &list) {
if (!_zipFile)
return 0;
int matches = 0;
int err = unzGoToFirstFile(_zipFile);
@ -1422,16 +1420,13 @@ int ZipArchive::listMembers(Common::ArchiveMemberList &list) {
}
ArchiveMemberPtr ZipArchive::getMember(const String &name) {
if (!_zipFile || !hasFile(name))
if (!hasFile(name))
return ArchiveMemberPtr();
return ArchiveMemberPtr(new GenericArchiveMember(name, this));
}
Common::SeekableReadStream *ZipArchive::createReadStreamForMember(const Common::String &name) const {
if (!_zipFile)
return 0;
if (unzLocateFile(_zipFile, name.c_str(), 2) != UNZ_OK)
return 0;
@ -1450,7 +1445,26 @@ Common::SeekableReadStream *ZipArchive::createReadStreamForMember(const Common::
// files in the archive and tries to use them indepenendtly.
}
Archive *makeZipArchive(const String &name) {
return makeZipArchive(SearchMan.createReadStreamForMember(name));
}
Archive *makeZipArchive(const FSNode &node) {
return makeZipArchive(node.createReadStream());
}
Archive *makeZipArchive(SeekableReadStream *stream) {
if (!stream)
return 0;
unzFile zipFile = unzOpen(stream);
if (!zipFile) {
// stream gets deleted by unzOpen() call if something
// goes wrong.
return 0;
}
return new ZipArchive(zipFile);
}
} // End of namespace Common
#endif

View file

@ -27,46 +27,41 @@
#ifdef USE_ZLIB
#include "common/sys.h"
#include "common/archive.h"
typedef void *unzFile;
namespace Common {
class ZipArchive : public Archive {
void *_zipFile;
public:
/**
* Open the .zip archive with the given file name.
*/
ZipArchive(const String &name);
class Archive;
class FSNode;
class SeekableReadStream;
class String;
/**
* Open the .zip archive to which the given FSNode refers to.
* This factory method creates an Archive instance corresponding to the content
* of the ZIP compressed file with the given name.
*
* May return 0 in case of a failure.
*/
ZipArchive(const FSNode &node);
Archive *makeZipArchive(const String &name);
/**
* Open a .zip file from a stream. This takes ownership of the stream,
* in particular, it is closed when the ZipArchive is deleted.
* This factory method creates an Archive instance corresponding to the content
* of the ZIP compressed file with the given name.
*
* May return 0 in case of a failure.
*/
ZipArchive(SeekableReadStream *stream);
Archive *makeZipArchive(const FSNode &node);
~ZipArchive();
bool isOpen() const;
virtual bool hasFile(const String &name);
virtual int listMembers(ArchiveMemberList &list);
virtual ArchiveMemberPtr getMember(const String &name);
virtual SeekableReadStream *createReadStreamForMember(const String &name) const;
};
/**
* This factory method creates an Archive instance corresponding to the content
* of the given ZIP compressed datastream.
* This takes ownership of the stream, in particular, it is deleted when the
* ZipArchive is deleted.
*
* May return 0 in case of a failure. In this case stream will still be deleted.
*/
Archive *makeZipArchive(SeekableReadStream *stream);
} // End of namespace Common
#endif // USE_ZLIB
#endif /* _unz_H */
#endif

View file

@ -26,57 +26,8 @@
#include "common/system.h"
#include "common/config-manager.h"
#include <stdarg.h> // For va_list etc.
#ifdef _WIN32_WCE
// This is required for the debugger attachment
extern bool isSmartphone();
#endif
#ifdef __PLAYSTATION2__
// for those replaced fopen/fread/etc functions
#include "backends/platform/ps2/fileio.h"
#define fputs(str, file) ps2_fputs(str, file)
#endif
#ifdef __DS__
#include "backends/fs/ds/ds-fs.h"
#define fputs(str, file) DS::std_fwrite(str, strlen(str), 1, file)
#endif
namespace Common {
StringTokenizer::StringTokenizer(const String &str, const String &delimiters) : _str(str), _delimiters(delimiters) {
reset();
}
void StringTokenizer::reset() {
_tokenBegin = _tokenEnd = 0;
}
bool StringTokenizer::empty() const {
// Search for the next token's start (i.e. the next non-delimiter character)
for (uint i = _tokenEnd; i < _str.size(); i++) {
if (!_delimiters.contains(_str[i]))
return false; // Found a token so the tokenizer is not empty
}
// Didn't find any more tokens so the tokenizer is empty
return true;
}
String StringTokenizer::nextToken() {
// Seek to next token's start (i.e. jump over the delimiters before next token)
for (_tokenBegin = _tokenEnd; _tokenBegin < _str.size() && _delimiters.contains(_str[_tokenBegin]); _tokenBegin++)
;
// Seek to the token's end (i.e. jump over the non-delimiters)
for (_tokenEnd = _tokenBegin; _tokenEnd < _str.size() && !_delimiters.contains(_str[_tokenEnd]); _tokenEnd++)
;
// Return the found token
return String(_str.c_str() + _tokenBegin, _tokenEnd - _tokenBegin);
}
//
// Print hexdump of the data passed in
//
@ -129,51 +80,25 @@ void hexdump(const byte * data, int len, int bytesPerLine, int startOffset) {
printf("|\n");
}
String tag2string(uint32 tag) {
char str[5];
str[0] = (char)(tag >> 24);
str[1] = (char)(tag >> 16);
str[2] = (char)(tag >> 8);
str[3] = (char)tag;
str[4] = '\0';
// Replace non-printable chars by dot
for (int i = 0; i < 4; ++i) {
if (!isprint((unsigned char)str[i]))
str[i] = '.';
}
return Common::String(str);
}
#pragma mark -
RandomSource::RandomSource() {
// Use system time as RNG seed. Normally not a good idea, if you are using
// a RNG for security purposes, but good enough for our purposes.
assert(g_system);
uint32 seed = g_system->getMillis();
setSeed(seed);
bool parseBool(const Common::String &val, bool &valAsBool) {
if (val.equalsIgnoreCase("true") ||
val.equalsIgnoreCase("yes") ||
val.equals("1")) {
valAsBool = true;
return true;
}
if (val.equalsIgnoreCase("false") ||
val.equalsIgnoreCase("no") ||
val.equals("0")) {
valAsBool = false;
return true;
}
void RandomSource::setSeed(uint32 seed) {
_randSeed = seed;
}
uint RandomSource::getRandomNumber(uint max) {
_randSeed = 0xDEADBF03 * (_randSeed + 1);
_randSeed = (_randSeed >> 13) | (_randSeed << 19);
return _randSeed % (max + 1);
}
uint RandomSource::getRandomBit() {
_randSeed = 0xDEADBF03 * (_randSeed + 1);
_randSeed = (_randSeed >> 13) | (_randSeed << 19);
return _randSeed & 1;
}
uint RandomSource::getRandomNumberRng(uint min, uint max) {
return getRandomNumber(max - min) + min;
return false;
}
@ -191,7 +116,8 @@ const LanguageDescription g_languages[] = {
{"fr", "French", FR_FRA},
{"de", "German", DE_DEU},
{"gr", "Greek", GR_GRE},
{"hb", "Hebrew", HB_ISR},
{"he", "Hebrew", HE_ISR},
{"hb", "Hebrew", HE_ISR}, // Deprecated
{"hu", "Hungarian", HU_HUN},
{"it", "Italian", IT_ITA},
{"jp", "Japanese", JA_JPN},

View file

@ -68,32 +68,6 @@ template<typename T> inline void SWAP(T &a, T &b) { T tmp = a; a = b; b = tmp; }
namespace Common {
/**
* A simple non-optimized string tokenizer.
*
* Example of use:
* StringTokenizer("Now, this is a test!", " ,!") gives tokens "Now", "this", "is", "a" and "test" using nextToken().
*/
class StringTokenizer {
public:
/**
* Creates a StringTokenizer.
* @param str The string to be tokenized.
* @param delimiters String containing all the delimiter characters (i.e. the characters to be ignored).
* @note Uses space, horizontal tab, carriage return, newline, form feed and vertical tab as delimiters by default.
*/
StringTokenizer(const String &str, const String &delimiters = " \t\r\n\f\v");
void reset(); ///< Resets the tokenizer to its initial state
bool empty() const; ///< Returns true if there are no more tokens left in the string, false otherwise
String nextToken(); ///< Returns the next token from the string (Or an empty string if there are no more tokens)
private:
const String _str; ///< The string to be tokenized
const String _delimiters; ///< String containing all the delimiter characters
uint _tokenBegin; ///< Latest found token's begin (Valid after a call to nextToken(), zero otherwise)
uint _tokenEnd; ///< Latest found token's end (Valid after a call to nextToken(), zero otherwise)
};
/**
* Print a hexdump of the data passed in. The number of bytes per line is
* customizable.
@ -106,52 +80,16 @@ extern void hexdump(const byte * data, int len, int bytesPerLine = 16, int start
/**
* Take a 32 bit value and turn it into a four character string, where each of
* the four bytes is turned into one character. Most significant byte is printed
* first.
* Parse a string for a boolean value.
* The strings "true", "yes", and "1" are interpreted as true.
* The strings "false", "no", and "0" are interpreted as false.
* This function ignores case.
*
* @param[in] val the string to parse
* @param[out] valAsBool the parsing result
* @return true if the string parsed correctly, false if an error occurred.
*/
String tag2string(uint32 tag);
#define tag2str(x) Common::tag2string(x).c_str()
/**
* Simple random number generator. Although it is definitely not suitable for
* cryptographic purposes, it serves our purposes just fine.
*/
class RandomSource {
private:
uint32 _randSeed;
public:
RandomSource();
void setSeed(uint32 seed);
uint32 getSeed() {
return _randSeed;
}
/**
* Generates a random unsigned integer in the interval [0, max].
* @param max the upper bound
* @return a random number in the interval [0, max]
*/
uint getRandomNumber(uint max);
/**
* Generates a random bit, i.e. either 0 or 1.
* Identical to getRandomNumber(1), but faster, hopefully.
* @return a random bit, either 0 or 1
*/
uint getRandomBit();
/**
* Generates a random unsigned integer in the interval [min, max].
* @param min the lower bound
* @param max the upper bound
* @return a random number in the interval [min, max]
*/
uint getRandomNumberRng(uint min, uint max);
};
bool parseBool(const Common::String &val, bool &valAsBool);
/**
* List of game language.
@ -167,7 +105,7 @@ enum Language {
FR_FRA,
DE_DEU,
GR_GRE,
HB_ISR,
HE_ISR,
HU_HUN,
IT_ITA,
JA_JPN,

326
configure vendored
View file

@ -94,6 +94,7 @@ _debug_build=auto
_release_build=auto
_text_console=no
_mt32emu=no
_enable_prof=no
# Default vkeybd/keymapper options
_vkeybd=no
_keymapper=no
@ -120,7 +121,24 @@ _sdlpath="$PATH"
_nasmpath="$PATH"
NASMFLAGS=""
NASM=""
_prefix=/usr/local
# Directories for installing Reesidual.
# This list is closely based on what GNU autoconf does,
# although the default value for datadir differs.
# Like GNU autoconf, we distinguish datadir and datarootdir
# to make it possible to change e.g. the location of the
# man pages independently of that of the engine data files,
# which are placed inside $datadir/residual
exec_prefix=NONE
prefix=NONE
bindir='${exec_prefix}/bin'
datarootdir='${prefix}/share'
datadir='${datarootdir}/residual'
docdir='${datarootdir}/doc/residual'
libdir='${exec_prefix}/lib'
#localedir='${datarootdir}/locale'
mandir='${datarootdir}/man'
# For cross compiling
_host=""
_host_cpu=""
@ -140,18 +158,52 @@ fi
TMPC=${TMPO}.cpp
TMPLOG=config.log
cc_check() {
cc_check_no_clean() {
echo >> "$TMPLOG"
cat "$TMPC" >> "$TMPLOG"
echo >> "$TMPLOG"
echo "$CXX $TMPC -o $TMPO$HOSTEXEEXT $@" >> "$TMPLOG"
echo "$CXX $LDFLAGS $CXXFLAGS $TMPC -o $TMPO$HOSTEXEEXT $@" >> "$TMPLOG"
rm -f "$TMPO$HOSTEXEEXT"
( $CXX $CXXFLAGS "$TMPC" -o "$TMPO$HOSTEXEEXT" "$@" ) >> "$TMPLOG" 2>&1
( $CXX $LDFLAGS $CXXFLAGS "$TMPC" -o "$TMPO$HOSTEXEEXT" "$@" ) >> "$TMPLOG" 2>&1
TMP="$?"
echo "return code: $TMP" >> "$TMPLOG"
echo >> "$TMPLOG"
return "$TMP"
}
cc_check_clean() {
rm -rf $TMPC $TMPO $TMPO.o $TMPO.dSYM $TMPO$HOSTEXEEXT "$@"
}
cc_check() {
cc_check_no_clean "$@"
TMP="$?"
cc_check_clean
return "$TMP"
}
cc_check_define() {
cat > $TMPC << EOF
int main(void) {
#ifndef $1
syntax error
#endif
return 0;
}
EOF
cc_check -c
return $?
}
gcc_get_define() {
# Note: The AmigaOS compiler doesn't like the "-" input file, so a real file
# is used instead
rm -f $TMPC
touch $TMPC
$CXX -dM -E $TMPC | fgrep "$1" | head -n1 | cut -d ' ' -f 3-
rm -f $TMPC
}
#
# Function to provide echo -n for bourne shells that don't have it
#
@ -519,11 +571,25 @@ Configuration:
--backend=BACKEND backend to build (sdl, null) [sdl]
Installation directories:
--prefix=DIR use this prefix for installing Residual [/usr/local]
--bindir=DIR directory to install the residual binary in [PREFIX/bin]
--mandir=DIR directory to install the manpage in [PREFIX/share/man]
--datadir=DIR directory to install the data files in [PREFIX/share]
--libdir=DIR directory to install the plugins in [PREFIX/lib]
--prefix=PREFIX install architecture-independent files in PREFIX
[/usr/local]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
[PREFIX]
By default, \`make install' will install all the files in
\`/usr/local/bin', \`/usr/local/lib' etc. You can specify
an installation prefix other than \`/usr/local' using \`--prefix',
for instance \`--prefix=\$HOME'.
For better control, use the options below.
Fine tuning of the installation directories:
--bindir=DIR user executables [EPREFIX/bin]
--libdir=DIR object code libraries [EPREFIX/lib]
--datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
--datadir=DIR read-only architecture-independent data [DATAROOTDIR/scummvm]
--mandir=DIR man documentation [DATAROOTDIR/man]
--docdir=DIR documentation root [DATAROOTDIR/doc/scummvm]
Special configuration feature:
--host=HOST cross-compile to target HOST (arm-linux, ...)
@ -535,11 +601,11 @@ $engines_help
Optional Features:
--disable-debug disable building with debugging symbols
--enable-Werror treat warnings as errors
--enable-release enable building in release mode (this activates optimizations)
--enable-profiling enable profiling
--enable-plugins enable the support for dynamic plugins
--default-dynamic make plugins dynamic by default
--disable-mt32emu don't enable the integrated MT-32 emulator
--enable-profiling enable building with gprof profile information
--enable-release set flags to build release binary
--enable-text-console use text console instead of graphical console
--enable-verbose-build enable regular echoing of commands during build process
@ -679,8 +745,7 @@ for ac_option in $@; do
_release_build=no
;;
--enable-profiling)
CXXFLAGS="$CXXFLAGS -pg"
LDFLAGS="$LDFLAGS -pg"
_enable_prof=yes
;;
--with-sdl-prefix=*)
arg=`echo $ac_option | cut -d '=' -f 2`
@ -696,20 +761,26 @@ for ac_option in $@; do
--host=*)
_host=`echo $ac_option | cut -d '=' -f 2`
;;
--exec-prefix=*)
exec_prefix=`echo $ac_option | cut -d '=' -f 2`
;;
--prefix=*)
_prefix=`echo $ac_option | cut -d '=' -f 2`
prefix=`echo $ac_option | cut -d '=' -f 2`
;;
--bindir=*)
_bindir=`echo $ac_option | cut -d '=' -f 2`
bindir=`echo $ac_option | cut -d '=' -f 2`
;;
--mandir=*)
_mandir=`echo $ac_option | cut -d '=' -f 2`
mandir=`echo $ac_option | cut -d '=' -f 2`
;;
--datarootdir=*)
datarootdir=`echo $ac_option | cut -d '=' -f 2`
;;
--datadir=*)
_datadir=`echo $ac_option | cut -d '=' -f 2`
datadir=`echo $ac_option | cut -d '=' -f 2`
;;
--libdir=*)
_libdir=`echo $ac_option | cut -d '=' -f 2`
libdir=`echo $ac_option | cut -d '=' -f 2`
;;
--enable-all-engines)
engine_enable_all
@ -816,7 +887,7 @@ psp)
_host_cpu=mipsallegrexel
_host_alias=psp
if test -z "$PSPDEV"; then
PSPDEV=$(psp-config --pspdev-path)
PSPDEV=`psp-config --pspdev-path`
fi
if test -d "$PSPDEV/psp/lib"; then
LDFLAGS="$LDFLAGS -L$PSPDEV/psp/lib"
@ -826,7 +897,7 @@ psp)
samsungtv)
_host_os=linux
_host_cpu=arm
_host_alias=arm-SamyGO-linux-gnueabi
_host_alias=arm-linux-gnueabi
;;
wii)
_host_os=wii
@ -910,7 +981,7 @@ ps2)
fi
;;
psp)
PSPSDK=$(psp-config --pspsdk-path)
PSPSDK=`psp-config --pspsdk-path`
if test -z "$PSPSDK"; then
echo "Please set the path to PSPSDK in your environment."
exit 1
@ -927,18 +998,20 @@ echo_n "Looking for C++ compiler... "
# Check whether the given command is a working C++ compiler
test_compiler() {
cat <<EOF >tmp_cxx_compiler.cpp
cat > tmp_cxx_compiler.cpp << EOF
class Foo { int a; };
int main(int argc, char **argv) {
Foo *a = new Foo(); delete a; return 0;
}
EOF
echo "testing compiler: $1" >> "$TMPLOG"
if test -n "$_host"; then
# In cross-compiling mode, we cannot run the result
eval "$1 $CXXFLAGS $LDFLAGS -o tmp_cxx_compiler$HOSTEXEEXT -c tmp_cxx_compiler.cpp" 2> /dev/null && rm -f tmp_cxx_compiler$HOSTEXEEXT tmp_cxx_compiler.cpp
eval "$1 $CXXFLAGS $LDFLAGS -o $TMPO.o -c tmp_cxx_compiler.cpp" 2> /dev/null && cc_check_clean tmp_cxx_compiler.cpp
else
eval "$1 $CXXFLAGS $LDFLAGS -o tmp_cxx_compiler$HOSTEXEEXT tmp_cxx_compiler.cpp" 2> /dev/null && eval "./tmp_cxx_compiler$HOSTEXEEXT 2> /dev/null" && rm -rf tmp_cxx_compiler$HOSTEXEEXT tmp_cxx_compiler.dSYM tmp_cxx_compiler.cpp
eval "$1 $CXXFLAGS $LDFLAGS -o $TMPO$HOSTEXEEXT tmp_cxx_compiler.cpp" 2> /dev/null && eval "$TMPO$HOSTEXEEXT 2> /dev/null" && cc_check_clean tmp_cxx_compiler.cpp
fi
}
@ -978,9 +1051,28 @@ LD=$CXX
echocheck "compiler version"
have_gcc=no
cxx_version=`( $CXX -dumpversion ) 2>&1`
if test "$?" -gt 0; then
# TODO: Big scary warning about unsupported Compilers
cc_check_define __GNUC__ && have_gcc=yes
if test "$have_gcc" = yes; then
add_line_to_config_mk 'HAVE_GCC = 1'
_cxx_major=`gcc_get_define __GNUC__`
_cxx_minor=`gcc_get_define __GNUC_MINOR__`
cxx_version="`( $CXX -dumpversion ) 2>&1`"
if test -n "`gcc_get_define __clang__`"; then
add_line_to_config_mk 'HAVE_CLANG = 1'
fi
if test "$_cxx_major" -eq 2 && test "$_cxx_minor" -ge 95 || \
test "$_cxx_major" -gt 2 ; then
cxx_version="$cxx_version, ok"
cxx_verc_fail=no
else
cxx_version="$cxx_version, bad"
cxx_verc_fail=yes
fi
else
# TODO: Big scary warning about unsupported compilers
cxx_version=`( $CXX -version ) 2>&1`
if test "$?" -eq 0; then
cxx_version="`echo "${cxx_version}" | sed -ne 's/^.*[^0-9]\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*$/\1/gp'`"
@ -994,46 +1086,15 @@ if test "$?" -gt 0; then
cxx_verc_fail=yes
echo found non-gcc compiler version ${cxx_version}
fi
else
add_line_to_config_mk 'HAVE_GCC = 1'
have_gcc=yes
fi
if test "$have_gcc" = yes; then
case $cxx_version in
2.95.[2-9]|2.95.[2-9][-.]*|3.[0-9]|3.[0-9].[0-9]|3.[0-9].[0-9][-.]*|4.[0-9]|4.[0-9].[0-9]|4.[0-9].[0-9][-.]*)
_cxx_major=`echo $cxx_version | cut -d '.' -f 1`
_cxx_minor=`echo $cxx_version | cut -d '.' -f 2`
cxx_version="$cxx_version, ok"
cxx_verc_fail=no
;;
# whacky beos version strings
2.9-beos-991026*|2.9-beos-000224*)
_cxx_major=2
_cxx_minor=95
cxx_version="$cxx_version, ok"
cxx_verc_fail=no
;;
3_4)
_cxx_major=3
_cxx_minor=4
;;
'not found')
cxx_verc_fail=yes
;;
*)
cxx_version="$cxx_version, bad"
cxx_verc_fail=yes
;;
esac
else
case $_host_os in
irix*)
case $cxx_version in
7.4.4*)
# We just assume this is SGI MipsPRO
# We just assume this is SGI MIPSpro
_cxx_major=7
_cxx_minor=4
cxx_verc_fail=no
add_line_to_config_mk 'CXX_UPDATE_DEP_FLAG = -MDupdate "$(*D)/$(DEPDIR)/$(*F).d"'
add_line_to_config_mk '-include Makedepend'
;;
@ -1048,7 +1109,6 @@ else
cxx_verc_fail=yes
;;
esac
fi
echo "$cxx_version"
@ -1064,7 +1124,7 @@ fi
# Check for endianness
#
echo_n "Checking endianness... "
cat <<EOF >tmp_endianness_check.cpp
cat > tmp_endianness_check.cpp << EOF
short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
void _ascii() { char* s = (char*) ascii_mm; s = (char*) ascii_ii; }
@ -1073,21 +1133,21 @@ short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
void _ebcdic() { char* s = (char*) ebcdic_mm; s = (char*) ebcdic_ii; }
int main() { _ascii (); _ebcdic (); return 0; }
EOF
$CXX $CXXFLAGS -c -o tmp_endianness_check.o tmp_endianness_check.cpp
if strings tmp_endianness_check.o | grep BIGenDianSyS >/dev/null; then
$CXX $CXXFLAGS -c -o $TMPO.o tmp_endianness_check.cpp
if strings $TMPO.o | grep BIGenDianSyS >/dev/null; then
_endian=big
else
_endian=little
fi
echo $_endian;
rm -f tmp_endianness_check.o tmp_endianness_check.cpp
cc_check_clean tmp_endianness_check.cpp
#
# Determine a data type with the given length
#
find_type_with_size() {
for datatype in int short char long 'long long' unknown; do
cat <<EOF >tmp_find_type_with_size.cpp
for datatype in int short char long unknown; do
cat > tmp_find_type_with_size.cpp << EOF
typedef $datatype ac__type_sizeof_;
int main() {
static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) == $1)];
@ -1095,7 +1155,7 @@ int main() {
return 0;
}
EOF
if $CXX $CXXFLAGS -c -o tmp_find_type_with_size$HOSTEXEEXT tmp_find_type_with_size.cpp 2>/dev/null ; then
if $CXX $CXXFLAGS -c -o $TMPO.o tmp_find_type_with_size.cpp 2>/dev/null ; then
break
else
if test "$datatype" = "unknown"; then
@ -1105,7 +1165,7 @@ else
continue
fi
done
rm -f tmp_find_type_with_size$HOSTEXEEXT tmp_find_type_with_size.cpp
cc_check_clean tmp_find_type_with_size.cpp
echo $datatype
}
@ -1113,16 +1173,16 @@ echo $datatype
# Determine a size of pointer type
#
find_pointer_size() {
cat <<EOF >tmp_find_pointer_size.cpp
cat > tmp_find_pointer_size.cpp << EOF
int main() {
void *p;
int v = (int)p;
return 0;
}
EOF
$CXX $CXXFLAGS -c -o tmp_find_pointer_size$HOSTEXEEXT tmp_find_pointer_size.cpp 2>/dev/null
$CXX $CXXFLAGS -c -o $TMPO.o tmp_find_pointer_size.cpp 2>/dev/null
status=$?
rm -f tmp_find_pointer_size$HOSTEXEEXT tmp_find_pointer_size.cpp
cc_check_clean tmp_find_pointer_size.cpp
return $status
}
@ -1202,8 +1262,6 @@ case $_host_os in
CFLAGS="-I/boot/home/config/include"
CXXFLAGS="$CXXFLAGS -fhuge-objects"
LIBS="$LIBS -lbind -lsocket"
# FIXME: Please document why 'long' has to be used instead of int
#type_4_byte='long'
;;
bsd* | hpux* | netbsd* | openbsd* | sunos*)
DEFINES="$DEFINES -DUNIX -DUSE_OPENGL"
@ -1239,8 +1297,6 @@ case $_host_os in
# Needs -lnetwork for the timidity MIDI driver
LIBS="$LIBS -lnetwork"
CXXFLAGS="$CXXFLAGS -fhuge-objects"
# FIXME: Please document why 'long' has to be used instead of int
#type_4_byte='long'
;;
irix*)
DEFINES="$DEFINES -DUNIX -DIRIX -DSYSTEM_NOT_SUPPORTING_D_TYPE"
@ -1304,9 +1360,9 @@ esac
if test -n "$_host"; then
# Cross-compiling mode - add your target here if needed
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
echo "Cross-compiling to $_host"
case "$_host" in
arm-linux|arm*-linux-gnueabi|arm-*-linux|*-angstrom-linux)
arm-linux|arm*-linux-gnueabi|arm-*-linux)
DEFINES="$DEFINES -DUNIX"
_need_memalign=yes
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
@ -1329,17 +1385,16 @@ if test -n "$_host"; then
_need_memalign=yes
_backend="dc"
_build_scalers="no"
_build_hq_scalers="no"
_mad="yes"
_zlib="yes"
add_line_to_config_mk 'include $(srcdir)/backends/platform/dc/dreamcast.mk'
add_line_to_config_mk 'ronindir = /usr/local/ronin'
_port_mk="backends/platform/dc/dreamcast.mk"
;;
gamecube)
_endian=big
_need_memalign=yes
_backend="wii"
_build_scalers="no"
_build_hq_scalers="no"
_mt32emu="no"
_port_mk="backends/platform/wii/wii.mk"
add_line_to_config_mk 'GAMECUBE = 1'
@ -1366,7 +1421,6 @@ if test -n "$_host"; then
DEFINES="$DEFINES -DUNIX -DGP2XWIZ -DNDEBUG"
CXXFLAGS="$CXXFLAGS -mcpu=arm926ej-s -mtune=arm926ej-s"
ASFLAGS="$ASFLAGS -mfloat-abi=soft"
LDFLAGS="$LDFLAGS"
_need_memalign=yes
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
@ -1388,8 +1442,6 @@ if test -n "$_host"; then
DEFINES="$DEFINES -DUNIX -DSYSTEM_NOT_SUPPORTING_D_TYPE"
_endian=big
_need_memalign=yes
# FIXME: Please document why 'long' has to be used instead of int
#type_4_byte='long'
_ranlib=m68k-atari-mint-ranlib
_ar="m68k-atari-mint-ar cru"
;;
@ -1436,7 +1488,7 @@ if test -n "$_host"; then
_backend="nds"
_build_hq_scalers="no"
_mt32emu="no"
add_line_to_config_mk 'include $(srcdir)/backends/platform/ds/ds.mk'
_port_mk="backends/platform/ds/ds.mk"
# TODO: Enable more ARM optimizations -- requires testing!
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
@ -1451,8 +1503,6 @@ if test -n "$_host"; then
ppc-amigaos)
_endian=big
_need_memalign=yes
# FIXME: Please document why 'long' has to be used instead of int
#type_4_byte='long'
;;
ps2)
# TODO: complete this
@ -1460,7 +1510,6 @@ if test -n "$_host"; then
_need_memalign=yes
_backend="ps2"
_build_scalers="no"
_build_hq_scalers="no"
_mt32emu="no"
# HACK to enable mad & zlib (they are not properly detected due to linker issues).
# This trick doesn't work for tremor right now, as the PS2 port the resulting library
@ -1488,7 +1537,6 @@ if test -n "$_host"; then
_need_memalign=yes
_backend="psp"
_build_scalers="no"
_build_hq_scalers="no"
_mt32emu="no"
_port_mk="backends/platform/psp/psp.mk"
;;
@ -1502,8 +1550,6 @@ if test -n "$_host"; then
add_line_to_config_mk 'USE_ARM_GFX_ASM = 1'
_backend="samsungtv"
_mt32emu="no"
_build_scalers="yes"
_build_hq_scalers="yes"
_vkeybd="yes"
;;
wii)
@ -1511,7 +1557,6 @@ if test -n "$_host"; then
_need_memalign=yes
_backend="wii"
_build_scalers="no"
_build_hq_scalers="no"
_port_mk="backends/platform/wii/wii.mk"
add_line_to_config_mk 'GAMECUBE = 0'
add_line_to_config_h "#define DEBUG_WII_USBGECKO"
@ -1579,7 +1624,8 @@ int main(int argc, char **argv) {
}
EOF
_need_memalign=yes
cc_check && $TMPO$HOSTEXEEXT && _need_memalign=no
cc_check_no_clean && $TMPO$HOSTEXEEXT && _need_memalign=no
cc_check_clean
;;
esac
echo "$_need_memalign"
@ -1769,7 +1815,7 @@ add_to_config_mk_if_yes "$_mt32emu" 'USE_MT32EMU = 1'
cat > $TMPC << EOF
int main(void) { return 0; }
EOF
cc_check $LDFLAGS $CXXFLAGS -lm && LDFLAGS="$LDFLAGS -lm"
cc_check -lm && LDFLAGS="$LDFLAGS -lm"
#
# Check for Ogg Vorbis
@ -1781,7 +1827,7 @@ if test "$_vorbis" = auto ; then
#include <vorbis/codec.h>
int main(void) { vorbis_packet_blocksize(0,0); return 0; }
EOF
cc_check $LDFLAGS $CXXFLAGS $OGG_CFLAGS $OGG_LIBS $VORBIS_CFLAGS $VORBIS_LIBS \
cc_check $OGG_CFLAGS $OGG_LIBS $VORBIS_CFLAGS $VORBIS_LIBS \
-lvorbisfile -lvorbis -logg && _vorbis=yes
fi
if test "$_vorbis" = yes ; then
@ -1804,7 +1850,7 @@ if test "$_tremor" = auto ; then
#include <tremor/ivorbiscodec.h>
int main(void) { vorbis_info_init(0); return 0; }
EOF
cc_check $LDFLAGS $CXXFLAGS $TREMOR_CFLAGS $TREMOR_LIBS -lvorbisidec && \
cc_check $TREMOR_CFLAGS $TREMOR_LIBS -lvorbisidec && \
_tremor=yes
fi
if test "$_tremor" = yes && test "$_vorbis" = no; then
@ -1832,10 +1878,10 @@ if test "$_flac" = auto ; then
int main(void) { return FLAC__STREAM_SYNC_LEN >> 30; /* guaranteed to be 0 */ }
EOF
if test "$_vorbis" = yes ; then
cc_check $LDFLAGS $CXXFLAGS $FLAC_CFLAGS $FLAC_LIBS $OGG_CFLAGS $OGG_LIBS \
cc_check $FLAC_CFLAGS $FLAC_LIBS $OGG_CFLAGS $OGG_LIBS \
-lFLAC -logg && _flac=yes
else
cc_check $LDFLAGS $CXXFLAGS $FLAC_CFLAGS $FLAC_LIBS \
cc_check $FLAC_CFLAGS $FLAC_LIBS \
-lFLAC && _flac=yes
fi
fi
@ -1863,7 +1909,7 @@ if test "$_mad" = auto ; then
#include <mad.h>
int main(void) { return 0; }
EOF
cc_check $LDFLAGS $CXXFLAGS $MAD_CFLAGS $MAD_LIBS -lmad && _mad=yes
cc_check $MAD_CFLAGS $MAD_LIBS -lmad && _mad=yes
fi
if test "$_mad" = yes ; then
_def_mad='#define USE_MAD'
@ -1885,7 +1931,7 @@ if test "$_alsa" = auto ; then
#include <alsa/asoundlib.h>
int main(void) { return (!(SND_LIB_MAJOR==0 && SND_LIB_MINOR==9)); }
EOF
cc_check $LDFLAGS $CXXFLAGS $ALSA_CFLAGS $ALSA_LIBS -lasound && _alsa=yes
cc_check $ALSA_CFLAGS $ALSA_LIBS -lasound && _alsa=yes
fi
if test "$_alsa" = yes ; then
_def_alsa='#define USE_ALSA'
@ -1901,14 +1947,12 @@ echo "$_alsa"
#
echocheck "zlib"
_zlib=no
cat > $TMPC << EOF
#include <string.h>
#include <zlib.h>
int main(void) { return strcmp(ZLIB_VERSION, zlibVersion()); }
EOF
cc_check $LDFLAGS $CXXFLAGS $ZLIB_CFLAGS $ZLIB_LIBS -lz && _zlib=yes
cc_check $ZLIB_CFLAGS $ZLIB_LIBS -lz && _zlib=yes
if test "$_zlib" = yes ; then
_def_zlib='#define USE_ZLIB'
@ -1932,7 +1976,7 @@ if test "$_fluidsynth" = auto ; then
#include <fluidsynth.h>
int main(void) { return 0; }
EOF
cc_check $LDFLAGS $CXXFLAGS $FLUIDSYNTH_CFLAGS $FLUIDSYNTH_LIBS -lfluidsynth && _fluidsynth=yes
cc_check $FLUIDSYNTH_CFLAGS $FLUIDSYNTH_LIBS -lfluidsynth && _fluidsynth=yes
fi
if test "$_fluidsynth" = yes ; then
_def_fluidsynth='#define USE_FLUIDSYNTH'
@ -1949,7 +1993,6 @@ else
_def_fluidsynth='#undef USE_FLUIDSYNTH'
fi
echo "$_fluidsynth"
rm -rf $TMPC $TMPO$HOSTEXEEXT $TMPO.dSYM
#
# Check for readline if text_console is enabled
@ -1968,14 +2011,13 @@ int main(void) {
char *x = readline("");
}
EOF
cc_check $LDFLAGS $CXXFLAGS $READLINE_CFLAGS $READLINE_LIBS $_READLINE_LIBS && _readline=yes
cc_check $READLINE_CFLAGS $READLINE_LIBS $_READLINE_LIBS && _readline=yes
if test "$_readline" = no ; then
_READLINE_LIBS="-lreadline -ltermcap"
cc_check $LDFLAGS $CXXFLAGS $READLINE_CFLAGS $READLINE_LIBS $_READLINE_LIBS && _readline=yes
cc_check $READLINE_CFLAGS $READLINE_LIBS $_READLINE_LIBS && _readline=yes
fi
fi
echo "$_readline"
rm -rf $TMPC $TMPO$HOSTEXEEXT $TMPO.dSYM
else
_readline=no
echo "skipping (text console disabled)"
@ -2008,11 +2050,24 @@ if test "$_have_x86" = yes ; then
for path_dir in $_nasmpath; do
if test -x "$path_dir/nasm$NATIVEEXEEXT" ; then
NASM="$path_dir/nasm$NATIVEEXEEXT"
NASMFLAGS="-O1 -g"
echo $NASM
break
fi
done
# fallback to the nasm compatible yasm
if test x$NASM = x -o x$NASM = x'"$NASM"'; then
for path_dir in $_nasmpath; do
if test -x "$path_dir/yasm$NATIVEEXEEXT" ; then
NASM="$path_dir/yasm$NATIVEEXEEXT"
NASMFLAGS="-a x86 -m x86"
echo $NASM
break
fi
done
fi
IFS="$ac_save_ifs"
if test x$NASM = x -o x$NASM = x'"$NASM"'; then
@ -2021,16 +2076,16 @@ if test "$_have_x86" = yes ; then
else
case $_host_os in
os2-emx*)
NASMFLAGS="-f aout"
NASMFLAGS="$NASMFLAGS -f aout"
;;
mingw*)
NASMFLAGS="-f win32"
NASMFLAGS="$NASMFLAGS -f win32"
;;
darwin*)
NASMFLAGS="-f macho"
NASMFLAGS="$NASMFLAGS -f macho"
;;
*)
NASMFLAGS="-f elf"
NASMFLAGS="$NASMFLAGS -f elf"
;;
esac
_nasm=yes
@ -2039,7 +2094,7 @@ if test "$_have_x86" = yes ; then
fi
add_to_config_h_if_yes $_nasm '#define USE_NASM'
add_to_config_mk_if_yes $_nasm 'HAVE_NASM = 1'
add_to_config_mk_if_yes $_nasm 'USE_NASM = 1'
#
# Enable vkeybd / keymapper
@ -2054,15 +2109,23 @@ fi
#
# Figure out installation directories
#
test -z "$_bindir" && _bindir="$_prefix/bin"
test -z "$_mandir" && _mandir="$_prefix/share/man"
test -z "$_datadir" && _datadir="$_prefix/share"
test -z "$_libdir" && _libdir="$_prefix/lib"
test "x$prefix" = xNONE && prefix=/usr/local
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
DEFINES="$DEFINES -DDATA_PATH=\\\"$_datadir/residual\\\""
DEFINES="$DEFINES -DDATA_PATH=\\\"$_datadir\\\""
DEFINES="$DEFINES -DPLUGIN_DIRECTORY=\\\"$_libdir/residual\\\""
#
# Set variables for profiling.
# We need to do it here to prevent mess-ups with the tests e.g. on the PSP
#
if test "$_enable_prof" = yes ; then
CXXFLAGS="$CXXFLAGS -pg"
LDFLAGS="$LDFLAGS -pg"
DEFINES="$DEFINES -DENABLE_PROFILING"
fi
echo_n "Backend... "
echo_n "$_backend"
@ -2138,7 +2201,7 @@ case $_backend in
DEFINES="$DEFINES -D__PSP__ -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE -DDISABLE_DOSBOX_OPL"
INCLUDES="$INCLUDES -I$PSPDEV/psp/include/SDL"
LIBS="$LIBS -lpng -lSDL -Wl,-Map,mapfile.txt"
SDLLIBS=$($PSPDEV/psp/bin/sdl-config --libs)
SDLLIBS=`$PSPDEV/psp/bin/sdl-config --libs`
if `echo "$SDLLIBS" | grep ".*-lGL.*" 1>/dev/null 2>&1`
then
@ -2146,12 +2209,11 @@ case $_backend in
fi
;;
samsungtv)
_sdlconfig="arm-SamyGO-linux-gnueabi-sdl-config"
find_sdlconfig
INCLUDES="$INCLUDES `$_sdlconfig --cflags`"
LIBS="$LIBS `$_sdlconfig --libs`"
INCLUDES="$INCLUDES `$_sdlconfig --prefix="$_sdlpath" --cflags`"
LIBS="$LIBS `$_sdlconfig --prefix="$_sdlpath" --libs`"
DEFINES="$DEFINES -DSDL_BACKEND -DSAMSUNGTV"
LDFLAGS="$LDFLAGS -shared -fpic -Wl,-whole-archive"
LDFLAGS="$LDFLAGS -shared -fpic"
MODULES="$MODULES backends/platform/sdl"
;;
sdl)
@ -2198,10 +2260,11 @@ if test "$have_gcc" = yes ; then
;;
esac
add_line_to_config_mk 'HAVE_GCC3 = 1'
add_line_to_config_mk 'CXX_UPDATE_DEP_FLAG = -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP'
add_line_to_config_mk 'CXX_UPDATE_DEP_FLAG = -MMD -MF "$(*D)/$(DEPDIR)/$(*F).d" -MQ "$@" -MP'
fi;
if test "$_cxx_major" -ge "4" && test "$_cxx_minor" -ge "3" ; then
if test "$_cxx_major" -eq 4 && test "$_cxx_minor" -ge 3 || \
test "$_cxx_major" -gt 4 ; then
CXXFLAGS="$CXXFLAGS -Wno-empty-body"
else
CXXFLAGS="$CXXFLAGS -Wconversion"
@ -2370,11 +2433,14 @@ EXEEXT := $HOSTEXEEXT
NASM := $NASM
NASMFLAGS := $NASMFLAGS
PREFIX := $_prefix
BINDIR := $_bindir
MANDIR := $_mandir
DATADIR := $_datadir
LIBDIR := $_libdir
prefix = $prefix
exec_prefix = $exec_prefix
bindir = $bindir
datarootdir = $datarootdir
datadir = $datadir
docdir = $docdir
libdir = $libdir
mandir = $mandir
$_config_mk_data

View file

@ -29,6 +29,7 @@
#include "common/util.h"
#include "common/hash-str.h"
#include "common/file.h"
#include "common/macresman.h"
#include "common/md5.h"
#include "common/config-manager.h"
@ -52,7 +53,7 @@ typedef Common::Array<const ADGameDescription*> ADGameDescList;
* @param platform restrict results to specified platform only
* @return list of ADGameDescription (or subclass) pointers corresponding to matched games
*/
static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &params, Common::Language language, Common::Platform platform, const Common::String extra);
static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &params, Common::Language language, Common::Platform platform, const Common::String &extra);
/**
@ -264,7 +265,7 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine)
// config file.
//
// Fixes bug #1544799
ConfMan.set("autoadded", "true");
ConfMan.setBool("autoadded", true);
warning("No path was provided. Assuming the data files are in the current directory");
}
@ -339,7 +340,7 @@ static void reportUnknown(const Common::FSNode &path, const SizeMD5Map &filesSiz
static ADGameDescList detectGameFilebased(const FileMap &allFiles, const ADParams &params);
static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &params, Common::Language language, Common::Platform platform, const Common::String extra) {
static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &params, Common::Language language, Common::Platform platform, const Common::String &extra) {
FileMap allFiles;
SizeMD5Map filesSizeMD5;
@ -374,10 +375,24 @@ static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &p
for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) {
Common::String fname = fileDesc->fileName;
SizeMD5 tmp;
if (g->flags & ADGF_MACRESFORK) {
Common::MacResManager *macResMan = new Common::MacResManager();
if (macResMan->open(parent, fname)) {
if (!macResMan->getResForkMD5(tmp.md5, params.md5Bytes))
tmp.md5[0] = 0;
tmp.size = macResMan->getResForkSize();
debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5);
filesSizeMD5[fname] = tmp;
}
delete macResMan;
} else {
if (allFiles.contains(fname) && !filesSizeMD5.contains(fname)) {
debug(3, "+ %s", fname.c_str());
SizeMD5 tmp;
Common::File testFile;
if (testFile.open(allFiles[fname])) {
@ -390,11 +405,11 @@ static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &p
}
debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5);
filesSizeMD5[fname] = tmp;
}
}
}
}
ADGameDescList matched;
int maxFilesMatched = 0;

View file

@ -43,9 +43,9 @@ struct ADGameFileDescription {
enum ADGameFlags {
ADGF_NO_FLAGS = 0,
ADGF_MACRESFORK = (1 << 25), // the md5 for this entry will be calculated from the resource fork
ADGF_USEEXTRAASTITLE = (1 << 26), // Extra field value will be used as main game title, not gameid
ADGF_KEEPMATCH = (1 << 27), // this entry is kept even when there are matched
// entries with more files
ADGF_KEEPMATCH = (1 << 27), // this entry is kept even when there are matched entries with more files
ADGF_DROPLANGUAGE = (1 << 28), // don't add language to gameid
ADGF_CD = (1 << 29), // add "-cd" to gameid
ADGF_DEMO = (1 << 30) // add "-demo" to gameid

View file

@ -48,11 +48,6 @@
using GUI::CommandSender;
using GUI::StaticTextWidget;
using GUI::kCloseCmd;
using GUI::WIDGET_ENABLED;
typedef GUI::OptionsDialog GUI_OptionsDialog;
typedef GUI::Dialog GUI_Dialog;
enum {
kSaveCmd = 'SAVE',
@ -129,49 +124,10 @@ void MainMenuDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
close();
break;
case kLoadCmd:
{
Common::String gameId = ConfMan.get("gameid");
const EnginePlugin *plugin = 0;
EngineMan.findGame(gameId, &plugin);
int slot = _loadDialog->runModal(plugin, ConfMan.getActiveDomainName());
if (slot >= 0) {
// FIXME: For now we just ignore the return
// value, which is quite bad since it could
// be a fatal loading error, which renders
// the engine unusable.
_engine->loadGameState(slot);
close();
}
}
load();
break;
case kSaveCmd:
{
Common::String gameId = ConfMan.get("gameid");
const EnginePlugin *plugin = 0;
EngineMan.findGame(gameId, &plugin);
int slot = _saveDialog->runModal(plugin, ConfMan.getActiveDomainName());
if (slot >= 0) {
Common::String result(_saveDialog->getResultString());
if (result.empty()) {
// If the user was lazy and entered no save name, come up with a default name.
char buf[20];
snprintf(buf, 20, "Save %d", slot + 1);
_engine->saveGameState(slot, buf);
} else {
_engine->saveGameState(slot, result.c_str());
}
close();
}
}
save();
break;
case kOptionsCmd:
_optionsDialog->runModal();
@ -236,9 +192,46 @@ void MainMenuDialog::reflowLayout() {
Dialog::reflowLayout();
}
enum {
kOKCmd = 'ok '
};
void MainMenuDialog::save() {
Common::String gameId = ConfMan.get("gameid");
const EnginePlugin *plugin = 0;
EngineMan.findGame(gameId, &plugin);
int slot = _saveDialog->runModal(plugin, ConfMan.getActiveDomainName());
if (slot >= 0) {
Common::String result(_saveDialog->getResultString());
if (result.empty()) {
// If the user was lazy and entered no save name, come up with a default name.
char buf[20];
snprintf(buf, 20, "Save %d", slot + 1);
_engine->saveGameState(slot, buf);
} else {
_engine->saveGameState(slot, result.c_str());
}
close();
}
}
void MainMenuDialog::load() {
Common::String gameId = ConfMan.get("gameid");
const EnginePlugin *plugin = 0;
EngineMan.findGame(gameId, &plugin);
int slot = _loadDialog->runModal(plugin, ConfMan.getActiveDomainName());
if (slot >= 0) {
// FIXME: For now we just ignore the return
// value, which is quite bad since it could
// be a fatal loading error, which renders
// the engine unusable.
_engine->loadGameState(slot);
close();
}
}
enum {
kKeysCmd = 'KEYS'
@ -270,36 +263,8 @@ enum {
// "" as value for the domain, and in fact provide a somewhat better user
// experience at the same time.
ConfigDialog::ConfigDialog(bool subtitleControls)
: GUI::OptionsDialog("", "ScummConfig") {
//
// Sound controllers
//
addVolumeControls(this, "ScummConfig.");
setVolumeSettingsState(true); // could disable controls by GUI options
//
// Subtitle speed and toggle controllers
//
if (subtitleControls) {
// Global talkspeed range of 0-255
addSubtitleControls(this, "ScummConfig.", 255);
setSubtitleSettingsState(true); // could disable controls by GUI options
}
//
// Add the buttons
//
new GUI::ButtonWidget(this, "ScummConfig.Ok", "OK", GUI::OptionsDialog::kOKCmd, 'O');
new GUI::ButtonWidget(this, "ScummConfig.Cancel", "Cancel", kCloseCmd, 'C');
#ifdef SMALL_SCREEN_DEVICE
new GUI::ButtonWidget(this, "ScummConfig.Keys", "Keys", kKeysCmd, 'K');
_keysDialog = NULL;
#endif
: GUI::OptionsDialog("", "") {
// Not in Residual
}
ConfigDialog::~ConfigDialog() {
@ -323,7 +288,7 @@ void ConfigDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data)
#endif
break;
default:
GUI_OptionsDialog::handleCommand (sender, cmd, data);
GUI::OptionsDialog::handleCommand (sender, cmd, data);
}
}

View file

@ -46,6 +46,10 @@ public:
virtual void reflowLayout();
protected:
void save();
void load();
protected:
Engine *_engine;

View file

@ -30,6 +30,10 @@
#endif
#include "engines/engine.h"
#include "engines/dialogs.h"
#include "engines/metaengine.h"
#include "engines/util.h"
#include "common/config-manager.h"
#include "common/debug.h"
#include "common/events.h"
@ -37,12 +41,15 @@
#include "common/timer.h"
#include "common/savefile.h"
#include "common/system.h"
#include "common/str.h"
#include "gui/debugger.h"
#include "gui/message.h"
#include "gui/GuiManager.h"
#include "sound/mixer.h"
#include "engines/dialogs.h"
#include "engines/metaengine.h"
#include "graphics/cursorman.h"
#ifdef _WIN32_WCE
extern bool isSmartphone();
@ -57,7 +64,7 @@ static void defaultOutputFormatter(char *dst, const char *src, size_t dstSize) {
if (g_engine) {
g_engine->errorString(src, dst, dstSize);
} else {
strncpy(dst, src, dstSize);
Common::strlcpy(dst, src, dstSize);
}
}
@ -85,7 +92,6 @@ Engine::Engine(OSystem *syst)
_eventMan(_system->getEventManager()),
_saveFileMan(_system->getSavefileManager()),
_targetName(ConfMan.getActiveDomainName()),
_gameDataDir(ConfMan.get("path")),
_pauseLevel(0),
_mainMenuDialog(NULL) {
@ -94,13 +100,14 @@ Engine::Engine(OSystem *syst)
Common::setErrorOutputFormatter(defaultOutputFormatter);
Common::setErrorHandler(defaultErrorHandler);
// FIXME: Get rid of the following again. It is only here temporarily.
// We really should never run with a non-working Mixer, so ought to handle
// this at a much earlier stage. If we *really* want to support systems
// without a working mixer, then we need more work. E.g. we could modify the
// Mixer to immediately drop any streams passed to it. This way, at least
// we don't crash because heaps of (sound) memory get allocated but never
// freed. Of course, there still would be problems with many games...
// FIXME: Get rid of the following again. It is only here
// temporarily. We really should never run with a non-working Mixer,
// so ought to handle this at a much earlier stage. If we *really*
// want to support systems without a working mixer, then we need
// more work. E.g. we could modify the Mixer to immediately drop any
// streams passed to it. This way, at least we don't crash because
// heaps of (sound) memory get allocated but never freed. Of course,
// there still would be problems with many games...
if (!_mixer->isReady())
warning("Sound initialization failed. This may cause severe problems in some games.");
}
@ -151,12 +158,14 @@ void Engine::checkCD() {
char buffer[MAXPATHLEN];
int i;
if (_gameDataDir.getPath().empty()) {
const Common::FSNode gameDataDir(ConfMan.get("path"));
if (gameDataDir.getPath().empty()) {
// That's it! I give up!
if (getcwd(buffer, MAXPATHLEN) == NULL)
return;
} else
strncpy(buffer, _gameDataDir.getPath().c_str(), MAXPATHLEN);
Common::strlcpy(buffer, gameDataDir.getPath().c_str(), sizeof(buffer));
for (i = 0; i < MAXPATHLEN - 1; i++) {
if (buffer[i] == '\\')
@ -195,9 +204,7 @@ bool Engine::shouldPerformAutoSave(int lastSaveTime) {
}
void Engine::errorString(const char *buf1, char *buf2, int size) {
strncpy(buf2, buf1, size);
if (size > 0)
buf2[size-1] = '\0';
Common::strlcpy(buf2, buf1, size);
}
void Engine::pauseEngine(bool pause) {

View file

@ -27,9 +27,7 @@
#include "common/sys.h"
#include "common/error.h"
#include "common/fs.h"
#include "common/str.h"
#include "graphics/pixelformat.h"
class OSystem;
@ -45,6 +43,7 @@ namespace GUI {
class Debugger;
class Dialog;
}
/**
* Initializes graphics and shows error message.
*/
@ -66,8 +65,6 @@ protected:
const Common::String _targetName; // target name for saves
const Common::FSNode _gameDataDir; // FIXME: Get rid of this
private:
/**
* The pause level, 0 means 'running', a positive value indicates

View file

@ -25,7 +25,6 @@
#include "engines/game.h"
#include "base/plugins.h"
#include "graphics/surface.h"
const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const PlainGameDescriptor *list) {
@ -103,54 +102,3 @@ void GameDescriptor::updateDesc(const char *extra) {
setVal("description", descr);
}
}
void SaveStateDescriptor::setThumbnail(Graphics::Surface *t) {
if (_thumbnail.get() == t)
return;
_thumbnail = Common::SharedPtr<Graphics::Surface>(t, Graphics::SharedPtrSurfaceDeleter());
}
bool SaveStateDescriptor::getBool(const Common::String &key) const {
if (contains(key)) {
Common::String value = getVal(key);
if (value.equalsIgnoreCase("true") ||
value.equalsIgnoreCase("yes") ||
value.equals("1"))
return true;
if (value.equalsIgnoreCase("false") ||
value.equalsIgnoreCase("no") ||
value.equals("0"))
return false;
error("SaveStateDescriptor: %s '%s' has unknown value '%s' for boolean '%s'",
save_slot().c_str(), description().c_str(), value.c_str(), key.c_str());
}
return false;
}
void SaveStateDescriptor::setDeletableFlag(bool state) {
setVal("is_deletable", state ? "true" : "false");
}
void SaveStateDescriptor::setWriteProtectedFlag(bool state) {
setVal("is_write_protected", state ? "true" : "false");
}
void SaveStateDescriptor::setSaveDate(int year, int month, int day) {
char buffer[32];
snprintf(buffer, 32, "%.2d.%.2d.%.4d", day, month, year);
setVal("save_date", buffer);
}
void SaveStateDescriptor::setSaveTime(int hour, int min) {
char buffer[32];
snprintf(buffer, 32, "%.2d:%.2d", hour, min);
setVal("save_time", buffer);
}
void SaveStateDescriptor::setPlayTime(int hours, int minutes) {
char buffer[32];
snprintf(buffer, 32, "%.2d:%.2d", hours, minutes);
setVal("play_time", buffer);
}

View file

@ -26,14 +26,9 @@
#ifndef ENGINES_GAME_H
#define ENGINES_GAME_H
#include "common/str.h"
#include "common/array.h"
#include "common/hash-str.h"
#include "common/ptr.h"
namespace Graphics {
struct Surface;
}
#include "engines/savestate.h" // TODO: Push this #include out to .cpp files needing it
/**
* A simple structure used to map gameids (like "monkey", "sword1", ...) to
@ -114,101 +109,4 @@ public:
}
};
/**
* A hashmap describing details about a given save state.
* TODO
* Guaranteed to contain save_slot and description values.
* Additional ideas: Playtime, creation date, thumbnail, ...
*/
class SaveStateDescriptor : public Common::StringMap {
protected:
Common::SharedPtr<Graphics::Surface> _thumbnail; // can be 0
public:
SaveStateDescriptor() : _thumbnail() {
setVal("save_slot", "-1"); // FIXME: default to 0 (first slot) or to -1 (invalid slot) ?
setVal("description", "");
}
SaveStateDescriptor(int s, const Common::String &d) : _thumbnail() {
char buf[16];
sprintf(buf, "%d", s);
setVal("save_slot", buf);
setVal("description", d);
}
SaveStateDescriptor(const Common::String &s, const Common::String &d) : _thumbnail() {
setVal("save_slot", s);
setVal("description", d);
}
/** The saveslot id, as it would be passed to the "-x" command line switch. */
Common::String &save_slot() { return getVal("save_slot"); }
/** The saveslot id, as it would be passed to the "-x" command line switch (read-only variant). */
const Common::String &save_slot() const { return getVal("save_slot"); }
/** A human readable description of the save state. */
Common::String &description() { return getVal("description"); }
/** A human readable description of the save state (read-only variant). */
const Common::String &description() const { return getVal("description"); }
/** Optional entries only included when querying via MetaEngine::querySaveMetaInfo */
/**
* Returns the value of a given key as boolean.
* It accepts 'true', 'yes' and '1' for true and
* 'false', 'no' and '0' for false.
* (FIXME:) On unknown value it errors out ScummVM.
* On unknown key it returns false as default.
*/
bool getBool(const Common::String &key) const;
/**
* Sets the 'is_deletable' key, which indicates if the
* given savestate is safe for deletion.
*/
void setDeletableFlag(bool state);
/**
* Sets the 'is_write_protected' key, which indicates if the
* given savestate can be overwritten or not
*/
void setWriteProtectedFlag(bool state);
/**
* Return a thumbnail graphics surface representing the savestate visually.
* This is usually a scaled down version of the game graphics. The size
* should be either 160x100 or 160x120 pixels, depending on the aspect
* ratio of the game. If another ratio is required, contact the core team.
*/
const Graphics::Surface *getThumbnail() const { return _thumbnail.get(); }
/**
* Set a thumbnail graphics surface representing the savestate visually.
* Ownership of the surface is transferred to the SaveStateDescriptor.
* Hence the caller must not delete the surface.
*/
void setThumbnail(Graphics::Surface *t);
/**
* Sets the 'save_date' key properly, based on the given values.
*/
void setSaveDate(int year, int month, int day);
/**
* Sets the 'save_time' key properly, based on the given values.
*/
void setSaveTime(int hour, int min);
/**
* Sets the 'play_time' key properly, based on the given values.
*/
void setPlayTime(int hours, int minutes);
};
/** List of savestates. */
typedef Common::Array<SaveStateDescriptor> SaveStateList;
#endif

View file

@ -33,6 +33,7 @@
#include "common/archive.h"
#include "common/events.h"
#include "common/file.h"
#include "common/fs.h"
#include "common/config-manager.h"
#include "engines/engine.h"
@ -238,7 +239,7 @@ GrimEngine *g_grim = NULL;
GfxBase *g_driver = NULL;
int g_imuseState = -1;
extern Common::StringList::const_iterator g_filesiter;
extern Common::StringArray::const_iterator g_filesiter;
// hack for access current upated actor to allow access position of actor to sound costume component
Actor *g_currentUpdatedActor = NULL;
@ -319,7 +320,8 @@ GrimEngine::GrimEngine(OSystem *syst, int gameFlags, GrimGameType gameType) :
blastTextDefaults.justify = TextObject::LJUSTIFY;
// Add 'movies' subdirectory for the demo
SearchMan.addSubDirectoryMatching(_gameDataDir, "movies");
const Common::FSNode gameDataDir(ConfMan.get("path"));
SearchMan.addSubDirectoryMatching(gameDataDir, "movies");
}
GrimEngine::~GrimEngine() {

View file

@ -145,7 +145,7 @@ void Imuse::restoreState(SaveGame *savedState) {
track->mixerFlags |= kFlagStereo | kFlagReverseStereo;
track->stream = Audio::makeQueuingAudioStream(freq, (track->mixerFlags & kFlagStereo) != 0);
g_system->getMixer()->playInputStream(track->getType(), &track->handle, track->stream, -1, track->getVol(),
g_system->getMixer()->playStream(track->getType(), &track->handle, track->stream, -1, track->getVol(),
track->getPan(), DisposeAfterUse::YES, false,
(track->mixerFlags & kFlagReverseStereo) != 0);
g_system->getMixer()->pauseHandle(track->handle, true);

View file

@ -140,7 +140,7 @@ bool Imuse::startSound(const char *soundName, int volGroupId, int hookId, int vo
}
track->stream = Audio::makeQueuingAudioStream(freq, track->mixerFlags & kFlagStereo);
g_system->getMixer()->playInputStream(track->getType(), &track->handle, track->stream, -1,
g_system->getMixer()->playStream(track->getType(), &track->handle, track->stream, -1,
track->getVol(), track->getPan(), DisposeAfterUse::YES,
false, (track->mixerFlags & kFlagReverseStereo) != 0);
track->used = true;
@ -379,7 +379,7 @@ Track *Imuse::cloneToFadeOutTrack(Track *track, int fadeDelay) {
// Create an appendable output buffer
fadeTrack->stream = Audio::makeQueuingAudioStream(_sound->getFreq(fadeTrack->soundDesc), track->mixerFlags & kFlagStereo);
g_system->getMixer()->playInputStream(track->getType(), &fadeTrack->handle, fadeTrack->stream, -1, fadeTrack->getVol(),
g_system->getMixer()->playStream(track->getType(), &fadeTrack->handle, fadeTrack->stream, -1, fadeTrack->getVol(),
fadeTrack->getPan(), DisposeAfterUse::YES, false,
(track->mixerFlags & kFlagReverseStereo) != 0);
fadeTrack->used = true;

View file

@ -48,8 +48,8 @@ namespace Grim {
extern Imuse *g_imuse;
Common::StringList g_listfiles;
Common::StringList::const_iterator g_filesiter;
Common::StringArray g_listfiles;
Common::StringArray::const_iterator g_filesiter;
int refSystemTable;
static int refTypeOverride;

View file

@ -139,7 +139,7 @@ void Smush::handleWave(const byte *src, uint32 size) {
if (!_stream) {
_stream = Audio::makeQueuingAudioStream(_freq, (_channels == 2));
g_system->getMixer()->playInputStream(Audio::Mixer::kMusicSoundType, &_soundHandle, _stream);
g_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, _stream);
}
if (g_system->getMixer()->isReady()) {
_stream->queueBuffer((byte *)dst, size * _channels * 2, DisposeAfterUse::YES, flags);
@ -304,7 +304,7 @@ void Smush::handleIACT(const byte *src, int32 size) {
if (!_stream) {
_stream = Audio::makeQueuingAudioStream(22050, true);
g_system->getMixer()->playInputStream(Audio::Mixer::kSFXSoundType, &_soundHandle, _stream);
g_system->getMixer()->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, _stream);
}
_stream->queueBuffer(output_data, 0x1000, DisposeAfterUse::YES, Audio::FLAG_STEREO | Audio::FLAG_16BITS);

View file

@ -29,6 +29,8 @@
#include "common/error.h"
#include "engines/game.h"
#include "engines/savestate.h"
#include "base/plugins.h"
class Engine;
@ -124,7 +126,7 @@ public:
* @param target name of a config manager target
* @param slot slot number of the save state to be removed
*/
virtual void removeSaveState(const char *target, int slot) const {};
virtual void removeSaveState(const char *target, int slot) const {}
/**
* Returns meta infos from the specified save state.

View file

@ -4,7 +4,8 @@ MODULE_OBJS := \
advancedDetector.o \
dialogs.o \
engine.o \
game.o
game.o \
savestate.o
# Include common rules
include $(srcdir)/rules.mk

71
engines/savestate.cpp Normal file
View file

@ -0,0 +1,71 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#include "engines/savestate.h"
#include "graphics/surface.h"
void SaveStateDescriptor::setThumbnail(Graphics::Surface *t) {
if (_thumbnail.get() == t)
return;
_thumbnail = Common::SharedPtr<Graphics::Surface>(t, Graphics::SharedPtrSurfaceDeleter());
}
bool SaveStateDescriptor::getBool(const Common::String &key) const {
if (contains(key)) {
const Common::String value = getVal(key);
bool valueAsBool;
if (Common::parseBool(value, valueAsBool))
return valueAsBool;
error("SaveStateDescriptor: %s '%s' has unknown value '%s' for boolean '%s'",
save_slot().c_str(), description().c_str(), value.c_str(), key.c_str());
}
return false;
}
void SaveStateDescriptor::setDeletableFlag(bool state) {
setVal("is_deletable", state ? "true" : "false");
}
void SaveStateDescriptor::setWriteProtectedFlag(bool state) {
setVal("is_write_protected", state ? "true" : "false");
}
void SaveStateDescriptor::setSaveDate(int year, int month, int day) {
char buffer[32];
snprintf(buffer, 32, "%.2d.%.2d.%.4d", day, month, year);
setVal("save_date", buffer);
}
void SaveStateDescriptor::setSaveTime(int hour, int min) {
char buffer[32];
snprintf(buffer, 32, "%.2d:%.2d", hour, min);
setVal("save_time", buffer);
}
void SaveStateDescriptor::setPlayTime(int hours, int minutes) {
char buffer[32];
snprintf(buffer, 32, "%.2d:%.2d", hours, minutes);
setVal("play_time", buffer);
}

135
engines/savestate.h Normal file
View file

@ -0,0 +1,135 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#ifndef ENGINES_SAVESTATE_H
#define ENGINES_SAVESTATE_H
#include "common/array.h"
#include "common/hash-str.h"
#include "common/ptr.h"
namespace Graphics {
struct Surface;
}
/**
* A hashmap describing details about a given save state.
* TODO
* Guaranteed to contain save_slot and description values.
* Additional ideas: Playtime, creation date, thumbnail, ...
*/
class SaveStateDescriptor : public Common::StringMap {
protected:
Common::SharedPtr<Graphics::Surface> _thumbnail; // can be 0
public:
SaveStateDescriptor() : _thumbnail() {
setVal("save_slot", "-1"); // FIXME: default to 0 (first slot) or to -1 (invalid slot) ?
setVal("description", "");
}
SaveStateDescriptor(int s, const Common::String &d) : _thumbnail() {
char buf[16];
sprintf(buf, "%d", s);
setVal("save_slot", buf);
setVal("description", d);
}
SaveStateDescriptor(const Common::String &s, const Common::String &d) : _thumbnail() {
setVal("save_slot", s);
setVal("description", d);
}
/** The saveslot id, as it would be passed to the "-x" command line switch. */
Common::String &save_slot() { return getVal("save_slot"); }
/** The saveslot id, as it would be passed to the "-x" command line switch (read-only variant). */
const Common::String &save_slot() const { return getVal("save_slot"); }
/** A human readable description of the save state. */
Common::String &description() { return getVal("description"); }
/** A human readable description of the save state (read-only variant). */
const Common::String &description() const { return getVal("description"); }
/** Optional entries only included when querying via MetaEngine::querySaveMetaInfo */
/**
* Returns the value of a given key as boolean.
* It accepts 'true', 'yes' and '1' for true and
* 'false', 'no' and '0' for false.
* (FIXME:) On unknown value it errors out ScummVM.
* On unknown key it returns false as default.
*/
bool getBool(const Common::String &key) const;
/**
* Sets the 'is_deletable' key, which indicates if the
* given savestate is safe for deletion.
*/
void setDeletableFlag(bool state);
/**
* Sets the 'is_write_protected' key, which indicates if the
* given savestate can be overwritten or not
*/
void setWriteProtectedFlag(bool state);
/**
* Return a thumbnail graphics surface representing the savestate visually.
* This is usually a scaled down version of the game graphics. The size
* should be either 160x100 or 160x120 pixels, depending on the aspect
* ratio of the game. If another ratio is required, contact the core team.
*/
const Graphics::Surface *getThumbnail() const { return _thumbnail.get(); }
/**
* Set a thumbnail graphics surface representing the savestate visually.
* Ownership of the surface is transferred to the SaveStateDescriptor.
* Hence the caller must not delete the surface.
*/
void setThumbnail(Graphics::Surface *t);
/**
* Sets the 'save_date' key properly, based on the given values.
*/
void setSaveDate(int year, int month, int day);
/**
* Sets the 'save_time' key properly, based on the given values.
*/
void setSaveTime(int hour, int min);
/**
* Sets the 'play_time' key properly, based on the given values.
*/
void setPlayTime(int hours, int minutes);
};
/** List of savestates. */
typedef Common::Array<SaveStateDescriptor> SaveStateList;
#endif

54
engines/util.h Normal file
View file

@ -0,0 +1,54 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*/
#ifndef ENGINES_UTIL_H
#define ENGINES_UTIL_H
#include "common/sys.h"
#include "common/list.h"
#include "graphics/pixelformat.h"
/**
* Setup the backend's graphics mode.
*/
void initCommonGFX(bool defaultTo1XScaler);
/**
* Setup the backend's screen size and graphics mode.
*
* Shows an various warnings on certain backend graphics
* transaction failures (aspect switch, fullscreen switch, etc.).
*
* Errors out when backend is not able to switch to the specified
* mode.
*
* Defaults to 256 color paletted mode if no graphics format is provided.
* Uses the backend's preferred format if graphics format pointer is NULL.
* Finds the best compatible format if a list of graphics formats is provided.
*/
void initGraphics(int width, int height, bool defaultTo1xScaler);
void initGraphics(int width, int height, bool defaultTo1xScaler, const Graphics::PixelFormat *format);
void initGraphics(int width, int height, bool defaultTo1xScaler, const Common::List<Graphics::PixelFormat> &formatList);
#endif

View file

@ -27,7 +27,7 @@
#include "common/system.h"
#include "common/stack.h"
DECLARE_SINGLETON(Graphics::CursorManager);
DECLARE_SINGLETON(Graphics::CursorManager)
namespace Graphics {

View file

@ -29,9 +29,6 @@
#include "common/stack.h"
#include "common/singleton.h"
#include "graphics/pixelformat.h"
//#ifdef USE_RGB_COLOR
//#include "common/system.h"
//#endif
namespace Graphics {

View file

@ -864,10 +864,10 @@ void Font::drawString(Surface *dst, const Common::String &sOld, int x, int y, in
struct WordWrapper {
Common::StringList &lines;
Common::Array<Common::String> &lines;
int actualMaxLineWidth;
WordWrapper(Common::StringList &l) : lines(l), actualMaxLineWidth(0) {
WordWrapper(Common::Array<Common::String> &l) : lines(l), actualMaxLineWidth(0) {
}
void add(Common::String &line, int &w) {
@ -881,7 +881,7 @@ struct WordWrapper {
}
};
int Font::wordWrapText(const Common::String &str, int maxWidth, Common::StringList &lines) const {
int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines) const {
WordWrapper wrapper(lines);
Common::String line;
Common::String tmpStr;

View file

@ -26,6 +26,7 @@
#define GRAPHICS_FONT_H
#include "common/str.h"
#include "common/array.h"
#include "graphics/surface.h"
namespace Common {
@ -78,7 +79,7 @@ public:
* @param lines the string list to which the text lines from str are appended
* @return the maximal width of any of the lines added to lines
*/
int wordWrapText(const Common::String &str, int maxWidth, Common::StringList &lines) const;
int wordWrapText(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines) const;
};

View file

@ -25,7 +25,7 @@
#include "graphics/fontman.h"
//#include "gui/consolefont.h"
DECLARE_SINGLETON(Graphics::FontManager);
DECLARE_SINGLETON(Graphics::FontManager)
namespace Graphics {

View file

@ -25,7 +25,6 @@
#include "graphics/imagedec.h"
#include "common/file.h"
//#include "common/system.h"
namespace Graphics {
//

View file

@ -30,22 +30,16 @@
#include "graphics/colormasks.h"
#define kHighBitsMask Graphics::ColorMasks<bitFormat>::kHighBitsMask
#define kLowBitsMask Graphics::ColorMasks<bitFormat>::kLowBitsMask
#define qhighBits Graphics::ColorMasks<bitFormat>::qhighBits
#define qlowBits Graphics::ColorMasks<bitFormat>::qlowBits
#define redblueMask Graphics::ColorMasks<bitFormat>::kRedBlueMask
#define greenMask Graphics::ColorMasks<bitFormat>::kGreenMask
/**
* Interpolate two 16 bit pixel *pairs* at once with equal weights 1.
* In particular, p1 and p2 can contain two pixels each in the upper
* and lower halves.
*/
template<int bitFormat>
template<typename ColorMask>
static inline uint32 interpolate32_1_1(uint32 p1, uint32 p2) {
return (((p1 & kHighBitsMask) >> 1) + ((p2 & kHighBitsMask) >> 1) + (p1 & p2 & kLowBitsMask));
return (((p1 & ColorMask::kHighBitsMask) >> 1) +
((p2 & ColorMask::kHighBitsMask) >> 1) +
(p1 & p2 & ColorMask::kLowBitsMask));
}
/**
@ -53,12 +47,12 @@ static inline uint32 interpolate32_1_1(uint32 p1, uint32 p2) {
* In particular, p1 and p2 can contain two pixels/each in the upper
* and lower halves.
*/
template<int bitFormat>
template<typename ColorMask>
static inline uint32 interpolate32_3_1(uint32 p1, uint32 p2) {
register uint32 x = ((p1 & qhighBits) >> 2) * 3 + ((p2 & qhighBits) >> 2);
register uint32 y = ((p1 & qlowBits) * 3 + (p2 & qlowBits)) >> 2;
register uint32 x = ((p1 & ColorMask::qhighBits) >> 2) * 3 + ((p2 & ColorMask::qhighBits) >> 2);
register uint32 y = ((p1 & ColorMask::qlowBits) * 3 + (p2 & ColorMask::qlowBits)) >> 2;
y &= qlowBits;
y &= ColorMask::qlowBits;
return x + y;
}
@ -217,22 +211,4 @@ static inline bool diffYUV(int yuv1, int yuv2) {
*/
}
/**
* 16bit RGB to YUV conversion table. This table is setup by InitLUT().
* Used by the hq scaler family.
*/
extern "C" uint32 *RGBtoYUV;
/** Auxiliary macro to simplify creating those template function wrappers. */
#define MAKE_WRAPPER(FUNC) \
void FUNC(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) { \
if (gBitFormat == 565) \
FUNC ## Template<565>(srcPtr, srcPitch, dstPtr, dstPitch, width, height); \
else \
FUNC ## Template<555>(srcPtr, srcPitch, dstPtr, dstPitch, width, height); \
}
/** Specifies the currently active 16bit pixel format, 555 or 565. */
extern int gBitFormat;
#endif

View file

@ -135,23 +135,30 @@ void Surface::fillRect(Common::Rect r, uint32 color) {
return;
int width = r.width();
int lineLen = width;
int height = r.height();
// int i;
bool useMemset = true;
if (bytesPerPixel == 1) {
if (bytesPerPixel == 2) {
lineLen *= 2;
if ((uint16)color != ((color & 0xff) | (color & 0xff) << 8))
useMemset = false;
} else if (bytesPerPixel != 1) {
error("Surface::fillRect: bytesPerPixel must be 1 or 2");
}
if (useMemset) {
byte *ptr = (byte *)getBasePtr(r.left, r.top);
while (height--) {
memset(ptr, (byte)color, width);
memset(ptr, (byte)color, lineLen);
ptr += pitch;
}
} else if (bytesPerPixel == 2) {
} else {
uint16 *ptr = (uint16 *)getBasePtr(r.left, r.top);
while (height--) {
Common::set_to(ptr, ptr + width, (uint16)color);
ptr += pitch/2;
}
} else {
error("Surface::fillRect: bytesPerPixel must be 1 or 2");
}
}

View file

@ -37,7 +37,7 @@
#include "graphics/cursorman.h"
DECLARE_SINGLETON(GUI::GuiManager);
DECLARE_SINGLETON(GUI::GuiManager)
namespace GUI {
@ -54,6 +54,8 @@ GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled),
_system = g_system;
_lastScreenChangeID = _system->getScreenChangeID();
_width = _system->getOverlayWidth();
_height = _system->getOverlayHeight();
// Clear the cursor
memset(_cursor, 0xFF, sizeof(_cursor));
@ -440,7 +442,7 @@ void GuiManager::animateCursor() {
bool GuiManager::checkScreenChange() {
int tmpScreenChangeID = _system->getScreenChangeID();
if (_lastScreenChangeID != tmpScreenChangeID) {
GuiManager::screenChange();
screenChange();
return true;
}
return false;
@ -448,6 +450,8 @@ bool GuiManager::checkScreenChange() {
void GuiManager::screenChange() {
_lastScreenChangeID = _system->getScreenChangeID();
_width = _system->getOverlayWidth();
_height = _system->getOverlayHeight();
// reinit the whole theme
_theme->refresh();

View file

@ -76,6 +76,9 @@ public:
ThemeEval *xmlEval() { return _theme->getEvaluator(); }
int getWidth() const { return _width; }
int getHeight() const { return _height; }
const Graphics::Font &getFont(ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return *(_theme->getFont(style)); }
int getFontHeight(ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getFontHeight(style); }
int getStringWidth(const Common::String &str, ThemeEngine::FontStyle style = ThemeEngine::kFontStyleBold) const { return _theme->getStringWidth(str, style); }
@ -104,6 +107,7 @@ protected:
// bool _needRedraw;
RedrawStatus _redrawStatus;
int _lastScreenChangeID;
int _width, _height;
DialogStack _dialogStack;
bool _stateIsSaved;

View file

@ -34,8 +34,7 @@
namespace GUI {
enum {
kMapCmd = 'map ',
kOKCmd = 'ok '
kMapCmd = 'map '
};
KeysDialog::KeysDialog(const Common::String &title)
@ -55,7 +54,7 @@ KeysDialog::KeysDialog(const Common::String &title)
_keyMapping->setFlags(WIDGET_CLEARBG);
// Get actions names
Common::StringList l;
ListWidget::StringArray l;
for (int i = 0; i < Actions::Instance()->size(); i++)
l.push_back(Actions::Instance()->actionName((ActionType)i));

View file

@ -25,6 +25,7 @@
#include "common/system.h"
#include "common/events.h"
#include "common/frac.h"
#include "common/tokenizer.h"
#include "gui/ListWidget.h"
#include "gui/ScrollBarWidget.h"
@ -152,7 +153,7 @@ ThemeEngine::FontColor ListWidget::getSelectionColor() const {
return _listColors[_listIndex[_selectedItem]];
}
void ListWidget::setList(const StringList &list, const ColorList *colors) {
void ListWidget::setList(const StringArray &list, const ColorList *colors) {
if (_editMode && _caretVisible)
drawCaret(true);
@ -286,11 +287,11 @@ bool ListWidget::handleKeyDown(Common::KeyState state) {
bool dirty = false;
int oldSelectedItem = _selectedItem;
if (!_editMode && isprint((unsigned char)state.ascii)) {
if (!_editMode && state.keycode <= Common::KEYCODE_z && isprint((unsigned char)state.ascii)) {
// Quick selection mode: Go to first list item starting with this key
// (or a substring accumulated from the last couple key presses).
// Only works in a useful fashion if the list entries are sorted.
uint32 time = getMillis();
uint32 time = g_system->getMillis();
if (_quickSelectTime < time) {
_quickSelectStr = (char)state.ascii;
} else {
@ -306,7 +307,7 @@ bool ListWidget::handleKeyDown(Common::KeyState state) {
int newSelectedItem = 0;
int bestMatch = 0;
bool stop;
for (StringList::const_iterator i = _list.begin(); i != _list.end(); ++i) {
for (StringArray::const_iterator i = _list.begin(); i != _list.end(); ++i) {
const int match = matchingCharsIgnoringCase(i->c_str(), _quickSelectStr.c_str(), stop);
if (match > bestMatch || stop) {
_selectedItem = newSelectedItem;
@ -339,8 +340,18 @@ bool ListWidget::handleKeyDown(Common::KeyState state) {
sendCommand(kListItemActivatedCmd, _selectedItem);
}
break;
case Common::KEYCODE_BACKSPACE:
// Keypad & special keys
// - if num lock is set, we do not handle the keypress
// - if num lock is not set, we either fall down to the special key case
// or ignore the key press for 0, 4, 5 and 6
case Common::KEYCODE_KP_PERIOD:
if (state.flags & Common::KBD_NUM) {
handled = false;
break;
}
case Common::KEYCODE_BACKSPACE:
case Common::KEYCODE_DELETE:
if (_selectedItem >= 0) {
if (_editable) {
@ -350,30 +361,68 @@ bool ListWidget::handleKeyDown(Common::KeyState state) {
}
}
break;
case Common::KEYCODE_UP:
if (_selectedItem > 0)
_selectedItem--;
case Common::KEYCODE_KP1:
if (state.flags & Common::KBD_NUM) {
handled = false;
break;
}
case Common::KEYCODE_END:
_selectedItem = _list.size() - 1;
break;
case Common::KEYCODE_KP2:
if (state.flags & Common::KBD_NUM) {
handled = false;
break;
}
case Common::KEYCODE_DOWN:
if (_selectedItem < (int)_list.size() - 1)
_selectedItem++;
break;
case Common::KEYCODE_PAGEUP:
_selectedItem -= _entriesPerPage - 1;
if (_selectedItem < 0)
_selectedItem = 0;
case Common::KEYCODE_KP3:
if (state.flags & Common::KBD_NUM) {
handled = false;
break;
}
case Common::KEYCODE_PAGEDOWN:
_selectedItem += _entriesPerPage - 1;
if (_selectedItem >= (int)_list.size() )
_selectedItem = _list.size() - 1;
break;
case Common::KEYCODE_KP7:
if (state.flags & Common::KBD_NUM) {
handled = false;
break;
}
case Common::KEYCODE_HOME:
_selectedItem = 0;
break;
case Common::KEYCODE_END:
_selectedItem = _list.size() - 1;
case Common::KEYCODE_KP8:
if (state.flags & Common::KBD_NUM) {
handled = false;
break;
}
case Common::KEYCODE_UP:
if (_selectedItem > 0)
_selectedItem--;
break;
case Common::KEYCODE_KP9:
if (state.flags & Common::KBD_NUM) {
handled = false;
break;
}
case Common::KEYCODE_PAGEUP:
_selectedItem -= _entriesPerPage - 1;
if (_selectedItem < 0)
_selectedItem = 0;
break;
default:
handled = false;
}
@ -644,7 +693,7 @@ void ListWidget::setFilter(const String &filter, bool redraw) {
_list.clear();
_listIndex.clear();
for (StringList::iterator i = _dataList.begin(); i != _dataList.end(); ++i, ++n) {
for (StringArray::iterator i = _dataList.begin(); i != _dataList.end(); ++i, ++n) {
tmp = *i;
tmp.toLowercase();
bool matches = true;

View file

@ -52,11 +52,11 @@ enum {
class ListWidget : public EditableWidget {
public:
typedef Common::String String;
typedef Common::StringList StringList;
typedef Common::Array<Common::String> StringArray;
typedef Common::Array<ThemeEngine::FontColor> ColorList;
protected:
StringList _list;
StringList _dataList;
StringArray _list;
StringArray _dataList;
ColorList _listColors;
Common::Array<int> _listIndex;
bool _editable;
@ -93,8 +93,8 @@ public:
virtual Widget *findWidget(int x, int y);
void setList(const StringList &list, const ColorList *colors = 0);
const StringList &getList() const { return _dataList; }
void setList(const StringArray &list, const ColorList *colors = 0);
const StringArray &getList() const { return _dataList; }
void append(const String &s, ThemeEngine::FontColor color = ThemeEngine::kFontColorNormal);

View file

@ -170,7 +170,7 @@ void PopUpDialog::drawDialog() {
if (_openTime == 0) {
// Time the popup was opened
_openTime = getMillis();
_openTime = g_system->getMillis();
}
}
@ -178,7 +178,7 @@ void PopUpDialog::handleMouseUp(int x, int y, int button, int clickCount) {
// Mouse was released. If it wasn't moved much since the original mouse down,
// let the popup stay open. If it did move, assume the user made his selection.
int dist = (_clickX - x) * (_clickX - x) + (_clickY - y) * (_clickY - y);
if (dist > 3 * 3 || getMillis() - _openTime > 300) {
if (dist > 3 * 3 || g_system->getMillis() - _openTime > 300) {
setResult(_selection);
close();
}
@ -222,23 +222,45 @@ void PopUpDialog::handleKeyDown(Common::KeyState state) {
return;
switch (state.keycode) {
case Common::KEYCODE_RETURN:
case Common::KEYCODE_KP_ENTER:
setResult(_selection);
close();
break;
case Common::KEYCODE_UP:
moveUp();
break;
case Common::KEYCODE_DOWN:
moveDown();
break;
case Common::KEYCODE_HOME:
setSelection(0);
// Keypad & special keys
// - if num lock is set, we ignore the keypress
// - if num lock is not set, we fall down to the special key case
case Common::KEYCODE_KP1:
if (state.flags & Common::KBD_NUM)
break;
case Common::KEYCODE_END:
setSelection(_popUpBoss->_entries.size()-1);
break;
case Common::KEYCODE_KP2:
if (state.flags & Common::KBD_NUM)
break;
case Common::KEYCODE_DOWN:
moveDown();
break;
case Common::KEYCODE_KP7:
if (state.flags & Common::KBD_NUM)
break;
case Common::KEYCODE_HOME:
setSelection(0);
break;
case Common::KEYCODE_KP8:
if (state.flags & Common::KBD_NUM)
break;
case Common::KEYCODE_UP:
moveUp();
break;
default:
break;
}

View file

@ -23,13 +23,13 @@
*
*/
#include "common/util.h"
#include "common/system.h"
#include "common/events.h"
#include "common/config-manager.h"
#include "common/file.h"
#include "common/fs.h"
#include "common/unzip.h"
#include "common/tokenizer.h"
#include "graphics/colormasks.h"
#include "graphics/cursorman.h"
@ -393,11 +393,9 @@ bool ThemeEngine::init() {
Common::FSNode node(_themeFile);
if (node.getName().hasSuffix(".zip") && !node.isDirectory()) {
#ifdef USE_ZLIB
Common::ZipArchive *zipArchive = new Common::ZipArchive(node);
Common::Archive *zipArchive = Common::makeZipArchive(node);
if (!zipArchive || !zipArchive->isOpen()) {
delete zipArchive;
zipArchive = 0;
if (!zipArchive) {
warning("Failed to open Zip archive '%s'.", node.getPath().c_str());
}
_themeArchive = zipArchive;
@ -1443,10 +1441,18 @@ bool ThemeEngine::themeConfigUsable(const Common::FSNode &node, Common::String &
if (node.getName().hasSuffix(".zip") && !node.isDirectory()) {
#ifdef USE_ZLIB
Common::ZipArchive zipArchive(node);
if (zipArchive.hasFile("THEMERC")) {
stream.open("THEMERC", zipArchive);
Common::Archive *zipArchive = Common::makeZipArchive(node);
if (zipArchive && zipArchive->hasFile("THEMERC")) {
// Open THEMERC from the ZIP file.
stream.open("THEMERC", *zipArchive);
}
// Delete the ZIP archive again. Note: This only works because
// stream.open() only uses ZipArchive::createReadStreamForMember,
// and that in turn happens to read all the data for a given
// archive member into a memory block. So there will be no dangling
// reference to zipArchive anywhere. This could change if we
// ever modify ZipArchive::createReadStreamForMember.
delete zipArchive;
#endif
} else if (node.isDirectory()) {
Common::FSNode headerfile = node.getChild("THEMERC");

View file

@ -28,6 +28,8 @@
#include "graphics/scaler.h"
#include "common/tokenizer.h"
namespace GUI {
ThemeEval::~ThemeEval() {

View file

@ -30,6 +30,8 @@
#include "graphics/VectorRenderer.h"
#include "common/tokenizer.h"
namespace GUI {
struct TextDataInfo {

View file

@ -210,7 +210,7 @@ protected:
KEY_END()
KEY_END()
} PARSER_END();
} PARSER_END()
/** Render info callbacks */
bool parserCallback_render_info(ParserNode *node);

View file

@ -164,10 +164,10 @@ void AboutDialog::addLine(const char *str) {
Common::String format(str, 2);
str += 2;
Common::StringList wrappedLines;
StringArray wrappedLines;
g_gui.getFont().wordWrapText(str, _w - 2 * _xOff, wrappedLines);
for (Common::StringList::const_iterator i = wrappedLines.begin(); i != wrappedLines.end(); ++i) {
for (StringArray::const_iterator i = wrappedLines.begin(); i != wrappedLines.end(); ++i) {
_lines.push_back(format + *i);
}
}
@ -175,7 +175,7 @@ void AboutDialog::addLine(const char *str) {
void AboutDialog::open() {
_scrollTime = getMillis() + kScrollStartDelay;
_scrollTime = g_system->getMillis() + kScrollStartDelay;
_scrollPos = 0;
_willClose = false;
@ -253,7 +253,7 @@ void AboutDialog::drawDialog() {
}
void AboutDialog::handleTickle() {
const uint32 t = getMillis();
const uint32 t = g_system->getMillis();
int scrollOffset = ((int)t - (int)_scrollTime) / kScrollMillisPerPixel;
if (scrollOffset > 0) {
int modifiers = g_system->getEventManager()->getModifierState();

View file

@ -32,11 +32,11 @@
namespace GUI {
class AboutDialog : public Dialog {
typedef Common::StringList StringList;
typedef Common::Array<Common::String> StringArray;
protected:
int _scrollPos;
uint32 _scrollTime;
StringList _lines;
StringArray _lines;
uint32 _lineHeight;
bool _willClose;

View file

@ -150,7 +150,7 @@ void BrowserDialog::updateListing() {
Common::sort(_nodeContent.begin(), _nodeContent.end());
// Populate the ListWidget
Common::StringList list;
ListWidget::StringArray list;
ListWidget::ColorList colors;
for (Common::FSList::iterator i = _nodeContent.begin(); i != _nodeContent.end(); ++i) {
if (i->isDirectory())

View file

@ -50,7 +50,7 @@ ChooserDialog::ChooserDialog(const String &title, String dialogId)
_chooseButton->setEnabled(false);
}
void ChooserDialog::setList(const StringList& list) {
void ChooserDialog::setList(const StringArray& list) {
_list->setList(list);
}

Some files were not shown because too many files have changed in this diff Show more