synced with scummvm rev svn 49000
This commit is contained in:
parent
786721e347
commit
e3a475ff7b
157 changed files with 5758 additions and 3811 deletions
8
Makefile
8
Makefile
|
@ -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
|
||||
|
||||
#######################################################################
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -97,5 +97,4 @@ bool DCPluginProvider::isPluginFilename(const Common::FSNode &node) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif // defined(DYNAMIC_MODULES) && defined(__DC__)
|
||||
|
|
|
@ -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__)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "common/util.h"
|
||||
#include "common/system.h"
|
||||
#include "common/archive.h"
|
||||
#include "common/tokenizer.h"
|
||||
|
||||
#include "graphics/imagedec.h"
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
namespace Common {
|
||||
|
||||
class RandomSource;
|
||||
|
||||
/**
|
||||
* Our generic event recorder.
|
||||
*
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "common/sys.h"
|
||||
#include "common/func.h"
|
||||
#include "common/util.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
132
common/debug-channels.h
Normal 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
|
|
@ -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);
|
||||
|
|
|
@ -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
72
common/error.cpp
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
14
common/fs.h
14
common/fs.h
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
573
common/macresman.cpp
Normal 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
155
common/macresman.h
Normal 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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
78
common/ptr.h
78
common/ptr.h
|
@ -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
59
common/random.cpp
Normal 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
71
common/random.h
Normal 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
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
42
common/str-array.h
Normal 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
|
|
@ -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
|
||||
|
|
53
common/str.h
53
common/str.h
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
59
common/tokenizer.cpp
Normal 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
61
common/tokenizer.h
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
104
common/util.cpp
104
common/util.cpp
|
@ -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},
|
||||
|
|
|
@ -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
326
configure
vendored
|
@ -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
|
||||
|
||||
|
|
|
@ -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 ¶ms, Common::Language language, Common::Platform platform, const Common::String extra);
|
||||
static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams ¶ms, 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 ¶ms);
|
||||
|
||||
static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams ¶ms, Common::Language language, Common::Platform platform, const Common::String extra) {
|
||||
static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams ¶ms, 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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,10 @@ public:
|
|||
|
||||
virtual void reflowLayout();
|
||||
|
||||
protected:
|
||||
void save();
|
||||
void load();
|
||||
|
||||
protected:
|
||||
Engine *_engine;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
104
engines/game.h
104
engines/game.h
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
71
engines/savestate.cpp
Normal 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
135
engines/savestate.h
Normal 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
54
engines/util.h
Normal 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
|
|
@ -27,7 +27,7 @@
|
|||
#include "common/system.h"
|
||||
#include "common/stack.h"
|
||||
|
||||
DECLARE_SINGLETON(Graphics::CursorManager);
|
||||
DECLARE_SINGLETON(Graphics::CursorManager)
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "graphics/fontman.h"
|
||||
//#include "gui/consolefont.h"
|
||||
|
||||
DECLARE_SINGLETON(Graphics::FontManager);
|
||||
DECLARE_SINGLETON(Graphics::FontManager)
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "graphics/imagedec.h"
|
||||
|
||||
#include "common/file.h"
|
||||
//#include "common/system.h"
|
||||
|
||||
namespace Graphics {
|
||||
//
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include "graphics/scaler.h"
|
||||
|
||||
#include "common/tokenizer.h"
|
||||
|
||||
namespace GUI {
|
||||
|
||||
ThemeEval::~ThemeEval() {
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
#include "graphics/VectorRenderer.h"
|
||||
|
||||
#include "common/tokenizer.h"
|
||||
|
||||
namespace GUI {
|
||||
|
||||
struct TextDataInfo {
|
||||
|
|
|
@ -210,7 +210,7 @@ protected:
|
|||
KEY_END()
|
||||
KEY_END()
|
||||
|
||||
} PARSER_END();
|
||||
} PARSER_END()
|
||||
|
||||
/** Render info callbacks */
|
||||
bool parserCallback_render_info(ParserNode *node);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue