synced with scummvm
This commit is contained in:
parent
fca3a20334
commit
7aa79c880d
115 changed files with 5209 additions and 2608 deletions
25
Makefile
25
Makefile
|
@ -20,21 +20,29 @@ MODULE_DIRS :=
|
||||||
# Load the make rules generated by configure
|
# Load the make rules generated by configure
|
||||||
-include config.mk
|
-include config.mk
|
||||||
|
|
||||||
|
ifeq "$(HAVE_GCC)" "1"
|
||||||
CXXFLAGS:= -Wall $(CXXFLAGS)
|
CXXFLAGS:= -Wall $(CXXFLAGS)
|
||||||
# Turn off some annoying and not-so-useful warnings
|
# Turn off some annoying and not-so-useful warnings
|
||||||
CXXFLAGS+= -Wno-long-long -Wno-multichar -Wno-unknown-pragmas -Wno-reorder -Wno-unused-parameter
|
CXXFLAGS+= -Wno-long-long -Wno-multichar -Wno-unknown-pragmas -Wno-reorder
|
||||||
# Enable even more warnings...
|
# Enable even more warnings...
|
||||||
#CXXFLAGS+= -Wpointer-arith -Wcast-qual -Wcast-align
|
CXXFLAGS+= -Wpointer-arith -Wcast-qual -Wcast-align
|
||||||
#CXXFLAGS+= -Wshadow -Wimplicit -Wnon-virtual-dtor -Wwrite-strings
|
CXXFLAGS+= -Wshadow -Wimplicit -Wnon-virtual-dtor -Wwrite-strings
|
||||||
|
|
||||||
|
# Currently we disable this gcc flag, since it will also warn in cases,
|
||||||
|
# where using GCC_PRINTF (means: __attribute__((format(printf, x, y))))
|
||||||
|
# is not possible, thus it would fail compiliation with -Werror without
|
||||||
|
# being helpful.
|
||||||
|
#CXXFLAGS+= -Wmissing-format-attribute
|
||||||
|
|
||||||
# Disable RTTI and exceptions, and enabled checking of pointers returned by "new"
|
# Disable RTTI and exceptions, and enabled checking of pointers returned by "new"
|
||||||
#CXXFLAGS+= -fno-rtti -fno-exceptions -fcheck-new
|
CXXFLAGS+= -fno-rtti -fno-exceptions -fcheck-new
|
||||||
|
|
||||||
# There is a nice extra warning that flags variables that are potentially
|
# There is a nice extra warning that flags variables that are potentially
|
||||||
# used before being initialized. Very handy to catch a certain kind of
|
# used before being initialized. Very handy to catch a certain kind of
|
||||||
# bugs. Unfortunately, it only works when optimizations are turned on,
|
# bugs. Unfortunately, it only works when optimizations are turned on,
|
||||||
# which is why we normally don't use it.
|
# which is why we normally don't use it.
|
||||||
#CXXFLAGS+= -O -Wuninitialized
|
#CXXFLAGS+= -O -Wuninitialized
|
||||||
|
endif
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# Default commands - put the necessary replacements in config.mk #
|
# Default commands - put the necessary replacements in config.mk #
|
||||||
|
@ -62,10 +70,15 @@ config.h config.mk: $(srcdir)/configure
|
||||||
ifeq "$(findstring config.mk,$(MAKEFILE_LIST))" "config.mk"
|
ifeq "$(findstring config.mk,$(MAKEFILE_LIST))" "config.mk"
|
||||||
@echo "Running $(srcdir)/configure with the last specified parameters"
|
@echo "Running $(srcdir)/configure with the last specified parameters"
|
||||||
@sleep 2
|
@sleep 2
|
||||||
LDFLAGS="$(SAVED_LDFLAGS)" CXX="$(SAVED_CXX)" CXXFLAGS="$(SAVED_CXXFLAGS)" CPPFLAGS="$(SAVED_CPPFLAGS)" \
|
LDFLAGS="$(SAVED_LDFLAGS)" CXX="$(SAVED_CXX)" \
|
||||||
|
CXXFLAGS="$(SAVED_CXXFLAGS)" CPPFLAGS="$(SAVED_CPPFLAGS)" \
|
||||||
|
ASFLAGS="$(SAVED_ASFLAGS)" WINDRESFLAGS="$(SAVED_WINDRESFLAGS)" \
|
||||||
$(srcdir)/configure $(SAVED_CONFIGFLAGS)
|
$(srcdir)/configure $(SAVED_CONFIGFLAGS)
|
||||||
else
|
else
|
||||||
$(error You need to run $(srcdir)/configure before you can run make. Check $(srcdir)/configure --help for a list of parameters)
|
$(error You need to run $(srcdir)/configure before you can run make. Check $(srcdir)/configure --help for a list of parameters)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include $(srcdir)/ports.mk
|
ifneq ($(origin port_mk), undefined)
|
||||||
|
include $(srcdir)/$(port_mk)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,8 @@ ifneq ($(findstring $(MAKEFLAGS),s),s)
|
||||||
ifneq ($(VERBOSE_BUILD),1)
|
ifneq ($(VERBOSE_BUILD),1)
|
||||||
ifneq ($(VERBOSE_BUILD),yes)
|
ifneq ($(VERBOSE_BUILD),yes)
|
||||||
QUIET_CXX = @echo ' ' C++ ' ' $@;
|
QUIET_CXX = @echo ' ' C++ ' ' $@;
|
||||||
|
QUIET_AS = @echo ' ' AS ' ' $@;
|
||||||
|
QUIET_NASM = @echo ' ' NASM ' ' $@;
|
||||||
QUIET_AR = @echo ' ' AR ' ' $@;
|
QUIET_AR = @echo ' ' AR ' ' $@;
|
||||||
QUIET_RANLIB = @echo ' ' RANLIB ' ' $@;
|
QUIET_RANLIB = @echo ' ' RANLIB ' ' $@;
|
||||||
QUIET_PLUGIN = @echo ' ' PLUGIN ' ' $@;
|
QUIET_PLUGIN = @echo ' ' PLUGIN ' ' $@;
|
||||||
|
@ -75,26 +77,40 @@ clean:
|
||||||
$(RM_REC) $(DEPDIRS)
|
$(RM_REC) $(DEPDIRS)
|
||||||
$(RM) $(OBJS) $(EXECUTABLE)
|
$(RM) $(OBJS) $(EXECUTABLE)
|
||||||
|
|
||||||
ifndef HAVE_GCC3
|
|
||||||
# If you use GCC, disable the above and enable this for intelligent
|
#
|
||||||
|
# The build rules for object files.
|
||||||
|
#
|
||||||
|
|
||||||
|
ifdef CXX_UPDATE_DEP_FLAG
|
||||||
|
|
||||||
|
# Build rule for C++ files. Makes use of CXX_UPDATE_DEP_FLAG for advanced
|
||||||
# dependency tracking.
|
# dependency tracking.
|
||||||
%.o: %.cpp
|
%.o: %.cpp
|
||||||
$(QUIET)$(MKDIR) $(*D)/$(DEPDIR)
|
$(QUIET)$(MKDIR) $(*D)/$(DEPDIR)
|
||||||
$(QUIET_CXX)$(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d2" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
|
$(QUIET_CXX)$(CXX) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
|
||||||
$(QUIET)$(ECHO) "$(*D)/" > $(*D)/$(DEPDIR)/$(*F).d
|
|
||||||
$(QUIET)$(CAT) "$(*D)/$(DEPDIR)/$(*F).d2" >> "$(*D)/$(DEPDIR)/$(*F).d"
|
# Build rule for Objective-C files. Strictly speaking, this is for OS X only.
|
||||||
$(QUIET)$(RM) "$(*D)/$(DEPDIR)/$(*F).d2"
|
|
||||||
else
|
|
||||||
# If you even have GCC 3.x, you can use this build rule, which is safer; the above
|
|
||||||
# rule can get you into a bad state if you Ctrl-C at the wrong moment.
|
|
||||||
# Also, with this GCC inserts additional dummy rules for the involved headers,
|
|
||||||
# which ensures a smooth compilation even if said headers become obsolete.
|
|
||||||
%.o: %.cpp
|
|
||||||
$(QUIET)$(MKDIR) $(*D)/$(DEPDIR)
|
|
||||||
$(QUIET_CXX)$(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
|
|
||||||
%.o: %.m
|
%.o: %.m
|
||||||
$(QUIET)$(MKDIR) $(*D)/$(DEPDIR)
|
$(QUIET)$(MKDIR) $(*D)/$(DEPDIR)
|
||||||
$(QUIET_CXX)$(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(OBJCFLAGS) -c $(<) -o $*.o
|
$(QUIET_CXX)$(CXX) $(CXX_UPDATE_DEP_FLAG) $(OBJCFLAGS) -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_CXX)$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
%.o: %.s
|
||||||
|
$(QUIET_AS)$(AS) $(ASFLAGS) $(<) -o $*.o
|
||||||
|
|
||||||
|
ifdef HAVE_NASM
|
||||||
|
%.o: %.asm
|
||||||
|
$(QUIET_NASM)$(NASM) -O1 $(NASMFLAGS) -g -o $*.o $(<)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Include the dependency tracking files.
|
# Include the dependency tracking files.
|
||||||
|
@ -134,25 +150,6 @@ CXXFLAGS+= -DRESIDUAL_SVN_REVISION=\"$(VER_SVNREV)\"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# Create the files that depend on the version
|
|
||||||
######################################################################
|
|
||||||
|
|
||||||
VERSION_FILES = \
|
|
||||||
$(srcdir)/dists/iphone/Info.plist \
|
|
||||||
$(srcdir)/dists/macosx/Info.plist
|
|
||||||
|
|
||||||
$(VERSION_FILES): %: %.in
|
|
||||||
@echo "Creating $@"
|
|
||||||
@cat $< | sed \
|
|
||||||
-e "s/@VER_MAJOR@/$(VER_MAJOR)/g" \
|
|
||||||
-e "s/@VER_MINOR@/$(VER_MINOR)/g" \
|
|
||||||
-e "s/@VER_PATCH@/$(VER_PATCH)/g" \
|
|
||||||
-e "s/@VER_EXTRA@/$(VER_EXTRA)/g" \
|
|
||||||
-e "s/@VERSION@/$(VERSION)/g" \
|
|
||||||
> $@
|
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Distribution settings
|
# Distribution settings
|
||||||
######################################################################
|
######################################################################
|
||||||
|
@ -198,10 +195,16 @@ dist-src: \
|
||||||
@#RPM-src?
|
@#RPM-src?
|
||||||
@#DEB-src?
|
@#DEB-src?
|
||||||
|
|
||||||
|
# Common files
|
||||||
|
DIST_FILES_DOCS:=$(addprefix $(srcdir)/,AUTHORS COPYING COPYING.LGPL COPYRIGHT NEWS README)
|
||||||
|
|
||||||
# Themes files
|
# Themes files
|
||||||
DIST_FILES_THEMES:=$(addprefix $(srcdir)/gui/themes/,scummmodern.zip)
|
DIST_FILES_THEMES:=$(addprefix $(srcdir)/gui/themes/,scummmodern.zip)
|
||||||
|
|
||||||
|
# Engine data files
|
||||||
|
DIST_FILES_ENGINEDATA=
|
||||||
|
DIST_FILES_ENGINEDATA:=$(addprefix $(srcdir)/dists/engine-data/,$(DIST_FILES_ENGINEDATA))
|
||||||
|
|
||||||
# Plugin files
|
# Plugin files
|
||||||
DIST_FILES_PLUGINS:=$(addprefix $(srcdir)/,$(PLUGINS))
|
DIST_FILES_PLUGINS:=$(addprefix $(srcdir)/,$(PLUGINS))
|
||||||
|
|
||||||
|
|
|
@ -27,10 +27,9 @@
|
||||||
#define BACKENDS_BASE_BACKEND_H
|
#define BACKENDS_BASE_BACKEND_H
|
||||||
|
|
||||||
#include "common/system.h"
|
#include "common/system.h"
|
||||||
#include "common/fs.h"
|
|
||||||
#include "backends/events/default/default-events.h"
|
#include "backends/events/default/default-events.h"
|
||||||
|
|
||||||
class BaseBackend : public OSystem, EventProvider {
|
class BaseBackend : public OSystem, Common::EventSource {
|
||||||
public:
|
public:
|
||||||
virtual Common::EventManager *getEventManager();
|
virtual Common::EventManager *getEventManager();
|
||||||
virtual void displayMessageOnOSD(const char *msg);
|
virtual void displayMessageOnOSD(const char *msg);
|
||||||
|
|
|
@ -35,242 +35,38 @@
|
||||||
#include "engines/engine.h"
|
#include "engines/engine.h"
|
||||||
#include "gui/message.h"
|
#include "gui/message.h"
|
||||||
|
|
||||||
#define RECORD_SIGNATURE 0x54455354
|
DefaultEventManager::DefaultEventManager(Common::EventSource *boss) :
|
||||||
#define RECORD_VERSION 1
|
|
||||||
|
|
||||||
void readRecord(Common::InSaveFile *inFile, uint32 &diff, Common::Event &event) {
|
|
||||||
diff = inFile->readUint32LE();
|
|
||||||
|
|
||||||
event.type = (Common::EventType)inFile->readUint32LE();
|
|
||||||
|
|
||||||
switch(event.type) {
|
|
||||||
case Common::EVENT_KEYDOWN:
|
|
||||||
case Common::EVENT_KEYUP:
|
|
||||||
event.kbd.keycode = (Common::KeyCode)inFile->readSint32LE();
|
|
||||||
event.kbd.ascii = inFile->readUint16LE();
|
|
||||||
event.kbd.flags = inFile->readByte();
|
|
||||||
break;
|
|
||||||
case Common::EVENT_MOUSEMOVE:
|
|
||||||
case Common::EVENT_LBUTTONDOWN:
|
|
||||||
case Common::EVENT_LBUTTONUP:
|
|
||||||
case Common::EVENT_RBUTTONDOWN:
|
|
||||||
case Common::EVENT_RBUTTONUP:
|
|
||||||
case Common::EVENT_WHEELUP:
|
|
||||||
case Common::EVENT_WHEELDOWN:
|
|
||||||
event.mouse.x = inFile->readSint16LE();
|
|
||||||
event.mouse.y = inFile->readSint16LE();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeRecord(Common::OutSaveFile *outFile, uint32 diff, Common::Event &event) {
|
|
||||||
outFile->writeUint32LE(diff);
|
|
||||||
|
|
||||||
outFile->writeUint32LE((uint32)event.type);
|
|
||||||
|
|
||||||
switch(event.type) {
|
|
||||||
case Common::EVENT_KEYDOWN:
|
|
||||||
case Common::EVENT_KEYUP:
|
|
||||||
outFile->writeSint32LE(event.kbd.keycode);
|
|
||||||
outFile->writeUint16LE(event.kbd.ascii);
|
|
||||||
outFile->writeByte(event.kbd.flags);
|
|
||||||
break;
|
|
||||||
case Common::EVENT_MOUSEMOVE:
|
|
||||||
case Common::EVENT_LBUTTONDOWN:
|
|
||||||
case Common::EVENT_LBUTTONUP:
|
|
||||||
case Common::EVENT_RBUTTONDOWN:
|
|
||||||
case Common::EVENT_RBUTTONUP:
|
|
||||||
case Common::EVENT_WHEELUP:
|
|
||||||
case Common::EVENT_WHEELDOWN:
|
|
||||||
outFile->writeSint16LE(event.mouse.x);
|
|
||||||
outFile->writeSint16LE(event.mouse.y);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultEventManager::DefaultEventManager(EventProvider *boss) :
|
|
||||||
_boss(boss),
|
|
||||||
_buttonState(0),
|
_buttonState(0),
|
||||||
_modifierState(0),
|
_modifierState(0),
|
||||||
_shouldQuit(false),
|
_shouldQuit(false),
|
||||||
_shouldRTL(false),
|
_shouldRTL(false),
|
||||||
_confirmExitDialogActive(false) {
|
_confirmExitDialogActive(false) {
|
||||||
|
|
||||||
assert(_boss);
|
assert(boss);
|
||||||
|
|
||||||
_recordFile = NULL;
|
_dispatcher.registerSource(boss, false);
|
||||||
_recordTimeFile = NULL;
|
_dispatcher.registerSource(&_artificialEventSource, false);
|
||||||
_playbackFile = NULL;
|
|
||||||
_playbackTimeFile = NULL;
|
|
||||||
_timeMutex = g_system->createMutex();
|
|
||||||
_recorderMutex = g_system->createMutex();
|
|
||||||
|
|
||||||
_eventCount = 0;
|
_dispatcher.registerObserver(this, kEventManPriority, false);
|
||||||
_lastEventCount = 0;
|
|
||||||
_lastMillis = 0;
|
|
||||||
|
|
||||||
Common::String recordModeString = ConfMan.get("record_mode");
|
|
||||||
if (recordModeString.compareToIgnoreCase("record") == 0) {
|
|
||||||
_recordMode = kRecorderRecord;
|
|
||||||
} else {
|
|
||||||
if (recordModeString.compareToIgnoreCase("playback") == 0) {
|
|
||||||
_recordMode = kRecorderPlayback;
|
|
||||||
} else {
|
|
||||||
_recordMode = kPassthrough;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_recordFileName = ConfMan.get("record_file_name");
|
|
||||||
if (_recordFileName.empty()) {
|
|
||||||
_recordFileName = "record.bin";
|
|
||||||
}
|
|
||||||
_recordTempFileName = ConfMan.get("record_temp_file_name");
|
|
||||||
if (_recordTempFileName.empty()) {
|
|
||||||
_recordTempFileName = "record.tmp";
|
|
||||||
}
|
|
||||||
_recordTimeFileName = ConfMan.get("record_time_file_name");
|
|
||||||
if (_recordTimeFileName.empty()) {
|
|
||||||
_recordTimeFileName = "record.time";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset key repeat
|
// Reset key repeat
|
||||||
_currentKeyDown.keycode = 0;
|
_currentKeyDown.keycode = 0;
|
||||||
|
|
||||||
// recorder stuff
|
|
||||||
if (_recordMode == kRecorderRecord) {
|
|
||||||
_recordCount = 0;
|
|
||||||
_recordTimeCount = 0;
|
|
||||||
_recordFile = g_system->getSavefileManager()->openForSaving(_recordTempFileName);
|
|
||||||
_recordTimeFile = g_system->getSavefileManager()->openForSaving(_recordTimeFileName);
|
|
||||||
_recordSubtitles = ConfMan.getBool("subtitles");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 sign;
|
|
||||||
uint32 version;
|
|
||||||
uint32 randomSourceCount;
|
|
||||||
if (_recordMode == kRecorderPlayback) {
|
|
||||||
_playbackCount = 0;
|
|
||||||
_playbackTimeCount = 0;
|
|
||||||
_playbackFile = g_system->getSavefileManager()->openForLoading(_recordFileName);
|
|
||||||
_playbackTimeFile = g_system->getSavefileManager()->openForLoading(_recordTimeFileName);
|
|
||||||
|
|
||||||
if (!_playbackFile) {
|
|
||||||
warning("Cannot open playback file %s. Playback was switched off", _recordFileName.c_str());
|
|
||||||
_recordMode = kPassthrough;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_playbackTimeFile) {
|
|
||||||
warning("Cannot open playback time file %s. Playback was switched off", _recordTimeFileName.c_str());
|
|
||||||
_recordMode = kPassthrough;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_recordMode == kRecorderPlayback) {
|
|
||||||
sign = _playbackFile->readUint32LE();
|
|
||||||
if (sign != RECORD_SIGNATURE) {
|
|
||||||
error("Unknown record file signature");
|
|
||||||
}
|
|
||||||
version = _playbackFile->readUint32LE();
|
|
||||||
|
|
||||||
// conf vars
|
|
||||||
ConfMan.setBool("subtitles", _playbackFile->readByte() != 0);
|
|
||||||
|
|
||||||
_recordCount = _playbackFile->readUint32LE();
|
|
||||||
_recordTimeCount = _playbackFile->readUint32LE();
|
|
||||||
randomSourceCount = _playbackFile->readUint32LE();
|
|
||||||
for (uint i = 0; i < randomSourceCount; ++i) {
|
|
||||||
RandomSourceRecord rec;
|
|
||||||
rec.name = "";
|
|
||||||
uint32 sLen = _playbackFile->readUint32LE();
|
|
||||||
for (uint j = 0; j < sLen; ++j) {
|
|
||||||
char c = _playbackFile->readSByte();
|
|
||||||
rec.name += c;
|
|
||||||
}
|
|
||||||
rec.seed = _playbackFile->readUint32LE();
|
|
||||||
_randomSourceRecords.push_back(rec);
|
|
||||||
}
|
|
||||||
|
|
||||||
_hasPlaybackEvent = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_VKEYBD
|
#ifdef ENABLE_VKEYBD
|
||||||
_vk = new Common::VirtualKeyboard();
|
_vk = new Common::VirtualKeyboard();
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_KEYMAPPER
|
#ifdef ENABLE_KEYMAPPER
|
||||||
_keymapper = new Common::Keymapper(this);
|
_keymapper = new Common::Keymapper(this);
|
||||||
|
// EventDispatcher will automatically free the keymapper
|
||||||
|
_dispatcher.registerMapper(_keymapper);
|
||||||
_remap = false;
|
_remap = false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultEventManager::~DefaultEventManager() {
|
DefaultEventManager::~DefaultEventManager() {
|
||||||
#ifdef ENABLE_KEYMAPPER
|
|
||||||
delete _keymapper;
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_VKEYBD
|
#ifdef ENABLE_VKEYBD
|
||||||
delete _vk;
|
delete _vk;
|
||||||
#endif
|
#endif
|
||||||
g_system->lockMutex(_timeMutex);
|
|
||||||
g_system->lockMutex(_recorderMutex);
|
|
||||||
_recordMode = kPassthrough;
|
|
||||||
g_system->unlockMutex(_timeMutex);
|
|
||||||
g_system->unlockMutex(_recorderMutex);
|
|
||||||
|
|
||||||
if (!artificialEventQueue.empty())
|
|
||||||
artificialEventQueue.clear();
|
|
||||||
|
|
||||||
if (_playbackFile != NULL) {
|
|
||||||
delete _playbackFile;
|
|
||||||
}
|
|
||||||
if (_playbackTimeFile != NULL) {
|
|
||||||
delete _playbackTimeFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_recordFile != NULL) {
|
|
||||||
_recordFile->finalize();
|
|
||||||
delete _recordFile;
|
|
||||||
_recordTimeFile->finalize();
|
|
||||||
delete _recordTimeFile;
|
|
||||||
|
|
||||||
_playbackFile = g_system->getSavefileManager()->openForLoading(_recordTempFileName);
|
|
||||||
|
|
||||||
assert(_playbackFile);
|
|
||||||
|
|
||||||
_recordFile = g_system->getSavefileManager()->openForSaving(_recordFileName);
|
|
||||||
_recordFile->writeUint32LE(RECORD_SIGNATURE);
|
|
||||||
_recordFile->writeUint32LE(RECORD_VERSION);
|
|
||||||
|
|
||||||
// conf vars
|
|
||||||
_recordFile->writeByte(_recordSubtitles ? 1 : 0);
|
|
||||||
|
|
||||||
_recordFile->writeUint32LE(_recordCount);
|
|
||||||
_recordFile->writeUint32LE(_recordTimeCount);
|
|
||||||
|
|
||||||
_recordFile->writeUint32LE(_randomSourceRecords.size());
|
|
||||||
for (uint i = 0; i < _randomSourceRecords.size(); ++i) {
|
|
||||||
_recordFile->writeUint32LE(_randomSourceRecords[i].name.size());
|
|
||||||
_recordFile->writeString(_randomSourceRecords[i].name);
|
|
||||||
_recordFile->writeUint32LE(_randomSourceRecords[i].seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint i = 0; i < _recordCount; ++i) {
|
|
||||||
uint32 tempDiff;
|
|
||||||
Common::Event tempEvent;
|
|
||||||
readRecord(_playbackFile, tempDiff, tempEvent);
|
|
||||||
writeRecord(_recordFile, tempDiff, tempEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
_recordFile->finalize();
|
|
||||||
delete _recordFile;
|
|
||||||
delete _playbackFile;
|
|
||||||
|
|
||||||
//TODO: remove recordTempFileName'ed file
|
|
||||||
}
|
|
||||||
g_system->deleteMutex(_timeMutex);
|
|
||||||
g_system->deleteMutex(_recorderMutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefaultEventManager::init() {
|
void DefaultEventManager::init() {
|
||||||
|
@ -283,145 +79,14 @@ void DefaultEventManager::init() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DefaultEventManager::playback(Common::Event &event) {
|
|
||||||
|
|
||||||
if (!_hasPlaybackEvent) {
|
|
||||||
if (_recordCount > _playbackCount) {
|
|
||||||
readRecord(_playbackFile, const_cast<uint32&>(_playbackDiff), _playbackEvent);
|
|
||||||
_playbackCount++;
|
|
||||||
_hasPlaybackEvent = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_hasPlaybackEvent) {
|
|
||||||
if (_playbackDiff <= (_eventCount - _lastEventCount)) {
|
|
||||||
switch(_playbackEvent.type) {
|
|
||||||
case Common::EVENT_MOUSEMOVE:
|
|
||||||
case Common::EVENT_LBUTTONDOWN:
|
|
||||||
case Common::EVENT_LBUTTONUP:
|
|
||||||
case Common::EVENT_RBUTTONDOWN:
|
|
||||||
case Common::EVENT_RBUTTONUP:
|
|
||||||
case Common::EVENT_WHEELUP:
|
|
||||||
case Common::EVENT_WHEELDOWN:
|
|
||||||
g_system->warpMouse(_playbackEvent.mouse.x, _playbackEvent.mouse.y);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
event = _playbackEvent;
|
|
||||||
_hasPlaybackEvent = false;
|
|
||||||
_lastEventCount = _eventCount;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DefaultEventManager::record(Common::Event &event) {
|
|
||||||
writeRecord(_recordFile, _eventCount - _lastEventCount, event);
|
|
||||||
|
|
||||||
_recordCount++;
|
|
||||||
_lastEventCount = _eventCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DefaultEventManager::registerRandomSource(Common::RandomSource &rnd, const char *name) {
|
|
||||||
|
|
||||||
if (_recordMode == kRecorderRecord) {
|
|
||||||
RandomSourceRecord rec;
|
|
||||||
rec.name = name;
|
|
||||||
rec.seed = rnd.getSeed();
|
|
||||||
_randomSourceRecords.push_back(rec);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_recordMode == kRecorderPlayback) {
|
|
||||||
for (uint i = 0; i < _randomSourceRecords.size(); ++i) {
|
|
||||||
if (_randomSourceRecords[i].name == name) {
|
|
||||||
rnd.setSeed(_randomSourceRecords[i].seed);
|
|
||||||
_randomSourceRecords.remove_at(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DefaultEventManager::processMillis(uint32 &millis) {
|
|
||||||
uint32 d;
|
|
||||||
if (_recordMode == kPassthrough) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_system->lockMutex(_timeMutex);
|
|
||||||
if (_recordMode == kRecorderRecord) {
|
|
||||||
//Simple RLE compression
|
|
||||||
d = millis - _lastMillis;
|
|
||||||
if (d >= 0xff) {
|
|
||||||
_recordTimeFile->writeByte(0xff);
|
|
||||||
_recordTimeFile->writeUint32LE(d);
|
|
||||||
} else {
|
|
||||||
_recordTimeFile->writeByte(d);
|
|
||||||
}
|
|
||||||
_recordTimeCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_recordMode == kRecorderPlayback) {
|
|
||||||
if (_recordTimeCount > _playbackTimeCount) {
|
|
||||||
d = _playbackTimeFile->readByte();
|
|
||||||
if (d == 0xff) {
|
|
||||||
d = _playbackTimeFile->readUint32LE();
|
|
||||||
}
|
|
||||||
millis = _lastMillis + d;
|
|
||||||
_playbackTimeCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastMillis = millis;
|
|
||||||
g_system->unlockMutex(_timeMutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DefaultEventManager::pollEvent(Common::Event &event) {
|
bool DefaultEventManager::pollEvent(Common::Event &event) {
|
||||||
uint32 time = g_system->getMillis();
|
uint32 time = g_system->getMillis();
|
||||||
bool result;
|
bool result = false;
|
||||||
|
|
||||||
if (!artificialEventQueue.empty()) {
|
_dispatcher.dispatch();
|
||||||
event = artificialEventQueue.pop();
|
if (!_eventQueue.empty()) {
|
||||||
|
event = _eventQueue.pop();
|
||||||
result = true;
|
result = true;
|
||||||
} else {
|
|
||||||
result = _boss->pollEvent(event);
|
|
||||||
|
|
||||||
#ifdef ENABLE_KEYMAPPER
|
|
||||||
if (result) {
|
|
||||||
// send key press events to keymapper
|
|
||||||
if (event.type == Common::EVENT_KEYDOWN) {
|
|
||||||
if (_keymapper->mapKeyDown(event.kbd)) {
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
} else if (event.type == Common::EVENT_KEYUP) {
|
|
||||||
if (_keymapper->mapKeyUp(event.kbd)) {
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_recordMode != kPassthrough) {
|
|
||||||
|
|
||||||
g_system->lockMutex(_recorderMutex);
|
|
||||||
_eventCount++;
|
|
||||||
|
|
||||||
if (_recordMode == kRecorderPlayback) {
|
|
||||||
if (event.type != Common::EVENT_QUIT) {
|
|
||||||
result = playback(event);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (_recordMode == kRecorderRecord) {
|
|
||||||
if (result) {
|
|
||||||
record(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_system->unlockMutex(_recorderMutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
|
@ -497,6 +162,16 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
else if (event.kbd.keycode == Common::KEYCODE_BACKSPACE) {
|
||||||
|
// WORKAROUND: Some engines incorrectly attempt to use the
|
||||||
|
// ascii value instead of the keycode to detect the backspace
|
||||||
|
// key (a non-portable behavior). This fails at least on
|
||||||
|
// Mac OS X, possibly also on other systems.
|
||||||
|
// As a workaround, we force the ascii value for backspace
|
||||||
|
// key pressed. A better fix would be for engines to stop
|
||||||
|
// making invalid assumptions about ascii values.
|
||||||
|
event.kbd.ascii = Common::KEYCODE_BACKSPACE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Common::EVENT_KEYUP:
|
case Common::EVENT_KEYUP:
|
||||||
|
@ -598,13 +273,12 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefaultEventManager::pushEvent(const Common::Event &event) {
|
void DefaultEventManager::pushEvent(const Common::Event &event) {
|
||||||
|
|
||||||
// If already received an EVENT_QUIT, don't add another one
|
// If already received an EVENT_QUIT, don't add another one
|
||||||
if (event.type == Common::EVENT_QUIT) {
|
if (event.type == Common::EVENT_QUIT) {
|
||||||
if (!_shouldQuit)
|
if (!_shouldQuit)
|
||||||
artificialEventQueue.push(event);
|
_artificialEventSource.addEvent(event);
|
||||||
} else
|
} else
|
||||||
artificialEventQueue.push(event);
|
_artificialEventSource.addEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !defined(DISABLE_DEFAULT_EVENTMANAGER)
|
#endif // !defined(DISABLE_DEFAULT_EVENTMANAGER)
|
||||||
|
|
|
@ -27,8 +27,6 @@
|
||||||
#define BACKEND_EVENTS_DEFAULT_H
|
#define BACKEND_EVENTS_DEFAULT_H
|
||||||
|
|
||||||
#include "common/events.h"
|
#include "common/events.h"
|
||||||
#include "common/savefile.h"
|
|
||||||
#include "common/mutex.h"
|
|
||||||
#include "common/queue.h"
|
#include "common/queue.h"
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
@ -41,21 +39,7 @@ namespace Common {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class EventProvider {
|
class DefaultEventManager : public Common::EventManager, Common::EventObserver {
|
||||||
public:
|
|
||||||
virtual ~EventProvider() {}
|
|
||||||
/**
|
|
||||||
* Get the next event in the event queue.
|
|
||||||
* @param event point to an Common::Event struct, which will be filled with the event data.
|
|
||||||
* @return true if an event was retrieved.
|
|
||||||
*/
|
|
||||||
virtual bool pollEvent(Common::Event &event) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class DefaultEventManager : public Common::EventManager {
|
|
||||||
EventProvider *_boss;
|
|
||||||
|
|
||||||
#ifdef ENABLE_VKEYBD
|
#ifdef ENABLE_VKEYBD
|
||||||
Common::VirtualKeyboard *_vk;
|
Common::VirtualKeyboard *_vk;
|
||||||
#endif
|
#endif
|
||||||
|
@ -65,7 +49,13 @@ class DefaultEventManager : public Common::EventManager {
|
||||||
bool _remap;
|
bool _remap;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Common::Queue<Common::Event> _artificialEventQueue;
|
Common::ArtificialEventSource _artificialEventSource;
|
||||||
|
|
||||||
|
Common::Queue<Common::Event> _eventQueue;
|
||||||
|
bool notifyEvent(const Common::Event &ev) {
|
||||||
|
_eventQueue.push(ev);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Common::Point _mousePos;
|
Common::Point _mousePos;
|
||||||
int _buttonState;
|
int _buttonState;
|
||||||
|
@ -74,44 +64,6 @@ class DefaultEventManager : public Common::EventManager {
|
||||||
bool _shouldRTL;
|
bool _shouldRTL;
|
||||||
bool _confirmExitDialogActive;
|
bool _confirmExitDialogActive;
|
||||||
|
|
||||||
class RandomSourceRecord {
|
|
||||||
public:
|
|
||||||
Common::String name;
|
|
||||||
uint32 seed;
|
|
||||||
};
|
|
||||||
Common::Array<RandomSourceRecord> _randomSourceRecords;
|
|
||||||
|
|
||||||
bool _recordSubtitles;
|
|
||||||
volatile uint32 _recordCount;
|
|
||||||
volatile uint32 _lastRecordEvent;
|
|
||||||
volatile uint32 _recordTimeCount;
|
|
||||||
Common::OutSaveFile *_recordFile;
|
|
||||||
Common::OutSaveFile *_recordTimeFile;
|
|
||||||
Common::MutexRef _timeMutex;
|
|
||||||
Common::MutexRef _recorderMutex;
|
|
||||||
volatile uint32 _lastMillis;
|
|
||||||
|
|
||||||
volatile uint32 _playbackCount;
|
|
||||||
volatile uint32 _playbackDiff;
|
|
||||||
volatile bool _hasPlaybackEvent;
|
|
||||||
volatile uint32 _playbackTimeCount;
|
|
||||||
Common::Event _playbackEvent;
|
|
||||||
Common::InSaveFile *_playbackFile;
|
|
||||||
Common::InSaveFile *_playbackTimeFile;
|
|
||||||
|
|
||||||
volatile uint32 _eventCount;
|
|
||||||
volatile uint32 _lastEventCount;
|
|
||||||
|
|
||||||
enum RecordMode {
|
|
||||||
kPassthrough = 0,
|
|
||||||
kRecorderRecord = 1,
|
|
||||||
kRecorderPlayback = 2
|
|
||||||
};
|
|
||||||
volatile RecordMode _recordMode;
|
|
||||||
Common::String _recordFileName;
|
|
||||||
Common::String _recordTempFileName;
|
|
||||||
Common::String _recordTimeFileName;
|
|
||||||
|
|
||||||
// for continuous events (keyDown)
|
// for continuous events (keyDown)
|
||||||
enum {
|
enum {
|
||||||
kKeyRepeatInitialDelay = 400,
|
kKeyRepeatInitialDelay = 400,
|
||||||
|
@ -124,18 +76,13 @@ class DefaultEventManager : public Common::EventManager {
|
||||||
int keycode;
|
int keycode;
|
||||||
} _currentKeyDown;
|
} _currentKeyDown;
|
||||||
uint32 _keyRepeatTime;
|
uint32 _keyRepeatTime;
|
||||||
|
|
||||||
void record(Common::Event &event);
|
|
||||||
bool playback(Common::Event &event);
|
|
||||||
public:
|
public:
|
||||||
DefaultEventManager(EventProvider *boss);
|
DefaultEventManager(Common::EventSource *boss);
|
||||||
~DefaultEventManager();
|
~DefaultEventManager();
|
||||||
|
|
||||||
virtual void init();
|
virtual void init();
|
||||||
virtual bool pollEvent(Common::Event &event);
|
virtual bool pollEvent(Common::Event &event);
|
||||||
virtual void pushEvent(const Common::Event &event);
|
virtual void pushEvent(const Common::Event &event);
|
||||||
virtual void registerRandomSource(Common::RandomSource &rnd, const char *name);
|
|
||||||
virtual void processMillis(uint32 &millis);
|
|
||||||
|
|
||||||
virtual Common::Point getMousePos() const { return _mousePos; }
|
virtual Common::Point getMousePos() const { return _mousePos; }
|
||||||
virtual int getButtonState() const { return _buttonState; }
|
virtual int getButtonState() const { return _buttonState; }
|
||||||
|
@ -143,6 +90,9 @@ public:
|
||||||
virtual int shouldQuit() const { return _shouldQuit; }
|
virtual int shouldQuit() const { return _shouldQuit; }
|
||||||
virtual int shouldRTL() const { return _shouldRTL; }
|
virtual int shouldRTL() const { return _shouldRTL; }
|
||||||
virtual void resetRTL() { _shouldRTL = false; }
|
virtual void resetRTL() { _shouldRTL = false; }
|
||||||
|
#ifdef FORCE_RTL
|
||||||
|
virtual void resetQuit() { _shouldQuit = false; }
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_KEYMAPPER
|
#ifdef ENABLE_KEYMAPPER
|
||||||
virtual Common::Keymapper *getKeymapper() { return _keymapper; }
|
virtual Common::Keymapper *getKeymapper() { return _keymapper; }
|
||||||
|
|
|
@ -43,8 +43,6 @@
|
||||||
#define ENTER() /* debug(6, "Enter") */
|
#define ENTER() /* debug(6, "Enter") */
|
||||||
#define LEAVE() /* debug(6, "Leave") */
|
#define LEAVE() /* debug(6, "Leave") */
|
||||||
|
|
||||||
const uint32 kExAllBufferSize = 40960; // TODO: is this okay for sure?
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of the ScummVM file system API.
|
* Implementation of the ScummVM file system API.
|
||||||
*
|
*
|
||||||
|
@ -57,30 +55,33 @@ protected:
|
||||||
Common::String _sPath;
|
Common::String _sPath;
|
||||||
bool _bIsDirectory;
|
bool _bIsDirectory;
|
||||||
bool _bIsValid;
|
bool _bIsValid;
|
||||||
|
uint32 _nProt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain the FileInfoBlock protection value for this FSNode,
|
* Creates a list with all the volumes present in the root node.
|
||||||
* as defined in the <proto/dos.h> header.
|
|
||||||
*
|
|
||||||
* @return -1 if there were errors, 0 or a positive integer otherwise.
|
|
||||||
*/
|
*/
|
||||||
virtual int getFibProtection() const;
|
virtual AbstractFSList listVolumes() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Creates a AmigaOSFilesystemNode with the root node as path.
|
* Creates an AmigaOSFilesystemNode with the root node as path.
|
||||||
*/
|
*/
|
||||||
AmigaOSFilesystemNode();
|
AmigaOSFilesystemNode();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a AmigaOSFilesystemNode for a given path.
|
* Creates an AmigaOSFilesystemNode for a given path.
|
||||||
*
|
*
|
||||||
* @param path Common::String with the path the new node should point to.
|
* @param path Common::String with the path the new node should point to.
|
||||||
*/
|
*/
|
||||||
AmigaOSFilesystemNode(const Common::String &p);
|
AmigaOSFilesystemNode(const Common::String &p);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FIXME: document this constructor.
|
* Creates an AmigaOSFilesystemNode given its lock and display name
|
||||||
|
*
|
||||||
|
* @param pLock BPTR to the lock.
|
||||||
|
* @param pDisplayName name to be used for display, in case not supplied the FilePart() of the filename will be used.
|
||||||
|
*
|
||||||
|
* @note This shouldn't even be public as it's only internally, at best it should have been protected if not private
|
||||||
*/
|
*/
|
||||||
AmigaOSFilesystemNode(BPTR pLock, const char *pDisplayName = 0);
|
AmigaOSFilesystemNode(BPTR pLock, const char *pDisplayName = 0);
|
||||||
|
|
||||||
|
@ -110,11 +111,6 @@ public:
|
||||||
|
|
||||||
virtual Common::SeekableReadStream *createReadStream();
|
virtual Common::SeekableReadStream *createReadStream();
|
||||||
virtual Common::WriteStream *createWriteStream();
|
virtual Common::WriteStream *createWriteStream();
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a list with all the volumes present in the root node.
|
|
||||||
*/
|
|
||||||
virtual AbstractFSList listVolumes() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -149,6 +145,7 @@ AmigaOSFilesystemNode::AmigaOSFilesystemNode() {
|
||||||
_bIsDirectory = true;
|
_bIsDirectory = true;
|
||||||
_sPath = "";
|
_sPath = "";
|
||||||
_pFileLock = 0;
|
_pFileLock = 0;
|
||||||
|
_nProt = 0; // protection is ignored for the root volume
|
||||||
LEAVE();
|
LEAVE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,37 +166,27 @@ AmigaOSFilesystemNode::AmigaOSFilesystemNode(const Common::String &p) {
|
||||||
_pFileLock = 0;
|
_pFileLock = 0;
|
||||||
_bIsDirectory = false;
|
_bIsDirectory = false;
|
||||||
|
|
||||||
struct FileInfoBlock *fib = (struct FileInfoBlock *)IDOS->AllocDosObject(DOS_FIB, NULL);
|
|
||||||
if (!fib) {
|
|
||||||
debug(6, "FileInfoBlock is NULL");
|
|
||||||
LEAVE();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether the node exists and if it is a directory
|
// Check whether the node exists and if it is a directory
|
||||||
BPTR pLock = IDOS->Lock((STRPTR)_sPath.c_str(), SHARED_LOCK);
|
struct ExamineData * pExd = IDOS->ExamineObjectTags(EX_StringNameInput,_sPath.c_str(),TAG_END);
|
||||||
if (pLock) {
|
if (pExd) {
|
||||||
if (IDOS->Examine(pLock, fib) != DOSFALSE) {
|
_nProt = pExd->Protection;
|
||||||
if (FIB_IS_DRAWER(fib)) {
|
if (EXD_IS_DIRECTORY(pExd)) {
|
||||||
_bIsDirectory = true;
|
_bIsDirectory = true;
|
||||||
_pFileLock = IDOS->DupLock(pLock);
|
_pFileLock = IDOS->Lock((CONST_STRPTR)_sPath.c_str(), SHARED_LOCK);;
|
||||||
_bIsValid = (_pFileLock != 0);
|
_bIsValid = (_pFileLock != 0);
|
||||||
|
|
||||||
// Add a trailing slash if it is needed
|
// Add a trailing slash if it is needed
|
||||||
const char c = _sPath.lastChar();
|
const char c = _sPath.lastChar();
|
||||||
if (c != '/' && c != ':')
|
if (c != '/' && c != ':')
|
||||||
_sPath += '/';
|
_sPath += '/';
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
//_bIsDirectory = false;
|
//_bIsDirectory = false;
|
||||||
_bIsValid = true;
|
_bIsValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IDOS->FreeDosObject(DOS_EXAMINEDATA, pExd);
|
||||||
}
|
}
|
||||||
|
|
||||||
IDOS->UnLock(pLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
IDOS->FreeDosObject(DOS_FIB, fib);
|
|
||||||
LEAVE();
|
LEAVE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,15 +219,10 @@ AmigaOSFilesystemNode::AmigaOSFilesystemNode(BPTR pLock, const char *pDisplayNam
|
||||||
_bIsValid = false;
|
_bIsValid = false;
|
||||||
_bIsDirectory = false;
|
_bIsDirectory = false;
|
||||||
|
|
||||||
struct FileInfoBlock *fib = (struct FileInfoBlock *)IDOS->AllocDosObject(DOS_FIB, NULL);
|
struct ExamineData * pExd = IDOS->ExamineObjectTags(EX_FileLockInput,pLock,TAG_END);
|
||||||
if (!fib) {
|
if (pExd) {
|
||||||
debug(6, "FileInfoBlock is NULL");
|
_nProt = pExd->Protection;
|
||||||
LEAVE();
|
if (EXD_IS_DIRECTORY(pExd)) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IDOS->Examine(pLock, fib) != DOSFALSE) {
|
|
||||||
if (FIB_IS_DRAWER(fib)) {
|
|
||||||
_bIsDirectory = true;
|
_bIsDirectory = true;
|
||||||
_pFileLock = IDOS->DupLock(pLock);
|
_pFileLock = IDOS->DupLock(pLock);
|
||||||
_bIsValid = _pFileLock != 0;
|
_bIsValid = _pFileLock != 0;
|
||||||
|
@ -248,25 +230,29 @@ AmigaOSFilesystemNode::AmigaOSFilesystemNode(BPTR pLock, const char *pDisplayNam
|
||||||
const char c = _sPath.lastChar();
|
const char c = _sPath.lastChar();
|
||||||
if (c != '/' && c != ':')
|
if (c != '/' && c != ':')
|
||||||
_sPath += '/';
|
_sPath += '/';
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
//_bIsDirectory = false;
|
//_bIsDirectory = false;
|
||||||
_bIsValid = true;
|
_bIsValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IDOS->FreeDosObject(DOS_EXAMINEDATA, pExd);
|
||||||
|
} else {
|
||||||
|
debug(6, "ExamineObject() returned NULL");
|
||||||
}
|
}
|
||||||
|
|
||||||
IDOS->FreeDosObject(DOS_FIB, fib);
|
|
||||||
LEAVE();
|
LEAVE();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need the custom copy constructor because of DupLock()
|
// We need the custom copy constructor because of DupLock()
|
||||||
AmigaOSFilesystemNode::AmigaOSFilesystemNode(const AmigaOSFilesystemNode& node) {
|
AmigaOSFilesystemNode::AmigaOSFilesystemNode(const AmigaOSFilesystemNode& node)
|
||||||
|
: AbstractFSNode() {
|
||||||
ENTER();
|
ENTER();
|
||||||
_sDisplayName = node._sDisplayName;
|
_sDisplayName = node._sDisplayName;
|
||||||
_bIsValid = node._bIsValid;
|
_bIsValid = node._bIsValid;
|
||||||
_bIsDirectory = node._bIsDirectory;
|
_bIsDirectory = node._bIsDirectory;
|
||||||
_sPath = node._sPath;
|
_sPath = node._sPath;
|
||||||
_pFileLock = IDOS->DupLock(node._pFileLock);
|
_pFileLock = IDOS->DupLock(node._pFileLock);
|
||||||
|
_nProt = node._nProt;
|
||||||
LEAVE();
|
LEAVE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,21 +270,29 @@ bool AmigaOSFilesystemNode::exists() const {
|
||||||
|
|
||||||
bool nodeExists = false;
|
bool nodeExists = false;
|
||||||
|
|
||||||
struct FileInfoBlock *fib = (struct FileInfoBlock *)IDOS->AllocDosObject(DOS_FIB, NULL);
|
// previously we were trying to examine the node in order
|
||||||
if (!fib) {
|
// to determine if the node exists or not.
|
||||||
debug(6, "FileInfoBlock is NULL");
|
// I don't see the point : once you have been granted a
|
||||||
LEAVE();
|
// lock on it then it means it exists...
|
||||||
return false;
|
//
|
||||||
}
|
// ============================= Old code
|
||||||
|
// BPTR pLock = IDOS->Lock((STRPTR)_sPath.c_str(), SHARED_LOCK);
|
||||||
BPTR pLock = IDOS->Lock((STRPTR)_sPath.c_str(), SHARED_LOCK);
|
// if (pLock)
|
||||||
|
// {
|
||||||
|
// if (IDOS->Examine(pLock, fib) != DOSFALSE)
|
||||||
|
// nodeExists = true;
|
||||||
|
// IDOS->UnLock(pLock);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// IDOS->FreeDosObject(DOS_FIB, fib);
|
||||||
|
//
|
||||||
|
// ============================= New code
|
||||||
|
BPTR pLock = IDOS->Lock(_sPath.c_str(), SHARED_LOCK);
|
||||||
if (pLock) {
|
if (pLock) {
|
||||||
if (IDOS->Examine(pLock, fib) != DOSFALSE)
|
|
||||||
nodeExists = true;
|
nodeExists = true;
|
||||||
IDOS->UnLock(pLock);
|
IDOS->UnLock(pLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
IDOS->FreeDosObject(DOS_FIB, fib);
|
|
||||||
LEAVE();
|
LEAVE();
|
||||||
return nodeExists;
|
return nodeExists;
|
||||||
}
|
}
|
||||||
|
@ -323,8 +317,10 @@ AbstractFSNode *AmigaOSFilesystemNode::getChild(const Common::String &n) const {
|
||||||
|
|
||||||
bool AmigaOSFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
|
bool AmigaOSFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
|
||||||
ENTER();
|
ENTER();
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
//TODO: honor the hidden flag
|
//TODO: honor the hidden flag
|
||||||
|
// There is nothing like a hidden flag under AmigaOS...
|
||||||
|
|
||||||
if (!_bIsValid) {
|
if (!_bIsValid) {
|
||||||
debug(6, "Invalid node");
|
debug(6, "Invalid node");
|
||||||
|
@ -345,85 +341,49 @@ bool AmigaOSFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ExAllControl *eac = (struct ExAllControl *)IDOS->AllocDosObject(DOS_EXALLCONTROL, 0);
|
APTR context = IDOS->ObtainDirContextTags( EX_FileLockInput, _pFileLock,
|
||||||
if (eac) {
|
EX_DoCurrentDir, TRUE, /* for softlinks */
|
||||||
struct ExAllData *data = (struct ExAllData *)IExec->AllocVec(kExAllBufferSize, MEMF_ANY);
|
EX_DataFields, (EXF_NAME|EXF_LINK|EXF_TYPE),
|
||||||
if (data) {
|
TAG_END);
|
||||||
BOOL bExMore;
|
if (context) {
|
||||||
eac->eac_LastKey = 0;
|
struct ExamineData * pExd = NULL; // NB: no need to free value after usage, all is dealt by the DirContext release
|
||||||
do {
|
|
||||||
// Examine directory
|
|
||||||
bExMore = IDOS->ExAll(_pFileLock, data, kExAllBufferSize, ED_TYPE, eac);
|
|
||||||
|
|
||||||
LONG error = IDOS->IoErr();
|
AmigaOSFilesystemNode *entry ;
|
||||||
if (!bExMore && error != ERROR_NO_MORE_ENTRIES)
|
while ( (pExd = IDOS->ExamineDir(context)) ) {
|
||||||
break; // Abnormal failure
|
if ( (EXD_IS_FILE(pExd) && ( Common::FSNode::kListFilesOnly == mode ))
|
||||||
|
|| (EXD_IS_DIRECTORY(pExd) && ( Common::FSNode::kListDirectoriesOnly == mode ))
|
||||||
if (eac->eac_Entries == 0)
|
|| Common::FSNode::kListAll == mode
|
||||||
continue; // Normal failure, no entries
|
)
|
||||||
|
{
|
||||||
struct ExAllData *ead = data;
|
BPTR pLock = IDOS->Lock( pExd->Name, SHARED_LOCK );
|
||||||
do {
|
|
||||||
if ((mode == Common::FSNode::kListAll) ||
|
|
||||||
(EAD_IS_DRAWER(ead) && (mode == Common::FSNode::kListDirectoriesOnly)) ||
|
|
||||||
(EAD_IS_FILE(ead) && (mode == Common::FSNode::kListFilesOnly))) {
|
|
||||||
Common::String full_path = _sPath;
|
|
||||||
full_path += (char*)ead->ed_Name;
|
|
||||||
|
|
||||||
BPTR lock = IDOS->Lock((STRPTR)full_path.c_str(), SHARED_LOCK);
|
|
||||||
if (lock) {
|
|
||||||
AmigaOSFilesystemNode *entry = new AmigaOSFilesystemNode(lock, (char *)ead->ed_Name);
|
|
||||||
if (entry) {
|
|
||||||
//FIXME: since the isValid() function is no longer part of the AbstractFSNode
|
|
||||||
// specification, the following call had to be changed:
|
|
||||||
// if (entry->isValid())
|
|
||||||
// Please verify that the logic of the code remains coherent. Also, remember
|
|
||||||
// that the isReadable() and isWritable() methods are available.
|
|
||||||
if (entry->exists())
|
|
||||||
myList.push_back(entry);
|
|
||||||
else
|
|
||||||
delete entry;
|
|
||||||
}
|
|
||||||
IDOS->UnLock(lock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ead = ead->ed_Next;
|
|
||||||
} while (ead);
|
|
||||||
} while (bExMore);
|
|
||||||
|
|
||||||
IExec->FreeVec(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
IDOS->FreeDosObject(DOS_EXALLCONTROL, eac);
|
|
||||||
}
|
|
||||||
|
|
||||||
LEAVE();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AmigaOSFilesystemNode::getFibProtection() const {
|
|
||||||
ENTER();
|
|
||||||
|
|
||||||
int fibProt = -1;
|
|
||||||
struct FileInfoBlock *fib = (struct FileInfoBlock *)IDOS->AllocDosObject(DOS_FIB, NULL);
|
|
||||||
if (!fib) {
|
|
||||||
debug(6, "FileInfoBlock is NULL");
|
|
||||||
LEAVE();
|
|
||||||
return fibProt;
|
|
||||||
}
|
|
||||||
|
|
||||||
BPTR pLock = IDOS->Lock((STRPTR)_sPath.c_str(), SHARED_LOCK);
|
|
||||||
if (pLock) {
|
if (pLock) {
|
||||||
if (IDOS->Examine(pLock, fib) != DOSFALSE) {
|
entry = new AmigaOSFilesystemNode( pLock, pExd->Name );
|
||||||
fibProt = fib->fib_Protection;
|
if (entry) {
|
||||||
|
myList.push_back(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
IDOS->UnLock(pLock);
|
IDOS->UnLock(pLock);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ERROR_NO_MORE_ENTRIES != IDOS->IoErr() ) {
|
||||||
|
debug(6, "An error occured during ExamineDir");
|
||||||
|
ret = false;
|
||||||
|
} else {
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IDOS->ReleaseDirContext(context);
|
||||||
|
} else {
|
||||||
|
debug(6, "Unable to ObtainDirContext");
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
IDOS->FreeDosObject(DOS_FIB, fib);
|
|
||||||
LEAVE();
|
LEAVE();
|
||||||
return fibProt;
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractFSNode *AmigaOSFilesystemNode::getParent() const {
|
AbstractFSNode *AmigaOSFilesystemNode::getParent() const {
|
||||||
|
@ -447,8 +407,7 @@ AbstractFSNode *AmigaOSFilesystemNode::getParent() const {
|
||||||
if (parentDir) {
|
if (parentDir) {
|
||||||
node = new AmigaOSFilesystemNode(parentDir);
|
node = new AmigaOSFilesystemNode(parentDir);
|
||||||
IDOS->UnLock(parentDir);
|
IDOS->UnLock(parentDir);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
node = new AmigaOSFilesystemNode();
|
node = new AmigaOSFilesystemNode();
|
||||||
|
|
||||||
LEAVE();
|
LEAVE();
|
||||||
|
@ -457,33 +416,19 @@ AbstractFSNode *AmigaOSFilesystemNode::getParent() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AmigaOSFilesystemNode::isReadable() const {
|
bool AmigaOSFilesystemNode::isReadable() const {
|
||||||
bool readable = false;
|
// Regular RWED protection flags are low-active or inverted, thus the negation.
|
||||||
int fibProt = getFibProtection();
|
// moreover pseudo root filesystem (null _pFileLock) is readable whatever the
|
||||||
|
// protection says
|
||||||
if (fibProt >= 0) {
|
bool readable = !(_nProt & EXDF_READ) || _pFileLock == 0;
|
||||||
/* The fib_Protection flag is low-active or inverted, thus the negation.
|
|
||||||
*
|
|
||||||
* For more information, consult the compiler/include/dos/dos.h
|
|
||||||
* file from the AROS source (http://aros.sourceforge.net/).
|
|
||||||
*/
|
|
||||||
readable = !(fibProt & FIBF_READ);
|
|
||||||
}
|
|
||||||
|
|
||||||
return readable;
|
return readable;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AmigaOSFilesystemNode::isWritable() const {
|
bool AmigaOSFilesystemNode::isWritable() const {
|
||||||
bool writable = false;
|
// Regular RWED protection flags are low-active or inverted, thus the negation.
|
||||||
int fibProt = getFibProtection();
|
// moreover pseudo root filesystem (null _pFileLock) is never writable whatever
|
||||||
|
// the protection says (because of the pseudo nature)
|
||||||
if (fibProt >= 0) {
|
bool writable = !(_nProt & EXDF_WRITE) && _pFileLock !=0;
|
||||||
/* The fib_Protection flag is low-active or inverted, thus the negation.
|
|
||||||
*
|
|
||||||
* For more information, consult the compiler/include/dos/dos.h
|
|
||||||
* file from the AROS source (http://aros.sourceforge.net/).
|
|
||||||
*/
|
|
||||||
writable = !(fibProt & FIBF_WRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return writable;
|
return writable;
|
||||||
}
|
}
|
||||||
|
@ -508,13 +453,10 @@ AbstractFSList AmigaOSFilesystemNode::listVolumes() const {
|
||||||
if (dosList->dol_Type == DLT_VOLUME &&
|
if (dosList->dol_Type == DLT_VOLUME &&
|
||||||
dosList->dol_Name &&
|
dosList->dol_Name &&
|
||||||
dosList->dol_Task) {
|
dosList->dol_Task) {
|
||||||
//const char *volName = (const char *)BADDR(dosList->dol_Name)+1;
|
|
||||||
|
|
||||||
// Copy name to buffer
|
// Copy name to buffer
|
||||||
IDOS->CopyStringBSTRToC(dosList->dol_Name, buffer, MAXPATHLEN);
|
IDOS->CopyStringBSTRToC(dosList->dol_Name, buffer, MAXPATHLEN);
|
||||||
|
|
||||||
//const char *devName = (const char *)((struct Task *)dosList->dol_Task->mp_SigTask)->tc_Node.ln_Name;
|
|
||||||
|
|
||||||
// Volume name + '\0'
|
// Volume name + '\0'
|
||||||
char *volName = new char [strlen(buffer) + 1];
|
char *volName = new char [strlen(buffer) + 1];
|
||||||
|
|
||||||
|
@ -536,15 +478,7 @@ AbstractFSList AmigaOSFilesystemNode::listVolumes() const {
|
||||||
|
|
||||||
AmigaOSFilesystemNode *entry = new AmigaOSFilesystemNode(volumeLock, buffer);
|
AmigaOSFilesystemNode *entry = new AmigaOSFilesystemNode(volumeLock, buffer);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
//FIXME: since the isValid() function is no longer part of the AbstractFSNode
|
|
||||||
// specification, the following call had to be changed:
|
|
||||||
// if (entry->isValid())
|
|
||||||
// Please verify that the logic of the code remains coherent. Also, remember
|
|
||||||
// that the isReadable() and isWritable() methods are available.
|
|
||||||
if(entry->exists())
|
|
||||||
myList.push_back(entry);
|
myList.push_back(entry);
|
||||||
else
|
|
||||||
delete entry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IDOS->UnLock(volumeLock);
|
IDOS->UnLock(volumeLock);
|
||||||
|
|
|
@ -33,7 +33,14 @@ AbstractFSNode *PSPFilesystemFactory::makeRootFileNode() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractFSNode *PSPFilesystemFactory::makeCurrentDirectoryFileNode() const {
|
AbstractFSNode *PSPFilesystemFactory::makeCurrentDirectoryFileNode() const {
|
||||||
return new PSPFilesystemNode();
|
char buf[MAXPATHLEN];
|
||||||
|
char * ret = 0;
|
||||||
|
|
||||||
|
PowerMan.beginCriticalSection();
|
||||||
|
ret = getcwd(buf, MAXPATHLEN);
|
||||||
|
PowerMan.endCriticalSection();
|
||||||
|
|
||||||
|
return (ret ? new PSPFilesystemNode(buf) : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractFSNode *PSPFilesystemFactory::makeFileNodePath(const Common::String &path) const {
|
AbstractFSNode *PSPFilesystemFactory::makeFileNodePath(const Common::String &path) const {
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#include "engines/engine.h"
|
#include "engines/engine.h"
|
||||||
#include "backends/fs/abstract-fs.h"
|
#include "backends/fs/abstract-fs.h"
|
||||||
#include "backends/fs/stdiostream.h"
|
#include "backends/fs/psp/psp-stream.h"
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -35,6 +35,8 @@
|
||||||
|
|
||||||
#define ROOT_PATH "ms0:/"
|
#define ROOT_PATH "ms0:/"
|
||||||
|
|
||||||
|
#include "backends/platform/psp/trace.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of the ScummVM file system API based on PSPSDK API.
|
* Implementation of the ScummVM file system API based on PSPSDK API.
|
||||||
*
|
*
|
||||||
|
@ -59,15 +61,15 @@ public:
|
||||||
* @param path Common::String with the path the new node should point to.
|
* @param path Common::String with the path the new node should point to.
|
||||||
* @param verify true if the isValid and isDirectory flags should be verified during the construction.
|
* @param verify true if the isValid and isDirectory flags should be verified during the construction.
|
||||||
*/
|
*/
|
||||||
PSPFilesystemNode(const Common::String &p, bool verify);
|
PSPFilesystemNode(const Common::String &p, bool verify = true);
|
||||||
|
|
||||||
virtual bool exists() const { return access(_path.c_str(), F_OK) == 0; }
|
virtual bool exists() const;
|
||||||
virtual Common::String getDisplayName() const { return _displayName; }
|
virtual Common::String getDisplayName() const { return _displayName; }
|
||||||
virtual Common::String getName() const { return _displayName; }
|
virtual Common::String getName() const { return _displayName; }
|
||||||
virtual Common::String getPath() const { return _path; }
|
virtual Common::String getPath() const { return _path; }
|
||||||
virtual bool isDirectory() const { return _isDirectory; }
|
virtual bool isDirectory() const { return _isDirectory; }
|
||||||
virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; }
|
virtual bool isReadable() const;
|
||||||
virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; }
|
virtual bool isWritable() const;
|
||||||
|
|
||||||
virtual AbstractFSNode *getChild(const Common::String &n) const;
|
virtual AbstractFSNode *getChild(const Common::String &n) const;
|
||||||
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
|
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
|
||||||
|
@ -94,11 +96,51 @@ PSPFilesystemNode::PSPFilesystemNode(const Common::String &p, bool verify) {
|
||||||
|
|
||||||
if (verify) {
|
if (verify) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
if (PowerMan.beginCriticalSection()==PowerManager::Blocked)
|
||||||
|
PSPDebugSuspend("Suspended in PSPFilesystemNode::PSPFilesystemNode\n");
|
||||||
_isValid = (0 == stat(_path.c_str(), &st));
|
_isValid = (0 == stat(_path.c_str(), &st));
|
||||||
|
PowerMan.endCriticalSection();
|
||||||
_isDirectory = S_ISDIR(st.st_mode);
|
_isDirectory = S_ISDIR(st.st_mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PSPFilesystemNode::exists() const {
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
|
||||||
|
PSPDebugSuspend("Suspended in PSPFilesystemNode::exists()\n"); // Make sure to block in case of suspend
|
||||||
|
|
||||||
|
ret = access(_path.c_str(), F_OK);
|
||||||
|
PowerMan.endCriticalSection();
|
||||||
|
|
||||||
|
return ret == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PSPFilesystemNode::isReadable() const {
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
|
||||||
|
PSPDebugSuspend("Suspended in PSPFilesystemNode::isReadable()\n"); // Make sure to block in case of suspend
|
||||||
|
|
||||||
|
ret = access(_path.c_str(), R_OK);
|
||||||
|
PowerMan.endCriticalSection();
|
||||||
|
|
||||||
|
return ret == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PSPFilesystemNode::isWritable() const {
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
|
||||||
|
PSPDebugSuspend("Suspended in PSPFilesystemNode::isWritable()\n"); // Make sure to block in case of suspend
|
||||||
|
|
||||||
|
ret = access(_path.c_str(), W_OK);
|
||||||
|
PowerMan.endCriticalSection();
|
||||||
|
|
||||||
|
return ret == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
AbstractFSNode *PSPFilesystemNode::getChild(const Common::String &n) const {
|
AbstractFSNode *PSPFilesystemNode::getChild(const Common::String &n) const {
|
||||||
// FIXME: Pretty lame implementation! We do no error checking to speak
|
// FIXME: Pretty lame implementation! We do no error checking to speak
|
||||||
// of, do not check if this is a special node, etc.
|
// of, do not check if this is a special node, etc.
|
||||||
|
@ -117,6 +159,11 @@ bool PSPFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool
|
||||||
|
|
||||||
//TODO: honor the hidden flag
|
//TODO: honor the hidden flag
|
||||||
|
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
|
||||||
|
PSPDebugSuspend("Suspended in PSPFilesystemNode::getChildren\n"); // Make sure to block in case of suspend
|
||||||
|
|
||||||
int dfd = sceIoDopen(_path.c_str());
|
int dfd = sceIoDopen(_path.c_str());
|
||||||
if (dfd > 0) {
|
if (dfd > 0) {
|
||||||
SceIoDirent dir;
|
SceIoDirent dir;
|
||||||
|
@ -149,10 +196,13 @@ bool PSPFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
sceIoDclose(dfd);
|
sceIoDclose(dfd);
|
||||||
return true;
|
ret = true;
|
||||||
} else {
|
} else { // dfd <= 0
|
||||||
return false;
|
ret = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PowerMan.endCriticalSection();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractFSNode *PSPFilesystemNode::getParent() const {
|
AbstractFSNode *PSPFilesystemNode::getParent() const {
|
||||||
|
@ -166,11 +216,11 @@ AbstractFSNode *PSPFilesystemNode::getParent() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::SeekableReadStream *PSPFilesystemNode::createReadStream() {
|
Common::SeekableReadStream *PSPFilesystemNode::createReadStream() {
|
||||||
return StdioStream::makeFromPath(getPath().c_str(), false);
|
return PSPIoStream::makeFromPath(getPath(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::WriteStream *PSPFilesystemNode::createWriteStream() {
|
Common::WriteStream *PSPFilesystemNode::createWriteStream() {
|
||||||
return StdioStream::makeFromPath(getPath().c_str(), true);
|
return PSPIoStream::makeFromPath(getPath(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //#ifdef __PSP__
|
#endif //#ifdef __PSP__
|
||||||
|
|
303
backends/fs/psp/psp-stream.cpp
Normal file
303
backends/fs/psp/psp-stream.cpp
Normal file
|
@ -0,0 +1,303 @@
|
||||||
|
/* 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$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifdef __PSP__
|
||||||
|
|
||||||
|
#include <SDL/SDL_thread.h>
|
||||||
|
#include <SDL/SDL_mutex.h>
|
||||||
|
|
||||||
|
#include "backends/platform/psp/trace.h"
|
||||||
|
#include "backends/platform/psp/powerman.h"
|
||||||
|
#include "backends/fs/psp/psp-stream.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
PSPIoStream::PSPIoStream(const Common::String &path, bool writeMode)
|
||||||
|
: StdioStream((void *)1), _path(path), _writeMode(writeMode) {
|
||||||
|
|
||||||
|
assert(!path.empty());
|
||||||
|
|
||||||
|
_handle = (void *)0; // Need to do this since base class asserts not 0.
|
||||||
|
_ferror = false;
|
||||||
|
_feof = false;
|
||||||
|
_pos = 0;
|
||||||
|
|
||||||
|
#ifdef __PSP_DEBUG_SUSPEND__
|
||||||
|
_errorSuspend = 0;
|
||||||
|
_errorSource = 0;
|
||||||
|
_errorPos = 0;
|
||||||
|
_errorHandle = 0;
|
||||||
|
_suspendCount = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
PSPIoStream::~PSPIoStream() {
|
||||||
|
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
|
||||||
|
PSPDebugSuspend("Suspended in PSPIoStream::~PSPIoStream()\n");
|
||||||
|
|
||||||
|
PowerMan.unregisterSuspend(this); // Unregister with powermanager to be suspended
|
||||||
|
// Must do this before fclose() or resume() will reopen.
|
||||||
|
|
||||||
|
fclose((FILE *)_handle); // We don't need a critical section(?). Worst case, the handle gets closed on its own
|
||||||
|
|
||||||
|
PowerMan.endCriticalSection();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to open the file pointed to by the path.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
void *PSPIoStream::open() {
|
||||||
|
if (PowerMan.beginCriticalSection() == PowerManager::Blocked) {
|
||||||
|
// No need to open. Just return the _handle resume() already opened.
|
||||||
|
PSPDebugSuspend("Suspended in PSPIoStream::open\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
_handle = fopen(_path.c_str(), _writeMode ? "wb" : "rb"); // open
|
||||||
|
|
||||||
|
PowerMan.registerSuspend(this); // Register with the powermanager to be suspended
|
||||||
|
|
||||||
|
PowerMan.endCriticalSection();
|
||||||
|
|
||||||
|
return _handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PSPIoStream::err() const {
|
||||||
|
if (_ferror)
|
||||||
|
PSPDebugSuspend("In PSPIoStream::err - mem_ferror=%d, source=%d, suspend error=%d, pos=%d, _errorPos=%d, _errorHandle=%p, suspendCount=%d _handle\n",
|
||||||
|
_ferror, _errorSource, _errorSuspend, _pos, _errorPos, _errorHandle, _suspendCount);
|
||||||
|
|
||||||
|
return _ferror;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PSPIoStream::clearErr() {
|
||||||
|
_ferror = false; // Remove regular error bit
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PSPIoStream::eos() const {
|
||||||
|
return _feof;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 PSPIoStream::pos() const {
|
||||||
|
return _pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32 PSPIoStream::size() const {
|
||||||
|
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
|
||||||
|
PSPDebugSuspend("Suspended in PSPIoStream::size()\n");
|
||||||
|
|
||||||
|
fseek((FILE *)_handle, 0, SEEK_END);
|
||||||
|
int32 length = ftell((FILE *)_handle);
|
||||||
|
fseek((FILE *)_handle, _pos, SEEK_SET);
|
||||||
|
|
||||||
|
if (_pos < 0 || length < 0) { // Check for errors
|
||||||
|
PSPDebugSuspend("In PSPIoStream::size(). encountered an error!\n");
|
||||||
|
_ferror = true;
|
||||||
|
length = -1; // If our oldPos is bad, we want length to be bad too to signal
|
||||||
|
clearerr((FILE *)_handle);
|
||||||
|
|
||||||
|
#ifdef __PSP_DEBUG_SUSPEND__
|
||||||
|
_errorSource = 2;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
PowerMan.endCriticalSection();
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PSPIoStream::seek(int32 offs, int whence) {
|
||||||
|
// Check if we can access the file
|
||||||
|
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
|
||||||
|
PSPDebugSuspend("Suspended in PSPIoStream::seek()\n");
|
||||||
|
|
||||||
|
int ret = fseek((FILE *)_handle, offs, whence);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
_ferror = true;
|
||||||
|
PSPDebugSuspend("In PSPIoStream::seek(). encountered an error!\n");
|
||||||
|
clearerr((FILE *)_handle);
|
||||||
|
_feof = feof((FILE *)_handle);
|
||||||
|
|
||||||
|
#ifdef __PSP_DEBUG_SUSPEND__
|
||||||
|
_errorSource = 3;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else { // everything ok
|
||||||
|
_feof = false; // Reset eof flag since we know it was ok
|
||||||
|
}
|
||||||
|
|
||||||
|
_pos = ftell((FILE *)_handle); // update pos
|
||||||
|
|
||||||
|
PowerMan.endCriticalSection();
|
||||||
|
|
||||||
|
return ret == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 PSPIoStream::read(void *ptr, uint32 len) {
|
||||||
|
// Check if we can access the file
|
||||||
|
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
|
||||||
|
PSPDebugSuspend("Suspended in PSPIoStream::read()\n");
|
||||||
|
|
||||||
|
size_t ret = fread((byte *)ptr, 1, len, (FILE *)_handle);
|
||||||
|
|
||||||
|
_pos += ret; // Update pos
|
||||||
|
|
||||||
|
if (ret != len) { // Check for eof
|
||||||
|
_feof = feof((FILE *)_handle);
|
||||||
|
if (!_feof) { // It wasn't an eof. Must be an error
|
||||||
|
_ferror = true;
|
||||||
|
clearerr((FILE *)_handle);
|
||||||
|
_pos = ftell((FILE *)_handle); // Update our position
|
||||||
|
PSPDebugSuspend("In PSPIoStream::read(). encountered an error!\n");
|
||||||
|
|
||||||
|
#ifdef __PSP_DEBUG_SUSPEND__
|
||||||
|
_errorSource = 4;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PowerMan.endCriticalSection();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 PSPIoStream::write(const void *ptr, uint32 len) {
|
||||||
|
// Check if we can access the file
|
||||||
|
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
|
||||||
|
PSPDebugSuspend("Suspended in PSPIoStream::read()\n");
|
||||||
|
|
||||||
|
size_t ret = fwrite(ptr, 1, len, (FILE *)_handle);
|
||||||
|
|
||||||
|
_pos += ret;
|
||||||
|
|
||||||
|
if (ret != len) { // Set error
|
||||||
|
_ferror = true;
|
||||||
|
clearerr((FILE *)_handle);
|
||||||
|
_pos = ftell((FILE *)_handle); // Update pos
|
||||||
|
PSPDebugTrace("In PSPIoStream::write(). encountered an error!\n");
|
||||||
|
|
||||||
|
#ifdef __PSP_DEBUG_SUSPEND__
|
||||||
|
_errorSource = 5;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
PowerMan.endCriticalSection();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PSPIoStream::flush() {
|
||||||
|
// Enter critical section
|
||||||
|
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
|
||||||
|
PSPDebugSuspend("Suspended in PSPIoStream::read()\n");
|
||||||
|
|
||||||
|
int ret = fflush((FILE *)_handle);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
_ferror = true;
|
||||||
|
clearerr((FILE *)_handle);
|
||||||
|
PSPDebugSuspend("In PSPIoStream::flush(). encountered an error!\n");
|
||||||
|
|
||||||
|
#ifdef __PSP_DEBUG_SUSPEND__
|
||||||
|
_errorSource = 6;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
PowerMan.endCriticalSection();
|
||||||
|
|
||||||
|
return ret == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For the PSP, since we're building in suspend support, we moved opening
|
||||||
|
// the actual file to an open function since we need an actual PSPIoStream object to suspend.
|
||||||
|
//
|
||||||
|
PSPIoStream *PSPIoStream::makeFromPath(const Common::String &path, bool writeMode) {
|
||||||
|
PSPIoStream *stream = new PSPIoStream(path, writeMode);
|
||||||
|
|
||||||
|
if (stream->open() > 0) {
|
||||||
|
return stream;
|
||||||
|
} else {
|
||||||
|
delete stream;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function to suspend the IO stream (called by PowerManager)
|
||||||
|
*/
|
||||||
|
int PSPIoStream::suspend() {
|
||||||
|
#ifdef __PSP_DEBUG_SUSPEND__
|
||||||
|
_suspendCount++;
|
||||||
|
|
||||||
|
if (_handle > 0 && _pos < 0) {
|
||||||
|
_errorSuspend = SuspendError;
|
||||||
|
_errorPos = _pos;
|
||||||
|
_errorHandle = _handle;
|
||||||
|
}
|
||||||
|
#endif /* __PSP_DEBUG_SUSPEND__ */
|
||||||
|
|
||||||
|
if (_handle > 0) {
|
||||||
|
fclose((FILE *)_handle); // close our file descriptor
|
||||||
|
_handle = (void *)0xFFFFFFFF; // Set handle to non-null invalid value so makeFromPath doesn't return error
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function to resume the IO stream (called by Power Manager)
|
||||||
|
*/
|
||||||
|
int PSPIoStream::resume() {
|
||||||
|
int ret = 0;
|
||||||
|
#ifdef __PSP_DEBUG_SUSPEND__
|
||||||
|
_suspendCount--;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// We reopen our file descriptor
|
||||||
|
_handle = fopen(_path.c_str(), _writeMode ? "wb" : "rb");
|
||||||
|
if (_handle <= 0) {
|
||||||
|
PSPDebugSuspend("PSPIoStream::resume(): Couldn't reopen file %s\n", _path.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resume our previous position
|
||||||
|
if (_handle > 0 && _pos > 0) {
|
||||||
|
ret = fseek((FILE *)_handle, _pos, SEEK_SET);
|
||||||
|
|
||||||
|
#ifdef __PSP_DEBUG_SUSPEND__
|
||||||
|
if (ret != 0) { // Check for problem
|
||||||
|
_errorSuspend = ResumeError;
|
||||||
|
_errorPos = _pos;
|
||||||
|
_errorHandle = _handle;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __PSP__ */
|
86
backends/fs/psp/psp-stream.h
Normal file
86
backends/fs/psp/psp-stream.h
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/* 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 PSPSTREAM_H_
|
||||||
|
#define PSPSTREAM_H_
|
||||||
|
|
||||||
|
#include "backends/fs/stdiostream.h"
|
||||||
|
#include "backends/platform/psp/powerman.h"
|
||||||
|
#include "common/list.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class to handle special suspend/resume needs of PSP IO Streams
|
||||||
|
*/
|
||||||
|
class PSPIoStream : public StdioStream, public Suspendable {
|
||||||
|
protected:
|
||||||
|
Common::String _path; /* Need to maintain for reopening after suspend */
|
||||||
|
bool _writeMode; /* "" */
|
||||||
|
int _pos; /* "" */
|
||||||
|
mutable int _ferror; /* Save file ferror */
|
||||||
|
mutable bool _feof; /* and eof */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SuspendError = 2,
|
||||||
|
ResumeError = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
int _errorSuspend;
|
||||||
|
mutable int _errorSource;
|
||||||
|
|
||||||
|
#ifdef __PSP_DEBUG_SUSPEND__
|
||||||
|
int _errorPos;
|
||||||
|
void * _errorHandle;
|
||||||
|
int _suspendCount;
|
||||||
|
#endif /* __PSP_DEBUG_SUSPEND__ */
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Given a path, invoke fopen on that path and wrap the result in a
|
||||||
|
* PSPIoStream instance.
|
||||||
|
*/
|
||||||
|
static PSPIoStream *makeFromPath(const Common::String &path, bool writeMode);
|
||||||
|
|
||||||
|
PSPIoStream(const Common::String &path, bool writeMode);
|
||||||
|
virtual ~PSPIoStream();
|
||||||
|
|
||||||
|
void * open(); // open the file pointed to by the file path
|
||||||
|
|
||||||
|
bool err() const;
|
||||||
|
void clearErr();
|
||||||
|
bool eos() const;
|
||||||
|
|
||||||
|
virtual uint32 write(const void *dataPtr, uint32 dataSize);
|
||||||
|
virtual bool flush();
|
||||||
|
|
||||||
|
virtual int32 pos() const;
|
||||||
|
virtual int32 size() const;
|
||||||
|
virtual bool seek(int32 offs, int whence = SEEK_SET);
|
||||||
|
virtual uint32 read(void *dataPtr, uint32 dataSize);
|
||||||
|
|
||||||
|
int suspend(); /* Suspendable interface (power manager) */
|
||||||
|
int resume(); /* " " */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* PSPSTREAM_H_ */
|
|
@ -46,17 +46,17 @@ public:
|
||||||
StdioStream(void *handle);
|
StdioStream(void *handle);
|
||||||
virtual ~StdioStream();
|
virtual ~StdioStream();
|
||||||
|
|
||||||
bool err() const;
|
virtual bool err() const;
|
||||||
void clearErr();
|
virtual void clearErr();
|
||||||
bool eos() const;
|
virtual bool eos() const;
|
||||||
|
|
||||||
virtual uint32 write(const void *dataPtr, uint32 dataSize);
|
virtual uint32 write(const void *dataPtr, uint32 dataSize);
|
||||||
virtual bool flush();
|
virtual bool flush();
|
||||||
|
|
||||||
virtual int32 pos() const;
|
virtual int32 pos() const;
|
||||||
virtual int32 size() const;
|
virtual int32 size() const;
|
||||||
bool seek(int32 offs, int whence = SEEK_SET);
|
virtual bool seek(int32 offs, int whence = SEEK_SET);
|
||||||
uint32 read(void *dataPtr, uint32 dataSize);
|
virtual uint32 read(void *dataPtr, uint32 dataSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -168,6 +168,15 @@ void Keymapper::popKeymap() {
|
||||||
_activeMaps.pop();
|
_activeMaps.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Keymapper::notifyEvent(const Common::Event &ev) {
|
||||||
|
if (ev.type == Common::EVENT_KEYDOWN)
|
||||||
|
return mapKeyDown(ev.kbd);
|
||||||
|
else if (ev.type == Common::EVENT_KEYUP)
|
||||||
|
return mapKeyUp(ev.kbd);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Keymapper::mapKeyDown(const KeyState& key) {
|
bool Keymapper::mapKeyDown(const KeyState& key) {
|
||||||
return mapKey(key, true);
|
return mapKey(key, true);
|
||||||
}
|
}
|
||||||
|
@ -255,7 +264,7 @@ void Keymapper::executeAction(const Action *action, bool keyDown) {
|
||||||
}
|
}
|
||||||
|
|
||||||
evt.mouse = _eventMan->getMousePos();
|
evt.mouse = _eventMan->getMousePos();
|
||||||
_eventMan->pushEvent(evt);
|
addEvent(evt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
class Keymapper {
|
class Keymapper : public Common::EventMapper, private Common::ArtificialEventSource {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct MapRecord {
|
struct MapRecord {
|
||||||
|
@ -134,6 +134,10 @@ public:
|
||||||
*/
|
*/
|
||||||
void popKeymap();
|
void popKeymap();
|
||||||
|
|
||||||
|
// Implementation of the EventMapper interface
|
||||||
|
bool notifyEvent(const Common::Event &ev);
|
||||||
|
bool pollEvent(Common::Event &ev) { return Common::ArtificialEventSource::pollEvent(ev); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Map a key press event.
|
* @brief Map a key press event.
|
||||||
* If the active keymap contains a Action mapped to the given key, then
|
* If the active keymap contains a Action mapped to the given key, then
|
||||||
|
|
|
@ -187,6 +187,8 @@ bool OSystem_SDL::pollEvent(Common::Event &event) {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
while (SDL_PollEvent(&ev)) {
|
while (SDL_PollEvent(&ev)) {
|
||||||
|
preprocessEvents(&ev);
|
||||||
|
|
||||||
switch (ev.type) {
|
switch (ev.type) {
|
||||||
case SDL_KEYDOWN:{
|
case SDL_KEYDOWN:{
|
||||||
b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState());
|
b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState());
|
||||||
|
|
|
@ -26,6 +26,13 @@
|
||||||
#include "backends/platform/sdl/sdl.h"
|
#include "backends/platform/sdl/sdl.h"
|
||||||
#include "common/mutex.h"
|
#include "common/mutex.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
#ifdef USE_RGB_COLOR
|
||||||
|
#include "common/list.h"
|
||||||
|
#endif
|
||||||
|
#include "graphics/font.h"
|
||||||
|
#include "graphics/fontman.h"
|
||||||
|
#include "graphics/scaler.h"
|
||||||
|
#include "graphics/surface.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -354,6 +361,11 @@ void OSystem_SDL::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, i
|
||||||
SDL_UnlockSurface(_overlayscreen);
|
SDL_UnlockSurface(_overlayscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark --- Mouse ---
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
bool OSystem_SDL::showMouse(bool visible) {
|
bool OSystem_SDL::showMouse(bool visible) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -396,7 +408,17 @@ void OSystem_SDL::warpMouse(int x, int y) {
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor, int cursorTargetScale) {
|
void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) {
|
||||||
|
#ifdef USE_RGB_COLOR
|
||||||
|
if (!format)
|
||||||
|
_cursorFormat = Graphics::PixelFormat::createFormatCLUT8();
|
||||||
|
else if (format->bytesPerPixel <= _screenFormat.bytesPerPixel)
|
||||||
|
_cursorFormat = *format;
|
||||||
|
keycolor &= (1 << (_cursorFormat.bytesPerPixel << 3)) - 1;
|
||||||
|
#else
|
||||||
|
keycolor &= 0xFF;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (w == 0 || h == 0)
|
if (w == 0 || h == 0)
|
||||||
return;
|
return;
|
||||||
/* Residual doesn't support this
|
/* Residual doesn't support this
|
||||||
|
@ -430,9 +452,13 @@ void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x,
|
||||||
}
|
}
|
||||||
|
|
||||||
free(_mouseData);
|
free(_mouseData);
|
||||||
|
#ifdef USE_RGB_COLOR
|
||||||
|
_mouseData = (byte *)malloc(w * h * _cursorFormat.bytesPerPixel);
|
||||||
|
memcpy(_mouseData, buf, w * h * _cursorFormat.bytesPerPixel);
|
||||||
|
#else
|
||||||
_mouseData = (byte *)malloc(w * h);
|
_mouseData = (byte *)malloc(w * h);
|
||||||
memcpy(_mouseData, buf, w * h);
|
memcpy(_mouseData, buf, w * h);
|
||||||
|
#endif
|
||||||
blitCursor();*/
|
blitCursor();*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
#include "SymbianOs.h"
|
#include "SymbianOs.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(__MAEMO__) && !defined(_WIN32_WCE) && !defined(GP2XWIZ)
|
#if !defined(__MAEMO__) && !defined(_WIN32_WCE) && !defined(GP2XWIZ)&& !defined(LINUXMOTO)
|
||||||
|
|
||||||
#if defined (WIN32)
|
#if defined (WIN32)
|
||||||
int __stdcall WinMain(HINSTANCE /*hInst*/, HINSTANCE /*hPrevInst*/, LPSTR /*lpCmdLine*/, int /*iShowCmd*/) {
|
int __stdcall WinMain(HINSTANCE /*hInst*/, HINSTANCE /*hPrevInst*/, LPSTR /*lpCmdLine*/, int /*iShowCmd*/) {
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
#include "common/archive.h"
|
#include "common/archive.h"
|
||||||
#include "common/config-manager.h"
|
#include "common/config-manager.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/events.h"
|
#include "common/EventRecorder.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
|
@ -215,7 +215,7 @@ OSystem_SDL::~OSystem_SDL() {
|
||||||
|
|
||||||
uint32 OSystem_SDL::getMillis() {
|
uint32 OSystem_SDL::getMillis() {
|
||||||
uint32 millis = SDL_GetTicks();
|
uint32 millis = SDL_GetTicks();
|
||||||
getEventManager()->processMillis(millis);
|
g_eventRec.processMillis(millis);
|
||||||
return millis;
|
return millis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,13 +349,20 @@ Common::WriteStream *OSystem_SDL::createConfigWriteStream() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSystem_SDL::setWindowCaption(const char *caption) {
|
void OSystem_SDL::setWindowCaption(const char *caption) {
|
||||||
Common::String cap(caption);
|
Common::String cap;
|
||||||
|
byte c;
|
||||||
|
|
||||||
|
// The string caption is supposed to be in LATIN-1 encoding.
|
||||||
|
// SDL expects UTF-8. So we perform the conversion here.
|
||||||
|
while ((c = *(const byte *)caption++)) {
|
||||||
|
if (c < 0x80)
|
||||||
|
cap += c;
|
||||||
|
else {
|
||||||
|
cap += 0xC0 | (c >> 6);
|
||||||
|
cap += 0x80 | (c & 0x3F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Filter out any non-ASCII characters, replacing them by question marks.
|
|
||||||
// At some point, we may wish to allow LATIN 1 or UTF-8.
|
|
||||||
for (uint i = 0; i < cap.size(); ++i)
|
|
||||||
if ((byte)cap[i] > 0x7F)
|
|
||||||
cap.setChar('?', i);
|
|
||||||
SDL_WM_SetCaption(cap.c_str(), cap.c_str());
|
SDL_WM_SetCaption(cap.c_str(), cap.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,7 +592,6 @@ void OSystem_SDL::mixCallback(void *sys, byte *samples, int len) {
|
||||||
|
|
||||||
void OSystem_SDL::setupMixer() {
|
void OSystem_SDL::setupMixer() {
|
||||||
SDL_AudioSpec desired;
|
SDL_AudioSpec desired;
|
||||||
SDL_AudioSpec obtained;
|
|
||||||
|
|
||||||
// Determine the desired output sampling frequency.
|
// Determine the desired output sampling frequency.
|
||||||
_samplesPerSec = 0;
|
_samplesPerSec = 0;
|
||||||
|
@ -615,7 +621,7 @@ void OSystem_SDL::setupMixer() {
|
||||||
_mixer = new Audio::MixerImpl(this);
|
_mixer = new Audio::MixerImpl(this);
|
||||||
assert(_mixer);
|
assert(_mixer);
|
||||||
|
|
||||||
if (SDL_OpenAudio(&desired, &obtained) != 0) {
|
if (SDL_OpenAudio(&desired, &_obtainedRate) != 0) {
|
||||||
warning("Could not open audio device: %s", SDL_GetError());
|
warning("Could not open audio device: %s", SDL_GetError());
|
||||||
_samplesPerSec = 0;
|
_samplesPerSec = 0;
|
||||||
_mixer->setReady(false);
|
_mixer->setReady(false);
|
||||||
|
@ -623,7 +629,7 @@ void OSystem_SDL::setupMixer() {
|
||||||
// Note: This should be the obtained output rate, but it seems that at
|
// 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
|
// 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.
|
// even if it didn't. Probably only happens for "weird" rates, though.
|
||||||
_samplesPerSec = obtained.freq;
|
_samplesPerSec = _obtainedRate.freq;
|
||||||
debug(1, "Output sample rate: %d Hz", _samplesPerSec);
|
debug(1, "Output sample rate: %d Hz", _samplesPerSec);
|
||||||
|
|
||||||
// Tell the mixer that we are ready and start the sound processing
|
// Tell the mixer that we are ready and start the sound processing
|
||||||
|
@ -631,7 +637,7 @@ void OSystem_SDL::setupMixer() {
|
||||||
_mixer->setReady(true);
|
_mixer->setReady(true);
|
||||||
|
|
||||||
#ifdef MIXER_DOUBLE_BUFFERING
|
#ifdef MIXER_DOUBLE_BUFFERING
|
||||||
initThreadedMixer(_mixer, obtained.samples * 4);
|
initThreadedMixer(_mixer, _obtainedRate.samples * 4);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// start the sound system
|
// start the sound system
|
||||||
|
|
|
@ -77,7 +77,7 @@ public:
|
||||||
virtual void warpMouse(int x, int y); // overloaded by CE backend (FIXME)
|
virtual void warpMouse(int x, int y); // overloaded by CE backend (FIXME)
|
||||||
|
|
||||||
// Set the bitmap that's used when drawing the cursor.
|
// Set the bitmap that's used when drawing the cursor.
|
||||||
virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor, int cursorTargetScale); // overloaded by CE backend (FIXME)
|
virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format); // overloaded by CE backend (FIXME)
|
||||||
|
|
||||||
// Get the number of milliseconds since the program was started.
|
// Get the number of milliseconds since the program was started.
|
||||||
uint32 getMillis();
|
uint32 getMillis();
|
||||||
|
@ -127,6 +127,7 @@ public:
|
||||||
|
|
||||||
// Overlay
|
// Overlay
|
||||||
virtual Graphics::PixelFormat getOverlayFormat() const { return _overlayFormat; }
|
virtual Graphics::PixelFormat getOverlayFormat() const { return _overlayFormat; }
|
||||||
|
|
||||||
virtual void showOverlay();
|
virtual void showOverlay();
|
||||||
virtual void hideOverlay();
|
virtual void hideOverlay();
|
||||||
virtual void clearOverlay();
|
virtual void clearOverlay();
|
||||||
|
@ -143,6 +144,7 @@ public:
|
||||||
virtual bool hasFeature(Feature f);
|
virtual bool hasFeature(Feature f);
|
||||||
virtual void setFeatureState(Feature f, bool enable);
|
virtual void setFeatureState(Feature f, bool enable);
|
||||||
virtual bool getFeatureState(Feature f);
|
virtual bool getFeatureState(Feature f);
|
||||||
|
virtual void preprocessEvents(SDL_Event *event) {};
|
||||||
|
|
||||||
virtual Common::SaveFileManager *getSavefileManager();
|
virtual Common::SaveFileManager *getSavefileManager();
|
||||||
virtual FilesystemFactory *getFilesystemFactory();
|
virtual FilesystemFactory *getFilesystemFactory();
|
||||||
|
@ -153,6 +155,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool _inited;
|
bool _inited;
|
||||||
|
SDL_AudioSpec _obtainedRate;
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_OPENGL
|
#ifdef USE_OPENGL
|
||||||
|
|
|
@ -55,11 +55,14 @@ void DefaultSaveFileManager::checkPath(const Common::FSNode &dir) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::StringList DefaultSaveFileManager::listSavefiles(const Common::String &pattern) {
|
Common::StringList DefaultSaveFileManager::listSavefiles(const Common::String &pattern) {
|
||||||
Common::FSNode savePath(getSavePath());
|
Common::String savePathName = getSavePath();
|
||||||
checkPath(savePath);
|
checkPath(Common::FSNode(savePathName));
|
||||||
if (getError() != Common::kNoError)
|
if (getError() != Common::kNoError)
|
||||||
return Common::StringList();
|
return Common::StringList();
|
||||||
|
|
||||||
|
// recreate FSNode since checkPath may have changed/created the directory
|
||||||
|
Common::FSNode savePath(savePathName);
|
||||||
|
|
||||||
Common::FSDirectory dir(savePath);
|
Common::FSDirectory dir(savePath);
|
||||||
Common::ArchiveMemberList savefiles;
|
Common::ArchiveMemberList savefiles;
|
||||||
Common::StringList results;
|
Common::StringList results;
|
||||||
|
@ -76,11 +79,14 @@ Common::StringList DefaultSaveFileManager::listSavefiles(const Common::String &p
|
||||||
|
|
||||||
Common::InSaveFile *DefaultSaveFileManager::openForLoading(const Common::String &filename) {
|
Common::InSaveFile *DefaultSaveFileManager::openForLoading(const Common::String &filename) {
|
||||||
// Ensure that the savepath is valid. If not, generate an appropriate error.
|
// Ensure that the savepath is valid. If not, generate an appropriate error.
|
||||||
Common::FSNode savePath(getSavePath());
|
Common::String savePathName = getSavePath();
|
||||||
checkPath(savePath);
|
checkPath(Common::FSNode(savePathName));
|
||||||
if (getError() != Common::kNoError)
|
if (getError() != Common::kNoError)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// recreate FSNode since checkPath may have changed/created the directory
|
||||||
|
Common::FSNode savePath(savePathName);
|
||||||
|
|
||||||
Common::FSNode file = savePath.getChild(filename);
|
Common::FSNode file = savePath.getChild(filename);
|
||||||
if (!file.exists())
|
if (!file.exists())
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -93,11 +99,14 @@ Common::InSaveFile *DefaultSaveFileManager::openForLoading(const Common::String
|
||||||
|
|
||||||
Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const Common::String &filename) {
|
Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const Common::String &filename) {
|
||||||
// Ensure that the savepath is valid. If not, generate an appropriate error.
|
// Ensure that the savepath is valid. If not, generate an appropriate error.
|
||||||
Common::FSNode savePath(getSavePath());
|
Common::String savePathName = getSavePath();
|
||||||
checkPath(savePath);
|
checkPath(Common::FSNode(savePathName));
|
||||||
if (getError() != Common::kNoError)
|
if (getError() != Common::kNoError)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// recreate FSNode since checkPath may have changed/created the directory
|
||||||
|
Common::FSNode savePath(savePathName);
|
||||||
|
|
||||||
Common::FSNode file = savePath.getChild(filename);
|
Common::FSNode file = savePath.getChild(filename);
|
||||||
|
|
||||||
// Open the file for saving
|
// Open the file for saving
|
||||||
|
@ -107,13 +116,14 @@ Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const Common::String
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DefaultSaveFileManager::removeSavefile(const Common::String &filename) {
|
bool DefaultSaveFileManager::removeSavefile(const Common::String &filename) {
|
||||||
clearError();
|
Common::String savePathName = getSavePath();
|
||||||
|
checkPath(Common::FSNode(savePathName));
|
||||||
Common::FSNode savePath(getSavePath());
|
|
||||||
checkPath(savePath);
|
|
||||||
if (getError() != Common::kNoError)
|
if (getError() != Common::kNoError)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// recreate FSNode since checkPath may have changed/created the directory
|
||||||
|
Common::FSNode savePath(savePathName);
|
||||||
|
|
||||||
Common::FSNode file = savePath.getChild(filename);
|
Common::FSNode file = savePath.getChild(filename);
|
||||||
|
|
||||||
// FIXME: remove does not exist on all systems. If your port fails to
|
// FIXME: remove does not exist on all systems. If your port fails to
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#ifdef __PSP__
|
#ifdef __PSP__
|
||||||
|
|
||||||
#include "backends/saves/psp/psp-saves.h"
|
#include "backends/saves/psp/psp-saves.h"
|
||||||
|
#include "backends/platform/psp/powerman.h"
|
||||||
|
|
||||||
#include "common/config-manager.h"
|
#include "common/config-manager.h"
|
||||||
#include "common/savefile.h"
|
#include "common/savefile.h"
|
||||||
|
@ -49,6 +50,8 @@ void PSPSaveFileManager::checkPath(const Common::FSNode &dir) {
|
||||||
const char *savePath = dir.getPath().c_str();
|
const char *savePath = dir.getPath().c_str();
|
||||||
clearError();
|
clearError();
|
||||||
|
|
||||||
|
PowerMan.beginCriticalSection();
|
||||||
|
|
||||||
//check if the save directory exists
|
//check if the save directory exists
|
||||||
SceUID fd = sceIoDopen(savePath);
|
SceUID fd = sceIoDopen(savePath);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
@ -58,6 +61,8 @@ void PSPSaveFileManager::checkPath(const Common::FSNode &dir) {
|
||||||
//it exists, so close it again.
|
//it exists, so close it again.
|
||||||
sceIoDclose(fd);
|
sceIoDclose(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PowerMan.endCriticalSection();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,12 @@ bool DefaultTimerManager::installTimerProc(TimerProc callback, int32 interval, v
|
||||||
slot->nextFireTimeMicro = interval % 1000;
|
slot->nextFireTimeMicro = interval % 1000;
|
||||||
slot->next = 0;
|
slot->next = 0;
|
||||||
|
|
||||||
|
// FIXME: It seems we do allow the client to add one callback multiple times over here,
|
||||||
|
// but "removeTimerProc" will remove *all* added instances. We should either prevent
|
||||||
|
// multiple additions of a timer proc OR we should change removeTimerProc to only remove
|
||||||
|
// a specific timer proc entry.
|
||||||
|
// Probably we can safely just allow a single addition of a specific function once
|
||||||
|
// and just update our Timer documentation accordingly.
|
||||||
insertPrioQueue(_head, slot);
|
insertPrioQueue(_head, slot);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ScummVM - Graphic Adventure Engine
|
/* Residual - A 3D game interpreter
|
||||||
*
|
*
|
||||||
* ScummVM is the legal property of its developers, whose names
|
* Residual is the legal property of its developers, whose names
|
||||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
* are too numerous to list here. Please refer to the AUTHORS
|
||||||
* file distributed with this source distribution.
|
* file distributed with this source distribution.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ScummVM - Graphic Adventure Engine
|
/* Residual - A 3D game interpreter
|
||||||
*
|
*
|
||||||
* ScummVM is the legal property of its developers, whose names
|
* Residual is the legal property of its developers, whose names
|
||||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
* are too numerous to list here. Please refer to the AUTHORS
|
||||||
* file distributed with this source distribution.
|
* file distributed with this source distribution.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ScummVM - Graphic Adventure Engine
|
/* Residual - A 3D game interpreter
|
||||||
*
|
*
|
||||||
* ScummVM is the legal property of its developers, whose names
|
* Residual is the legal property of its developers, whose names
|
||||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
* are too numerous to list here. Please refer to the AUTHORS
|
||||||
* file distributed with this source distribution.
|
* file distributed with this source distribution.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ScummVM - Graphic Adventure Engine
|
/* Residual - A 3D game interpreter
|
||||||
*
|
*
|
||||||
* ScummVM is the legal property of its developers, whose names
|
* Residual is the legal property of its developers, whose names
|
||||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
* are too numerous to list here. Please refer to the AUTHORS
|
||||||
* file distributed with this source distribution.
|
* file distributed with this source distribution.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ScummVM - Graphic Adventure Engine
|
/* Residual - A 3D game interpreter
|
||||||
*
|
*
|
||||||
* ScummVM is the legal property of its developers, whose names
|
* Residual is the legal property of its developers, whose names
|
||||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
* are too numerous to list here. Please refer to the AUTHORS
|
||||||
* file distributed with this source distribution.
|
* file distributed with this source distribution.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ScummVM - Graphic Adventure Engine
|
/* Residual - A 3D game interpreter
|
||||||
*
|
*
|
||||||
* ScummVM is the legal property of its developers, whose names
|
* Residual is the legal property of its developers, whose names
|
||||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
* are too numerous to list here. Please refer to the AUTHORS
|
||||||
* file distributed with this source distribution.
|
* file distributed with this source distribution.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ScummVM - Graphic Adventure Engine
|
/* Residual - A 3D game interpreter
|
||||||
*
|
*
|
||||||
* ScummVM is the legal property of its developers, whose names
|
* Residual is the legal property of its developers, whose names
|
||||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
* are too numerous to list here. Please refer to the AUTHORS
|
||||||
* file distributed with this source distribution.
|
* file distributed with this source distribution.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ScummVM - Graphic Adventure Engine
|
/* Residual - A 3D game interpreter
|
||||||
*
|
*
|
||||||
* ScummVM is the legal property of its developers, whose names
|
* Residual is the legal property of its developers, whose names
|
||||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
* are too numerous to list here. Please refer to the AUTHORS
|
||||||
* file distributed with this source distribution.
|
* file distributed with this source distribution.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ScummVM - Graphic Adventure Engine
|
/* Residual - A 3D game interpreter
|
||||||
*
|
*
|
||||||
* ScummVM is the legal property of its developers, whose names
|
* Residual is the legal property of its developers, whose names
|
||||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
* are too numerous to list here. Please refer to the AUTHORS
|
||||||
* file distributed with this source distribution.
|
* file distributed with this source distribution.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
@ -31,7 +31,6 @@
|
||||||
#include "backends/vkeybd/virtual-keyboard-parser.h"
|
#include "backends/vkeybd/virtual-keyboard-parser.h"
|
||||||
#include "backends/vkeybd/keycode-descriptions.h"
|
#include "backends/vkeybd/keycode-descriptions.h"
|
||||||
#include "common/config-manager.h"
|
#include "common/config-manager.h"
|
||||||
#include "common/fs.h"
|
|
||||||
#include "common/unzip.h"
|
#include "common/unzip.h"
|
||||||
|
|
||||||
#define KEY_START_CHAR ('[')
|
#define KEY_START_CHAR ('[')
|
||||||
|
@ -77,50 +76,76 @@ void VirtualKeyboard::reset() {
|
||||||
_kbdGUI->reset();
|
_kbdGUI->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VirtualKeyboard::loadKeyboardPack(String packName) {
|
bool VirtualKeyboard::openPack(const String &packName, const FSNode &node) {
|
||||||
|
if (node.getChild(packName + ".xml").exists()) {
|
||||||
|
_fileArchive = new FSDirectory(node, 1);
|
||||||
|
|
||||||
|
// uncompressed keyboard pack
|
||||||
|
if (!_parser->loadFile(node.getChild(packName + ".xml"))) {
|
||||||
|
delete _fileArchive;
|
||||||
|
_fileArchive = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_ZLIB
|
||||||
|
if (node.getChild(packName + ".zip").exists()) {
|
||||||
|
// compressed keyboard pack
|
||||||
|
_fileArchive = new ZipArchive(node.getChild(packName + ".zip"));
|
||||||
|
if (_fileArchive->hasFile(packName + ".xml")) {
|
||||||
|
if (!_parser->loadStream(_fileArchive->createReadStreamForMember(packName + ".xml"))) {
|
||||||
|
delete _fileArchive;
|
||||||
|
_fileArchive = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warning("Could not find %s.xml file in %s.zip keyboard pack", packName.c_str(), packName.c_str());
|
||||||
|
delete _fileArchive;
|
||||||
|
_fileArchive = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VirtualKeyboard::loadKeyboardPack(const String &packName) {
|
||||||
_kbdGUI->initSize(_system->getOverlayWidth(), _system->getOverlayHeight());
|
_kbdGUI->initSize(_system->getOverlayWidth(), _system->getOverlayHeight());
|
||||||
|
|
||||||
delete _fileArchive;
|
delete _fileArchive;
|
||||||
_fileArchive = 0;
|
_fileArchive = 0;
|
||||||
|
_loaded = false;
|
||||||
|
|
||||||
FSNode vkDir;
|
bool opened = false;
|
||||||
if (ConfMan.hasKey("vkeybdpath"))
|
if (ConfMan.hasKey("vkeybdpath"))
|
||||||
vkDir = FSNode(ConfMan.get("vkeybdpath"));
|
opened = openPack(packName, FSNode(ConfMan.get("vkeybdpath")));
|
||||||
else if (ConfMan.hasKey("extrapath"))
|
else if (ConfMan.hasKey("extrapath"))
|
||||||
vkDir = FSNode(ConfMan.get("extrapath"));
|
opened = openPack(packName, FSNode(ConfMan.get("extrapath")));
|
||||||
else // use current directory
|
|
||||||
vkDir = FSNode(".");
|
|
||||||
|
|
||||||
if (vkDir.getChild(packName + ".xml").exists()) {
|
// fallback to the current dir
|
||||||
_fileArchive = new FSDirectory(vkDir, 1);
|
if (!opened)
|
||||||
|
opened = openPack(packName, FSNode("."));
|
||||||
// uncompressed keyboard pack
|
|
||||||
if (!_parser->loadFile(vkDir.getChild(packName + ".xml")))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
} else if (vkDir.getChild(packName + ".zip").exists()) {
|
|
||||||
// compressed keyboard pack
|
|
||||||
#ifdef USE_ZLIB
|
|
||||||
_fileArchive = new ZipArchive(vkDir.getChild(packName + ".zip"));
|
|
||||||
if (_fileArchive->hasFile(packName + ".xml")) {
|
|
||||||
if (!_parser->loadStream(_fileArchive->createReadStreamForMember(packName + ".xml")))
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
warning("Could not find %s.xml file in %s.zip keyboard pack", packName.c_str(), packName.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
warning("Keyboard pack not found");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (opened) {
|
||||||
_parser->setParseMode(VirtualKeyboardParser::kParseFull);
|
_parser->setParseMode(VirtualKeyboardParser::kParseFull);
|
||||||
_loaded = _parser->parse();
|
_loaded = _parser->parse();
|
||||||
if (_loaded)
|
|
||||||
|
if (_loaded) {
|
||||||
printf("Keyboard pack '%s' loaded successfully!\n", packName.c_str());
|
printf("Keyboard pack '%s' loaded successfully!\n", packName.c_str());
|
||||||
|
} else {
|
||||||
|
warning("Error parsing the keyboard pack '%s'", packName.c_str());
|
||||||
|
|
||||||
|
delete _fileArchive;
|
||||||
|
_fileArchive = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warning("Keyboard pack not found");
|
||||||
|
}
|
||||||
|
|
||||||
return _loaded;
|
return _loaded;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ScummVM - Graphic Adventure Engine
|
/* Residual - A 3D game interpreter
|
||||||
*
|
*
|
||||||
* ScummVM is the legal property of its developers, whose names
|
* Residual is the legal property of its developers, whose names
|
||||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
* are too numerous to list here. Please refer to the AUTHORS
|
||||||
* file distributed with this source distribution.
|
* file distributed with this source distribution.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
@ -37,6 +37,7 @@ class OSystem;
|
||||||
#include "common/keyboard.h"
|
#include "common/keyboard.h"
|
||||||
#include "common/list.h"
|
#include "common/list.h"
|
||||||
#include "common/str.h"
|
#include "common/str.h"
|
||||||
|
#include "common/fs.h"
|
||||||
|
|
||||||
#include "backends/vkeybd/image-map.h"
|
#include "backends/vkeybd/image-map.h"
|
||||||
#include "graphics/surface.h"
|
#include "graphics/surface.h"
|
||||||
|
@ -190,7 +191,7 @@ public:
|
||||||
* searches for a compressed keyboard pack by looking for packName.zip.
|
* searches for a compressed keyboard pack by looking for packName.zip.
|
||||||
* @param packName name of the keyboard pack
|
* @param packName name of the keyboard pack
|
||||||
*/
|
*/
|
||||||
bool loadKeyboardPack(String packName);
|
bool loadKeyboardPack(const String &packName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the keyboard, starting an event loop that will intercept all
|
* Shows the keyboard, starting an event loop that will intercept all
|
||||||
|
@ -232,6 +233,7 @@ protected:
|
||||||
VirtualKeyboardParser *_parser;
|
VirtualKeyboardParser *_parser;
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
bool openPack(const String &packName, const FSNode &node);
|
||||||
void deleteEvents();
|
void deleteEvents();
|
||||||
bool checkModeResolutions();
|
bool checkModeResolutions();
|
||||||
void switchMode(Mode *newMode);
|
void switchMode(Mode *newMode);
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
|
|
||||||
#include "gui/ThemeEngine.h"
|
#include "gui/ThemeEngine.h"
|
||||||
|
|
||||||
|
#define DETECTOR_TESTING_HACK
|
||||||
|
#define UPGRADE_ALL_TARGETS_HACK
|
||||||
|
|
||||||
namespace Base {
|
namespace Base {
|
||||||
|
|
||||||
#ifndef DISABLE_COMMAND_LINE
|
#ifndef DISABLE_COMMAND_LINE
|
||||||
|
@ -235,6 +238,18 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
|
||||||
DO_COMMAND('z', "list-games")
|
DO_COMMAND('z', "list-games")
|
||||||
END_OPTION
|
END_OPTION
|
||||||
|
|
||||||
|
#ifdef DETECTOR_TESTING_HACK
|
||||||
|
// HACK FIXME TODO: This command is intentionally *not* documented!
|
||||||
|
DO_LONG_COMMAND("test-detector")
|
||||||
|
END_OPTION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UPGRADE_ALL_TARGETS_HACK
|
||||||
|
// HACK FIXME TODO: This command is intentionally *not* documented!
|
||||||
|
DO_LONG_COMMAND("upgrade-targets")
|
||||||
|
END_OPTION
|
||||||
|
#endif
|
||||||
|
|
||||||
DO_OPTION('c', "config")
|
DO_OPTION('c', "config")
|
||||||
END_OPTION
|
END_OPTION
|
||||||
|
|
||||||
|
@ -253,10 +268,13 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
|
||||||
DO_OPTION_INT('m', "music-volume")
|
DO_OPTION_INT('m', "music-volume")
|
||||||
END_OPTION
|
END_OPTION
|
||||||
|
|
||||||
DO_OPTION('s', "sfx-volume")
|
DO_OPTION('p', "path")
|
||||||
END_OPTION
|
Common::FSNode path(option);
|
||||||
|
if (!path.exists()) {
|
||||||
DO_OPTION('r', "speech-volume")
|
usage("Non-existent game path '%s'", option);
|
||||||
|
} else if (!path.isReadable()) {
|
||||||
|
usage("Non-readable game path '%s'", option);
|
||||||
|
}
|
||||||
END_OPTION
|
END_OPTION
|
||||||
|
|
||||||
DO_OPTION('q', "language")
|
DO_OPTION('q', "language")
|
||||||
|
@ -264,6 +282,15 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
|
||||||
usage("Unrecognized language '%s'", option);
|
usage("Unrecognized language '%s'", option);
|
||||||
END_OPTION
|
END_OPTION
|
||||||
|
|
||||||
|
DO_OPTION_INT('s', "sfx-volume")
|
||||||
|
END_OPTION
|
||||||
|
|
||||||
|
DO_OPTION_INT('r', "speech-volume")
|
||||||
|
END_OPTION
|
||||||
|
|
||||||
|
DO_LONG_OPTION_INT("cdrom")
|
||||||
|
END_OPTION
|
||||||
|
|
||||||
DO_LONG_OPTION_OPT("joystick", "0")
|
DO_LONG_OPTION_OPT("joystick", "0")
|
||||||
settings["joystick_num"] = option;
|
settings["joystick_num"] = option;
|
||||||
settings.erase("joystick");
|
settings.erase("joystick");
|
||||||
|
@ -275,24 +302,15 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
|
||||||
DO_LONG_OPTION("soft-renderer")
|
DO_LONG_OPTION("soft-renderer")
|
||||||
END_OPTION
|
END_OPTION
|
||||||
|
|
||||||
|
DO_LONG_OPTION_BOOL("disable-sdl-parachute")
|
||||||
|
END_OPTION
|
||||||
|
|
||||||
DO_LONG_OPTION("engine-speed")
|
DO_LONG_OPTION("engine-speed")
|
||||||
END_OPTION
|
END_OPTION
|
||||||
|
|
||||||
DO_LONG_OPTION("gamma")
|
DO_LONG_OPTION("gamma")
|
||||||
END_OPTION
|
END_OPTION
|
||||||
|
|
||||||
DO_OPTION('p', "path")
|
|
||||||
Common::FSNode path(option);
|
|
||||||
if (!path.exists()) {
|
|
||||||
usage("Non-existent game path '%s'", option);
|
|
||||||
} else if (!path.isReadable()) {
|
|
||||||
usage("Non-readable game path '%s'", option);
|
|
||||||
}
|
|
||||||
END_OPTION
|
|
||||||
|
|
||||||
DO_LONG_OPTION_BOOL("disable-sdl-parachute")
|
|
||||||
END_OPTION
|
|
||||||
|
|
||||||
DO_LONG_OPTION("savepath")
|
DO_LONG_OPTION("savepath")
|
||||||
Common::FSNode path(option);
|
Common::FSNode path(option);
|
||||||
if (!path.exists()) {
|
if (!path.exists()) {
|
||||||
|
@ -326,8 +344,15 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
|
||||||
DO_LONG_COMMAND("list-themes")
|
DO_LONG_COMMAND("list-themes")
|
||||||
END_OPTION
|
END_OPTION
|
||||||
|
|
||||||
|
DO_LONG_OPTION("target-md5")
|
||||||
|
END_OPTION
|
||||||
|
|
||||||
DO_LONG_OPTION("text-speed")
|
DO_LONG_OPTION("text-speed")
|
||||||
END_OPTION
|
END_OPTION
|
||||||
|
#ifdef ENABLE_SCUMM
|
||||||
|
DO_LONG_OPTION_INT("dimuse-tempo")
|
||||||
|
END_OPTION
|
||||||
|
#endif
|
||||||
|
|
||||||
DO_LONG_OPTION("speech-mode")
|
DO_LONG_OPTION("speech-mode")
|
||||||
END_OPTION
|
END_OPTION
|
||||||
|
@ -414,6 +439,192 @@ static void listThemes() {
|
||||||
printf("%-14s %s\n", i->id.c_str(), i->name.c_str());
|
printf("%-14s %s\n", i->id.c_str(), i->name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DETECTOR_TESTING_HACK
|
||||||
|
static void runDetectorTest() {
|
||||||
|
// HACK: The following code can be used to test the detection code of our
|
||||||
|
// engines. Basically, it loops over all targets, and calls the detector
|
||||||
|
// for the given path. It then prints out the result and also checks
|
||||||
|
// whether the result agrees with the settings of the target.
|
||||||
|
|
||||||
|
const Common::ConfigManager::DomainMap &domains = ConfMan.getGameDomains();
|
||||||
|
Common::ConfigManager::DomainMap::const_iterator iter = domains.begin();
|
||||||
|
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"));
|
||||||
|
printf("Looking at target '%s', gameid '%s', path '%s' ...\n",
|
||||||
|
name.c_str(), gameid.c_str(), path.c_str());
|
||||||
|
if (path.empty()) {
|
||||||
|
printf(" ... no path specified, skipping\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (gameid.empty()) {
|
||||||
|
gameid = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::FSNode dir(path);
|
||||||
|
Common::FSList files;
|
||||||
|
if (!dir.getChildren(files, Common::FSNode::kListAll)) {
|
||||||
|
printf(" ... invalid path, skipping\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameList candidates(EngineMan.detectGames(files));
|
||||||
|
bool gameidDiffers = false;
|
||||||
|
GameList::iterator x;
|
||||||
|
for (x = candidates.begin(); x != candidates.end(); ++x) {
|
||||||
|
gameidDiffers |= (strcasecmp(gameid.c_str(), x->gameid().c_str()) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (candidates.empty()) {
|
||||||
|
printf(" FAILURE: No games detected\n");
|
||||||
|
failure++;
|
||||||
|
} else if (candidates.size() > 1) {
|
||||||
|
if (gameidDiffers) {
|
||||||
|
printf(" WARNING: Multiple games detected, some/all with wrong gameid\n");
|
||||||
|
} else {
|
||||||
|
printf(" WARNING: Multiple games detected, but all have matching gameid\n");
|
||||||
|
}
|
||||||
|
failure++;
|
||||||
|
} else if (gameidDiffers) {
|
||||||
|
printf(" FAILURE: Wrong gameid detected\n");
|
||||||
|
failure++;
|
||||||
|
} else {
|
||||||
|
printf(" SUCCESS: Game was detected correctly\n");
|
||||||
|
success++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (x = candidates.begin(); x != candidates.end(); ++x) {
|
||||||
|
printf(" gameid '%s', desc '%s', language '%s', platform '%s'\n",
|
||||||
|
x->gameid().c_str(),
|
||||||
|
x->description().c_str(),
|
||||||
|
Common::getLanguageCode(x->language()),
|
||||||
|
Common::getPlatformCode(x->platform()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int total = domains.size();
|
||||||
|
printf("Detector test run: %d fail, %d success, %d skipped, out of %d\n",
|
||||||
|
failure, success, total - failure - success, total);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UPGRADE_ALL_TARGETS_HACK
|
||||||
|
void upgradeTargets() {
|
||||||
|
// HACK: The following upgrades all your targets to the latest and
|
||||||
|
// greatest. Right now that means updating the guioptions and (optionally)
|
||||||
|
// also the game descriptions.
|
||||||
|
// Basically, it loops over all targets, and calls the detector for the
|
||||||
|
// given path. It then compares the result with the settings of the target.
|
||||||
|
// If the basics seem to match, it updates the guioptions.
|
||||||
|
|
||||||
|
printf("Upgrading all your existing targets\n");
|
||||||
|
|
||||||
|
Common::ConfigManager::DomainMap &domains = ConfMan.getGameDomains();
|
||||||
|
Common::ConfigManager::DomainMap::iterator iter = domains.begin();
|
||||||
|
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"));
|
||||||
|
printf("Looking at target '%s', gameid '%s' ...\n",
|
||||||
|
name.c_str(), gameid.c_str());
|
||||||
|
if (path.empty()) {
|
||||||
|
printf(" ... no path specified, skipping\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (gameid.empty()) {
|
||||||
|
gameid = name;
|
||||||
|
}
|
||||||
|
gameid.toLowercase(); // TODO: Is this paranoia? Maybe we should just assume all lowercase, always?
|
||||||
|
|
||||||
|
Common::FSNode dir(path);
|
||||||
|
Common::FSList files;
|
||||||
|
if (!dir.getChildren(files, Common::FSNode::kListAll)) {
|
||||||
|
printf(" ... invalid path, skipping\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::Language lang = Common::parseLanguage(dom.get("language"));
|
||||||
|
Common::Platform plat = Common::parsePlatform(dom.get("platform"));
|
||||||
|
Common::String desc(dom.get("description"));
|
||||||
|
|
||||||
|
GameList candidates(EngineMan.detectGames(files));
|
||||||
|
GameDescriptor *g = 0;
|
||||||
|
|
||||||
|
// We proceed as follows:
|
||||||
|
// * If detection failed to produce candidates, skip.
|
||||||
|
// * If there is a unique detector match, trust it.
|
||||||
|
// * If there are multiple match, run over them comparing gameid, language and platform.
|
||||||
|
// If we end up with a unique match, use it. Otherwise, skip.
|
||||||
|
if (candidates.size() == 0) {
|
||||||
|
printf(" ... failed to detect game, skipping\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (candidates.size() > 1) {
|
||||||
|
// Scan over all candidates, check if there is a unique match for gameid, language and platform
|
||||||
|
GameList::iterator x;
|
||||||
|
int matchesFound = 0;
|
||||||
|
for (x = candidates.begin(); x != candidates.end(); ++x) {
|
||||||
|
if (x->gameid() == gameid && x->language() == lang && x->platform() == plat) {
|
||||||
|
matchesFound++;
|
||||||
|
g = &(*x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (matchesFound != 1) {
|
||||||
|
printf(" ... detected multiple games, could not establish unique match, skipping\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Unique match -> use it
|
||||||
|
g = &candidates[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point, g points to a GameDescriptor which we can use to update
|
||||||
|
// the target referred to by dom. We update several things
|
||||||
|
|
||||||
|
// Always set the gameid explicitly (in case of legacy targets)
|
||||||
|
dom["gameid"] = g->gameid();
|
||||||
|
|
||||||
|
// Always set the GUI options. The user should not modify them, and engines might
|
||||||
|
// gain more features over time, so we want to keep this list up-to-date.
|
||||||
|
if (g->contains("guioptions")) {
|
||||||
|
printf(" -> update guioptions to '%s'\n", (*g)["guioptions"].c_str());
|
||||||
|
dom["guioptions"] = (*g)["guioptions"];
|
||||||
|
} else if (dom.contains("guioptions")) {
|
||||||
|
dom.erase("guioptions");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the language setting but only if none has been set yet.
|
||||||
|
if (lang == Common::UNK_LANG && g->language() != Common::UNK_LANG) {
|
||||||
|
printf(" -> set language to '%s'\n", Common::getLanguageCode(g->language()));
|
||||||
|
dom["language"] = (*g)["language"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the platform setting but only if none has been set yet.
|
||||||
|
if (plat == Common::kPlatformUnknown && g->platform() != Common::kPlatformUnknown) {
|
||||||
|
printf(" -> set platform to '%s'\n", Common::getPlatformCode(g->platform()));
|
||||||
|
dom["platform"] = (*g)["platform"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: We could also update the description. But not everybody will want that.
|
||||||
|
// Esp. because for some games (e.g. the combined Zak/Loom FM-TOWNS demo etc.)
|
||||||
|
// ScummVM still generates an incorrect description string. So, the description
|
||||||
|
// should only be updated if the user explicitly requests this.
|
||||||
|
#if 0
|
||||||
|
if (desc != g->description()) {
|
||||||
|
printf(" -> update desc from '%s' to\n '%s' ?\n", desc.c_str(), g->description().c_str());
|
||||||
|
dom["description"] = (*g)["description"];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, save our changes to disk
|
||||||
|
ConfMan.flushToDisk();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#else // DISABLE_COMMAND_LINE
|
#else // DISABLE_COMMAND_LINE
|
||||||
|
|
||||||
|
|
||||||
|
@ -449,6 +660,18 @@ bool processSettings(Common::String &command, Common::StringMap &settings) {
|
||||||
printf(HELP_STRING, s_appName);
|
printf(HELP_STRING, s_appName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#ifdef DETECTOR_TESTING_HACK
|
||||||
|
else if (command == "test-detector") {
|
||||||
|
runDetectorTest();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef UPGRADE_ALL_TARGETS_HACK
|
||||||
|
else if (command == "upgrade-targets") {
|
||||||
|
upgradeTargets();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // DISABLE_COMMAND_LINE
|
#endif // DISABLE_COMMAND_LINE
|
||||||
|
|
||||||
|
|
|
@ -41,12 +41,16 @@
|
||||||
#include "common/config-manager.h"
|
#include "common/config-manager.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/events.h"
|
#include "common/events.h"
|
||||||
|
#include "common/EventRecorder.h"
|
||||||
#include "common/file.h"
|
#include "common/file.h"
|
||||||
#include "common/fs.h"
|
#include "common/fs.h"
|
||||||
#include "common/system.h"
|
#include "common/system.h"
|
||||||
|
|
||||||
#include "gui/GuiManager.h"
|
#include "gui/GuiManager.h"
|
||||||
#include "gui/message.h"
|
#include "gui/message.h"
|
||||||
|
|
||||||
|
#include "sound/audiocd.h"
|
||||||
|
|
||||||
#include "backends/keymapper/keymapper.h"
|
#include "backends/keymapper/keymapper.h"
|
||||||
|
|
||||||
#if defined(_WIN32_WCE)
|
#if defined(_WIN32_WCE)
|
||||||
|
@ -168,9 +172,9 @@ static Common::Error runGame(const EnginePlugin *plugin, OSystem &system, const
|
||||||
// Set the window caption to the game name
|
// Set the window caption to the game name
|
||||||
Common::String caption(ConfMan.get("description"));
|
Common::String caption(ConfMan.get("description"));
|
||||||
|
|
||||||
Common::String desc = EngineMan.findGame(ConfMan.get("gameid")).description();
|
if (caption.empty()) {
|
||||||
if (caption.empty() && !desc.empty())
|
caption = EngineMan.findGame(ConfMan.get("gameid")).description();
|
||||||
caption = desc;
|
}
|
||||||
if (caption.empty())
|
if (caption.empty())
|
||||||
caption = ConfMan.getActiveDomainName(); // Use the domain (=target) name
|
caption = ConfMan.getActiveDomainName(); // Use the domain (=target) name
|
||||||
if (!caption.empty()) {
|
if (!caption.empty()) {
|
||||||
|
@ -341,6 +345,14 @@ extern "C" int residual_main(int argc, const char * const argv[]) {
|
||||||
// take place after the backend is initiated and the screen has been setup
|
// take place after the backend is initiated and the screen has been setup
|
||||||
system.getEventManager()->init();
|
system.getEventManager()->init();
|
||||||
|
|
||||||
|
// Directly after initializing the event manager, we will initialize our
|
||||||
|
// event recorder.
|
||||||
|
//
|
||||||
|
// TODO: This is just to match the current behavior, when we further extend
|
||||||
|
// our event recorder, we might do this at another place. Or even change
|
||||||
|
// the whole API for that ;-).
|
||||||
|
g_eventRec.init();
|
||||||
|
|
||||||
// Now as the event manager is created, setup the keymapper
|
// Now as the event manager is created, setup the keymapper
|
||||||
setupKeymapper(system);
|
setupKeymapper(system);
|
||||||
|
|
||||||
|
@ -368,11 +380,15 @@ extern "C" int residual_main(int argc, const char * const argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quit unless an error occurred, or Return to launcher was requested
|
// Quit unless an error occurred, or Return to launcher was requested
|
||||||
|
#ifndef FORCE_RTL
|
||||||
if (result == 0 && !g_system->getEventManager()->shouldRTL())
|
if (result == 0 && !g_system->getEventManager()->shouldRTL())
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
// Reset RTL flag in case we want to load another engine
|
// Reset RTL flag in case we want to load another engine
|
||||||
g_system->getEventManager()->resetRTL();
|
g_system->getEventManager()->resetRTL();
|
||||||
|
#ifdef FORCE_RTL
|
||||||
|
g_system->getEventManager()->resetQuit();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Discard any command line options. It's unlikely that the user
|
// Discard any command line options. It's unlikely that the user
|
||||||
// wanted to apply them to *all* games ever launched.
|
// wanted to apply them to *all* games ever launched.
|
||||||
|
@ -389,6 +405,15 @@ extern "C" int residual_main(int argc, const char * const argv[]) {
|
||||||
warning("Could not find any engine capable of running the selected game");
|
warning("Could not find any engine capable of running the selected game");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We will destroy the AudioCDManager singleton here to save some memory.
|
||||||
|
// This will not make the CD audio stop, one would have to enable this:
|
||||||
|
//AudioCD.stop();
|
||||||
|
// but the engine is responsible for stopping CD playback anyway and
|
||||||
|
// this way we catch engines not doing it properly. For some more
|
||||||
|
// information about why AudioCDManager::destroy does not stop the CD
|
||||||
|
// playback read the FIXME in sound/audiocd.h
|
||||||
|
Audio::AudioCDManager::destroy();
|
||||||
|
|
||||||
// reset the graphics to default
|
// reset the graphics to default
|
||||||
setupGraphics(system);
|
setupGraphics(system);
|
||||||
launcherDialog();
|
launcherDialog();
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
|
|
||||||
#include "common/sys.h"
|
#include "common/sys.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// The residual main entry point, to be invoked by ports
|
||||||
|
//
|
||||||
extern "C" int residual_main(int argc, const char *const argv[]);
|
extern "C" int residual_main(int argc, const char *const argv[]);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,9 +23,39 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "common/sys.h"
|
||||||
#include "base/internal_version.h"
|
#include "base/internal_version.h"
|
||||||
#include "base/version.h"
|
#include "base/version.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Version string and build date string. These can be used by anything that
|
||||||
|
* wants to display this information to the user (e.g. about dialog).
|
||||||
|
*
|
||||||
|
* Note: it would be very nice if we could instead of (or in addition to) the
|
||||||
|
* build date present a date which corresponds to the date our source files
|
||||||
|
* were last changed. To understand the difference, imagine that a user
|
||||||
|
* makes a checkout on January 1, then after a week compiles it
|
||||||
|
* (e.g. after doing a 'make clean'). The build date then will say January 8
|
||||||
|
* even though the files were last changed on January 1.
|
||||||
|
*
|
||||||
|
* Another problem is that __DATE__/__TIME__ depend on the local time zone.
|
||||||
|
*
|
||||||
|
* It's clear that such a "last changed" date would be much more useful to us
|
||||||
|
* for feedback purposes. After all, when somebody files a bug report, we
|
||||||
|
* don't care about the build date, we want to know which date their checkout
|
||||||
|
* was made.
|
||||||
|
*
|
||||||
|
* So, how could we implement this? At least on unix systems, a special script
|
||||||
|
* could do it. Basically, that script could parse the output of "svn info" or
|
||||||
|
* "svnversion" to determine the revision of the checkout, and insert that
|
||||||
|
* information somehow into the build process (e.g. by generating a tiny
|
||||||
|
* header file, analog to internal_version.h, maybe called svn_rev.h or so.)
|
||||||
|
*
|
||||||
|
* Drawback: This only works on systems which can run suitable scripts as part
|
||||||
|
* of the build proces (so I guess Visual C++ would be out of the game here?
|
||||||
|
* I don't know VC enough to be sure). And of course it must be robust enough
|
||||||
|
* to properly work in exports (i.e. release tar balls etc.).
|
||||||
|
*/
|
||||||
const char *gResidualVersion = RESIDUAL_VERSION;
|
const char *gResidualVersion = RESIDUAL_VERSION;
|
||||||
const char *gResidualBuildDate = __DATE__ " " __TIME__;
|
const char *gResidualBuildDate = __DATE__ " " __TIME__;
|
||||||
const char *gResidualVersionDate = RESIDUAL_VERSION " (" __DATE__ " " __TIME__ ")";
|
const char *gResidualVersionDate = RESIDUAL_VERSION " (" __DATE__ " " __TIME__ ")";
|
||||||
|
@ -52,6 +82,14 @@ const char *gResidualFeatures = ""
|
||||||
"MP3 "
|
"MP3 "
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_ALSA
|
||||||
|
"ALSA "
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_RGB_COLOR
|
||||||
|
"RGB "
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_ZLIB
|
#ifdef USE_ZLIB
|
||||||
"zLib "
|
"zLib "
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* Residual is the legal property of its developers, whose names
|
* Residual is the legal property of its developers, whose names
|
||||||
* are too numerous to list here. Please refer to the AUTHORS
|
* are too numerous to list here. Please refer to the AUTHORS
|
||||||
* file distributed with this source distribution.
|
* file distributed with this source distribution.
|
||||||
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation; either version 2
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
|
138
common/EventDispatcher.cpp
Normal file
138
common/EventDispatcher.cpp
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
/* 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/events.h"
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
EventDispatcher::EventDispatcher() : _mapper(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
EventDispatcher::~EventDispatcher() {
|
||||||
|
for (Common::List<SourceEntry>::iterator i = _sources.begin(); i != _sources.end(); ++i) {
|
||||||
|
if (i->autoFree)
|
||||||
|
delete i->source;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Common::List<ObserverEntry>::iterator i = _observers.begin(); i != _observers.end(); ++i) {
|
||||||
|
if (i->autoFree)
|
||||||
|
delete i->observer;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete _mapper;
|
||||||
|
_mapper = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventDispatcher::dispatch() {
|
||||||
|
Common::Event event;
|
||||||
|
|
||||||
|
for (Common::List<SourceEntry>::iterator i = _sources.begin(); i != _sources.end(); ++i) {
|
||||||
|
const bool allowMapping = i->source->allowMapping();
|
||||||
|
|
||||||
|
while (i->source->pollEvent(event)) {
|
||||||
|
// We only try to process the events via the setup event mapper, when
|
||||||
|
// we have a setup mapper and when the event source allows mapping.
|
||||||
|
if (_mapper && allowMapping) {
|
||||||
|
if (_mapper->notifyEvent(event)) {
|
||||||
|
// We allow the event mapper to create multiple events, when
|
||||||
|
// eating an event.
|
||||||
|
while (_mapper->pollEvent(event))
|
||||||
|
dispatchEvent(event);
|
||||||
|
|
||||||
|
// Try getting another event from the current EventSource.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatchEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventDispatcher::registerMapper(EventMapper *mapper) {
|
||||||
|
if (_mapper)
|
||||||
|
delete _mapper;
|
||||||
|
_mapper = mapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventDispatcher::registerSource(EventSource *source, bool autoFree) {
|
||||||
|
SourceEntry newEntry;
|
||||||
|
|
||||||
|
newEntry.source = source;
|
||||||
|
newEntry.autoFree = autoFree;
|
||||||
|
|
||||||
|
_sources.push_back(newEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventDispatcher::unregisterSource(EventSource *source) {
|
||||||
|
for (Common::List<SourceEntry>::iterator i = _sources.begin(); i != _sources.end(); ++i) {
|
||||||
|
if (i->source == source) {
|
||||||
|
if (i->autoFree)
|
||||||
|
delete source;
|
||||||
|
|
||||||
|
_sources.erase(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventDispatcher::registerObserver(EventObserver *obs, uint priority, bool autoFree) {
|
||||||
|
ObserverEntry newEntry;
|
||||||
|
|
||||||
|
newEntry.observer = obs;
|
||||||
|
newEntry.priority = priority;
|
||||||
|
newEntry.autoFree = autoFree;
|
||||||
|
|
||||||
|
for (Common::List<ObserverEntry>::iterator i = _observers.begin(); i != _observers.end(); ++i) {
|
||||||
|
if (i->priority < priority) {
|
||||||
|
_observers.insert(i, newEntry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_observers.push_back(newEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventDispatcher::unregisterObserver(EventObserver *obs) {
|
||||||
|
for (Common::List<ObserverEntry>::iterator i = _observers.begin(); i != _observers.end(); ++i) {
|
||||||
|
if (i->observer == obs) {
|
||||||
|
if (i->autoFree)
|
||||||
|
delete obs;
|
||||||
|
|
||||||
|
_observers.erase(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventDispatcher::dispatchEvent(const Event &event) {
|
||||||
|
for (Common::List<ObserverEntry>::iterator i = _observers.begin(); i != _observers.end(); ++i) {
|
||||||
|
if (i->observer->notifyEvent(event))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of namespace Common
|
||||||
|
|
367
common/EventRecorder.cpp
Normal file
367
common/EventRecorder.cpp
Normal file
|
@ -0,0 +1,367 @@
|
||||||
|
/* 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/EventRecorder.h"
|
||||||
|
|
||||||
|
#include "common/config-manager.h"
|
||||||
|
|
||||||
|
DECLARE_SINGLETON(Common::EventRecorder);
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
#define RECORD_SIGNATURE 0x54455354
|
||||||
|
#define RECORD_VERSION 1
|
||||||
|
|
||||||
|
void readRecord(Common::InSaveFile *inFile, uint32 &diff, Common::Event &event) {
|
||||||
|
diff = inFile->readUint32LE();
|
||||||
|
|
||||||
|
event.type = (Common::EventType)inFile->readUint32LE();
|
||||||
|
|
||||||
|
switch (event.type) {
|
||||||
|
case Common::EVENT_KEYDOWN:
|
||||||
|
case Common::EVENT_KEYUP:
|
||||||
|
event.kbd.keycode = (Common::KeyCode)inFile->readSint32LE();
|
||||||
|
event.kbd.ascii = inFile->readUint16LE();
|
||||||
|
event.kbd.flags = inFile->readByte();
|
||||||
|
break;
|
||||||
|
case Common::EVENT_MOUSEMOVE:
|
||||||
|
case Common::EVENT_LBUTTONDOWN:
|
||||||
|
case Common::EVENT_LBUTTONUP:
|
||||||
|
case Common::EVENT_RBUTTONDOWN:
|
||||||
|
case Common::EVENT_RBUTTONUP:
|
||||||
|
case Common::EVENT_WHEELUP:
|
||||||
|
case Common::EVENT_WHEELDOWN:
|
||||||
|
event.mouse.x = inFile->readSint16LE();
|
||||||
|
event.mouse.y = inFile->readSint16LE();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeRecord(Common::OutSaveFile *outFile, uint32 diff, const Common::Event &event) {
|
||||||
|
outFile->writeUint32LE(diff);
|
||||||
|
|
||||||
|
outFile->writeUint32LE((uint32)event.type);
|
||||||
|
|
||||||
|
switch (event.type) {
|
||||||
|
case Common::EVENT_KEYDOWN:
|
||||||
|
case Common::EVENT_KEYUP:
|
||||||
|
outFile->writeSint32LE(event.kbd.keycode);
|
||||||
|
outFile->writeUint16LE(event.kbd.ascii);
|
||||||
|
outFile->writeByte(event.kbd.flags);
|
||||||
|
break;
|
||||||
|
case Common::EVENT_MOUSEMOVE:
|
||||||
|
case Common::EVENT_LBUTTONDOWN:
|
||||||
|
case Common::EVENT_LBUTTONUP:
|
||||||
|
case Common::EVENT_RBUTTONDOWN:
|
||||||
|
case Common::EVENT_RBUTTONUP:
|
||||||
|
case Common::EVENT_WHEELUP:
|
||||||
|
case Common::EVENT_WHEELDOWN:
|
||||||
|
outFile->writeSint16LE(event.mouse.x);
|
||||||
|
outFile->writeSint16LE(event.mouse.y);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EventRecorder::EventRecorder() {
|
||||||
|
_recordFile = NULL;
|
||||||
|
_recordTimeFile = NULL;
|
||||||
|
_playbackFile = NULL;
|
||||||
|
_playbackTimeFile = NULL;
|
||||||
|
_timeMutex = g_system->createMutex();
|
||||||
|
_recorderMutex = g_system->createMutex();
|
||||||
|
|
||||||
|
_eventCount = 0;
|
||||||
|
_lastEventCount = 0;
|
||||||
|
_lastMillis = 0;
|
||||||
|
|
||||||
|
_recordMode = kPassthrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventRecorder::~EventRecorder() {
|
||||||
|
deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventRecorder::init() {
|
||||||
|
Common::String recordModeString = ConfMan.get("record_mode");
|
||||||
|
if (recordModeString.compareToIgnoreCase("record") == 0) {
|
||||||
|
_recordMode = kRecorderRecord;
|
||||||
|
} else {
|
||||||
|
if (recordModeString.compareToIgnoreCase("playback") == 0) {
|
||||||
|
_recordMode = kRecorderPlayback;
|
||||||
|
} else {
|
||||||
|
_recordMode = kPassthrough;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_recordFileName = ConfMan.get("record_file_name");
|
||||||
|
if (_recordFileName.empty()) {
|
||||||
|
_recordFileName = "record.bin";
|
||||||
|
}
|
||||||
|
_recordTempFileName = ConfMan.get("record_temp_file_name");
|
||||||
|
if (_recordTempFileName.empty()) {
|
||||||
|
_recordTempFileName = "record.tmp";
|
||||||
|
}
|
||||||
|
_recordTimeFileName = ConfMan.get("record_time_file_name");
|
||||||
|
if (_recordTimeFileName.empty()) {
|
||||||
|
_recordTimeFileName = "record.time";
|
||||||
|
}
|
||||||
|
|
||||||
|
// recorder stuff
|
||||||
|
if (_recordMode == kRecorderRecord) {
|
||||||
|
_recordCount = 0;
|
||||||
|
_recordTimeCount = 0;
|
||||||
|
_recordFile = g_system->getSavefileManager()->openForSaving(_recordTempFileName);
|
||||||
|
_recordTimeFile = g_system->getSavefileManager()->openForSaving(_recordTimeFileName);
|
||||||
|
_recordSubtitles = ConfMan.getBool("subtitles");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 sign;
|
||||||
|
uint32 version;
|
||||||
|
uint32 randomSourceCount;
|
||||||
|
if (_recordMode == kRecorderPlayback) {
|
||||||
|
_playbackCount = 0;
|
||||||
|
_playbackTimeCount = 0;
|
||||||
|
_playbackFile = g_system->getSavefileManager()->openForLoading(_recordFileName);
|
||||||
|
_playbackTimeFile = g_system->getSavefileManager()->openForLoading(_recordTimeFileName);
|
||||||
|
|
||||||
|
if (!_playbackFile) {
|
||||||
|
warning("Cannot open playback file %s. Playback was switched off", _recordFileName.c_str());
|
||||||
|
_recordMode = kPassthrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_playbackTimeFile) {
|
||||||
|
warning("Cannot open playback time file %s. Playback was switched off", _recordTimeFileName.c_str());
|
||||||
|
_recordMode = kPassthrough;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_recordMode == kRecorderPlayback) {
|
||||||
|
sign = _playbackFile->readUint32LE();
|
||||||
|
if (sign != RECORD_SIGNATURE) {
|
||||||
|
error("Unknown record file signature");
|
||||||
|
}
|
||||||
|
version = _playbackFile->readUint32LE();
|
||||||
|
|
||||||
|
// conf vars
|
||||||
|
ConfMan.setBool("subtitles", _playbackFile->readByte() != 0);
|
||||||
|
|
||||||
|
_recordCount = _playbackFile->readUint32LE();
|
||||||
|
_recordTimeCount = _playbackFile->readUint32LE();
|
||||||
|
randomSourceCount = _playbackFile->readUint32LE();
|
||||||
|
for (uint i = 0; i < randomSourceCount; ++i) {
|
||||||
|
RandomSourceRecord rec;
|
||||||
|
rec.name = "";
|
||||||
|
uint32 sLen = _playbackFile->readUint32LE();
|
||||||
|
for (uint j = 0; j < sLen; ++j) {
|
||||||
|
char c = _playbackFile->readSByte();
|
||||||
|
rec.name += c;
|
||||||
|
}
|
||||||
|
rec.seed = _playbackFile->readUint32LE();
|
||||||
|
_randomSourceRecords.push_back(rec);
|
||||||
|
}
|
||||||
|
|
||||||
|
_hasPlaybackEvent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_system->getEventManager()->getEventDispatcher()->registerSource(this, false);
|
||||||
|
g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventRecorder::deinit() {
|
||||||
|
g_system->getEventManager()->getEventDispatcher()->unregisterSource(this);
|
||||||
|
g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
|
||||||
|
|
||||||
|
g_system->lockMutex(_timeMutex);
|
||||||
|
g_system->lockMutex(_recorderMutex);
|
||||||
|
_recordMode = kPassthrough;
|
||||||
|
g_system->unlockMutex(_timeMutex);
|
||||||
|
g_system->unlockMutex(_recorderMutex);
|
||||||
|
|
||||||
|
if (_playbackFile != NULL) {
|
||||||
|
delete _playbackFile;
|
||||||
|
}
|
||||||
|
if (_playbackTimeFile != NULL) {
|
||||||
|
delete _playbackTimeFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_recordFile != NULL) {
|
||||||
|
_recordFile->finalize();
|
||||||
|
delete _recordFile;
|
||||||
|
_recordTimeFile->finalize();
|
||||||
|
delete _recordTimeFile;
|
||||||
|
|
||||||
|
_playbackFile = g_system->getSavefileManager()->openForLoading(_recordTempFileName);
|
||||||
|
|
||||||
|
assert(_playbackFile);
|
||||||
|
|
||||||
|
_recordFile = g_system->getSavefileManager()->openForSaving(_recordFileName);
|
||||||
|
_recordFile->writeUint32LE(RECORD_SIGNATURE);
|
||||||
|
_recordFile->writeUint32LE(RECORD_VERSION);
|
||||||
|
|
||||||
|
// conf vars
|
||||||
|
_recordFile->writeByte(_recordSubtitles ? 1 : 0);
|
||||||
|
|
||||||
|
_recordFile->writeUint32LE(_recordCount);
|
||||||
|
_recordFile->writeUint32LE(_recordTimeCount);
|
||||||
|
|
||||||
|
_recordFile->writeUint32LE(_randomSourceRecords.size());
|
||||||
|
for (uint i = 0; i < _randomSourceRecords.size(); ++i) {
|
||||||
|
_recordFile->writeUint32LE(_randomSourceRecords[i].name.size());
|
||||||
|
_recordFile->writeString(_randomSourceRecords[i].name);
|
||||||
|
_recordFile->writeUint32LE(_randomSourceRecords[i].seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i = 0; i < _recordCount; ++i) {
|
||||||
|
uint32 tempDiff;
|
||||||
|
Common::Event tempEvent;
|
||||||
|
readRecord(_playbackFile, tempDiff, tempEvent);
|
||||||
|
writeRecord(_recordFile, tempDiff, tempEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
_recordFile->finalize();
|
||||||
|
delete _recordFile;
|
||||||
|
delete _playbackFile;
|
||||||
|
|
||||||
|
//TODO: remove recordTempFileName'ed file
|
||||||
|
}
|
||||||
|
|
||||||
|
g_system->deleteMutex(_timeMutex);
|
||||||
|
g_system->deleteMutex(_recorderMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventRecorder::registerRandomSource(Common::RandomSource &rnd, const char *name) {
|
||||||
|
if (_recordMode == kRecorderRecord) {
|
||||||
|
RandomSourceRecord rec;
|
||||||
|
rec.name = name;
|
||||||
|
rec.seed = rnd.getSeed();
|
||||||
|
_randomSourceRecords.push_back(rec);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_recordMode == kRecorderPlayback) {
|
||||||
|
for (uint i = 0; i < _randomSourceRecords.size(); ++i) {
|
||||||
|
if (_randomSourceRecords[i].name == name) {
|
||||||
|
rnd.setSeed(_randomSourceRecords[i].seed);
|
||||||
|
_randomSourceRecords.remove_at(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventRecorder::processMillis(uint32 &millis) {
|
||||||
|
uint32 d;
|
||||||
|
if (_recordMode == kPassthrough) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_system->lockMutex(_timeMutex);
|
||||||
|
if (_recordMode == kRecorderRecord) {
|
||||||
|
//Simple RLE compression
|
||||||
|
d = millis - _lastMillis;
|
||||||
|
if (d >= 0xff) {
|
||||||
|
_recordTimeFile->writeByte(0xff);
|
||||||
|
_recordTimeFile->writeUint32LE(d);
|
||||||
|
} else {
|
||||||
|
_recordTimeFile->writeByte(d);
|
||||||
|
}
|
||||||
|
_recordTimeCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_recordMode == kRecorderPlayback) {
|
||||||
|
if (_recordTimeCount > _playbackTimeCount) {
|
||||||
|
d = _playbackTimeFile->readByte();
|
||||||
|
if (d == 0xff) {
|
||||||
|
d = _playbackTimeFile->readUint32LE();
|
||||||
|
}
|
||||||
|
millis = _lastMillis + d;
|
||||||
|
_playbackTimeCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastMillis = millis;
|
||||||
|
g_system->unlockMutex(_timeMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EventRecorder::notifyEvent(const Common::Event &ev) {
|
||||||
|
if (_recordMode != kRecorderRecord)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Common::StackLock lock(_recorderMutex);
|
||||||
|
++_eventCount;
|
||||||
|
|
||||||
|
writeRecord(_recordFile, _eventCount - _lastEventCount, ev);
|
||||||
|
|
||||||
|
_recordCount++;
|
||||||
|
_lastEventCount = _eventCount;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EventRecorder::pollEvent(Common::Event &ev) {
|
||||||
|
if (_recordMode != kRecorderPlayback)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Common::StackLock lock(_recorderMutex);
|
||||||
|
++_eventCount;
|
||||||
|
|
||||||
|
if (!_hasPlaybackEvent) {
|
||||||
|
if (_recordCount > _playbackCount) {
|
||||||
|
readRecord(_playbackFile, const_cast<uint32&>(_playbackDiff), _playbackEvent);
|
||||||
|
_playbackCount++;
|
||||||
|
_hasPlaybackEvent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_hasPlaybackEvent) {
|
||||||
|
if (_playbackDiff <= (_eventCount - _lastEventCount)) {
|
||||||
|
switch (_playbackEvent.type) {
|
||||||
|
case Common::EVENT_MOUSEMOVE:
|
||||||
|
case Common::EVENT_LBUTTONDOWN:
|
||||||
|
case Common::EVENT_LBUTTONUP:
|
||||||
|
case Common::EVENT_RBUTTONDOWN:
|
||||||
|
case Common::EVENT_RBUTTONUP:
|
||||||
|
case Common::EVENT_WHEELUP:
|
||||||
|
case Common::EVENT_WHEELDOWN:
|
||||||
|
g_system->warpMouse(_playbackEvent.mouse.x, _playbackEvent.mouse.y);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ev = _playbackEvent;
|
||||||
|
_hasPlaybackEvent = false;
|
||||||
|
_lastEventCount = _eventCount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of namespace Common
|
||||||
|
|
106
common/EventRecorder.h
Normal file
106
common/EventRecorder.h
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/* 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_EVENTRECORDER_H
|
||||||
|
#define COMMON_EVENTRECORDER_H
|
||||||
|
|
||||||
|
#include "common/sys.h"
|
||||||
|
#include "common/events.h"
|
||||||
|
#include "common/singleton.h"
|
||||||
|
#include "common/savefile.h"
|
||||||
|
#include "common/mutex.h"
|
||||||
|
#include "common/array.h"
|
||||||
|
|
||||||
|
#define g_eventRec (Common::EventRecorder::instance())
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Our generic event recorder.
|
||||||
|
*
|
||||||
|
* TODO: Add more documentation.
|
||||||
|
*/
|
||||||
|
class EventRecorder : private EventSource, private EventObserver, public Singleton<EventRecorder> {
|
||||||
|
friend class Common::Singleton<SingletonBaseType>;
|
||||||
|
EventRecorder();
|
||||||
|
~EventRecorder();
|
||||||
|
public:
|
||||||
|
void init();
|
||||||
|
void deinit();
|
||||||
|
|
||||||
|
/** Register random source so it can be serialized in game test purposes */
|
||||||
|
void registerRandomSource(Common::RandomSource &rnd, const char *name);
|
||||||
|
|
||||||
|
/** TODO: Add documentation, this is only used by the backend */
|
||||||
|
void processMillis(uint32 &millis);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool notifyEvent(const Common::Event &ev);
|
||||||
|
bool pollEvent(Common::Event &ev);
|
||||||
|
bool allowMapping() const { return false; }
|
||||||
|
|
||||||
|
class RandomSourceRecord {
|
||||||
|
public:
|
||||||
|
Common::String name;
|
||||||
|
uint32 seed;
|
||||||
|
};
|
||||||
|
Common::Array<RandomSourceRecord> _randomSourceRecords;
|
||||||
|
|
||||||
|
bool _recordSubtitles;
|
||||||
|
volatile uint32 _recordCount;
|
||||||
|
volatile uint32 _lastRecordEvent;
|
||||||
|
volatile uint32 _recordTimeCount;
|
||||||
|
Common::OutSaveFile *_recordFile;
|
||||||
|
Common::OutSaveFile *_recordTimeFile;
|
||||||
|
Common::MutexRef _timeMutex;
|
||||||
|
Common::MutexRef _recorderMutex;
|
||||||
|
volatile uint32 _lastMillis;
|
||||||
|
|
||||||
|
volatile uint32 _playbackCount;
|
||||||
|
volatile uint32 _playbackDiff;
|
||||||
|
volatile bool _hasPlaybackEvent;
|
||||||
|
volatile uint32 _playbackTimeCount;
|
||||||
|
Common::Event _playbackEvent;
|
||||||
|
Common::InSaveFile *_playbackFile;
|
||||||
|
Common::InSaveFile *_playbackTimeFile;
|
||||||
|
|
||||||
|
volatile uint32 _eventCount;
|
||||||
|
volatile uint32 _lastEventCount;
|
||||||
|
|
||||||
|
enum RecordMode {
|
||||||
|
kPassthrough = 0,
|
||||||
|
kRecorderRecord = 1,
|
||||||
|
kRecorderPlayback = 2
|
||||||
|
};
|
||||||
|
volatile RecordMode _recordMode;
|
||||||
|
Common::String _recordFileName;
|
||||||
|
Common::String _recordTempFileName;
|
||||||
|
Common::String _recordTimeFileName;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace Common
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -56,7 +56,7 @@ int Archive::listMatchingMembers(ArchiveMemberList &list, const String &pattern)
|
||||||
|
|
||||||
ArchiveMemberList::iterator it = allNames.begin();
|
ArchiveMemberList::iterator it = allNames.begin();
|
||||||
for ( ; it != allNames.end(); ++it) {
|
for ( ; it != allNames.end(); ++it) {
|
||||||
if ((*it)->getName().matchString(lowercasePattern, true)) {
|
if ((*it)->getName().matchString(lowercasePattern, false, true)) {
|
||||||
list.push_back(*it);
|
list.push_back(*it);
|
||||||
matches++;
|
matches++;
|
||||||
}
|
}
|
||||||
|
@ -123,6 +123,55 @@ void SearchSet::addDirectory(const String &name, const FSNode &dir, int priority
|
||||||
add(name, new FSDirectory(dir, depth, flat), priority);
|
add(name, new FSDirectory(dir, depth, flat), priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SearchSet::addSubDirectoriesMatching(const FSNode &directory, String origPattern, bool ignoreCase, int priority) {
|
||||||
|
FSList subDirs;
|
||||||
|
if (!directory.getChildren(subDirs))
|
||||||
|
return;
|
||||||
|
|
||||||
|
String nextPattern, pattern;
|
||||||
|
String::const_iterator sep = Common::find(origPattern.begin(), origPattern.end(), '/');
|
||||||
|
if (sep != origPattern.end()) {
|
||||||
|
pattern = String(origPattern.begin(), sep);
|
||||||
|
|
||||||
|
++sep;
|
||||||
|
if (sep != origPattern.end())
|
||||||
|
nextPattern = String(sep, origPattern.end());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pattern = origPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: The code we have for displaying all matches, which vary only in case, might
|
||||||
|
// be a bit overhead, but as long as we want to display all useful information to the
|
||||||
|
// user we will need to keep track of all directory names added so far. We might
|
||||||
|
// want to reconsider this though.
|
||||||
|
typedef HashMap<String, bool, IgnoreCase_Hash, IgnoreCase_EqualTo> MatchList;
|
||||||
|
MatchList multipleMatches;
|
||||||
|
MatchList::iterator matchIter;
|
||||||
|
|
||||||
|
for (FSList::const_iterator i = subDirs.begin(); i != subDirs.end(); ++i) {
|
||||||
|
String name = i->getName();
|
||||||
|
|
||||||
|
if (Common::matchString(name.c_str(), pattern.c_str(), ignoreCase)) {
|
||||||
|
matchIter = multipleMatches.find(name);
|
||||||
|
if (matchIter == multipleMatches.end()) {
|
||||||
|
multipleMatches[name] = true;
|
||||||
|
} else {
|
||||||
|
if (matchIter->_value) {
|
||||||
|
warning("Clash in case for match of pattern \"%s\" found in directory \"%s\": \"%s\"", pattern.c_str(), directory.getPath().c_str(), matchIter->_key.c_str());
|
||||||
|
matchIter->_value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
warning("Clash in case for match of pattern \"%s\" found in directory \"%s\": \"%s\"", pattern.c_str(), directory.getPath().c_str(), name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextPattern.empty())
|
||||||
|
addDirectory(name, *i, priority);
|
||||||
|
else
|
||||||
|
addSubDirectoriesMatching(*i, nextPattern, ignoreCase, priority);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SearchSet::remove(const String &name) {
|
void SearchSet::remove(const String &name) {
|
||||||
ArchiveNodeList::iterator it = find(name);
|
ArchiveNodeList::iterator it = find(name);
|
||||||
|
|
|
@ -168,6 +168,52 @@ public:
|
||||||
*/
|
*/
|
||||||
void addDirectory(const String &name, const FSNode &directory, int priority = 0, int depth = 1, bool flat = false);
|
void addDirectory(const String &name, const FSNode &directory, int priority = 0, int depth = 1, bool flat = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and add a sub directory by name (caseless).
|
||||||
|
*
|
||||||
|
* It is also possible to add sub directories of sub directories (of any depth) with this function.
|
||||||
|
* The path seperator for this case is SLASH for *all* systems.
|
||||||
|
*
|
||||||
|
* An example would be:
|
||||||
|
*
|
||||||
|
* "game/itedata"
|
||||||
|
*
|
||||||
|
* In this example the code would first try to search for all directories matching
|
||||||
|
* "game" (case insensitive) in the path "directory" first and search through all
|
||||||
|
* of the matches for "itedata" (case insensitive too).
|
||||||
|
*
|
||||||
|
* Note that it will add *all* matches found!
|
||||||
|
*
|
||||||
|
* Even though this method is currently implemented via addSubDirectoriesMatching it is not safe
|
||||||
|
* to assume that this method is using anything other than a simple case insensitive compare.
|
||||||
|
* Thus do not use any tokens like '*' or '?' in the "caselessName" parameter of this function!
|
||||||
|
*/
|
||||||
|
void addSubDirectoryMatching(const FSNode &directory, const String &caselessName, int priority = 0) {
|
||||||
|
addSubDirectoriesMatching(directory, caselessName, true, priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and add sub directories by pattern.
|
||||||
|
*
|
||||||
|
* It is also possible to add sub directories of sub directories (of any depth) with this function.
|
||||||
|
* The path seperator for this case is SLASH for *all* systems.
|
||||||
|
*
|
||||||
|
* An example would be:
|
||||||
|
*
|
||||||
|
* "game/itedata"
|
||||||
|
*
|
||||||
|
* In this example the code would first try to search for all directories matching
|
||||||
|
* "game" in the path "directory" first and search through all of the matches for
|
||||||
|
* "itedata". If "ingoreCase" is set to true, the code would do a case insensitive
|
||||||
|
* match, otherwise it is doing a case sensitive match.
|
||||||
|
*
|
||||||
|
* This method works of course also with tokens. For a list of available tokens
|
||||||
|
* see the documentation for Common::matchString.
|
||||||
|
*
|
||||||
|
* @see Common::matchString
|
||||||
|
*/
|
||||||
|
void addSubDirectoriesMatching(const FSNode &directory, String origPattern, bool ignoreCase, int priority = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove an archive from the searchable set.
|
* Remove an archive from the searchable set.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -222,7 +222,7 @@ public:
|
||||||
|
|
||||||
T *old_storage = _storage;
|
T *old_storage = _storage;
|
||||||
_capacity = newCapacity;
|
_capacity = newCapacity;
|
||||||
_storage = new T[newCapacity]();
|
_storage = new T[newCapacity];
|
||||||
assert(_storage);
|
assert(_storage);
|
||||||
|
|
||||||
if (old_storage) {
|
if (old_storage) {
|
||||||
|
@ -273,7 +273,7 @@ protected:
|
||||||
// If there is not enough space, allocate more and
|
// If there is not enough space, allocate more and
|
||||||
// copy old elements over.
|
// copy old elements over.
|
||||||
uint newCapacity = roundUpCapacity(_size + n);
|
uint newCapacity = roundUpCapacity(_size + n);
|
||||||
newStorage = new T[newCapacity]();
|
newStorage = new T[newCapacity];
|
||||||
assert(newStorage);
|
assert(newStorage);
|
||||||
copy(_storage, _storage + idx, newStorage);
|
copy(_storage, _storage + idx, newStorage);
|
||||||
pos = newStorage + idx;
|
pos = newStorage + idx;
|
||||||
|
|
|
@ -26,10 +26,8 @@
|
||||||
#include "common/config-file.h"
|
#include "common/config-file.h"
|
||||||
#include "common/file.h"
|
#include "common/file.h"
|
||||||
#include "common/savefile.h"
|
#include "common/savefile.h"
|
||||||
#include "common/util.h"
|
|
||||||
#include "common/debug.h"
|
|
||||||
#include "common/system.h"
|
#include "common/system.h"
|
||||||
|
#include "common/util.h"
|
||||||
|
|
||||||
#define MAXLINELEN 256
|
#define MAXLINELEN 256
|
||||||
|
|
||||||
|
|
|
@ -132,10 +132,10 @@ public:
|
||||||
//
|
//
|
||||||
// Some additional convenience accessors.
|
// Some additional convenience accessors.
|
||||||
//
|
//
|
||||||
int getInt(const String &key, const String &domName = String::emptyString) const;
|
int getInt(const String &key, const String &domName = String()) const;
|
||||||
bool getBool(const String &key, const String &domName = String::emptyString) const;
|
bool getBool(const String &key, const String &domName = String()) const;
|
||||||
void setInt(const String &key, int value, const String &domName = String::emptyString);
|
void setInt(const String &key, int value, const String &domName = String());
|
||||||
void setBool(const String &key, bool value, const String &domName = String::emptyString);
|
void setBool(const String &key, bool value, const String &domName = String());
|
||||||
|
|
||||||
|
|
||||||
void registerDefault(const String &key, const String &value);
|
void registerDefault(const String &key, const String &value);
|
||||||
|
|
|
@ -154,7 +154,14 @@ static void debugHelper(const char *s, va_list va, bool caret = true) {
|
||||||
char buf[STRINGBUFLEN];
|
char buf[STRINGBUFLEN];
|
||||||
vsnprintf(in_buf, STRINGBUFLEN, s, va);
|
vsnprintf(in_buf, STRINGBUFLEN, s, va);
|
||||||
|
|
||||||
|
// Next, give the active engine (if any) a chance to augment the message,
|
||||||
|
// but only if not used from debugN.
|
||||||
|
if (g_engine && caret) {
|
||||||
|
g_engine->errorString(in_buf, buf, STRINGBUFLEN);
|
||||||
|
} else {
|
||||||
strncpy(buf, in_buf, STRINGBUFLEN);
|
strncpy(buf, in_buf, STRINGBUFLEN);
|
||||||
|
}
|
||||||
|
buf[STRINGBUFLEN-1] = '\0';
|
||||||
|
|
||||||
if (caret) {
|
if (caret) {
|
||||||
buf[STRINGBUFLEN-2] = '\0';
|
buf[STRINGBUFLEN-2] = '\0';
|
||||||
|
|
405
common/endian.h
405
common/endian.h
|
@ -28,28 +28,115 @@
|
||||||
|
|
||||||
#include "common/sys.h"
|
#include "common/sys.h"
|
||||||
|
|
||||||
//
|
/**
|
||||||
// Endian conversion functions, macros etc., follow from here!
|
* \file endian.h
|
||||||
//
|
* Endian conversion and byteswap conversion functions or macros
|
||||||
|
*
|
||||||
|
* SWAP_BYTES_??(a) - inverse byte order
|
||||||
|
* SWAP_CONSTANT_??(a) - inverse byte order, implemented as macro.
|
||||||
|
* Use with compiletime-constants only, the result will be a compiletime-constant aswell.
|
||||||
|
* Unlike most other functions these can be used for eg. switch-case labels
|
||||||
|
*
|
||||||
|
* READ_UINT??(a) - read native value from pointer a
|
||||||
|
* READ_??_UINT??(a) - read LE/BE value from pointer a and convert it to native
|
||||||
|
* WRITE_??_UINT??(a, v) - write native value v to pointer a with LE/BE encoding
|
||||||
|
* TO_??_??(a) - convert native value v to LE/BE
|
||||||
|
* FROM_??_??(a) - convert LE/BE value v to native
|
||||||
|
* CONSTANT_??_??(a) - convert LE/BE value v to native, implemented as macro.
|
||||||
|
* Use with compiletime-constants only, the result will be a compiletime-constant aswell.
|
||||||
|
* Unlike most other functions these can be used for eg. switch-case labels
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Sanity check
|
||||||
|
#if !defined(SYSTEM_LITTLE_ENDIAN) && !defined(SYSTEM_BIG_ENDIAN)
|
||||||
|
# error No endianness defined
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SWAP_CONSTANT_32(a) \
|
||||||
|
((uint32)((((a) >> 24) & 0x00FF) | \
|
||||||
|
(((a) >> 8) & 0xFF00) | \
|
||||||
|
(((a) & 0xFF00) << 8) | \
|
||||||
|
(((a) & 0x00FF) << 24) ))
|
||||||
|
|
||||||
|
#define SWAP_CONSTANT_16(a) \
|
||||||
|
((uint16)((((a) >> 8) & 0x00FF) | \
|
||||||
|
(((a) << 8) & 0xFF00) ))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swap the bytes in a 32 bit word in order to convert LE encoded data to BE
|
* Swap the bytes in a 32 bit word in order to convert LE encoded data to BE
|
||||||
* and vice versa.
|
* and vice versa.
|
||||||
*/
|
*/
|
||||||
FORCEINLINE uint32 SWAP_BYTES_32(uint32 a) {
|
|
||||||
return ((a >> 24) & 0x000000FF) |
|
// machine/compiler-specific variants come first, fallback last
|
||||||
((a >> 8) & 0x0000FF00) |
|
|
||||||
((a << 8) & 0x00FF0000) |
|
// Test for GCC and if the target has the MIPS rel.2 instructions (we know the psp does)
|
||||||
((a << 24) & 0xFF000000);
|
#if defined(__GNUC__) && (defined(__psp__) || defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2))
|
||||||
|
|
||||||
|
FORCEINLINE uint32 SWAP_BYTES_32(const uint32 a) {
|
||||||
|
if (__builtin_constant_p(a)) {
|
||||||
|
return SWAP_CONSTANT_32(a);
|
||||||
|
} else {
|
||||||
|
uint32 result;
|
||||||
|
# if defined(__psp__)
|
||||||
|
// use special allegrex instruction
|
||||||
|
__asm__ ("wsbw %0,%1" : "=r" (result) : "r" (a));
|
||||||
|
# else
|
||||||
|
__asm__ ("wsbh %0,%1\n"
|
||||||
|
"rotr %0,%0,16" : "=r" (result) : "r" (a));
|
||||||
|
# endif
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for GCC >= 4.3.0 as this version added the bswap builtin
|
||||||
|
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
|
||||||
|
|
||||||
|
FORCEINLINE uint32 SWAP_BYTES_32(uint32 a) {
|
||||||
|
return __builtin_bswap32(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test for MSVC 7 or newer
|
||||||
|
#elif defined(_MSC_VER) && _MSC_VER >= 1300
|
||||||
|
|
||||||
|
FORCEINLINE uint32 SWAP_BYTES_32(uint32 a) {
|
||||||
|
return _byteswap_ulong(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// generic fallback
|
||||||
|
#else
|
||||||
|
|
||||||
|
inline uint32 SWAP_BYTES_32(uint32 a) {
|
||||||
|
const uint16 low = (uint16)a, high = (uint16)(a >> 16);
|
||||||
|
return ((uint32)(uint16)((low >> 8) | (low << 8)) << 16)
|
||||||
|
| (uint16)((high >> 8) | (high << 8));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swap the bytes in a 16 bit word in order to convert LE encoded data to BE
|
* Swap the bytes in a 16 bit word in order to convert LE encoded data to BE
|
||||||
* and vice versa.
|
* and vice versa.
|
||||||
*/
|
*/
|
||||||
FORCEINLINE uint16 SWAP_BYTES_16(uint16 a) {
|
|
||||||
return ((a >> 8) & 0x00FF) + ((a << 8) & 0xFF00);
|
// compilerspecific variants come first, fallback last
|
||||||
|
|
||||||
|
// Test for GCC and if the target has the MIPS rel.2 instructions (we know the psp does)
|
||||||
|
#if defined(__GNUC__) && (defined(__psp__) || defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2))
|
||||||
|
|
||||||
|
FORCEINLINE uint16 SWAP_BYTES_16(const uint16 a) {
|
||||||
|
if (__builtin_constant_p(a)) {
|
||||||
|
return SWAP_CONSTANT_16(a);
|
||||||
|
} else {
|
||||||
|
uint16 result;
|
||||||
|
__asm__ ("wsbh %0,%1" : "=r" (result) : "r" (a));
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
inline uint16 SWAP_BYTES_16(const uint16 a) {
|
||||||
|
return (a >> 8) | (a << 8);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,25 +157,119 @@ FORCEINLINE uint16 SWAP_BYTES_16(uint16 a) {
|
||||||
* For the latter systems we provide the INVERSE_MKID override.
|
* For the latter systems we provide the INVERSE_MKID override.
|
||||||
*/
|
*/
|
||||||
#if defined(INVERSE_MKID)
|
#if defined(INVERSE_MKID)
|
||||||
#define MKID_BE(a) ((uint32) \
|
#define MKID_BE(a) SWAP_CONSTANT_32(a)
|
||||||
(((a) >> 24) & 0x000000FF) | \
|
|
||||||
(((a) >> 8) & 0x0000FF00) | \
|
|
||||||
(((a) << 8) & 0x00FF0000) | \
|
|
||||||
(((a) << 24) & 0xFF000000))
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# define MKID_BE(a) ((uint32)(a))
|
# define MKID_BE(a) ((uint32)(a))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Functions for reading/writing native Integers,
|
||||||
|
// this transparently handles the need for alignment
|
||||||
|
|
||||||
|
#if !defined(SYSTEM_NEED_ALIGNMENT)
|
||||||
|
|
||||||
|
FORCEINLINE uint16 READ_UINT16(const void *ptr) {
|
||||||
|
return *(const uint16 *)(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE uint32 READ_UINT32(const void *ptr) {
|
||||||
|
return *(const uint32 *)(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE void WRITE_UINT16(void *ptr, uint16 value) {
|
||||||
|
*(uint16 *)(ptr) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE void WRITE_UINT32(void *ptr, uint32 value) {
|
||||||
|
*(uint32 *)(ptr) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test for GCC >= 4.0. these implementations will automatically use CPU-specific
|
||||||
|
// instructions for unaligned data when they are available (eg. MIPS)
|
||||||
|
#elif defined(__GNUC__) && (__GNUC__ >= 4)
|
||||||
|
|
||||||
|
FORCEINLINE uint16 READ_UINT16(const void *ptr) {
|
||||||
|
struct Unaligned16 { uint16 val; } __attribute__ ((__packed__));
|
||||||
|
return ((const Unaligned16 *)ptr)->val;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE uint32 READ_UINT32(const void *ptr) {
|
||||||
|
struct Unaligned32 { uint32 val; } __attribute__ ((__packed__));
|
||||||
|
return ((const Unaligned32 *)ptr)->val;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE void WRITE_UINT16(void *ptr, uint16 value) {
|
||||||
|
struct Unaligned16 { uint16 val; } __attribute__ ((__packed__));
|
||||||
|
((Unaligned16 *)ptr)->val = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE void WRITE_UINT32(void *ptr, uint32 value) {
|
||||||
|
struct Unaligned32 { uint32 val; } __attribute__ ((__packed__));
|
||||||
|
((Unaligned32 *)ptr)->val = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use software fallback by loading each byte explicitely
|
||||||
|
#else
|
||||||
|
|
||||||
# if defined(SYSTEM_LITTLE_ENDIAN)
|
# if defined(SYSTEM_LITTLE_ENDIAN)
|
||||||
|
|
||||||
#define READ_UINT16(a) READ_LE_UINT16(a)
|
inline uint16 READ_UINT16(const void *ptr) {
|
||||||
#define READ_UINT32(a) READ_LE_UINT32(a)
|
const uint8 *b = (const uint8 *)ptr;
|
||||||
|
return (b[1] << 8) | b[0];
|
||||||
|
}
|
||||||
|
inline uint32 READ_UINT32(const void *ptr) {
|
||||||
|
const uint8 *b = (const uint8 *)ptr;
|
||||||
|
return (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0]);
|
||||||
|
}
|
||||||
|
inline void WRITE_UINT16(void *ptr, uint16 value) {
|
||||||
|
uint8 *b = (uint8 *)ptr;
|
||||||
|
b[0] = (uint8)(value >> 0);
|
||||||
|
b[1] = (uint8)(value >> 8);
|
||||||
|
}
|
||||||
|
inline void WRITE_UINT32(void *ptr, uint32 value) {
|
||||||
|
uint8 *b = (uint8 *)ptr;
|
||||||
|
b[0] = (uint8)(value >> 0);
|
||||||
|
b[1] = (uint8)(value >> 8);
|
||||||
|
b[2] = (uint8)(value >> 16);
|
||||||
|
b[3] = (uint8)(value >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
#define WRITE_UINT16(a, v) WRITE_LE_UINT16(a, v)
|
# elif defined(SYSTEM_BIG_ENDIAN)
|
||||||
#define WRITE_UINT32(a, v) WRITE_LE_UINT32(a, v)
|
|
||||||
|
inline uint16 READ_UINT16(const void *ptr) {
|
||||||
|
const uint8 *b = (const uint8 *)ptr;
|
||||||
|
return (b[0] << 8) | b[1];
|
||||||
|
}
|
||||||
|
inline uint32 READ_UINT32(const void *ptr) {
|
||||||
|
const uint8 *b = (const uint8 *)ptr;
|
||||||
|
return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
|
||||||
|
}
|
||||||
|
inline void WRITE_UINT16(void *ptr, uint16 value) {
|
||||||
|
uint8 *b = (uint8 *)ptr;
|
||||||
|
b[0] = (uint8)(value >> 8);
|
||||||
|
b[1] = (uint8)(value >> 0);
|
||||||
|
}
|
||||||
|
inline void WRITE_UINT32(void *ptr, uint32 value) {
|
||||||
|
uint8 *b = (uint8 *)ptr;
|
||||||
|
b[0] = (uint8)(value >> 24);
|
||||||
|
b[1] = (uint8)(value >> 16);
|
||||||
|
b[2] = (uint8)(value >> 8);
|
||||||
|
b[3] = (uint8)(value >> 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Map Funtions for reading/writing BE/LE integers depending on native endianess
|
||||||
|
#if defined(SYSTEM_LITTLE_ENDIAN)
|
||||||
|
|
||||||
|
#define READ_LE_UINT16(a) READ_UINT16(a)
|
||||||
|
#define READ_LE_UINT32(a) READ_UINT32(a)
|
||||||
|
|
||||||
|
#define WRITE_LE_UINT16(a, v) WRITE_UINT16(a, v)
|
||||||
|
#define WRITE_LE_UINT32(a, v) WRITE_UINT32(a, v)
|
||||||
|
|
||||||
#define FROM_LE_32(a) ((uint32)(a))
|
#define FROM_LE_32(a) ((uint32)(a))
|
||||||
#define FROM_LE_16(a) ((uint16)(a))
|
#define FROM_LE_16(a) ((uint16)(a))
|
||||||
|
@ -102,16 +283,61 @@ FORCEINLINE uint16 SWAP_BYTES_16(uint16 a) {
|
||||||
#define TO_BE_32(a) SWAP_BYTES_32(a)
|
#define TO_BE_32(a) SWAP_BYTES_32(a)
|
||||||
#define TO_BE_16(a) SWAP_BYTES_16(a)
|
#define TO_BE_16(a) SWAP_BYTES_16(a)
|
||||||
|
|
||||||
|
#define CONSTANT_LE_32(a) ((uint32)(a))
|
||||||
|
#define CONSTANT_LE_16(a) ((uint16)(a))
|
||||||
|
|
||||||
|
#define CONSTANT_BE_32(a) SWAP_CONSTANT_32(a)
|
||||||
|
#define CONSTANT_BE_16(a) SWAP_CONSTANT_16(a)
|
||||||
|
|
||||||
|
// if the unaligned load and the byteswap take alot instructions its better to directly read and invert
|
||||||
|
# if defined(SYSTEM_NEED_ALIGNMENT) && !defined(__mips__)
|
||||||
|
|
||||||
|
inline uint16 READ_BE_UINT16(const void *ptr) {
|
||||||
|
const uint8 *b = (const uint8 *)ptr;
|
||||||
|
return (b[0] << 8) | b[1];
|
||||||
|
}
|
||||||
|
inline uint32 READ_BE_UINT32(const void *ptr) {
|
||||||
|
const uint8 *b = (const uint8 *)ptr;
|
||||||
|
return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
|
||||||
|
}
|
||||||
|
inline void WRITE_BE_UINT16(void *ptr, uint16 value) {
|
||||||
|
uint8 *b = (uint8 *)ptr;
|
||||||
|
b[0] = (uint8)(value >> 8);
|
||||||
|
b[1] = (uint8)(value >> 0);
|
||||||
|
}
|
||||||
|
inline void WRITE_BE_UINT32(void *ptr, uint32 value) {
|
||||||
|
uint8 *b = (uint8 *)ptr;
|
||||||
|
b[0] = (uint8)(value >> 24);
|
||||||
|
b[1] = (uint8)(value >> 16);
|
||||||
|
b[2] = (uint8)(value >> 8);
|
||||||
|
b[3] = (uint8)(value >> 0);
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
|
||||||
|
inline uint16 READ_BE_UINT16(const void *ptr) {
|
||||||
|
return SWAP_BYTES_16(READ_UINT16(ptr));
|
||||||
|
}
|
||||||
|
inline uint32 READ_BE_UINT32(const void *ptr) {
|
||||||
|
return SWAP_BYTES_32(READ_UINT32(ptr));
|
||||||
|
}
|
||||||
|
inline void WRITE_BE_UINT16(void *ptr, uint16 value) {
|
||||||
|
WRITE_UINT16(ptr, SWAP_BYTES_16(value));
|
||||||
|
}
|
||||||
|
inline void WRITE_BE_UINT32(void *ptr, uint32 value) {
|
||||||
|
WRITE_UINT32(ptr, SWAP_BYTES_32(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif // if defined(SYSTEM_NEED_ALIGNMENT)
|
||||||
|
|
||||||
#elif defined(SYSTEM_BIG_ENDIAN)
|
#elif defined(SYSTEM_BIG_ENDIAN)
|
||||||
|
|
||||||
#define MKID(a) ((uint32)(a))
|
|
||||||
#define MKID_BE(a) ((uint32)(a))
|
#define MKID_BE(a) ((uint32)(a))
|
||||||
|
|
||||||
#define READ_UINT16(a) READ_BE_UINT16(a)
|
#define READ_BE_UINT16(a) READ_UINT16(a)
|
||||||
#define READ_UINT32(a) READ_BE_UINT32(a)
|
#define READ_BE_UINT32(a) READ_UINT32(a)
|
||||||
|
|
||||||
#define WRITE_UINT16(a, v) WRITE_BE_UINT16(a, v)
|
#define WRITE_BE_UINT16(a, v) WRITE_UINT16(a, v)
|
||||||
#define WRITE_UINT32(a, v) WRITE_BE_UINT32(a, v)
|
#define WRITE_BE_UINT32(a, v) WRITE_UINT32(a, v)
|
||||||
|
|
||||||
#define FROM_LE_32(a) SWAP_BYTES_32(a)
|
#define FROM_LE_32(a) SWAP_BYTES_32(a)
|
||||||
#define FROM_LE_16(a) SWAP_BYTES_16(a)
|
#define FROM_LE_16(a) SWAP_BYTES_16(a)
|
||||||
|
@ -125,95 +351,62 @@ FORCEINLINE uint16 SWAP_BYTES_16(uint16 a) {
|
||||||
#define TO_BE_32(a) ((uint32)(a))
|
#define TO_BE_32(a) ((uint32)(a))
|
||||||
#define TO_BE_16(a) ((uint16)(a))
|
#define TO_BE_16(a) ((uint16)(a))
|
||||||
|
|
||||||
|
#define CONSTANT_LE_32(a) SWAP_CONSTANT_32(a)
|
||||||
|
#define CONSTANT_LE_16(a) SWAP_CONSTANT_16(a)
|
||||||
|
|
||||||
|
#define CONSTANT_BE_32(a) ((uint32)(a))
|
||||||
|
#define CONSTANT_BE_16(a) ((uint16)(a))
|
||||||
|
|
||||||
|
// if the unaligned load and the byteswap take alot instructions its better to directly read and invert
|
||||||
|
# if defined(SYSTEM_NEED_ALIGNMENT) && !defined(__mips__)
|
||||||
|
|
||||||
|
inline uint16 READ_LE_UINT16(const void *ptr) {
|
||||||
|
const uint8 *b = (const uint8 *)ptr;
|
||||||
|
return (b[1] << 8) | b[0];
|
||||||
|
}
|
||||||
|
inline uint32 READ_LE_UINT32(const void *ptr) {
|
||||||
|
const uint8 *b = (const uint8 *)ptr;
|
||||||
|
return (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0]);
|
||||||
|
}
|
||||||
|
inline void WRITE_LE_UINT16(void *ptr, uint16 value) {
|
||||||
|
uint8 *b = (uint8 *)ptr;
|
||||||
|
b[0] = (uint8)(value >> 0);
|
||||||
|
b[1] = (uint8)(value >> 8);
|
||||||
|
}
|
||||||
|
inline void WRITE_LE_UINT32(void *ptr, uint32 value) {
|
||||||
|
uint8 *b = (uint8 *)ptr;
|
||||||
|
b[0] = (uint8)(value >> 0);
|
||||||
|
b[1] = (uint8)(value >> 8);
|
||||||
|
b[2] = (uint8)(value >> 16);
|
||||||
|
b[3] = (uint8)(value >> 24);
|
||||||
|
}
|
||||||
# else
|
# else
|
||||||
|
|
||||||
#error No endianness defined
|
inline uint16 READ_LE_UINT16(const void *ptr) {
|
||||||
|
return SWAP_BYTES_16(READ_UINT16(ptr));
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(SYSTEM_NEED_ALIGNMENT) || !defined(SYSTEM_LITTLE_ENDIAN)
|
|
||||||
FORCEINLINE uint16 READ_LE_UINT16(const void *ptr) {
|
|
||||||
const byte *b = (const byte *)ptr;
|
|
||||||
return (b[1] << 8) + b[0];
|
|
||||||
}
|
}
|
||||||
FORCEINLINE uint32 READ_LE_UINT32(const void *ptr) {
|
inline uint32 READ_LE_UINT32(const void *ptr) {
|
||||||
const byte *b = (const byte *)ptr;
|
return SWAP_BYTES_32(READ_UINT32(ptr));
|
||||||
return (b[3] << 24) + (b[2] << 16) + (b[1] << 8) + (b[0]);
|
|
||||||
}
|
}
|
||||||
FORCEINLINE void WRITE_LE_UINT16(void *ptr, uint16 value) {
|
inline void WRITE_LE_UINT16(void *ptr, uint16 value) {
|
||||||
byte *b = (byte *)ptr;
|
WRITE_UINT16(ptr, SWAP_BYTES_16(value));
|
||||||
b[0] = (byte)(value >> 0);
|
|
||||||
b[1] = (byte)(value >> 8);
|
|
||||||
}
|
}
|
||||||
FORCEINLINE void WRITE_LE_UINT32(void *ptr, uint32 value) {
|
inline void WRITE_LE_UINT32(void *ptr, uint32 value) {
|
||||||
byte *b = (byte *)ptr;
|
WRITE_UINT32(ptr, SWAP_BYTES_32(value));
|
||||||
b[0] = (byte)(value >> 0);
|
|
||||||
b[1] = (byte)(value >> 8);
|
|
||||||
b[2] = (byte)(value >> 16);
|
|
||||||
b[3] = (byte)(value >> 24);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
FORCEINLINE uint16 READ_LE_UINT16(const void *ptr) {
|
|
||||||
return *(const uint16 *)(ptr);
|
|
||||||
}
|
|
||||||
FORCEINLINE uint32 READ_LE_UINT32(const void *ptr) {
|
|
||||||
return *(const uint32 *)(ptr);
|
|
||||||
}
|
|
||||||
FORCEINLINE void WRITE_LE_UINT16(void *ptr, uint16 value) {
|
|
||||||
*(uint16 *)(ptr) = value;
|
|
||||||
}
|
|
||||||
FORCEINLINE void WRITE_LE_UINT32(void *ptr, uint32 value) {
|
|
||||||
*(uint32 *)(ptr) = value;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(SYSTEM_NEED_ALIGNMENT) || !defined(SYSTEM_BIG_ENDIAN)
|
|
||||||
FORCEINLINE uint16 READ_BE_UINT16(const void *ptr) {
|
|
||||||
const byte *b = (const byte *)ptr;
|
|
||||||
return (b[0] << 8) + b[1];
|
|
||||||
}
|
|
||||||
FORCEINLINE uint32 READ_BE_UINT32(const void *ptr) {
|
|
||||||
const byte *b = (const byte*)ptr;
|
|
||||||
return (b[0] << 24) + (b[1] << 16) + (b[2] << 8) + (b[3]);
|
|
||||||
}
|
|
||||||
FORCEINLINE void WRITE_BE_UINT16(void *ptr, uint16 value) {
|
|
||||||
byte *b = (byte *)ptr;
|
|
||||||
b[0] = (byte)(value >> 8);
|
|
||||||
b[1] = (byte)(value >> 0);
|
|
||||||
}
|
|
||||||
FORCEINLINE void WRITE_BE_UINT32(void *ptr, uint32 value) {
|
|
||||||
byte *b = (byte *)ptr;
|
|
||||||
b[0] = (byte)(value >> 24);
|
|
||||||
b[1] = (byte)(value >> 16);
|
|
||||||
b[2] = (byte)(value >> 8);
|
|
||||||
b[3] = (byte)(value >> 0);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
FORCEINLINE uint16 READ_BE_UINT16(const void *ptr) {
|
|
||||||
return *(const uint16 *)(ptr);
|
|
||||||
}
|
|
||||||
FORCEINLINE uint32 READ_BE_UINT32(const void *ptr) {
|
|
||||||
return *(const uint32 *)(ptr);
|
|
||||||
}
|
|
||||||
FORCEINLINE void WRITE_BE_UINT16(void *ptr, uint16 value) {
|
|
||||||
*(uint16 *)(ptr) = value;
|
|
||||||
}
|
|
||||||
FORCEINLINE void WRITE_BE_UINT32(void *ptr, uint32 value) {
|
|
||||||
*(uint32 *)(ptr) = value;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FORCEINLINE uint32 READ_LE_UINT24(const void *ptr) {
|
|
||||||
const byte *b = (const byte *)ptr;
|
|
||||||
return (b[2] << 16) + (b[1] << 8) + (b[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE uint32 READ_BE_UINT24(const void *ptr) {
|
# endif // if defined(SYSTEM_NEED_ALIGNMENT)
|
||||||
const byte *b = (const byte*)ptr;
|
|
||||||
return (b[0] << 16) + (b[1] << 8) + (b[2]);
|
#endif // if defined(SYSTEM_LITTLE_ENDIAN)
|
||||||
|
|
||||||
|
inline uint32 READ_LE_UINT24(const void *ptr) {
|
||||||
|
const uint8 *b = (const uint8 *)ptr;
|
||||||
|
return (b[2] << 16) | (b[1] << 8) | (b[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32 READ_BE_UINT24(const void *ptr) {
|
||||||
|
const uint8 *b = (const uint8 *)ptr;
|
||||||
|
return (b[0] << 16) | (b[1] << 8) | (b[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SYSTEM_BIG_ENDIAN)
|
#if defined(SYSTEM_BIG_ENDIAN)
|
||||||
|
|
|
@ -48,6 +48,7 @@ enum Error {
|
||||||
kInvalidPathError, //!< Engine initialization: Invalid game path was passed
|
kInvalidPathError, //!< Engine initialization: Invalid game path was passed
|
||||||
kNoGameDataFoundError, //!< Engine initialization: No game data was found in the specified location
|
kNoGameDataFoundError, //!< Engine initialization: No game data was found in the specified location
|
||||||
kUnsupportedGameidError, //!< Engine initialization: Gameid not supported by this (Meta)Engine
|
kUnsupportedGameidError, //!< Engine initialization: Gameid not supported by this (Meta)Engine
|
||||||
|
kUnsupportedColorMode, //!< Engine initialization: Engine does not support backend's color mode
|
||||||
|
|
||||||
|
|
||||||
kReadPermissionDenied, //!< Unable to read data due to missing read permission
|
kReadPermissionDenied, //!< Unable to read data due to missing read permission
|
||||||
|
|
212
common/events.h
212
common/events.h
|
@ -31,6 +31,9 @@
|
||||||
#include "common/rect.h"
|
#include "common/rect.h"
|
||||||
#include "common/noncopyable.h"
|
#include "common/noncopyable.h"
|
||||||
|
|
||||||
|
#include "common/list.h"
|
||||||
|
#include "common/singleton.h"
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,6 +129,190 @@ struct Event {
|
||||||
Event() : type(EVENT_INVALID), synthetic(false) {}
|
Event() : type(EVENT_INVALID), synthetic(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A source of Events.
|
||||||
|
*
|
||||||
|
* An example for this is OSystem, it provides events created by the system
|
||||||
|
* and or user.
|
||||||
|
*/
|
||||||
|
class EventSource {
|
||||||
|
public:
|
||||||
|
virtual ~EventSource() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries a event from the source.
|
||||||
|
*
|
||||||
|
* @param event a reference to the event struct, where the event should be stored.
|
||||||
|
* @return true if an event was polled, false otherwise.
|
||||||
|
*/
|
||||||
|
virtual bool pollEvent(Event &event) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether events from this source are allowed to be mapped.
|
||||||
|
*
|
||||||
|
* Possible event sources not allowing mapping are: the event recorder/player and/or
|
||||||
|
* the EventManager, which allows user events to be pushed.
|
||||||
|
*
|
||||||
|
* By default we allow mapping for every event source.
|
||||||
|
*/
|
||||||
|
virtual bool allowMapping() const { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An artificial event source. This is class is used as an event source, which is
|
||||||
|
* made up by client specific events.
|
||||||
|
*
|
||||||
|
* Example usage cases for this are the Keymapper or the DefaultEventManager.
|
||||||
|
*/
|
||||||
|
class ArtificialEventSource : public EventSource {
|
||||||
|
protected:
|
||||||
|
Common::Queue<Common::Event> _artificialEventQueue;
|
||||||
|
public:
|
||||||
|
void addEvent(const Common::Event &ev) {
|
||||||
|
_artificialEventQueue.push(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pollEvent(Common::Event &ev) {
|
||||||
|
if (!_artificialEventQueue.empty()) {
|
||||||
|
ev = _artificialEventQueue.pop();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By default an artificial event source prevents its events
|
||||||
|
* from being mapped.
|
||||||
|
*/
|
||||||
|
virtual bool allowMapping() const { return false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object which catches and processes Events.
|
||||||
|
*
|
||||||
|
* An example for this is the Engine object, it is catching events and processing them.
|
||||||
|
*/
|
||||||
|
class EventObserver {
|
||||||
|
public:
|
||||||
|
virtual ~EventObserver() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the source of an incoming event.
|
||||||
|
*
|
||||||
|
* An obeser is supposed to eat the event, with returning true, when
|
||||||
|
* it might want prevent other observers from preventing to receive
|
||||||
|
* the event. An usage example here is the keymapper:
|
||||||
|
* If it processes an Event, it should 'eat' it and create a new
|
||||||
|
* event, which the EventDispatcher will then catch.
|
||||||
|
*
|
||||||
|
* @param event the event, which is incoming.
|
||||||
|
* @return true if this observer uses this event, false otherwise.
|
||||||
|
*/
|
||||||
|
virtual bool notifyEvent(const Event &event) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A event mapper, which will map events to others.
|
||||||
|
*
|
||||||
|
* An example for this is the Keymapper.
|
||||||
|
*/
|
||||||
|
class EventMapper : public EventSource, public EventObserver {
|
||||||
|
public:
|
||||||
|
/** For event mappers resulting events should never be mapped */
|
||||||
|
bool allowMapping() const { return false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches events from various sources to various observers.
|
||||||
|
*
|
||||||
|
* EventDispatcher is using a priority based approach. Observers
|
||||||
|
* with higher priority will be notified before observers with
|
||||||
|
* lower priority. Because of the possibility that oberservers
|
||||||
|
* might 'eat' events, not all observers might be notified.
|
||||||
|
*
|
||||||
|
* Another speciality is the support for a event mapper, which
|
||||||
|
* will catch events and create new events out of them. This
|
||||||
|
* mapper will be processed before an event is sent to the
|
||||||
|
* observers.
|
||||||
|
*/
|
||||||
|
class EventDispatcher {
|
||||||
|
public:
|
||||||
|
EventDispatcher();
|
||||||
|
~EventDispatcher();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to catch events from the registered event
|
||||||
|
* sources and dispatch them to the observers.
|
||||||
|
*
|
||||||
|
* This dispatches *all* events the sources offer.
|
||||||
|
*/
|
||||||
|
void dispatch();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers an event mapper with the dispatcher.
|
||||||
|
*
|
||||||
|
* The ownership of the "mapper" variable will pass
|
||||||
|
* to the EventDispatcher, thus it will be deleted
|
||||||
|
* with "delete", when EventDispatcher is destroyed.
|
||||||
|
*
|
||||||
|
* Note there is only one mapper per EventDispatcher
|
||||||
|
* possible, thus when this method is called twice,
|
||||||
|
* the former mapper will be destroied.
|
||||||
|
*/
|
||||||
|
void registerMapper(EventMapper *mapper);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries the setup event mapper.
|
||||||
|
*/
|
||||||
|
EventMapper *queryMapper() const { return _mapper; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a new EventSource with the Dispatcher.
|
||||||
|
*/
|
||||||
|
void registerSource(EventSource *source, bool autoFree);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters a EventSource.
|
||||||
|
*
|
||||||
|
* This takes the "autoFree" flag passed to registerSource into account.
|
||||||
|
*/
|
||||||
|
void unregisterSource(EventSource *source);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a new EventObserver with the Dispatcher.
|
||||||
|
*/
|
||||||
|
void registerObserver(EventObserver *obs, uint priority, bool autoFree);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters a EventObserver.
|
||||||
|
*
|
||||||
|
* This takes the "autoFree" flag passed to registerObserver into account.
|
||||||
|
*/
|
||||||
|
void unregisterObserver(EventObserver *obs);
|
||||||
|
private:
|
||||||
|
EventMapper *_mapper;
|
||||||
|
|
||||||
|
struct Entry {
|
||||||
|
bool autoFree;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SourceEntry : public Entry {
|
||||||
|
EventSource *source;
|
||||||
|
};
|
||||||
|
|
||||||
|
Common::List<SourceEntry> _sources;
|
||||||
|
|
||||||
|
struct ObserverEntry : public Entry {
|
||||||
|
uint priority;
|
||||||
|
EventObserver *observer;
|
||||||
|
};
|
||||||
|
|
||||||
|
Common::List<ObserverEntry> _observers;
|
||||||
|
|
||||||
|
void dispatchEvent(const Event &event);
|
||||||
|
};
|
||||||
|
|
||||||
class Keymapper;
|
class Keymapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -161,11 +348,6 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void pushEvent(const Common::Event &event) = 0;
|
virtual void pushEvent(const Common::Event &event) = 0;
|
||||||
|
|
||||||
/** Register random source so it can be serialized in game test purposes **/
|
|
||||||
virtual void registerRandomSource(Common::RandomSource &rnd, const char *name) = 0;
|
|
||||||
|
|
||||||
virtual void processMillis(uint32 &millis) = 0;
|
|
||||||
|
|
||||||
/** Return the current mouse position */
|
/** Return the current mouse position */
|
||||||
virtual Common::Point getMousePos() const = 0;
|
virtual Common::Point getMousePos() const = 0;
|
||||||
|
|
||||||
|
@ -195,7 +377,9 @@ public:
|
||||||
* Used when we have returned to the launcher.
|
* Used when we have returned to the launcher.
|
||||||
*/
|
*/
|
||||||
virtual void resetRTL() = 0;
|
virtual void resetRTL() = 0;
|
||||||
|
#ifdef FORCE_RTL
|
||||||
|
virtual void resetQuit() = 0;
|
||||||
|
#endif
|
||||||
// Optional: check whether a given key is currently pressed ????
|
// Optional: check whether a given key is currently pressed ????
|
||||||
//virtual bool isKeyPressed(int keycode) = 0;
|
//virtual bool isKeyPressed(int keycode) = 0;
|
||||||
|
|
||||||
|
@ -207,9 +391,21 @@ public:
|
||||||
virtual Common::Keymapper *getKeymapper() = 0;
|
virtual Common::Keymapper *getKeymapper() = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
enum {
|
||||||
|
/**
|
||||||
|
* Priority of the event manager, for now it's lowest since it eats
|
||||||
|
* *all* events, we might to change that in the future though.
|
||||||
|
*/
|
||||||
|
kEventManPriority = 0
|
||||||
|
};
|
||||||
|
|
||||||
Common::Queue<Common::Event> artificialEventQueue;
|
/**
|
||||||
|
* Returns the underlying EventDispatcher.
|
||||||
|
*/
|
||||||
|
EventDispatcher *getEventDispatcher() { return &_dispatcher; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
EventDispatcher _dispatcher;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace Common
|
} // End of namespace Common
|
||||||
|
|
|
@ -32,16 +32,6 @@
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
void File::addDefaultDirectory(const String &directory) {
|
|
||||||
FSNode dir(directory);
|
|
||||||
addDefaultDirectory(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
void File::addDefaultDirectory(const FSNode &dir) {
|
|
||||||
if (dir.exists() && dir.isDirectory())
|
|
||||||
SearchMan.addDirectory(dir.getPath(), dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
File::File()
|
File::File()
|
||||||
: _handle(0) {
|
: _handle(0) {
|
||||||
}
|
}
|
||||||
|
@ -120,15 +110,6 @@ bool File::isOpen() const {
|
||||||
return _handle != NULL;
|
return _handle != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool File::ioFailed() const {
|
|
||||||
return !_handle || (eos() || err());
|
|
||||||
}
|
|
||||||
|
|
||||||
void File::clearIOFailed() {
|
|
||||||
if (_handle)
|
|
||||||
_handle->clearErr();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool File::err() const {
|
bool File::err() const {
|
||||||
assert(_handle);
|
assert(_handle);
|
||||||
return _handle->err();
|
return _handle->err();
|
||||||
|
|
|
@ -48,10 +48,6 @@ protected:
|
||||||
String _name;
|
String _name;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static void addDefaultDirectory(const String &directory);
|
|
||||||
static void addDefaultDirectory(const FSNode &directory);
|
|
||||||
|
|
||||||
File();
|
File();
|
||||||
virtual ~File();
|
virtual ~File();
|
||||||
|
|
||||||
|
@ -126,19 +122,6 @@ public:
|
||||||
*/
|
*/
|
||||||
const char *getName() const { return _name.c_str(); }
|
const char *getName() const { return _name.c_str(); }
|
||||||
|
|
||||||
/**
|
|
||||||
* DEPRECATED: Use err() or eos() instead.
|
|
||||||
* Returns true if any I/O failure occurred or the end of the
|
|
||||||
* stream was reached while reading.
|
|
||||||
*/
|
|
||||||
bool ioFailed() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DEPRECATED: Don't use this unless you are still using ioFailed().
|
|
||||||
* Reset the I/O error status.
|
|
||||||
*/
|
|
||||||
void clearIOFailed();
|
|
||||||
|
|
||||||
bool err() const; // implement abstract Stream method
|
bool err() const; // implement abstract Stream method
|
||||||
void clearErr(); // implement abstract Stream method
|
void clearErr(); // implement abstract Stream method
|
||||||
bool eos() const; // implement abstract SeekableReadStream method
|
bool eos() const; // implement abstract SeekableReadStream method
|
||||||
|
|
|
@ -249,7 +249,7 @@ SeekableReadStream *FSDirectory::createReadStreamForMember(const String &name) c
|
||||||
}
|
}
|
||||||
|
|
||||||
FSDirectory *FSDirectory::getSubDirectory(const String &name, int depth, bool flat) {
|
FSDirectory *FSDirectory::getSubDirectory(const String &name, int depth, bool flat) {
|
||||||
return getSubDirectory(String::emptyString, name, depth, flat);
|
return getSubDirectory(String(), name, depth, flat);
|
||||||
}
|
}
|
||||||
|
|
||||||
FSDirectory *FSDirectory::getSubDirectory(const String &prefix, const String &name, int depth, bool flat) {
|
FSDirectory *FSDirectory::getSubDirectory(const String &prefix, const String &name, int depth, bool flat) {
|
||||||
|
@ -320,7 +320,7 @@ int FSDirectory::listMatchingMembers(ArchiveMemberList &list, const String &patt
|
||||||
int matches = 0;
|
int matches = 0;
|
||||||
NodeCache::iterator it = _fileCache.begin();
|
NodeCache::iterator it = _fileCache.begin();
|
||||||
for ( ; it != _fileCache.end(); ++it) {
|
for ( ; it != _fileCache.end(); ++it) {
|
||||||
if (it->_key.matchString(lowercasePattern, true)) {
|
if (it->_key.matchString(lowercasePattern, false, true)) {
|
||||||
list.push_back(ArchiveMemberPtr(new FSNode(it->_value)));
|
list.push_back(ArchiveMemberPtr(new FSNode(it->_value)));
|
||||||
matches++;
|
matches++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,12 @@
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
|
// The sgi IRIX MIPSpro Compiler has difficulties with nested templates.
|
||||||
|
// This and the other __sgi conditionals below work around these problems.
|
||||||
|
#ifdef __sgi
|
||||||
|
template<class T> class IteratorImpl;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Enable the following #define if you want to check how many collisions the
|
// Enable the following #define if you want to check how many collisions the
|
||||||
// code produces (many collisions indicate either a bad hash function, or a
|
// code produces (many collisions indicate either a bad hash function, or a
|
||||||
// hash table that is too small).
|
// hash table that is too small).
|
||||||
|
@ -93,39 +99,41 @@ public:
|
||||||
|
|
||||||
ObjectPool<Node, HASHMAP_MEMORYPOOL_SIZE> _nodePool;
|
ObjectPool<Node, HASHMAP_MEMORYPOOL_SIZE> _nodePool;
|
||||||
|
|
||||||
Node *allocNode(const Key &key) {
|
Node **_storage; ///< hashtable of size arrsize.
|
||||||
return new (_nodePool) Node(key);
|
uint _mask; ///< Capacity of the HashMap minus one; must be a power of two of minus one
|
||||||
}
|
|
||||||
|
|
||||||
void freeNode(Node *node) {
|
|
||||||
if (node && node != &_dummyNode)
|
|
||||||
_nodePool.deleteChunk(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
Node **_storage; // hashtable of size arrsize.
|
|
||||||
uint _mask; /**< Capacity of the HashMap minus one; must be a power of two of minus one */
|
|
||||||
uint _size;
|
uint _size;
|
||||||
uint _deleted; ///< Number of deleted elements (_dummyNodes)
|
uint _deleted; ///< Number of deleted elements (_dummyNodes)
|
||||||
|
|
||||||
HashFunc _hash;
|
HashFunc _hash;
|
||||||
EqualFunc _equal;
|
EqualFunc _equal;
|
||||||
|
|
||||||
// Default value, returned by the const getVal.
|
/** Default value, returned by the const getVal. */
|
||||||
const Val _defaultVal;
|
const Val _defaultVal;
|
||||||
|
|
||||||
// Dummy node, used as marker for erased objects.
|
/** Dummy node, used as marker for erased objects. */
|
||||||
Node _dummyNode;
|
#define HASHMAP_DUMMY_NODE ((Node *)1)
|
||||||
|
|
||||||
#ifdef DEBUG_HASH_COLLISIONS
|
#ifdef DEBUG_HASH_COLLISIONS
|
||||||
mutable int _collisions, _lookups, _dummyHits;
|
mutable int _collisions, _lookups, _dummyHits;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Node *allocNode(const Key &key) {
|
||||||
|
return new (_nodePool) Node(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeNode(Node *node) {
|
||||||
|
if (node && node != HASHMAP_DUMMY_NODE)
|
||||||
|
_nodePool.deleteChunk(node);
|
||||||
|
}
|
||||||
|
|
||||||
void assign(const HM_t &map);
|
void assign(const HM_t &map);
|
||||||
int lookup(const Key &key) const;
|
int lookup(const Key &key) const;
|
||||||
int lookupAndCreateIfMissing(const Key &key);
|
int lookupAndCreateIfMissing(const Key &key);
|
||||||
void expandStorage(uint newCapacity);
|
void expandStorage(uint newCapacity);
|
||||||
|
|
||||||
|
#ifndef __sgi
|
||||||
template<class T> friend class IteratorImpl;
|
template<class T> friend class IteratorImpl;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple HashMap iterator implementation.
|
* Simple HashMap iterator implementation.
|
||||||
|
@ -133,7 +141,11 @@ public:
|
||||||
template<class NodeType>
|
template<class NodeType>
|
||||||
class IteratorImpl {
|
class IteratorImpl {
|
||||||
friend class HashMap;
|
friend class HashMap;
|
||||||
|
#ifdef __sgi
|
||||||
|
template<class T> friend class Common::IteratorImpl;
|
||||||
|
#else
|
||||||
template<class T> friend class IteratorImpl;
|
template<class T> friend class IteratorImpl;
|
||||||
|
#endif
|
||||||
protected:
|
protected:
|
||||||
typedef const HashMap hashmap_t;
|
typedef const HashMap hashmap_t;
|
||||||
|
|
||||||
|
@ -148,6 +160,7 @@ public:
|
||||||
assert(_idx <= _hashmap->_mask);
|
assert(_idx <= _hashmap->_mask);
|
||||||
Node *node = _hashmap->_storage[_idx];
|
Node *node = _hashmap->_storage[_idx];
|
||||||
assert(node != 0);
|
assert(node != 0);
|
||||||
|
assert(node != HASHMAP_DUMMY_NODE);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +179,7 @@ public:
|
||||||
assert(_hashmap);
|
assert(_hashmap);
|
||||||
do {
|
do {
|
||||||
_idx++;
|
_idx++;
|
||||||
} while (_idx <= _hashmap->_mask && _hashmap->_storage[_idx] == 0);
|
} while (_idx <= _hashmap->_mask && (_hashmap->_storage[_idx] == 0 || _hashmap->_storage[_idx] == HASHMAP_DUMMY_NODE));
|
||||||
if (_idx > _hashmap->_mask)
|
if (_idx > _hashmap->_mask)
|
||||||
_idx = (uint)-1;
|
_idx = (uint)-1;
|
||||||
|
|
||||||
|
@ -207,6 +220,7 @@ public:
|
||||||
|
|
||||||
Val &getVal(const Key &key);
|
Val &getVal(const Key &key);
|
||||||
const Val &getVal(const Key &key) const;
|
const Val &getVal(const Key &key) const;
|
||||||
|
const Val &getVal(const Key &key, const Val &defaultVal) const;
|
||||||
void setVal(const Key &key, const Val &val);
|
void setVal(const Key &key, const Val &val);
|
||||||
|
|
||||||
void clear(bool shrinkArray = 0);
|
void clear(bool shrinkArray = 0);
|
||||||
|
@ -218,7 +232,7 @@ public:
|
||||||
iterator begin() {
|
iterator begin() {
|
||||||
// Find and return the first non-empty entry
|
// Find and return the first non-empty entry
|
||||||
for (uint ctr = 0; ctr <= _mask; ++ctr) {
|
for (uint ctr = 0; ctr <= _mask; ++ctr) {
|
||||||
if (_storage[ctr])
|
if (_storage[ctr] && _storage[ctr] != HASHMAP_DUMMY_NODE)
|
||||||
return iterator(ctr, this);
|
return iterator(ctr, this);
|
||||||
}
|
}
|
||||||
return end();
|
return end();
|
||||||
|
@ -230,7 +244,7 @@ public:
|
||||||
const_iterator begin() const {
|
const_iterator begin() const {
|
||||||
// Find and return the first non-empty entry
|
// Find and return the first non-empty entry
|
||||||
for (uint ctr = 0; ctr <= _mask; ++ctr) {
|
for (uint ctr = 0; ctr <= _mask; ++ctr) {
|
||||||
if (_storage[ctr])
|
if (_storage[ctr] && _storage[ctr] != HASHMAP_DUMMY_NODE)
|
||||||
return const_iterator(ctr, this);
|
return const_iterator(ctr, this);
|
||||||
}
|
}
|
||||||
return end();
|
return end();
|
||||||
|
@ -274,7 +288,7 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap()
|
||||||
#ifdef __PLAYSTATION2__
|
#ifdef __PLAYSTATION2__
|
||||||
{
|
{
|
||||||
#else
|
#else
|
||||||
: _defaultVal(), _dummyNode() {
|
: _defaultVal() {
|
||||||
#endif
|
#endif
|
||||||
_mask = HASHMAP_MIN_CAPACITY - 1;
|
_mask = HASHMAP_MIN_CAPACITY - 1;
|
||||||
_storage = new Node *[HASHMAP_MIN_CAPACITY];
|
_storage = new Node *[HASHMAP_MIN_CAPACITY];
|
||||||
|
@ -298,7 +312,7 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap()
|
||||||
*/
|
*/
|
||||||
template<class Key, class Val, class HashFunc, class EqualFunc>
|
template<class Key, class Val, class HashFunc, class EqualFunc>
|
||||||
HashMap<Key, Val, HashFunc, EqualFunc>::HashMap(const HM_t &map) :
|
HashMap<Key, Val, HashFunc, EqualFunc>::HashMap(const HM_t &map) :
|
||||||
_defaultVal(), _dummyNode() {
|
_defaultVal() {
|
||||||
#ifdef DEBUG_HASH_COLLISIONS
|
#ifdef DEBUG_HASH_COLLISIONS
|
||||||
_collisions = 0;
|
_collisions = 0;
|
||||||
_lookups = 0;
|
_lookups = 0;
|
||||||
|
@ -340,8 +354,8 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::assign(const HM_t &map) {
|
||||||
_size = 0;
|
_size = 0;
|
||||||
_deleted = 0;
|
_deleted = 0;
|
||||||
for (uint ctr = 0; ctr <= _mask; ++ctr) {
|
for (uint ctr = 0; ctr <= _mask; ++ctr) {
|
||||||
if (map._storage[ctr] == &map._dummyNode) {
|
if (map._storage[ctr] == HASHMAP_DUMMY_NODE) {
|
||||||
_storage[ctr] = &_dummyNode;
|
_storage[ctr] = HASHMAP_DUMMY_NODE;
|
||||||
_deleted++;
|
_deleted++;
|
||||||
} else if (map._storage[ctr] != NULL) {
|
} else if (map._storage[ctr] != NULL) {
|
||||||
_storage[ctr] = allocNode(map._storage[ctr]->_key);
|
_storage[ctr] = allocNode(map._storage[ctr]->_key);
|
||||||
|
@ -383,7 +397,9 @@ template<class Key, class Val, class HashFunc, class EqualFunc>
|
||||||
void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) {
|
void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) {
|
||||||
assert(newCapacity > _mask+1);
|
assert(newCapacity > _mask+1);
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
const uint old_size = _size;
|
const uint old_size = _size;
|
||||||
|
#endif
|
||||||
const uint old_mask = _mask;
|
const uint old_mask = _mask;
|
||||||
Node **old_storage = _storage;
|
Node **old_storage = _storage;
|
||||||
|
|
||||||
|
@ -397,7 +413,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) {
|
||||||
|
|
||||||
// rehash all the old elements
|
// rehash all the old elements
|
||||||
for (uint ctr = 0; ctr <= old_mask; ++ctr) {
|
for (uint ctr = 0; ctr <= old_mask; ++ctr) {
|
||||||
if (old_storage[ctr] == NULL || old_storage[ctr] == &_dummyNode)
|
if (old_storage[ctr] == NULL || old_storage[ctr] == HASHMAP_DUMMY_NODE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Insert the element from the old table into the new table.
|
// Insert the element from the old table into the new table.
|
||||||
|
@ -406,7 +422,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(uint newCapacity) {
|
||||||
// don't have to call _equal().
|
// don't have to call _equal().
|
||||||
const uint hash = _hash(old_storage[ctr]->_key);
|
const uint hash = _hash(old_storage[ctr]->_key);
|
||||||
uint idx = hash & _mask;
|
uint idx = hash & _mask;
|
||||||
for (uint perturb = hash; _storage[idx] != NULL && _storage[idx] != &_dummyNode; perturb >>= HASHMAP_PERTURB_SHIFT) {
|
for (uint perturb = hash; _storage[idx] != NULL && _storage[idx] != HASHMAP_DUMMY_NODE; perturb >>= HASHMAP_PERTURB_SHIFT) {
|
||||||
idx = (5 * idx + perturb + 1) & _mask;
|
idx = (5 * idx + perturb + 1) & _mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,7 +446,7 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const {
|
||||||
for (uint perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) {
|
for (uint perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) {
|
||||||
if (_storage[ctr] == NULL)
|
if (_storage[ctr] == NULL)
|
||||||
break;
|
break;
|
||||||
if (_storage[ctr] == &_dummyNode) {
|
if (_storage[ctr] == HASHMAP_DUMMY_NODE) {
|
||||||
#ifdef DEBUG_HASH_COLLISIONS
|
#ifdef DEBUG_HASH_COLLISIONS
|
||||||
_dummyHits++;
|
_dummyHits++;
|
||||||
#endif
|
#endif
|
||||||
|
@ -464,7 +480,7 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key &
|
||||||
for (uint perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) {
|
for (uint perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) {
|
||||||
if (_storage[ctr] == NULL)
|
if (_storage[ctr] == NULL)
|
||||||
break;
|
break;
|
||||||
if (_storage[ctr] == &_dummyNode) {
|
if (_storage[ctr] == HASHMAP_DUMMY_NODE) {
|
||||||
#ifdef DEBUG_HASH_COLLISIONS
|
#ifdef DEBUG_HASH_COLLISIONS
|
||||||
_dummyHits++;
|
_dummyHits++;
|
||||||
#endif
|
#endif
|
||||||
|
@ -540,11 +556,16 @@ Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) {
|
||||||
|
|
||||||
template<class Key, class Val, class HashFunc, class EqualFunc>
|
template<class Key, class Val, class HashFunc, class EqualFunc>
|
||||||
const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) const {
|
const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) const {
|
||||||
|
return getVal(key, _defaultVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Key, class Val, class HashFunc, class EqualFunc>
|
||||||
|
const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key, const Val &defaultVal) const {
|
||||||
uint ctr = lookup(key);
|
uint ctr = lookup(key);
|
||||||
if (_storage[ctr] != NULL)
|
if (_storage[ctr] != NULL)
|
||||||
return _storage[ctr]->_value;
|
return _storage[ctr]->_value;
|
||||||
else
|
else
|
||||||
return _defaultVal;
|
return defaultVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Key, class Val, class HashFunc, class EqualFunc>
|
template<class Key, class Val, class HashFunc, class EqualFunc>
|
||||||
|
@ -563,12 +584,14 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::erase(const Key &key) {
|
||||||
|
|
||||||
// If we remove a key, we replace it with a dummy node.
|
// If we remove a key, we replace it with a dummy node.
|
||||||
freeNode(_storage[ctr]);
|
freeNode(_storage[ctr]);
|
||||||
_storage[ctr] = &_dummyNode;
|
_storage[ctr] = HASHMAP_DUMMY_NODE;
|
||||||
_size--;
|
_size--;
|
||||||
_deleted++;
|
_deleted++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef HASHMAP_DUMMY_NODE
|
||||||
|
|
||||||
} // End of namespace Common
|
} // End of namespace Common
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -46,6 +46,12 @@ MemoryPool::MemoryPool(size_t chunkSize) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryPool::~MemoryPool() {
|
MemoryPool::~MemoryPool() {
|
||||||
|
#if 0
|
||||||
|
freeUnusedPages();
|
||||||
|
if (!_pages.empty())
|
||||||
|
warning("Memory leak found in pool");
|
||||||
|
#endif
|
||||||
|
|
||||||
for (size_t i = 0; i < _pages.size(); ++i)
|
for (size_t i = 0; i < _pages.size(); ++i)
|
||||||
::free(_pages[i].start);
|
::free(_pages[i].start);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +68,7 @@ void MemoryPool::allocPage() {
|
||||||
_pages.push_back(page);
|
_pages.push_back(page);
|
||||||
|
|
||||||
|
|
||||||
// Next time, we'll alocate a page twice as big as this one.
|
// Next time, we'll allocate a page twice as big as this one.
|
||||||
_chunksPerPage *= 2;
|
_chunksPerPage *= 2;
|
||||||
|
|
||||||
// Add the page to the pool of free chunk
|
// Add the page to the pool of free chunk
|
||||||
|
|
|
@ -5,6 +5,8 @@ MODULE_OBJS := \
|
||||||
config-file.o \
|
config-file.o \
|
||||||
config-manager.o \
|
config-manager.o \
|
||||||
debug.o \
|
debug.o \
|
||||||
|
EventDispatcher.o \
|
||||||
|
EventRecorder.o \
|
||||||
file.o \
|
file.o \
|
||||||
fs.o \
|
fs.o \
|
||||||
hashmap.o \
|
hashmap.o \
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
|
|
||||||
#include "common/memorypool.h"
|
#include "common/memorypool.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#if !defined(__SYMBIAN32__)
|
#if !defined(__SYMBIAN32__)
|
||||||
#include <new>
|
#include <new>
|
||||||
#endif
|
#endif
|
||||||
|
@ -350,12 +352,12 @@ bool String::contains(char x) const {
|
||||||
return strchr(c_str(), x) != NULL;
|
return strchr(c_str(), x) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool String::matchString(const char *pat, bool pathMode) const {
|
bool String::matchString(const char *pat, bool ignoreCase, bool pathMode) const {
|
||||||
return Common::matchString(c_str(), pat, pathMode);
|
return Common::matchString(c_str(), pat, ignoreCase, pathMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool String::matchString(const String &pat, bool pathMode) const {
|
bool String::matchString(const String &pat, bool ignoreCase, bool pathMode) const {
|
||||||
return Common::matchString(c_str(), pat.c_str(), pathMode);
|
return Common::matchString(c_str(), pat.c_str(), ignoreCase, pathMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void String::deleteLastChar() {
|
void String::deleteLastChar() {
|
||||||
|
@ -435,6 +437,50 @@ uint String::hash() const {
|
||||||
return hashit(c_str());
|
return hashit(c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
String String::printf(const char *fmt, ...) {
|
||||||
|
String output;
|
||||||
|
assert(output.isStorageIntern());
|
||||||
|
|
||||||
|
va_list va;
|
||||||
|
va_start(va, fmt);
|
||||||
|
int len = vsnprintf(output._str, _builtinCapacity, fmt, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
if (len == -1) {
|
||||||
|
// MSVC doesn't return the size the full string would take up.
|
||||||
|
// Try increasing the size of the string until it fits.
|
||||||
|
|
||||||
|
// We assume MSVC failed to output the correct, null-terminated string
|
||||||
|
// if the return value is either -1 or size.
|
||||||
|
int size = _builtinCapacity;
|
||||||
|
do {
|
||||||
|
size *= 2;
|
||||||
|
output.ensureCapacity(size-1, false);
|
||||||
|
assert(!output.isStorageIntern());
|
||||||
|
size = output._extern._capacity;
|
||||||
|
|
||||||
|
va_start(va, fmt);
|
||||||
|
len = vsnprintf(output._str, size, fmt, va);
|
||||||
|
va_end(va);
|
||||||
|
} while (len == -1 || len >= size);
|
||||||
|
} else if (len < (int)_builtinCapacity) {
|
||||||
|
// vsnprintf succeeded
|
||||||
|
output._size = len;
|
||||||
|
} else {
|
||||||
|
// vsnprintf didn't have enough space, so grow buffer
|
||||||
|
output.ensureCapacity(len, false);
|
||||||
|
va_start(va, fmt);
|
||||||
|
int len2 = vsnprintf(output._str, len+1, fmt, va);
|
||||||
|
va_end(va);
|
||||||
|
assert(len == len2);
|
||||||
|
output._size = len2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
bool String::operator ==(const String &x) const {
|
bool String::operator ==(const String &x) const {
|
||||||
|
@ -635,7 +681,7 @@ Common::String normalizePath(const Common::String &path, const char sep) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool matchString(const char *str, const char *pat, bool pathMode) {
|
bool matchString(const char *str, const char *pat, bool ignoreCase, bool pathMode) {
|
||||||
assert(str);
|
assert(str);
|
||||||
assert(pat);
|
assert(pat);
|
||||||
|
|
||||||
|
@ -652,7 +698,7 @@ bool matchString(const char *str, const char *pat, bool pathMode) {
|
||||||
|
|
||||||
switch (*pat) {
|
switch (*pat) {
|
||||||
case '*':
|
case '*':
|
||||||
// Record pattern / string possition for backtracking
|
// Record pattern / string position for backtracking
|
||||||
p = ++pat;
|
p = ++pat;
|
||||||
q = str;
|
q = str;
|
||||||
// If pattern ended with * -> match
|
// If pattern ended with * -> match
|
||||||
|
@ -661,7 +707,8 @@ bool matchString(const char *str, const char *pat, bool pathMode) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (*pat != *str) {
|
if ((!ignoreCase && *pat != *str) ||
|
||||||
|
(ignoreCase && tolower(*pat) != tolower(*str))) {
|
||||||
if (p) {
|
if (p) {
|
||||||
// No match, oops -> try to backtrack
|
// No match, oops -> try to backtrack
|
||||||
pat = p;
|
pat = p;
|
||||||
|
|
13
common/str.h
13
common/str.h
|
@ -170,12 +170,13 @@ public:
|
||||||
*
|
*
|
||||||
* @param str Text to be matched against the given pattern.
|
* @param str Text to be matched against the given pattern.
|
||||||
* @param pat Glob pattern.
|
* @param pat Glob pattern.
|
||||||
|
* @param ignoreCase Whether to ignore the case when doing pattern match
|
||||||
* @param pathMode Whether to use path mode, i.e., whether slashes must be matched explicitly.
|
* @param pathMode Whether to use path mode, i.e., whether slashes must be matched explicitly.
|
||||||
*
|
*
|
||||||
* @return true if str matches the pattern, false otherwise.
|
* @return true if str matches the pattern, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool matchString(const char *pat, bool pathMode = false) const;
|
bool matchString(const char *pat, bool ignoreCase = false, bool pathMode = false) const;
|
||||||
bool matchString(const String &pat, bool pathMode = false) const;
|
bool matchString(const String &pat, bool ignoreCase = false, bool pathMode = false) const;
|
||||||
|
|
||||||
|
|
||||||
inline const char *c_str() const { return _str; }
|
inline const char *c_str() const { return _str; }
|
||||||
|
@ -218,6 +219,11 @@ public:
|
||||||
|
|
||||||
uint hash() const;
|
uint hash() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Printf-like function. Returns a formatted String.
|
||||||
|
*/
|
||||||
|
static Common::String printf(const char *fmt, ...) GCC_PRINTF(1,2);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef char * iterator;
|
typedef char * iterator;
|
||||||
typedef const char * const_iterator;
|
typedef const char * const_iterator;
|
||||||
|
@ -311,11 +317,12 @@ Common::String normalizePath(const Common::String &path, const char sep);
|
||||||
*
|
*
|
||||||
* @param str Text to be matched against the given pattern.
|
* @param str Text to be matched against the given pattern.
|
||||||
* @param pat Glob pattern.
|
* @param pat Glob pattern.
|
||||||
|
* @param ignoreCase Whether to ignore the case when doing pattern match
|
||||||
* @param pathMode Whether to use path mode, i.e., whether slashes must be matched explicitly.
|
* @param pathMode Whether to use path mode, i.e., whether slashes must be matched explicitly.
|
||||||
*
|
*
|
||||||
* @return true if str matches the pattern, false otherwise.
|
* @return true if str matches the pattern, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool matchString(const char *str, const char *pat, bool pathMode = false);
|
bool matchString(const char *str, const char *pat, bool ignoreCase = false, bool pathMode = false);
|
||||||
|
|
||||||
|
|
||||||
typedef Array<String> StringList;
|
typedef Array<String> StringList;
|
||||||
|
|
120
common/stream.h
120
common/stream.h
|
@ -27,6 +27,7 @@
|
||||||
#define COMMON_STREAM_H
|
#define COMMON_STREAM_H
|
||||||
|
|
||||||
#include "common/sys.h"
|
#include "common/sys.h"
|
||||||
|
#include "common/endian.h"
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
|
@ -106,38 +107,38 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeUint16LE(uint16 value) {
|
void writeUint16LE(uint16 value) {
|
||||||
writeByte((byte)(value & 0xff));
|
value = TO_LE_16(value);
|
||||||
writeByte((byte)(value >> 8));
|
write(&value, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeUint32LE(uint32 value) {
|
void writeUint32LE(uint32 value) {
|
||||||
writeUint16LE((uint16)(value & 0xffff));
|
value = TO_LE_32(value);
|
||||||
writeUint16LE((uint16)(value >> 16));
|
write(&value, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeUint16BE(uint16 value) {
|
void writeUint16BE(uint16 value) {
|
||||||
writeByte((byte)(value >> 8));
|
value = TO_BE_16(value);
|
||||||
writeByte((byte)(value & 0xff));
|
write(&value, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeUint32BE(uint32 value) {
|
void writeUint32BE(uint32 value) {
|
||||||
writeUint16BE((uint16)(value >> 16));
|
value = TO_BE_32(value);
|
||||||
writeUint16BE((uint16)(value & 0xffff));
|
write(&value, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeSint16LE(int16 value) {
|
FORCEINLINE void writeSint16LE(int16 value) {
|
||||||
writeUint16LE((uint16)value);
|
writeUint16LE((uint16)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeSint32LE(int32 value) {
|
FORCEINLINE void writeSint32LE(int32 value) {
|
||||||
writeUint32LE((uint32)value);
|
writeUint32LE((uint32)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeSint16BE(int16 value) {
|
FORCEINLINE void writeSint16BE(int16 value) {
|
||||||
writeUint16BE((uint16)value);
|
writeUint16BE((uint16)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeSint32BE(int32 value) {
|
FORCEINLINE void writeSint32BE(int32 value) {
|
||||||
writeUint32BE((uint32)value);
|
writeUint32BE((uint32)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +180,7 @@ public:
|
||||||
* DEPRECATED
|
* DEPRECATED
|
||||||
* Default implementation for backward compatibility
|
* Default implementation for backward compatibility
|
||||||
*/
|
*/
|
||||||
virtual bool ioFailed() { return (eos() || err()); }
|
inline bool ioFailed() { return (eos() || err()); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read an unsigned byte from the stream and return it.
|
* Read an unsigned byte from the stream and return it.
|
||||||
|
@ -188,7 +189,7 @@ public:
|
||||||
* calling err() and eos() ).
|
* calling err() and eos() ).
|
||||||
*/
|
*/
|
||||||
byte readByte() {
|
byte readByte() {
|
||||||
byte b = 0;
|
byte b = 0; // FIXME: remove initialisation
|
||||||
read(&b, 1);
|
read(&b, 1);
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
@ -199,10 +200,8 @@ public:
|
||||||
* if a read error occurred (for which client code can check by
|
* if a read error occurred (for which client code can check by
|
||||||
* calling err() and eos() ).
|
* calling err() and eos() ).
|
||||||
*/
|
*/
|
||||||
int8 readSByte() {
|
FORCEINLINE int8 readSByte() {
|
||||||
int8 b = 0;
|
return (int8)readByte();
|
||||||
read(&b, 1);
|
|
||||||
return b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -213,9 +212,9 @@ public:
|
||||||
* calling err() and eos() ).
|
* calling err() and eos() ).
|
||||||
*/
|
*/
|
||||||
uint16 readUint16LE() {
|
uint16 readUint16LE() {
|
||||||
uint16 a = readByte();
|
uint16 val;
|
||||||
uint16 b = readByte();
|
read(&val, 2);
|
||||||
return a | (b << 8);
|
return FROM_LE_16(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -226,9 +225,9 @@ public:
|
||||||
* calling err() and eos() ).
|
* calling err() and eos() ).
|
||||||
*/
|
*/
|
||||||
uint32 readUint32LE() {
|
uint32 readUint32LE() {
|
||||||
uint32 a = readUint16LE();
|
uint32 val;
|
||||||
uint32 b = readUint16LE();
|
read(&val, 4);
|
||||||
return (b << 16) | a;
|
return FROM_LE_32(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -239,9 +238,9 @@ public:
|
||||||
* calling err() and eos() ).
|
* calling err() and eos() ).
|
||||||
*/
|
*/
|
||||||
uint16 readUint16BE() {
|
uint16 readUint16BE() {
|
||||||
uint16 b = readByte();
|
uint16 val;
|
||||||
uint16 a = readByte();
|
read(&val, 2);
|
||||||
return a | (b << 8);
|
return FROM_BE_16(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -252,9 +251,9 @@ public:
|
||||||
* calling err() and eos() ).
|
* calling err() and eos() ).
|
||||||
*/
|
*/
|
||||||
uint32 readUint32BE() {
|
uint32 readUint32BE() {
|
||||||
uint32 b = readUint16BE();
|
uint32 val;
|
||||||
uint32 a = readUint16BE();
|
read(&val, 4);
|
||||||
return (b << 16) | a;
|
return FROM_BE_32(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -264,7 +263,7 @@ public:
|
||||||
* if a read error occurred (for which client code can check by
|
* if a read error occurred (for which client code can check by
|
||||||
* calling err() and eos() ).
|
* calling err() and eos() ).
|
||||||
*/
|
*/
|
||||||
int16 readSint16LE() {
|
FORCEINLINE int16 readSint16LE() {
|
||||||
return (int16)readUint16LE();
|
return (int16)readUint16LE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +274,7 @@ public:
|
||||||
* if a read error occurred (for which client code can check by
|
* if a read error occurred (for which client code can check by
|
||||||
* calling err() and eos() ).
|
* calling err() and eos() ).
|
||||||
*/
|
*/
|
||||||
int32 readSint32LE() {
|
FORCEINLINE int32 readSint32LE() {
|
||||||
return (int32)readUint32LE();
|
return (int32)readUint32LE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +285,7 @@ public:
|
||||||
* if a read error occurred (for which client code can check by
|
* if a read error occurred (for which client code can check by
|
||||||
* calling err() and eos() ).
|
* calling err() and eos() ).
|
||||||
*/
|
*/
|
||||||
int16 readSint16BE() {
|
FORCEINLINE int16 readSint16BE() {
|
||||||
return (int16)readUint16BE();
|
return (int16)readUint16BE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +296,7 @@ public:
|
||||||
* if a read error occurred (for which client code can check by
|
* if a read error occurred (for which client code can check by
|
||||||
* calling err() and eos() ).
|
* calling err() and eos() ).
|
||||||
*/
|
*/
|
||||||
int32 readSint32BE() {
|
FORCEINLINE int32 readSint32BE() {
|
||||||
return (int32)readUint32BE();
|
return (int32)readUint32BE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,6 +399,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* SubReadStream provides access to a ReadStream restricted to the range
|
* SubReadStream provides access to a ReadStream restricted to the range
|
||||||
* [currentPosition, currentPosition+end).
|
* [currentPosition, currentPosition+end).
|
||||||
|
*
|
||||||
* Manipulating the parent stream directly /will/ mess up a substream.
|
* Manipulating the parent stream directly /will/ mess up a substream.
|
||||||
* Likewise, manipulating two substreams of a parent stream will cause them to
|
* Likewise, manipulating two substreams of a parent stream will cause them to
|
||||||
* step on each others toes.
|
* step on each others toes.
|
||||||
|
@ -434,6 +434,9 @@ public:
|
||||||
* SeekableSubReadStream provides access to a SeekableReadStream restricted to
|
* SeekableSubReadStream provides access to a SeekableReadStream restricted to
|
||||||
* the range [begin, end).
|
* the range [begin, end).
|
||||||
* The same caveats apply to SeekableSubReadStream as do to SeekableReadStream.
|
* The same caveats apply to SeekableSubReadStream as do to SeekableReadStream.
|
||||||
|
*
|
||||||
|
* Manipulating the parent stream directly /will/ mess up a substream.
|
||||||
|
* @see SubReadStream
|
||||||
*/
|
*/
|
||||||
class SeekableSubReadStream : public SubReadStream, public SeekableReadStream {
|
class SeekableSubReadStream : public SubReadStream, public SeekableReadStream {
|
||||||
protected:
|
protected:
|
||||||
|
@ -451,28 +454,36 @@ public:
|
||||||
/**
|
/**
|
||||||
* This is a wrapper around SeekableSubReadStream, but it adds non-endian
|
* This is a wrapper around SeekableSubReadStream, but it adds non-endian
|
||||||
* read methods whose endianness is set on the stream creation.
|
* read methods whose endianness is set on the stream creation.
|
||||||
|
*
|
||||||
|
* Manipulating the parent stream directly /will/ mess up a substream.
|
||||||
|
* @see SubReadStream
|
||||||
*/
|
*/
|
||||||
class SeekableSubReadStreamEndian : public SeekableSubReadStream {
|
class SeekableSubReadStreamEndian : public SeekableSubReadStream {
|
||||||
public:
|
private:
|
||||||
bool _bigEndian;
|
const bool _bigEndian;
|
||||||
|
|
||||||
|
public:
|
||||||
SeekableSubReadStreamEndian(SeekableReadStream *parentStream, uint32 begin, uint32 end, bool bigEndian = false, bool disposeParentStream = false)
|
SeekableSubReadStreamEndian(SeekableReadStream *parentStream, uint32 begin, uint32 end, bool bigEndian = false, bool disposeParentStream = false)
|
||||||
: SeekableSubReadStream(parentStream, begin, end, disposeParentStream), _bigEndian(bigEndian) {
|
: SeekableSubReadStream(parentStream, begin, end, disposeParentStream), _bigEndian(bigEndian) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint16 readUint16() {
|
uint16 readUint16() {
|
||||||
return (_bigEndian) ? readUint16BE() : readUint16LE();
|
uint16 val;
|
||||||
|
read(&val, 2);
|
||||||
|
return (_bigEndian) ? TO_BE_16(val) : TO_LE_16(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32 readUint32() {
|
uint32 readUint32() {
|
||||||
return (_bigEndian) ? readUint32BE() : readUint32LE();
|
uint32 val;
|
||||||
|
read(&val, 4);
|
||||||
|
return (_bigEndian) ? TO_BE_32(val) : TO_LE_32(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int16 readSint16() {
|
FORCEINLINE int16 readSint16() {
|
||||||
return (int16)readUint16();
|
return (int16)readUint16();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int32 readSint32() {
|
FORCEINLINE int32 readSint32() {
|
||||||
return (int32)readUint32();
|
return (int32)readUint32();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -575,23 +586,28 @@ public:
|
||||||
*/
|
*/
|
||||||
class MemoryReadStreamEndian : public Common::MemoryReadStream {
|
class MemoryReadStreamEndian : public Common::MemoryReadStream {
|
||||||
private:
|
private:
|
||||||
|
const bool _bigEndian;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool _bigEndian;
|
|
||||||
MemoryReadStreamEndian(const byte *buf, uint32 len, bool bigEndian = false) : MemoryReadStream(buf, len), _bigEndian(bigEndian) {}
|
MemoryReadStreamEndian(const byte *buf, uint32 len, bool bigEndian = false) : MemoryReadStream(buf, len), _bigEndian(bigEndian) {}
|
||||||
|
|
||||||
inline uint16 readUint16() {
|
uint16 readUint16() {
|
||||||
return (_bigEndian) ? readUint16BE() : readUint16LE();
|
uint16 val;
|
||||||
|
read(&val, 2);
|
||||||
|
return (_bigEndian) ? TO_BE_16(val) : TO_LE_16(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32 readUint32() {
|
uint32 readUint32() {
|
||||||
return (_bigEndian) ? readUint32BE() : readUint32LE();
|
uint32 val;
|
||||||
|
read(&val, 4);
|
||||||
|
return (_bigEndian) ? TO_BE_32(val) : TO_LE_32(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int16 readSint16() {
|
FORCEINLINE int16 readSint16() {
|
||||||
return (int16)readUint16();
|
return (int16)readUint16();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int32 readSint32() {
|
FORCEINLINE int32 readSint32() {
|
||||||
return (int32)readUint32();
|
return (int32)readUint32();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -642,13 +658,13 @@ private:
|
||||||
byte *old_data = _data;
|
byte *old_data = _data;
|
||||||
|
|
||||||
_capacity = new_len + 32;
|
_capacity = new_len + 32;
|
||||||
_data = new byte[_capacity];
|
_data = (byte *)malloc(_capacity);
|
||||||
_ptr = _data + _pos;
|
_ptr = _data + _pos;
|
||||||
|
|
||||||
if (old_data) {
|
if (old_data) {
|
||||||
// Copy old data
|
// Copy old data
|
||||||
memcpy(_data, old_data, _size);
|
memcpy(_data, old_data, _size);
|
||||||
delete[] old_data;
|
free(old_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
_size = new_len;
|
_size = new_len;
|
||||||
|
@ -658,7 +674,7 @@ public:
|
||||||
|
|
||||||
~MemoryWriteStreamDynamic() {
|
~MemoryWriteStreamDynamic() {
|
||||||
if (_disposeMemory)
|
if (_disposeMemory)
|
||||||
delete[] _data;
|
free(_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 write(const void *dataPtr, uint32 dataSize) {
|
uint32 write(const void *dataPtr, uint32 dataSize) {
|
||||||
|
|
|
@ -125,7 +125,6 @@ public:
|
||||||
* like PocketPC, Palms, Symbian phones like the P800, Zaurus, etc.
|
* like PocketPC, Palms, Symbian phones like the P800, Zaurus, etc.
|
||||||
*/
|
*/
|
||||||
kFeatureVirtualKeyboard,
|
kFeatureVirtualKeyboard,
|
||||||
kFeatureIconifyWindow,
|
|
||||||
kFeatureOpenGL,
|
kFeatureOpenGL,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -174,7 +173,6 @@ public:
|
||||||
* rather complicated for backend authors to fully understand and
|
* rather complicated for backend authors to fully understand and
|
||||||
* implement the semantics of the OSystem interface.
|
* implement the semantics of the OSystem interface.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -323,8 +321,10 @@ public:
|
||||||
* @param hotspotY vertical offset from the top side to the hotspot
|
* @param hotspotY vertical offset from the top side to the hotspot
|
||||||
* @param keycolor transparency color index
|
* @param keycolor transparency color index
|
||||||
* @param cursorTargetScale scale factor which cursor is designed for
|
* @param cursorTargetScale scale factor which cursor is designed for
|
||||||
|
* @param format pointer to the pixel format which cursor graphic uses
|
||||||
*/
|
*/
|
||||||
virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int cursorTargetScale = 1) = 0;
|
virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 0xFFFFFFFF, int cursorTargetScale = 1, const Graphics::PixelFormat *format = NULL) = 0;
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
|
||||||
|
@ -490,13 +490,11 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a window caption or any other comparable status display to the
|
* Set a window caption or any other comparable status display to the
|
||||||
* given value. The caption must be a pure ASCII string. Passing a
|
* given value. The caption must be a pure ISO LATIN 1 string. Passing a
|
||||||
* non-ASCII string may lead to unexpected behavior, even crashes.
|
* string with a different encoding may lead to unexpected behavior,
|
||||||
|
* even crashes.
|
||||||
*
|
*
|
||||||
* In a future revision of this API, this may be changed to allowing
|
* @param caption the window caption to use, as an ISO LATIN 1 string
|
||||||
* UTF-8 or UTF-16 encoded data, or maybe ISO LATIN 1.
|
|
||||||
*
|
|
||||||
* @param caption the window caption to use, as an ASCII string
|
|
||||||
*/
|
*/
|
||||||
virtual void setWindowCaption(const char *caption) {}
|
virtual void setWindowCaption(const char *caption) {}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
#include "common/system.h"
|
#include "common/system.h"
|
||||||
|
#include "common/config-manager.h"
|
||||||
#include "gui/debugger.h"
|
#include "gui/debugger.h"
|
||||||
#include "engines/engine.h"
|
#include "engines/engine.h"
|
||||||
|
|
||||||
|
@ -211,6 +212,7 @@ const LanguageDescription g_languages[] = {
|
||||||
{"ru", "Russian", RU_RUS},
|
{"ru", "Russian", RU_RUS},
|
||||||
{"es", "Spanish", ES_ESP},
|
{"es", "Spanish", ES_ESP},
|
||||||
{"se", "Swedish", SE_SWE},
|
{"se", "Swedish", SE_SWE},
|
||||||
|
{"hu", "Hungarian", HU_HUN},
|
||||||
{0, 0, UNK_LANG}
|
{0, 0, UNK_LANG}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -419,6 +421,14 @@ String getGameGUIOptionsDescription(uint32 options) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateGameGUIOptions(const uint32 options) {
|
||||||
|
if ((options && !ConfMan.hasKey("guioptions")) ||
|
||||||
|
(ConfMan.hasKey("guioptions") && options != parseGameGUIOptions(ConfMan.get("guioptions")))) {
|
||||||
|
ConfMan.set("guioptions", getGameGUIOptionsDescription(options));
|
||||||
|
ConfMan.flushToDisk();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace Common
|
} // End of namespace Common
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#define COMMON_UTIL_H
|
#define COMMON_UTIL_H
|
||||||
|
|
||||||
#include "common/sys.h"
|
#include "common/sys.h"
|
||||||
#include "common/debug.h"
|
|
||||||
#include "common/str.h"
|
#include "common/str.h"
|
||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
|
@ -183,6 +182,7 @@ enum Language {
|
||||||
RU_RUS,
|
RU_RUS,
|
||||||
ES_ESP,
|
ES_ESP,
|
||||||
SE_SWE,
|
SE_SWE,
|
||||||
|
HU_HUN,
|
||||||
|
|
||||||
UNK_LANG = -1 // Use default language (i.e. none specified)
|
UNK_LANG = -1 // Use default language (i.e. none specified)
|
||||||
};
|
};
|
||||||
|
@ -294,6 +294,13 @@ bool checkGameGUIOption(GameGUIOption option, const String &str);
|
||||||
uint32 parseGameGUIOptions(const String &str);
|
uint32 parseGameGUIOptions(const String &str);
|
||||||
String getGameGUIOptionsDescription(uint32 options);
|
String getGameGUIOptionsDescription(uint32 options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the GUI options of the current config manager
|
||||||
|
* domain, when they differ to the ones passed as
|
||||||
|
* parameter.
|
||||||
|
*/
|
||||||
|
void updateGameGUIOptions(const uint32 options);
|
||||||
|
|
||||||
} // End of namespace Common
|
} // End of namespace Common
|
||||||
|
|
||||||
|
|
||||||
|
|
175
config.guess
vendored
175
config.guess
vendored
|
@ -1,10 +1,10 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Attempt to guess a canonical system name.
|
# Attempt to guess a canonical system name.
|
||||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||||
# Free Software Foundation, Inc.
|
# Free Software Foundation, Inc.
|
||||||
|
|
||||||
timestamp='2009-04-27'
|
timestamp='2009-09-18'
|
||||||
|
|
||||||
# This file is free software; you can redistribute it and/or modify it
|
# This file is free software; you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU General Public License as published by
|
# under the terms of the GNU General Public License as published by
|
||||||
|
@ -27,16 +27,16 @@ timestamp='2009-04-27'
|
||||||
# the same distribution terms that you use for the rest of that program.
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
|
||||||
# Originally written by Per Bothner <per@bothner.com>.
|
# Originally written by Per Bothner. Please send patches (context
|
||||||
# Please send patches to <config-patches@gnu.org>. Submit a context
|
# diff format) to <config-patches@gnu.org> and include a ChangeLog
|
||||||
# diff and a properly formatted ChangeLog entry.
|
# entry.
|
||||||
#
|
#
|
||||||
# This script attempts to guess a canonical system name similar to
|
# This script attempts to guess a canonical system name similar to
|
||||||
# config.sub. If it succeeds, it prints the system name on stdout, and
|
# config.sub. If it succeeds, it prints the system name on stdout, and
|
||||||
# exits with 0. Otherwise, it exits with 1.
|
# exits with 0. Otherwise, it exits with 1.
|
||||||
#
|
#
|
||||||
# The plan is that this can be called by configure scripts if you
|
# You can get the latest version of this script from:
|
||||||
# don't specify an explicit build system type.
|
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
|
||||||
|
|
||||||
me=`echo "$0" | sed -e 's,.*/,,'`
|
me=`echo "$0" | sed -e 's,.*/,,'`
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||||
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
|
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
|
||||||
eval $set_cc_for_build
|
eval $set_cc_for_build
|
||||||
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||||
| grep __ELF__ >/dev/null
|
| grep -q __ELF__
|
||||||
then
|
then
|
||||||
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
|
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
|
||||||
# Return netbsd for either. FIX?
|
# Return netbsd for either. FIX?
|
||||||
|
@ -656,7 +656,7 @@ EOF
|
||||||
# => hppa64-hp-hpux11.23
|
# => hppa64-hp-hpux11.23
|
||||||
|
|
||||||
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
|
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
|
||||||
grep __LP64__ >/dev/null
|
grep -q __LP64__
|
||||||
then
|
then
|
||||||
HP_ARCH="hppa2.0w"
|
HP_ARCH="hppa2.0w"
|
||||||
else
|
else
|
||||||
|
@ -822,6 +822,9 @@ EOF
|
||||||
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
|
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
|
||||||
echo i${UNAME_MACHINE}-pc-mks
|
echo i${UNAME_MACHINE}-pc-mks
|
||||||
exit ;;
|
exit ;;
|
||||||
|
8664:Windows_NT:*)
|
||||||
|
echo x86_64-pc-mks
|
||||||
|
exit ;;
|
||||||
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
|
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
|
||||||
# How do we know it's Interix rather than the generic POSIX subsystem?
|
# How do we know it's Interix rather than the generic POSIX subsystem?
|
||||||
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
|
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
|
||||||
|
@ -851,6 +854,20 @@ EOF
|
||||||
i*86:Minix:*:*)
|
i*86:Minix:*:*)
|
||||||
echo ${UNAME_MACHINE}-pc-minix
|
echo ${UNAME_MACHINE}-pc-minix
|
||||||
exit ;;
|
exit ;;
|
||||||
|
alpha:Linux:*:*)
|
||||||
|
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
|
||||||
|
EV5) UNAME_MACHINE=alphaev5 ;;
|
||||||
|
EV56) UNAME_MACHINE=alphaev56 ;;
|
||||||
|
PCA56) UNAME_MACHINE=alphapca56 ;;
|
||||||
|
PCA57) UNAME_MACHINE=alphapca56 ;;
|
||||||
|
EV6) UNAME_MACHINE=alphaev6 ;;
|
||||||
|
EV67) UNAME_MACHINE=alphaev67 ;;
|
||||||
|
EV68*) UNAME_MACHINE=alphaev68 ;;
|
||||||
|
esac
|
||||||
|
objdump --private-headers /bin/sh | grep -q ld.so.1
|
||||||
|
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
|
||||||
|
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
|
||||||
|
exit ;;
|
||||||
arm*:Linux:*:*)
|
arm*:Linux:*:*)
|
||||||
eval $set_cc_for_build
|
eval $set_cc_for_build
|
||||||
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||||
|
@ -873,6 +890,9 @@ EOF
|
||||||
frv:Linux:*:*)
|
frv:Linux:*:*)
|
||||||
echo frv-unknown-linux-gnu
|
echo frv-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
|
i*86:Linux:*:*)
|
||||||
|
echo ${UNAME_MACHINE}-pc-linux-gnu
|
||||||
|
exit ;;
|
||||||
ia64:Linux:*:*)
|
ia64:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
|
@ -882,40 +902,17 @@ EOF
|
||||||
m68*:Linux:*:*)
|
m68*:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
mips:Linux:*:*)
|
mips:Linux:*:* | mips64:Linux:*:*)
|
||||||
eval $set_cc_for_build
|
eval $set_cc_for_build
|
||||||
sed 's/^ //' << EOF >$dummy.c
|
sed 's/^ //' << EOF >$dummy.c
|
||||||
#undef CPU
|
#undef CPU
|
||||||
#undef mips
|
#undef ${UNAME_MACHINE}
|
||||||
#undef mipsel
|
#undef ${UNAME_MACHINE}el
|
||||||
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
|
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
|
||||||
CPU=mipsel
|
CPU=${UNAME_MACHINE}el
|
||||||
#else
|
#else
|
||||||
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
|
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
|
||||||
CPU=mips
|
CPU=${UNAME_MACHINE}
|
||||||
#else
|
|
||||||
CPU=
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
EOF
|
|
||||||
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
|
|
||||||
/^CPU/{
|
|
||||||
s: ::g
|
|
||||||
p
|
|
||||||
}'`"
|
|
||||||
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
|
|
||||||
;;
|
|
||||||
mips64:Linux:*:*)
|
|
||||||
eval $set_cc_for_build
|
|
||||||
sed 's/^ //' << EOF >$dummy.c
|
|
||||||
#undef CPU
|
|
||||||
#undef mips64
|
|
||||||
#undef mips64el
|
|
||||||
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
|
|
||||||
CPU=mips64el
|
|
||||||
#else
|
|
||||||
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
|
|
||||||
CPU=mips64
|
|
||||||
#else
|
#else
|
||||||
CPU=
|
CPU=
|
||||||
#endif
|
#endif
|
||||||
|
@ -931,29 +928,12 @@ EOF
|
||||||
or32:Linux:*:*)
|
or32:Linux:*:*)
|
||||||
echo or32-unknown-linux-gnu
|
echo or32-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
ppc:Linux:*:*)
|
|
||||||
echo powerpc-unknown-linux-gnu
|
|
||||||
exit ;;
|
|
||||||
ppc64:Linux:*:*)
|
|
||||||
echo powerpc64-unknown-linux-gnu
|
|
||||||
exit ;;
|
|
||||||
alpha:Linux:*:*)
|
|
||||||
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
|
|
||||||
EV5) UNAME_MACHINE=alphaev5 ;;
|
|
||||||
EV56) UNAME_MACHINE=alphaev56 ;;
|
|
||||||
PCA56) UNAME_MACHINE=alphapca56 ;;
|
|
||||||
PCA57) UNAME_MACHINE=alphapca56 ;;
|
|
||||||
EV6) UNAME_MACHINE=alphaev6 ;;
|
|
||||||
EV67) UNAME_MACHINE=alphaev67 ;;
|
|
||||||
EV68*) UNAME_MACHINE=alphaev68 ;;
|
|
||||||
esac
|
|
||||||
objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
|
|
||||||
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
|
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
|
|
||||||
exit ;;
|
|
||||||
padre:Linux:*:*)
|
padre:Linux:*:*)
|
||||||
echo sparc-unknown-linux-gnu
|
echo sparc-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
|
parisc64:Linux:*:* | hppa64:Linux:*:*)
|
||||||
|
echo hppa64-unknown-linux-gnu
|
||||||
|
exit ;;
|
||||||
parisc:Linux:*:* | hppa:Linux:*:*)
|
parisc:Linux:*:* | hppa:Linux:*:*)
|
||||||
# Look for CPU level
|
# Look for CPU level
|
||||||
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
|
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
|
||||||
|
@ -962,8 +942,11 @@ EOF
|
||||||
*) echo hppa-unknown-linux-gnu ;;
|
*) echo hppa-unknown-linux-gnu ;;
|
||||||
esac
|
esac
|
||||||
exit ;;
|
exit ;;
|
||||||
parisc64:Linux:*:* | hppa64:Linux:*:*)
|
ppc64:Linux:*:*)
|
||||||
echo hppa64-unknown-linux-gnu
|
echo powerpc64-unknown-linux-gnu
|
||||||
|
exit ;;
|
||||||
|
ppc:Linux:*:*)
|
||||||
|
echo powerpc-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
s390:Linux:*:* | s390x:Linux:*:*)
|
s390:Linux:*:* | s390x:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-ibm-linux
|
echo ${UNAME_MACHINE}-ibm-linux
|
||||||
|
@ -986,66 +969,6 @@ EOF
|
||||||
xtensa*:Linux:*:*)
|
xtensa*:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||||
exit ;;
|
exit ;;
|
||||||
i*86:Linux:*:*)
|
|
||||||
# The BFD linker knows what the default object file format is, so
|
|
||||||
# first see if it will tell us. cd to the root directory to prevent
|
|
||||||
# problems with other programs or directories called `ld' in the path.
|
|
||||||
# Set LC_ALL=C to ensure ld outputs messages in English.
|
|
||||||
ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
|
|
||||||
| sed -ne '/supported targets:/!d
|
|
||||||
s/[ ][ ]*/ /g
|
|
||||||
s/.*supported targets: *//
|
|
||||||
s/ .*//
|
|
||||||
p'`
|
|
||||||
case "$ld_supported_targets" in
|
|
||||||
elf32-i386)
|
|
||||||
TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
|
|
||||||
;;
|
|
||||||
a.out-i386-linux)
|
|
||||||
echo "${UNAME_MACHINE}-pc-linux-gnuaout"
|
|
||||||
exit ;;
|
|
||||||
"")
|
|
||||||
# Either a pre-BFD a.out linker (linux-gnuoldld) or
|
|
||||||
# one that does not give us useful --help.
|
|
||||||
echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
|
|
||||||
exit ;;
|
|
||||||
esac
|
|
||||||
# Determine whether the default compiler is a.out or elf
|
|
||||||
eval $set_cc_for_build
|
|
||||||
sed 's/^ //' << EOF >$dummy.c
|
|
||||||
#include <features.h>
|
|
||||||
#ifdef __ELF__
|
|
||||||
# ifdef __GLIBC__
|
|
||||||
# if __GLIBC__ >= 2
|
|
||||||
LIBC=gnu
|
|
||||||
# else
|
|
||||||
LIBC=gnulibc1
|
|
||||||
# endif
|
|
||||||
# else
|
|
||||||
LIBC=gnulibc1
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
|
||||||
LIBC=gnu
|
|
||||||
#else
|
|
||||||
LIBC=gnuaout
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifdef __dietlibc__
|
|
||||||
LIBC=dietlibc
|
|
||||||
#endif
|
|
||||||
EOF
|
|
||||||
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
|
|
||||||
/^LIBC/{
|
|
||||||
s: ::g
|
|
||||||
p
|
|
||||||
}'`"
|
|
||||||
test x"${LIBC}" != x && {
|
|
||||||
echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
|
|
||||||
;;
|
|
||||||
i*86:DYNIX/ptx:4*:*)
|
i*86:DYNIX/ptx:4*:*)
|
||||||
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
|
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
|
||||||
# earlier versions are messed up and put the nodename in both
|
# earlier versions are messed up and put the nodename in both
|
||||||
|
@ -1074,7 +997,7 @@ EOF
|
||||||
i*86:syllable:*:*)
|
i*86:syllable:*:*)
|
||||||
echo ${UNAME_MACHINE}-pc-syllable
|
echo ${UNAME_MACHINE}-pc-syllable
|
||||||
exit ;;
|
exit ;;
|
||||||
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
|
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
|
||||||
echo i386-unknown-lynxos${UNAME_RELEASE}
|
echo i386-unknown-lynxos${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
i*86:*DOS:*:*)
|
i*86:*DOS:*:*)
|
||||||
|
@ -1182,7 +1105,7 @@ EOF
|
||||||
rs6000:LynxOS:2.*:*)
|
rs6000:LynxOS:2.*:*)
|
||||||
echo rs6000-unknown-lynxos${UNAME_RELEASE}
|
echo rs6000-unknown-lynxos${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
|
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
|
||||||
echo powerpc-unknown-lynxos${UNAME_RELEASE}
|
echo powerpc-unknown-lynxos${UNAME_RELEASE}
|
||||||
exit ;;
|
exit ;;
|
||||||
SM[BE]S:UNIX_SV:*:*)
|
SM[BE]S:UNIX_SV:*:*)
|
||||||
|
@ -1275,6 +1198,16 @@ EOF
|
||||||
*:Darwin:*:*)
|
*:Darwin:*:*)
|
||||||
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
|
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
|
||||||
case $UNAME_PROCESSOR in
|
case $UNAME_PROCESSOR in
|
||||||
|
i386)
|
||||||
|
eval $set_cc_for_build
|
||||||
|
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
||||||
|
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||||
|
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||||
|
grep IS_64BIT_ARCH >/dev/null
|
||||||
|
then
|
||||||
|
UNAME_PROCESSOR="x86_64"
|
||||||
|
fi
|
||||||
|
fi ;;
|
||||||
unknown) UNAME_PROCESSOR=powerpc ;;
|
unknown) UNAME_PROCESSOR=powerpc ;;
|
||||||
esac
|
esac
|
||||||
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
|
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
|
||||||
|
|
27
config.sub
vendored
27
config.sub
vendored
|
@ -1,10 +1,10 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Configuration validation subroutine script.
|
# Configuration validation subroutine script.
|
||||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||||
# Free Software Foundation, Inc.
|
# Free Software Foundation, Inc.
|
||||||
|
|
||||||
timestamp='2009-04-17'
|
timestamp='2009-08-19'
|
||||||
|
|
||||||
# This file is (in principle) common to ALL GNU software.
|
# This file is (in principle) common to ALL GNU software.
|
||||||
# The presence of a machine in this file suggests that SOME GNU software
|
# The presence of a machine in this file suggests that SOME GNU software
|
||||||
|
@ -32,13 +32,16 @@ timestamp='2009-04-17'
|
||||||
|
|
||||||
|
|
||||||
# Please send patches to <config-patches@gnu.org>. Submit a context
|
# Please send patches to <config-patches@gnu.org>. Submit a context
|
||||||
# diff and a properly formatted ChangeLog entry.
|
# diff and a properly formatted GNU ChangeLog entry.
|
||||||
#
|
#
|
||||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||||
# Supply the specified configuration type as an argument.
|
# Supply the specified configuration type as an argument.
|
||||||
# If it is invalid, we print an error message on stderr and exit with code 1.
|
# If it is invalid, we print an error message on stderr and exit with code 1.
|
||||||
# Otherwise, we print the canonical config type on stdout and succeed.
|
# Otherwise, we print the canonical config type on stdout and succeed.
|
||||||
|
|
||||||
|
# You can get the latest version of this script from:
|
||||||
|
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
|
||||||
|
|
||||||
# This file is supposed to be the same for all GNU packages
|
# This file is supposed to be the same for all GNU packages
|
||||||
# and recognize all the CPU types, system types and aliases
|
# and recognize all the CPU types, system types and aliases
|
||||||
# that are meaningful with *any* GNU software.
|
# that are meaningful with *any* GNU software.
|
||||||
|
@ -149,10 +152,13 @@ case $os in
|
||||||
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
||||||
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
||||||
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
||||||
-apple | -axis | -knuth | -cray)
|
-apple | -axis | -knuth | -cray | -microblaze)
|
||||||
os=
|
os=
|
||||||
basic_machine=$1
|
basic_machine=$1
|
||||||
;;
|
;;
|
||||||
|
-bluegene*)
|
||||||
|
os=-cnk
|
||||||
|
;;
|
||||||
-sim | -cisco | -oki | -wec | -winbond)
|
-sim | -cisco | -oki | -wec | -winbond)
|
||||||
os=
|
os=
|
||||||
basic_machine=$1
|
basic_machine=$1
|
||||||
|
@ -337,7 +343,7 @@ case $basic_machine in
|
||||||
| lm32-* \
|
| lm32-* \
|
||||||
| m32c-* | m32r-* | m32rle-* \
|
| m32c-* | m32r-* | m32rle-* \
|
||||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||||
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
|
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
|
||||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||||
| mips16-* \
|
| mips16-* \
|
||||||
| mips64-* | mips64el-* \
|
| mips64-* | mips64el-* \
|
||||||
|
@ -467,6 +473,10 @@ case $basic_machine in
|
||||||
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
|
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
os=-linux
|
os=-linux
|
||||||
;;
|
;;
|
||||||
|
bluegene*)
|
||||||
|
basic_machine=powerpc-ibm
|
||||||
|
os=-cnk
|
||||||
|
;;
|
||||||
c90)
|
c90)
|
||||||
basic_machine=c90-cray
|
basic_machine=c90-cray
|
||||||
os=-unicos
|
os=-unicos
|
||||||
|
@ -719,6 +729,9 @@ case $basic_machine in
|
||||||
basic_machine=ns32k-utek
|
basic_machine=ns32k-utek
|
||||||
os=-sysv
|
os=-sysv
|
||||||
;;
|
;;
|
||||||
|
microblaze)
|
||||||
|
basic_machine=microblaze-xilinx
|
||||||
|
;;
|
||||||
mingw32)
|
mingw32)
|
||||||
basic_machine=i386-pc
|
basic_machine=i386-pc
|
||||||
os=-mingw32
|
os=-mingw32
|
||||||
|
@ -1260,7 +1273,7 @@ case $os in
|
||||||
# Each alternative MUST END IN A *, to match a version number.
|
# Each alternative MUST END IN A *, to match a version number.
|
||||||
# -sysv* is not here because it comes later, after sysvr4.
|
# -sysv* is not here because it comes later, after sysvr4.
|
||||||
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
||||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
|
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
|
||||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
|
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
|
||||||
| -kopensolaris* \
|
| -kopensolaris* \
|
||||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||||
|
@ -1613,7 +1626,7 @@ case $basic_machine in
|
||||||
-sunos*)
|
-sunos*)
|
||||||
vendor=sun
|
vendor=sun
|
||||||
;;
|
;;
|
||||||
-aix*)
|
-cnk*|-aix*)
|
||||||
vendor=ibm
|
vendor=ibm
|
||||||
;;
|
;;
|
||||||
-beos*)
|
-beos*)
|
||||||
|
|
324
configure
vendored
324
configure
vendored
|
@ -29,6 +29,8 @@ SAVED_LDFLAGS=$LDFLAGS
|
||||||
SAVED_CXX=$CXX
|
SAVED_CXX=$CXX
|
||||||
SAVED_CXXFLAGS=$CXXFLAGS
|
SAVED_CXXFLAGS=$CXXFLAGS
|
||||||
SAVED_CPPFLAGS=$CPPFLAGS
|
SAVED_CPPFLAGS=$CPPFLAGS
|
||||||
|
SAVED_ASFLAGS=$ASFLAGS
|
||||||
|
SAVED_WINDRESFLAGS=$WINDRESFLAGS
|
||||||
|
|
||||||
# Use environment vars if set
|
# Use environment vars if set
|
||||||
CXXFLAGS="$CXXFLAGS $CPPFLAGS"
|
CXXFLAGS="$CXXFLAGS $CPPFLAGS"
|
||||||
|
@ -54,15 +56,22 @@ if test "$ac_emxsupport" != "no" -a "$ac_emxsupport" != "NO"; then
|
||||||
unset ac_TEMP_PATH
|
unset ac_TEMP_PATH
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
set_var() {
|
||||||
|
eval ${1}='${2}'
|
||||||
|
}
|
||||||
|
|
||||||
|
get_var() {
|
||||||
|
eval echo \$${1}
|
||||||
|
}
|
||||||
|
|
||||||
# Add an engine: id name build subengines
|
# Add an engine: id name build subengines
|
||||||
add_engine() {
|
add_engine() {
|
||||||
_engines="${_engines} ${1}"
|
_engines="${_engines} ${1}"
|
||||||
eval _engine_${1}_name='${2}'
|
set_var _engine_${1}_name "${2}"
|
||||||
eval _engine_${1}_build='${3}'
|
set_var _engine_${1}_build "${3}"
|
||||||
eval _engine_${1}_subengines='${4}'
|
set_var _engine_${1}_subengines "${4}"
|
||||||
for sub in ${4}; do
|
for sub in ${4}; do
|
||||||
eval _engine_${sub}_sub=yes
|
set_var _engine_${sub}_sub "yes"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +101,7 @@ _plugins_default=static
|
||||||
_ranlib=ranlib
|
_ranlib=ranlib
|
||||||
_strip=strip
|
_strip=strip
|
||||||
_ar="ar cru"
|
_ar="ar cru"
|
||||||
|
_as="as"
|
||||||
_windres=windres
|
_windres=windres
|
||||||
_win32path="C:/residual"
|
_win32path="C:/residual"
|
||||||
_aos4path="Games:Residual"
|
_aos4path="Games:Residual"
|
||||||
|
@ -107,6 +117,7 @@ _host_os=""
|
||||||
_host_alias=""
|
_host_alias=""
|
||||||
|
|
||||||
_srcdir=`dirname $0`
|
_srcdir=`dirname $0`
|
||||||
|
_port_mk="ports.mk"
|
||||||
|
|
||||||
# Determine a tmp file name, using mktemp(1) when available.
|
# Determine a tmp file name, using mktemp(1) when available.
|
||||||
if type mktemp > /dev/null 2>&1 ; then
|
if type mktemp > /dev/null 2>&1 ; then
|
||||||
|
@ -225,7 +236,7 @@ find_sdlconfig() {
|
||||||
#
|
#
|
||||||
get_system_exe_extension() {
|
get_system_exe_extension() {
|
||||||
case $1 in
|
case $1 in
|
||||||
mingw* | *os2-emx)
|
mingw* | *os2-emx | wince)
|
||||||
_exeext=".exe"
|
_exeext=".exe"
|
||||||
;;
|
;;
|
||||||
arm-riscos)
|
arm-riscos)
|
||||||
|
@ -237,7 +248,7 @@ get_system_exe_extension() {
|
||||||
gp2x-linux)
|
gp2x-linux)
|
||||||
_exeext=".gp2x"
|
_exeext=".gp2x"
|
||||||
;;
|
;;
|
||||||
dreamcast | wii | gamecube | psp)
|
dreamcast | wii | gamecube | nds | psp)
|
||||||
_exeext=".elf"
|
_exeext=".elf"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
@ -271,22 +282,22 @@ Try \`$0 --help' for more information." >&2
|
||||||
|
|
||||||
# Get the name of the engine
|
# Get the name of the engine
|
||||||
get_engine_name() {
|
get_engine_name() {
|
||||||
eval echo \$_engine_$1_name
|
get_var _engine_$1_name
|
||||||
}
|
}
|
||||||
|
|
||||||
# Will this engine be built?
|
# Will this engine be built?
|
||||||
get_engine_build() {
|
get_engine_build() {
|
||||||
eval echo \$_engine_$1_build
|
get_var _engine_$1_build
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get the subengines
|
# Get the subengines
|
||||||
get_engine_subengines() {
|
get_engine_subengines() {
|
||||||
eval echo \$_engine_$1_subengines
|
get_var _engine_$1_subengines
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ask if this is a subengine
|
# Ask if this is a subengine
|
||||||
get_engine_sub() {
|
get_engine_sub() {
|
||||||
sub=`eval echo \\$_engine_$1_sub`
|
sub=`get_var _engine_$1_sub`
|
||||||
if test -z "$sub" ; then
|
if test -z "$sub" ; then
|
||||||
sub=no
|
sub=no
|
||||||
fi
|
fi
|
||||||
|
@ -296,14 +307,14 @@ get_engine_sub() {
|
||||||
# Enable *all* engines
|
# Enable *all* engines
|
||||||
engine_enable_all() {
|
engine_enable_all() {
|
||||||
for engine in $_engines; do
|
for engine in $_engines; do
|
||||||
eval _engine_${engine}_build=yes
|
set_var _engine_${engine}_build "yes"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
# Disable *all* engines
|
# Disable *all* engines
|
||||||
engine_disable_all() {
|
engine_disable_all() {
|
||||||
for engine in $_engines; do
|
for engine in $_engines; do
|
||||||
eval _engine_${engine}_build=no
|
set_var _engine_${engine}_build "no"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +338,7 @@ engine_enable() {
|
||||||
|
|
||||||
if test "$opt" = "static" -o "$opt" = "dynamic" -o "$opt" = "yes" ; then
|
if test "$opt" = "static" -o "$opt" = "dynamic" -o "$opt" = "yes" ; then
|
||||||
if test "`get_engine_name ${engine}`" != "" ; then
|
if test "`get_engine_name ${engine}`" != "" ; then
|
||||||
eval _engine_${engine}_build=$opt
|
set_var _engine_${engine}_build "$opt"
|
||||||
else
|
else
|
||||||
option_error
|
option_error
|
||||||
fi
|
fi
|
||||||
|
@ -346,7 +357,7 @@ engine_disable() {
|
||||||
|
|
||||||
engine=`echo $1 | sed 's/-/_/g'`
|
engine=`echo $1 | sed 's/-/_/g'`
|
||||||
if test "`get_engine_name ${engine}`" != "" ; then
|
if test "`get_engine_name ${engine}`" != "" ; then
|
||||||
eval _engine_${engine}_build=no
|
set_var _engine_${engine}_build "no"
|
||||||
else
|
else
|
||||||
option_error
|
option_error
|
||||||
fi
|
fi
|
||||||
|
@ -493,7 +504,7 @@ Usage: $0 [OPTIONS]...
|
||||||
|
|
||||||
Configuration:
|
Configuration:
|
||||||
-h, --help display this help and exit
|
-h, --help display this help and exit
|
||||||
--backend=BACKEND backend to build (sdl, morphos, dc, gp2x, gp2xwiz, iphone, wii, psp, null) [sdl]
|
--backend=BACKEND backend to build (sdl, dc, gp2x, gp2xwiz, iphone, morphos, nds, psp, wii, wince, linuxmoto, null) [sdl]
|
||||||
|
|
||||||
Installation directories:
|
Installation directories:
|
||||||
--prefix=DIR use this prefix for installing Residual [/usr/local]
|
--prefix=DIR use this prefix for installing Residual [/usr/local]
|
||||||
|
@ -508,20 +519,23 @@ Special configuration feature:
|
||||||
dreamcast for Sega Dreamcast
|
dreamcast for Sega Dreamcast
|
||||||
wii for Nintendo Wii
|
wii for Nintendo Wii
|
||||||
gamecube for Nintendo Gamecube
|
gamecube for Nintendo Gamecube
|
||||||
|
nds for Nintendo DS
|
||||||
iphone for Apple iPhone
|
iphone for Apple iPhone
|
||||||
|
wince for Windows CE
|
||||||
psp for PlayStation Portable
|
psp for PlayStation Portable
|
||||||
|
|
||||||
Optional Features:
|
Game engines:
|
||||||
--disable-debug disable building with debugging symbols
|
|
||||||
--enable-Werror treat warnings as errors
|
|
||||||
--enable-profiling enable building with gprof profile information
|
|
||||||
--enable-release set flags to build release binary
|
|
||||||
--enable-verbose-build enable regular echoing of commands during build process
|
|
||||||
--enable-all-engines enable all engines
|
--enable-all-engines enable all engines
|
||||||
--disable-all-engines disable all engines
|
--disable-all-engines disable all engines
|
||||||
$engines_help
|
$engines_help
|
||||||
|
Optional Features:
|
||||||
|
--disable-debug disable building with debugging symbols
|
||||||
|
--enable-Werror treat warnings as errors
|
||||||
--enable-plugins enable the support for dynamic plugins
|
--enable-plugins enable the support for dynamic plugins
|
||||||
--default-dynamic make plugins dynamic by default
|
--default-dynamic make plugins dynamic by default
|
||||||
|
--enable-profiling enable building with gprof profile information
|
||||||
|
--enable-release set flags to build release binary
|
||||||
|
--enable-verbose-build enable regular echoing of commands during build process
|
||||||
|
|
||||||
Optional Libraries:
|
Optional Libraries:
|
||||||
--with-ogg-prefix=DIR Prefix where libogg is installed (optional)
|
--with-ogg-prefix=DIR Prefix where libogg is installed (optional)
|
||||||
|
@ -548,6 +562,8 @@ Some influential environment variables:
|
||||||
CXXFLAGS C++ compiler flags
|
CXXFLAGS C++ compiler flags
|
||||||
CPPFLAGS C++ preprocessor flags, e.g. -I<include dir> if you have
|
CPPFLAGS C++ preprocessor flags, e.g. -I<include dir> if you have
|
||||||
headers in a nonstandard directory <include dir>
|
headers in a nonstandard directory <include dir>
|
||||||
|
ASFLAGS assembler flags
|
||||||
|
WINDRESFLAGS Windows resource compiler flags
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
exit 0
|
exit 0
|
||||||
|
@ -566,8 +582,9 @@ for ac_option in $@; do
|
||||||
--disable-flac) _flac=no ;;
|
--disable-flac) _flac=no ;;
|
||||||
--enable-mad) _mad=yes ;;
|
--enable-mad) _mad=yes ;;
|
||||||
--disable-mad) _mad=no ;;
|
--disable-mad) _mad=no ;;
|
||||||
--enable-plugins) _dynamic_modules=yes ;;
|
|
||||||
--enable-verbose-build) _verbose_build=yes ;;
|
--enable-verbose-build) _verbose_build=yes ;;
|
||||||
|
--enable-plugins) _dynamic_modules=yes ;;
|
||||||
--default-dynamic) _plugins_default=dynamic ;;
|
--default-dynamic) _plugins_default=dynamic ;;
|
||||||
--enable-vkeybd) _vkeybd=yes ;;
|
--enable-vkeybd) _vkeybd=yes ;;
|
||||||
--disable-vkeybd) _vkeybd=no ;;
|
--disable-vkeybd) _vkeybd=no ;;
|
||||||
|
@ -676,6 +693,16 @@ linupy)
|
||||||
_host_os=linux
|
_host_os=linux
|
||||||
_host_cpu=arm
|
_host_cpu=arm
|
||||||
;;
|
;;
|
||||||
|
motoezx)
|
||||||
|
_host_os=linux
|
||||||
|
_host_cpu=arm
|
||||||
|
_host_alias=arm-linux-gnu
|
||||||
|
;;
|
||||||
|
motomagx)
|
||||||
|
_host_os=linux
|
||||||
|
_host_cpu=arm
|
||||||
|
_host_alias=arm-linux-gnueabi
|
||||||
|
;;
|
||||||
arm-riscos)
|
arm-riscos)
|
||||||
_host_os=riscos
|
_host_os=riscos
|
||||||
_host_cpu=arm
|
_host_cpu=arm
|
||||||
|
@ -703,6 +730,11 @@ iphone)
|
||||||
_host_cpu=arm
|
_host_cpu=arm
|
||||||
_host_alias=arm-apple-darwin9
|
_host_alias=arm-apple-darwin9
|
||||||
;;
|
;;
|
||||||
|
wince)
|
||||||
|
_host_os=wince
|
||||||
|
_host_cpu=arm
|
||||||
|
_host_alias=arm-wince-mingw32ce
|
||||||
|
;;
|
||||||
neuros)
|
neuros)
|
||||||
_host_os=linux
|
_host_os=linux
|
||||||
_host_cpu=arm
|
_host_cpu=arm
|
||||||
|
@ -719,17 +751,22 @@ wii)
|
||||||
_host_cpu=ppc
|
_host_cpu=ppc
|
||||||
_host_alias=powerpc-gekko
|
_host_alias=powerpc-gekko
|
||||||
;;
|
;;
|
||||||
|
gamecube)
|
||||||
|
_host_os=gamecube
|
||||||
|
_host_cpu=ppc
|
||||||
|
_host_alias=powerpc-gekko
|
||||||
|
;;
|
||||||
|
nds)
|
||||||
|
_host_os=nds
|
||||||
|
_host_cpu=arm
|
||||||
|
_host_alias=arm-eabi
|
||||||
|
;;
|
||||||
psp)
|
psp)
|
||||||
_host_os=psp
|
_host_os=psp
|
||||||
_host_cpu=mipsallegrexel
|
_host_cpu=mipsallegrexel
|
||||||
_host_alias=psp
|
_host_alias=psp
|
||||||
LDFLAGS="$LDFLAGS -L$PSPDEV/psp/sdk/lib -specs=$_srcdir/backends/platform/psp/psp.spec"
|
LDFLAGS="$LDFLAGS -L$PSPDEV/psp/sdk/lib -specs=$_srcdir/backends/platform/psp/psp.spec"
|
||||||
;;
|
;;
|
||||||
gamecube)
|
|
||||||
_host_os=gamecube
|
|
||||||
_host_cpu=ppc
|
|
||||||
_host_alias=powerpc-gekko
|
|
||||||
;;
|
|
||||||
*)
|
*)
|
||||||
if test -n "$_host"; then
|
if test -n "$_host"; then
|
||||||
guessed_host=`$_srcdir/config.sub $_host`
|
guessed_host=`$_srcdir/config.sub $_host`
|
||||||
|
@ -742,6 +779,13 @@ esac
|
||||||
|
|
||||||
if test -z "$_host_alias"; then
|
if test -z "$_host_alias"; then
|
||||||
_host_alias="$_host_cpu-$_host_os"
|
_host_alias="$_host_cpu-$_host_os"
|
||||||
|
else
|
||||||
|
# if _host_alias was set, default to the standard GNU tools
|
||||||
|
_ranlib=$_host_alias-ranlib
|
||||||
|
_strip=$_host_alias-strip
|
||||||
|
_ar="$_host_alias-ar cru"
|
||||||
|
_as="$_host_alias-as"
|
||||||
|
_windres=$_host_alias-windres
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -766,7 +810,7 @@ esac
|
||||||
# Platform specific sanity checks
|
# Platform specific sanity checks
|
||||||
#
|
#
|
||||||
case $_host_os in
|
case $_host_os in
|
||||||
wii | gamecube)
|
wii | gamecube | nds)
|
||||||
if test -z "$DEVKITPRO"; then
|
if test -z "$DEVKITPRO"; then
|
||||||
echo "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to devkitPRO>"
|
echo "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to devkitPRO>"
|
||||||
exit 1
|
exit 1
|
||||||
|
@ -836,11 +880,29 @@ fi
|
||||||
#
|
#
|
||||||
echocheck "compiler version"
|
echocheck "compiler version"
|
||||||
|
|
||||||
|
have_gcc=no
|
||||||
cxx_version=`( $CXX -dumpversion ) 2>&1`
|
cxx_version=`( $CXX -dumpversion ) 2>&1`
|
||||||
if test "$?" -gt 0; then
|
if test "$?" -gt 0; then
|
||||||
|
# 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'`"
|
||||||
|
if test -z "${cxx_version}"; then
|
||||||
cxx_version="not found"
|
cxx_version="not found"
|
||||||
|
cxx_verc_fail=yes
|
||||||
|
fi
|
||||||
|
echo non-gcc compiler version ${cxx_version}
|
||||||
|
else
|
||||||
|
cxx_version="not found"
|
||||||
|
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
|
fi
|
||||||
|
|
||||||
|
if test "$have_gcc" = yes; then
|
||||||
case $cxx_version in
|
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][-.]*)
|
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_major=`echo $cxx_version | cut -d '.' -f 1`
|
||||||
|
@ -867,6 +929,30 @@ case $cxx_version in
|
||||||
cxx_verc_fail=yes
|
cxx_verc_fail=yes
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
else
|
||||||
|
case $_host_os in
|
||||||
|
irix*)
|
||||||
|
case $cxx_version in
|
||||||
|
7.4.4*)
|
||||||
|
# We just assume this is SGI MipsPRO
|
||||||
|
_cxx_major=7
|
||||||
|
_cxx_minor=4
|
||||||
|
add_line_to_config_mk 'CXX_UPDATE_DEP_FLAG = -MDupdate "$(*D)/$(DEPDIR)/$(*F).d"'
|
||||||
|
add_line_to_config_mk '-include Makedepend'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
cxx_version="$cxx_version, bad"
|
||||||
|
cxx_verc_fail=yes
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
cxx_version="$cxx_version, bad"
|
||||||
|
cxx_verc_fail=yes
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
echo "$cxx_version"
|
echo "$cxx_version"
|
||||||
|
|
||||||
|
@ -1040,7 +1126,7 @@ case $_host_os in
|
||||||
;;
|
;;
|
||||||
darwin*)
|
darwin*)
|
||||||
DEFINES="$DEFINES -DUNIX -DMACOSX -DUSE_OPENGL"
|
DEFINES="$DEFINES -DUNIX -DMACOSX -DUSE_OPENGL"
|
||||||
LIBS="$LIBS -framework QuickTime -framework AudioUnit -framework AudioToolbox -framework Carbon -Wl,-framework,OpenGL \
|
LIBS="$LIBS -framework QuickTime -framework AudioUnit -framework AudioToolbox -framework Carbon -framework OpenGL \
|
||||||
-dylib_file /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib"
|
-dylib_file /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib"
|
||||||
;;
|
;;
|
||||||
mingw*)
|
mingw*)
|
||||||
|
@ -1073,17 +1159,24 @@ case $_host_os in
|
||||||
wii)
|
wii)
|
||||||
CXXFLAGS="$CXXFLAGS -Os -mrvl -mcpu=750 -meabi -mhard-float"
|
CXXFLAGS="$CXXFLAGS -Os -mrvl -mcpu=750 -meabi -mhard-float"
|
||||||
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections -fmodulo-sched"
|
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections -fmodulo-sched"
|
||||||
CXXFLAGS="$CXXFLAGS -I$DEVKITPRO/libogc/include"
|
CXXFLAGS="$CXXFLAGS -I$DEVKITPRO/libogc/include -I$DEVKITPRO/wii/include"
|
||||||
LDFLAGS="$LDFLAGS -mrvl -mcpu=750 -L$DEVKITPRO/libogc/lib/wii"
|
LDFLAGS="$LDFLAGS -mrvl -mcpu=750 -L$DEVKITPRO/libogc/lib/wii -L$DEVKITPRO/wii/lib"
|
||||||
;;
|
;;
|
||||||
gamecube)
|
gamecube)
|
||||||
CXXFLAGS="$CXXFLAGS -Os -mogc -mcpu=750 -meabi -mhard-float"
|
CXXFLAGS="$CXXFLAGS -Os -mogc -mcpu=750 -meabi -mhard-float"
|
||||||
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections -fmodulo-sched"
|
CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections -fmodulo-sched"
|
||||||
CXXFLAGS="$CXXFLAGS -I$DEVKITPRO/libogc/include"
|
CXXFLAGS="$CXXFLAGS -I$DEVKITPRO/libogc/include -I$DEVKITPRO/cube/include"
|
||||||
LDFLAGS="$LDFLAGS -mogc -mcpu=750 -L$DEVKITPRO/libogc/lib/cube"
|
LDFLAGS="$LDFLAGS -mogc -mcpu=750 -L$DEVKITPRO/libogc/lib/cube -L$DEVKITPRO/cube/lib"
|
||||||
|
;;
|
||||||
|
nds)
|
||||||
|
# TODO nds
|
||||||
;;
|
;;
|
||||||
psp)
|
psp)
|
||||||
CXXFLAGS="$CXXFLAGS -O2 -G0 -I$PSPDEV/psp/sdk/include -D_PSP_FW_VERSION=150"
|
CXXFLAGS="$CXXFLAGS -O3 -G0 -I$PSPDEV/psp/sdk/include -D_PSP_FW_VERSION=150"
|
||||||
|
;;
|
||||||
|
wince)
|
||||||
|
CXXFLAGS="$CXXFLAGS -O3 -march=armv4 -mtune=xscale -D_WIN32_WCE=300 -D__ARM__ -D_ARM_ -DUNICODE -DFPM_DEFAULT -DNONSTANDARD_PORT"
|
||||||
|
CXXFLAGS="$CXXFLAGS -DWIN32 -Dcdecl= -D__cdecl__="
|
||||||
;;
|
;;
|
||||||
# given this is a shell script assume some type of unix
|
# given this is a shell script assume some type of unix
|
||||||
*)
|
*)
|
||||||
|
@ -1098,16 +1191,6 @@ if test -n "$_host"; then
|
||||||
linupy|arm-riscos)
|
linupy|arm-riscos)
|
||||||
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
||||||
DEFINES="$DEFINES -DUNIX"
|
DEFINES="$DEFINES -DUNIX"
|
||||||
_endian=little
|
|
||||||
_need_memalign=yes
|
|
||||||
add_line_to_config_h "#define LINUPY"
|
|
||||||
type_1_byte='char'
|
|
||||||
type_2_byte='short'
|
|
||||||
type_4_byte='int'
|
|
||||||
;;
|
|
||||||
arm-linux|arm*-linux-gnueabi|arm-*-linux|*-angstrom-linux)
|
|
||||||
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
|
||||||
DEFINES="$DEFINES -DUNIX -DUSE_ARM_SOUND_ASM"
|
|
||||||
#not true for all ARM systems, but the interesting ones are all LE. Most (if not all) BE arm devices don't have a screen
|
#not true for all ARM systems, but the interesting ones are all LE. Most (if not all) BE arm devices don't have a screen
|
||||||
_endian=little
|
_endian=little
|
||||||
_need_memalign=yes
|
_need_memalign=yes
|
||||||
|
@ -1115,6 +1198,44 @@ if test -n "$_host"; then
|
||||||
type_2_byte='short'
|
type_2_byte='short'
|
||||||
type_4_byte='int'
|
type_4_byte='int'
|
||||||
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
|
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
|
||||||
|
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
|
||||||
|
;;
|
||||||
|
motoezx)
|
||||||
|
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
||||||
|
DEFINES="$DEFINES -DUNIX -DMOTOEZX"
|
||||||
|
#not true for all ARM systems, but the interesting ones are all LE. Most (if not all) BE arm devices don't have a screen
|
||||||
|
ASFLAGS="$ASFLAGS -mfpu=vfp"
|
||||||
|
_endian=little
|
||||||
|
_need_memalign=yes
|
||||||
|
type_1_byte='char'
|
||||||
|
type_2_byte='short'
|
||||||
|
type_4_byte='int'
|
||||||
|
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
|
||||||
|
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
|
||||||
|
add_line_to_config_mk 'USE_ARM_GFX_ASM = 1'
|
||||||
|
add_line_to_config_mk 'USE_ARM_COSTUME_ASM = 1'
|
||||||
|
add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
|
||||||
|
_backend="linuxmoto"
|
||||||
|
_build_hq_scalers="no"
|
||||||
|
_mt32emu="no"
|
||||||
|
_port_mk="backends/platform/linuxmoto/linuxmoto.mk"
|
||||||
|
;;
|
||||||
|
motomagx)
|
||||||
|
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
||||||
|
DEFINES="$DEFINES -DUNIX -DMOTOMAGX"
|
||||||
|
#not true for all ARM systems, but the interesting ones are all LE. Most (if not all) BE arm devices don't have a screen
|
||||||
|
ASFLAGS="$ASFLAGS -mfpu=vfp"
|
||||||
|
_endian=little
|
||||||
|
_need_memalign=yes
|
||||||
|
type_1_byte='char'
|
||||||
|
type_2_byte='short'
|
||||||
|
type_4_byte='int'
|
||||||
|
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
|
||||||
|
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
|
||||||
|
_backend="linuxmoto"
|
||||||
|
_build_hq_scalers="no"
|
||||||
|
_mt32emu="no"
|
||||||
|
_port_mk="backends/platform/linuxmoto/linuxmoto.mk"
|
||||||
;;
|
;;
|
||||||
bfin*)
|
bfin*)
|
||||||
_need_memalign=yes
|
_need_memalign=yes
|
||||||
|
@ -1125,7 +1246,7 @@ if test -n "$_host"; then
|
||||||
;;
|
;;
|
||||||
gp2xwiz)
|
gp2xwiz)
|
||||||
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
||||||
DEFINES="$DEFINES -DUNIX -DGP2XWIZ -DNDEBUG -DUSE_ARM_SMUSH_ASM"
|
DEFINES="$DEFINES -DUNIX -DGP2XWIZ -DNDEBUG"
|
||||||
CXXFLAGS="$CXXFLAGS -mcpu=arm926ej-s -mtune=arm926ej-s"
|
CXXFLAGS="$CXXFLAGS -mcpu=arm926ej-s -mtune=arm926ej-s"
|
||||||
LDFLAGS="$LDFLAGS"
|
LDFLAGS="$LDFLAGS"
|
||||||
_endian=little
|
_endian=little
|
||||||
|
@ -1133,8 +1254,6 @@ if test -n "$_host"; then
|
||||||
type_1_byte='char'
|
type_1_byte='char'
|
||||||
type_2_byte='short'
|
type_2_byte='short'
|
||||||
type_4_byte='int'
|
type_4_byte='int'
|
||||||
_ar="$_host_alias-ar cru"
|
|
||||||
_ranlib=$_host_alias-ranlib
|
|
||||||
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
|
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
|
||||||
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
|
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
|
||||||
_backend="gp2xwiz"
|
_backend="gp2xwiz"
|
||||||
|
@ -1143,27 +1262,26 @@ if test -n "$_host"; then
|
||||||
;;
|
;;
|
||||||
gp2x)
|
gp2x)
|
||||||
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
||||||
DEFINES="$DEFINES -DUNIX -DGP2X -DNDEBUG -DUSE_ARM_SMUSH_ASM"
|
DEFINES="$DEFINES -DUNIX -DGP2X -DNDEBUG"
|
||||||
CXXFLAGS="$CXXFLAGS -march=armv4t"
|
CXXFLAGS="$CXXFLAGS -march=armv4t"
|
||||||
|
ASFLAGS="$ASFLAGS -mfloat-abi=soft"
|
||||||
LDFLAGS="$LDFLAGS -static"
|
LDFLAGS="$LDFLAGS -static"
|
||||||
_endian=little
|
_endian=little
|
||||||
_need_memalign=yes
|
_need_memalign=yes
|
||||||
type_1_byte='char'
|
type_1_byte='char'
|
||||||
type_2_byte='short'
|
type_2_byte='short'
|
||||||
type_4_byte='int'
|
type_4_byte='int'
|
||||||
_ar="$_host_alias-ar cru"
|
|
||||||
_ranlib=$_host_alias-ranlib
|
|
||||||
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
|
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
|
||||||
|
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
|
||||||
_backend="gp2x"
|
_backend="gp2x"
|
||||||
_build_hq_scalers="no"
|
_build_hq_scalers="no"
|
||||||
_mt32emu="no"
|
_mt32emu="no"
|
||||||
;;
|
;;
|
||||||
neuros)
|
neuros)
|
||||||
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
||||||
DEFINES="$DEFINES -DUNIX"
|
DEFINES="$DEFINES -DUNIX -DNEUROS"
|
||||||
_endian=little
|
_endian=little
|
||||||
_need_memalign=yes
|
_need_memalign=yes
|
||||||
add_line_to_config_h "#define NEUROS"
|
|
||||||
type_1_byte='char'
|
type_1_byte='char'
|
||||||
type_2_byte='short'
|
type_2_byte='short'
|
||||||
type_4_byte='int'
|
type_4_byte='int'
|
||||||
|
@ -1198,34 +1316,46 @@ if test -n "$_host"; then
|
||||||
_windres=$_host-windres
|
_windres=$_host-windres
|
||||||
_ar="$_host-ar cru"
|
_ar="$_host-ar cru"
|
||||||
_ranlib=$_host-ranlib
|
_ranlib=$_host-ranlib
|
||||||
_strip=$_host-strip
|
|
||||||
;;
|
;;
|
||||||
iphone)
|
iphone)
|
||||||
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
||||||
DEFINES="$DEFINES -DIPHONE -DUNIX -DUSE_ARM_SOUND_ASM"
|
DEFINES="$DEFINES -DIPHONE -DUNIX"
|
||||||
_endian=little
|
_endian=little
|
||||||
_need_memalign=yes
|
_need_memalign=yes
|
||||||
type_1_byte='char'
|
type_1_byte='char'
|
||||||
type_2_byte='short'
|
type_2_byte='short'
|
||||||
type_4_byte='int'
|
type_4_byte='int'
|
||||||
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
|
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
|
||||||
|
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
|
||||||
_backend="iphone"
|
_backend="iphone"
|
||||||
_ar="$_host_alias-ar cru"
|
;;
|
||||||
_ranlib=$_host_alias-ranlib
|
wince)
|
||||||
_strip=$_host_alias-strip
|
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
||||||
|
LDFLAGS="$LDFLAGS -Wl,-Map,scummvm.exe.map -Wl,--stack,65536"
|
||||||
|
_endian=little
|
||||||
|
_need_memalign=yes
|
||||||
|
type_1_byte='char'
|
||||||
|
type_2_byte='short'
|
||||||
|
type_4_byte='int'
|
||||||
|
add_line_to_config_mk 'USE_TREMOLO = 1'
|
||||||
|
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
|
||||||
|
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
|
||||||
|
_backend="wince"
|
||||||
|
_mt32emu="no"
|
||||||
|
_port_mk="backends/platform/wince/wince.mk"
|
||||||
;;
|
;;
|
||||||
dreamcast)
|
dreamcast)
|
||||||
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
||||||
DEFINES="$DEFINES -DDISABLE_DEFAULT_SAVEFILEMANAGER -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE"
|
DEFINES="$DEFINES -DDISABLE_DEFAULT_SAVEFILEMANAGER -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE"
|
||||||
CXXFLAGS="$CXXFLAGS -O3 -Wno-multichar -funroll-loops -fschedule-insns2 -fomit-frame-pointer -fdelete-null-pointer-checks -fno-exceptions"
|
CXXFLAGS="$CXXFLAGS -O3 -funroll-loops -fschedule-insns2 -fomit-frame-pointer -fdelete-null-pointer-checks"
|
||||||
_endian=little
|
_endian=little
|
||||||
_need_memalign=yes
|
_need_memalign=yes
|
||||||
type_1_byte='char'
|
type_1_byte='char'
|
||||||
type_2_byte='short'
|
type_2_byte='short'
|
||||||
type_4_byte='int'
|
type_4_byte='int'
|
||||||
_backend="dc"
|
_backend="dc"
|
||||||
_ar="$_host_alias-ar cru"
|
_mad="yes"
|
||||||
_ranlib=$_host_alias-ranlib
|
_zlib="yes"
|
||||||
add_line_to_config_mk 'include $(srcdir)/backends/platform/dc/dreamcast.mk'
|
add_line_to_config_mk 'include $(srcdir)/backends/platform/dc/dreamcast.mk'
|
||||||
;;
|
;;
|
||||||
wii)
|
wii)
|
||||||
|
@ -1235,16 +1365,14 @@ if test -n "$_host"; then
|
||||||
type_1_byte='char'
|
type_1_byte='char'
|
||||||
type_2_byte='short'
|
type_2_byte='short'
|
||||||
type_4_byte='int'
|
type_4_byte='int'
|
||||||
_ar="$_host_alias-ar cru"
|
|
||||||
_ranlib=$_host_alias-ranlib
|
|
||||||
_strip=$_host_alias-strip
|
|
||||||
_backend="wii"
|
_backend="wii"
|
||||||
|
_port_mk="backends/platform/wii/wii.mk"
|
||||||
add_line_to_config_mk 'GAMECUBE = 0'
|
add_line_to_config_mk 'GAMECUBE = 0'
|
||||||
add_line_to_config_mk 'include $(srcdir)/backends/platform/wii/wii.mk'
|
|
||||||
add_line_to_config_h "#define DEBUG_WII_USBGECKO"
|
add_line_to_config_h "#define DEBUG_WII_USBGECKO"
|
||||||
add_line_to_config_h "/* #define DEBUG_WII_MEMSTATS */"
|
add_line_to_config_h "/* #define DEBUG_WII_MEMSTATS */"
|
||||||
add_line_to_config_h "/* #define DEBUG_WII_GDB */"
|
add_line_to_config_h "/* #define DEBUG_WII_GDB */"
|
||||||
add_line_to_config_h "#define USE_WII_DI"
|
add_line_to_config_h "#define USE_WII_DI"
|
||||||
|
add_line_to_config_h "#define USE_WII_SMB"
|
||||||
add_line_to_config_h "#define USE_WII_KBD"
|
add_line_to_config_h "#define USE_WII_KBD"
|
||||||
;;
|
;;
|
||||||
gamecube)
|
gamecube)
|
||||||
|
@ -1254,17 +1382,36 @@ if test -n "$_host"; then
|
||||||
type_1_byte='char'
|
type_1_byte='char'
|
||||||
type_2_byte='short'
|
type_2_byte='short'
|
||||||
type_4_byte='int'
|
type_4_byte='int'
|
||||||
_ar="$_host_alias-ar cru"
|
|
||||||
_ranlib=$_host_alias-ranlib
|
|
||||||
_strip=$_host_alias-strip
|
|
||||||
_backend="wii"
|
_backend="wii"
|
||||||
|
_port_mk="backends/platform/wii/wii.mk"
|
||||||
add_line_to_config_mk 'GAMECUBE = 1'
|
add_line_to_config_mk 'GAMECUBE = 1'
|
||||||
add_line_to_config_mk 'include $(srcdir)/backends/platform/wii/wii.mk'
|
|
||||||
add_line_to_config_h '#define GAMECUBE'
|
add_line_to_config_h '#define GAMECUBE'
|
||||||
add_line_to_config_h "/* #define DEBUG_WII_USBGECKO */"
|
add_line_to_config_h "/* #define DEBUG_WII_USBGECKO */"
|
||||||
add_line_to_config_h "/* #define DEBUG_WII_MEMSTATS */"
|
add_line_to_config_h "/* #define DEBUG_WII_MEMSTATS */"
|
||||||
add_line_to_config_h "/* #define DEBUG_WII_GDB */"
|
add_line_to_config_h "/* #define DEBUG_WII_GDB */"
|
||||||
;;
|
;;
|
||||||
|
nds)
|
||||||
|
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
||||||
|
# TODO: complete this
|
||||||
|
# TODO: Maybe rename nds -> ds (would be more consistent with other backends)
|
||||||
|
DEFINES="$DEFINES -D__DS__ -DNDS -DARM9 -DARM -DNONSTANDARD_PORT"
|
||||||
|
DEFINES="$DEFINES -DDISABLE_FANCY_THEMES -DVECTOR_RENDERER_FORMAT=1555"
|
||||||
|
DEFINES="$DEFINES -DDISABLE_DEFAULT_SAVEFILEMANAGER"
|
||||||
|
DEFINES="$DEFINES -DREDUCE_MEMORY_USAGE"
|
||||||
|
DEFINES="$DEFINES -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE"
|
||||||
|
_endian=little
|
||||||
|
_need_memalign=yes
|
||||||
|
type_1_byte='char'
|
||||||
|
type_2_byte='short'
|
||||||
|
type_4_byte='int'
|
||||||
|
_backend="nds"
|
||||||
|
_build_hq_scalers="no"
|
||||||
|
_mt32emu="no"
|
||||||
|
add_line_to_config_mk 'include $(srcdir)/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'
|
||||||
|
;;
|
||||||
psp)
|
psp)
|
||||||
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"
|
||||||
_endian=little
|
_endian=little
|
||||||
|
@ -1272,10 +1419,8 @@ if test -n "$_host"; then
|
||||||
type_1_byte='char'
|
type_1_byte='char'
|
||||||
type_2_byte='short'
|
type_2_byte='short'
|
||||||
type_4_byte='int'
|
type_4_byte='int'
|
||||||
_ar="$_host_alias-ar cru"
|
|
||||||
_ranlib=$_host_alias-ranlib
|
|
||||||
_backend="psp"
|
_backend="psp"
|
||||||
add_line_to_config_mk 'include $(srcdir)/backends/platform/psp/psp.mk'
|
_port_mk="backends/platform/psp/psp.mk"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Continuing with auto-detected values ... if you have problems, please add your target to configure."
|
echo "Continuing with auto-detected values ... if you have problems, please add your target to configure."
|
||||||
|
@ -1667,6 +1812,12 @@ case $_backend in
|
||||||
LIBS="$LIBS `$_sdlconfig --prefix="$_sdlpath" --libs`"
|
LIBS="$LIBS `$_sdlconfig --prefix="$_sdlpath" --libs`"
|
||||||
DEFINES="$DEFINES -DSDL_BACKEND"
|
DEFINES="$DEFINES -DSDL_BACKEND"
|
||||||
;;
|
;;
|
||||||
|
linuxmoto)
|
||||||
|
find_sdlconfig
|
||||||
|
INCLUDES="$INCLUDES `$_sdlconfig --prefix="$_sdlpath" --cflags`"
|
||||||
|
LIBS="$LIBS `$_sdlconfig --prefix="$_sdlpath" --libs`"
|
||||||
|
DEFINES="$DEFINES -DSDL_BACKEND -DLINUXMOTO"
|
||||||
|
;;
|
||||||
gp2x)
|
gp2x)
|
||||||
find_sdlconfig
|
find_sdlconfig
|
||||||
INCLUDES="$INCLUDES `$_sdlconfig --prefix="$_sdlpath" --cflags`"
|
INCLUDES="$INCLUDES `$_sdlconfig --prefix="$_sdlpath" --cflags`"
|
||||||
|
@ -1685,6 +1836,10 @@ case $_backend in
|
||||||
OBJCFLAGS="$OBJCFLAGS --std=c99"
|
OBJCFLAGS="$OBJCFLAGS --std=c99"
|
||||||
LIBS="$LIBS -lobjc -framework UIKit -framework CoreGraphics -framework OpenGLES -framework QuartzCore -framework GraphicsServices -framework CoreFoundation -framework Foundation -framework AudioToolbox -framework CoreAudio"
|
LIBS="$LIBS -lobjc -framework UIKit -framework CoreGraphics -framework OpenGLES -framework QuartzCore -framework GraphicsServices -framework CoreFoundation -framework Foundation -framework AudioToolbox -framework CoreAudio"
|
||||||
;;
|
;;
|
||||||
|
wince)
|
||||||
|
INCLUDES="$INCLUDES "'-I$(srcdir) -I$(srcdir)/backends/platform/wince -I$(srcdir)/engines -I$(srcdir)/backends/platform/wince/missing/gcc -I$(srcdir)/backends/platform/wince/CEgui -I$(srcdir)/backends/platform/wince/CEkeys'
|
||||||
|
LIBS="$LIBS -static -lSDL"
|
||||||
|
;;
|
||||||
dc)
|
dc)
|
||||||
INCLUDES="$INCLUDES "'-I$(srcdir)/backends/platform/dc -isystem $(ronindir)/include'
|
INCLUDES="$INCLUDES "'-I$(srcdir)/backends/platform/dc -isystem $(ronindir)/include'
|
||||||
LDFLAGS="$LDFLAGS -Wl,-Ttext,0x8c010000 -nostartfiles "'$(ronindir)/lib/crt0.o -L$(ronindir)/lib'
|
LDFLAGS="$LDFLAGS -Wl,-Ttext,0x8c010000 -nostartfiles "'$(ronindir)/lib/crt0.o -L$(ronindir)/lib'
|
||||||
|
@ -1694,15 +1849,18 @@ case $_backend in
|
||||||
DEFINES="$DEFINES -D__WII__ -DGEKKO"
|
DEFINES="$DEFINES -D__WII__ -DGEKKO"
|
||||||
case $_host_os in
|
case $_host_os in
|
||||||
gamecube)
|
gamecube)
|
||||||
LIBS="$LIBS -lfat -logc -ldb"
|
LIBS="$LIBS -lgxflux -lfat -logc -ldb"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
LIBS="$LIBS -ldi -lfat -lwiiuse -lbte -logc -lwiikeyboard -ldb"
|
LIBS="$LIBS -lgxflux -ldi -ltinysmb -lfat -lwiiuse -lbte -logc -lwiikeyboard -ldb"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
|
nds)
|
||||||
|
# TODO nds
|
||||||
|
;;
|
||||||
psp)
|
psp)
|
||||||
DEFINES="$DEFINES -D__PSP__ -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE"
|
DEFINES="$DEFINES -D__PSP__ -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE -DDISABLE_DOSBOX_OPL"
|
||||||
INCLUDES="$INCLUDES -I$PSPDEV/psp/include/SDL"
|
INCLUDES="$INCLUDES -I$PSPDEV/psp/include/SDL"
|
||||||
LIBS="$LIBS -lSDL"
|
LIBS="$LIBS -lSDL"
|
||||||
;;
|
;;
|
||||||
|
@ -1716,11 +1874,12 @@ MODULES="$MODULES backends/platform/$_backend"
|
||||||
#
|
#
|
||||||
# Do CXXFLAGS now we know the compiler version
|
# Do CXXFLAGS now we know the compiler version
|
||||||
#
|
#
|
||||||
|
if test "$have_gcc" = yes ; then
|
||||||
if test "$_cxx_major" -ge "3" ; then
|
if test "$_cxx_major" -ge "3" ; then
|
||||||
case $_host_os in
|
case $_host_os in
|
||||||
# newlib-based system include files suppress non-C89 function
|
# newlib-based system include files suppress non-C89 function
|
||||||
# declarations under __STRICT_ANSI__
|
# declarations under __STRICT_ANSI__
|
||||||
mingw* | dreamcast | wii | gamecube | psp | amigaos*)
|
mingw* | dreamcast | wii | gamecube | psp | wince | amigaos*)
|
||||||
CXXFLAGS="$CXXFLAGS -W -Wno-unused-parameter"
|
CXXFLAGS="$CXXFLAGS -W -Wno-unused-parameter"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
@ -1728,6 +1887,7 @@ if test "$_cxx_major" -ge "3" ; then
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
add_line_to_config_mk 'HAVE_GCC3 = 1'
|
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'
|
||||||
fi;
|
fi;
|
||||||
|
|
||||||
if test "$_cxx_major" -ge "4" && test "$_cxx_minor" -ge "3" ; then
|
if test "$_cxx_major" -ge "4" && test "$_cxx_minor" -ge "3" ; then
|
||||||
|
@ -1735,6 +1895,7 @@ if test "$_cxx_major" -ge "4" && test "$_cxx_minor" -ge "3" ; then
|
||||||
else
|
else
|
||||||
CXXFLAGS="$CXXFLAGS -Wconversion"
|
CXXFLAGS="$CXXFLAGS -Wconversion"
|
||||||
fi;
|
fi;
|
||||||
|
fi;
|
||||||
|
|
||||||
# Some platforms use certain GNU extensions in header files
|
# Some platforms use certain GNU extensions in header files
|
||||||
case $_host_os in
|
case $_host_os in
|
||||||
|
@ -1761,12 +1922,12 @@ for engine in $_engines; do
|
||||||
# If dynamic plugins aren't supported, mark
|
# If dynamic plugins aren't supported, mark
|
||||||
# all the engines as static
|
# all the engines as static
|
||||||
if test $_dynamic_modules = no ; then
|
if test $_dynamic_modules = no ; then
|
||||||
eval _engine_${engine}_build=static
|
set_var _engine_${engine}_build "static"
|
||||||
else
|
else
|
||||||
# If it wasn't explicitly marked as static or
|
# If it wasn't explicitly marked as static or
|
||||||
# dynamic, use the configured default
|
# dynamic, use the configured default
|
||||||
if test `get_engine_build $engine` = yes ; then
|
if test `get_engine_build $engine` = yes ; then
|
||||||
eval _engine_${engine}_build=${_plugins_default}
|
set_var _engine_${engine}_build "${_plugins_default}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -1774,7 +1935,7 @@ for engine in $_engines; do
|
||||||
if test `get_engine_build $engine` = dynamic ; then
|
if test `get_engine_build $engine` = dynamic ; then
|
||||||
isbuilt=DYNAMIC_PLUGIN
|
isbuilt=DYNAMIC_PLUGIN
|
||||||
else
|
else
|
||||||
eval _engine_${engine}_build=static
|
set_var _engine_${engine}_build "static"
|
||||||
isbuilt=STATIC_PLUGIN
|
isbuilt=STATIC_PLUGIN
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
@ -1871,7 +2032,10 @@ LIBS += $LIBS
|
||||||
RANLIB := $_ranlib
|
RANLIB := $_ranlib
|
||||||
STRIP := $_strip
|
STRIP := $_strip
|
||||||
AR := $_ar
|
AR := $_ar
|
||||||
|
AS := $_as
|
||||||
|
ASFLAGS := $ASFLAGS
|
||||||
WINDRES := $_windres
|
WINDRES := $_windres
|
||||||
|
WINDRESFLAGS := $WINDRESFLAGS
|
||||||
WIN32PATH=$_win32path
|
WIN32PATH=$_win32path
|
||||||
AOS4PATH=$_aos4path
|
AOS4PATH=$_aos4path
|
||||||
STATICLIBPATH=$_staticlibpath
|
STATICLIBPATH=$_staticlibpath
|
||||||
|
@ -1896,11 +2060,15 @@ LDFLAGS += $LDFLAGS
|
||||||
|
|
||||||
$_mak_plugins
|
$_mak_plugins
|
||||||
|
|
||||||
|
port_mk = $_port_mk
|
||||||
|
|
||||||
SAVED_CONFIGFLAGS := $SAVED_CONFIGFLAGS
|
SAVED_CONFIGFLAGS := $SAVED_CONFIGFLAGS
|
||||||
SAVED_LDFLAGS := $SAVED_LDFLAGS
|
SAVED_LDFLAGS := $SAVED_LDFLAGS
|
||||||
SAVED_CXX := $SAVED_CXX
|
SAVED_CXX := $SAVED_CXX
|
||||||
SAVED_CXXFLAGS := $SAVED_CXXFLAGS
|
SAVED_CXXFLAGS := $SAVED_CXXFLAGS
|
||||||
SAVED_CPPFLAGS := $SAVED_CPPFLAGS
|
SAVED_CPPFLAGS := $SAVED_CPPFLAGS
|
||||||
|
SAVED_ASFLAGS := $SAVED_ASFLAGS
|
||||||
|
SAVED_WINDRESFLAGS := $SAVED_WINDRESFLAGS
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -2,7 +2,7 @@ Source: residual
|
||||||
Section: games
|
Section: games
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Maintainer: Pino Toscano <pino@kde.org>
|
Maintainer: Pino Toscano <pino@kde.org>
|
||||||
Build-Depends: debhelper (>= 5.0.0), libgl1-mesa-dev, libsdl1.2-dev, libz-dev
|
Build-Depends: debhelper (>= 5.0.0), libgl1-mesa-dev, libsdl1.2-dev, libz-dev, libmad0-dev, libvorbis-dev (>= 1.0.0-2), libflac-dev (>= 1.1.1-2), libz-dev, libfluidsynth-dev
|
||||||
Standards-Version: 3.8.0
|
Standards-Version: 3.8.0
|
||||||
|
|
||||||
Package: residual
|
Package: residual
|
||||||
|
|
|
@ -4,7 +4,7 @@ build: residual
|
||||||
|
|
||||||
residual:
|
residual:
|
||||||
dh_testdir
|
dh_testdir
|
||||||
./configure --enable-release --prefix=/usr --bindir=/usr/games --datadir=/usr/share/games --mandir=/usr/share/man --disable-vorbis --disable-mad --disable-tremor --disable-flac
|
./configure --enable-release --prefix=/usr --bindir=/usr/games --datadir=/usr/share/games --mandir=/usr/share/man
|
||||||
$(MAKE)
|
$(MAKE)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
|
@ -11,15 +11,12 @@ if not exist rpl.exe goto no_rpl
|
||||||
echo Creating MSVC9 project files from the MSVC8 ones
|
echo Creating MSVC9 project files from the MSVC8 ones
|
||||||
copy /y msvc8\*.vcproj msvc9\
|
copy /y msvc8\*.vcproj msvc9\
|
||||||
copy /y msvc8\*.sln msvc9\
|
copy /y msvc8\*.sln msvc9\
|
||||||
|
copy /y msvc8\*.vsprops msvc9\
|
||||||
rpl -e -q "Version=\"8.00\"" "Version=\"9.00\"" msvc9\*.vcproj
|
rpl -e -q "Version=\"8.00\"" "Version=\"9.00\"" msvc9\*.vcproj
|
||||||
rpl -e -q "Version=\"8,00\"" "Version=\"9,00\"" msvc9\*.vcproj
|
rpl -e -q "Version=\"8,00\"" "Version=\"9,00\"" msvc9\*.vcproj
|
||||||
rpl -e -q "Keyword=\"Win32Proj\"" "Keyword=\"Win32Proj\"\n\tTargetFrameworkVersion=\"131072\"" msvc9\*.vcproj
|
rpl -e -q "Keyword=\"Win32Proj\"" "Keyword=\"Win32Proj\"\n\tTargetFrameworkVersion=\"131072\"" msvc9\*.vcproj
|
||||||
rpl -e -q "EntryPointSymbol=\"WinMainCRTStartup\"" "EntryPointSymbol=\"WinMainCRTStartup\"\n\t\t\t\tRandomizedBaseAddress=\"1\"\n\t\t\t\tDataExecutionPrevention=\"0\"" msvc9\residual.vcproj
|
rpl -e -q "Format Version 9.00" "Format Version 10.00" msvc9\scummvm.sln
|
||||||
rpl -e -q "Format Version 9.00" "Format Version 10.00" msvc9\residual.sln
|
rpl -e -q "Format Version 9,00" "Format Version 10,00" msvc9\scummvm.sln
|
||||||
rpl -e -q "Format Version 9,00" "Format Version 10,00" msvc9\residual.sln
|
|
||||||
rpl -e -q "# Visual C++ Express 2005" "# Visual C++ Express 2008" msvc9\residual.sln
|
|
||||||
rpl -e -q "# Visual Studio 2005" "# Visual Studio 2008" msvc9\residual
|
|
||||||
.sln
|
|
||||||
goto the_end
|
goto the_end
|
||||||
|
|
||||||
:no_rpl
|
:no_rpl
|
||||||
|
|
|
@ -240,6 +240,18 @@
|
||||||
RelativePath="..\..\common\error.h"
|
RelativePath="..\..\common\error.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\common\EventDispatcher.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\common\EventRecorder.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\common\EventRecorder.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\common\events.h"
|
RelativePath="..\..\common\events.h"
|
||||||
>
|
>
|
||||||
|
@ -460,6 +472,14 @@
|
||||||
<Filter
|
<Filter
|
||||||
Name="sound"
|
Name="sound"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\sound\audiocd.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\sound\audiocd.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\sound\audiostream.cpp"
|
RelativePath="..\..\sound\audiostream.cpp"
|
||||||
>
|
>
|
||||||
|
@ -468,6 +488,14 @@
|
||||||
RelativePath="..\..\sound\audiostream.h"
|
RelativePath="..\..\sound\audiostream.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\sound\flac.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\sound\flac.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\sound\mixer.cpp"
|
RelativePath="..\..\sound\mixer.cpp"
|
||||||
>
|
>
|
||||||
|
@ -480,6 +508,18 @@
|
||||||
RelativePath="..\..\sound\mixer_intern.h"
|
RelativePath="..\..\sound\mixer_intern.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\sound\module.mk"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\sound\mp3.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\sound\mp3.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\sound\rate.cpp"
|
RelativePath="..\..\sound\rate.cpp"
|
||||||
>
|
>
|
||||||
|
@ -488,6 +528,14 @@
|
||||||
RelativePath="..\..\sound\rate.h"
|
RelativePath="..\..\sound\rate.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\sound\vorbis.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\sound\vorbis.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="rsc"
|
Name="rsc"
|
||||||
|
|
|
@ -11,15 +11,12 @@ if not exist rpl.exe goto no_rpl
|
||||||
echo Creating MSVC8 project files from the MSVC9 ones
|
echo Creating MSVC8 project files from the MSVC9 ones
|
||||||
copy /y msvc9\*.vcproj msvc8\
|
copy /y msvc9\*.vcproj msvc8\
|
||||||
copy /y msvc9\*.sln msvc8\
|
copy /y msvc9\*.sln msvc8\
|
||||||
|
copy /y msvc9\*.vsprops msvc8\
|
||||||
rpl -e -q "Version=\"9.00\"" "Version=\"8.00\"" msvc8\*.vcproj
|
rpl -e -q "Version=\"9.00\"" "Version=\"8.00\"" msvc8\*.vcproj
|
||||||
rpl -e -q "Version=\"9,00\"" "Version=\"8,00\"" msvc8\*.vcproj
|
rpl -e -q "Version=\"9,00\"" "Version=\"8,00\"" msvc8\*.vcproj
|
||||||
rpl -e -q "\tTargetFrameworkVersion=\"131072\"\n" "" msvc8\*.vcproj
|
rpl -e -q "\tTargetFrameworkVersion=\"131072\"\n" "" msvc8\*.vcproj
|
||||||
rpl -e -q "\t\t\t\tRandomizedBaseAddress=\"1\"\n" "" msvc8\residual.vcproj
|
rpl -e -q "Format Version 10.00" "Format Version 9.00" msvc8\scummvm.sln
|
||||||
rpl -e -q "\t\t\t\tDataExecutionPrevention=\"0\"\n" "" msvc8\residual.vcproj
|
rpl -e -q "Format Version 10,00" "Format Version 9,00" msvc8\scummvm.sln
|
||||||
rpl -e -q "Format Version 10.00" "Format Version 9.00" msvc8\residual.sln
|
|
||||||
rpl -e -q "Format Version 10,00" "Format Version 9,00" msvc8\residual.sln
|
|
||||||
rpl -e -q "# Visual C++ Express 2008" "# Visual C++ Express 2005" msvc8\residual.sln
|
|
||||||
rpl -e -q "# Visual Studio 2008" "# Visual Studio 2005" msvc8\residual.sln
|
|
||||||
goto the_end
|
goto the_end
|
||||||
|
|
||||||
:no_rpl
|
:no_rpl
|
||||||
|
|
|
@ -291,14 +291,17 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (agdDesc == 0) {
|
if (agdDesc == 0)
|
||||||
return Common::kNoGameDataFoundError;
|
return Common::kNoGameDataFoundError;
|
||||||
}
|
|
||||||
|
// If the GUI options were updated, we catch this here and update them in the users config
|
||||||
|
// file transparently.
|
||||||
|
Common::updateGameGUIOptions(agdDesc->guioptions | params.guioptions);
|
||||||
|
|
||||||
debug(2, "Running %s", toGameDescriptor(*agdDesc, params.list).description().c_str());
|
debug(2, "Running %s", toGameDescriptor(*agdDesc, params.list).description().c_str());
|
||||||
if (!createInstance(syst, engine, agdDesc)) {
|
if (!createInstance(syst, engine, agdDesc))
|
||||||
return Common::kNoGameDataFoundError;
|
return Common::kNoGameDataFoundError;
|
||||||
}
|
else
|
||||||
return Common::kNoError;
|
return Common::kNoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
#include "common/system.h"
|
#include "common/system.h"
|
||||||
#include "common/events.h"
|
#include "common/events.h"
|
||||||
|
|
||||||
|
#include "graphics/scaler.h"
|
||||||
|
|
||||||
#include "gui/about.h"
|
#include "gui/about.h"
|
||||||
#include "gui/GuiManager.h"
|
#include "gui/GuiManager.h"
|
||||||
#include "gui/launcher.h"
|
#include "gui/launcher.h"
|
||||||
|
|
|
@ -221,7 +221,10 @@ void Engine::syncSoundSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::flipMute() {
|
void Engine::flipMute() {
|
||||||
bool mute = false;
|
// Mute will be set to true by default here. This has two reasons:
|
||||||
|
// - if the game already has an "mute" config entry, it will be overwritten anyway.
|
||||||
|
// - if it does not have a "mute" config entry, the sound is unmuted currently and should be muted now.
|
||||||
|
bool mute = true;
|
||||||
|
|
||||||
if (ConfMan.hasKey("mute")) {
|
if (ConfMan.hasKey("mute")) {
|
||||||
mute = !ConfMan.getBool("mute");
|
mute = !ConfMan.getBool("mute");
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "common/error.h"
|
#include "common/error.h"
|
||||||
#include "common/fs.h"
|
#include "common/fs.h"
|
||||||
#include "common/str.h"
|
#include "common/str.h"
|
||||||
|
#include "graphics/pixelformat.h"
|
||||||
|
|
||||||
class OSystem;
|
class OSystem;
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common/events.h"
|
#include "common/events.h"
|
||||||
|
#include "common/file.h"
|
||||||
#include "common/config-manager.h"
|
#include "common/config-manager.h"
|
||||||
|
|
||||||
#include "engines/engine.h"
|
#include "engines/engine.h"
|
||||||
|
@ -352,9 +353,6 @@ Common::Error GrimEngine::run() {
|
||||||
error("gfx backend doesn't support hardware rendering");
|
error("gfx backend doesn't support hardware rendering");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (g_grim->getGameFlags() & GF_DEMO)
|
|
||||||
Common::File::addDefaultDirectory(_gameDataDir.getChild("Movies"));
|
|
||||||
|
|
||||||
g_driver->setupScreen(640, 480, fullscreen);
|
g_driver->setupScreen(640, 480, fullscreen);
|
||||||
|
|
||||||
Bitmap *splash_bm = NULL;
|
Bitmap *splash_bm = NULL;
|
||||||
|
|
|
@ -36,6 +36,10 @@
|
||||||
namespace Graphics {
|
namespace Graphics {
|
||||||
class VectorRenderer;
|
class VectorRenderer;
|
||||||
|
|
||||||
|
|
||||||
|
typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const Graphics::DrawStep &);
|
||||||
|
|
||||||
|
|
||||||
struct DrawStep {
|
struct DrawStep {
|
||||||
struct Color {
|
struct Color {
|
||||||
uint8 r, g, b;
|
uint8 r, g, b;
|
||||||
|
@ -58,7 +62,10 @@ struct DrawStep {
|
||||||
kVectorAlignBottom,
|
kVectorAlignBottom,
|
||||||
kVectorAlignTop,
|
kVectorAlignTop,
|
||||||
kVectorAlignCenter
|
kVectorAlignCenter
|
||||||
} xAlign, yAlign;
|
};
|
||||||
|
|
||||||
|
VectorAlignment xAlign;
|
||||||
|
VectorAlignment yAlign;
|
||||||
|
|
||||||
uint8 shadow, stroke, factor, radius, bevel; /**< Misc options... */
|
uint8 shadow, stroke, factor, radius, bevel; /**< Misc options... */
|
||||||
|
|
||||||
|
@ -67,7 +74,7 @@ struct DrawStep {
|
||||||
|
|
||||||
uint32 scale; /**< scale of all the coordinates in FIXED POINT with 16 bits mantissa */
|
uint32 scale; /**< scale of all the coordinates in FIXED POINT with 16 bits mantissa */
|
||||||
|
|
||||||
void (VectorRenderer::*drawingCall)(const Common::Rect &, const DrawStep &); /** Pointer to drawing function */
|
DrawingFunctionCallback drawingCall; /**< Pointer to drawing function */
|
||||||
Graphics::Surface *blitSrc;
|
Graphics::Surface *blitSrc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -365,22 +365,24 @@ applyScreenShading(GUI::ThemeEngine::ShadingStyle shadingStyle) {
|
||||||
uint8 r, g, b;
|
uint8 r, g, b;
|
||||||
uint lum;
|
uint lum;
|
||||||
|
|
||||||
const uint32 shiftMask = (uint32)~(
|
// Mask to clear the last bit of every color component and all unused bits
|
||||||
(1 << _format.rShift) | (1 << _format.gShift) | (1 << _format.bShift) | (_format.aLoss == 8 ? 0 : (1 << _format.aShift))) >> 1;
|
const uint32 colorMask = ~((1 << _format.rShift) | (1 << _format.gShift) | (1 << _format.bShift) // R/G/B components
|
||||||
|
| (_format.aLoss == 8 ? 0 : (1 << _format.aShift)) // Alpha component
|
||||||
|
| ~(_alphaMask | _redMask | _greenMask | _blueMask)); // All unused bits
|
||||||
|
|
||||||
if (shadingStyle == GUI::ThemeEngine::kShadingDim) {
|
if (shadingStyle == GUI::ThemeEngine::kShadingDim) {
|
||||||
|
|
||||||
int n = (pixels + 7) >> 3;
|
int n = (pixels + 7) >> 3;
|
||||||
switch (pixels % 8) {
|
switch (pixels % 8) {
|
||||||
case 0: do {
|
case 0: do {
|
||||||
*ptr = (*ptr >> 1) & shiftMask; ++ptr;
|
*ptr = (*ptr & colorMask) >> 1; ++ptr;
|
||||||
case 7: *ptr = (*ptr >> 1) & shiftMask; ++ptr;
|
case 7: *ptr = (*ptr & colorMask) >> 1; ++ptr;
|
||||||
case 6: *ptr = (*ptr >> 1) & shiftMask; ++ptr;
|
case 6: *ptr = (*ptr & colorMask) >> 1; ++ptr;
|
||||||
case 5: *ptr = (*ptr >> 1) & shiftMask; ++ptr;
|
case 5: *ptr = (*ptr & colorMask) >> 1; ++ptr;
|
||||||
case 4: *ptr = (*ptr >> 1) & shiftMask; ++ptr;
|
case 4: *ptr = (*ptr & colorMask) >> 1; ++ptr;
|
||||||
case 3: *ptr = (*ptr >> 1) & shiftMask; ++ptr;
|
case 3: *ptr = (*ptr & colorMask) >> 1; ++ptr;
|
||||||
case 2: *ptr = (*ptr >> 1) & shiftMask; ++ptr;
|
case 2: *ptr = (*ptr & colorMask) >> 1; ++ptr;
|
||||||
case 1: *ptr = (*ptr >> 1) & shiftMask; ++ptr;
|
case 1: *ptr = (*ptr & colorMask) >> 1; ++ptr;
|
||||||
} while (--n > 0);
|
} while (--n > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,7 +425,7 @@ calcGradient(uint32 pos, uint32 max) {
|
||||||
output |= ((_gradientStart & _redMask) + ((Base::_gradientBytes[0] * pos) >> 12)) & _redMask;
|
output |= ((_gradientStart & _redMask) + ((Base::_gradientBytes[0] * pos) >> 12)) & _redMask;
|
||||||
output |= ((_gradientStart & _greenMask) + ((Base::_gradientBytes[1] * pos) >> 12)) & _greenMask;
|
output |= ((_gradientStart & _greenMask) + ((Base::_gradientBytes[1] * pos) >> 12)) & _greenMask;
|
||||||
output |= ((_gradientStart & _blueMask) + ((Base::_gradientBytes[2] * pos) >> 12)) & _blueMask;
|
output |= ((_gradientStart & _blueMask) + ((Base::_gradientBytes[2] * pos) >> 12)) & _blueMask;
|
||||||
output |= ~(_redMask | _greenMask | _blueMask);
|
output |= _alphaMask;
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
@ -599,12 +601,12 @@ drawRoundedSquare(int x, int y, int r, int w, int h) {
|
||||||
w <= 0 || h <= 0 || x < 0 || y < 0 || r <= 0)
|
w <= 0 || h <= 0 || x < 0 || y < 0 || r <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((r << 1) > w || (r << 1) > h)
|
if ((r * 2) > w || (r * 2) > h)
|
||||||
r = MIN(w >> 1, h >> 1);
|
r = MIN(w /2, h / 2);
|
||||||
|
|
||||||
if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
|
if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
|
||||||
&& x + w + Base::_shadowOffset < Base::_activeSurface->w
|
&& x + w + Base::_shadowOffset + 1 < Base::_activeSurface->w
|
||||||
&& y + h + Base::_shadowOffset < Base::_activeSurface->h) {
|
&& y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h) {
|
||||||
drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
|
drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -918,10 +920,12 @@ drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, P
|
||||||
}
|
}
|
||||||
|
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
x = MAX(x - bevel, 0);
|
x = MAX(x - bevel, 0);
|
||||||
y = MAX(y - bevel, 0);
|
y = MAX(y - bevel, 0);
|
||||||
h += bevel << 1;
|
|
||||||
w += bevel << 1;
|
w = MIN(w + (bevel * 2), (int)_activeSurface->w);
|
||||||
|
h = MIN(h + (bevel * 2), (int)_activeSurface->h);
|
||||||
|
|
||||||
PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
|
PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
|
||||||
|
|
||||||
|
|
|
@ -237,6 +237,33 @@ struct ColorMasks<8888> {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef __WII__
|
||||||
|
/* Gamecube/Wii specific ColorMask ARGB3444 */
|
||||||
|
template<>
|
||||||
|
struct ColorMasks<3444> {
|
||||||
|
enum {
|
||||||
|
kBytesPerPixel = 2,
|
||||||
|
|
||||||
|
kAlphaBits = 3,
|
||||||
|
kRedBits = 4,
|
||||||
|
kGreenBits = 4,
|
||||||
|
kBlueBits = 4,
|
||||||
|
|
||||||
|
kBlueShift = 0,
|
||||||
|
kGreenShift = kBlueBits,
|
||||||
|
kRedShift = kGreenBits+kBlueBits,
|
||||||
|
kAlphaShift = kGreenBits+kBlueBits+kRedBits,
|
||||||
|
|
||||||
|
kAlphaMask = ((1 << kAlphaBits) - 1) << kAlphaShift,
|
||||||
|
kRedMask = ((1 << kRedBits) - 1) << kRedShift,
|
||||||
|
kGreenMask = ((1 << kGreenBits) - 1) << kGreenShift,
|
||||||
|
kBlueMask = ((1 << kBlueBits) - 1) << kBlueShift,
|
||||||
|
|
||||||
|
kRedBlueMask = kRedMask | kBlueMask
|
||||||
|
};
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
uint32 RGBToColor(uint8 r, uint8 g, uint8 b) {
|
uint32 RGBToColor(uint8 r, uint8 g, uint8 b) {
|
||||||
return T::kAlphaMask |
|
return T::kAlphaMask |
|
||||||
|
|
|
@ -57,14 +57,14 @@ bool CursorManager::showMouse(bool visible) {
|
||||||
return g_system->showMouse(visible);
|
return g_system->showMouse(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CursorManager::pushCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor, int targetScale) {
|
void CursorManager::pushCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int targetScale, const Graphics::PixelFormat *format) {
|
||||||
Cursor *cur = new Cursor(buf, w, h, hotspotX, hotspotY, keycolor, targetScale);
|
Cursor *cur = new Cursor(buf, w, h, hotspotX, hotspotY, keycolor, targetScale, format);
|
||||||
|
|
||||||
cur->_visible = isVisible();
|
cur->_visible = isVisible();
|
||||||
_cursorStack.push(cur);
|
_cursorStack.push(cur);
|
||||||
|
|
||||||
if (buf) {
|
if (buf) {
|
||||||
g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale);
|
g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale, format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ void CursorManager::popCursor() {
|
||||||
|
|
||||||
if (!_cursorStack.empty()) {
|
if (!_cursorStack.empty()) {
|
||||||
cur = _cursorStack.top();
|
cur = _cursorStack.top();
|
||||||
g_system->setMouseCursor(cur->_data, cur->_width, cur->_height, cur->_hotspotX, cur->_hotspotY, cur->_keycolor, cur->_targetScale);
|
g_system->setMouseCursor(cur->_data, cur->_width, cur->_height, cur->_hotspotX, cur->_hotspotY, cur->_keycolor, cur->_targetScale, &cur->_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_system->showMouse(isVisible());
|
g_system->showMouse(isVisible());
|
||||||
|
@ -93,15 +93,24 @@ void CursorManager::popAllCursors() {
|
||||||
g_system->showMouse(isVisible());
|
g_system->showMouse(isVisible());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int targetScale, const Graphics::PixelFormat *format) {
|
||||||
|
|
||||||
void CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor, int targetScale) {
|
|
||||||
if (_cursorStack.empty()) {
|
if (_cursorStack.empty()) {
|
||||||
pushCursor(buf, w, h, hotspotX, hotspotY, keycolor, targetScale);
|
pushCursor(buf, w, h, hotspotX, hotspotY, keycolor, targetScale, format);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cursor *cur = _cursorStack.top();
|
Cursor *cur = _cursorStack.top();
|
||||||
|
|
||||||
|
#ifdef USE_RGB_COLOR
|
||||||
|
uint size;
|
||||||
|
if (!format)
|
||||||
|
size = w * h;
|
||||||
|
else
|
||||||
|
size = w * h * format->bytesPerPixel;
|
||||||
|
#else
|
||||||
uint size = w * h;
|
uint size = w * h;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (cur->_size < size) {
|
if (cur->_size < size) {
|
||||||
delete[] cur->_data;
|
delete[] cur->_data;
|
||||||
|
@ -118,8 +127,14 @@ void CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX,
|
||||||
cur->_hotspotY = hotspotY;
|
cur->_hotspotY = hotspotY;
|
||||||
cur->_keycolor = keycolor;
|
cur->_keycolor = keycolor;
|
||||||
cur->_targetScale = targetScale;
|
cur->_targetScale = targetScale;
|
||||||
|
#ifdef USE_RGB_COLOR
|
||||||
|
if (format)
|
||||||
|
cur->_format = *format;
|
||||||
|
else
|
||||||
|
cur->_format = Graphics::PixelFormat::createFormatCLUT8();
|
||||||
|
#endif
|
||||||
|
|
||||||
g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale);
|
g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CursorManager::supportsCursorPalettes() {
|
bool CursorManager::supportsCursorPalettes() {
|
||||||
|
|
|
@ -28,6 +28,10 @@
|
||||||
#include "common/sys.h"
|
#include "common/sys.h"
|
||||||
#include "common/stack.h"
|
#include "common/stack.h"
|
||||||
#include "common/singleton.h"
|
#include "common/singleton.h"
|
||||||
|
#include "graphics/pixelformat.h"
|
||||||
|
#ifdef USE_RGB_COLOR
|
||||||
|
#include "common/system.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Graphics {
|
namespace Graphics {
|
||||||
|
|
||||||
|
@ -36,7 +40,21 @@ public:
|
||||||
/** Query whether the mouse cursor is visible. */
|
/** Query whether the mouse cursor is visible. */
|
||||||
bool isVisible();
|
bool isVisible();
|
||||||
|
|
||||||
/** Show or hide the mouse cursor. */
|
/**
|
||||||
|
* Show or hide the mouse cursor.
|
||||||
|
*
|
||||||
|
* This function does not call OSystem::updateScreen, when visible is true.
|
||||||
|
* This fact might result in a non visible mouse cursor if the caller does
|
||||||
|
* not call OSystem::updateScreen itself after a showMouse(true) call.
|
||||||
|
*
|
||||||
|
* TODO: We might want to reconsider this behavior, it might be confusing
|
||||||
|
* for the user to call OSystem::updateScreen separately, on the other
|
||||||
|
* hand OSystem::updateScreen might as well display unwanted changes on
|
||||||
|
* the screen. Another alternative would be to let the backend worry
|
||||||
|
* about this on OSystem::showMouse call.
|
||||||
|
*
|
||||||
|
* @see OSystem::showMouse.
|
||||||
|
*/
|
||||||
bool showMouse(bool visible);
|
bool showMouse(bool visible);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,12 +69,13 @@ public:
|
||||||
* @param hotspotY the hotspot Y coordinate
|
* @param hotspotY the hotspot Y coordinate
|
||||||
* @param keycolor the index for the transparent color
|
* @param keycolor the index for the transparent color
|
||||||
* @param targetScale the scale for which the cursor is designed
|
* @param targetScale the scale for which the cursor is designed
|
||||||
*
|
* @param format a pointer to the pixel format which the cursor graphic uses,
|
||||||
|
* CLUT8 will be used if this is NULL or not specified.
|
||||||
* @note It is ok for the buffer to be a NULL pointer. It is sometimes
|
* @note It is ok for the buffer to be a NULL pointer. It is sometimes
|
||||||
* useful to push a "dummy" cursor and modify it later. The
|
* useful to push a "dummy" cursor and modify it later. The
|
||||||
* cursor will be added to the stack, but not to the backend.
|
* cursor will be added to the stack, but not to the backend.
|
||||||
*/
|
*/
|
||||||
void pushCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int targetScale = 1);
|
void pushCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 0xFFFFFFFF, int targetScale = 1, const Graphics::PixelFormat *format = NULL);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pop a cursor from the stack, and restore the previous one to the
|
* Pop a cursor from the stack, and restore the previous one to the
|
||||||
|
@ -76,8 +95,10 @@ public:
|
||||||
* @param hotspotY the hotspot Y coordinate
|
* @param hotspotY the hotspot Y coordinate
|
||||||
* @param keycolor the index for the transparent color
|
* @param keycolor the index for the transparent color
|
||||||
* @param targetScale the scale for which the cursor is designed
|
* @param targetScale the scale for which the cursor is designed
|
||||||
|
* @param format a pointer to the pixel format which the cursor graphic uses,
|
||||||
|
* CLUT8 will be used if this is NULL or not specified.
|
||||||
*/
|
*/
|
||||||
void replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int targetScale = 1);
|
void replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 0xFFFFFFFF, int targetScale = 1, const Graphics::PixelFormat *format = NULL);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pop all of the cursors and cursor palettes from their respective stacks.
|
* Pop all of the cursors and cursor palettes from their respective stacks.
|
||||||
|
@ -152,13 +173,24 @@ private:
|
||||||
uint _height;
|
uint _height;
|
||||||
int _hotspotX;
|
int _hotspotX;
|
||||||
int _hotspotY;
|
int _hotspotY;
|
||||||
byte _keycolor;
|
uint32 _keycolor;
|
||||||
|
Graphics::PixelFormat _format;
|
||||||
byte _targetScale;
|
byte _targetScale;
|
||||||
|
|
||||||
uint _size;
|
uint _size;
|
||||||
|
Cursor(const byte *data, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 0xFFFFFFFF, int targetScale = 1, const Graphics::PixelFormat *format = NULL) {
|
||||||
Cursor(const byte *data, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int targetScale = 1) {
|
#ifdef USE_RGB_COLOR
|
||||||
|
if (!format)
|
||||||
|
_format = Graphics::PixelFormat::createFormatCLUT8();
|
||||||
|
else
|
||||||
|
_format = *format;
|
||||||
|
_size = w * h * _format.bytesPerPixel;
|
||||||
|
_keycolor = keycolor & ((1 << (_format.bytesPerPixel << 3)) - 1);
|
||||||
|
#else
|
||||||
|
_format = Graphics::PixelFormat::createFormatCLUT8();
|
||||||
_size = w * h;
|
_size = w * h;
|
||||||
|
_keycolor = keycolor & 0xFF;
|
||||||
|
#endif
|
||||||
_data = new byte[_size];
|
_data = new byte[_size];
|
||||||
if (data && _data)
|
if (data && _data)
|
||||||
memcpy(_data, data, _size);
|
memcpy(_data, data, _size);
|
||||||
|
@ -166,7 +198,6 @@ private:
|
||||||
_height = h;
|
_height = h;
|
||||||
_hotspotX = hotspotX;
|
_hotspotX = hotspotX;
|
||||||
_hotspotY = hotspotY;
|
_hotspotY = hotspotY;
|
||||||
_keycolor = keycolor;
|
|
||||||
_targetScale = targetScale;
|
_targetScale = targetScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +233,6 @@ private:
|
||||||
delete[] _data;
|
delete[] _data;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Common::Stack<Cursor *> _cursorStack;
|
Common::Stack<Cursor *> _cursorStack;
|
||||||
Common::Stack<Palette *> _cursorPaletteStack;
|
Common::Stack<Palette *> _cursorPaletteStack;
|
||||||
};
|
};
|
||||||
|
|
|
@ -572,8 +572,10 @@ bitmap_t bdf_hexval(unsigned char *buf) {
|
||||||
|
|
||||||
NewFont *NewFont::loadFont(Common::SeekableReadStream &stream) {
|
NewFont *NewFont::loadFont(Common::SeekableReadStream &stream) {
|
||||||
NewFontData *data = bdf_read_font(stream);
|
NewFontData *data = bdf_read_font(stream);
|
||||||
if (!data)
|
if (!data || stream.err()) {
|
||||||
|
free_font(data);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
FontDesc desc;
|
FontDesc desc;
|
||||||
desc.name = data->name;
|
desc.name = data->name;
|
||||||
|
@ -731,6 +733,14 @@ NewFont *NewFont::loadFromCache(Common::SeekableReadStream &stream) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stream.err() || stream.eos()) {
|
||||||
|
free(data->bits);
|
||||||
|
free(data->offset);
|
||||||
|
free(data->width);
|
||||||
|
free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
FontDesc desc;
|
FontDesc desc;
|
||||||
desc.name = data->name;
|
desc.name = data->name;
|
||||||
desc.maxwidth = data->maxwidth;
|
desc.maxwidth = data->maxwidth;
|
||||||
|
@ -750,7 +760,7 @@ NewFont *NewFont::loadFromCache(Common::SeekableReadStream &stream) {
|
||||||
desc.bits_size = data->bits_size;
|
desc.bits_size = data->bits_size;
|
||||||
|
|
||||||
font = new NewFont(desc, data);
|
font = new NewFont(desc, data);
|
||||||
if (!font || stream.ioFailed()) {
|
if (!font) {
|
||||||
free(data->bits);
|
free(data->bits);
|
||||||
free(data->offset);
|
free(data->offset);
|
||||||
free(data->width);
|
free(data->width);
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#define GRAPHICS_PIXELFORMAT_H
|
#define GRAPHICS_PIXELFORMAT_H
|
||||||
|
|
||||||
#include "common/sys.h"
|
#include "common/sys.h"
|
||||||
|
#include "common/list.h"
|
||||||
|
|
||||||
namespace Graphics {
|
namespace Graphics {
|
||||||
|
|
||||||
|
@ -50,6 +51,24 @@ struct PixelFormat {
|
||||||
byte rLoss, gLoss, bLoss, aLoss; /**< Precision loss of each color component. */
|
byte rLoss, gLoss, bLoss, aLoss; /**< Precision loss of each color component. */
|
||||||
byte rShift, gShift, bShift, aShift; /**< Binary left shift of each color component in the pixel value. */
|
byte rShift, gShift, bShift, aShift; /**< Binary left shift of each color component in the pixel value. */
|
||||||
|
|
||||||
|
inline PixelFormat() {
|
||||||
|
bytesPerPixel =
|
||||||
|
rLoss = gLoss = bLoss = aLoss =
|
||||||
|
rShift = gShift = bShift = aShift = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PixelFormat(byte BytesPerPixel,
|
||||||
|
byte RBits, byte GBits, byte BBits, byte ABits,
|
||||||
|
byte RShift, byte GShift, byte BShift, byte AShift) {
|
||||||
|
bytesPerPixel = BytesPerPixel;
|
||||||
|
rLoss = 8 - RBits, gLoss = 8 - GBits, bLoss = 8 - BBits, aLoss = 8 - ABits;
|
||||||
|
rShift = RShift, gShift = GShift, bShift = BShift, aShift = AShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline PixelFormat createFormatCLUT8() {
|
||||||
|
return PixelFormat(1, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
inline bool operator==(const PixelFormat &fmt) const {
|
inline bool operator==(const PixelFormat &fmt) const {
|
||||||
// TODO: If aLoss==8, then the value of aShift is irrelevant, and should be ignored.
|
// TODO: If aLoss==8, then the value of aShift is irrelevant, and should be ignored.
|
||||||
return 0 == memcmp(this, &fmt, sizeof(PixelFormat));
|
return 0 == memcmp(this, &fmt, sizeof(PixelFormat));
|
||||||
|
@ -129,6 +148,26 @@ struct PixelFormat {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the first matching format between two lists.
|
||||||
|
*
|
||||||
|
* @param backend The higher priority list, meant to be a list of formats supported by the backend
|
||||||
|
* @param frontend The lower priority list, meant to be a list of formats supported by the engine
|
||||||
|
* @return The first item on the backend list that also occurs on the frontend list
|
||||||
|
* or PixelFormat::createFormatCLUT8() if no matching formats were found.
|
||||||
|
*/
|
||||||
|
inline PixelFormat findCompatibleFormat(Common::List<PixelFormat> backend, Common::List<PixelFormat> frontend) {
|
||||||
|
#ifdef USE_RGB_COLOR
|
||||||
|
for (Common::List<PixelFormat>::iterator i = backend.begin(); i != backend.end(); ++i) {
|
||||||
|
for (Common::List<PixelFormat>::iterator j = frontend.begin(); j != frontend.end(); ++j) {
|
||||||
|
if (*i == *j)
|
||||||
|
return *i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return PixelFormat::createFormatCLUT8();
|
||||||
|
}
|
||||||
|
|
||||||
} // end of namespace Graphics
|
} // end of namespace Graphics
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -84,7 +84,7 @@ void EditTextWidget::drawWidget() {
|
||||||
|
|
||||||
// Draw the text
|
// Draw the text
|
||||||
adjustOffset();
|
adjustOffset();
|
||||||
g_gui.theme()->drawText(Common::Rect(_x+2+ _leftPadding,_y+2, _x+_leftPadding+getEditRect().width()+2, _y+_h-2), _editString, _state, Graphics::kTextAlignLeft, false, -_editScrollOffset, false, _font);
|
g_gui.theme()->drawText(Common::Rect(_x+2+ _leftPadding,_y+2, _x+_leftPadding+getEditRect().width()+2, _y+_h-2), _editString, _state, Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, -_editScrollOffset, false, _font);
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::Rect EditTextWidget::getEditRect() const {
|
Common::Rect EditTextWidget::getEditRect() const {
|
||||||
|
|
|
@ -72,7 +72,6 @@ GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled),
|
||||||
error("Failed to load any GUI theme, aborting");
|
error("Failed to load any GUI theme, aborting");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_themeChange = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiManager::~GuiManager() {
|
GuiManager::~GuiManager() {
|
||||||
|
@ -143,12 +142,20 @@ bool GuiManager::loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx)
|
||||||
// Enable the new theme
|
// Enable the new theme
|
||||||
//
|
//
|
||||||
_theme = newTheme;
|
_theme = newTheme;
|
||||||
_themeChange = true;
|
_useStdCursor = !_theme->ownCursor();
|
||||||
|
|
||||||
|
// If _stateIsSaved is set, we know that a Theme is already initialized,
|
||||||
|
// thus we initialize the new theme properly
|
||||||
|
if (_stateIsSaved) {
|
||||||
|
_theme->enable();
|
||||||
|
|
||||||
|
if (_useStdCursor)
|
||||||
|
setupCursor();
|
||||||
|
}
|
||||||
|
|
||||||
// refresh all dialogs
|
// refresh all dialogs
|
||||||
for (int i = 0; i < _dialogStack.size(); ++i) {
|
for (int i = 0; i < _dialogStack.size(); ++i)
|
||||||
_dialogStack[i]->reflowLayout();
|
_dialogStack[i]->reflowLayout();
|
||||||
}
|
|
||||||
|
|
||||||
// We need to redraw immediately. Otherwise
|
// We need to redraw immediately. Otherwise
|
||||||
// some other event may cause a widget to be
|
// some other event may cause a widget to be
|
||||||
|
@ -157,10 +164,6 @@ bool GuiManager::loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx)
|
||||||
redraw();
|
redraw();
|
||||||
_system->updateScreen();
|
_system->updateScreen();
|
||||||
|
|
||||||
Common::Event event;
|
|
||||||
event.type = Common::EVENT_SCREEN_CHANGED;
|
|
||||||
_system->getEventManager()->pushEvent(event);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +236,6 @@ void GuiManager::runLoop() {
|
||||||
|
|
||||||
// _theme->refresh();
|
// _theme->refresh();
|
||||||
|
|
||||||
_themeChange = false;
|
|
||||||
_redrawStatus = kRedrawFull;
|
_redrawStatus = kRedrawFull;
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
|
@ -285,21 +287,6 @@ void GuiManager::runLoop() {
|
||||||
|
|
||||||
Common::Point mouse(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y);
|
Common::Point mouse(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y);
|
||||||
|
|
||||||
// HACK to change the cursor to the new themes one
|
|
||||||
if (_themeChange) {
|
|
||||||
_theme->enable();
|
|
||||||
|
|
||||||
_useStdCursor = !_theme->ownCursor();
|
|
||||||
if (_useStdCursor)
|
|
||||||
setupCursor();
|
|
||||||
|
|
||||||
// _theme->refresh();
|
|
||||||
|
|
||||||
_themeChange = false;
|
|
||||||
_redrawStatus = kRedrawFull;
|
|
||||||
redraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastRedraw + waitTime < _system->getMillis()) {
|
if (lastRedraw + waitTime < _system->getMillis()) {
|
||||||
_theme->updateScreen();
|
_theme->updateScreen();
|
||||||
_system->updateScreen();
|
_system->updateScreen();
|
||||||
|
|
|
@ -122,8 +122,6 @@ protected:
|
||||||
int _cursorAnimateTimer;
|
int _cursorAnimateTimer;
|
||||||
byte _cursor[2048];
|
byte _cursor[2048];
|
||||||
|
|
||||||
bool _themeChange;
|
|
||||||
|
|
||||||
void initKeymap();
|
void initKeymap();
|
||||||
|
|
||||||
void saveState();
|
void saveState();
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
|
|
||||||
#include "common/system.h"
|
#include "common/system.h"
|
||||||
#include "common/events.h"
|
#include "common/events.h"
|
||||||
|
#include "common/frac.h"
|
||||||
|
|
||||||
#include "gui/ListWidget.h"
|
#include "gui/ListWidget.h"
|
||||||
#include "gui/ScrollBarWidget.h"
|
#include "gui/ScrollBarWidget.h"
|
||||||
#include "gui/dialog.h"
|
#include "gui/dialog.h"
|
||||||
|
@ -62,6 +64,7 @@ ListWidget::ListWidget(GuiObject *boss, const String &name, uint32 cmd)
|
||||||
_editable = true;
|
_editable = true;
|
||||||
|
|
||||||
_quickSelect = true;
|
_quickSelect = true;
|
||||||
|
_editColor = ThemeEngine::kFontColorNormal;
|
||||||
}
|
}
|
||||||
|
|
||||||
ListWidget::ListWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd)
|
ListWidget::ListWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd)
|
||||||
|
@ -105,6 +108,22 @@ Widget *ListWidget::findWidget(int x, int y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::setSelected(int item) {
|
void ListWidget::setSelected(int item) {
|
||||||
|
// HACK/FIXME: If our _listIndex has a non zero size,
|
||||||
|
// we will need to look up, whether the user selected
|
||||||
|
// item is present in that list
|
||||||
|
if (_listIndex.size()) {
|
||||||
|
int filteredItem = -1;
|
||||||
|
|
||||||
|
for (uint i = 0; i < _listIndex.size(); ++i) {
|
||||||
|
if (_listIndex[i] == item) {
|
||||||
|
filteredItem = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item = filteredItem;
|
||||||
|
}
|
||||||
|
|
||||||
assert(item >= -1 && item < (int)_list.size());
|
assert(item >= -1 && item < (int)_list.size());
|
||||||
|
|
||||||
// We only have to do something if the widget is enabled and the selection actually changes
|
// We only have to do something if the widget is enabled and the selection actually changes
|
||||||
|
@ -123,7 +142,17 @@ void ListWidget::setSelected(int item) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::setList(const StringList &list) {
|
ThemeEngine::FontColor ListWidget::getSelectionColor() const {
|
||||||
|
if (_listColors.empty())
|
||||||
|
return ThemeEngine::kFontColorNormal;
|
||||||
|
|
||||||
|
if (_filter.empty())
|
||||||
|
return _listColors[_selectedItem];
|
||||||
|
else
|
||||||
|
return _listColors[_listIndex[_selectedItem]];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListWidget::setList(const StringList &list, const ColorList *colors) {
|
||||||
if (_editMode && _caretVisible)
|
if (_editMode && _caretVisible)
|
||||||
drawCaret(true);
|
drawCaret(true);
|
||||||
|
|
||||||
|
@ -131,6 +160,13 @@ void ListWidget::setList(const StringList &list) {
|
||||||
_dataList = list;
|
_dataList = list;
|
||||||
_list = list;
|
_list = list;
|
||||||
_filter.clear();
|
_filter.clear();
|
||||||
|
_listIndex.clear();
|
||||||
|
_listColors.clear();
|
||||||
|
|
||||||
|
if (colors) {
|
||||||
|
_listColors = *colors;
|
||||||
|
assert(_listColors.size() == _dataList.size());
|
||||||
|
}
|
||||||
|
|
||||||
int size = list.size();
|
int size = list.size();
|
||||||
if (_currentPos >= size)
|
if (_currentPos >= size)
|
||||||
|
@ -143,7 +179,19 @@ void ListWidget::setList(const StringList &list) {
|
||||||
scrollBarRecalc();
|
scrollBarRecalc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::append(const String &s) {
|
void ListWidget::append(const String &s, ThemeEngine::FontColor color) {
|
||||||
|
if (_dataList.size() == _listColors.size()) {
|
||||||
|
// If the color list has the size of the data list, we append the color.
|
||||||
|
_listColors.push_back(color);
|
||||||
|
} else if (!_listColors.size() && color != ThemeEngine::kFontColorNormal) {
|
||||||
|
// If it's the first entry to use a non default color, we will fill
|
||||||
|
// up all other entries of the color list with the default color and
|
||||||
|
// add the requested color for the new entry.
|
||||||
|
for (uint i = 0; i < _dataList.size(); ++i)
|
||||||
|
_listColors.push_back(ThemeEngine::kFontColorNormal);
|
||||||
|
_listColors.push_back(color);
|
||||||
|
}
|
||||||
|
|
||||||
_dataList.push_back(s);
|
_dataList.push_back(s);
|
||||||
_list.push_back(s);
|
_list.push_back(s);
|
||||||
|
|
||||||
|
@ -356,8 +404,13 @@ bool ListWidget::handleKeyUp(Common::KeyState state) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListWidget::receivedFocusWidget() {
|
||||||
|
// Redraw the widget so the selection color will change
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
|
||||||
void ListWidget::lostFocusWidget() {
|
void ListWidget::lostFocusWidget() {
|
||||||
// If we loose focus, we simply forget the user changes
|
// If we lose focus, we simply forget the user changes
|
||||||
_editMode = false;
|
_editMode = false;
|
||||||
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
|
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
|
||||||
drawCaret(true);
|
drawCaret(true);
|
||||||
|
@ -387,15 +440,14 @@ void ListWidget::drawWidget() {
|
||||||
for (i = 0, pos = _currentPos; i < _entriesPerPage && pos < len; i++, pos++) {
|
for (i = 0, pos = _currentPos; i < _entriesPerPage && pos < len; i++, pos++) {
|
||||||
const int y = _y + _topPadding + kLineHeight * i;
|
const int y = _y + _topPadding + kLineHeight * i;
|
||||||
const int fontHeight = kLineHeight;
|
const int fontHeight = kLineHeight;
|
||||||
bool inverted = false;
|
ThemeEngine::TextInversionState inverted = ThemeEngine::kTextInversionNone;
|
||||||
|
|
||||||
// Draw the selected item inverted, on a highlighted background.
|
// Draw the selected item inverted, on a highlighted background.
|
||||||
if (_selectedItem == pos) {
|
if (_selectedItem == pos) {
|
||||||
if (_hasFocus)
|
if (_hasFocus)
|
||||||
inverted = true;
|
inverted = ThemeEngine::kTextInversionFocus;
|
||||||
else
|
else
|
||||||
g_gui.theme()->drawWidgetBackground(Common::Rect(_x, y - 1, _x + _w - 1, y + fontHeight - 1),
|
inverted = ThemeEngine::kTextInversion;
|
||||||
0, ThemeEngine::kWidgetBackgroundBorderSmall);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::Rect r(getEditRect());
|
Common::Rect r(getEditRect());
|
||||||
|
@ -413,17 +465,27 @@ void ListWidget::drawWidget() {
|
||||||
|
|
||||||
int width;
|
int width;
|
||||||
|
|
||||||
|
ThemeEngine::FontColor color = ThemeEngine::kFontColorNormal;
|
||||||
|
|
||||||
|
if (!_listColors.empty()) {
|
||||||
|
if (_filter.empty() || _selectedItem == -1)
|
||||||
|
color = _listColors[pos];
|
||||||
|
else
|
||||||
|
color = _listColors[_listIndex[pos]];
|
||||||
|
}
|
||||||
|
|
||||||
if (_selectedItem == pos && _editMode) {
|
if (_selectedItem == pos && _editMode) {
|
||||||
buffer = _editString;
|
buffer = _editString;
|
||||||
|
color = _editColor;
|
||||||
adjustOffset();
|
adjustOffset();
|
||||||
width = _w - r.left - _hlRightPadding - _leftPadding - scrollbarW;
|
width = _w - r.left - _hlRightPadding - _leftPadding - scrollbarW;
|
||||||
g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight - 2),
|
g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight - 2), buffer, _state,
|
||||||
buffer, _state, Graphics::kTextAlignLeft, inverted, pad, true);
|
Graphics::kTextAlignLeft, inverted, pad, true, ThemeEngine::kFontStyleBold, color);
|
||||||
} else {
|
} else {
|
||||||
buffer = _list[pos];
|
buffer = _list[pos];
|
||||||
width = _w - r.left - scrollbarW;
|
width = _w - r.left - scrollbarW;
|
||||||
g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight - 2),
|
g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight - 2), buffer, _state,
|
||||||
buffer, _state, Graphics::kTextAlignLeft, inverted, pad, true);
|
Graphics::kTextAlignLeft, inverted, pad, true, ThemeEngine::kFontStyleBold, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
_textWidth[i] = width;
|
_textWidth[i] = width;
|
||||||
|
@ -481,6 +543,14 @@ void ListWidget::startEditMode() {
|
||||||
if (_editable && !_editMode && _selectedItem >= 0) {
|
if (_editable && !_editMode && _selectedItem >= 0) {
|
||||||
_editMode = true;
|
_editMode = true;
|
||||||
setEditString(_list[_selectedItem]);
|
setEditString(_list[_selectedItem]);
|
||||||
|
if (_listColors.empty()) {
|
||||||
|
_editColor = ThemeEngine::kFontColorNormal;
|
||||||
|
} else {
|
||||||
|
if (_filter.empty())
|
||||||
|
_editColor = _listColors[_selectedItem];
|
||||||
|
else
|
||||||
|
_editColor = _listColors[_listIndex[_selectedItem]];
|
||||||
|
}
|
||||||
draw();
|
draw();
|
||||||
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
|
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
|
||||||
}
|
}
|
||||||
|
@ -522,13 +592,15 @@ void ListWidget::reflowLayout() {
|
||||||
// of the list.
|
// of the list.
|
||||||
// We do a rough rounding on the decimal places of Entries Per Page,
|
// We do a rough rounding on the decimal places of Entries Per Page,
|
||||||
// to add another entry even if it goes a tad over the padding.
|
// to add another entry even if it goes a tad over the padding.
|
||||||
_entriesPerPage = ((_h - _topPadding - _bottomPadding) << 16) / kLineHeight;
|
frac_t entriesPerPage = intToFrac(_h - _topPadding - _bottomPadding) / kLineHeight;
|
||||||
|
|
||||||
if ((uint)(_entriesPerPage & 0xFFFF) >= 0xF000)
|
// Our threshold before we add another entry is 0.9375 (0xF000 with FRAC_BITS being 16).
|
||||||
_entriesPerPage += (1 << 16);
|
const frac_t threshold = intToFrac(15) / 16;
|
||||||
|
|
||||||
_entriesPerPage >>= 16;
|
if ((frac_t)(entriesPerPage & FRAC_LO_MASK) >= threshold)
|
||||||
|
entriesPerPage += FRAC_ONE;
|
||||||
|
|
||||||
|
_entriesPerPage = fracToInt(entriesPerPage);
|
||||||
assert(_entriesPerPage > 0);
|
assert(_entriesPerPage > 0);
|
||||||
|
|
||||||
delete[] _textWidth;
|
delete[] _textWidth;
|
||||||
|
@ -560,9 +632,12 @@ void ListWidget::setFilter(const String &filter, bool redraw) {
|
||||||
if (_filter.empty()) {
|
if (_filter.empty()) {
|
||||||
// No filter -> display everything
|
// No filter -> display everything
|
||||||
_list = _dataList;
|
_list = _dataList;
|
||||||
|
_listIndex.clear();
|
||||||
} else {
|
} else {
|
||||||
// Restrict the list to everything which contains _filter as a substring,
|
// Restrict the list to everything which contains all words in _filter
|
||||||
// ignoring case.
|
// as substrings, ignoring case.
|
||||||
|
|
||||||
|
Common::StringTokenizer tok(_filter);
|
||||||
String tmp;
|
String tmp;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
|
@ -572,7 +647,16 @@ void ListWidget::setFilter(const String &filter, bool redraw) {
|
||||||
for (StringList::iterator i = _dataList.begin(); i != _dataList.end(); ++i, ++n) {
|
for (StringList::iterator i = _dataList.begin(); i != _dataList.end(); ++i, ++n) {
|
||||||
tmp = *i;
|
tmp = *i;
|
||||||
tmp.toLowercase();
|
tmp.toLowercase();
|
||||||
if (tmp.contains(_filter)) {
|
bool matches = true;
|
||||||
|
tok.reset();
|
||||||
|
while (!tok.empty()) {
|
||||||
|
if (!tmp.contains(tok.nextToken())) {
|
||||||
|
matches = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matches) {
|
||||||
_list.push_back(*i);
|
_list.push_back(*i);
|
||||||
_listIndex.push_back(n);
|
_listIndex.push_back(n);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#include "gui/editable.h"
|
#include "gui/editable.h"
|
||||||
#include "common/str.h"
|
#include "common/str.h"
|
||||||
|
|
||||||
|
#include "gui/ThemeEngine.h"
|
||||||
|
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
class ScrollBarWidget;
|
class ScrollBarWidget;
|
||||||
|
@ -51,9 +53,11 @@ class ListWidget : public EditableWidget {
|
||||||
public:
|
public:
|
||||||
typedef Common::String String;
|
typedef Common::String String;
|
||||||
typedef Common::StringList StringList;
|
typedef Common::StringList StringList;
|
||||||
|
typedef Common::Array<ThemeEngine::FontColor> ColorList;
|
||||||
protected:
|
protected:
|
||||||
StringList _list;
|
StringList _list;
|
||||||
StringList _dataList;
|
StringList _dataList;
|
||||||
|
ColorList _listColors;
|
||||||
Common::Array<int> _listIndex;
|
Common::Array<int> _listIndex;
|
||||||
bool _editable;
|
bool _editable;
|
||||||
bool _editMode;
|
bool _editMode;
|
||||||
|
@ -80,6 +84,8 @@ protected:
|
||||||
|
|
||||||
uint32 _cmd;
|
uint32 _cmd;
|
||||||
|
|
||||||
|
ThemeEngine::FontColor _editColor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ListWidget(GuiObject *boss, const String &name, uint32 cmd = 0);
|
ListWidget(GuiObject *boss, const String &name, uint32 cmd = 0);
|
||||||
ListWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd = 0);
|
ListWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd = 0);
|
||||||
|
@ -87,20 +93,33 @@ public:
|
||||||
|
|
||||||
virtual Widget *findWidget(int x, int y);
|
virtual Widget *findWidget(int x, int y);
|
||||||
|
|
||||||
void setList(const StringList &list);
|
void setList(const StringList &list, const ColorList *colors = 0);
|
||||||
void append(const String &s);
|
|
||||||
const StringList &getList() const { return _dataList; }
|
const StringList &getList() const { return _dataList; }
|
||||||
int getSelected() const { return (_filter.empty() || _selectedItem == -1) ? _selectedItem : _listIndex[_selectedItem]; }
|
|
||||||
|
void append(const String &s, ThemeEngine::FontColor color = ThemeEngine::kFontColorNormal);
|
||||||
|
|
||||||
void setSelected(int item);
|
void setSelected(int item);
|
||||||
|
int getSelected() const { return (_filter.empty() || _selectedItem == -1) ? _selectedItem : _listIndex[_selectedItem]; }
|
||||||
|
|
||||||
const String &getSelectedString() const { return _list[_selectedItem]; }
|
const String &getSelectedString() const { return _list[_selectedItem]; }
|
||||||
|
ThemeEngine::FontColor getSelectionColor() const;
|
||||||
|
|
||||||
void setNumberingMode(NumberingMode numberingMode) { _numberingMode = numberingMode; }
|
void setNumberingMode(NumberingMode numberingMode) { _numberingMode = numberingMode; }
|
||||||
bool isEditable() const { return _editable; }
|
|
||||||
void setEditable(bool editable) { _editable = editable; }
|
|
||||||
void scrollTo(int item);
|
void scrollTo(int item);
|
||||||
void scrollToEnd();
|
void scrollToEnd();
|
||||||
|
|
||||||
void enableQuickSelect(bool enable) { _quickSelect = enable; }
|
void enableQuickSelect(bool enable) { _quickSelect = enable; }
|
||||||
String getQuickSelectString() const { return _quickSelectStr; }
|
String getQuickSelectString() const { return _quickSelectStr; }
|
||||||
|
|
||||||
|
bool isEditable() const { return _editable; }
|
||||||
|
void setEditable(bool editable) { _editable = editable; }
|
||||||
|
void setEditColor(ThemeEngine::FontColor color) { _editColor = color; }
|
||||||
|
|
||||||
|
// Made startEditMode/endEditMode for SaveLoadChooser
|
||||||
|
void startEditMode();
|
||||||
|
void endEditMode();
|
||||||
|
|
||||||
void setFilter(const String &filter, bool redraw = true);
|
void setFilter(const String &filter, bool redraw = true);
|
||||||
|
|
||||||
virtual void handleTickle();
|
virtual void handleTickle();
|
||||||
|
@ -115,10 +134,6 @@ public:
|
||||||
|
|
||||||
virtual bool wantsFocus() { return true; }
|
virtual bool wantsFocus() { return true; }
|
||||||
|
|
||||||
// Made startEditMode for SCUMM's SaveLoadChooser
|
|
||||||
void startEditMode();
|
|
||||||
void endEditMode();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void drawWidget();
|
void drawWidget();
|
||||||
|
|
||||||
|
@ -130,6 +145,7 @@ protected:
|
||||||
|
|
||||||
Common::Rect getEditRect() const;
|
Common::Rect getEditRect() const;
|
||||||
|
|
||||||
|
void receivedFocusWidget();
|
||||||
void lostFocusWidget();
|
void lostFocusWidget();
|
||||||
void scrollToCurrent();
|
void scrollToCurrent();
|
||||||
|
|
||||||
|
|
|
@ -345,7 +345,7 @@ void PopUpDialog::drawMenuEntry(int entry, bool hilite) {
|
||||||
g_gui.theme()->drawLineSeparator(Common::Rect(x, y, x+w, y+kLineHeight));
|
g_gui.theme()->drawLineSeparator(Common::Rect(x, y, x+w, y+kLineHeight));
|
||||||
} else {
|
} else {
|
||||||
g_gui.theme()->drawText(Common::Rect(x+1, y+2, x+w, y+2+kLineHeight), name, hilite ? ThemeEngine::kStateHighlight : ThemeEngine::kStateEnabled,
|
g_gui.theme()->drawText(Common::Rect(x+1, y+2, x+w, y+2+kLineHeight), name, hilite ? ThemeEngine::kStateHighlight : ThemeEngine::kStateEnabled,
|
||||||
Graphics::kTextAlignLeft, false, _leftPadding);
|
Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, _leftPadding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,9 +63,9 @@ void ScrollBarWidget::handleMouseDown(int x, int y, int button, int clickCount)
|
||||||
_currentPos++;
|
_currentPos++;
|
||||||
_draggingPart = kDownArrowPart;
|
_draggingPart = kDownArrowPart;
|
||||||
} else if (y < _sliderPos) {
|
} else if (y < _sliderPos) {
|
||||||
_currentPos -= _entriesPerPage;
|
_currentPos -= _entriesPerPage - 1;
|
||||||
} else if (y >= _sliderPos + _sliderHeight) {
|
} else if (y >= _sliderPos + _sliderHeight) {
|
||||||
_currentPos += _entriesPerPage;
|
_currentPos += _entriesPerPage - 1;
|
||||||
} else {
|
} else {
|
||||||
_draggingPart = kSliderPart;
|
_draggingPart = kSliderPart;
|
||||||
_sliderDeltaMouseDownPos = y - _sliderPos;
|
_sliderDeltaMouseDownPos = y - _sliderPos;
|
||||||
|
|
|
@ -91,7 +91,37 @@ int TabWidget::addTab(const String &title) {
|
||||||
|
|
||||||
int numTabs = _tabs.size();
|
int numTabs = _tabs.size();
|
||||||
|
|
||||||
|
// HACK: Nintendo DS uses a custom config dialog. This dialog does not work with
|
||||||
|
// our default "Globals.TabWidget.Tab.Width" setting.
|
||||||
|
//
|
||||||
|
// TODO: Add proper handling in the theme layout for such cases.
|
||||||
|
//
|
||||||
|
// There are different solutions to this problem:
|
||||||
|
// - offer a "Tab.Width" setting per tab widget and thus let the Ninteno DS
|
||||||
|
// backend set a default value for its special dialog.
|
||||||
|
//
|
||||||
|
// - change our themes to use auto width calculaction by default
|
||||||
|
//
|
||||||
|
// - change "Globals.TabWidget.Tab.Width" to be the minimal tab width setting and
|
||||||
|
// rename it accordingly.
|
||||||
|
// Actually this solution is pretty similar to our HACK for the Nintendo DS
|
||||||
|
// backend. This hack enables auto width calculation by default with the
|
||||||
|
// "Globals.TabWidget.Tab.Width" value as minimal width for the tab buttons.
|
||||||
|
//
|
||||||
|
// - we might also consider letting every tab button having its own width.
|
||||||
|
//
|
||||||
|
// - other solutions you can think of, which are hopefully less evil ;-).
|
||||||
|
//
|
||||||
|
// Of course also the Ninteno DS' dialog should be in our layouting engine, instead
|
||||||
|
// of being hard coded like it is right now.
|
||||||
|
//
|
||||||
|
// There are checks for __DS__ all over this source file to take care of the
|
||||||
|
// aforemnetioned problem.
|
||||||
|
#ifdef __DS__
|
||||||
|
if (true) {
|
||||||
|
#else
|
||||||
if (g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Width") == 0) {
|
if (g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Width") == 0) {
|
||||||
|
#endif
|
||||||
if (_tabWidth == 0)
|
if (_tabWidth == 0)
|
||||||
_tabWidth = 40;
|
_tabWidth = 40;
|
||||||
// Determine the new tab width
|
// Determine the new tab width
|
||||||
|
@ -217,6 +247,10 @@ void TabWidget::reflowLayout() {
|
||||||
|
|
||||||
if (_tabWidth == 0) {
|
if (_tabWidth == 0) {
|
||||||
_tabWidth = 40;
|
_tabWidth = 40;
|
||||||
|
#ifdef __DS__
|
||||||
|
}
|
||||||
|
if (true) {
|
||||||
|
#endif
|
||||||
int maxWidth = _w / _tabs.size();
|
int maxWidth = _w / _tabs.size();
|
||||||
|
|
||||||
for (uint i = 0; i < _tabs.size(); ++i) {
|
for (uint i = 0; i < _tabs.size(); ++i) {
|
||||||
|
|
|
@ -76,6 +76,10 @@ public:
|
||||||
*/
|
*/
|
||||||
void removeTab(int tabID);
|
void removeTab(int tabID);
|
||||||
|
|
||||||
|
int getActiveTab() {
|
||||||
|
return _activeTab;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the active tab by specifying a valid tab ID.
|
* Set the active tab by specifying a valid tab ID.
|
||||||
* setActiveTab changes the value of _firstWidget. This means new
|
* setActiveTab changes the value of _firstWidget. This means new
|
||||||
|
|
|
@ -56,10 +56,10 @@ const char * const ThemeEngine::kImageSearch = "search.bmp";
|
||||||
|
|
||||||
struct TextDrawData {
|
struct TextDrawData {
|
||||||
const Graphics::Font *_fontPtr;
|
const Graphics::Font *_fontPtr;
|
||||||
|
};
|
||||||
|
|
||||||
struct {
|
struct TextColorData {
|
||||||
uint8 r, g, b;
|
int r, g, b;
|
||||||
} _color;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WidgetDrawData {
|
struct WidgetDrawData {
|
||||||
|
@ -67,6 +67,7 @@ struct WidgetDrawData {
|
||||||
Common::List<Graphics::DrawStep> _steps;
|
Common::List<Graphics::DrawStep> _steps;
|
||||||
|
|
||||||
TextData _textDataId;
|
TextData _textDataId;
|
||||||
|
TextColor _textColorId;
|
||||||
Graphics::TextAlign _textAlignH;
|
Graphics::TextAlign _textAlignH;
|
||||||
GUI::ThemeEngine::TextAlignVertical _textAlignV;
|
GUI::ThemeEngine::TextAlignVertical _textAlignV;
|
||||||
|
|
||||||
|
@ -116,16 +117,17 @@ protected:
|
||||||
|
|
||||||
class ThemeItemTextData : public ThemeItem {
|
class ThemeItemTextData : public ThemeItem {
|
||||||
public:
|
public:
|
||||||
ThemeItemTextData(ThemeEngine *engine, const TextDrawData *data, const Common::Rect &area, const Common::String &text,
|
ThemeItemTextData(ThemeEngine *engine, const TextDrawData *data, const TextColorData *color, const Common::Rect &area, const Common::String &text,
|
||||||
Graphics::TextAlign alignH, GUI::ThemeEngine::TextAlignVertical alignV,
|
Graphics::TextAlign alignH, GUI::ThemeEngine::TextAlignVertical alignV,
|
||||||
bool ellipsis, bool restoreBg, int deltaX) :
|
bool ellipsis, bool restoreBg, int deltaX) :
|
||||||
ThemeItem(engine, area), _data(data), _text(text), _alignH(alignH), _alignV(alignV),
|
ThemeItem(engine, area), _data(data), _color(color), _text(text), _alignH(alignH), _alignV(alignV),
|
||||||
_ellipsis(ellipsis), _restoreBg(restoreBg), _deltax(deltaX) {}
|
_ellipsis(ellipsis), _restoreBg(restoreBg), _deltax(deltaX) {}
|
||||||
|
|
||||||
void drawSelf(bool draw, bool restore);
|
void drawSelf(bool draw, bool restore);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const TextDrawData *_data;
|
const TextDrawData *_data;
|
||||||
|
const TextColorData *_color;
|
||||||
Common::String _text;
|
Common::String _text;
|
||||||
Graphics::TextAlign _alignH;
|
Graphics::TextAlign _alignH;
|
||||||
GUI::ThemeEngine::TextAlignVertical _alignV;
|
GUI::ThemeEngine::TextAlignVertical _alignV;
|
||||||
|
@ -167,6 +169,7 @@ static const DrawDataInfo kDrawDataDefaults[] = {
|
||||||
{kDDPlainColorBackground, "plain_bg", true, kDDNone},
|
{kDDPlainColorBackground, "plain_bg", true, kDDNone},
|
||||||
{kDDDefaultBackground, "default_bg", true, kDDNone},
|
{kDDDefaultBackground, "default_bg", true, kDDNone},
|
||||||
{kDDTextSelectionBackground, "text_selection", false, kDDNone},
|
{kDDTextSelectionBackground, "text_selection", false, kDDNone},
|
||||||
|
{kDDTextSelectionFocusBackground, "text_selection_focus", false, kDDNone},
|
||||||
|
|
||||||
{kDDWidgetBackgroundDefault, "widget_default", true, kDDNone},
|
{kDDWidgetBackgroundDefault, "widget_default", true, kDDNone},
|
||||||
{kDDWidgetBackgroundSmall, "widget_small", true, kDDNone},
|
{kDDWidgetBackgroundSmall, "widget_small", true, kDDNone},
|
||||||
|
@ -179,7 +182,7 @@ static const DrawDataInfo kDrawDataDefaults[] = {
|
||||||
|
|
||||||
{kDDSliderFull, "slider_full", false, kDDNone},
|
{kDDSliderFull, "slider_full", false, kDDNone},
|
||||||
{kDDSliderHover, "slider_hover", false, kDDNone},
|
{kDDSliderHover, "slider_hover", false, kDDNone},
|
||||||
{kDDSliderDisabled, "slider_disabled", true, kDDNone},
|
{kDDSliderDisabled, "slider_disabled", false, kDDNone},
|
||||||
|
|
||||||
{kDDCheckboxDefault, "checkbox_default", true, kDDNone},
|
{kDDCheckboxDefault, "checkbox_default", true, kDDNone},
|
||||||
{kDDCheckboxDisabled, "checkbox_disabled", true, kDDNone},
|
{kDDCheckboxDisabled, "checkbox_disabled", true, kDDNone},
|
||||||
|
@ -231,7 +234,7 @@ void ThemeItemTextData::drawSelf(bool draw, bool restore) {
|
||||||
_engine->restoreBackground(_area);
|
_engine->restoreBackground(_area);
|
||||||
|
|
||||||
if (draw) {
|
if (draw) {
|
||||||
_engine->renderer()->setFgColor(_data->_color.r, _data->_color.g, _data->_color.b);
|
_engine->renderer()->setFgColor(_color->r, _color->g, _color->b);
|
||||||
_engine->renderer()->drawString(_data->_fontPtr, _text, _area, _alignH, _alignV, _deltax, _ellipsis);
|
_engine->renderer()->drawString(_data->_fontPtr, _text, _area, _alignH, _alignV, _deltax, _ellipsis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,6 +279,10 @@ ThemeEngine::ThemeEngine(Common::String id, GraphicsMode mode) :
|
||||||
_texts[i] = 0;
|
_texts[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < kTextColorMAX; ++i) {
|
||||||
|
_textColors[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// We currently allow two different ways of theme selection in our config file:
|
// We currently allow two different ways of theme selection in our config file:
|
||||||
// 1) Via full path
|
// 1) Via full path
|
||||||
// 2) Via a basename, which will need to be translated into a full path
|
// 2) Via a basename, which will need to be translated into a full path
|
||||||
|
@ -531,20 +538,21 @@ void ThemeEngine::addDrawStep(const Common::String &drawDataId, const Graphics::
|
||||||
_widgets[id]->_steps.push_back(step);
|
_widgets[id]->_steps.push_back(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ThemeEngine::addTextData(const Common::String &drawDataId, TextData textId, Graphics::TextAlign alignH, TextAlignVertical alignV) {
|
bool ThemeEngine::addTextData(const Common::String &drawDataId, TextData textId, TextColor colorId, Graphics::TextAlign alignH, TextAlignVertical alignV) {
|
||||||
DrawData id = parseDrawDataId(drawDataId);
|
DrawData id = parseDrawDataId(drawDataId);
|
||||||
|
|
||||||
if (id == -1 || textId == -1 || !_widgets[id])
|
if (id == -1 || textId == -1 || colorId == kTextColorMAX || !_widgets[id])
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_widgets[id]->_textDataId = textId;
|
_widgets[id]->_textDataId = textId;
|
||||||
|
_widgets[id]->_textColorId = colorId;
|
||||||
_widgets[id]->_textAlignH = alignH;
|
_widgets[id]->_textAlignH = alignH;
|
||||||
_widgets[id]->_textAlignV = alignV;
|
_widgets[id]->_textAlignV = alignV;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ThemeEngine::addFont(TextData textId, const Common::String &file, int r, int g, int b) {
|
bool ThemeEngine::addFont(TextData textId, const Common::String &file) {
|
||||||
if (textId == -1)
|
if (textId == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -568,13 +576,26 @@ bool ThemeEngine::addFont(TextData textId, const Common::String &file, int r, in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_texts[textId]->_color.r = r;
|
|
||||||
_texts[textId]->_color.g = g;
|
|
||||||
_texts[textId]->_color.b = b;
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ThemeEngine::addTextColor(TextColor colorId, int r, int g, int b) {
|
||||||
|
if (colorId >= kTextColorMAX)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (_textColors[colorId] != 0)
|
||||||
|
delete _textColors[colorId];
|
||||||
|
|
||||||
|
_textColors[colorId] = new TextColorData;
|
||||||
|
|
||||||
|
_textColors[colorId]->r = r;
|
||||||
|
_textColors[colorId]->g = g;
|
||||||
|
_textColors[colorId]->b = b;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ThemeEngine::addBitmap(const Common::String &filename) {
|
bool ThemeEngine::addBitmap(const Common::String &filename) {
|
||||||
// Nothing has to be done if the bitmap already has been loaded.
|
// Nothing has to be done if the bitmap already has been loaded.
|
||||||
Graphics::Surface *surf = _bitmaps[filename];
|
Graphics::Surface *surf = _bitmaps[filename];
|
||||||
|
@ -655,6 +676,11 @@ void ThemeEngine::unloadTheme() {
|
||||||
_texts[i] = 0;
|
_texts[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < kTextColorMAX; ++i) {
|
||||||
|
delete _textColors[i];
|
||||||
|
_textColors[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
_themeEval->reset();
|
_themeEval->reset();
|
||||||
_themeOk = false;
|
_themeOk = false;
|
||||||
}
|
}
|
||||||
|
@ -770,7 +796,7 @@ void ThemeEngine::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThemeEngine::queueDDText(TextData type, const Common::Rect &r, const Common::String &text, bool restoreBg,
|
void ThemeEngine::queueDDText(TextData type, TextColor color, const Common::Rect &r, const Common::String &text, bool restoreBg,
|
||||||
bool ellipsis, Graphics::TextAlign alignH, TextAlignVertical alignV, int deltax) {
|
bool ellipsis, Graphics::TextAlign alignH, TextAlignVertical alignV, int deltax) {
|
||||||
|
|
||||||
if (_texts[type] == 0)
|
if (_texts[type] == 0)
|
||||||
|
@ -779,7 +805,7 @@ void ThemeEngine::queueDDText(TextData type, const Common::Rect &r, const Common
|
||||||
Common::Rect area = r;
|
Common::Rect area = r;
|
||||||
area.clip(_screen.w, _screen.h);
|
area.clip(_screen.w, _screen.h);
|
||||||
|
|
||||||
ThemeItemTextData *q = new ThemeItemTextData(this, _texts[type], area, text, alignH, alignV, ellipsis, restoreBg, deltax);
|
ThemeItemTextData *q = new ThemeItemTextData(this, _texts[type], _textColors[color], area, text, alignH, alignV, ellipsis, restoreBg, deltax);
|
||||||
|
|
||||||
if (_buffering) {
|
if (_buffering) {
|
||||||
_screenQueue.push_back(q);
|
_screenQueue.push_back(q);
|
||||||
|
@ -823,7 +849,7 @@ void ThemeEngine::drawButton(const Common::Rect &r, const Common::String &str, W
|
||||||
dd = kDDButtonDisabled;
|
dd = kDDButtonDisabled;
|
||||||
|
|
||||||
queueDD(dd, r, 0, hints & WIDGET_CLEARBG);
|
queueDD(dd, r, 0, hints & WIDGET_CLEARBG);
|
||||||
queueDDText(getTextData(dd), r, str, false, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV);
|
queueDDText(getTextData(dd), getTextColor(dd), r, str, false, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThemeEngine::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) {
|
void ThemeEngine::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) {
|
||||||
|
@ -846,7 +872,6 @@ void ThemeEngine::drawCheckbox(const Common::Rect &r, const Common::String &str,
|
||||||
if (state == kStateDisabled)
|
if (state == kStateDisabled)
|
||||||
dd = kDDCheckboxDisabled;
|
dd = kDDCheckboxDisabled;
|
||||||
|
|
||||||
TextData td = (state == kStateHighlight) ? kTextDataHover : getTextData(dd);
|
|
||||||
const int checkBoxSize = MIN((int)r.height(), getFontHeight());
|
const int checkBoxSize = MIN((int)r.height(), getFontHeight());
|
||||||
|
|
||||||
r2.bottom = r2.top + checkBoxSize;
|
r2.bottom = r2.top + checkBoxSize;
|
||||||
|
@ -857,7 +882,7 @@ void ThemeEngine::drawCheckbox(const Common::Rect &r, const Common::String &str,
|
||||||
r2.left = r2.right + checkBoxSize;
|
r2.left = r2.right + checkBoxSize;
|
||||||
r2.right = r.right;
|
r2.right = r.right;
|
||||||
|
|
||||||
queueDDText(td, r2, str, false, false, _widgets[kDDCheckboxDefault]->_textAlignH, _widgets[dd]->_textAlignV);
|
queueDDText(getTextData(dd), getTextColor(dd), r2, str, false, false, _widgets[kDDCheckboxDefault]->_textAlignH, _widgets[dd]->_textAlignV);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThemeEngine::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) {
|
void ThemeEngine::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) {
|
||||||
|
@ -957,7 +982,7 @@ void ThemeEngine::drawPopUpWidget(const Common::Rect &r, const Common::String &s
|
||||||
|
|
||||||
if (!sel.empty()) {
|
if (!sel.empty()) {
|
||||||
Common::Rect text(r.left + 3, r.top + 1, r.right - 10, r.bottom);
|
Common::Rect text(r.left + 3, r.top + 1, r.right - 10, r.bottom);
|
||||||
queueDDText(getTextData(dd), text, sel, true, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV, deltax);
|
queueDDText(getTextData(dd), getTextColor(dd), text, sel, true, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV, deltax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -995,74 +1020,114 @@ void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, co
|
||||||
if (!ready())
|
if (!ready())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const int tabOffset = 2;
|
|
||||||
tabWidth -= tabOffset;
|
|
||||||
|
|
||||||
queueDD(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight));
|
queueDD(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight));
|
||||||
|
|
||||||
for (int i = 0; i < (int)tabs.size(); ++i) {
|
for (int i = 0; i < (int)tabs.size(); ++i) {
|
||||||
if (i == active)
|
if (i == active)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Common::Rect tabRect(r.left + i * (tabWidth + tabOffset), r.top, r.left + i * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight);
|
Common::Rect tabRect(r.left + i * tabWidth, r.top, r.left + (i + 1) * tabWidth, r.top + tabHeight);
|
||||||
queueDD(kDDTabInactive, tabRect);
|
queueDD(kDDTabInactive, tabRect);
|
||||||
queueDDText(getTextData(kDDTabInactive), tabRect, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV);
|
queueDDText(getTextData(kDDTabInactive), getTextColor(kDDTabInactive), tabRect, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (active >= 0) {
|
if (active >= 0) {
|
||||||
Common::Rect tabRect(r.left + active * (tabWidth + tabOffset), r.top, r.left + active * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight);
|
Common::Rect tabRect(r.left + active * tabWidth, r.top, r.left + (active + 1) * tabWidth, r.top + tabHeight);
|
||||||
const uint16 tabLeft = active * (tabWidth + tabOffset);
|
const uint16 tabLeft = active * tabWidth;
|
||||||
const uint16 tabRight = MAX(r.right - tabRect.right, 0);
|
const uint16 tabRight = MAX(r.right - tabRect.right, 0);
|
||||||
queueDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF));
|
queueDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF));
|
||||||
queueDDText(getTextData(kDDTabActive), tabRect, tabs[active], false, false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV);
|
queueDDText(getTextData(kDDTabActive), getTextColor(kDDTabActive), tabRect, tabs[active], false, false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) {
|
void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color) {
|
||||||
if (!ready())
|
if (!ready())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
TextColor colorId = kTextColorMAX;
|
||||||
|
|
||||||
|
switch (color) {
|
||||||
|
case kFontColorNormal:
|
||||||
if (inverted) {
|
if (inverted) {
|
||||||
queueDD(kDDTextSelectionBackground, r);
|
colorId = kTextColorNormalInverted;
|
||||||
queueDDText(kTextDataInverted, r, str, false, useEllipsis, align, kTextAlignVCenter, deltax);
|
} else {
|
||||||
|
switch (state) {
|
||||||
|
case kStateDisabled:
|
||||||
|
colorId = kTextColorNormalDisabled;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kStateHighlight:
|
||||||
|
colorId = kTextColorNormalHover;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kStateEnabled:
|
||||||
|
colorId = kTextColorNormal;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kFontColorAlternate:
|
||||||
|
if (inverted) {
|
||||||
|
colorId = kTextColorAlternativeInverted;
|
||||||
|
} else {
|
||||||
|
switch (state) {
|
||||||
|
case kStateDisabled:
|
||||||
|
colorId = kTextColorAlternativeDisabled;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kStateHighlight:
|
||||||
|
colorId = kTextColorAlternativeHover;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kStateEnabled:
|
||||||
|
colorId = kTextColorAlternative;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (font) {
|
TextData textId = kTextDataNone;
|
||||||
case kFontStyleNormal:
|
if (font == kFontStyleNormal)
|
||||||
queueDDText(kTextDataNormalFont, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax);
|
textId = kTextDataNormalFont;
|
||||||
return;
|
else
|
||||||
|
textId = kTextDataDefault;
|
||||||
|
|
||||||
|
bool restore = true;
|
||||||
|
|
||||||
|
switch (inverted) {
|
||||||
|
case kTextInversion:
|
||||||
|
queueDD(kDDTextSelectionBackground, r);
|
||||||
|
restore = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kTextInversionFocus:
|
||||||
|
queueDD(kDDTextSelectionFocusBackground, r);
|
||||||
|
restore = false;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (state) {
|
queueDDText(textId, colorId, r, str, restore, useEllipsis, align, kTextAlignVCenter, deltax);
|
||||||
case kStateDisabled:
|
|
||||||
queueDDText(kTextDataDisabled, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case kStateHighlight:
|
|
||||||
queueDDText(kTextDataHover, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case kStateEnabled:
|
|
||||||
queueDDText(kTextDataDefault, r, str, true, useEllipsis, align, kTextAlignVCenter, deltax);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThemeEngine::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state) {
|
void ThemeEngine::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state, FontColor color) {
|
||||||
if (!ready())
|
if (!ready())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Common::Rect charArea = r;
|
Common::Rect charArea = r;
|
||||||
charArea.clip(_screen.w, _screen.h);
|
charArea.clip(_screen.w, _screen.h);
|
||||||
|
|
||||||
uint32 color = _overlayFormat.RGBToColor(_texts[kTextDataDefault]->_color.r, _texts[kTextDataDefault]->_color.g, _texts[kTextDataDefault]->_color.b);
|
uint32 rgbColor = _overlayFormat.RGBToColor(_textColors[color]->r, _textColors[color]->g, _textColors[color]->b);
|
||||||
|
|
||||||
restoreBackground(charArea);
|
restoreBackground(charArea);
|
||||||
font->drawChar(&_screen, ch, charArea.left, charArea.top, color);
|
font->drawChar(&_screen, ch, charArea.left, charArea.top, rgbColor);
|
||||||
addDirtyRect(charArea);
|
addDirtyRect(charArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1161,6 +1226,78 @@ void ThemeEngine::openDialog(bool doBuffer, ShadingStyle style) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int hotspotY, int scale) {
|
bool ThemeEngine::createCursor(const Common::String &filename, int hotspotX, int hotspotY, int scale) {
|
||||||
|
return true; // Residual doesn's support cursor palette mode
|
||||||
|
|
||||||
|
// Try to locate the specified file among all loaded bitmaps
|
||||||
|
const Graphics::Surface *cursor = _bitmaps[filename];
|
||||||
|
if (!cursor)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#ifdef USE_RGB_COLOR
|
||||||
|
_cursorFormat.bytesPerPixel = 1;
|
||||||
|
_cursorFormat.rLoss = _cursorFormat.gLoss = _cursorFormat.bLoss = _cursorFormat.aLoss = 8;
|
||||||
|
_cursorFormat.rShift = _cursorFormat.gShift = _cursorFormat.bShift = _cursorFormat.aShift = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set up the cursor parameters
|
||||||
|
_cursorHotspotX = hotspotX;
|
||||||
|
_cursorHotspotY = hotspotY;
|
||||||
|
_cursorTargetScale = scale;
|
||||||
|
|
||||||
|
_cursorWidth = cursor->w;
|
||||||
|
_cursorHeight = cursor->h;
|
||||||
|
|
||||||
|
// Allocate a new buffer for the cursor
|
||||||
|
delete[] _cursor;
|
||||||
|
_cursor = new byte[_cursorWidth * _cursorHeight];
|
||||||
|
assert(_cursor);
|
||||||
|
memset(_cursor, 0xFF, sizeof(byte) * _cursorWidth * _cursorHeight);
|
||||||
|
|
||||||
|
// the transparent color is 0xFF00FF
|
||||||
|
const int colTransparent = _overlayFormat.RGBToColor(0xFF, 0, 0xFF);
|
||||||
|
|
||||||
|
// Now, scan the bitmap. We have to convert it from 16 bit color mode
|
||||||
|
// to 8 bit mode, and have to create a suitable palette on the fly.
|
||||||
|
uint colorsFound = 0;
|
||||||
|
Common::HashMap<int, int> colorToIndex;
|
||||||
|
const OverlayColor *src = (const OverlayColor*)cursor->pixels;
|
||||||
|
for (uint y = 0; y < _cursorHeight; ++y) {
|
||||||
|
for (uint x = 0; x < _cursorWidth; ++x) {
|
||||||
|
byte r, g, b;
|
||||||
|
|
||||||
|
// Skip transparency
|
||||||
|
if (src[x] == colTransparent)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_overlayFormat.colorToRGB(src[x], r, g, b);
|
||||||
|
const int col = (r << 16) | (g << 8) | b;
|
||||||
|
|
||||||
|
// If there is no entry yet for this color in the palette: Add one
|
||||||
|
if (!colorToIndex.contains(col)) {
|
||||||
|
const int index = colorsFound++;
|
||||||
|
colorToIndex[col] = index;
|
||||||
|
|
||||||
|
_cursorPal[index * 4 + 0] = r;
|
||||||
|
_cursorPal[index * 4 + 1] = g;
|
||||||
|
_cursorPal[index * 4 + 2] = b;
|
||||||
|
_cursorPal[index * 4 + 3] = 0xFF;
|
||||||
|
|
||||||
|
if (colorsFound > MAX_CURS_COLORS) {
|
||||||
|
warning("Cursor contains too many colors (%d, but only %d are allowed)", colorsFound, MAX_CURS_COLORS);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy pixel from the 16 bit source surface to the 8bit target surface
|
||||||
|
const int index = colorToIndex[col];
|
||||||
|
_cursor[y * _cursorWidth + x] = index;
|
||||||
|
}
|
||||||
|
src += _cursorWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
_useCursor = true;
|
||||||
|
_cursorPalSize = colorsFound;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1189,6 +1326,9 @@ TextData ThemeEngine::getTextData(DrawData ddId) const {
|
||||||
return _widgets[ddId] ? (TextData)_widgets[ddId]->_textDataId : kTextDataNone;
|
return _widgets[ddId] ? (TextData)_widgets[ddId]->_textDataId : kTextDataNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextColor ThemeEngine::getTextColor(DrawData ddId) const {
|
||||||
|
return _widgets[ddId] ? _widgets[ddId]->_textColorId : kTextColorMAX;
|
||||||
|
}
|
||||||
|
|
||||||
DrawData ThemeEngine::parseDrawDataId(const Common::String &name) const {
|
DrawData ThemeEngine::parseDrawDataId(const Common::String &name) const {
|
||||||
for (int i = 0; i < kDrawDataMAX; ++i)
|
for (int i = 0; i < kDrawDataMAX; ++i)
|
||||||
|
@ -1287,7 +1427,7 @@ bool ThemeEngine::themeConfigParseHeader(Common::String header, Common::String &
|
||||||
|
|
||||||
Common::StringTokenizer tok(header, ":");
|
Common::StringTokenizer tok(header, ":");
|
||||||
|
|
||||||
if (tok.nextToken() != SCUMMVM_THEME_VERSION_STR)
|
if (tok.nextToken() != RESIDUAL_THEME_VERSION_STR)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
themeName = tok.nextToken();
|
themeName = tok.nextToken();
|
||||||
|
@ -1383,7 +1523,7 @@ void ThemeEngine::listUsableThemes(Common::List<ThemeDescriptor> &list) {
|
||||||
output.clear();
|
output.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThemeEngine::listUsableThemes(Common::FSNode node, Common::List<ThemeDescriptor> &list, int depth) {
|
void ThemeEngine::listUsableThemes(const Common::FSNode &node, Common::List<ThemeDescriptor> &list, int depth) {
|
||||||
if (!node.exists() || !node.isReadable() || !node.isDirectory())
|
if (!node.exists() || !node.isReadable() || !node.isDirectory())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include "graphics/surface.h"
|
#include "graphics/surface.h"
|
||||||
#include "graphics/fontman.h"
|
#include "graphics/fontman.h"
|
||||||
|
|
||||||
#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.5"
|
#define RESIDUAL_THEME_VERSION_STR "RESIDUAL_STX0.8"
|
||||||
|
|
||||||
namespace Graphics {
|
namespace Graphics {
|
||||||
struct DrawStep;
|
struct DrawStep;
|
||||||
|
@ -45,6 +45,7 @@ struct WidgetDrawData;
|
||||||
struct DrawDataInfo;
|
struct DrawDataInfo;
|
||||||
struct TextDataInfo;
|
struct TextDataInfo;
|
||||||
struct TextDrawData;
|
struct TextDrawData;
|
||||||
|
struct TextColorData;
|
||||||
class Dialog;
|
class Dialog;
|
||||||
class GuiObject;
|
class GuiObject;
|
||||||
class ThemeEval;
|
class ThemeEval;
|
||||||
|
@ -62,6 +63,7 @@ enum DrawData {
|
||||||
kDDPlainColorBackground,
|
kDDPlainColorBackground,
|
||||||
kDDDefaultBackground,
|
kDDDefaultBackground,
|
||||||
kDDTextSelectionBackground,
|
kDDTextSelectionBackground,
|
||||||
|
kDDTextSelectionFocusBackground,
|
||||||
|
|
||||||
kDDWidgetBackgroundDefault,
|
kDDWidgetBackgroundDefault,
|
||||||
kDDWidgetBackgroundSmall,
|
kDDWidgetBackgroundSmall,
|
||||||
|
@ -104,15 +106,26 @@ enum DrawData {
|
||||||
enum TextData {
|
enum TextData {
|
||||||
kTextDataNone = -1,
|
kTextDataNone = -1,
|
||||||
kTextDataDefault = 0,
|
kTextDataDefault = 0,
|
||||||
kTextDataHover,
|
|
||||||
kTextDataDisabled,
|
|
||||||
kTextDataInverted,
|
|
||||||
kTextDataButton,
|
kTextDataButton,
|
||||||
kTextDataButtonHover,
|
|
||||||
kTextDataNormalFont,
|
kTextDataNormalFont,
|
||||||
kTextDataMAX
|
kTextDataMAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum TextColor {
|
||||||
|
kTextColorNormal = 0,
|
||||||
|
kTextColorNormalInverted,
|
||||||
|
kTextColorNormalHover,
|
||||||
|
kTextColorNormalDisabled,
|
||||||
|
kTextColorAlternative,
|
||||||
|
kTextColorAlternativeInverted,
|
||||||
|
kTextColorAlternativeHover,
|
||||||
|
kTextColorAlternativeDisabled,
|
||||||
|
kTextColorButton,
|
||||||
|
kTextColorButtonHover,
|
||||||
|
kTextColorButtonDisabled,
|
||||||
|
kTextColorMAX
|
||||||
|
};
|
||||||
|
|
||||||
class ThemeEngine {
|
class ThemeEngine {
|
||||||
protected:
|
protected:
|
||||||
typedef Common::HashMap<Common::String, Graphics::Surface*> ImagesMap;
|
typedef Common::HashMap<Common::String, Graphics::Surface*> ImagesMap;
|
||||||
|
@ -156,6 +169,13 @@ public:
|
||||||
|
|
||||||
typedef State WidgetStateInfo;
|
typedef State WidgetStateInfo;
|
||||||
|
|
||||||
|
//! Text inversion state of the text to be draw
|
||||||
|
enum TextInversionState {
|
||||||
|
kTextInversionNone, //!< Indicates that the text should not be drawn inverted
|
||||||
|
kTextInversion, //!< Indicates that the text should be drawn inverted, but not focused
|
||||||
|
kTextInversionFocus //!< Indicates thte the test should be drawn inverted, and focused
|
||||||
|
};
|
||||||
|
|
||||||
enum ScrollbarState {
|
enum ScrollbarState {
|
||||||
kScrollbarStateNo,
|
kScrollbarStateNo,
|
||||||
kScrollbarStateUp,
|
kScrollbarStateUp,
|
||||||
|
@ -175,6 +195,13 @@ public:
|
||||||
kFontStyleMax
|
kFontStyleMax
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! Font color selector
|
||||||
|
enum FontColor {
|
||||||
|
kFontColorNormal = 0, //!< The default color of the theme
|
||||||
|
kFontColorAlternate = 1, //!< Alternative font color
|
||||||
|
kFontColorMax
|
||||||
|
};
|
||||||
|
|
||||||
//! Function used to process areas other than the current dialog
|
//! Function used to process areas other than the current dialog
|
||||||
enum ShadingStyle {
|
enum ShadingStyle {
|
||||||
kShadingNone, //!< No special post processing
|
kShadingNone, //!< No special post processing
|
||||||
|
@ -302,9 +329,9 @@ public:
|
||||||
|
|
||||||
void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state = kStateEnabled);
|
void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state = kStateEnabled);
|
||||||
|
|
||||||
void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, bool inverted = false, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold);
|
void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal);
|
||||||
|
|
||||||
void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state = kStateEnabled);
|
void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state = kStateEnabled, FontColor color = kFontColorNormal);
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
@ -332,6 +359,7 @@ public:
|
||||||
DrawData parseDrawDataId(const Common::String &name) const;
|
DrawData parseDrawDataId(const Common::String &name) const;
|
||||||
|
|
||||||
TextData getTextData(DrawData ddId) const;
|
TextData getTextData(DrawData ddId) const;
|
||||||
|
TextColor getTextColor(DrawData ddId) const;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -363,9 +391,16 @@ public:
|
||||||
*
|
*
|
||||||
* @param fontName Identifier name for the font.
|
* @param fontName Identifier name for the font.
|
||||||
* @param file Name of the font file.
|
* @param file Name of the font file.
|
||||||
|
*/
|
||||||
|
bool addFont(TextData textId, const Common::String &file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for the ThemeParser class: adds a text color value.
|
||||||
|
*
|
||||||
|
* @param colorId Identifier for the color type.
|
||||||
* @param r, g, b Color of the font.
|
* @param r, g, b Color of the font.
|
||||||
*/
|
*/
|
||||||
bool addFont(TextData textId, const Common::String &file, int r, int g, int b);
|
bool addTextColor(TextColor colorId, int r, int g, int b);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -380,7 +415,7 @@ public:
|
||||||
* Adds a new TextStep from the ThemeParser. This will be deprecated/removed once the
|
* Adds a new TextStep from the ThemeParser. This will be deprecated/removed once the
|
||||||
* new Font API is in place. FIXME: Is that so ???
|
* new Font API is in place. FIXME: Is that so ???
|
||||||
*/
|
*/
|
||||||
bool addTextData(const Common::String &drawDataId, TextData textId, Graphics::TextAlign alignH, TextAlignVertical alignV);
|
bool addTextData(const Common::String &drawDataId, TextData textId, TextColor id, Graphics::TextAlign alignH, TextAlignVertical alignV);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
|
@ -503,7 +538,7 @@ protected:
|
||||||
* This function is called from all the Widget Drawing methods.
|
* This function is called from all the Widget Drawing methods.
|
||||||
*/
|
*/
|
||||||
void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0, bool restore = false);
|
void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0, bool restore = false);
|
||||||
void queueDDText(TextData type, const Common::Rect &r, const Common::String &text, bool restoreBg,
|
void queueDDText(TextData type, TextColor color, const Common::Rect &r, const Common::String &text, bool restoreBg,
|
||||||
bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0);
|
bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0);
|
||||||
void queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha);
|
void queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha);
|
||||||
|
|
||||||
|
@ -529,7 +564,7 @@ private:
|
||||||
|
|
||||||
static Common::String getThemeFile(const Common::String &id);
|
static Common::String getThemeFile(const Common::String &id);
|
||||||
static Common::String getThemeId(const Common::String &filename);
|
static Common::String getThemeId(const Common::String &filename);
|
||||||
static void listUsableThemes(Common::FSNode node, Common::List<ThemeDescriptor> &list, int depth=-1);
|
static void listUsableThemes(const Common::FSNode &node, Common::List<ThemeDescriptor> &list, int depth = -1);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
OSystem *_system; /** Global system object. */
|
OSystem *_system; /** Global system object. */
|
||||||
|
@ -572,8 +607,14 @@ protected:
|
||||||
/** Array of all the text fonts that can be drawn. */
|
/** Array of all the text fonts that can be drawn. */
|
||||||
TextDrawData *_texts[kTextDataMAX];
|
TextDrawData *_texts[kTextDataMAX];
|
||||||
|
|
||||||
|
/** Array of all font colors available. */
|
||||||
|
TextColorData *_textColors[kTextColorMAX];
|
||||||
|
|
||||||
ImagesMap _bitmaps;
|
ImagesMap _bitmaps;
|
||||||
Graphics::PixelFormat _overlayFormat;
|
Graphics::PixelFormat _overlayFormat;
|
||||||
|
#ifdef USE_RGB_COLOR
|
||||||
|
Graphics::PixelFormat _cursorFormat;
|
||||||
|
#endif
|
||||||
|
|
||||||
/** List of all the dirty screens that must be blitted to the overlay. */
|
/** List of all the dirty screens that must be blitted to the overlay. */
|
||||||
Common::List<Common::Rect> _dirtyScreen;
|
Common::List<Common::Rect> _dirtyScreen;
|
||||||
|
|
|
@ -23,17 +23,11 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common/util.h"
|
|
||||||
#include "common/system.h"
|
|
||||||
#include "common/events.h"
|
|
||||||
#include "common/hashmap.h"
|
|
||||||
#include "common/hash-str.h"
|
|
||||||
#include "common/xmlparser.h"
|
|
||||||
|
|
||||||
#include "gui/ThemeEngine.h"
|
#include "gui/ThemeEngine.h"
|
||||||
#include "gui/ThemeEval.h"
|
#include "gui/ThemeEval.h"
|
||||||
#include "gui/ThemeParser.h"
|
#include "gui/ThemeParser.h"
|
||||||
#include "gui/GuiManager.h"
|
#include "gui/GuiManager.h"
|
||||||
|
|
||||||
#include "graphics/VectorRenderer.h"
|
#include "graphics/VectorRenderer.h"
|
||||||
|
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
@ -45,11 +39,7 @@ struct TextDataInfo {
|
||||||
|
|
||||||
static const TextDataInfo kTextDataDefaults[] = {
|
static const TextDataInfo kTextDataDefaults[] = {
|
||||||
{ kTextDataDefault, "text_default" },
|
{ kTextDataDefault, "text_default" },
|
||||||
{kTextDataHover, "text_hover"},
|
|
||||||
{kTextDataDisabled, "text_disabled"},
|
|
||||||
{kTextDataInverted, "text_inverted"},
|
|
||||||
{ kTextDataButton, "text_button" },
|
{ kTextDataButton, "text_button" },
|
||||||
{kTextDataButtonHover, "text_button_hover"},
|
|
||||||
{ kTextDataNormalFont, "text_normal" }
|
{ kTextDataNormalFont, "text_normal" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,6 +52,33 @@ static TextData parseTextDataId(const Common::String &name) {
|
||||||
return kTextDataNone;
|
return kTextDataNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TextColorDataInfo {
|
||||||
|
TextColor id;
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const TextColorDataInfo kTextColorDefaults[] = {
|
||||||
|
{ kTextColorNormal, "color_normal" },
|
||||||
|
{ kTextColorNormalInverted, "color_normal_inverted" },
|
||||||
|
{ kTextColorNormalHover, "color_normal_hover" },
|
||||||
|
{ kTextColorNormalDisabled, "color_normal_disabled" },
|
||||||
|
{ kTextColorAlternative, "color_alternative" },
|
||||||
|
{ kTextColorAlternativeInverted, "color_alternative_inverted" },
|
||||||
|
{ kTextColorAlternativeHover, "color_alternative_hover" },
|
||||||
|
{ kTextColorAlternativeDisabled, "color_alternative_disabled" },
|
||||||
|
{ kTextColorButton, "color_button" },
|
||||||
|
{ kTextColorButtonHover, "color_button_hover" },
|
||||||
|
{ kTextColorButtonDisabled, "color_button_disabled" }
|
||||||
|
};
|
||||||
|
|
||||||
|
static TextColor parseTextColorId(const Common::String &name) {
|
||||||
|
for (int i = 0; i < kTextColorMAX; ++i)
|
||||||
|
if (name.compareToIgnoreCase(kTextColorDefaults[i].name) == 0)
|
||||||
|
return kTextColorDefaults[i].id;
|
||||||
|
|
||||||
|
return kTextColorMAX;
|
||||||
|
}
|
||||||
|
|
||||||
static Graphics::TextAlign parseTextHAlign(const Common::String &val) {
|
static Graphics::TextAlign parseTextHAlign(const Common::String &val) {
|
||||||
if (val == "left")
|
if (val == "left")
|
||||||
return Graphics::kTextAlignLeft;
|
return Graphics::kTextAlignLeft;
|
||||||
|
@ -86,19 +103,6 @@ static GUI::ThemeEngine::TextAlignVertical parseTextVAlign(const Common::String
|
||||||
|
|
||||||
|
|
||||||
ThemeParser::ThemeParser(ThemeEngine *parent) : XMLParser() {
|
ThemeParser::ThemeParser(ThemeEngine *parent) : XMLParser() {
|
||||||
|
|
||||||
_drawFunctions["circle"] = &Graphics::VectorRenderer::drawCallback_CIRCLE;
|
|
||||||
_drawFunctions["square"] = &Graphics::VectorRenderer::drawCallback_SQUARE;
|
|
||||||
_drawFunctions["roundedsq"] = &Graphics::VectorRenderer::drawCallback_ROUNDSQ;
|
|
||||||
_drawFunctions["bevelsq"] = &Graphics::VectorRenderer::drawCallback_BEVELSQ;
|
|
||||||
_drawFunctions["line"] = &Graphics::VectorRenderer::drawCallback_LINE;
|
|
||||||
_drawFunctions["triangle"] = &Graphics::VectorRenderer::drawCallback_TRIANGLE;
|
|
||||||
_drawFunctions["fill"] = &Graphics::VectorRenderer::drawCallback_FILLSURFACE;
|
|
||||||
_drawFunctions["tab"] = &Graphics::VectorRenderer::drawCallback_TAB;
|
|
||||||
_drawFunctions["void"] = &Graphics::VectorRenderer::drawCallback_VOID;
|
|
||||||
_drawFunctions["bitmap"] = &Graphics::VectorRenderer::drawCallback_BITMAP;
|
|
||||||
_drawFunctions["cross"] = &Graphics::VectorRenderer::drawCallback_CROSS;
|
|
||||||
|
|
||||||
_defaultStepGlobal = defaultDrawStep();
|
_defaultStepGlobal = defaultDrawStep();
|
||||||
_defaultStepLocal = 0;
|
_defaultStepLocal = 0;
|
||||||
_theme = parent;
|
_theme = parent;
|
||||||
|
@ -107,8 +111,6 @@ ThemeParser::ThemeParser(ThemeEngine *parent) : XMLParser() {
|
||||||
ThemeParser::~ThemeParser() {
|
ThemeParser::~ThemeParser() {
|
||||||
delete _defaultStepGlobal;
|
delete _defaultStepGlobal;
|
||||||
delete _defaultStepLocal;
|
delete _defaultStepLocal;
|
||||||
_palette.clear();
|
|
||||||
_drawFunctions.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThemeParser::cleanup() {
|
void ThemeParser::cleanup() {
|
||||||
|
@ -169,21 +171,32 @@ bool ThemeParser::parserCallback_defaults(ParserNode *node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ThemeParser::parserCallback_font(ParserNode *node) {
|
bool ThemeParser::parserCallback_font(ParserNode *node) {
|
||||||
int red, green, blue;
|
|
||||||
|
|
||||||
if (resolutionCheck(node->values["resolution"]) == false) {
|
if (resolutionCheck(node->values["resolution"]) == false) {
|
||||||
node->ignore = true;
|
node->ignore = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextData textDataId = parseTextDataId(node->values["id"]);
|
||||||
|
if (!_theme->addFont(textDataId, node->values["file"]))
|
||||||
|
return parserError("Error loading Font in theme engine.");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ThemeParser::parserCallback_text_color(ParserNode *node) {
|
||||||
|
int red, green, blue;
|
||||||
|
|
||||||
|
TextColor colorId = parseTextColorId(node->values["id"]);
|
||||||
|
if (colorId == kTextColorMAX)
|
||||||
|
return parserError("Error text color is not defined.");
|
||||||
|
|
||||||
if (_palette.contains(node->values["color"]))
|
if (_palette.contains(node->values["color"]))
|
||||||
getPaletteColor(node->values["color"], red, green, blue);
|
getPaletteColor(node->values["color"], red, green, blue);
|
||||||
else if (!parseIntegerKey(node->values["color"].c_str(), 3, &red, &green, &blue))
|
else if (!parseIntegerKey(node->values["color"].c_str(), 3, &red, &green, &blue))
|
||||||
return parserError("Error parsing color value for font definition.");
|
return parserError("Error parsing color value for text color definition.");
|
||||||
|
|
||||||
TextData textDataId = parseTextDataId(node->values["id"]);
|
if (!_theme->addTextColor(colorId, red, green, blue))
|
||||||
if (!_theme->addFont(textDataId, node->values["file"], red, green, blue))
|
return parserError("Error while adding text color information.");
|
||||||
return parserError("Error loading Font in theme engine.");
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -236,8 +249,9 @@ bool ThemeParser::parserCallback_text(ParserNode *node) {
|
||||||
|
|
||||||
Common::String id = getParentNode(node)->values["id"];
|
Common::String id = getParentNode(node)->values["id"];
|
||||||
TextData textDataId = parseTextDataId(node->values["font"]);
|
TextData textDataId = parseTextDataId(node->values["font"]);
|
||||||
|
TextColor textColorId = parseTextColorId(node->values["text_color"]);
|
||||||
|
|
||||||
if (!_theme->addTextData(id, textDataId, alignH, alignV))
|
if (!_theme->addTextData(id, textDataId, textColorId, alignH, alignV))
|
||||||
return parserError("Error adding Text Data for '%s'.", id.c_str());
|
return parserError("Error adding Text Data for '%s'.", id.c_str());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -281,15 +295,44 @@ bool ThemeParser::parserCallback_color(ParserNode *node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Graphics::DrawingFunctionCallback getDrawingFunctionCallback(const Common::String &name) {
|
||||||
|
|
||||||
|
if (name == "circle")
|
||||||
|
return &Graphics::VectorRenderer::drawCallback_CIRCLE;
|
||||||
|
if (name == "square")
|
||||||
|
return &Graphics::VectorRenderer::drawCallback_SQUARE;
|
||||||
|
if (name == "roundedsq")
|
||||||
|
return &Graphics::VectorRenderer::drawCallback_ROUNDSQ;
|
||||||
|
if (name == "bevelsq")
|
||||||
|
return &Graphics::VectorRenderer::drawCallback_BEVELSQ;
|
||||||
|
if (name == "line")
|
||||||
|
return &Graphics::VectorRenderer::drawCallback_LINE;
|
||||||
|
if (name == "triangle")
|
||||||
|
return &Graphics::VectorRenderer::drawCallback_TRIANGLE;
|
||||||
|
if (name == "fill")
|
||||||
|
return &Graphics::VectorRenderer::drawCallback_FILLSURFACE;
|
||||||
|
if (name == "tab")
|
||||||
|
return &Graphics::VectorRenderer::drawCallback_TAB;
|
||||||
|
if (name == "void")
|
||||||
|
return &Graphics::VectorRenderer::drawCallback_VOID;
|
||||||
|
if (name == "bitmap")
|
||||||
|
return &Graphics::VectorRenderer::drawCallback_BITMAP;
|
||||||
|
if (name == "cross")
|
||||||
|
return &Graphics::VectorRenderer::drawCallback_CROSS;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ThemeParser::parserCallback_drawstep(ParserNode *node) {
|
bool ThemeParser::parserCallback_drawstep(ParserNode *node) {
|
||||||
Graphics::DrawStep *drawstep = newDrawStep();
|
Graphics::DrawStep *drawstep = newDrawStep();
|
||||||
|
|
||||||
Common::String functionName = node->values["func"];
|
Common::String functionName = node->values["func"];
|
||||||
|
|
||||||
if (_drawFunctions.contains(functionName) == false)
|
drawstep->drawingCall = getDrawingFunctionCallback(functionName);
|
||||||
return parserError("%s is not a valid drawing function name", functionName.c_str());
|
|
||||||
|
|
||||||
drawstep->drawingCall = _drawFunctions[functionName];
|
if (drawstep->drawingCall == 0)
|
||||||
|
return parserError("%s is not a valid drawing function name", functionName.c_str());
|
||||||
|
|
||||||
if (!parseDrawStep(node, drawstep, true))
|
if (!parseDrawStep(node, drawstep, true))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#define THEME_PARSER_H
|
#define THEME_PARSER_H
|
||||||
|
|
||||||
#include "common/sys.h"
|
#include "common/sys.h"
|
||||||
#include "common/system.h"
|
|
||||||
#include "common/xmlparser.h"
|
#include "common/xmlparser.h"
|
||||||
|
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
@ -35,8 +34,6 @@ namespace GUI {
|
||||||
class ThemeEngine;
|
class ThemeEngine;
|
||||||
|
|
||||||
class ThemeParser : public Common::XMLParser {
|
class ThemeParser : public Common::XMLParser {
|
||||||
typedef void (Graphics::VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const Graphics::DrawStep &);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ThemeParser(ThemeEngine *parent);
|
ThemeParser(ThemeEngine *parent);
|
||||||
|
|
||||||
|
@ -70,9 +67,13 @@ protected:
|
||||||
XML_KEY(font)
|
XML_KEY(font)
|
||||||
XML_PROP(id, true)
|
XML_PROP(id, true)
|
||||||
XML_PROP(file, true)
|
XML_PROP(file, true)
|
||||||
XML_PROP(color, true)
|
|
||||||
XML_PROP(resolution, false)
|
XML_PROP(resolution, false)
|
||||||
KEY_END()
|
KEY_END()
|
||||||
|
|
||||||
|
XML_KEY(text_color)
|
||||||
|
XML_PROP(id, true);
|
||||||
|
XML_PROP(color, true);
|
||||||
|
KEY_END()
|
||||||
KEY_END()
|
KEY_END()
|
||||||
|
|
||||||
XML_KEY(bitmaps)
|
XML_KEY(bitmaps)
|
||||||
|
@ -146,6 +147,7 @@ protected:
|
||||||
|
|
||||||
XML_KEY(text)
|
XML_KEY(text)
|
||||||
XML_PROP(font, true)
|
XML_PROP(font, true)
|
||||||
|
XML_PROP(text_color, true)
|
||||||
XML_PROP(vertical_align, true)
|
XML_PROP(vertical_align, true)
|
||||||
XML_PROP(horizontal_align, true)
|
XML_PROP(horizontal_align, true)
|
||||||
KEY_END()
|
KEY_END()
|
||||||
|
@ -214,6 +216,7 @@ protected:
|
||||||
bool parserCallback_render_info(ParserNode *node);
|
bool parserCallback_render_info(ParserNode *node);
|
||||||
bool parserCallback_defaults(ParserNode *node);
|
bool parserCallback_defaults(ParserNode *node);
|
||||||
bool parserCallback_font(ParserNode *node);
|
bool parserCallback_font(ParserNode *node);
|
||||||
|
bool parserCallback_text_color(ParserNode *node);
|
||||||
bool parserCallback_fonts(ParserNode *node);
|
bool parserCallback_fonts(ParserNode *node);
|
||||||
bool parserCallback_text(ParserNode *node);
|
bool parserCallback_text(ParserNode *node);
|
||||||
bool parserCallback_palette(ParserNode *node);
|
bool parserCallback_palette(ParserNode *node);
|
||||||
|
@ -249,8 +252,6 @@ protected:
|
||||||
Graphics::DrawStep *_defaultStepGlobal;
|
Graphics::DrawStep *_defaultStepGlobal;
|
||||||
Graphics::DrawStep *_defaultStepLocal;
|
Graphics::DrawStep *_defaultStepLocal;
|
||||||
|
|
||||||
Common::HashMap<Common::String, DrawingFunctionCallback, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _drawFunctions;
|
|
||||||
|
|
||||||
struct PaletteColor {
|
struct PaletteColor {
|
||||||
uint8 r, g, b;
|
uint8 r, g, b;
|
||||||
};
|
};
|
||||||
|
|
|
@ -247,7 +247,7 @@ void AboutDialog::drawDialog() {
|
||||||
str++;
|
str++;
|
||||||
|
|
||||||
if (*str && y > _y && y + g_gui.theme()->getFontHeight() < _y + _h)
|
if (*str && y > _y && y + g_gui.theme()->getFontHeight() < _y + _h)
|
||||||
g_gui.theme()->drawText(Common::Rect(_x + _xOff, y, _x + _w - _xOff, y + g_gui.theme()->getFontHeight()), str, state, align, false, 0, false);
|
g_gui.theme()->drawText(Common::Rect(_x + _xOff, y, _x + _w - _xOff, y + g_gui.theme()->getFontHeight()), str, state, align, ThemeEngine::kTextInversionNone, 0, false);
|
||||||
y += _lineHeight;
|
y += _lineHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ enum {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BrowserDialog::BrowserDialog(const char *title, bool dirBrowser)
|
BrowserDialog::BrowserDialog(const char *title, bool dirBrowser)
|
||||||
: Dialog("browser") {
|
: Dialog("Browser") {
|
||||||
_titleRef = CFStringCreateWithCString(0, title, CFStringGetSystemEncoding());
|
_titleRef = CFStringCreateWithCString(0, title, CFStringGetSystemEncoding());
|
||||||
_isDirBrowser = dirBrowser;
|
_isDirBrowser = dirBrowser;
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,7 @@ void ConsoleDialog::init() {
|
||||||
|
|
||||||
_w = _w - _w / 20;
|
_w = _w - _w / 20;
|
||||||
_h = _h * kConsoleLineHeight + 2;
|
_h = _h * kConsoleLineHeight + 2;
|
||||||
|
_x = _w / 40;
|
||||||
|
|
||||||
// Set scrollbar dimensions
|
// Set scrollbar dimensions
|
||||||
int scrollBarWidth = g_gui.xmlEval()->getVar("Globals.Scrollbar.Width", 0);
|
int scrollBarWidth = g_gui.xmlEval()->getVar("Globals.Scrollbar.Width", 0);
|
||||||
|
@ -149,8 +150,8 @@ void ConsoleDialog::open() {
|
||||||
if (_w != w || _h != h)
|
if (_w != w || _h != h)
|
||||||
init();
|
init();
|
||||||
|
|
||||||
_x = _w / 40;
|
|
||||||
_y = -_h;
|
_y = -_h;
|
||||||
|
|
||||||
_slideTime = g_system->getMillis();
|
_slideTime = g_system->getMillis();
|
||||||
_slideMode = kDownSlideMode;
|
_slideMode = kDownSlideMode;
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,7 @@ public:
|
||||||
void handleKeyDown(Common::KeyState state);
|
void handleKeyDown(Common::KeyState state);
|
||||||
void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
|
void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
|
||||||
|
|
||||||
int printf(const char *format, ...);
|
int printf(const char *format, ...) GCC_PRINTF(2, 3);
|
||||||
int vprintf(const char *format, va_list argptr);
|
int vprintf(const char *format, va_list argptr);
|
||||||
#undef putchar
|
#undef putchar
|
||||||
void putchar(int c);
|
void putchar(int c);
|
||||||
|
|
|
@ -27,10 +27,14 @@
|
||||||
#include "common/system.h"
|
#include "common/system.h"
|
||||||
|
|
||||||
#include "gui/debugger.h"
|
#include "gui/debugger.h"
|
||||||
#if USE_CONSOLE
|
#ifndef USE_TEXT_CONSOLE
|
||||||
#include "gui/console.h"
|
#include "gui/console.h"
|
||||||
|
#elif defined(USE_READLINE)
|
||||||
|
#include <readline/readline.h>
|
||||||
|
#include <readline/history.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
Debugger::Debugger() {
|
Debugger::Debugger() {
|
||||||
|
@ -39,9 +43,11 @@ Debugger::Debugger() {
|
||||||
_isAttached = false;
|
_isAttached = false;
|
||||||
_errStr = NULL;
|
_errStr = NULL;
|
||||||
_firstTime = true;
|
_firstTime = true;
|
||||||
_debuggerDialog = new GUI::ConsoleDialog(1.0, 0.67F);
|
#ifndef USE_TEXT_CONSOLE
|
||||||
|
_debuggerDialog = new GUI::ConsoleDialog(1.0f, 0.67f);
|
||||||
_debuggerDialog->setInputCallback(debuggerInputCallback, this);
|
_debuggerDialog->setInputCallback(debuggerInputCallback, this);
|
||||||
_debuggerDialog->setCompletionCallback(debuggerCompletionCallback, this);
|
_debuggerDialog->setCompletionCallback(debuggerCompletionCallback, this);
|
||||||
|
#endif
|
||||||
|
|
||||||
//DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
|
//DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
|
||||||
DCmd_Register("exit", WRAP_METHOD(Debugger, Cmd_Exit));
|
DCmd_Register("exit", WRAP_METHOD(Debugger, Cmd_Exit));
|
||||||
|
@ -55,7 +61,9 @@ Debugger::Debugger() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Debugger::~Debugger() {
|
Debugger::~Debugger() {
|
||||||
|
#ifndef USE_TEXT_CONSOLE
|
||||||
delete _debuggerDialog;
|
delete _debuggerDialog;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,7 +73,7 @@ int Debugger::DebugPrintf(const char *format, ...) {
|
||||||
|
|
||||||
va_start(argptr, format);
|
va_start(argptr, format);
|
||||||
int count;
|
int count;
|
||||||
#if USE_CONSOLE
|
#ifndef USE_TEXT_CONSOLE
|
||||||
count = _debuggerDialog->vprintf(format, argptr);
|
count = _debuggerDialog->vprintf(format, argptr);
|
||||||
#else
|
#else
|
||||||
count = ::vprintf(format, argptr);
|
count = ::vprintf(format, argptr);
|
||||||
|
@ -112,9 +120,22 @@ void Debugger::onFrame() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(USE_TEXT_CONSOLE) && defined(USE_READLINE)
|
||||||
|
namespace {
|
||||||
|
Debugger *g_readline_debugger;
|
||||||
|
|
||||||
|
char *readline_completionFunction(const char *text, int state) {
|
||||||
|
return g_readline_debugger->readlineComplete(text, state);
|
||||||
|
}
|
||||||
|
} // end of anonymous namespace
|
||||||
|
#endif
|
||||||
|
|
||||||
// Main Debugger Loop
|
// Main Debugger Loop
|
||||||
void Debugger::enter() {
|
void Debugger::enter() {
|
||||||
#if USE_CONSOLE
|
// TODO: Having three I/O methods #ifdef-ed in this file is not the
|
||||||
|
// cleanest approach to this...
|
||||||
|
|
||||||
|
#ifndef USE_TEXT_CONSOLE
|
||||||
if (_firstTime) {
|
if (_firstTime) {
|
||||||
DebugPrintf("Debugger started, type 'exit' to return to the game.\n");
|
DebugPrintf("Debugger started, type 'exit' to return to the game.\n");
|
||||||
DebugPrintf("Type 'help' to see a little list of commands and variables.\n");
|
DebugPrintf("Type 'help' to see a little list of commands and variables.\n");
|
||||||
|
@ -129,18 +150,28 @@ void Debugger::enter() {
|
||||||
|
|
||||||
_debuggerDialog->runModal();
|
_debuggerDialog->runModal();
|
||||||
#else
|
#else
|
||||||
// TODO: compared to the console input, this here is very bare bone.
|
|
||||||
// For example, no support for tab completion and no history. At least
|
|
||||||
// we should re-add (optional) support for the readline library.
|
|
||||||
// Or maybe instead of choosing between a console dialog and stdio,
|
|
||||||
// we should move that choice into the ConsoleDialog class - that is,
|
|
||||||
// the console dialog code could be #ifdef'ed to not print to the dialog
|
|
||||||
// but rather to stdio. This way, we could also reuse the command history
|
|
||||||
// and tab completion of the console. It would still require a lot of
|
|
||||||
// work, but at least no dependency on a 3rd party library...
|
|
||||||
|
|
||||||
printf("Debugger entered, please switch to this console for input.\n");
|
printf("Debugger entered, please switch to this console for input.\n");
|
||||||
|
|
||||||
|
#ifdef USE_READLINE
|
||||||
|
// TODO: add support for saving/loading history?
|
||||||
|
|
||||||
|
g_readline_debugger = this;
|
||||||
|
rl_completion_entry_function = &readline_completionFunction;
|
||||||
|
|
||||||
|
char *line_read = 0;
|
||||||
|
do {
|
||||||
|
free(line_read);
|
||||||
|
line_read = readline("debug> ");
|
||||||
|
|
||||||
|
if (line_read && line_read[0])
|
||||||
|
add_history(line_read);
|
||||||
|
|
||||||
|
} while (line_read && parseCommand(line_read));
|
||||||
|
|
||||||
|
free(line_read);
|
||||||
|
line_read = 0;
|
||||||
|
|
||||||
|
#else
|
||||||
int i;
|
int i;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
|
|
||||||
|
@ -156,6 +187,7 @@ void Debugger::enter() {
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
continue;
|
continue;
|
||||||
} while (parseCommand(buf));
|
} while (parseCommand(buf));
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -211,7 +243,7 @@ bool Debugger::parseCommand(const char *inputOrig) {
|
||||||
break;
|
break;
|
||||||
// Integer Array
|
// Integer Array
|
||||||
case DVAR_INTARRAY: {
|
case DVAR_INTARRAY: {
|
||||||
char *chr = (char *)strchr(param[0], '[');
|
const char *chr = strchr(param[0], '[');
|
||||||
if (!chr) {
|
if (!chr) {
|
||||||
DebugPrintf("You must access this array as %s[element]\n", param[0]);
|
DebugPrintf("You must access this array as %s[element]\n", param[0]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -307,7 +339,8 @@ bool Debugger::tabComplete(const char *input, Common::String &completion) const
|
||||||
} else {
|
} else {
|
||||||
// take common prefix of previous match and this command
|
// take common prefix of previous match and this command
|
||||||
for (uint j = 0; j < completion.size(); j++) {
|
for (uint j = 0; j < completion.size(); j++) {
|
||||||
if (completion[j] != i->_key[inputlen + j]) {
|
if (inputlen + j >= i->_key.size() ||
|
||||||
|
completion[j] != i->_key[inputlen + j]) {
|
||||||
completion = Common::String(completion.begin(), completion.begin() + j);
|
completion = Common::String(completion.begin(), completion.begin() + j);
|
||||||
// If there is no unambiguous completion, abort
|
// If there is no unambiguous completion, abort
|
||||||
if (completion.empty())
|
if (completion.empty())
|
||||||
|
@ -325,6 +358,29 @@ bool Debugger::tabComplete(const char *input, Common::String &completion) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(USE_TEXT_CONSOLE) && defined(USE_READLINE)
|
||||||
|
char *Debugger::readlineComplete(const char *input, int state) {
|
||||||
|
static CommandsMap::const_iterator iter;
|
||||||
|
|
||||||
|
// We assume that _cmds isn't changed between calls to readlineComplete,
|
||||||
|
// unless state is 0.
|
||||||
|
if (state == 0) {
|
||||||
|
iter = _cmds.begin();
|
||||||
|
} else {
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; iter != _cmds.end(); ++iter) {
|
||||||
|
if (iter->_key.hasPrefix(input)) {
|
||||||
|
char *ret = (char *)malloc(iter->_key.size() + 1);
|
||||||
|
strcpy(ret, iter->_key.c_str());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Variable registration function
|
// Variable registration function
|
||||||
void Debugger::DVar_Register(const Common::String &varname, void *pointer, int type, int optional) {
|
void Debugger::DVar_Register(const Common::String &varname, void *pointer, int type, int optional) {
|
||||||
// TODO: Filter out duplicates
|
// TODO: Filter out duplicates
|
||||||
|
@ -356,8 +412,15 @@ bool Debugger::Cmd_Exit(int argc, const char **argv) {
|
||||||
// Print a list of all registered commands (and variables, if any),
|
// Print a list of all registered commands (and variables, if any),
|
||||||
// nicely word-wrapped.
|
// nicely word-wrapped.
|
||||||
bool Debugger::Cmd_Help(int argc, const char **argv) {
|
bool Debugger::Cmd_Help(int argc, const char **argv) {
|
||||||
|
#ifndef USE_TEXT_CONSOLE
|
||||||
const int charsPerLine = _debuggerDialog->getCharsPerLine();
|
const int charsPerLine = _debuggerDialog->getCharsPerLine();
|
||||||
|
#elif defined(USE_READLINE)
|
||||||
|
int charsPerLine, rows;
|
||||||
|
rl_get_screen_size(&rows, &charsPerLine);
|
||||||
|
#else
|
||||||
|
// Can we do better?
|
||||||
|
const int charsPerLine = 80;
|
||||||
|
#endif
|
||||||
int width, size;
|
int width, size;
|
||||||
uint i;
|
uint i;
|
||||||
|
|
||||||
|
@ -452,7 +515,7 @@ bool Debugger::Cmd_DebugFlagDisable(int argc, const char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Console handler
|
// Console handler
|
||||||
#if USE_CONSOLE
|
#ifndef USE_TEXT_CONSOLE
|
||||||
bool Debugger::debuggerInputCallback(GUI::ConsoleDialog *console, const char *input, void *refCon) {
|
bool Debugger::debuggerInputCallback(GUI::ConsoleDialog *console, const char *input, void *refCon) {
|
||||||
Debugger *debugger = (Debugger *)refCon;
|
Debugger *debugger = (Debugger *)refCon;
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,7 @@
|
||||||
|
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
// Choose between text console or ScummConsole
|
#ifndef USE_TEXT_CONSOLE
|
||||||
#define USE_CONSOLE 1
|
|
||||||
|
|
||||||
#ifdef USE_CONSOLE
|
|
||||||
class ConsoleDialog;
|
class ConsoleDialog;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -86,7 +83,9 @@ private:
|
||||||
bool _isAttached;
|
bool _isAttached;
|
||||||
char *_errStr;
|
char *_errStr;
|
||||||
bool _firstTime;
|
bool _firstTime;
|
||||||
|
#ifndef USE_TEXT_CONSOLE
|
||||||
GUI::ConsoleDialog *_debuggerDialog;
|
GUI::ConsoleDialog *_debuggerDialog;
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Hook for subclasses: Called just before enter() is run
|
// Hook for subclasses: Called just before enter() is run
|
||||||
|
@ -118,11 +117,15 @@ protected:
|
||||||
bool Cmd_DebugFlagEnable(int argc, const char **argv);
|
bool Cmd_DebugFlagEnable(int argc, const char **argv);
|
||||||
bool Cmd_DebugFlagDisable(int argc, const char **argv);
|
bool Cmd_DebugFlagDisable(int argc, const char **argv);
|
||||||
|
|
||||||
#if USE_CONSOLE
|
#ifndef USE_TEXT_CONSOLE
|
||||||
private:
|
private:
|
||||||
static bool debuggerInputCallback(GUI::ConsoleDialog *console, const char *input, void *refCon);
|
static bool debuggerInputCallback(GUI::ConsoleDialog *console, const char *input, void *refCon);
|
||||||
static bool debuggerCompletionCallback(GUI::ConsoleDialog *console, const char *input, Common::String &completion, void *refCon);
|
static bool debuggerCompletionCallback(GUI::ConsoleDialog *console, const char *input, Common::String &completion, void *refCon);
|
||||||
|
#elif defined(USE_READLINE)
|
||||||
|
public:
|
||||||
|
char *readlineComplete(const char *input, int state);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace GUI
|
} // End of namespace GUI
|
||||||
|
|
|
@ -638,6 +638,10 @@ void LauncherDialog::updateListing() {
|
||||||
// Select the last entry if the list has been reduced
|
// Select the last entry if the list has been reduced
|
||||||
_list->setSelected(_list->getList().size() - 1);
|
_list->setSelected(_list->getList().size() - 1);
|
||||||
updateButtons();
|
updateButtons();
|
||||||
|
|
||||||
|
// Update the filter settings, those are lost when "setList"
|
||||||
|
// is called.
|
||||||
|
_list->setFilter(_searchWidget->getEditString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherDialog::addGame() {
|
void LauncherDialog::addGame() {
|
||||||
|
|
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