aboutsummaryrefslogtreecommitdiff
path: root/backends
diff options
context:
space:
mode:
Diffstat (limited to 'backends')
-rw-r--r--backends/events/default/default-events.cpp74
-rw-r--r--backends/events/default/default-events.h4
-rw-r--r--backends/fs/abstract-fs.cpp40
-rw-r--r--backends/fs/abstract-fs.h53
-rw-r--r--backends/fs/amigaos4/amigaos4-fs-factory.cpp4
-rw-r--r--backends/fs/amigaos4/amigaos4-fs-factory.h13
-rw-r--r--backends/fs/amigaos4/amigaos4-fs.cpp49
-rw-r--r--backends/fs/ds/ds-fs-factory.cpp2
-rw-r--r--backends/fs/ds/ds-fs-factory.h4
-rw-r--r--backends/fs/ds/ds-fs.cpp250
-rw-r--r--backends/fs/ds/ds-fs.h47
-rw-r--r--backends/fs/palmos/palmos-fs-factory.cpp2
-rw-r--r--backends/fs/palmos/palmos-fs-factory.h4
-rw-r--r--backends/fs/palmos/palmos-fs.cpp72
-rw-r--r--backends/fs/posix/posix-fs-factory.cpp11
-rw-r--r--backends/fs/posix/posix-fs-factory.h14
-rw-r--r--backends/fs/posix/posix-fs.cpp212
-rw-r--r--backends/fs/posix/posix-fs.h86
-rw-r--r--backends/fs/ps2/ps2-fs-factory.cpp2
-rw-r--r--backends/fs/ps2/ps2-fs-factory.h4
-rw-r--r--backends/fs/ps2/ps2-fs.cpp73
-rw-r--r--backends/fs/psp/psp-fs-factory.cpp2
-rw-r--r--backends/fs/psp/psp-fs-factory.h4
-rw-r--r--backends/fs/psp/psp-fs.cpp64
-rw-r--r--backends/fs/stdiostream.cpp161
-rw-r--r--backends/fs/stdiostream.h62
-rw-r--r--backends/fs/symbian/symbian-fs-factory.cpp4
-rw-r--r--backends/fs/symbian/symbian-fs-factory.h13
-rw-r--r--backends/fs/symbian/symbian-fs.cpp162
-rw-r--r--backends/fs/symbian/symbianstream.cpp274
-rw-r--r--backends/fs/symbian/symbianstream.h62
-rw-r--r--backends/fs/wii/wii-fs-factory.cpp2
-rw-r--r--backends/fs/wii/wii-fs-factory.h4
-rw-r--r--backends/fs/wii/wii-fs.cpp70
-rw-r--r--backends/fs/windows/windows-fs-factory.cpp4
-rw-r--r--backends/fs/windows/windows-fs-factory.h13
-rw-r--r--backends/fs/windows/windows-fs.cpp86
-rw-r--r--backends/midi/seq.cpp2
-rw-r--r--backends/midi/stmidi.cpp155
-rw-r--r--backends/module.mk3
-rw-r--r--backends/platform/dc/dc-fs.cpp79
-rw-r--r--backends/platform/dc/selector.cpp12
-rw-r--r--backends/platform/dc/vmsave.cpp26
-rw-r--r--backends/platform/ds/arm7/Makefile2
-rw-r--r--backends/platform/ds/arm7/source/main.cpp5
-rw-r--r--backends/platform/ds/arm9/dist/readme_ds.txt840
-rw-r--r--backends/platform/ds/arm9/makefile90
-rw-r--r--backends/platform/ds/arm9/source/blitters_arm.s137
-rw-r--r--backends/platform/ds/arm9/source/cdaudio.h2
-rw-r--r--backends/platform/ds/arm9/source/dsmain.cpp709
-rw-r--r--backends/platform/ds/arm9/source/dsmain.h13
-rw-r--r--backends/platform/ds/arm9/source/dsoptions.cpp283
-rw-r--r--backends/platform/ds/arm9/source/dsoptions.h13
-rw-r--r--backends/platform/ds/arm9/source/gbampsave.cpp43
-rw-r--r--backends/platform/ds/arm9/source/gbampsave.h8
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.cpp232
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.h26
-rw-r--r--backends/platform/ds/arm9/source/portdefs.h5
-rw-r--r--backends/platform/ds/arm9/source/ramsave.cpp30
-rw-r--r--backends/platform/ds/arm9/source/ramsave.h14
-rw-r--r--backends/platform/ds/arm9/source/touchkeyboard.cpp30
-rw-r--r--backends/platform/ds/arm9/source/touchkeyboard.h1
-rw-r--r--backends/platform/ds/logog.bmpbin0 -> 630 bytes
-rw-r--r--backends/platform/ds/makefile20
-rw-r--r--backends/platform/iphone/iphone_keyboard.m3
-rw-r--r--backends/platform/iphone/iphone_main.m13
-rw-r--r--backends/platform/iphone/iphone_video.m14
-rw-r--r--backends/platform/iphone/osys_iphone.cpp753
-rw-r--r--backends/platform/iphone/osys_iphone.h30
-rw-r--r--backends/platform/null/null.cpp29
-rw-r--r--backends/platform/ps2/rawsavefile.cpp13
-rw-r--r--backends/platform/ps2/rawsavefile.h3
-rw-r--r--backends/platform/ps2/savefile.cpp59
-rw-r--r--backends/platform/ps2/savefile.h37
-rw-r--r--backends/platform/psp/osys_psp.cpp15
-rw-r--r--backends/platform/psp/osys_psp_gu.cpp14
-rw-r--r--backends/platform/psp/portdefs.h1
-rw-r--r--backends/platform/psp/psp_main.cpp10
-rw-r--r--backends/platform/sdl/sdl.cpp146
-rw-r--r--backends/platform/sdl/sdl.h4
-rw-r--r--backends/platform/symbian/AdaptAllMMPs.pl16
-rw-r--r--backends/platform/symbian/BuildPackageUpload_AllVersions.pl10
-rw-r--r--backends/platform/symbian/BuildPackageUpload_LocalSettings.pl76
-rw-r--r--backends/platform/symbian/README12
-rw-r--r--backends/platform/symbian/S60/ScummVM_S60.mmp.in1
-rw-r--r--backends/platform/symbian/S60/scummvm-CVS-SymbianS60v1.pkg4
-rw-r--r--backends/platform/symbian/S60/scummvm-CVS-SymbianS60v2.pkg2
-rw-r--r--backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in1
-rw-r--r--backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg4
-rw-r--r--backends/platform/symbian/S80/ScummVM_S80.mmp.in1
-rw-r--r--backends/platform/symbian/S80/scummvm-CVS-SymbianS80.pkg2
-rw-r--r--backends/platform/symbian/S90/Scummvm_S90.mmp.in1
-rw-r--r--backends/platform/symbian/S90/scummvm-CVS-SymbianS90.pkg2
-rw-r--r--backends/platform/symbian/UIQ2/ScummVM_UIQ2.mmp.in1
-rw-r--r--backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2.pkg4
-rw-r--r--backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2_SE.pkg2
-rw-r--r--backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in1
-rw-r--r--backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg2
-rw-r--r--backends/platform/symbian/mmp/scummvm_base.mmp.in8
-rw-r--r--backends/platform/symbian/mmp/scummvm_tinsel.mmp.in56
-rw-r--r--backends/platform/symbian/src/SymbianActions.cpp2
-rw-r--r--backends/platform/symbian/src/SymbianOS.cpp292
-rw-r--r--backends/platform/symbian/src/SymbianOS.h11
-rw-r--r--backends/platform/symbian/src/main_features.inl92
-rw-r--r--backends/platform/symbian/src/portdefs.h44
-rw-r--r--backends/platform/symbian/src/vsnprintf.h668
-rw-r--r--backends/platform/wince/CEActionsPocket.cpp2
-rw-r--r--backends/platform/wince/CEActionsSmartphone.cpp2
-rw-r--r--backends/platform/wince/CELauncherDialog.cpp12
-rw-r--r--backends/platform/wince/CELauncherDialog.h2
-rw-r--r--backends/platform/wince/Makefile6
-rw-r--r--backends/platform/wince/README-WinCE.txt189
-rw-r--r--backends/platform/wince/wince-sdl.cpp13
-rw-r--r--backends/platform/wince/wince-sdl.h1
-rw-r--r--backends/saves/compressed/compressed-saves.cpp270
-rw-r--r--backends/saves/default/default-saves.cpp35
-rw-r--r--backends/saves/default/default-saves.h3
117 files changed, 5184 insertions, 2597 deletions
diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index 0caba25792..c503e6a536 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -93,7 +93,8 @@ DefaultEventManager::DefaultEventManager(OSystem *boss) :
_boss(boss),
_buttonState(0),
_modifierState(0),
- _shouldQuit(false) {
+ _shouldQuit(false),
+ _shouldRTL(false) {
assert(_boss);
@@ -200,6 +201,9 @@ DefaultEventManager::~DefaultEventManager() {
_boss->unlockMutex(_timeMutex);
_boss->unlockMutex(_recorderMutex);
+ if (!artificialEventQueue.empty())
+ artificialEventQueue.clear();
+
if (_playbackFile != NULL) {
delete _playbackFile;
}
@@ -349,7 +353,11 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
uint32 time = _boss->getMillis();
bool result;
- result = _boss->pollEvent(event);
+ if (!artificialEventQueue.empty()) {
+ event = artificialEventQueue.pop();
+ result = true;
+ } else
+ result = _boss->pollEvent(event);
if (_recordMode != kPassthrough) {
@@ -375,7 +383,6 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
switch (event.type) {
case Common::EVENT_KEYDOWN:
_modifierState = event.kbd.flags;
-
// init continuous event stream
// not done on PalmOS because keyboard is emulated and keyup is not generated
#if !defined(PALMOS_MODE)
@@ -384,7 +391,41 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
_currentKeyDown.flags = event.kbd.flags;
_keyRepeatTime = time + kKeyRepeatInitialDelay;
#endif
+ // Global Main Menu
+ // FIXME: F6 is not the best trigger, it conflicts with some games!!!
+ if (event.kbd.keycode == Common::KEYCODE_F6) {
+ if (g_engine && !g_engine->isPaused()) {
+ Common::Event menuEvent;
+ menuEvent.type = Common::EVENT_MAINMENU;
+
+ // FIXME: GSoC RTL branch passes the F6 key event to the
+ // engine, and also enqueues a EVENT_MAINMENU. For now,
+ // we just drop the key event and return an EVENT_MAINMENU
+ // instead. This way, we don't have to add special cases
+ // to engines (like it was the case for LURE in the RTL branch).
+ //
+ // However, this has other consequences, possibly negative ones.
+ // Like, what happens with key repeat for the trigger key?
+
+ //pushEvent(menuEvent);
+ event = menuEvent;
+
+ // FIXME: Since now we do not push another MAINMENU event onto
+ // our event stack, the GMM would never open, so we have to do
+ // that here. Of course when the engine would handle MAINMENU
+ // as an event now and open up the GMM itself it would open the
+ // menu twice.
+ if (g_engine && !g_engine->isPaused())
+ g_engine->mainMenuDialog();
+
+ if (_shouldQuit)
+ event.type = Common::EVENT_QUIT;
+ else if (_shouldRTL)
+ event.type = Common::EVENT_RTL;
+ }
+ }
break;
+
case Common::EVENT_KEYUP:
_modifierState = event.kbd.flags;
if (event.kbd.keycode == _currentKeyDown.keycode) {
@@ -401,6 +442,7 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
_mousePos = event.mouse;
_buttonState |= LBUTTON;
break;
+
case Common::EVENT_LBUTTONUP:
_mousePos = event.mouse;
_buttonState &= ~LBUTTON;
@@ -410,11 +452,26 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
_mousePos = event.mouse;
_buttonState |= RBUTTON;
break;
+
case Common::EVENT_RBUTTONUP:
_mousePos = event.mouse;
_buttonState &= ~RBUTTON;
break;
+ case Common::EVENT_MAINMENU:
+ if (g_engine && !g_engine->isPaused())
+ g_engine->mainMenuDialog();
+
+ if (_shouldQuit)
+ event.type = Common::EVENT_QUIT;
+ else if (_shouldRTL)
+ event.type = Common::EVENT_RTL;
+ break;
+
+ case Common::EVENT_RTL:
+ _shouldRTL = true;
+ break;
+
case Common::EVENT_QUIT:
if (ConfMan.getBool("confirm_exit")) {
if (g_engine)
@@ -425,6 +482,7 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
g_engine->pauseEngine(false);
} else
_shouldQuit = true;
+
break;
default:
@@ -447,4 +505,14 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
return result;
}
+void DefaultEventManager::pushEvent(Common::Event event) {
+
+ // If already received an EVENT_QUIT, don't add another one
+ if (event.type == Common::EVENT_QUIT) {
+ if (!_shouldQuit)
+ artificialEventQueue.push(event);
+ } else
+ artificialEventQueue.push(event);
+}
+
#endif // !defined(DISABLE_DEFAULT_EVENTMANAGER)
diff --git a/backends/events/default/default-events.h b/backends/events/default/default-events.h
index 98dcd4b3de..b2cd1354cc 100644
--- a/backends/events/default/default-events.h
+++ b/backends/events/default/default-events.h
@@ -48,6 +48,7 @@ class DefaultEventManager : public Common::EventManager {
int _buttonState;
int _modifierState;
bool _shouldQuit;
+ bool _shouldRTL;
class RandomSourceRecord {
public:
@@ -107,6 +108,7 @@ public:
~DefaultEventManager();
virtual bool pollEvent(Common::Event &event);
+ virtual void pushEvent(Common::Event event);
virtual void registerRandomSource(Common::RandomSource &rnd, const char *name);
virtual void processMillis(uint32 &millis);
@@ -114,6 +116,8 @@ public:
virtual int getButtonState() const { return _buttonState; }
virtual int getModifierState() const { return _modifierState; }
virtual int shouldQuit() const { return _shouldQuit; }
+ virtual int shouldRTL() const { return _shouldRTL; }
+ virtual void resetRTL() { _shouldRTL = false; }
};
#endif
diff --git a/backends/fs/abstract-fs.cpp b/backends/fs/abstract-fs.cpp
new file mode 100644
index 0000000000..6daad7152a
--- /dev/null
+++ b/backends/fs/abstract-fs.cpp
@@ -0,0 +1,40 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * 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 "backends/fs/abstract-fs.h"
+
+const char *AbstractFilesystemNode::lastPathComponent(const Common::String &str, const char sep) {
+ // TODO: Get rid of this eventually! Use Common::lastPathComponent instead
+ if(str.empty())
+ return "";
+
+ const char *start = str.c_str();
+ const char *cur = start + str.size() - 2;
+
+ while (cur >= start && *cur != sep) {
+ --cur;
+ }
+
+ return cur + 1;
+}
diff --git a/backends/fs/abstract-fs.h b/backends/fs/abstract-fs.h
index 97de40a2fc..b3a652f2ae 100644
--- a/backends/fs/abstract-fs.h
+++ b/backends/fs/abstract-fs.h
@@ -43,22 +43,21 @@ typedef Common::Array<AbstractFilesystemNode *> AbstractFSList;
*/
class AbstractFilesystemNode {
protected:
- friend class FilesystemNode;
- typedef Common::String String;
- typedef FilesystemNode::ListMode ListMode;
+ friend class Common::FilesystemNode;
+ typedef Common::FilesystemNode::ListMode ListMode;
/**
- * Returns the child node with the given name. If no child with this name
- * exists, returns 0. When called on a non-directory node, it should
- * handle this gracefully by returning 0.
+ * Returns the child node with the given name. When called on a non-directory
+ * node, it should handle this gracefully by returning 0.
+ * When called with a name not matching any of the files/dirs contained in this
+ * directory, a valid node shold be returned, which returns 'false' upon calling
+ * the exists() method. The idea is that this node can then still can be used to
+ * create a new file via the openForWriting() method.
*
* Example:
* Calling getChild() for a node with path "/foo/bar" using name="file.txt",
* would produce a new node with "/foo/bar/file.txt" as path.
*
- * @note This function will append a separator char (\ or /) to the end of the
- * path if needed.
- *
* @note Handling calls on non-dir nodes gracefully makes it possible to
* switch to a lazy type detection scheme in the future.
*
@@ -72,6 +71,19 @@ protected:
*/
virtual AbstractFilesystemNode *getParent() const = 0;
+ /**
+ * Returns the last component of a given path.
+ *
+ * Examples:
+ * /foo/bar.txt would return /bar.txt
+ * /foo/bar/ would return /bar/
+ *
+ * @param str String containing the path.
+ * @param sep character used to separate path components
+ * @return Pointer to the first char of the last component inside str.
+ */
+ static const char *lastPathComponent(const Common::String &str, const char sep);
+
public:
/**
* Destructor.
@@ -149,9 +161,26 @@ public:
*/
virtual bool isWritable() const = 0;
- /* TODO:
- bool isFile();
- */
+
+ /**
+ * Creates a SeekableReadStream instance corresponding to the file
+ * referred by this node. This assumes that the node actually refers
+ * to a readable file. If this is not the case, 0 is returned.
+ *
+ * @return pointer to the stream object, 0 in case of a failure
+ */
+ virtual Common::SeekableReadStream *openForReading() = 0;
+
+ /**
+ * Creates a WriteStream instance corresponding to the file
+ * referred by this node. This assumes that the node actually refers
+ * to a readable file. If this is not the case, 0 is returned.
+ *
+ * @return pointer to the stream object, 0 in case of a failure
+ */
+ virtual Common::WriteStream *openForWriting() = 0;
};
+
+
#endif //BACKENDS_ABSTRACT_FS_H
diff --git a/backends/fs/amigaos4/amigaos4-fs-factory.cpp b/backends/fs/amigaos4/amigaos4-fs-factory.cpp
index af843b7c78..2b0b2f1908 100644
--- a/backends/fs/amigaos4/amigaos4-fs-factory.cpp
+++ b/backends/fs/amigaos4/amigaos4-fs-factory.cpp
@@ -26,8 +26,6 @@
#include "backends/fs/amigaos4/amigaos4-fs-factory.h"
#include "backends/fs/amigaos4/amigaos4-fs.cpp"
-DECLARE_SINGLETON(AmigaOSFilesystemFactory);
-
AbstractFilesystemNode *AmigaOSFilesystemFactory::makeRootFileNode() const {
return new AmigaOSFilesystemNode();
}
@@ -36,7 +34,7 @@ AbstractFilesystemNode *AmigaOSFilesystemFactory::makeCurrentDirectoryFileNode()
return new AmigaOSFilesystemNode();
}
-AbstractFilesystemNode *AmigaOSFilesystemFactory::makeFileNodePath(const String &path) const {
+AbstractFilesystemNode *AmigaOSFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new AmigaOSFilesystemNode(path);
}
#endif
diff --git a/backends/fs/amigaos4/amigaos4-fs-factory.h b/backends/fs/amigaos4/amigaos4-fs-factory.h
index 58a7dcd372..03af6e95b9 100644
--- a/backends/fs/amigaos4/amigaos4-fs-factory.h
+++ b/backends/fs/amigaos4/amigaos4-fs-factory.h
@@ -25,7 +25,6 @@
#ifndef AMIGAOS_FILESYSTEM_FACTORY_H
#define AMIGAOS_FILESYSTEM_FACTORY_H
-#include "common/singleton.h"
#include "backends/fs/fs-factory.h"
/**
@@ -33,19 +32,11 @@
*
* Parts of this class are documented in the base interface class, FilesystemFactory.
*/
-class AmigaOSFilesystemFactory : public FilesystemFactory, public Common::Singleton<AmigaOSFilesystemFactory> {
+class AmigaOSFilesystemFactory : public FilesystemFactory {
public:
- typedef Common::String String;
-
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
-
-protected:
- AmigaOSFilesystemFactory() {};
-
-private:
- friend class Common::Singleton<SingletonBaseType>;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
};
#endif /*AMIGAOS_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/amigaos4/amigaos4-fs.cpp b/backends/fs/amigaos4/amigaos4-fs.cpp
index 5bf57ddf34..d517121dc0 100644
--- a/backends/fs/amigaos4/amigaos4-fs.cpp
+++ b/backends/fs/amigaos4/amigaos4-fs.cpp
@@ -36,8 +36,8 @@
#endif
#include "common/util.h"
-#include "engines/engine.h"
#include "backends/fs/abstract-fs.h"
+#include "backends/fs/stdiostream.h"
#define ENTER() /* debug(6, "Enter") */
#define LEAVE() /* debug(6, "Leave") */
@@ -52,8 +52,8 @@ const uint32 kExAllBufferSize = 40960; // TODO: is this okay for sure?
class AmigaOSFilesystemNode : public AbstractFilesystemNode {
protected:
BPTR _pFileLock;
- String _sDisplayName;
- String _sPath;
+ Common::String _sDisplayName;
+ Common::String _sPath;
bool _bIsDirectory;
bool _bIsValid;
@@ -74,9 +74,9 @@ public:
/**
* Creates a AmigaOSFilesystemNode for a given path.
*
- * @param path 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 String &p);
+ AmigaOSFilesystemNode(const Common::String &p);
/**
* FIXME: document this constructor.
@@ -96,17 +96,20 @@ public:
virtual ~AmigaOSFilesystemNode();
virtual bool exists() const;
- virtual String getDisplayName() const { return _sDisplayName; };
- virtual String getName() const { return _sDisplayName; };
- virtual String getPath() const { return _sPath; };
+ virtual Common::String getDisplayName() const { return _sDisplayName; };
+ virtual Common::String getName() const { return _sDisplayName; };
+ virtual Common::String getPath() const { return _sPath; };
virtual bool isDirectory() const { return _bIsDirectory; };
virtual bool isReadable() const;
virtual bool isWritable() const;
- virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+
/**
* Creates a list with all the volumes present in the root node.
*/
@@ -116,7 +119,7 @@ public:
/**
* Returns the last component of a given path.
*
- * @param str String containing the path.
+ * @param str Common::String containing the path.
* @return Pointer to the first char of the last component inside str.
*/
const char *lastPathComponent(const Common::String &str) {
@@ -148,10 +151,10 @@ AmigaOSFilesystemNode::AmigaOSFilesystemNode() {
LEAVE();
}
-AmigaOSFilesystemNode::AmigaOSFilesystemNode(const String &p) {
+AmigaOSFilesystemNode::AmigaOSFilesystemNode(const Common::String &p) {
ENTER();
- int len = 0, offset = p.size();
+ int offset = p.size();
//assert(offset > 0);
@@ -161,7 +164,7 @@ AmigaOSFilesystemNode::AmigaOSFilesystemNode(const String &p) {
}
_sPath = p;
- _sDisplayName = lastPathComponent(_sPath);
+ _sDisplayName = ::lastPathComponent(_sPath);
_pFileLock = 0;
_bIsDirectory = false;
@@ -299,14 +302,14 @@ bool AmigaOSFilesystemNode::exists() const {
return nodeExists;
}
-AbstractFilesystemNode *AmigaOSFilesystemNode::getChild(const String &n) const {
+AbstractFilesystemNode *AmigaOSFilesystemNode::getChild(const Common::String &n) const {
ENTER();
if (!_bIsDirectory) {
debug(6, "Not a directory");
return 0;
}
- String newPath(_sPath);
+ Common::String newPath(_sPath);
if (_sPath.lastChar() != '/')
newPath += '/';
@@ -368,10 +371,10 @@ bool AmigaOSFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b
struct ExAllData *ead = data;
do {
- if ((mode == FilesystemNode::kListAll) ||
- (EAD_IS_DRAWER(ead) && (mode == FilesystemNode::kListDirectoriesOnly)) ||
- (EAD_IS_FILE(ead) && (mode == FilesystemNode::kListFilesOnly))) {
- String full_path = _sPath;
+ if ((mode == Common::FilesystemNode::kListAll) ||
+ (EAD_IS_DRAWER(ead) && (mode == Common::FilesystemNode::kListDirectoriesOnly)) ||
+ (EAD_IS_FILE(ead) && (mode == Common::FilesystemNode::kListFilesOnly))) {
+ Common::String full_path = _sPath;
full_path += (char*)ead->ed_Name;
BPTR lock = IDOS->Lock((STRPTR)full_path.c_str(), SHARED_LOCK);
@@ -566,4 +569,12 @@ AbstractFSList AmigaOSFilesystemNode::listVolumes() const {
return myList;
}
+Common::SeekableReadStream *AmigaOSFilesystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
+
+Common::WriteStream *AmigaOSFilesystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
+}
+
#endif //defined(__amigaos4__)
diff --git a/backends/fs/ds/ds-fs-factory.cpp b/backends/fs/ds/ds-fs-factory.cpp
index 2eae2f2403..5c8c3f45f8 100644
--- a/backends/fs/ds/ds-fs-factory.cpp
+++ b/backends/fs/ds/ds-fs-factory.cpp
@@ -45,7 +45,7 @@ AbstractFilesystemNode *DSFilesystemFactory::makeCurrentDirectoryFileNode() cons
}
}
-AbstractFilesystemNode *DSFilesystemFactory::makeFileNodePath(const String &path) const {
+AbstractFilesystemNode *DSFilesystemFactory::makeFileNodePath(const Common::String &path) const {
if (DS::isGBAMPAvailable()) {
return new DS::GBAMPFileSystemNode(path);
} else {
diff --git a/backends/fs/ds/ds-fs-factory.h b/backends/fs/ds/ds-fs-factory.h
index bff21a309d..67e0076b78 100644
--- a/backends/fs/ds/ds-fs-factory.h
+++ b/backends/fs/ds/ds-fs-factory.h
@@ -35,11 +35,9 @@
*/
class DSFilesystemFactory : public FilesystemFactory, public Common::Singleton<DSFilesystemFactory> {
public:
- typedef Common::String String;
-
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
protected:
DSFilesystemFactory() {};
diff --git a/backends/fs/ds/ds-fs.cpp b/backends/fs/ds/ds-fs.cpp
index cffe4c118d..911702316d 100644
--- a/backends/fs/ds/ds-fs.cpp
+++ b/backends/fs/ds/ds-fs.cpp
@@ -24,6 +24,7 @@
#include "common/util.h"
//#include <NDS/ARM9/console.h> //basic print funcionality
#include "backends/fs/ds/ds-fs.h"
+#include "backends/fs/stdiostream.h"
#include "dsmain.h"
#include "fat/gba_nds_fat.h"
@@ -55,7 +56,7 @@ DSFileSystemNode::DSFileSystemNode() {
}
}
-DSFileSystemNode::DSFileSystemNode(const String& path) {
+DSFileSystemNode::DSFileSystemNode(const Common::String& path) {
// consolePrintf("--%s ",path.c_str());
char disp[128];
@@ -70,7 +71,7 @@ DSFileSystemNode::DSFileSystemNode(const String& path) {
strcpy(disp, pathStr + lastSlash + 1);
- _displayName = String(disp);
+ _displayName = Common::String(disp);
_path = path;
// _isValid = true;
// _isDirectory = false;
@@ -98,7 +99,7 @@ DSFileSystemNode::DSFileSystemNode(const String& path) {
// consolePrintf("%s - Found: %d, Dir: %d\n", pathStr, _isValid, _isDirectory);
}
-DSFileSystemNode::DSFileSystemNode(const String& path, bool isDir) {
+DSFileSystemNode::DSFileSystemNode(const Common::String& path, bool isDir) {
// consolePrintf("--%s ",path.c_str());
char disp[128];
@@ -112,7 +113,7 @@ DSFileSystemNode::DSFileSystemNode(const String& path, bool isDir) {
strcpy(disp, pathStr + lastSlash + 1);
- _displayName = String(disp);
+ _displayName = Common::String(disp);
_path = path;
_isValid = true;
_isDirectory = isDir;
@@ -167,10 +168,10 @@ bool DSFileSystemNode::getChildren(AbstractFSList &dirList, ListMode mode, bool
_zipFile->getFileName(n);
// consolePrintf("file: %s\n", n);
- if ( (_zipFile->isDirectory() && ((mode == FilesystemNode::kListDirectoriesOnly) || (mode == FilesystemNode::kListAll)) )
- || (!_zipFile->isDirectory() && ((mode == FilesystemNode::kListFilesOnly) || (mode == FilesystemNode::kListAll)) ) )
+ if ( (_zipFile->isDirectory() && ((mode == Common::FilesystemNode::kListDirectoriesOnly) || (mode == Common::FilesystemNode::kListAll)) )
+ || (!_zipFile->isDirectory() && ((mode == Common::FilesystemNode::kListFilesOnly) || (mode == Common::FilesystemNode::kListAll)) ) )
{
- DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/" + String(n), _zipFile->isDirectory());
+ DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/" + Common::String(n), _zipFile->isDirectory());
dsfsn->_isDirectory = _zipFile->isDirectory();
dirList.push_back((dsfsn));
}
@@ -195,7 +196,7 @@ AbstractFilesystemNode* DSFileSystemNode::getParent() const {
}
}
- p = new DSFileSystemNode(String(path, lastSlash));
+ p = new DSFileSystemNode(Common::String(path, lastSlash));
((DSFileSystemNode *) (p))->_isDirectory = true;
} else {
p = new DSFileSystemNode();
@@ -204,6 +205,14 @@ AbstractFilesystemNode* DSFileSystemNode::getParent() const {
return p;
}
+Common::SeekableReadStream *DSFileSystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
+
+Common::WriteStream *DSFileSystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
+}
+
//////////////////////////////////////////////////////////////////////////
// GBAMPFileSystemNode - File system using GBA Movie Player and CF card //
//////////////////////////////////////////////////////////////////////////
@@ -216,7 +225,7 @@ GBAMPFileSystemNode::GBAMPFileSystemNode() {
_path = "mp:/";
}
-GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path) {
+GBAMPFileSystemNode::GBAMPFileSystemNode(const Common::String& path) {
// consolePrintf("'%s'",path.c_str());
char disp[128];
@@ -245,13 +254,13 @@ GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path) {
}
// consolePrintf("Path: %s (%d)\n", check, success);
- _displayName = String(disp);
+ _displayName = Common::String(disp);
_path = path;
_isValid = success == FT_FILE;
_isDirectory = success == FT_DIR;
}
-GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path, bool isDirectory) {
+GBAMPFileSystemNode::GBAMPFileSystemNode(const Common::String& path, bool isDirectory) {
// consolePrintf("'%s'",path.c_str());
char disp[128];
@@ -265,7 +274,7 @@ GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path, bool isDirectory) {
strcpy(disp, pathStr + lastSlash + 1);
- _displayName = String(disp);
+ _displayName = Common::String(disp);
_path = path;
_isValid = true;
_isDirectory = isDirectory;
@@ -313,8 +322,8 @@ bool GBAMPFileSystemNode::getChildren(AbstractFSList& dirList, ListMode mode, bo
while (entryType != TYPE_NO_MORE) {
- if ( ((entryType == TYPE_DIR) && ((mode == FilesystemNode::kListDirectoriesOnly) || (mode == FilesystemNode::kListAll)))
- || ((entryType == TYPE_FILE) && ((mode == FilesystemNode::kListFilesOnly) || (mode == FilesystemNode::kListAll))) ) {
+ if ( ((entryType == TYPE_DIR) && ((mode == Common::FilesystemNode::kListDirectoriesOnly) || (mode == Common::FilesystemNode::kListAll)))
+ || ((entryType == TYPE_FILE) && ((mode == Common::FilesystemNode::kListFilesOnly) || (mode == Common::FilesystemNode::kListAll))) ) {
GBAMPFileSystemNode* dsfsn;
consolePrintf("Fname: %s\n", fname);
@@ -322,9 +331,9 @@ bool GBAMPFileSystemNode::getChildren(AbstractFSList& dirList, ListMode mode, bo
if (strcmp(fname, ".") && strcmp(fname, "..")) {
if (!strcmp(path, "/")) {
- dsfsn = new GBAMPFileSystemNode("mp:" + String(path) + String(fname), entryType == TYPE_DIR);
+ dsfsn = new GBAMPFileSystemNode("mp:" + Common::String(path) + Common::String(fname), entryType == TYPE_DIR);
} else {
- dsfsn = new GBAMPFileSystemNode("mp:" + String(path) + String("/") + String(fname), entryType == TYPE_DIR);
+ dsfsn = new GBAMPFileSystemNode("mp:" + Common::String(path) + Common::String("/") + Common::String(fname), entryType == TYPE_DIR);
}
// dsfsn->_isDirectory = entryType == DIR;
@@ -358,7 +367,7 @@ AbstractFilesystemNode* GBAMPFileSystemNode::getParent() const {
}
}
- p = new GBAMPFileSystemNode(String(path, lastSlash));
+ p = new GBAMPFileSystemNode(Common::String(path, lastSlash));
p->_isDirectory = true;
} else {
p = new GBAMPFileSystemNode();
@@ -367,6 +376,14 @@ AbstractFilesystemNode* GBAMPFileSystemNode::getParent() const {
return p;
}
+Common::SeekableReadStream *GBAMPFileSystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
+
+Common::WriteStream *GBAMPFileSystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
+}
+
// Stdio replacements
#define MAX_FILE_HANDLES 32
@@ -399,6 +416,7 @@ FILE* std_fopen(const char* name, const char* mode) {
if (DS::isGBAMPAvailable()) {
FAT_chdir("/");
+ // Turn all back slashes into forward slashes for gba_nds_fat
char* p = realName;
while (*p) {
if (*p == '\\') *p = '/';
@@ -422,8 +440,12 @@ FILE* std_fopen(const char* name, const char* mode) {
// Allocate a file handle
int r = 0;
- while (handle[r].used) r++;
+ while (handle[r].used) {
+ r++;
+ assert(r < MAX_FILE_HANDLES);
+ }
+#ifdef GBA_SRAM_SAVE
if (strchr(mode, 'w')) {
// consolePrintf("Writing %s\n", realName);
handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, true);
@@ -431,6 +453,7 @@ FILE* std_fopen(const char* name, const char* mode) {
// consolePrintf("Reading %s\n", realName);
handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, false);
}
+#endif
if (handle[r].sramFile) {
handle[r].used = true;
@@ -512,69 +535,6 @@ size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
return bytes / size;
}
return numItems;
-
-/* int item = 0;
- u8* data = (u8 *) ptr;
- while ((item < numItems) && (!FAT_feof((FAT_FILE *) handle))) {
-
-
- int bytes = 0;
- while ((bytes < size) && (!FAT_feof((FAT_FILE *) handle))) {
- *data++ = FAT_fgetc((FAT_FILE *) handle);
- bytes++;
- }
-
- item++;
-
- }
-
- return item;
-*/
- int items = 0;
-
- //for (int r = 0; r < numItems; r++) {
- if (!std_feof(handle)) {
-/* for (int t = 0; t < size; t++) {
- if (feof(handle)) eof = true;
- *(((char *) (ptr)) + r * size + t) = getc(handle);
- }*/
- int left = size * numItems;
- int bytesRead = -1;
-
- while ((left > 0) && (!FAT_feof((FAT_FILE *) handle))) {
- int amount = left > 8192? 8192: left;
-// do {
- bytesRead = FAT_fread((void *) ptr, 1, amount, (FAT_FILE *) handle);
-/* if (bytesRead == 0) {
- consolePrintf("Pos:%d items:%d num:%d amount:%d read:%d\n", ftell(handle), items, numItems, amount, bytesRead);
- left++;
-
- int pos = ftell(handle);
-
- fseek(handle, 0, SEEK_SET);
- int c = getc(handle);
- fseek(handle, pos - 1024, SEEK_SET);
- fread(ptr, 1024, 1, handle);
- swiWaitForVBlank();
- //while (true);
- }
-
- } while (bytesRead == 0);
-*/
- left -= bytesRead;
- ptr = ((char *) (ptr)) + bytesRead;
- }
-
- items = numItems - (left / size);
-
-// FAT_fread((void *) ptr, size, 1, ((int) (handle)) - 1);
-// ptr = ((char *) (ptr)) + size;
- }
-// }
-
-// consolePrintf("...done %d \n", items)
-
- return items;
}
if (handle->sramFile) {
@@ -641,10 +601,6 @@ size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) {
}
}
-void std_fprintf(FILE* handle, const char* fmt, ...) {
- consolePrintf(fmt);
-}
-
bool std_feof(FILE* handle) {
// consolePrintf("feof ");
@@ -660,42 +616,10 @@ bool std_feof(FILE* handle) {
return handle->pos >= handle->size;
}
-void std_fflush(FILE* handle) {
+int std_fflush(FILE* handle) {
//FIXME: not implemented?
// consolePrintf("fflush ");
-}
-
-char* std_fgets(char* str, int size, FILE* file) {
-// consolePrintf("fgets file=%d ", file);
-
- if (DS::isGBAMPAvailable()) {
- char* s = str;
- while ((*s++ = std_getc(file)) >= 32) {
-// consolePrintf("%d ", *s);
- }
- *s = 0;
-
-// consolePrintf("Read:%s\n", str);
-
- return str;
- }
-
- if (file->sramFile) {
- file->pos--;
- int p = -1;
- do {
- file->pos++;
- p++;
- file->sramFile->read((char *) &str[p], 1);
-// consolePrintf("%d,", str[p]);
- } while ((str[p] >= 32) && (!std_feof(file)) && (p < size));
- str[p + 1] = 0;
- file->pos++;
-// consolePrintf("Read:%s\n", str);
- return str;
- }
-
- return NULL;
+ return 0;
}
long int std_ftell(FILE* handle) {
@@ -731,92 +655,20 @@ int std_fseek(FILE* handle, long int offset, int whence) {
return 0;
}
-void std_clearerr(FILE* handle) {
+int std_ferror(FILE* handle) {
//FIXME: not implemented?
-// consolePrintf("clearerr ");
-}
-
-int std_getc(FILE* handle) {
- if (DS::isGBAMPAvailable()) {
- char c;
- FAT_fread(&c, 1, 1, (FAT_FILE *) handle);
-
- return c;
- }
-
-// consolePrintf("fgetc ");
- return 0; // Not supported yet
+// consolePrintf("ferror ");
+ return 0;
}
-char* std_getcwd(char* dir, int dunno) {
-// consolePrintf("getcwd ");
- dir[0] = '\0';
- return dir; // Not supported yet
+void std_clearerr(FILE* handle) {
+ //FIXME: not implemented?
+// consolePrintf("clearerr ");
}
-void std_cwd(char* dir) {
- char buffer[128];
- strcpy(buffer, dir);
- char* realName = buffer;
-
- if (DS::isGBAMPAvailable()) {
- if ((strlen(dir) >= 4) && (dir[0] == 'm') && (dir[1] == 'p') && (dir[2] == ':') && (dir[3] == '/')) {
- realName += 4;
- }
-
- // consolePrintf("Real cwd:%d\n", realName);
-
- char* p = realName;
- while (*p) {
- if (*p == '\\') *p = '/';
- p++;
- }
-
- // consolePrintf("Real cwd:%d\n", realName);
- FAT_chdir(realName);
- } else {
- if ((strlen(dir) >= 4) && (dir[0] == 'd') && (dir[1] == 's') && (dir[2] == ':') && (dir[3] == '/')) {
- realName += 4;
- }
-
- char* p = realName;
- while (*p) {
- if (*p == '\\') *p = '/';
- p++;
- }
-
- strcpy(currentDir, realName);
- if (*(currentDir + strlen(currentDir) - 1) == '/') {
- *(currentDir + strlen(currentDir) - 1) = '\0';
- }
-// consolePrintf("CWD: %s\n", currentDir);
- }
+void std_fprintf(FILE* handle, const char* fmt, ...) {
+ consolePrintf(fmt);
}
-int std_ferror(FILE* handle) {
- return 0;
-}
} // namespace DS
-
-/**
- * Returns the last component of a given path.
- *
- * Examples:
- * /foo/bar.txt would return /bar.txt
- * /foo/bar/ would return /bar/
- *
- * @param str String containing the path.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *lastPathComponent(const Common::String &str) {
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '/' && *cur != '\\') {
- --cur;
- }
-
- return cur + 1;
-}
-
diff --git a/backends/fs/ds/ds-fs.h b/backends/fs/ds/ds-fs.h
index 9ac453aca9..36e7bc9824 100644
--- a/backends/fs/ds/ds-fs.h
+++ b/backends/fs/ds/ds-fs.h
@@ -41,12 +41,10 @@ namespace DS {
*/
class DSFileSystemNode : public AbstractFilesystemNode {
protected:
- typedef class Common::String String;
-
static ZipFile* _zipFile;
- String _displayName;
- String _path;
+ Common::String _displayName;
+ Common::String _path;
bool _isDirectory;
bool _isValid;
@@ -61,7 +59,7 @@ public:
*
* @param path String with the path the new node should point to.
*/
- DSFileSystemNode(const String &path);
+ DSFileSystemNode(const Common::String &path);
/**
* Creates a DSFilesystemNode for a given path.
@@ -69,7 +67,7 @@ public:
* @param path String with the path the new node should point to.
* @param path true if path is a directory, false otherwise.
*/
- DSFileSystemNode(const String& path, bool isDir);
+ DSFileSystemNode(const Common::String& path, bool isDir);
/**
* Copy constructor.
@@ -77,9 +75,9 @@ public:
DSFileSystemNode(const DSFileSystemNode *node);
virtual bool exists() const { return true; } //FIXME: this is just a stub
- virtual String getDisplayName() const { return _displayName; }
- virtual String getName() const { return _displayName; }
- virtual String getPath() const { return _path; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return true; } //FIXME: this is just a stub
virtual bool isWritable() const { return true; } //FIXME: this is just a stub
@@ -89,9 +87,12 @@ public:
*/
virtual AbstractFilesystemNode *clone() const { return new DSFileSystemNode(this); }
virtual AbstractFilesystemNode *getChild(const Common::String& name) const;
- virtual bool getChildren(AbstractFSList &list, ListMode mode = FilesystemNode::kListDirectoriesOnly, bool hidden = false) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+
/**
* Returns the zip file this node points to.
* TODO: check this documentation.
@@ -107,10 +108,8 @@ public:
*/
class GBAMPFileSystemNode : public AbstractFilesystemNode {
protected:
- typedef class Common::String String;
-
- String _displayName;
- String _path;
+ Common::String _displayName;
+ Common::String _path;
bool _isDirectory;
bool _isValid;
@@ -125,7 +124,7 @@ public:
*
* @param path String with the path the new node should point to.
*/
- GBAMPFileSystemNode(const String &path);
+ GBAMPFileSystemNode(const Common::String &path);
/**
* Creates a DSFilesystemNode for a given path.
@@ -133,7 +132,7 @@ public:
* @param path String with the path the new node should point to.
* @param path true if path is a directory, false otherwise.
*/
- GBAMPFileSystemNode(const String &path, bool isDirectory);
+ GBAMPFileSystemNode(const Common::String &path, bool isDirectory);
/**
* Copy constructor.
@@ -141,9 +140,9 @@ public:
GBAMPFileSystemNode(const GBAMPFileSystemNode *node);
virtual bool exists() const { return _isValid || _isDirectory; }
- virtual String getDisplayName() const { return _displayName; }
- virtual String getName() const { return _displayName; }
- virtual String getPath() const { return _path; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return true; } //FIXME: this is just a stub
virtual bool isWritable() const { return true; } //FIXME: this is just a stub
@@ -153,8 +152,11 @@ public:
*/
virtual AbstractFilesystemNode *clone() const { return new GBAMPFileSystemNode(this); }
virtual AbstractFilesystemNode *getChild(const Common::String& name) const;
- virtual bool getChildren(AbstractFSList &list, ListMode mode = FilesystemNode::kListDirectoriesOnly, bool hidden = false) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
+
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
};
struct fileHandle {
@@ -179,15 +181,14 @@ struct fileHandle {
// Please do not remove any of these prototypes that appear not to be required.
FILE* std_fopen(const char* name, const char* mode);
void std_fclose(FILE* handle);
-int std_getc(FILE* handle);
size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle);
size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle);
bool std_feof(FILE* handle);
long int std_ftell(FILE* handle);
int std_fseek(FILE* handle, long int offset, int whence);
void std_clearerr(FILE* handle);
-void std_cwd(char* dir);
-void std_fflush(FILE* handle);
+int std_fflush(FILE* handle);
+int std_ferror(FILE* handle);
} //namespace DS
diff --git a/backends/fs/palmos/palmos-fs-factory.cpp b/backends/fs/palmos/palmos-fs-factory.cpp
index 8699a9788b..bbc1639897 100644
--- a/backends/fs/palmos/palmos-fs-factory.cpp
+++ b/backends/fs/palmos/palmos-fs-factory.cpp
@@ -36,7 +36,7 @@ AbstractFilesystemNode *PalmOSFilesystemFactory::makeCurrentDirectoryFileNode()
return new PalmOSFilesystemNode();
}
-AbstractFilesystemNode *PalmOSFilesystemFactory::makeFileNodePath(const String &path) const {
+AbstractFilesystemNode *PalmOSFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new PalmOSFilesystemNode(path);
}
#endif
diff --git a/backends/fs/palmos/palmos-fs-factory.h b/backends/fs/palmos/palmos-fs-factory.h
index 3ea8b5fe47..f778aa89ef 100644
--- a/backends/fs/palmos/palmos-fs-factory.h
+++ b/backends/fs/palmos/palmos-fs-factory.h
@@ -35,11 +35,9 @@
*/
class PalmOSFilesystemFactory : public FilesystemFactory, public Common::Singleton<PalmOSFilesystemFactory> {
public:
- typedef Common::String String;
-
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
protected:
PalmOSFilesystemFactory() {};
diff --git a/backends/fs/palmos/palmos-fs.cpp b/backends/fs/palmos/palmos-fs.cpp
index 5edb6c2d26..7c415aa320 100644
--- a/backends/fs/palmos/palmos-fs.cpp
+++ b/backends/fs/palmos/palmos-fs.cpp
@@ -28,6 +28,7 @@
#include "globals.h"
#include "backends/fs/abstract-fs.h"
+#include "backends/fs/stdiostream.h"
/**
* Implementation of the ScummVM file system API based on PalmOS VFS API.
@@ -36,8 +37,8 @@
*/
class PalmOSFilesystemNode : public AbstractFilesystemNode {
protected:
- String _displayName;
- String _path;
+ Common::String _displayName;
+ Common::String _path;
bool _isDirectory;
bool _isValid;
bool _isPseudoRoot;
@@ -51,22 +52,25 @@ public:
/**
* Creates a POSIXFilesystemNode for a given path.
*
- * @param path String with the path the new node should point to.
+ * @param path Common::String with the path the new node should point to.
*/
- PalmOSFilesystemNode(const String &p);
+ PalmOSFilesystemNode(const Common::String &p);
virtual bool exists() const { return _isValid; }
- virtual String getDisplayName() const { return _displayName; }
- virtual String getName() const { return _displayName; }
- virtual String getPath() const { return _path; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return true; } //FIXME: this is just a stub
virtual bool isWritable() const { return true; } //FIXME: this is just a stub
- virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+
private:
/**
* Adds a single WindowsFilesystemNode to a given list.
@@ -74,44 +78,20 @@ private:
*
* @param list List to put the file entry node in.
* @param mode Mode to use while adding the file entry to the list.
- * @param base String with the directory being listed.
+ * @param base Common::String with the directory being listed.
* @param find_data Describes a file that the FindFirstFile, FindFirstFileEx, or FindNextFile functions find.
*/
static void addFile(AbstractFSList &list, ListMode mode, const Char *base, FileInfoType* find_data);
};
-/**
- * Returns the last component of a given path.
- *
- * Examples:
- * /foo/bar.txt would return /bar.txt
- * /foo/bar/ would return /bar/
- *
- * @param str String containing the path.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *lastPathComponent(const Common::String &str) {
- if(str.empty())
- return "";
-
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '/') {
- --cur;
- }
-
- return cur + 1;
-}
-
void PalmOSFilesystemNode::addFile(AbstractFSList &list, ListMode mode, const char *base, FileInfoType* find_data) {
PalmOSFilesystemNode entry;
bool isDir;
isDir = (find_data->attributes & vfsFileAttrDirectory);
- if ((!isDir && mode == FilesystemNode::kListDirectoriesOnly) ||
- (isDir && mode == FilesystemNode::kListFilesOnly))
+ if ((!isDir && mode == Common::FilesystemNode::kListDirectoriesOnly) ||
+ (isDir && mode == Common::FilesystemNode::kListFilesOnly))
return;
entry._isDirectory = isDir;
@@ -136,9 +116,9 @@ PalmOSFilesystemNode::PalmOSFilesystemNode() {
_isPseudoRoot = false;
}
-PalmOSFilesystemNode::PalmOSFilesystemNode(const String &p) {
+PalmOSFilesystemNode::PalmOSFilesystemNode(const Common::String &p) {
_path = p;
- _displayName = lastPathComponent(_path);
+ _displayName = lastPathComponent(_path, '/');
UInt32 attr;
FileRef handle;
@@ -159,10 +139,10 @@ PalmOSFilesystemNode::PalmOSFilesystemNode(const String &p) {
_isPseudoRoot = false;
}
-AbstractFilesystemNode *PalmOSFilesystemNode::getChild(const String &n) const {
+AbstractFilesystemNode *PalmOSFilesystemNode::getChild(const Common::String &n) const {
assert(_isDirectory);
- String newPath(_path);
+ Common::String newPath(_path);
if (_path.lastChar() != '/')
newPath += '/';
newPath += n;
@@ -215,17 +195,25 @@ AbstractFilesystemNode *PalmOSFilesystemNode::getParent() const {
if (!_isPseudoRoot) {
const char *start = _path.c_str();
- const char *end = lastPathComponent(_path);
+ const char *end = lastPathComponent(_path, '/');
p = new PalmOSFilesystemNode();
- p->_path = String(start, end - start);
+ p->_path = Common::String(start, end - start);
p->_isValid = true;
p->_isDirectory = true;
- p->_displayName = lastPathComponent(p->_path);
+ p->_displayName = lastPathComponent(p->_path, '/');
p->_isPseudoRoot =(p->_path == "/");
}
return p;
}
+Common::SeekableReadStream *PalmOSFilesystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
+
+Common::WriteStream *PalmOSFilesystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
+}
+
#endif // PALMOS_MODE
diff --git a/backends/fs/posix/posix-fs-factory.cpp b/backends/fs/posix/posix-fs-factory.cpp
index 0a1160ff8f..cbfb69b76a 100644
--- a/backends/fs/posix/posix-fs-factory.cpp
+++ b/backends/fs/posix/posix-fs-factory.cpp
@@ -26,19 +26,18 @@
#include "backends/fs/posix/posix-fs-factory.h"
#include "backends/fs/posix/posix-fs.cpp"
-DECLARE_SINGLETON(POSIXFilesystemFactory);
-
AbstractFilesystemNode *POSIXFilesystemFactory::makeRootFileNode() const {
- return new POSIXFilesystemNode();
+ return new POSIXFilesystemNode("/");
}
AbstractFilesystemNode *POSIXFilesystemFactory::makeCurrentDirectoryFileNode() const {
char buf[MAXPATHLEN];
getcwd(buf, MAXPATHLEN);
- return new POSIXFilesystemNode(buf, true);
+ return new POSIXFilesystemNode(buf);
}
-AbstractFilesystemNode *POSIXFilesystemFactory::makeFileNodePath(const String &path) const {
- return new POSIXFilesystemNode(path, true);
+AbstractFilesystemNode *POSIXFilesystemFactory::makeFileNodePath(const Common::String &path) const {
+ assert(!path.empty());
+ return new POSIXFilesystemNode(path);
}
#endif
diff --git a/backends/fs/posix/posix-fs-factory.h b/backends/fs/posix/posix-fs-factory.h
index d8eecda6ef..c697679814 100644
--- a/backends/fs/posix/posix-fs-factory.h
+++ b/backends/fs/posix/posix-fs-factory.h
@@ -25,7 +25,6 @@
#ifndef POSIX_FILESYSTEM_FACTORY_H
#define POSIX_FILESYSTEM_FACTORY_H
-#include "common/singleton.h"
#include "backends/fs/fs-factory.h"
/**
@@ -33,19 +32,10 @@
*
* Parts of this class are documented in the base interface class, FilesystemFactory.
*/
-class POSIXFilesystemFactory : public FilesystemFactory, public Common::Singleton<POSIXFilesystemFactory> {
-public:
- typedef Common::String String;
-
+class POSIXFilesystemFactory : public FilesystemFactory {
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
-
-protected:
- POSIXFilesystemFactory() {};
-
-private:
- friend class Common::Singleton<SingletonBaseType>;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
};
#endif /*POSIX_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/posix/posix-fs.cpp b/backends/fs/posix/posix-fs.cpp
index 10782a9057..8dca78d82a 100644
--- a/backends/fs/posix/posix-fs.cpp
+++ b/backends/fs/posix/posix-fs.cpp
@@ -24,85 +24,20 @@
#if defined(UNIX)
-#include "backends/fs/abstract-fs.h"
+#include "backends/fs/posix/posix-fs.h"
+#include "backends/fs/stdiostream.h"
+#include "common/algorithm.h"
-#ifdef MACOSX
-#include <sys/types.h>
-#endif
#include <sys/param.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>
-#include <unistd.h>
-/**
- * Implementation of the ScummVM file system API based on POSIX.
- *
- * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
- */
-class POSIXFilesystemNode : public AbstractFilesystemNode {
-protected:
- Common::String _displayName;
- Common::String _path;
- bool _isDirectory;
- bool _isValid;
-
-public:
- /**
- * Creates a POSIXFilesystemNode with the root node as path.
- */
- POSIXFilesystemNode();
-
- /**
- * Creates a POSIXFilesystemNode for a given path.
- *
- * @param path 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.
- */
- POSIXFilesystemNode(const Common::String &path, bool verify);
-
- virtual bool exists() const { return access(_path.c_str(), F_OK) == 0; }
- virtual Common::String getDisplayName() const { return _displayName; }
- virtual Common::String getName() const { return _displayName; }
- virtual Common::String getPath() const { return _path; }
- virtual bool isDirectory() const { return _isDirectory; }
- virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; }
- virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; }
-
- virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
- virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
- virtual AbstractFilesystemNode *getParent() const;
-
-private:
- /**
- * Tests and sets the _isValid and _isDirectory flags, using the stat() function.
- */
- virtual void setFlags();
-};
-
-/**
- * Returns the last component of a given path.
- *
- * Examples:
- * /foo/bar.txt would return /bar.txt
- * /foo/bar/ would return /bar/
- *
- * @param str String containing the path.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *lastPathComponent(const Common::String &str) {
- if(str.empty())
- return "";
-
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '/') {
- --cur;
- }
+#ifdef __OS2__
+#define INCL_DOS
+#include <os2.h>
+#endif
- return cur + 1;
-}
void POSIXFilesystemNode::setFlags() {
struct stat st;
@@ -111,15 +46,7 @@ void POSIXFilesystemNode::setFlags() {
_isDirectory = _isValid ? S_ISDIR(st.st_mode) : false;
}
-POSIXFilesystemNode::POSIXFilesystemNode() {
- // The root dir.
- _path = "/";
- _displayName = _path;
- _isValid = true;
- _isDirectory = true;
-}
-
-POSIXFilesystemNode::POSIXFilesystemNode(const Common::String &p, bool verify) {
+POSIXFilesystemNode::POSIXFilesystemNode(const Common::String &p) {
assert(p.size() > 0);
// Expand "~/" to the value of the HOME env variable
@@ -134,30 +61,85 @@ POSIXFilesystemNode::POSIXFilesystemNode(const Common::String &p, bool verify) {
} else {
_path = p;
}
-
- _displayName = lastPathComponent(_path);
-
- if (verify) {
- setFlags();
+
+#ifdef __OS2__
+ // On OS/2, 'X:/' is a root of drive X, so we should not remove that last
+ // slash.
+ if (!(_path.size() == 3 && _path.hasSuffix(":/")))
+#endif
+ // Normalize the path (that is, remove unneeded slashes etc.)
+ _path = Common::normalizePath(_path, '/');
+ _displayName = Common::lastPathComponent(_path, '/');
+
+ // TODO: should we turn relative paths into absolute ones?
+ // Pro: Ensures the "getParent" works correctly even for relative dirs.
+ // Contra: The user may wish to use (and keep!) relative paths in his
+ // config file, and converting relative to absolute paths may hurt him...
+ //
+ // An alternative approach would be to change getParent() to work correctly
+ // if "_path" is the empty string.
+#if 0
+ if (!_path.hasPrefix("/")) {
+ char buf[MAXPATHLEN+1];
+ getcwd(buf, MAXPATHLEN);
+ strcat(buf, "/");
+ _path = buf + _path;
}
+#endif
+ // TODO: Should we enforce that the path is absolute at this point?
+ //assert(_path.hasPrefix("/"));
+
+ setFlags();
}
AbstractFilesystemNode *POSIXFilesystemNode::getChild(const Common::String &n) const {
- // FIXME: Pretty lame implementation! We do no error checking to speak
- // of, do not check if this is a special node, etc.
+ assert(!_path.empty());
assert(_isDirectory);
+
+ // Make sure the string contains no slashes
+ assert(!n.contains('/'));
+ // We assume here that _path is already normalized (hence don't bother to call
+ // Common::normalizePath on the final path).
Common::String newPath(_path);
if (_path.lastChar() != '/')
newPath += '/';
newPath += n;
- return new POSIXFilesystemNode(newPath, true);
+ return makeNode(newPath);
}
bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
assert(_isDirectory);
+#ifdef __OS2__
+ if (_path == "/") {
+ // Special case for the root dir: List all DOS drives
+ ULONG ulDrvNum;
+ ULONG ulDrvMap;
+
+ DosQueryCurrentDisk(&ulDrvNum, &ulDrvMap);
+
+ for (int i = 0; i < 26; i++) {
+ if (ulDrvMap & 1) {
+ char drive_root[] = "A:/";
+ drive_root[0] += i;
+
+ POSIXFilesystemNode *entry = new POSIXFilesystemNode();
+ entry->_isDirectory = true;
+ entry->_isValid = true;
+ entry->_path = drive_root;
+ entry->_displayName = "[" + Common::String(drive_root, 2) + "]";
+ myList.push_back(entry);
+ }
+
+ ulDrvMap >>= 1;
+ }
+
+ return true;
+ }
+#endif
+
DIR *dirp = opendir(_path.c_str());
struct dirent *dp;
@@ -175,12 +157,12 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, boo
continue;
}
- Common::String newPath(_path);
- if (newPath.lastChar() != '/')
- newPath += '/';
- newPath += dp->d_name;
-
- POSIXFilesystemNode entry(newPath, false);
+ // Start with a clone of this node, with the correct path set
+ POSIXFilesystemNode entry(*this);
+ entry._displayName = dp->d_name;
+ if (_path.lastChar() != '/')
+ entry._path += '/';
+ entry._path += entry._displayName;
#if defined(SYSTEM_NOT_SUPPORTING_D_TYPE)
/* TODO: d_type is not part of POSIX, so it might not be supported
@@ -215,13 +197,10 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, boo
continue;
// Honor the chosen mode
- if ((mode == FilesystemNode::kListFilesOnly && entry._isDirectory) ||
- (mode == FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
+ if ((mode == Common::FilesystemNode::kListFilesOnly && entry._isDirectory) ||
+ (mode == Common::FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
continue;
- if (entry._isDirectory)
- entry._path += "/";
-
myList.push_back(new POSIXFilesystemNode(entry));
}
closedir(dirp);
@@ -231,12 +210,39 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, boo
AbstractFilesystemNode *POSIXFilesystemNode::getParent() const {
if (_path == "/")
- return 0;
+ return 0; // The filesystem root has no parent
+
+#ifdef __OS2__
+ if (_path.size() == 3 && _path.hasSuffix(":/"))
+ // This is a root directory of a drive
+ return makeNode("/"); // return a virtual root for a list of drives
+#endif
const char *start = _path.c_str();
- const char *end = lastPathComponent(_path);
+ const char *end = start + _path.size();
+
+ // Strip of the last component. We make use of the fact that at this
+ // point, _path is guaranteed to be normalized
+ while (end > start && *(end-1) != '/')
+ end--;
+
+ if (end == start) {
+ // This only happens if we were called with a relative path, for which
+ // there simply is no parent.
+ // TODO: We could also resolve this by assuming that the parent is the
+ // current working directory, and returning a node referring to that.
+ return 0;
+ }
+
+ return makeNode(Common::String(start, end));
+}
+
+Common::SeekableReadStream *POSIXFilesystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
- return new POSIXFilesystemNode(Common::String(start, end - start), true);
+Common::WriteStream *POSIXFilesystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
}
#endif //#if defined(UNIX)
diff --git a/backends/fs/posix/posix-fs.h b/backends/fs/posix/posix-fs.h
new file mode 100644
index 0000000000..e09e433e05
--- /dev/null
+++ b/backends/fs/posix/posix-fs.h
@@ -0,0 +1,86 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * 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 POSIX_FILESYSTEM_H
+#define POSIX_FILESYSTEM_H
+
+#include "backends/fs/abstract-fs.h"
+
+#ifdef MACOSX
+#include <sys/types.h>
+#endif
+#include <unistd.h>
+
+/**
+ * Implementation of the ScummVM file system API based on POSIX.
+ *
+ * Parts of this class are documented in the base interface class, AbstractFilesystemNode.
+ */
+class POSIXFilesystemNode : public AbstractFilesystemNode {
+protected:
+ Common::String _displayName;
+ Common::String _path;
+ bool _isDirectory;
+ bool _isValid;
+
+ virtual AbstractFilesystemNode *makeNode(const Common::String &path) const {
+ return new POSIXFilesystemNode(path);
+ }
+
+ /**
+ * Plain constructor, for internal use only (hence protected).
+ */
+ POSIXFilesystemNode() : _isDirectory(false), _isValid(false) {}
+
+public:
+ /**
+ * Creates a POSIXFilesystemNode for a given path.
+ *
+ * @param path the path the new node should point to.
+ */
+ POSIXFilesystemNode(const Common::String &path);
+
+ virtual bool exists() const { return access(_path.c_str(), F_OK) == 0; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
+ virtual bool isDirectory() const { return _isDirectory; }
+ virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; }
+ virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; }
+
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
+ virtual AbstractFilesystemNode *getParent() const;
+
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+
+private:
+ /**
+ * Tests and sets the _isValid and _isDirectory flags, using the stat() function.
+ */
+ virtual void setFlags();
+};
+
+#endif /*POSIX_FILESYSTEM_H*/
diff --git a/backends/fs/ps2/ps2-fs-factory.cpp b/backends/fs/ps2/ps2-fs-factory.cpp
index ce3b4a5eaf..e96671ee0a 100644
--- a/backends/fs/ps2/ps2-fs-factory.cpp
+++ b/backends/fs/ps2/ps2-fs-factory.cpp
@@ -36,7 +36,7 @@ AbstractFilesystemNode *Ps2FilesystemFactory::makeCurrentDirectoryFileNode() con
return new Ps2FilesystemNode();
}
-AbstractFilesystemNode *Ps2FilesystemFactory::makeFileNodePath(const String &path) const {
+AbstractFilesystemNode *Ps2FilesystemFactory::makeFileNodePath(const Common::String &path) const {
// return new Ps2FilesystemNode(path);
Ps2FilesystemNode *nf = new Ps2FilesystemNode(path, true);
diff --git a/backends/fs/ps2/ps2-fs-factory.h b/backends/fs/ps2/ps2-fs-factory.h
index 416024c905..432cf467c3 100644
--- a/backends/fs/ps2/ps2-fs-factory.h
+++ b/backends/fs/ps2/ps2-fs-factory.h
@@ -35,11 +35,9 @@
*/
class Ps2FilesystemFactory : public FilesystemFactory, public Common::Singleton<Ps2FilesystemFactory> {
public:
- typedef Common::String String;
-
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
protected:
Ps2FilesystemFactory() {};
diff --git a/backends/fs/ps2/ps2-fs.cpp b/backends/fs/ps2/ps2-fs.cpp
index 782e97b959..3d7656e9f0 100644
--- a/backends/fs/ps2/ps2-fs.cpp
+++ b/backends/fs/ps2/ps2-fs.cpp
@@ -23,6 +23,7 @@
*/
#include "backends/fs/abstract-fs.h"
+#include "backends/fs/stdiostream.h"
#include <kernel.h>
#include <stdio.h>
#include <stdlib.h>
@@ -47,8 +48,8 @@ class Ps2FilesystemNode : public AbstractFilesystemNode {
friend class Ps2FilesystemFactory;
protected:
- String _displayName;
- String _path;
+ Common::String _displayName;
+ Common::String _path;
bool _isDirectory;
bool _isRoot;
@@ -65,10 +66,10 @@ public:
/**
* Creates a PS2FilesystemNode for a given path.
*
- * @param path String with the path the new node should point to.
+ * @param path Common::String with the path the new node should point to.
*/
- Ps2FilesystemNode(const String &path);
- Ps2FilesystemNode(const String &path, bool verify);
+ Ps2FilesystemNode(const Common::String &path);
+ Ps2FilesystemNode(const Common::String &path, bool verify);
/**
* Copy constructor.
@@ -77,9 +78,9 @@ public:
virtual bool exists(void) const;
- virtual String getDisplayName() const { return _displayName; }
- virtual String getName() const { return _displayName; }
- virtual String getPath() const { return _path; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const {
return _isDirectory;
@@ -95,32 +96,13 @@ public:
}
virtual AbstractFilesystemNode *clone() const { return new Ps2FilesystemNode(this); }
- virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
-};
-
-/**
- * Returns the last component of a given path.
- *
- * @param str String containing the path.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *lastPathComponent(const Common::String &str) {
- if (str.empty())
- return "";
-
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '/' && *cur != ':') {
- --cur;
- }
-
- printf("romeo : lastPathComponent = %s\n", cur + 1);
- return cur + 1;
-}
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+};
Ps2FilesystemNode::Ps2FilesystemNode() {
_isDirectory = true;
@@ -129,12 +111,12 @@ Ps2FilesystemNode::Ps2FilesystemNode() {
_path = "";
}
-Ps2FilesystemNode::Ps2FilesystemNode(const String &path) {
+Ps2FilesystemNode::Ps2FilesystemNode(const Common::String &path) {
_path = path;
_isDirectory = true;
if (strcmp(path.c_str(), "") == 0) {
_isRoot = true;
- _displayName = String("PlayStation 2");
+ _displayName = Common::String("PlayStation 2");
} else {
_isRoot = false;
const char *dsplName = NULL, *pos = path.c_str();
@@ -142,18 +124,18 @@ Ps2FilesystemNode::Ps2FilesystemNode(const String &path) {
if (*pos++ == '/')
dsplName = pos;
if (dsplName)
- _displayName = String(dsplName);
+ _displayName = Common::String(dsplName);
else
_displayName = getDeviceDescription(path.c_str());
}
}
-Ps2FilesystemNode::Ps2FilesystemNode(const String &path, bool verify) {
+Ps2FilesystemNode::Ps2FilesystemNode(const Common::String &path, bool verify) {
_path = path;
if (strcmp(path.c_str(), "") == 0) {
_isRoot = true; /* root is always a dir*/
- _displayName = String("PlayStation 2");
+ _displayName = Common::String("PlayStation 2");
_isDirectory = true;
} else {
_isRoot = false;
@@ -163,7 +145,7 @@ Ps2FilesystemNode::Ps2FilesystemNode(const String &path, bool verify) {
dsplName = pos;
if (dsplName) {
- _displayName = String(dsplName);
+ _displayName = Common::String(dsplName);
if (verify)
_isDirectory = getDirectoryFlag(path.c_str());
else
@@ -228,7 +210,7 @@ bool Ps2FilesystemNode::getDirectoryFlag(const char *path) {
return false;
}
-AbstractFilesystemNode *Ps2FilesystemNode::getChild(const String &n) const {
+AbstractFilesystemNode *Ps2FilesystemNode::getChild(const Common::String &n) const {
if (!_isDirectory)
return NULL;
@@ -306,9 +288,9 @@ bool Ps2FilesystemNode::getChildren(AbstractFSList &list, ListMode mode, bool hi
while ((dreadRes = fio.dread(fd, &dirent)) > 0) {
if (dirent.name[0] == '.')
continue; // ignore '.' and '..'
- if (((mode == FilesystemNode::kListDirectoriesOnly) && (dirent.stat.mode & FIO_S_IFDIR)) ||
- ((mode == FilesystemNode::kListFilesOnly) && !(dirent.stat.mode & FIO_S_IFDIR)) ||
- (mode == FilesystemNode::kListAll)) {
+ if (((mode == Common::FilesystemNode::kListDirectoriesOnly) && (dirent.stat.mode & FIO_S_IFDIR)) ||
+ ((mode == Common::FilesystemNode::kListFilesOnly) && !(dirent.stat.mode & FIO_S_IFDIR)) ||
+ (mode == Common::FilesystemNode::kListAll)) {
dirEntry._isDirectory = (bool)(dirent.stat.mode & FIO_S_IFDIR);
dirEntry._isRoot = false;
@@ -344,7 +326,7 @@ AbstractFilesystemNode *Ps2FilesystemNode::getParent() const {
}
if (slash)
- return new Ps2FilesystemNode(String(_path.c_str(), slash - _path.c_str()));
+ return new Ps2FilesystemNode(Common::String(_path.c_str(), slash - _path.c_str()));
else
return new Ps2FilesystemNode();
}
@@ -359,3 +341,10 @@ char *Ps2FilesystemNode::getDeviceDescription(const char *path) const {
return "Harddisk";
}
+Common::SeekableReadStream *Ps2FilesystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
+
+Common::WriteStream *Ps2FilesystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
+}
diff --git a/backends/fs/psp/psp-fs-factory.cpp b/backends/fs/psp/psp-fs-factory.cpp
index 87f0e0f587..a38462f02a 100644
--- a/backends/fs/psp/psp-fs-factory.cpp
+++ b/backends/fs/psp/psp-fs-factory.cpp
@@ -36,7 +36,7 @@ AbstractFilesystemNode *PSPFilesystemFactory::makeCurrentDirectoryFileNode() con
return new PSPFilesystemNode();
}
-AbstractFilesystemNode *PSPFilesystemFactory::makeFileNodePath(const String &path) const {
+AbstractFilesystemNode *PSPFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new PSPFilesystemNode(path, true);
}
#endif
diff --git a/backends/fs/psp/psp-fs-factory.h b/backends/fs/psp/psp-fs-factory.h
index ffa934755f..abf03d288e 100644
--- a/backends/fs/psp/psp-fs-factory.h
+++ b/backends/fs/psp/psp-fs-factory.h
@@ -35,11 +35,9 @@
*/
class PSPFilesystemFactory : public FilesystemFactory, public Common::Singleton<PSPFilesystemFactory> {
public:
- typedef Common::String String;
-
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
protected:
PSPFilesystemFactory() {};
diff --git a/backends/fs/psp/psp-fs.cpp b/backends/fs/psp/psp-fs.cpp
index 3fe6060928..13cd63903b 100644
--- a/backends/fs/psp/psp-fs.cpp
+++ b/backends/fs/psp/psp-fs.cpp
@@ -26,6 +26,7 @@
#include "engines/engine.h"
#include "backends/fs/abstract-fs.h"
+#include "backends/fs/stdiostream.h"
#include <sys/stat.h>
#include <unistd.h>
@@ -39,8 +40,8 @@
*/
class PSPFilesystemNode : public AbstractFilesystemNode {
protected:
- String _displayName;
- String _path;
+ Common::String _displayName;
+ Common::String _path;
bool _isDirectory;
bool _isValid;
@@ -53,47 +54,26 @@ public:
/**
* Creates a PSPFilesystemNode for a given path.
*
- * @param path 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.
*/
PSPFilesystemNode(const Common::String &p, bool verify);
virtual bool exists() const { return access(_path.c_str(), F_OK) == 0; }
- virtual String getDisplayName() const { return _displayName; }
- virtual String getName() const { return _displayName; }
- virtual String getPath() const { return _path; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; }
virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; }
- virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
-};
-
-/**
- * Returns the last component of a given path.
- *
- * Examples:
- * /foo/bar.txt would return /bar.txt
- * /foo/bar/ would return /bar/
- *
- * @param str String containing the path.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *lastPathComponent(const Common::String &str) {
- if(str.empty())
- return "";
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '/') {
- --cur;
- }
-
- return cur + 1;
-}
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+};
PSPFilesystemNode::PSPFilesystemNode() {
_isDirectory = true;
@@ -106,7 +86,7 @@ PSPFilesystemNode::PSPFilesystemNode(const Common::String &p, bool verify) {
assert(p.size() > 0);
_path = p;
- _displayName = lastPathComponent(_path);
+ _displayName = lastPathComponent(_path, '/');
_isValid = true;
_isDirectory = true;
@@ -117,12 +97,12 @@ PSPFilesystemNode::PSPFilesystemNode(const Common::String &p, bool verify) {
}
}
-AbstractFilesystemNode *PSPFilesystemNode::getChild(const String &n) const {
+AbstractFilesystemNode *PSPFilesystemNode::getChild(const Common::String &n) const {
// FIXME: Pretty lame implementation! We do no error checking to speak
// of, do not check if this is a special node, etc.
assert(_isDirectory);
- String newPath(_path);
+ Common::String newPath(_path);
if (_path.lastChar() != '/')
newPath += '/';
newPath += n;
@@ -157,8 +137,8 @@ bool PSPFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool
entry._path += "/";
// Honor the chosen mode
- if ((mode == FilesystemNode::kListFilesOnly && entry._isDirectory) ||
- (mode == FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
+ if ((mode == Common::FilesystemNode::kListFilesOnly && entry._isDirectory) ||
+ (mode == Common::FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
continue;
myList.push_back(new PSPFilesystemNode(entry));
@@ -176,9 +156,17 @@ AbstractFilesystemNode *PSPFilesystemNode::getParent() const {
return 0;
const char *start = _path.c_str();
- const char *end = lastPathComponent(_path);
+ const char *end = lastPathComponent(_path, '/');
+
+ return new PSPFilesystemNode(Common::String(start, end - start), false);
+}
+
+Common::SeekableReadStream *PSPFilesystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
- return new PSPFilesystemNode(String(start, end - start), false);
+Common::WriteStream *PSPFilesystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
}
#endif //#ifdef __PSP__
diff --git a/backends/fs/stdiostream.cpp b/backends/fs/stdiostream.cpp
new file mode 100644
index 0000000000..3b0de253ab
--- /dev/null
+++ b/backends/fs/stdiostream.cpp
@@ -0,0 +1,161 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * 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 "backends/fs/stdiostream.h"
+
+#include <errno.h>
+
+#if defined(MACOSX) || defined(IPHONE)
+#include "CoreFoundation/CoreFoundation.h"
+#endif
+
+
+#ifdef __PLAYSTATION2__
+ // for those replaced fopen/fread/etc functions
+ typedef unsigned long uint64;
+ typedef signed long int64;
+ #include "backends/platform/ps2/fileio.h"
+
+ #define fopen(a, b) ps2_fopen(a, b)
+ #define fclose(a) ps2_fclose(a)
+ #define fseek(a, b, c) ps2_fseek(a, b, c)
+ #define ftell(a) ps2_ftell(a)
+ #define feof(a) ps2_feof(a)
+ #define fread(a, b, c, d) ps2_fread(a, b, c, d)
+ #define fwrite(a, b, c, d) ps2_fwrite(a, b, c, d)
+
+ //#define fprintf ps2_fprintf // used in common/util.cpp
+ //#define fflush(a) ps2_fflush(a) // used in common/util.cpp
+
+ //#define fgetc(a) ps2_fgetc(a) // not used
+ //#define fgets(a, b, c) ps2_fgets(a, b, c) // not used
+ //#define fputc(a, b) ps2_fputc(a, b) // not used
+ //#define fputs(a, b) ps2_fputs(a, b) // not used
+
+ //#define fsize(a) ps2_fsize(a) // not used -- and it is not a standard function either
+#endif
+
+#ifdef __DS__
+
+ // These functions replace the standard library functions of the same name.
+ // As this header is included after the standard one, I have the chance to #define
+ // all of these to my own code.
+ //
+ // A #define is the only way, as redefinig the functions would cause linker errors.
+
+ // These functions need to be #undef'ed, as their original definition
+ // in devkitarm is done with #includes (ugh!)
+ #undef feof
+ #undef clearerr
+ //#undef getc
+ //#undef ferror
+
+ #include "backends/fs/ds/ds-fs.h"
+
+
+ // Only functions used in the ScummVM source have been defined here!
+ #define fopen(name, mode) DS::std_fopen(name, mode)
+ #define fclose(handle) DS::std_fclose(handle)
+ #define fread(ptr, size, items, file) DS::std_fread(ptr, size, items, file)
+ #define fwrite(ptr, size, items, file) DS::std_fwrite(ptr, size, items, file)
+ #define feof(handle) DS::std_feof(handle)
+ #define ftell(handle) DS::std_ftell(handle)
+ #define fseek(handle, offset, whence) DS::std_fseek(handle, offset, whence)
+ #define clearerr(handle) DS::std_clearerr(handle)
+ #define fflush(file) DS::std_fflush(file)
+ #define ferror(handle) DS::std_ferror(handle)
+
+#endif
+
+StdioStream::StdioStream(void *handle) : _handle(handle) {
+ assert(handle);
+}
+
+StdioStream::~StdioStream() {
+ fclose((FILE *)_handle);
+}
+
+bool StdioStream::err() const {
+ return ferror((FILE *)_handle) != 0;
+}
+
+void StdioStream::clearErr() {
+ clearerr((FILE *)_handle);
+}
+
+bool StdioStream::eos() const {
+ return feof((FILE *)_handle) != 0;
+}
+
+int32 StdioStream::pos() const {
+ return ftell((FILE *)_handle);
+}
+
+int32 StdioStream::size() const {
+ int32 oldPos = ftell((FILE *)_handle);
+ fseek((FILE *)_handle, 0, SEEK_END);
+ int32 length = ftell((FILE *)_handle);
+ fseek((FILE *)_handle, oldPos, SEEK_SET);
+
+ return length;
+}
+
+bool StdioStream::seek(int32 offs, int whence) {
+ return fseek((FILE *)_handle, offs, whence) == 0;
+}
+
+uint32 StdioStream::read(void *ptr, uint32 len) {
+ return fread((byte *)ptr, 1, len, (FILE *)_handle);
+}
+
+uint32 StdioStream::write(const void *ptr, uint32 len) {
+ return fwrite(ptr, 1, len, (FILE *)_handle);
+}
+
+bool StdioStream::flush() {
+ return fflush((FILE *)_handle) == 0;
+}
+
+StdioStream *StdioStream::makeFromPath(const Common::String &path, bool writeMode) {
+ FILE *handle = fopen(path.c_str(), writeMode ? "wb" : "rb");
+
+#ifdef __amigaos4__
+ //
+ // Work around for possibility that someone uses AmigaOS "newlib" build
+ // with SmartFileSystem (blocksize 512 bytes), leading to buffer size
+ // being only 512 bytes. "Clib2" sets the buffer size to 8KB, resulting
+ // smooth movie playback. This forces the buffer to be enough also when
+ // using "newlib" compile on SFS.
+ //
+ if (handle && !writeMode) {
+ setvbuf(handle, NULL, _IOFBF, 8192);
+ }
+#endif
+
+
+ if (handle)
+ return new StdioStream(handle);
+ return 0;
+}
diff --git a/backends/fs/stdiostream.h b/backends/fs/stdiostream.h
new file mode 100644
index 0000000000..3d44062d7f
--- /dev/null
+++ b/backends/fs/stdiostream.h
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * 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 BACKENDS_FS_STDIOSTREAM_H
+#define BACKENDS_FS_STDIOSTREAM_H
+
+#include "common/scummsys.h"
+#include "common/noncopyable.h"
+#include "common/stream.h"
+#include "common/str.h"
+
+class StdioStream : public Common::SeekableReadStream, public Common::WriteStream, public Common::NonCopyable {
+protected:
+ /** File handle to the actual file. */
+ void *_handle;
+
+public:
+ /**
+ * Given a path, invokes fopen on that path and wrap the result in a
+ * StdioStream instance.
+ */
+ static StdioStream *makeFromPath(const Common::String &path, bool writeMode);
+
+ StdioStream(void *handle);
+ virtual ~StdioStream();
+
+ 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;
+ bool seek(int32 offs, int whence = SEEK_SET);
+ uint32 read(void *dataPtr, uint32 dataSize);
+};
+
+#endif
diff --git a/backends/fs/symbian/symbian-fs-factory.cpp b/backends/fs/symbian/symbian-fs-factory.cpp
index 0a1bd62134..c31dfb594a 100644
--- a/backends/fs/symbian/symbian-fs-factory.cpp
+++ b/backends/fs/symbian/symbian-fs-factory.cpp
@@ -26,8 +26,6 @@
#include "backends/fs/symbian/symbian-fs-factory.h"
#include "backends/fs/symbian/symbian-fs.cpp"
-DECLARE_SINGLETON(SymbianFilesystemFactory);
-
AbstractFilesystemNode *SymbianFilesystemFactory::makeRootFileNode() const {
return new SymbianFilesystemNode(true);
}
@@ -38,7 +36,7 @@ AbstractFilesystemNode *SymbianFilesystemFactory::makeCurrentDirectoryFileNode()
return new SymbianFilesystemNode(path);
}
-AbstractFilesystemNode *SymbianFilesystemFactory::makeFileNodePath(const String &path) const {
+AbstractFilesystemNode *SymbianFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new SymbianFilesystemNode(path);
}
#endif
diff --git a/backends/fs/symbian/symbian-fs-factory.h b/backends/fs/symbian/symbian-fs-factory.h
index 502fba2930..ef5a231e72 100644
--- a/backends/fs/symbian/symbian-fs-factory.h
+++ b/backends/fs/symbian/symbian-fs-factory.h
@@ -25,7 +25,6 @@
#ifndef SYMBIAN_FILESYSTEM_FACTORY_H
#define SYMBIAN_FILESYSTEM_FACTORY_H
-#include "common/singleton.h"
#include "backends/fs/fs-factory.h"
/**
@@ -33,19 +32,11 @@
*
* Parts of this class are documented in the base interface class, FilesystemFactory.
*/
-class SymbianFilesystemFactory : public FilesystemFactory, public Common::Singleton<SymbianFilesystemFactory> {
+class SymbianFilesystemFactory : public FilesystemFactory {
public:
- typedef Common::String String;
-
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
-
-protected:
- SymbianFilesystemFactory() {};
-
-private:
- friend class Common::Singleton<SingletonBaseType>;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
};
#endif /*SYMBIAN_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/symbian/symbian-fs.cpp b/backends/fs/symbian/symbian-fs.cpp
index 85fc58179a..1c6d8435a9 100644
--- a/backends/fs/symbian/symbian-fs.cpp
+++ b/backends/fs/symbian/symbian-fs.cpp
@@ -24,12 +24,16 @@
#if defined (__SYMBIAN32__)
#include "backends/fs/abstract-fs.h"
+#include "backends/fs/symbian/symbianstream.h"
+#include "backends/platform/symbian/src/symbianos.h"
#include <dirent.h>
#include <eikenv.h>
#include <f32file.h>
#include <bautils.h>
+#define KDriveLabelSize 30
+
/**
* Implementation of the ScummVM file system API based on POSIX.
*
@@ -37,12 +41,11 @@
*/
class SymbianFilesystemNode : public AbstractFilesystemNode {
protected:
- String _displayName;
- String _path;
- bool _isDirectory;
- bool _isValid;
- bool _isPseudoRoot;
-
+ Common::String _displayName;
+ Common::String _path;
+ TBool _isDirectory;
+ TBool _isValid;
+ TBool _isPseudoRoot;
public:
/**
* Creates a SymbianFilesystemNode with the root node as path.
@@ -54,57 +57,36 @@ public:
/**
* Creates a SymbianFilesystemNode for a given path.
*
- * @param path String with the path the new node should point to.
+ * @param path Common::String with the path the new node should point to.
*/
- SymbianFilesystemNode(const String &path);
+ SymbianFilesystemNode(const Common::String &path);
virtual bool exists() const {
TFileName fname;
- TPtrC8 ptr((const unsigned char*)_path.c_str(),_path.size());
+ TPtrC8 ptr((const unsigned char*) _path.c_str(), _path.size());
fname.Copy(ptr);
- TBool fileExists = BaflUtils::FileExists(CEikonEnv::Static()->FsSession(), fname);
+ TBool fileExists = BaflUtils::FileExists(static_cast<OSystem_SDL_Symbian*> (g_system)->FsSession(), fname);
return fileExists;
}
- virtual String getDisplayName() const { return _displayName; }
- virtual String getName() const { return _displayName; }
- virtual String getPath() const { return _path; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; } //FIXME: this is just a stub
virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; } //FIXME: this is just a stub
- virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
-};
-/**
- * Returns the last component of a given path.
- *
- * Examples:
- * c:\foo\bar.txt would return "\bar.txt"
- * c:\foo\bar\ would return "\bar\"
- *
- * @param str Path to obtain the last component from.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *lastPathComponent(const Common::String &str) {
- if(str.empty())
- return "";
-
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '\\') {
- --cur;
- }
-
- return cur + 1;
-}
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+};
/**
* Fixes the path by changing all slashes to backslashes.
*
- * @param path String with the path to be fixed.
+ * @param path Common::String with the path to be fixed.
*/
static void fixFilePath(Common::String& aPath){
TInt len = aPath.size();
@@ -118,54 +100,47 @@ static void fixFilePath(Common::String& aPath){
SymbianFilesystemNode::SymbianFilesystemNode(bool aIsRoot) {
_path = "";
- _isValid = true;
- _isDirectory = true;
+ _isValid = ETrue;
+ _isDirectory = ETrue;
_isPseudoRoot = aIsRoot;
_displayName = "Root";
}
-SymbianFilesystemNode::SymbianFilesystemNode(const String &path) {
+SymbianFilesystemNode::SymbianFilesystemNode(const Common::String &path) {
if (path.size() == 0)
- _isPseudoRoot = true;
+ _isPseudoRoot = ETrue;
else
- _isPseudoRoot = false;
+ _isPseudoRoot = EFalse;
_path = path;
fixFilePath(_path);
- _displayName = lastPathComponent(_path);
+ _displayName = lastPathComponent(_path, '\\');
TEntry fileAttribs;
TFileName fname;
TPtrC8 ptr((const unsigned char*)_path.c_str(),_path.size());
fname.Copy(ptr);
- if (CEikonEnv::Static()->FsSession().Entry(fname, fileAttribs) == KErrNone) {
- _isValid = true;
+ if (static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession().Entry(fname, fileAttribs) == KErrNone) {
+ _isValid = ETrue;
_isDirectory = fileAttribs.IsDir();
} else {
- _isValid = false;
- _isDirectory = false;
+ _isValid = ETrue;
+ _isDirectory = EFalse;
}
}
-AbstractFilesystemNode *SymbianFilesystemNode::getChild(const String &n) const {
+AbstractFilesystemNode *SymbianFilesystemNode::getChild(const Common::String &n) const {
assert(_isDirectory);
- String newPath(_path);
+ Common::String newPath(_path);
if (_path.lastChar() != '\\')
newPath += '\\';
- newPath += n;
- TPtrC8 ptr((const unsigned char*) newPath.c_str(), newPath.size());
- TFileName fname;
- fname.Copy(ptr);
- TBool isFolder = EFalse;
- BaflUtils::IsFolder(CEikonEnv::Static()->FsSession(), fname, isFolder);
- if (!isFolder)
- return 0;
+ newPath += n;
return new SymbianFilesystemNode(newPath);
}
@@ -177,19 +152,19 @@ bool SymbianFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b
if (_isPseudoRoot) {
// Drives enumeration
- RFs fs = CEikonEnv::Static()->FsSession();
+ RFs& fs = static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession();
TInt driveNumber;
TChar driveLetter;
TUint driveLetterValue;
TVolumeInfo volumeInfo;
- TBuf8<30> driveLabel8;
- TBuf8<30> driveString8;
+ TBuf8<KDriveLabelSize> driveLabel8;
+ TBuf8<KDriveLabelSize> driveString8;
for (driveNumber=EDriveA; driveNumber<=EDriveZ; driveNumber++) {
TInt err = fs.Volume(volumeInfo, driveNumber);
if (err != KErrNone)
continue;
- if (fs.DriveToChar(driveNumber,driveLetter) != KErrNone)
+ if (fs.DriveToChar(driveNumber, driveLetter) != KErrNone)
continue;
driveLetterValue = driveLetter;
@@ -205,40 +180,46 @@ bool SymbianFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b
sprintf(path,"%c:\\", driveNumber+'A');
SymbianFilesystemNode entry(false);
- entry._displayName = (char*)driveString8.PtrZ(); // drive_name
- entry._isDirectory = true;
- entry._isValid = true;
- entry._isPseudoRoot = false;
+ entry._displayName = (char*) driveString8.PtrZ(); // drive_name
+ entry._isDirectory = ETrue;
+ entry._isValid = ETrue;
+ entry._isPseudoRoot = EFalse;
entry._path = path;
myList.push_back(new SymbianFilesystemNode(entry));
}
} else {
- TPtrC8 ptr((const unsigned char*)_path.c_str(),_path.size());
+ TPtrC8 ptr((const unsigned char*) _path.c_str(), _path.size());
TFileName fname;
- fname.Copy(ptr);
TBuf8<256>nameBuf;
CDir* dirPtr;
- if (CEikonEnv::Static()->FsSession().GetDir(fname,KEntryAttNormal|KEntryAttDir,0,dirPtr)==KErrNone) {
+ fname.Copy(ptr);
+
+ if (_path.lastChar() != '\\')
+ fname.Append('\\');
+
+ if (static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession().GetDir(fname, KEntryAttNormal|KEntryAttDir, 0, dirPtr) == KErrNone) {
CleanupStack::PushL(dirPtr);
TInt cnt=dirPtr->Count();
for (TInt loop=0;loop<cnt;loop++) {
TEntry fileentry=(*dirPtr)[loop];
nameBuf.Copy(fileentry.iName);
- SymbianFilesystemNode entry(false);
- entry._isPseudoRoot = false;
+ SymbianFilesystemNode entry(EFalse);
+ entry._isPseudoRoot = EFalse;
- entry._displayName =(char*)nameBuf.PtrZ();
+ entry._displayName =(char*) nameBuf.PtrZ();
entry._path = _path;
- entry._path +=(char*)nameBuf.PtrZ();
+
+ if (entry._path.lastChar() != '\\')
+ entry._path+= '\\';
+
+ entry._path +=(char*) nameBuf.PtrZ();
entry._isDirectory = fileentry.IsDir();
// Honor the chosen mode
- if ((mode == FilesystemNode::kListFilesOnly && entry._isDirectory) ||
- (mode == FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
+ if ((mode == Common::FilesystemNode::kListFilesOnly && entry._isDirectory) ||
+ (mode == Common::FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
continue;
-
- if (entry._isDirectory)
- entry._path += "\\";
+
myList.push_back(new SymbianFilesystemNode(entry));
}
CleanupStack::PopAndDestroy(dirPtr);
@@ -254,21 +235,30 @@ AbstractFilesystemNode *SymbianFilesystemNode::getParent() const {
// Root node is its own parent. Still we can't just return this
// as the GUI code will call delete on the old node.
if (!_isPseudoRoot && _path.size() > 3) {
- p = new SymbianFilesystemNode(false);
+ p = new SymbianFilesystemNode(EFalse);
const char *start = _path.c_str();
- const char *end = lastPathComponent(_path);
+ const char *end = lastPathComponent(_path, '\\');
- p->_path = String(start, end - start);
- p->_isValid = true;
- p->_isDirectory = true;
- p->_displayName = lastPathComponent(p->_path);
+ p->_path = Common::String(start, end - start);
+ p->_isValid = ETrue;
+ p->_isDirectory = ETrue;
+ p->_displayName = lastPathComponent(p->_path, '\\');
}
else
{
- p = new SymbianFilesystemNode(true);
+ p = new SymbianFilesystemNode(ETrue);
}
return p;
}
+Common::SeekableReadStream *SymbianFilesystemNode::openForReading() {
+ return SymbianStdioStream::makeFromPath(getPath().c_str(), false);
+}
+
+Common::WriteStream *SymbianFilesystemNode::openForWriting() {
+ return SymbianStdioStream::makeFromPath(getPath().c_str(), true);
+}
#endif //#if defined (__SYMBIAN32__)
+
+
diff --git a/backends/fs/symbian/symbianstream.cpp b/backends/fs/symbian/symbianstream.cpp
new file mode 100644
index 0000000000..5944cab892
--- /dev/null
+++ b/backends/fs/symbian/symbianstream.cpp
@@ -0,0 +1,274 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * 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/scummsys.h"
+#include "backends/fs/symbian/symbianstream.h"
+#include "common/system.h"
+#include "backends/platform/symbian/src/symbianos.h"
+
+#include <f32file.h>
+
+#define KInputBufferLength 128
+
+// Symbian libc file functionality in order to provide shared file handles
+class TSymbianFileEntry {
+public:
+ RFile _fileHandle;
+ char _inputBuffer[KInputBufferLength];
+ TInt _inputBufferLen;
+ TInt _inputPos;
+ TInt _lastError;
+ TBool _eofReached;
+};
+
+TSymbianFileEntry* CreateSymbianFileEntry(const char* name, const char* mode) {
+ TSymbianFileEntry* fileEntry = new TSymbianFileEntry;
+ fileEntry->_inputPos = KErrNotFound;
+ fileEntry->_lastError = 0;
+ fileEntry->_eofReached = EFalse;
+
+ if (fileEntry != NULL) {
+ TInt modeLen = strlen(mode);
+
+ TPtrC8 namePtr((unsigned char*) name, strlen(name));
+ TFileName tempFileName;
+ tempFileName.Copy(namePtr);
+
+ TInt fileMode = EFileRead;
+
+ if (mode[0] == 'a')
+ fileMode = EFileWrite;
+
+ if (!((modeLen > 1 && mode[1] == 'b') || (modeLen > 2 && mode[2] == 'b'))) {
+ fileMode |= EFileStreamText;
+ }
+
+ if ((modeLen > 1 && mode[1] == '+') || (modeLen > 2 && mode[2] == '+')) {
+ fileMode = fileMode| EFileWrite;
+ }
+
+ fileMode = fileMode| EFileShareAny;
+
+ switch(mode[0]) {
+ case 'a':
+ if (fileEntry->_fileHandle.Open(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) {
+ if (fileEntry->_fileHandle.Create(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) {
+ delete fileEntry;
+ fileEntry = NULL;
+ }
+ }
+ break;
+ case 'r':
+ if (fileEntry->_fileHandle.Open(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) {
+ delete fileEntry;
+ fileEntry = NULL;
+ }
+ break;
+
+ case 'w':
+ if (fileEntry->_fileHandle.Replace(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) {
+ delete fileEntry;
+ fileEntry = NULL;
+ }
+ break;
+ }
+ }
+ return fileEntry;
+}
+
+size_t ReadData(const void* ptr, size_t size, size_t numItems, TSymbianFileEntry* handle) {
+ TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle));
+ TUint32 totsize = size*numItems;
+ TPtr8 pointer ( (unsigned char*) ptr, totsize);
+
+ // Nothing cached and we want to load at least KInputBufferLength bytes
+ if (totsize >= KInputBufferLength) {
+ TUint32 totLength = 0;
+ if (entry->_inputPos != KErrNotFound) {
+ TPtr8 cacheBuffer( (unsigned char*) entry->_inputBuffer+entry->_inputPos, entry->_inputBufferLen - entry->_inputPos, KInputBufferLength);
+ pointer.Append(cacheBuffer);
+ entry->_inputPos = KErrNotFound;
+ totLength+=pointer.Length();
+ pointer.Set(totLength+(unsigned char*) ptr, 0, totsize-totLength);
+ }
+
+ entry->_lastError = entry->_fileHandle.Read(pointer);
+
+ totLength+=pointer.Length();
+
+ pointer.Set((unsigned char*) ptr, totLength, totsize);
+
+ } else {
+ // Nothing in buffer
+ if (entry->_inputPos == KErrNotFound) {
+ TPtr8 cacheBuffer( (unsigned char*) entry->_inputBuffer, KInputBufferLength);
+ entry->_lastError = entry->_fileHandle.Read(cacheBuffer);
+
+ if (cacheBuffer.Length() >= totsize) {
+ pointer.Copy(cacheBuffer.Left(totsize));
+ entry->_inputPos = totsize;
+ entry->_inputBufferLen = cacheBuffer.Length();
+ } else {
+ pointer.Copy(cacheBuffer);
+ entry->_inputPos = KErrNotFound;
+ }
+
+ } else {
+ TPtr8 cacheBuffer( (unsigned char*) entry->_inputBuffer, entry->_inputBufferLen, KInputBufferLength);
+
+ if (entry->_inputPos+totsize < entry->_inputBufferLen) {
+ pointer.Copy(cacheBuffer.Mid(entry->_inputPos, totsize));
+ entry->_inputPos+=totsize;
+ } else {
+
+ pointer.Copy(cacheBuffer.Mid(entry->_inputPos, entry->_inputBufferLen-entry->_inputPos));
+ cacheBuffer.SetLength(0);
+ entry->_lastError = entry->_fileHandle.Read(cacheBuffer);
+
+ if (cacheBuffer.Length() >= totsize-pointer.Length()) {
+ TUint32 restSize = totsize-pointer.Length();
+ pointer.Append(cacheBuffer.Left(restSize));
+ entry->_inputPos = restSize;
+ entry->_inputBufferLen = cacheBuffer.Length();
+ } else {
+ pointer.Append(cacheBuffer);
+ entry->_inputPos = KErrNotFound;
+ }
+ }
+ }
+ }
+
+ if((numItems * size) != pointer.Length() && entry->_lastError == KErrNone) {
+ entry->_eofReached = ETrue;
+ }
+
+ return pointer.Length() / size;
+}
+
+SymbianStdioStream::SymbianStdioStream(void *handle) : _handle(handle) {
+ assert(handle);
+}
+
+SymbianStdioStream::~SymbianStdioStream() {
+ ((TSymbianFileEntry*)(_handle))->_fileHandle.Close();
+
+ delete (TSymbianFileEntry*)(_handle);
+}
+
+bool SymbianStdioStream::err() const {
+ return ((TSymbianFileEntry*)(_handle))->_lastError != 0;
+}
+
+void SymbianStdioStream::clearErr() {
+ ((TSymbianFileEntry*)(_handle))->_lastError = 0;
+ ((TSymbianFileEntry*)(_handle))->_eofReached = 0;
+}
+
+bool SymbianStdioStream::eos() const {
+ TSymbianFileEntry* entry = ((TSymbianFileEntry*)(_handle));
+
+ return entry->_eofReached != 0;
+}
+
+int32 SymbianStdioStream::pos() const {
+ TInt pos = 0;
+ TSymbianFileEntry* entry = ((TSymbianFileEntry*)(_handle));
+
+ entry->_lastError = entry->_fileHandle.Seek(ESeekCurrent, pos);
+ if (entry->_lastError == KErrNone && entry->_inputPos != KErrNotFound) {
+ pos += (entry->_inputPos - entry->_inputBufferLen);
+ }
+
+ return pos;
+}
+
+int32 SymbianStdioStream::size() const {
+
+ TInt length = 0;
+ ((TSymbianFileEntry*)(_handle))->_fileHandle.Size(length);
+
+ return length;
+}
+
+bool SymbianStdioStream::seek(int32 offs, int whence) {
+ assert(_handle);
+
+ TSeek seekMode = ESeekStart;
+ TInt pos = offs;
+ TSymbianFileEntry* entry = ((TSymbianFileEntry*)(_handle));
+
+ switch (whence) {
+ case SEEK_SET:
+ seekMode = ESeekStart;
+ break;
+ case SEEK_CUR:
+ seekMode = ESeekCurrent;
+ if (entry->_inputPos != KErrNotFound) {
+ pos += (entry->_inputPos - entry->_inputBufferLen);
+ }
+ break;
+ case SEEK_END:
+ seekMode = ESeekEnd;
+ break;
+
+ }
+
+ entry->_inputPos = KErrNotFound;
+ entry->_eofReached = EFalse;
+ entry->_fileHandle.Seek(seekMode, pos);
+
+ return true; // FIXME: Probably should return a value based on what _fileHandle.Seek returns
+}
+
+uint32 SymbianStdioStream::read(void *ptr, uint32 len) {
+ return (uint32)ReadData((byte *)ptr, 1, len, (TSymbianFileEntry *)_handle);
+}
+
+uint32 SymbianStdioStream::write(const void *ptr, uint32 len) {
+ TPtrC8 pointer( (unsigned char*) ptr, len);
+
+ ((TSymbianFileEntry*)(_handle))->_inputPos = KErrNotFound;
+ ((TSymbianFileEntry*)(_handle))->_lastError = ((TSymbianFileEntry*)(_handle))->_fileHandle.Write(pointer);
+ ((TSymbianFileEntry*)(_handle))->_eofReached = EFalse;
+
+ if (((TSymbianFileEntry*)(_handle))->_lastError == KErrNone) {
+ return len;
+ }
+
+ return 0;
+}
+
+bool SymbianStdioStream::flush() {
+ ((TSymbianFileEntry*)(_handle))->_fileHandle.Flush();
+ return true;
+}
+
+SymbianStdioStream *SymbianStdioStream::makeFromPath(const Common::String &path, bool writeMode) {
+ void *handle = CreateSymbianFileEntry(path.c_str(), writeMode ? "wb" : "rb");
+ if (handle)
+ return new SymbianStdioStream(handle);
+ return 0;
+}
+
diff --git a/backends/fs/symbian/symbianstream.h b/backends/fs/symbian/symbianstream.h
new file mode 100644
index 0000000000..d783856687
--- /dev/null
+++ b/backends/fs/symbian/symbianstream.h
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * 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 BACKENDS_FS_SYMBIANSTDIOSTREAM_H
+#define BACKENDS_FS_SYMBIANSTDIOSTREAM_H
+
+#include "common/scummsys.h"
+#include "common/noncopyable.h"
+#include "common/stream.h"
+#include "common/str.h"
+
+class SymbianStdioStream : public Common::SeekableReadStream, public Common::WriteStream, public Common::NonCopyable {
+protected:
+ /** File handle to the actual file. */
+ void *_handle;
+
+public:
+ /**
+ * Given a path, invokes fopen on that path and wrap the result in a
+ * StdioStream instance.
+ */
+ static SymbianStdioStream *makeFromPath(const Common::String &path, bool writeMode);
+
+ SymbianStdioStream(void *handle);
+ virtual ~SymbianStdioStream();
+
+ 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;
+ bool seek(int32 offs, int whence = SEEK_SET);
+ uint32 read(void *dataPtr, uint32 dataSize);
+};
+
+#endif
diff --git a/backends/fs/wii/wii-fs-factory.cpp b/backends/fs/wii/wii-fs-factory.cpp
index 9839858dd5..69086a95f1 100644
--- a/backends/fs/wii/wii-fs-factory.cpp
+++ b/backends/fs/wii/wii-fs-factory.cpp
@@ -42,7 +42,7 @@ AbstractFilesystemNode *WiiFilesystemFactory::makeCurrentDirectoryFileNode() con
return new WiiFilesystemNode();
}
-AbstractFilesystemNode *WiiFilesystemFactory::makeFileNodePath(const String &path) const {
+AbstractFilesystemNode *WiiFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new WiiFilesystemNode(path, true);
}
#endif
diff --git a/backends/fs/wii/wii-fs-factory.h b/backends/fs/wii/wii-fs-factory.h
index 24badee330..36867a392c 100644
--- a/backends/fs/wii/wii-fs-factory.h
+++ b/backends/fs/wii/wii-fs-factory.h
@@ -33,11 +33,9 @@
*/
class WiiFilesystemFactory : public FilesystemFactory, public Common::Singleton<WiiFilesystemFactory> {
public:
- typedef Common::String String;
-
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
protected:
WiiFilesystemFactory() {};
diff --git a/backends/fs/wii/wii-fs.cpp b/backends/fs/wii/wii-fs.cpp
index e6d0cf4c7e..a620df5471 100644
--- a/backends/fs/wii/wii-fs.cpp
+++ b/backends/fs/wii/wii-fs.cpp
@@ -23,6 +23,7 @@
#if defined(__WII__)
#include "backends/fs/abstract-fs.h"
+#include "backends/fs/stdiostream.h"
#include <sys/dir.h>
@@ -37,8 +38,8 @@
*/
class WiiFilesystemNode : public AbstractFilesystemNode {
protected:
- String _displayName;
- String _path;
+ Common::String _displayName;
+ Common::String _path;
bool _isDirectory, _isReadable, _isWritable;
public:
@@ -50,51 +51,30 @@ public:
/**
* Creates a WiiFilesystemNode for a given path.
*
- * @param path 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.
*/
- WiiFilesystemNode(const String &path, bool verify);
+ WiiFilesystemNode(const Common::String &path, bool verify);
virtual bool exists() const;
- virtual String getDisplayName() const { return _displayName; }
- virtual String getName() const { return _displayName; }
- virtual String getPath() const { return _path; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return _isReadable; }
virtual bool isWritable() const { return _isWritable; }
- virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+
private:
virtual void setFlags();
};
-/**
- * Returns the last component of a given path.
- *
- * Examples:
- * /foo/bar.txt would return /bar.txt
- * /foo/bar/ would return /bar/
- *
- * @param str String containing the path.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *lastPathComponent(const Common::String &str) {
- if(str.empty())
- return "";
-
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '/') {
- --cur;
- }
-
- return cur + 1;
-}
-
void WiiFilesystemNode::setFlags() {
struct stat st;
@@ -118,12 +98,12 @@ WiiFilesystemNode::WiiFilesystemNode() {
setFlags();
}
-WiiFilesystemNode::WiiFilesystemNode(const String &p, bool verify) {
+WiiFilesystemNode::WiiFilesystemNode(const Common::String &p, bool verify) {
assert(p.size() > 0);
_path = p;
- _displayName = lastPathComponent(_path);
+ _displayName = lastPathComponent(_path, '/');
if (verify)
setFlags();
@@ -134,10 +114,10 @@ bool WiiFilesystemNode::exists() const {
return stat(_path.c_str (), &st) == 0;
}
-AbstractFilesystemNode *WiiFilesystemNode::getChild(const String &n) const {
+AbstractFilesystemNode *WiiFilesystemNode::getChild(const Common::String &n) const {
assert(_isDirectory);
- String newPath(_path);
+ Common::String newPath(_path);
if (newPath.lastChar() != '/')
newPath += '/';
newPath += n;
@@ -160,15 +140,15 @@ bool WiiFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool
if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
continue;
- String newPath(_path);
+ Common::String newPath(_path);
if (newPath.lastChar() != '/')
newPath += '/';
newPath += filename;
bool isDir = S_ISDIR(st.st_mode);
- if ((mode == FilesystemNode::kListFilesOnly && isDir) ||
- (mode == FilesystemNode::kListDirectoriesOnly && !isDir))
+ if ((mode == Common::FilesystemNode::kListFilesOnly && isDir) ||
+ (mode == Common::FilesystemNode::kListDirectoriesOnly && !isDir))
continue;
if (isDir)
@@ -187,9 +167,17 @@ AbstractFilesystemNode *WiiFilesystemNode::getParent() const {
return 0;
const char *start = _path.c_str();
- const char *end = lastPathComponent(_path);
+ const char *end = lastPathComponent(_path, '/');
+
+ return new WiiFilesystemNode(Common::String(start, end - start), true);
+}
+
+Common::SeekableReadStream *WiiFilesystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
- return new WiiFilesystemNode(String(start, end - start), true);
+Common::WriteStream *WiiFilesystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
}
#endif //#if defined(__WII__)
diff --git a/backends/fs/windows/windows-fs-factory.cpp b/backends/fs/windows/windows-fs-factory.cpp
index 7fbf4f7fff..ed273bb746 100644
--- a/backends/fs/windows/windows-fs-factory.cpp
+++ b/backends/fs/windows/windows-fs-factory.cpp
@@ -26,8 +26,6 @@
#include "backends/fs/windows/windows-fs-factory.h"
#include "backends/fs/windows/windows-fs.cpp"
-DECLARE_SINGLETON(WindowsFilesystemFactory);
-
AbstractFilesystemNode *WindowsFilesystemFactory::makeRootFileNode() const {
return new WindowsFilesystemNode();
}
@@ -36,7 +34,7 @@ AbstractFilesystemNode *WindowsFilesystemFactory::makeCurrentDirectoryFileNode()
return new WindowsFilesystemNode("", true);
}
-AbstractFilesystemNode *WindowsFilesystemFactory::makeFileNodePath(const String &path) const {
+AbstractFilesystemNode *WindowsFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new WindowsFilesystemNode(path, false);
}
#endif
diff --git a/backends/fs/windows/windows-fs-factory.h b/backends/fs/windows/windows-fs-factory.h
index 0745b286a8..3c7b80942d 100644
--- a/backends/fs/windows/windows-fs-factory.h
+++ b/backends/fs/windows/windows-fs-factory.h
@@ -25,7 +25,6 @@
#ifndef WINDOWS_FILESYSTEM_FACTORY_H
#define WINDOWS_FILESYSTEM_FACTORY_H
-#include "common/singleton.h"
#include "backends/fs/fs-factory.h"
/**
@@ -33,19 +32,11 @@
*
* Parts of this class are documented in the base interface class, FilesystemFactory.
*/
-class WindowsFilesystemFactory : public FilesystemFactory, public Common::Singleton<WindowsFilesystemFactory> {
+class WindowsFilesystemFactory : public FilesystemFactory {
public:
- typedef Common::String String;
-
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
- virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
-
-protected:
- WindowsFilesystemFactory() {};
-
-private:
- friend class Common::Singleton<SingletonBaseType>;
+ virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
};
#endif /*WINDOWS_FILESYSTEM_FACTORY_H*/
diff --git a/backends/fs/windows/windows-fs.cpp b/backends/fs/windows/windows-fs.cpp
index 2105317a96..c59c7dbe71 100644
--- a/backends/fs/windows/windows-fs.cpp
+++ b/backends/fs/windows/windows-fs.cpp
@@ -24,24 +24,17 @@
#ifdef WIN32
-#ifdef ARRAYSIZE
-#undef ARRAYSIZE
-#endif
-#ifdef _WIN32_WCE
#include <windows.h>
// winnt.h defines ARRAYSIZE, but we want our own one...
#undef ARRAYSIZE
+#ifdef _WIN32_WCE
#undef GetCurrentDirectory
#endif
#include "backends/fs/abstract-fs.h"
+#include "backends/fs/stdiostream.h"
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
-#ifndef _WIN32_WCE
-#include <windows.h>
-// winnt.h defines ARRAYSIZE, but we want our own one...
-#undef ARRAYSIZE
-#endif
#include <tchar.h>
// F_OK, R_OK and W_OK are not defined under MSVC, so we define them here
@@ -66,8 +59,8 @@
*/
class WindowsFilesystemNode : public AbstractFilesystemNode {
protected:
- String _displayName;
- String _path;
+ Common::String _displayName;
+ Common::String _path;
bool _isDirectory;
bool _isPseudoRoot;
bool _isValid;
@@ -89,23 +82,26 @@ public:
* path=c:\foo\bar.txt, currentDir=true -> current directory
* path=NULL, currentDir=true -> current directory
*
- * @param path String with the path the new node should point to.
+ * @param path Common::String with the path the new node should point to.
* @param currentDir if true, the path parameter will be ignored and the resulting node will point to the current directory.
*/
- WindowsFilesystemNode(const String &path, const bool currentDir);
+ WindowsFilesystemNode(const Common::String &path, const bool currentDir);
virtual bool exists() const { return _access(_path.c_str(), F_OK) == 0; }
- virtual String getDisplayName() const { return _displayName; }
- virtual String getName() const { return _displayName; }
- virtual String getPath() const { return _path; }
+ virtual Common::String getDisplayName() const { return _displayName; }
+ virtual Common::String getName() const { return _displayName; }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return _access(_path.c_str(), R_OK) == 0; }
virtual bool isWritable() const { return _access(_path.c_str(), W_OK) == 0; }
- virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+
private:
/**
* Adds a single WindowsFilesystemNode to a given list.
@@ -113,7 +109,7 @@ private:
*
* @param list List to put the file entry node in.
* @param mode Mode to use while adding the file entry to the list.
- * @param base String with the directory being listed.
+ * @param base Common::String with the directory being listed.
* @param find_data Describes a file that the FindFirstFile, FindFirstFileEx, or FindNextFile functions find.
*/
static void addFile(AbstractFSList &list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data);
@@ -121,7 +117,7 @@ private:
/**
* Converts a Unicode string to Ascii format.
*
- * @param str String to convert from Unicode to Ascii.
+ * @param str Common::String to convert from Unicode to Ascii.
* @return str in Ascii format.
*/
static char *toAscii(TCHAR *str);
@@ -129,36 +125,12 @@ private:
/**
* Converts an Ascii string to Unicode format.
*
- * @param str String to convert from Ascii to Unicode.
+ * @param str Common::String to convert from Ascii to Unicode.
* @return str in Unicode format.
*/
static const TCHAR* toUnicode(const char *str);
};
-/**
- * Returns the last component of a given path.
- *
- * Examples:
- * c:\foo\bar.txt would return "\bar.txt"
- * c:\foo\bar\ would return "\bar\"
- *
- * @param str Path to obtain the last component from.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *lastPathComponent(const Common::String &str) {
- if(str.empty())
- return "";
-
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '\\') {
- --cur;
- }
-
- return cur + 1;
-}
-
void WindowsFilesystemNode::addFile(AbstractFSList &list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data) {
WindowsFilesystemNode entry;
char *asciiName = toAscii(find_data->cFileName);
@@ -170,8 +142,8 @@ void WindowsFilesystemNode::addFile(AbstractFSList &list, ListMode mode, const c
isDirectory = (find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? true : false);
- if ((!isDirectory && mode == FilesystemNode::kListDirectoriesOnly) ||
- (isDirectory && mode == FilesystemNode::kListFilesOnly))
+ if ((!isDirectory && mode == Common::FilesystemNode::kListDirectoriesOnly) ||
+ (isDirectory && mode == Common::FilesystemNode::kListFilesOnly))
return;
entry._isDirectory = isDirectory;
@@ -222,7 +194,7 @@ WindowsFilesystemNode::WindowsFilesystemNode() {
#endif
}
-WindowsFilesystemNode::WindowsFilesystemNode(const String &p, const bool currentDir) {
+WindowsFilesystemNode::WindowsFilesystemNode(const Common::String &p, const bool currentDir) {
if (currentDir) {
char path[MAX_PATH];
GetCurrentDirectory(MAX_PATH, path);
@@ -232,7 +204,7 @@ WindowsFilesystemNode::WindowsFilesystemNode(const String &p, const bool current
_path = p;
}
- _displayName = lastPathComponent(_path);
+ _displayName = lastPathComponent(_path, '\\');
// Check whether it is a directory, and whether the file actually exists
DWORD fileAttribs = GetFileAttributes(toUnicode(_path.c_str()));
@@ -251,10 +223,10 @@ WindowsFilesystemNode::WindowsFilesystemNode(const String &p, const bool current
_isPseudoRoot = false;
}
-AbstractFilesystemNode *WindowsFilesystemNode::getChild(const String &n) const {
+AbstractFilesystemNode *WindowsFilesystemNode::getChild(const Common::String &n) const {
assert(_isDirectory);
- String newPath(_path);
+ Common::String newPath(_path);
if (_path.lastChar() != '\\')
newPath += '\\';
newPath += n;
@@ -322,17 +294,25 @@ AbstractFilesystemNode *WindowsFilesystemNode::getParent() const {
WindowsFilesystemNode *p = new WindowsFilesystemNode();
if (_path.size() > 3) {
const char *start = _path.c_str();
- const char *end = lastPathComponent(_path);
+ const char *end = lastPathComponent(_path, '\\');
p = new WindowsFilesystemNode();
- p->_path = String(start, end - start);
+ p->_path = Common::String(start, end - start);
p->_isValid = true;
p->_isDirectory = true;
- p->_displayName = lastPathComponent(p->_path);
+ p->_displayName = lastPathComponent(p->_path, '\\');
p->_isPseudoRoot = false;
}
return p;
}
+Common::SeekableReadStream *WindowsFilesystemNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
+
+Common::WriteStream *WindowsFilesystemNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
+}
+
#endif //#ifdef WIN32
diff --git a/backends/midi/seq.cpp b/backends/midi/seq.cpp
index 57a5a1ea32..9e86181674 100644
--- a/backends/midi/seq.cpp
+++ b/backends/midi/seq.cpp
@@ -28,7 +28,7 @@
* both the QuickTime support and (vkeybd http://www.alsa-project.org/~iwai/alsa.html)
*/
-#if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__)
+#if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__) && !defined(__MINT__)
#include "common/util.h"
#include "sound/musicplugin.h"
diff --git a/backends/midi/stmidi.cpp b/backends/midi/stmidi.cpp
new file mode 100644
index 0000000000..addb23c6bd
--- /dev/null
+++ b/backends/midi/stmidi.cpp
@@ -0,0 +1,155 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001-2006 The ScummVM project
+ *
+ * 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.
+ */
+
+/*
+ * Raw MIDI output for the Atari ST line of computers.
+ * Based on the ScummVM SEQ & CoreMIDI drivers.
+ * Atari code by Keith Scroggins
+ * We, unfortunately, could not use the SEQ driver because the /dev/midi under
+ * FreeMiNT (and hence in libc) is considered to be a serial port for machine
+ * access. So, we just use OS calls then to send the data to the MIDI ports
+ * directly. The current implementation is sending 1 byte at a time because
+ * in most cases we are only sending up to 3 bytes, I believe this saves a few
+ * cycles. I might change so sysex messages are sent the other way later.
+ */
+
+#if defined __MINT__
+
+#include <osbind.h>
+#include "sound/mpu401.h"
+#include "common/util.h"
+#include "sound/musicplugin.h"
+
+class MidiDriver_STMIDI : public MidiDriver_MPU401 {
+public:
+ MidiDriver_STMIDI() : _isOpen (false) { }
+ int open();
+ void close();
+ void send(uint32 b);
+ void sysEx(const byte *msg, uint16 length);
+
+private:
+ bool _isOpen;
+};
+
+int MidiDriver_STMIDI::open() {
+ if ((_isOpen) && (!Bcostat(4)))
+ return MERR_ALREADY_OPEN;
+ warning("ST Midi Port Open");
+ _isOpen = true;
+ return 0;
+}
+
+void MidiDriver_STMIDI::close() {
+ MidiDriver_MPU401::close();
+ _isOpen = false;
+}
+
+void MidiDriver_STMIDI::send(uint32 b) {
+
+ byte status_byte = (b & 0x000000FF);
+ byte first_byte = (b & 0x0000FF00) >> 8;
+ byte second_byte = (b & 0x00FF0000) >> 16;
+
+// warning("ST MIDI Packet sent");
+
+ switch (b & 0xF0) {
+ case 0x80: // Note Off
+ case 0x90: // Note On
+ case 0xA0: // Polyphonic Key Pressure
+ case 0xB0: // Controller
+ case 0xE0: // Pitch Bend
+ Bconout(3, status_byte);
+ Bconout(3, first_byte);
+ Bconout(3, second_byte);
+ break;
+ case 0xC0: // Program Change
+ case 0xD0: // Aftertouch
+ Bconout(3, status_byte);
+ Bconout(3, first_byte);
+ break;
+ default:
+ fprintf(stderr, "Unknown : %08x\n", (int)b);
+ break;
+ }
+}
+
+void MidiDriver_STMIDI::sysEx (const byte *msg, uint16 length) {
+ if (length > 254) {
+ warning ("Cannot send SysEx block - data too large");
+ return;
+ }
+
+ const byte *chr = msg;
+ warning("Sending SysEx Message");
+
+ Bconout(3, '0xF0');
+ for (; length; --length, ++chr) {
+ Bconout(3,((unsigned char) *chr & 0x7F));
+ }
+ Bconout(3, '0xF7');
+}
+
+// Plugin interface
+
+class StMidiMusicPlugin : public MusicPluginObject {
+public:
+ const char *getName() const {
+ return "STMIDI";
+ }
+
+ const char *getId() const {
+ return "stmidi";
+ }
+
+ MusicDevices getDevices() const;
+ PluginError createInstance(Audio::Mixer *mixer, MidiDriver **mididriver)
+ const;
+};
+
+MusicDevices StMidiMusicPlugin::getDevices() const {
+ MusicDevices devices;
+ // TODO: Return a different music type depending on the configuration
+ // TODO: List the available devices
+ devices.push_back(MusicDevice(this, "", MT_GM));
+ return devices;
+}
+
+PluginError StMidiMusicPlugin::createInstance(Audio::Mixer *mixer, MidiDriver **mididriver) const {
+ *mididriver = new MidiDriver_STMIDI();
+
+ return kNoError;
+}
+
+MidiDriver *MidiDriver_STMIDI_create(Audio::Mixer *mixer) {
+ MidiDriver *mididriver;
+
+ StMidiMusicPlugin p;
+ p.createInstance(mixer, &mididriver);
+
+ return mididriver;
+}
+
+//#if PLUGIN_ENABLED_DYNAMIC(STMIDI)
+ //REGISTER_PLUGIN_DYNAMIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
+//#else
+ REGISTER_PLUGIN_STATIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
+//#endif
+
+#endif
diff --git a/backends/module.mk b/backends/module.mk
index 6642a3a281..8944e9a3db 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -1,6 +1,8 @@
MODULE := backends
MODULE_OBJS := \
+ fs/abstract-fs.o \
+ fs/stdiostream.o \
fs/amigaos4/amigaos4-fs-factory.o \
fs/ds/ds-fs-factory.o \
fs/palmos/palmos-fs-factory.o \
@@ -17,6 +19,7 @@ MODULE_OBJS := \
midi/coremidi.o \
midi/quicktime.o \
midi/seq.o \
+ midi/stmidi.o \
midi/timidity.o \
midi/dmedia.o \
midi/windows.o \
diff --git a/backends/platform/dc/dc-fs.cpp b/backends/platform/dc/dc-fs.cpp
index f4dc4037df..c4f1d76f10 100644
--- a/backends/platform/dc/dc-fs.cpp
+++ b/backends/platform/dc/dc-fs.cpp
@@ -24,6 +24,7 @@
#include "dc.h"
#include "backends/fs/abstract-fs.h"
+#include "backends/fs/stdiostream.h"
#include <ronin/cdfs.h>
#include <stdio.h>
@@ -34,75 +35,50 @@
*
* Parts of this class are documented in the base interface class, AbstractFilesystemNode.
*/
-
-/* A file */
class RoninCDFileNode : public AbstractFilesystemNode {
protected:
- String _path;
- static const char *lastPathComponent(const Common::String &str);
+ Common::String _path;
public:
- RoninCDFileNode(const String &path) : _path(path) {};
+ RoninCDFileNode(const Common::String &path) : _path(path) {};
virtual bool exists() const { return true; }
- virtual String getName() const { return lastPathComponent(_path); }
- virtual String getPath() const { return _path; }
+ virtual Common::String getName() const { return lastPathComponent(_path, '/'); }
+ virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return false; }
virtual bool isReadable() const { return true; }
virtual bool isWritable() const { return false; }
- virtual AbstractFilesystemNode *getChild(const String &n) const { return NULL; }
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const { return NULL; }
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const { return false; }
virtual AbstractFilesystemNode *getParent() const;
+ virtual Common::SeekableReadStream *openForReading();
+ virtual Common::WriteStream *openForWriting();
+
static AbstractFilesystemNode *makeFileNodePath(const Common::String &path);
};
/* A directory */
class RoninCDDirectoryNode : public RoninCDFileNode {
public:
- RoninCDDirectoryNode(const String &path) : RoninCDFileNode(path) {};
+ RoninCDDirectoryNode(const Common::String &path) : RoninCDFileNode(path) {};
virtual bool isDirectory() const { return true; }
- virtual AbstractFilesystemNode *getChild(const String &n) const;
+ virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
};
/* A file/directory which does not exist */
class RoninCDNonexistingNode : public RoninCDFileNode {
public:
- RoninCDNonexistingNode(const String &path) : RoninCDFileNode(path) {};
+ RoninCDNonexistingNode(const Common::String &path) : RoninCDFileNode(path) {};
virtual bool exists() const { return false; }
virtual bool isReadable() const { return false; }
};
-/**
- * Returns the last component of a given path.
- *
- * Examples:
- * /foo/bar.txt would return /bar.txt
- * /foo/bar/ would return /bar/
- *
- * @param str String containing the path.
- * @return Pointer to the first char of the last component inside str.
- */
-const char *RoninCDFileNode::lastPathComponent(const Common::String &str) {
- if(str.empty())
- return "";
-
- const char *start = str.c_str();
- const char *cur = start + str.size() - 2;
-
- while (cur >= start && *cur != '/') {
- --cur;
- }
-
- return cur + 1;
-}
-
-AbstractFilesystemNode *RoninCDFileNode::makeFileNodePath(const Common::String &path)
-{
+AbstractFilesystemNode *RoninCDFileNode::makeFileNodePath(const Common::String &path) {
assert(path.size() > 0);
int fd;
@@ -110,18 +86,16 @@ AbstractFilesystemNode *RoninCDFileNode::makeFileNodePath(const Common::String &
if ((fd = open(path.c_str(), O_RDONLY)) >= 0) {
close(fd);
return new RoninCDFileNode(path);
- }
- else if ((fd = open(path.c_str(), O_DIR|O_RDONLY)) >= 0) {
+ } else if ((fd = open(path.c_str(), O_DIR|O_RDONLY)) >= 0) {
close(fd);
return new RoninCDDirectoryNode(path);
- }
- else {
+ } else {
return NULL;
}
}
-AbstractFilesystemNode *RoninCDDirectoryNode::getChild(const String &n) const {
- String newPath(_path);
+AbstractFilesystemNode *RoninCDDirectoryNode::getChild(const Common::String &n) const {
+ Common::String newPath(_path);
if (_path.lastChar() != '/')
newPath += '/';
newPath += n;
@@ -139,20 +113,20 @@ bool RoninCDDirectoryNode::getChildren(AbstractFSList &myList, ListMode mode, bo
// ... loop over dir entries using readdir
while ((dp = readdir(dirp)) != NULL) {
- String newPath(_path);
+ Common::String newPath(_path);
if (newPath.lastChar() != '/')
newPath += '/';
newPath += dp->d_name;
if (dp->d_size < 0) {
// Honor the chosen mode
- if (mode == FilesystemNode::kListFilesOnly)
+ if (mode == Common::FilesystemNode::kListFilesOnly)
continue;
myList.push_back(new RoninCDDirectoryNode(newPath+"/"));
} else {
// Honor the chosen mode
- if (mode == FilesystemNode::kListDirectoriesOnly)
+ if (mode == Common::FilesystemNode::kListDirectoriesOnly)
continue;
myList.push_back(new RoninCDFileNode(newPath));
@@ -168,9 +142,18 @@ AbstractFilesystemNode *RoninCDFileNode::getParent() const {
return 0;
const char *start = _path.c_str();
- const char *end = lastPathComponent(_path);
+ const char *end = lastPathComponent(_path, '/');
+
+ return new RoninCDDirectoryNode(Common::String(start, end - start));
+}
+
+
+Common::SeekableReadStream *RoninCDFileNode::openForReading() {
+ return StdioStream::makeFromPath(getPath().c_str(), false);
+}
- return new RoninCDDirectoryNode(String(start, end - start));
+Common::WriteStream *RoninCDFileNode::openForWriting() {
+ return StdioStream::makeFromPath(getPath().c_str(), true);
}
AbstractFilesystemNode *OSystem_Dreamcast::makeRootFileNode() const {
diff --git a/backends/platform/dc/selector.cpp b/backends/platform/dc/selector.cpp
index 91c851506f..a4a53e0f65 100644
--- a/backends/platform/dc/selector.cpp
+++ b/backends/platform/dc/selector.cpp
@@ -146,12 +146,12 @@ struct Dir
{
char name[252];
char deficon[256];
- FilesystemNode node;
+ Common::FilesystemNode node;
};
static Game the_game;
-static bool isIcon(const FilesystemNode &entry)
+static bool isIcon(const Common::FilesystemNode &entry)
{
int l = entry.getDisplayName().size();
if (l>4 && !strcasecmp(entry.getDisplayName().c_str()+l-4, ".ICO"))
@@ -198,14 +198,14 @@ static int findGames(Game *games, int max)
{
Dir *dirs = new Dir[MAX_DIR];
int curr_game = 0, curr_dir = 0, num_dirs = 1;
- dirs[0].node = FilesystemNode("");
+ dirs[0].node = Common::FilesystemNode("");
while (curr_game < max && curr_dir < num_dirs) {
strncpy(dirs[curr_dir].name, dirs[curr_dir].node.getPath().c_str(), 252);
dirs[curr_dir].name[251] = '\0';
dirs[curr_dir].deficon[0] = '\0';
- FSList files, fslist;
- dirs[curr_dir++].node.getChildren(fslist, FilesystemNode::kListAll);
- for (FSList::const_iterator entry = fslist.begin(); entry != fslist.end();
+ Common::FSList files, fslist;
+ dirs[curr_dir++].node.getChildren(fslist, Common::FilesystemNode::kListAll);
+ for (Common::FSList::const_iterator entry = fslist.begin(); entry != fslist.end();
++entry) {
if (entry->isDirectory()) {
if (num_dirs < MAX_DIR && strcasecmp(entry->getDisplayName().c_str(),
diff --git a/backends/platform/dc/vmsave.cpp b/backends/platform/dc/vmsave.cpp
index 6ab8fc4558..d17e1f6213 100644
--- a/backends/platform/dc/vmsave.cpp
+++ b/backends/platform/dc/vmsave.cpp
@@ -269,14 +269,15 @@ class InVMSave : public Common::InSaveFile {
private:
char *buffer;
int _pos, _size;
+ bool _eos;
uint32 read(void *buf, uint32 cnt);
- void skip(uint32 offset);
- void seek(int32 offs, int whence);
+ bool skip(uint32 offset);
+ bool seek(int32 offs, int whence);
public:
InVMSave()
- : _pos(0), buffer(NULL)
+ : _pos(0), buffer(NULL), _eos(false)
{ }
~InVMSave()
@@ -285,9 +286,10 @@ public:
delete[] buffer;
}
- bool eos() const { return _pos >= _size; }
- uint32 pos() const { return _pos; }
- uint32 size() const { return _size; }
+ bool eos() const { return _eos; }
+ void clearErr() { _eos = false; }
+ int32 pos() const { return _pos; }
+ int32 size() const { return _size; }
bool readSaveGame(const char *filename)
{ return ::readSaveGame(buffer, _size, filename); }
@@ -312,8 +314,8 @@ public:
~OutVMSave();
- bool ioFailed() const { return iofailed; }
- void clearIOFailed() { iofailed = false; }
+ bool err() const { return iofailed; }
+ void clearErr() { iofailed = false; }
void finalize();
};
@@ -370,6 +372,7 @@ uint32 InVMSave::read(void *buf, uint32 cnt)
int nbyt = cnt;
if (_pos + nbyt > _size) {
cnt = (_size - _pos);
+ _eos = true;
nbyt = cnt;
}
if (nbyt)
@@ -378,15 +381,16 @@ uint32 InVMSave::read(void *buf, uint32 cnt)
return cnt;
}
-void InVMSave::skip(uint32 offset)
+bool InVMSave::skip(uint32 offset)
{
int nbyt = offset;
if (_pos + nbyt > _size)
nbyt = (_size - _pos);
_pos += nbyt;
+ return true;
}
-void InVMSave::seek(int32 offs, int whence)
+bool InVMSave::seek(int32 offs, int whence)
{
switch(whence) {
case SEEK_SET:
@@ -403,6 +407,8 @@ void InVMSave::seek(int32 offs, int whence)
_pos = 0;
else if (_pos > _size)
_pos = _size;
+ _eos = false;
+ return true;
}
uint32 OutVMSave::write(const void *buf, uint32 cnt)
diff --git a/backends/platform/ds/arm7/Makefile b/backends/platform/ds/arm7/Makefile
index 55db7f8cad..82637845db 100644
--- a/backends/platform/ds/arm7/Makefile
+++ b/backends/platform/ds/arm7/Makefile
@@ -107,7 +107,7 @@ MAPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.map)))
export OFILES := $(MAPFILES:.map=.o) $(RAWFILES:.raw=.o) $(PALFILES:.pal=.o) $(BINFILES:.bin=.o) $(PCXFILES:.pcx=.o)\
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
-export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) -I- -I$(CURDIR)/../commoninclude\
+export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) -Iquote -I$(CURDIR)/../commoninclude\
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include/nds)\
-I$(CURDIR)/$(BUILD) -I$(CURDIR)/source/libcartreset
diff --git a/backends/platform/ds/arm7/source/main.cpp b/backends/platform/ds/arm7/source/main.cpp
index bee39f1efe..d252ed44de 100644
--- a/backends/platform/ds/arm7/source/main.cpp
+++ b/backends/platform/ds/arm7/source/main.cpp
@@ -233,7 +233,7 @@ void DummyHandler() {
REG_IF = REG_IF;
}
-uint16 powerManagerWrite(uint32 command, u32 data, bool enable) {
+void powerManagerWrite(uint32 command, u32 data, bool enable) {
uint16 result;
SerialWaitBusy();
@@ -261,9 +261,6 @@ uint16 powerManagerWrite(uint32 command, u32 data, bool enable) {
REG_SPICNT = SPI_ENABLE | SPI_BAUD_1MHz;
REG_SPIDATA = enable? (result | data): (result & ~data);
SerialWaitBusy();
-
- // FIXME: This function should either return something, or have a comment
- // explaining why it is valid for it to not return something. :-)
}
/*
diff --git a/backends/platform/ds/arm9/dist/readme_ds.txt b/backends/platform/ds/arm9/dist/readme_ds.txt
new file mode 100644
index 0000000000..f77da418c9
--- /dev/null
+++ b/backends/platform/ds/arm9/dist/readme_ds.txt
@@ -0,0 +1,840 @@
+
+
+
+ The official port of ScummVM
+ to the Nintendo DS handheld console
+ by Neil Millstone (agentq)
+ http://scummvm.drunkencoders.com
+------------------------------------------------------------------------
+Visit the main ScummVM website <http://www.scummvm.org>
+
+
+
+
+ Contents
+ ------------------------------------------------------------------------
+
+
+
+ * What's New?
+ * What is ScummVM DS?
+ * Features
+ * Screenshots
+ * How to Get ScummVM DS Onto Your DS - Simple Explanation
+ o Using a CF/SD/Mini SD/Micro SD card reader and a DLDI driver
+ o Instructions for specific card readers
+ * What to do if saving doesn't work or your card gets corruped -
+ force SRAM saves
+ * How to use ScummVM DS
+ * Game Specific Controls
+ * DS Options Screen
+ * Which games are compatible with ScummVM DS
+ * Predictive dictionary for Sierra AGI games
+ * Converting your CD audio
+ * Converting speech to MP3 format
+ * Frequently Asked Questions
+ * Downloads
+ * Contributors
+ * Donations and Getting Help
+ * Building from Sources
+
+
+
+ What's New?
+ ------------------------------------------------------------------------
+
+ScummVM DS 0.12.0
+
+ * New games supported: Lure of the Temptress, Nippon Safes, Lost in Time.
+ * New laptop-style trackpad input method. Uses relative movement when you
+ drag on the touch screen.
+ * New option which allows you to drag to hover, tap the touch screen to
+ click, and double tap the screen to right click.
+ * Reorganised DS Options screen into three tabs for clearer navigation
+ * New top screen scaling options let you choose the scaling factor used
+ on startup.
+ * The usual round of bug fixes.
+
+
+ScummVM DS 0.11.1
+
+ * Bugfix release - No new DS port features
+
+
+ScummVM DS 0.11.0
+
+ * New games supported: Elvira 1 and 2, Waxworks (Amiga version)
+ * Software scaler for improved image quality. Turn it on using the DS options
+ screen (press select during the game). Thanks to Tramboi and Robin Watts for
+ this feature!
+ * Function keys added to virtual keyboard (used in AGI games)
+ * Plenty of bug fixes
+
+ What is ScummVM DS?
+ ------------------------------------------------------------------------
+
+ScummVM DS is a part of the ScummVM project. The ScummVM project is an
+attempt to re-engineer many classic point and click adventure games of the
+80s and 90s to run on modern computer hardware. Technology has changed a
+lot since these games were written, and so ScummVM attempts to replicate the
+gameplay of the original games in exacting details, without any of the original
+code that the game ran on. ScummVM needs a copy of the original game, in order
+to take the graphics, sound, and scripts that made the game work.
+
+ScummVM is written in such a way that it can be 'ported' from one type of
+machine to another, and ScummVM DS is a port of ScummVM to the Nintendo DS
+handheld games console.
+
+
+ Features
+ ------------------------------------------------------------------------
+
+ * Runs nearly all of Lucasarts' SCUMM games up to and including Sam
+ & Max Hit the Road
+ * Runs many non-Lucasarts point-and-click adventures too
+ * Supports sound
+ * Provides a GUI to change settings and choose games
+ * Supports using the DS touch screen for controls
+ * Suports saving games to compatible flash cards
+ * All games run at pretty much full speed
+
+
+
+
+
+ How to Get ScummVM DS Onto Your DS - Simple Explanation
+ ------------------------------------------------------------------------
+
+Nintendo don't want you to run ScummVM on your DS. They control
+which companies can make games on the DS, and there is an expensive
+process to go through in order to be licenced. Having to pay for
+this would prevent me from giving away ScummVM for free.
+
+So, the result is that to run ScummVM on your DS you'll need an
+unofficial card reader. There are many of these, and all are different.
+Popular models at the time of writing are the R4DS and the M3DS Real,
+but many different models work. You need to buy one of these, and at
+MicroSD card to go with it.
+
+There are also slot-2 card readers which fit into the bottom slot on
+your DS, usually used for Game Boy Advance games. These are less common
+these days, and although they have certain advantages, the details of
+these are beyond the scope of this website. Information on these is
+quite easy to find by searching.
+
+Once you have your card reader and a MicroSD card, you will also need
+a copy of the game you want to run. ScummVM can run a large variety
+of games, but you must own a real boxed copy of the game. These games
+are still under copyright, and it is illegal to copy them from a friend
+or download them from the Internet without paying. The exception to
+this are the three Revolution Software games. These are 'Beneath a
+Steel Sky', 'Lure of the Temptress' and 'Flight of the Amazon Queen'.
+Revolution have kindly allowed us to give these games away for free.
+You can download them from the main ScummVM site at
+<http://www.scummvm.org/downloads.php>
+
+NOTE: Previous version of ScummVM DS supported a method which used a
+zip file to run games on unsupported flash card readers. This method
+is no longer supported.
+
+
+ How to Get ScummVM DS Onto Your DS - Using a CF/SD/Mini SD/Micro
+ SD card reader and a DLDI driver
+ ------------------------------------------------------------------------
+
+ScummVM DS needs something called a DLDI driver to run on each make
+and model of card reader. Many modern card readers (R4DS, M3 DS Real)
+handle this autmatically and for those, you don't have to do anything.
+Just running ScummVM on the card will handle this step for you.
+For others, you will need to follow the steps in this section before
+ScummVM DS will work.
+
+All DS card readers are different in the way that they work. In order to
+support many different card readers, ScummVM DS uses a DLDI driver installed
+into the ScummVM DS code. This is done using a program called DLDITool
+which you can download and run on your computer. Each DLDI driver is
+designed to tell ScummVM DS how to use a specific type of card reader.
+These drivers can be used with any homebrew program which supports the
+DLDI interface.
+
+While each card reader should work with these instructions, there are
+some exceptions. Please read the card reader notes
+section to see if there is any specific information about your card reader.
+
+Here is what you need to do:
+
+ * Visit the DLDI page <http://dldi.drunkencoders.com/> and
+ download the executable for DLDITool for your operating system
+ (versions are available for Windows, Linux, and MacOS)
+ * Download the DLDI for your card reader. This is the big table at
+ the top of the page. The first column marked DLDI is the one you
+ want. You should get a single file with a .dldi extension.
+ * Extract DLDITool into a folder, and put the DLDI of your choice in
+ the same folder.
+ * If you're using the command line version of DLDITool enter the
+ following at a command prompt:
+
+ dlditool <dldiname> <scummvm nds name>
+
+
+ If you're using the Windows GUI version, double click on
+ dlditool32.exe, select your card reader from the box, drag your
+ ScummVM binaries (either the .nds, or the .ds.gba version
+ depending on your card reader. I think only Supercards use the
+ .ds.gba files) into the lower box, then click patch.
+
+ Either way, you should see 'Patched Successfully'. If you don't,
+ you're doing something wrong.
+
+ You need to patch one of the builds labeled A - F depending on
+ which game you want to run. See the table on the ScummVM DS
+ website to see which games are supported by which build.
+
+ * Put the patched .nds or .ds.gba files on your flash card. If
+ you're using the Supercard, you will need to use the .ds.gba
+ files, but rename them to .nds.
+ * Put your game data in any folder on the card. Do NOT use a zip file.
+ * Boot up your DS and run ScummVM.
+ * Click 'Add Game', browse to the folder with your game data, click
+ 'Choose', then 'OK'. Click 'Start' to run the game.
+
+If your copy of ScummVM DS has been successfully patched, you will get a
+message on the top screen that looks like this:
+
+ DLDI Device:
+ GBA Movie Player (Compact Flash)
+
+The message should show the name of your card reader. If it is wrong,
+you have used the wrong DLDI file.
+
+If you haven't patched your .nds file, you will get the following message
+
+ DLDI Driver not patched!
+ DLDI Initialise failed.
+
+In this case, you've made a mistake following the above instructions, or
+have patched the wrong file.
+
+You may also see the following message:
+
+ DLDI Device:
+ GBA Movie Player (Compact Flash)
+ DLDI Initialise failed.
+
+In this case, the driver did not start up correctly. The driver is
+probably broken, or you've used the wrong one for your card reader.
+
+In the case of the Supercard, M3 Lite and DS Link, there are several
+drivers available. You might want to try one of the others.
+
+This version of ScummVM DS will run on any card reader that has a DLDI
+driver available. If yours doesn't, you need to pressure your card
+reader manufacturer to release one.
+
+DO NOT EMAIL ME TO ASK ME TO CREATE A DRIVER FOR YOUR CARD READER, I
+CANNOT DO THIS.
+
+
+ How to Get ScummVM DS Onto Your DS - Instructions for specific
+ card readers
+ ------------------------------------------------------------------------
+
+ * *GBAMP CF:* You need to upload replacement firmware to your card
+ reader before it will work. You can download the firmware program
+ here <http://chishm.drunkencoders.com/NDSMP/index.html>. Name your
+ .nds file _BOOT_MP.nds.
+ * *M3 CF/SD:* Copy the .nds file to your card with the M3 Game
+ Manager in order to avoid an annoying message when you boot your
+ M3. Use the default options to copy the file. Be sure to press 'A'
+ in the M3 browser to start the .nds file, and not 'Start', or it
+ won't work.
+ * *M3 CF/SD:* Copy the .nds file to your card with the M3 Game
+ Manager in order to avoid an annoying message when you boot your
+ M3. Use the default options to copy the file. Be sure to press 'A'
+ in the M3 browser to start the .nds file, and not 'Start', or it
+ won't work.
+ * *Supercard CF/SD (slot-2):* Use the .ds.gba files to run ScummVM
+ on the Supercard. Other than that, just follow the instructions as
+ normal.
+ * *Supercard Lite (slot-2):* It has been reported that only the
+ standard Supercard driver and the Moonshell version work with
+ ScummVM DS.
+ * *Datel Max Media Dock: * If you haven't already, upgrade your
+ firmware to the latest version. The firmware that came with my Max
+ Media Dock was unable to run ScummVM DS at all. Click here to
+ visit Datel's support page and download the latest firmware
+ <http://us.codejunkies.com/mpds/support.htm>
+ * *NinjaDS*: There are firmware upgrades for this device, but for
+ me, ScummVM DS ran straight out of the box. Visit this page
+ <http://www.ninjads.com/news.html> to download the latest firmware
+ if you want. If you have installed FlashMe on your DS, it will
+ make your DS crash on boot when the NinjaDS is inserted. You can
+ hold the 'select' button during boot to disable FlashMe, which
+ will allow the NinjaDS to work. Due to this, it is not recommended
+ to install FlashMe if you use a NinjaDS.
+ * *EZ-Flash*: This card reader uses .ds.gba files from the ScummVM
+ archive. Rename them to .nds before patching them with the DLDI
+ patcher.
+ * *R4DS*: If you upgrade the firmware for your R4DS to version 1.10
+ or later, the card will autmatically DLDI patch the game, meaning
+ you don't have to use dlditool to patch the .NDS file. This makes
+ things a lot easier!
+ * *M3DS Real*: This card autmatically DLDI patches the game, meaning
+ that you do not need to do this yourself.
+
+
+
+ Which games are compatible with ScummVM DS?
+ ------------------------------------------------------------------------
+
+I'm glad you asked. Here is a list of the compatible games in version
+0.12.0. Demo versions of the games listed should work too.
+
+Flight of the Amazon Queen, Beneath a Steel Sky, and Lure of the
+Temptress have generously been released as freeware by the original
+authors, Revolution Software <http://www.revolution.co.uk/>. This is a
+great thing and we should support Revolution for being so kind to us.
+You can download the game data from the official ScummVM download page
+<http://www.scummvm.org/downloads.php>.
+
+The other games on this list are commercial, and still under copyright,
+which means downloading them without paying for it is illegal. You can
+probably find a second-hand copy on eBay. Please don't email me to ask
+for a copy, as I am unable to send it to you.
+
+Game Build Notes
+
+Manic Mansion A
+
+Zak McKracken and the Alien Mindbenders A
+
+Indiana Jones and the Last Crusade A
+
+Loom A
+
+Passport to Adventure A
+
+The Secret of Monkey Island A
+
+Monkey Island 2: LeChuck's Revenge A
+
+Indiana Jones and the Fate of Atlantis A
+
+Day of the Tentacle A
+
+Sam & Max Hit the Road A Some slowdown in a few scenes
+ when MP3 audio is enabled
+
+Bear Stormin' (DOS) A
+
+Fatty Bear's Birthday Surprise (DOS) A
+
+Fatty Bear's Fun Pack (DOS) A
+
+Putt-Putt's Fun Pack (DOS) A
+
+Putt-Putt Goes to the Moon (DOS) A
+
+Putt-Putt Joins the Parade (DOS) A Can sometimes crash due to low memory
+
+Beneath a Steel Sky B
+
+Flight of the Amazon Queen B
+
+Simon the Sorcerer 1 C Zoomed view does not follow the
+ speaking character
+Simon the Sorcerer 2 C Zoomed view does not follow the
+ speaking character
+Elvira 1 C
+
+Elvira 2 C
+
+Waxworks (Amiga version) C
+
+Gobliiins D
+
+Gobliins 2 D
+
+Goblins 3 D
+
+Ween: The Prophecy D
+
+Bargon Attack D
+
+Lost in Time D
+
+Future Wars D
+
+All Sierra AGI games.
+For a complete list, see this page
+<http://wiki.scummvm.org/index.php/AGI> D
+
+Inherit the Earth E
+
+The Legend of Kyrandia F Zoomed view does not follow the
+ speaking character
+
+Lure of the Temptress G
+
+Nippon Safes G
+
+There is no support for Full Throttle, The Dig, or The Curse of Monkey
+Island because of memory issues. There simply is not enough RAM on the
+DS to run these games. Sorry. Also there is no support for Windows Humongous
+Entertainment games. The extra code required to make this work uses up
+too much RAM.
+
+
+ What to do when saving doesn't work or your card gets corrupted -
+ forcing SRAM Saves
+ ------------------------------------------------------------------------
+
+This method only works for cards which use the Game Boy Advance slot on the
+bottom of your DS.
+
+If ScummVM DS cannot save games to your SD card, or it causes corruption
+when it does, you can force it to use GBA SRAM to save the game. This
+uses your flash cart reader's GBA features to save the game to a .sav or
+.dat file (depending on the reader). Only slot-2 devices can use SRAM saves,
+and only ones with support for GBA games.
+
+If you want to use SRAM save, just create a text file called scummvm.ini
+(or scummvmb.ini, scummvmc.ini for builds B or C) in the root of your
+card which contains the following:
+
+[ds]
+forcesramsave=true
+
+When you boot your game, ScummVM DS will not save games to your SD card
+directly, instead it will save to GBA SRAM. On most cards, you need to
+transfer the data to your SD card by rebooting and using your card
+reader's boot-up menu. Using this method, around four saves can me made.
+
+One disadvantage of forcing SRAM saves is that your settings won't be
+saved. You can add games manually to the ini file so that you don't have
+to select them on each boot. Just add a section like the following on
+for each game on your card.
+
+[monkey2]
+description=Monkey Island 2: LeChuck's Revenge (English/DOS)
+path=mp:/MONKEY2
+
+
+ How to Use ScummVM
+ ------------------------------------------------------------------------
+
+Once you've booted up ScummVM, you'll see the start up screen.
+
+ 1. Tap the 'Add' button with the pen, then browse to the folder
+ containing your game data. Once you have clicked on your folder, you will
+ not see any files inside. This is normal, as the folder selector only shows
+ folders!
+
+ 2. Click the 'Choose' button.
+
+ 3. You will get some options for the game. You can usually just click 'Ok' to
+ this.
+
+ 4. Now click on the name of the game you want to play from the list and
+ click 'Start'. Your game will start!
+
+You can use the B button to skip cutscenes, and the select button to
+show an options menu which will let you tweak the DS contols, including
+switch between scaled and unscaled video modes. The text is clearer in
+the unscaled mode, but the whole game doesn't fit on the screen. To
+scroll around, hold either shoulder button and use the D-pad or drag the
+screen around with the stylus. Even in scaled mode, a small amount is
+missing from the top and bottom of the screen. You can scroll around to
+see those areas. The top screen shows a zoomed-in view. This scrolls
+around to focus on the character who's speaking, and also follows where
+the pen touches the screen. You can change the zoom level by holding one
+of the shoulder buttons and pressing B to zoom in and A to zoom out.
+
+Press the start button for the in-game menu where you can load or save
+your game (this works in Lucasarts games, other games vary). Saves will
+write directly to your flash card. You can choose the folder where they
+are stored using the GUI that appears when you boot up. If you're using
+a GBA Flash Cartridge, or an unsupported flash card adaptor, you will be
+using GBA SRAM to save your game. Four or five save game will fit in
+save RAM. If you save more games than will fit, a warning will appear on
+the top screen. When you turn your DS off, the new save will be lost,
+and only the first ones you saved will be present.
+
+Many of the games use both mouse buttons. Usually the right button often
+performs the default action on any object you click on. To simulate this
+with the DS pen, you can switch the input into one of three modes. Press
+left on the D-pad to enable the left mouse button. Press right on the
+D-pad to enable the right mouse button. Press up on the D-pad to enable
+hover mode. In this mode, you won't click on anything, just hover the
+mouse cursor over it. This lets you pick out active objects in the scene.
+
+An icon on the top screen will show you which mode you're in.
+
+In hover mode, there are some additional controls. While holding the pen
+on the screen, tapping D-pad left or D-pad right (or A/Y in left handed
+mode) will click the left or right mouse button.
+
+There is an alternative method of control which doesn't require you to
+change modes with the D-pad. Press 'Select' to bring up the DS options,
+and choose 'Tap for left click, double tap for right click'. In this
+mode, you can quickly tap the screen to left click the mouse, and tap twice
+to right click the mouse.
+
+
+Here is a complete list of controls in right-handed mode (the default
+setting):
+Key Usage
+Pad Left Left mouse button
+Pad Right Right mouse button
+Pad Up Hover mouse (no mouse button)
+Pad Down Skip dialogue line (for some Lucasarts games), Show inventory
+ (for Beneath a Steel Sky), Show active objects (for Simon the Sorceror)
+Start Pause/game menu (works in some games)
+Select DS Options
+B Skip cutscenes
+A Swap main screen and zoomed screen
+Y Show/Hide debug console
+X Show/Hide on-screen keyboard
+L + D-pad or L + Pen Scroll touch screen view
+L + B Zoom in
+L + A Zoom out
+
+
+
+And here's left-handed mode:
+Key Usage
+Y Left mouse button
+A Right mouse button
+X Hover mouse (no mouse button)
+B Skip dialogue line (for some Lucasarts games), Show inventory (for
+ Beneath a Steel Sky), Show active objects (for Simon the Sorceror)
+Start Pause/game menu (works in some games)
+Select DS Options
+D-pad down Skip cutscenes
+D-pad up Swap main screen and zoomed screen
+D-pad left Show/Hide debug console
+D-pad right Show/Hide on-screen keyboard
+R + D-pad or R + Pen Scroll touch screen view
+R + D-pad down Zoom in
+R + d-pad right Zoom out
+
+
+
+ Game-specific controls
+ ------------------------------------------------------------------------
+
+ * Sam and Max Hit the Road: The current cursor mode is displayed on
+ the top screen. Use d-pad right to switch mode.
+ * Indiana Jones games: If you get into a fight, press Select, and
+ check the box marked 'Use Indy Fighting Controls'.
+ Return to the game, then use the following controls to fight:
+
+ D-pad left: move left
+ D-pad right: move right
+ D-pad up: guard up
+ D-pad down: guard down
+ Y: guard middle
+ X: Punch high
+ A: Punch middle
+ B: Punch low
+ Left shoulder: Fight towards the left
+ Right shoulder: Fight towards the right
+
+ The icon on the top screen shows which way you're currently
+ facing. Remember to turn the option off when the fight ends, or
+ the normal controls won't work!
+ * Beneath a Steel Sky: Press D-pad down to show your inventory.
+ * Simon the Sorcerer 1/2: Press D-pad down to show active objects.
+ * AGI games: Press Start to show the menu bar.
+ * Bargon Attack: Press Start to hit F1 when you need to start the
+ game. Use the on-screen keyboard (hit X) to press other function keys.
+
+
+ DS Options Screen
+ ------------------------------------------------------------------------
+
+Pressing the 'select' button during any game to show the DS options
+screen. This screen shows options specific to the Nintendo DS version
+of ScummVM.
+
+Controls tab
+
+Indy Fight Controls - Enable fighting controls for the Indiana Jones
+games. See 'Game Specific Controls' for more information.
+
+Left handed Mode - Switch the controls on the D-pad with the controls
+on the A/B/X/Y buttons.
+
+Show mouse cursor - Shows the game's mouse cursor on the bottom screen.
+
+Snap to edges - makes it easier for the mouse controls to reach the edges
+of the screen. Useful for Beneath a Steel Sky and Goblins 3.
+
+Touch X offset - if your screen doesn't perform properly, this setting
+allows you to adjust when the cursor appears left or right relative to
+the screen's measured touch position.
+
+Touch Y offset - if your screen doesn't perform properly, this setting
+allows you to adjust when the cursor appears higher or lower relative to
+the screen's measured touch position.
+
+Use Laptop Trackpad-style cursor control - In this mode, use the lower
+screen to drag the cursor around, a bit like using a trackpad on a laptop.
+When this option is enabled, the following option is also enabled.
+
+Tap for left click, double tap for right click - In this mode, you can
+quickly tap on the screen to left click the mouse, or quickly
+double tap on the screen to right click the mouse. If you find clicking
+or double-clicking difficult, try and make a firmer touch on the screen,
+and keep the pen down for longer.
+
+Sensitivity - this bar adjusts the speed of cursor movement when laptop
+trackpad-style cursor control is enabled (see above).
+
+Graphics Tab
+
+Scaling options:
+
+Three scaling options are available for the main screen.
+
+Harware Scale - Scales using the DS hardware scaler using a flicker method.
+Produces lower quality graphics but doesn't slow the game down.
+
+Software Scale - Scales using the CPU. A much higher quality image is
+produced, but at the expense of speed in some games.
+
+Unscaled - Allows you to see the graphics as originaly displayed. This
+doesn't fit on the DS screen, but you can scroll the screen around by holding
+the left shoulder button and using the D-pad or touch screen.
+
+Top screen zoom - These three options control the zoom level of the top
+screen when ScummVM is started up. Changing this option will set the zoom
+to the specified level immediately.
+
+Initial top screen scale:
+
+This option controls the scaling level of the zoomed screen. In ScummVM
+DS, one screen shows a zoomed-in view of the action, and this option controls
+how zoomed in it is. You can also adjust this in the game by holding L and
+pressing A/B.
+
+General Tab
+
+High Quality Audio - Enhance the sound quality, at the expense of some
+slowdown during some games.
+
+Disable power off - ScummVM DS turns the power off when the game quits.
+This option disables that feature.
+
+
+
+
+
+
+ Auto completion dictionary for Sierra AGI games
+ ------------------------------------------------------------------------
+
+If you are playing a Sierra AGI game, you will be using the on-screen
+keyboard quite a lot (press X to show it). To reduce the amount you have
+to type, the game can automatically complete long words for you. To use
+this feature, simply copy the PRED.DIC file from the ScummVM DS archive
+into your game folder on your card. Now, when you use the keyboard,
+possible words will be shown underneith it. To type one of those words,
+simply double click on it with your stylus.
+
+
+ Converting your CD audio
+ ------------------------------------------------------------------------
+
+ScummVM supports playing CD audio for specific games which came with
+music stored as standard music CD tracks. To use this music in ScummVM
+DS, they need to be ripped from the CD and stored in a specific format.
+This can only be done for the CD versions of certain games, such as
+Monkey Island 1, Loom, and Gobliiins. All the floppy games and CD games
+that didn't have CD audio tracks for music don't require any conversion,
+and will work unmodified on ScummVM DS. MP3 audio files for CD music are
+not supported.
+
+Cdex can do the conversion very well and I recommend using it to convert
+your audio files, although any CD ripping software can be used, so feel
+free to use your favourite program. The format you need to use is
+IMA-ADPCM 4-bit Mono. You may use any sample rate. All other formats
+will be rejected, including uncompressed WAV files.
+
+Now I will to describe how to rip your CD tracks with Cdex, which can be
+found here: Cdex Homepage <http://sourceforge.net/projects/cdexos/>.
+Other software can be used to create IMA ADPCM files under Linux or
+MacOS.
+
+To set this up in Cdex, select Settings from the Options menu. On the
+Encoder tab, select 'WAV Output Encoder'. Under 'Encoder Options',
+choose the following:
+
+ Format: WAV
+ Compression: IMA ADPCM
+ Samplerate: 22050 Hz
+ Channels: Mono
+ On the fly encoding: On
+
+Next, go to the 'Filenames' tab and select the folder you want to save
+your Wav files to. Under 'Filename format', enter 'track%3'. This should
+name your WAV files in the correct way. Click OK.
+
+Now select all the tracks on your CD, and click 'Extract CD tracks to a
+compressed audio file'. Cdex should rip all the audio off your CD.
+
+Now all you have to do is copy the newly created WAV files into the same
+directory that your other game data is stored on your CompactFlash card.
+Next time your run ScummVM DS, it should play with music!
+
+*Important Note:* Do not select 'Extract CD tracks to a WAV file'. This
+creates uncompressed WAVs only. You want 'Extract CD tracks to a
+compressed audio file'.
+
+
+ Converting Speech files to MP3 format
+ ------------------------------------------------------------------------
+
+ScummVM supports playing back speech for talkie games in MP3 format.
+Unfortunately, the DS CPU is not quite up to the task, and MP3 audio
+will sometimes cause slowdown in your game. However, if your flash card
+isn't big enough to fit the audio files on, you will have no choice!
+
+To convert your audio you will need a copy of the ScummVM Tools package
+<http://sourceforge.net/project/showfiles.php?group_id=37116&package_id=67433>.
+You will also need a copy of the LAME MP3 encoder
+<http://www.free-codecs.com/Lame_Encoder_download.htm>.
+
+Once this is all installed and set up, the process to encode your audio
+varies from game to game, but the Lucasarts games can all be compressed
+using the following command line:
+
+compress_scumm_sou --mp3 monster.sou
+
+This produces a monster.so3 file which you can copy to your flash card
+and replaces the original monster.sou. Ogg format (monster.sog) and flac
+format files are not currently supported by ScummVM DS, and it is
+unlikely they will ever be supported. There is no way to convert .sog or
+.so3 files back to .sou files. Just dig out your original CD and copy
+the file from that.
+
+
+ Frequently Asked Questions
+ ------------------------------------------------------------------------
+
+I get a lot of email about ScummVM DS. Nearly all of them are exactly
+the same. Here I'm going to try and answer the questions that everybody
+asks me in the hope that I will spend less time answering questions that
+are clearly in the documentation and more time helping people who have a
+real problem or have discovered a real bug.
+
+*Q:* I can't see the bottom line of inventory items in Day of the
+Tentacle, Monkey Island 2, or a few other games! What do I do?
+*A:* Hold down the left shoulder button and use D-pad (or the touch
+screen) to scroll the screen around.
+
+*Q:* I dont see a menu when I press Start in Flight of the Amazon Queen
+or Simon the Sorcerer. Is ScummVM broken?
+*A:* No. To save in Simon the Sorcerer, click 'use', then click on the
+postcard in your inventory. In Flight of the Amazon Queen, click 'use',
+then click on the journal in your inventory.
+
+*Q:* Why does ScummVM crash when I play Monkey Island 1?
+*A:* This happens when MP3 audio tracks are present from the PC version
+of ScummVM. Delete the MP3 tracks and reencode them to ADPCM WAV files
+as described in the CD audio section.
+
+*Q:* When will you support my Mini/Micro SD card reader? I want it!
+Pretty please?
+*A:* ScummVM uses DLDI drivers. If your card reader manufacturer doesn't
+provide a driver, there is nothing I can do about it. The people to ask
+are the card reader manufacturers themselves.
+
+*Q:* Can't you use the extra RAM in the M3/Supercard or the official
+Opera Expansion Pack to support more games like The Dig and Full
+Throttle? DS Linux has done it, so why can't you?
+*A:* Not at the moment. The extra RAM has certain differences to the
+build in RAM which makes it difficult to use for general programs. As
+ScummVM DS is an official port, the changes to the ScummVM code base
+must be minimal to avoid making the code difficult to read for other
+users. I do have plans to work on this some time in the future, but
+don't nag me about when it'll be done. If and when there's progress with
+this, I will post on the ScummVM forums about it.
+
+
+*Q:* ScummVM DS turns off my DS when I hit 'Quit' in the game or quit
+from the frontend. Why doesn't it return to the menu?
+*A:* Due to bugs in the ScummVM codebase, many of the ScummVM games
+cannot quit cleanly leaving the machine in the same state as when it
+started. You will notice that no other versions of ScummVM can quit back
+to the menu either. This will be fixed at some time in the future.
+
+
+
+
+ Contributors
+ ------------------------------------------------------------------------
+
+ScummVM DS uses chishm's GBA Movie Player FAT driver.
+The CPU scaler is by Tramboi and Robin Watts
+The ARM code was optimised by Robin Watts
+Thanks to highpass for the ScummVM DS icons.
+Thanks to zhevon for the Sam & Max cursor code.
+Thanks to theNinjaBunny for the M3 Adaptor guide on this site.
+Thanks also to everyone on the GBADev Forums.
+
+This program was brought to you by caffiene, sugar, and late nights.
+
+
+ Donations and Getting Help
+ ------------------------------------------------------------------------
+
+If you have problems getting ScummVM to work on your hardware, please
+read the FAQ first. /Please/ don't ask me questions which are
+answered in the FAQ, I get many emails about this program each day, and
+I can't help the people who really need help if I'm answering the same
+question all the time which is already answered on this page. Other than
+that, feel free to post on the ScummVM DS forum <http://forums.scummvm.org>
+for help. Please do your research first though. There is no way of
+running this on an out-of-the box DS without extra hardware. Most of
+these things are fairly inexpensive though.
+
+If you want to contact me, please email me on scummvm at millstone dot
+demon dot co dot uk.
+
+If you want to help with the development of ScummVM DS, great! Download
+the source code and get building. There are plenty of things left to do.
+
+You can also help by making a donation if you've particularly enjoyed
+ScummVM DS. This uses Paypal, and is completely secure. There's no
+pressure though, ScummVM DS is completely free. This is just for those
+who would like to make a contribution to further development.
+
+
+
+ Building from Sources
+ ------------------------------------------------------------------------
+
+ScummVM is an open source project. This means that anyone is free to
+take the source code to the project and make their own additions and fixes,
+contributing them back to the authors for consideration for the next version.
+
+To build ScummVM DS from source, it's probably better to checkout the
+latest version of the code from the ScummVM SVN repository. The ScummVM
+Sourceforge.net homepage <http://sourceforge.net/projects/scummvm> has
+all the information about how to do this.
+
+By default, ScummVM DS expects to find libmad, an MP3 compressor library
+targeted for the ARM platform. If you don't have this, you must disable
+libmad support by opening 'backends/platform/ds/arm9/makefile' and
+commenting out the line which says USE_MAD = 1.
+
+Then, enter the 'backends/platform/ds' folder and type:
+make SCUMM_BUILD=a
+
+The executable nds file will build inside 'backends/platform/ds/arm9/SCUMMVM-A'.
+
+For other builds, substitute the letters b - g in the above line.
+
+
+
diff --git a/backends/platform/ds/arm9/makefile b/backends/platform/ds/arm9/makefile
index 7472a32218..e74bcf28da 100644
--- a/backends/platform/ds/arm9/makefile
+++ b/backends/platform/ds/arm9/makefile
@@ -8,25 +8,29 @@ libndsdir = $(DEVKITPRO)/libnds
# Select the build by setting SCUMM_BUILD to a,b,c,d,e,f or g.
# Anything else gets build a.
-ifeq ($(SCUMM_BUILD),g)
+ifeq ($(SCUMM_BUILD),h)
+ DS_BUILD_H = 1
+ else
+ ifeq ($(SCUMM_BUILD),g)
DS_BUILD_G = 1
-else
- ifeq ($(SCUMM_BUILD),f)
+ else
+ ifeq ($(SCUMM_BUILD),f)
DS_BUILD_F = 1
- else
- ifeq ($(SCUMM_BUILD),e)
- DS_BUILD_E = 1
else
- ifeq ($(SCUMM_BUILD),d)
- DS_BUILD_D = 1
+ ifeq ($(SCUMM_BUILD),e)
+ DS_BUILD_E = 1
else
- ifeq ($(SCUMM_BUILD),c)
- DS_BUILD_C = 1
+ ifeq ($(SCUMM_BUILD),d)
+ DS_BUILD_D = 1
else
- ifeq ($(SCUMM_BUILD),b)
- DS_BUILD_B = 1
+ ifeq ($(SCUMM_BUILD),c)
+ DS_BUILD_C = 1
else
+ ifeq ($(SCUMM_BUILD),b)
+ DS_BUILD_B = 1
+ else
DS_BUILD_A = 1
+ endif
endif
endif
endif
@@ -67,7 +71,12 @@ endif
# NOTE: The header and libs for the debugger is assumed to be in the libnds
# folder.
-VPATH = $(srcdir)
+vpath %.h $(srcdir)
+vpath %.cpp $(srcdir)
+vpath %.c $(srcdir)
+vpath %.m $(srcdir)
+vpath %.asm $(srcdir)
+vpath %.s $(srcdir)
# Command to build libmad is:
# ./configure --host=arm-elf --enable-speed --enable-sso -enable-fpm=arm CFLAGS='-specs=ds_arm9.specs -mthumb-interwork'
@@ -75,8 +84,8 @@ VPATH = $(srcdir)
# I actually had to use
# ./configure --host=arm-elf --enable-speed --enable-sso -enable-fpm=arm CFLAGS='-specs=ds_arm9.specs -mthumb-interwork' LDFLAGS='C:/Progra~1/devkitpro/libnds/lib/libnds9.a' --disable-shared --disable-debugging
-USE_ARM_SOUND_ASM = 1
ARM = 1
+USE_ARM_SOUND_ASM = 1
USE_ARM_COSTUME_ASM = 1
ifdef DS_BUILD_A
@@ -135,6 +144,13 @@ ifdef DS_BUILD_G
BUILD=scummvm-G
endif
+ifdef DS_BUILD_H
+ DEFINES = -DDS_NON_SCUMM_BUILD -DDS_BUILD_H
+ LOGO = logog.bmp
+ ENABLE_PARALLACTION = STATIC_PLUGIN
+ BUILD=scummvm-H
+endif
+
ARM7BIN := -7 $(CURDIR)/../../arm7/arm7.bin
ICON := -b ../../../logo.bmp "ScummVM;By Neil Millstone;"
@@ -147,6 +163,7 @@ CFLAGS = -Wno-multichar -Wall\
-mcpu=arm9tdmi -mtune=arm9tdmi -fomit-frame-pointer\
-mthumb-interwork -DUSE_ARM_COSTUME_ASM=1
+
# -ffast-math
ifdef USE_DEBUGGER
@@ -160,7 +177,7 @@ ifdef USE_PROFILER
endif
CXXFLAGS= $(CFLAGS) -Wno-non-virtual-dtor -Wno-unknown-pragmas -Wno-reorder \
- -fno-exceptions -fno-rtti -mthumb-interwork
+ -fno-exceptions -fno-rtti -mthumb-interwork -ffunction-sections -fdata-sections
# -mthumb
@@ -180,12 +197,12 @@ ifdef USE_MAD
endif
-LDFLAGS = -specs=ds_arm9.specs -mthumb-interwork -Wl,--wrap,time -mno-fpu -Wl,-Map,map.txt
+LDFLAGS = -specs=ds_arm9.specs -mthumb-interwork -Wl,--wrap,time -mno-fpu -Wl,-Map,map.txt -Wl,--gc-sections
-INCLUDES= -I./ -I$(portdir)/$(BUILD) -I$(srcdir) -I$(srcdir)/common -I$(portdir)/source \
- -I$(portdir)/data -I$(libndsdir)/include -I$(portdir)/../commoninclude\
- -I$(libndsdir)/include -I$(libndsdir)/include/nds -I$(srcdir)/engines -I$(portdir)/source/mad\
- -I$(portdir)/source/libcartreset -include $(srcdir)/common/scummsys.h
+INCLUDES= -I$(portdir)/$(BUILD) -I$(srcdir) -I$(srcdir)/engines \
+ -I$(portdir)/data -I$(portdir)/../commoninclude \
+ -I$(portdir)/source -I$(portdir)/source/mad -I$(portdir)/source/libcartreset \
+ -I$(libndsdir)/include -include $(srcdir)/common/scummsys.h
LIBS = -lm -L$(libndsdir)/lib -L$(portdir)/lib -lnds9
@@ -232,7 +249,8 @@ endif
DATA_OBJS := $(portdir)/data/icons.o $(portdir)/data/keyboard.o $(portdir)/data/keyboard_pal.o $(portdir)/data/default_font.o $(portdir)/data/8x8font_tga.o
-COMPRESSOR_OBJS := $(portdir)/source/compressor/lz.o
+COMPRESSOR_OBJS :=
+#$(portdir)/source/compressor/lz.o
FAT_OBJS := $(portdir)/source/fat/disc_io.o $(portdir)/source/fat/gba_nds_fat.o\
$(portdir)/source/fat/io_fcsr.o $(portdir)/source/fat/io_m3cf.o\
@@ -252,14 +270,15 @@ FAT_OBJS := $(portdir)/source/fat/disc_io.o $(portdir)/source/fat/gba_nds_fat.o
# $(portdir)/source/fat/io_sd_common.o $(portdir)/source/fat/io_scsd_s.o \
# $(portdir)/source/fat/io_sc_common.o $(portdir)/source/fat/io_sd_common.o
-LIBCARTRESET_OBJS := $(portdir)/source/libcartreset/cartreset.o
+LIBCARTRESET_OBJS :=
+#$(portdir)/source/libcartreset/cartreset.o
# Files in this list will be optimisied for speed, otherwise they will be optimised for space
OPTLIST := actor.cpp ds_main.cpp osystem_ds.cpp blitters.cpp fmopl.cpp rate.cpp mixer.cpp isomap.cpp image.cpp gfx.cpp sprite.cpp actor_path.cpp actor_walk.cpp
#OPTLIST :=
# Compiler options for files which should be optimised for speed
-OPT_SPEED := -O2
+OPT_SPEED := -O3
# Compiler options for files which should be optimised for space
OPT_SIZE := -Os
@@ -281,7 +300,7 @@ ndsall:
include $(srcdir)/Makefile.common
semiclean:
- $(RM) $(portdir)/source/dsoptions.o $(portdir)/source/dsmain.o $(FAT_OBJS) $(DATA_OBJS) $(portdir)/source/wordcompletion.o
+ $(RM) $(portdir)/source/dsoptions.o $(portdir)/source/dsmain.o $(FAT_OBJS) $(DATA_OBJS) $(portdir)/source/wordcompletion.o $(portdir)/source/dsoptions.o
clean:
$(RM) $(OBJS) $(EXECUTABLE)
@@ -333,36 +352,17 @@ endef
##############
# Replacement rule for the one in makefile.common
##############
-ifndef HAVE_GCC3
-# If you use GCC, disable the above and enable this for intelligent
-# dependency tracking.
-#.cpp.o:
-%.o:%.cpp
- $(MKDIR) $(*D)/$(DEPDIR)
- $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d2" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
-# $(ECHO) "$(*D)/" > $(*D)/$(DEPDIR)/$(*F).d
- $(CAT) "$(*D)/$(DEPDIR)/$(*F).d2" >> "$(*D)/$(DEPDIR)/$(*F).d"
- $(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.
-#.cpp.o:
-%.o:%.cpp
+%.o: %.cpp
# echo !!!!!!!!!!!! $(notdir $<)
# ifeq ( $(notdir $<), $(findstring $(notdir $<), $(OPTLIST)) )
# OPTFLAG=-O3
# else
# OPTFLAG=-Os
# endif
-
# export OPTFLAG = ;
# echo !!!!!!!! $(OPTFLAG)
-
$(MKDIR) $(*D)/$(DEPDIR)
$(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(if $(findstring $(notdir $<), $(OPTLIST)), $(OPT_SPEED), $(OPT_SIZE)) $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
-endif
#---------------------------------------------------------------------------------
@@ -412,6 +412,7 @@ endif
padbin 16 $(basename $@).ds.gba
#---------------------------------------------------------------------------------
+# FIXME: The following rule hardcodes the input & output filename -- shouldn't it use $< and $@ instead?
%.bin: %.elf
$(OBJCOPY) -S scummvm.elf scummvm-stripped.elf
$(OBJCOPY) -O binary scummvm-stripped.elf scummvm.bin
@@ -419,4 +420,3 @@ endif
#%.o: %.s
# $(MKDIR) $(*D)/$(DEPDIR)
# $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
-
diff --git a/backends/platform/ds/arm9/source/blitters_arm.s b/backends/platform/ds/arm9/source/blitters_arm.s
index 5f7df298b4..48ec316675 100644
--- a/backends/platform/ds/arm9/source/blitters_arm.s
+++ b/backends/platform/ds/arm9/source/blitters_arm.s
@@ -20,149 +20,12 @@
@
@ @author Robin Watts (robin@wss.co.uk)
- .global asmDrawStripToScreen
- .global asmCopy8Col
.global Rescale_320x256xPAL8_To_256x256x1555
.global Rescale_320x256x1555_To_256x256x1555
.section .itcm,"ax", %progbits
.align 2
.code 32
- @ ARM implementation of asmDrawStripToScreen.
- @
- @ C prototype would be:
- @
- @ extern "C" void asmDrawStripToScreen(int height,
- @ int width,
- @ byte const *text,
- @ byte const *src,
- @ byte *dst,
- @ int vsPitch,
- @ int vsScreenWidth,
- @ int textSurfacePitch);
- @
- @ In addition, we assume that text, src and dst are all word (4 byte)
- @ aligned. This is the same assumption that the old 'inline' version
- @ made.
-asmDrawStripToScreen:
- @ r0 = height
- @ r1 = width
- @ r2 = text
- @ r3 = src
- MOV r12,r13
- STMFD r13!,{r4-r7,r9-r11,R14}
- LDMIA r12,{r4,r5,r6,r7}
- @ r4 = dst
- @ r5 = vsPitch
- @ r6 = vmScreenWidth
- @ r7 = textSurfacePitch
-
- CMP r0,#0 @ If height<=0
- MOVLE r0,#1 @ height=1
- CMP r1,#4 @ If width<4
- BLT end @ return
-
- @ Width &= ~4 ? What's that about then? Width &= ~3 I could have
- @ understood...
- BIC r1,r1,#4
-
- SUB r5,r5,r1 @ vsPitch -= width
- SUB r6,r6,r1 @ vmScreenWidth -= width
- SUB r7,r7,r1 @ textSurfacePitch -= width
- MOV r10,#253
- ORR r10,r10,r10,LSL #8
- ORR r10,r10,r10,LSL #16 @ r10 = mask
-yLoop:
- MOV r14,r1 @ r14 = width
-xLoop:
- LDR r12,[r2],#4 @ r12 = [text]
- LDR r11,[r3],#4 @ r11 = [src]
- CMP r12,r10
- BNE singleByteCompare
- SUBS r14,r14,#4
- STR r11,[r4], #4 @ r4 = [dst]
- BGT xLoop
-
- ADD r2,r2,r7 @ text += textSurfacePitch
- ADD r3,r3,r5 @ src += vsPitch
- ADD r4,r4,r6 @ dst += vmScreenWidth
- SUBS r0,r0,#1
- BGT yLoop
- LDMFD r13!,{r4-r7,r9-r11,PC}
-
-singleByteCompare:
- MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
- CMP r9,r10,LSR #24 @ if (r9 == mask)
- MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
- ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
-
- MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
- CMP r9,r10,LSR #24 @ if (r9 == mask)
- MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
- ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
-
- MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
- CMP r9,r10,LSR #24 @ if (r9 == mask)
- MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
- ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
-
- MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
- CMP r9,r10,LSR #24 @ if (r9 == mask)
- MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
- ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
-
- STR r12,[r4],#4
- SUBS r14,r14,#4
- BGT xLoop
-
- ADD r2,r2,r7 @ text += textSurfacePitch
- ADD r3,r3,r5 @ src += vsPitch
- ADD r4,r4,r6 @ dst += vmScreenWidth
- SUBS r0,r0,#1
- BGT yLoop
-end:
- LDMFD r13!,{r4-r7,r9-r11,PC}
-
-
- @ ARM implementation of asmCopy8Col
- @
- @ C prototype would be:
- @
- @ extern "C" void asmCopy8Col(byte *dst,
- @ int dstPitch,
- @ const byte *src,
- @ int height);
- @
- @ In addition, we assume that src and dst are both word (4 byte)
- @ aligned. This is the same assumption that the old 'inline' version
- @ made.
-asmCopy8Col:
- @ r0 = dst
- @ r1 = dstPitch
- @ r2 = src
- @ r3 = height
- STMFD r13!,{r14}
- SUB r1,r1,#4
-
- TST r3,#1
- ADDNE r3,r3,#1
- BNE roll2
-yLoop2:
- LDR r12,[r2],#4
- LDR r14,[r2],r1
- STR r12,[r0],#4
- STR r14,[r0],r1
-roll2:
- LDR r12,[r2],#4
- LDR r14,[r2],r1
- SUBS r3,r3,#2
- STR r12,[r0],#4
- STR r14,[r0],r1
- BNE yLoop2
-
- LDMFD r13!,{PC}
-
-
@ ARM implementation of Rescale_320x256x1555_To_256x256x1555
@
@ C prototype would be:
diff --git a/backends/platform/ds/arm9/source/cdaudio.h b/backends/platform/ds/arm9/source/cdaudio.h
index d237569bb7..d1897d3e5d 100644
--- a/backends/platform/ds/arm9/source/cdaudio.h
+++ b/backends/platform/ds/arm9/source/cdaudio.h
@@ -20,7 +20,7 @@
*
*/
- #ifndef _CDAUDIO_H_
+#ifndef _CDAUDIO_H_
#define _CDAUDIO_H_
namespace DS {
diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp
index f4706807f7..872a196e9b 100644
--- a/backends/platform/ds/arm9/source/dsmain.cpp
+++ b/backends/platform/ds/arm9/source/dsmain.cpp
@@ -65,6 +65,8 @@
//#define USE_LIBCARTRESET
#include <nds.h>
+#include <nds/registers_alt.h>
+#include <nds/arm9/exceptions.h>
//#include <ARM9/console.h> //basic print funcionality
@@ -75,13 +77,10 @@
#include "icons_raw.h"
#include "fat/gba_nds_fat.h"
#include "fat/disc_io.h"
-#include "common/config-manager.h"
-#include "engines/scumm/scumm.h"
#include "keyboard_raw.h"
#include "keyboard_pal_raw.h"
#define V16(a, b) ((a << 12) | b)
#include "touchkeyboard.h"
-#include "registers_alt.h"
//#include "compact_flash.h"
#include "dsoptions.h"
#ifdef USE_DEBUGGER
@@ -96,6 +95,26 @@
#endif
#include "backends/fs/ds/ds-fs.h"
+extern "C" u32 getExceptionAddress( u32 opcodeAddress, u32 thumbState);
+extern const char __itcm_start[];
+static const char *registerNames[] =
+ { "r0","r1","r2","r3","r4","r5","r6","r7",
+ "r8 ","r9 ","r10","r11","r12","sp ","lr ","pc " };
+
+/*
+extern "C" void* __real_malloc(size_t size);
+
+extern "C" void* __wrap_malloc(size_t size) {
+ void* res = __real_malloc(size);
+ if (res) {
+ return res;
+ } else {
+ consolePrintf("Failed alloc %d\n", size);
+ return NULL;
+ }
+}
+*/
+
namespace DS {
// From console.c in NDSLib
@@ -168,7 +187,7 @@ bool displayModeIs8Bit = false;
u8 gameID;
bool snapToBorder = false;
-bool consoleEnable = true;
+bool consoleEnable = false;
bool gameScreenSwap = false;
bool isCpuScalerEnabled();
//#define HEAVY_LOGGING
@@ -197,6 +216,13 @@ int mouseHotspotX, mouseHotspotY;
bool cursorEnable = false;
bool mouseCursorVisible = true;
bool rightButtonDown = false;
+bool touchPadStyle = false;
+int touchPadSensitivity = 8;
+bool tapScreenClicks = true;
+
+int tapCount = 0;
+int tapTimeout = 0;
+int tapComplete = 0;
// Dragging
int dragStartX, dragStartY;
@@ -213,7 +239,14 @@ int gameHeight = 200;
// Scale
bool twoHundredPercentFixedScale = false;
bool cpuScalerEnable = false;
-#define NUM_SUPPORTED_GAMES 20
+
+ // 100 256
+ // 150 192
+ // 200 128
+
+ // (256 << 8) / scale
+
+
#ifdef USE_PROFILER
int hBlankCount = 0;
@@ -221,6 +254,7 @@ int hBlankCount = 0;
u8* scalerBackBuffer = NULL;
+#define NUM_SUPPORTED_GAMES 21
gameListType gameList[NUM_SUPPORTED_GAMES] = {
// Unknown game - use normal SCUMM controls
@@ -248,6 +282,7 @@ gameListType gameList[NUM_SUPPORTED_GAMES] = {
{"elvira2", CONT_SIMON},
{"elvira1", CONT_SIMON},
{"waxworks", CONT_SIMON},
+ {"parallaction", CONT_NIPPON},
};
gameListType* currentGame = NULL;
@@ -260,6 +295,7 @@ bool penHeld;
bool penReleased;
bool penDownLastFrame;
s32 penX, penY;
+s32 penDownX, penDownY;
int keysDownSaved;
int keysReleasedSaved;
int keysChangedSaved;
@@ -299,9 +335,41 @@ void setCpuScalerEnable(bool enable) {
cpuScalerEnable = enable;
}
+void setTrackPadStyleEnable(bool enable) {
+ touchPadStyle = enable;
+}
+
+void setTapScreenClicksEnable(bool enable) {
+ tapScreenClicks = enable;
+}
+
+void setGameScreenSwap(bool enable) {
+ gameScreenSwap = enable;
+}
+
+void setSensitivity(int sensitivity) {
+ touchPadSensitivity = sensitivity;
+}
+
+void setTopScreenZoom(int percentage) {
+ // 100 256
+ // 150 192
+ // 200 128
+
+ // (256 << 8) / scale
+
+ s32 scale = (percentage << 8) / 100;
+ subScreenScale = (256 * 256) / scale;
+
+// consolePrintf("Scale is %d %%\n", percentage);
+}
// return (ConfMan.hasKey("cpu_scaler", "ds") && ConfMan.getBool("cpu_scaler", "ds"));
+controlType getControlType() {
+ return currentGame->control;
+}
+
//plays an 8 bit mono sample at 11025Hz
void playSound(const void* data, u32 length, bool loop, bool adpcm, int rate)
@@ -429,14 +497,14 @@ void initGame() {
consolePrintf("initing game...");
#endif
- static bool firstTime = true;
+// static bool firstTime = true;
setOptions();
//strcpy(gameName, ConfMan.getActiveDomain().c_str());
strcpy(gameName, ConfMan.get("gameid").c_str());
- consolePrintf("\n\n\n\nCurrent game: '%s' %d\n", gameName, gameName[0]);
+// consolePrintf("\n\n\n\nCurrent game: '%s' %d\n", gameName, gameName[0]);
currentGame = &gameList[0]; // Default game
@@ -447,16 +515,12 @@ void initGame() {
}
}
- if (firstTime) {
+/* if (firstTime) {
firstTime = false;
- if (ConfMan.hasKey("22khzaudio", "ds") && ConfMan.getBool("22khzaudio", "ds")) {
- startSound(22050, 8192);
- } else {
- startSound(11025, 4096);
- }
}
+*/
#ifdef HEAVY_LOGGING
consolePrintf("done\n");
#endif
@@ -631,7 +695,7 @@ void checkSleepMode() {
void setShowCursor(bool enable)
{
- if (currentGame->control == CONT_SCUMM_SAMNMAX)
+ if ((currentGame) && (currentGame->control == CONT_SCUMM_SAMNMAX))
{
if (cursorEnable) {
sprites[1].attribute[0] = ATTR0_BMP | 150;
@@ -654,23 +718,28 @@ void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX,
mouseHotspotX = hotspotX;
mouseHotspotY = hotspotY;
+ //consolePrintf("Set cursor icon %d, %d\n", w, h);
+
{
int off = 128*64;
memset(SPRITE_GFX + off, 0, 32 * 32 * 2);
memset(SPRITE_GFX_SUB + off, 0, 32 * 32 * 2);
+
for (uint y=0; y<h; y++) {
for (uint x=0; x<w; x++) {
int color = icon[y*w+x];
+
+ //consolePrintf("%d:%d ", color, OSystem_DS::instance()->getDSPaletteEntry(color));
if (color == keycolor) {
SPRITE_GFX[off+(y)*32+x] = 0x0000; // black background
SPRITE_GFX_SUB[off+(y)*32+x] = 0x0000; // black background
} else {
- SPRITE_GFX[off+(y)*32+x] = BG_PALETTE[color] | 0x8000;
- SPRITE_GFX_SUB[off+(y)*32+x] = BG_PALETTE[color] | 0x8000;
+ SPRITE_GFX[off+(y)*32+x] = OSystem_DS::instance()->getDSCursorPaletteEntry(color) | 0x8000;
+ SPRITE_GFX_SUB[off+(y)*32+x] = OSystem_DS::instance()->getDSCursorPaletteEntry(color) | 0x8000;
}
}
}
@@ -733,6 +802,7 @@ void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX,
sprites[1].attribute[1] = ATTR1_SIZE_64 | pos;
sprites[1].attribute[2] = ATTR2_ALPHA(1) | 176;
}
+
}
@@ -745,6 +815,7 @@ void displayMode16Bit() {
u16 buffer[32 * 32 * 2];
+ releaseAllKeys();
if (displayModeIs8Bit) {
// static int test = 0;
@@ -1109,7 +1180,7 @@ void setKeyboardEnable(bool en) {
} else {
-
+ DS::releaseAllKeys();
// Restore the palette that the keyboard has used
for (int r = 0; r < 256; r++) {
BG_PALETTE_SUB[r] = BG_PALETTE[r];
@@ -1157,6 +1228,194 @@ bool getIsDisplayMode8Bit() {
return displayModeIs8Bit;
}
+void doScreenTapMode(OSystem_DS* system)
+{
+ Common::Event event;
+ static bool left = false, right = false;
+
+ if (left) {
+ event.type = Common::EVENT_LBUTTONUP;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ left = false;
+ }
+
+ if (right) {
+ event.type = Common::EVENT_RBUTTONUP;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ right = false;
+ }
+
+
+ if (tapComplete == 1) {
+ event.type = Common::EVENT_LBUTTONDOWN;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ tapComplete = 0;
+ left = true;
+ } else if (tapComplete == 2) {
+ event.type = Common::EVENT_RBUTTONDOWN;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ tapComplete = 0;
+ right = true;
+ }
+
+
+ if (getKeysDown() & KEY_LEFT) {
+ event.type = Common::EVENT_LBUTTONDOWN;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+
+ if (getKeysReleased() & KEY_LEFT) {
+ event.type = Common::EVENT_LBUTTONUP;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+
+
+ if (getKeysDown() & KEY_RIGHT) {
+ event.type = Common::EVENT_RBUTTONDOWN;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+
+ if (getKeysReleased() & KEY_RIGHT) {
+ event.type = Common::EVENT_RBUTTONUP;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+
+ event.type = Common::EVENT_MOUSEMOVE;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+}
+
+void doButtonSelectMode(OSystem_DS* system)
+{
+ Common::Event event;
+
+
+ if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) {
+ event.type = Common::EVENT_MOUSEMOVE;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ //consolePrintf("x=%d y=%d \n", getPenX(), getPenY());
+ }
+
+ static bool leftButtonDown = false;
+ static bool rightButtonDown = false;
+
+ if (getPenReleased() && (leftButtonDown || rightButtonDown)) {
+ if (leftButtonDown) {
+ event.type = Common::EVENT_LBUTTONUP;
+ } else {
+ event.type = Common::EVENT_RBUTTONUP;
+ }
+
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+
+
+ if ((mouseMode != MOUSE_HOVER) || (!displayModeIs8Bit)) {
+ if (getPenDown() && (!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) {
+ if ((mouseMode == MOUSE_LEFT) || (!displayModeIs8Bit)) {
+ event.type = Common::EVENT_LBUTTONDOWN;
+ leftButtonDown = true;
+ } else {
+ event.type = Common::EVENT_RBUTTONDOWN;
+ rightButtonDown = true;
+ }
+
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+
+ } else {
+ // In hover mode, D-pad left and right click the mouse when the pen is on the screen
+
+ if (getPenHeld()) {
+ if (getKeysDown() & KEY_LEFT) {
+ event.type = Common::EVENT_LBUTTONDOWN;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+ if (getKeysReleased() & KEY_LEFT) {
+ event.type = Common::EVENT_LBUTTONUP;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+
+
+ if (getKeysDown() & KEY_RIGHT) {
+ event.type = Common::EVENT_RBUTTONDOWN;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+ if (getKeysReleased() & KEY_RIGHT) {
+ event.type = Common::EVENT_RBUTTONUP;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ system->addEvent(event);
+ }
+ }
+ }
+
+ if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (!getIndyFightState()) && (!getKeyboardEnable())) {
+
+ if (!getPenHeld() || (mouseMode != MOUSE_HOVER)) {
+ if (getKeysDown() & KEY_LEFT) {
+ mouseMode = MOUSE_LEFT;
+ }
+
+ if (rightButtonDown)
+ {
+ Common::Event event;
+ event.mouse = Common::Point(getPenX(), getPenY());
+ event.type = Common::EVENT_RBUTTONUP;
+ system->addEvent(event);
+ rightButtonDown = false;
+ }
+
+
+ if (getKeysDown() & KEY_RIGHT) {
+ if ((currentGame->control != CONT_SCUMM_SAMNMAX) && (currentGame->control != CONT_FUTURE_WARS) && (currentGame->control != CONT_GOBLINS)) {
+ mouseMode = MOUSE_RIGHT;
+ } else {
+ // If we're playing sam and max, click and release the right mouse
+ // button to change verb
+ Common::Event event;
+
+ if (currentGame->control == CONT_FUTURE_WARS) {
+ event.mouse = Common::Point(320 - 128, 200 - 128);
+ event.type = Common::EVENT_MOUSEMOVE;
+ system->addEvent(event);
+ } else {
+ event.mouse = Common::Point(getPenX(), getPenY());
+ }
+
+ rightButtonDown = true;
+
+
+ event.type = Common::EVENT_RBUTTONDOWN;
+ system->addEvent(event);
+
+ //event.type = Common::EVENT_RBUTTONUP;
+ //system->addEvent(event);
+ }
+ }
+
+
+
+ if (getKeysDown() & KEY_UP) {
+ mouseMode = MOUSE_HOVER;
+ }
+ }
+ }
+}
+
void addEventsToQueue() {
#ifdef HEAVY_LOGGING
consolePrintf("addEventsToQueue\n");
@@ -1286,54 +1545,6 @@ void addEventsToQueue() {
}
- if (!getPenHeld() || (mouseMode != MOUSE_HOVER)) {
- if (getKeysDown() & KEY_LEFT) {
- mouseMode = MOUSE_LEFT;
- }
-
- if (rightButtonDown)
- {
- Common::Event event;
- event.mouse = Common::Point(getPenX(), getPenY());
- event.type = Common::EVENT_RBUTTONUP;
- system->addEvent(event);
- rightButtonDown = false;
- }
-
-
- if (getKeysDown() & KEY_RIGHT) {
- if ((currentGame->control != CONT_SCUMM_SAMNMAX) && (currentGame->control != CONT_FUTURE_WARS) && (currentGame->control != CONT_GOBLINS)) {
- mouseMode = MOUSE_RIGHT;
- } else {
- // If we're playing sam and max, click and release the right mouse
- // button to change verb
- Common::Event event;
-
- if (currentGame->control == CONT_FUTURE_WARS) {
- event.mouse = Common::Point(320 - 128, 200 - 128);
- event.type = Common::EVENT_MOUSEMOVE;
- system->addEvent(event);
- } else {
- event.mouse = Common::Point(getPenX(), getPenY());
- }
-
- rightButtonDown = true;
-
-
- event.type = Common::EVENT_RBUTTONDOWN;
- system->addEvent(event);
-
- //event.type = Common::EVENT_RBUTTONUP;
- //system->addEvent(event);
- }
- }
-
-
-
- if (getKeysDown() & KEY_UP) {
- mouseMode = MOUSE_HOVER;
- }
- }
@@ -1359,52 +1570,13 @@ void addEventsToQueue() {
if (!keyboardEnable) {
- if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) {
- event.type = Common::EVENT_MOUSEMOVE;
- event.mouse = Common::Point(getPenX(), getPenY());
- system->addEvent(event);
- //consolePrintf("x=%d y=%d \n", getPenX(), getPenY());
+ if ((tapScreenClicks) && (getIsDisplayMode8Bit()))
+ {
+ doScreenTapMode(system);
}
-
- if ((mouseMode != MOUSE_HOVER) || (!displayModeIs8Bit)) {
- if (getPenDown() && (!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) {
- event.type = ((mouseMode == MOUSE_LEFT) || (!displayModeIs8Bit))? Common::EVENT_LBUTTONDOWN: Common::EVENT_RBUTTONDOWN;
- event.mouse = Common::Point(getPenX(), getPenY());
- system->addEvent(event);
- }
-
- if (getPenReleased()) {
- event.type = mouseMode == MOUSE_LEFT? Common::EVENT_LBUTTONUP: Common::EVENT_RBUTTONUP;
- event.mouse = Common::Point(getPenX(), getPenY());
- system->addEvent(event);
- }
- } else {
- // In hover mode, D-pad left and right click the mouse when the pen is on the screen
-
- if (getPenHeld()) {
- if (getKeysDown() & KEY_LEFT) {
- event.type = Common::EVENT_LBUTTONDOWN;
- event.mouse = Common::Point(getPenX(), getPenY());
- system->addEvent(event);
- }
- if (getKeysReleased() & KEY_LEFT) {
- event.type = Common::EVENT_LBUTTONUP;
- event.mouse = Common::Point(getPenX(), getPenY());
- system->addEvent(event);
- }
-
-
- if (getKeysDown() & KEY_RIGHT) {
- event.type = Common::EVENT_RBUTTONDOWN;
- event.mouse = Common::Point(getPenX(), getPenY());
- system->addEvent(event);
- }
- if (getKeysReleased() & KEY_RIGHT) {
- event.type = Common::EVENT_RBUTTONUP;
- event.mouse = Common::Point(getPenX(), getPenY());
- system->addEvent(event);
- }
- }
+ else
+ {
+ doButtonSelectMode(system);
}
if (((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R)) || (indyFightState)) && (displayModeIs8Bit)) {
@@ -1537,8 +1709,8 @@ void triggerIcon(int imageNum) {
void setIcon(int num, int x, int y, int imageNum, int flags, bool enable) {
- sprites[num].attribute[0] = ATTR0_BMP | (enable? y: 192) | (!enable? ATTR0_DISABLED: 0);
- sprites[num].attribute[1] = ATTR1_SIZE_32 | x | flags;
+ sprites[num].attribute[0] = ATTR0_BMP | (enable? (y & 0xFF): 192) | (!enable? ATTR0_DISABLED: 0);
+ sprites[num].attribute[1] = ATTR1_SIZE_32 | (x & 0x1FF) | flags;
sprites[num].attribute[2] = ATTR2_ALPHA(1)| (imageNum * 16);
}
@@ -1552,28 +1724,30 @@ void updateStatus() {
int offs;
if (displayModeIs8Bit) {
- switch (mouseMode) {
- case MOUSE_LEFT: {
- offs = 1;
- break;
- }
- case MOUSE_RIGHT: {
- offs = 2;
- break;
- }
- case MOUSE_HOVER: {
- offs = 0;
- break;
- }
- default: {
- // Nothing!
- offs = 0;
- break;
+ if (!tapScreenClicks) {
+ switch (mouseMode) {
+ case MOUSE_LEFT: {
+ offs = 1;
+ break;
+ }
+ case MOUSE_RIGHT: {
+ offs = 2;
+ break;
+ }
+ case MOUSE_HOVER: {
+ offs = 0;
+ break;
+ }
+ default: {
+ // Nothing!
+ offs = 0;
+ break;
+ }
}
+
+ setIcon(0, 208, 150, offs, 0, true);
}
- setIcon(0, 208, 150, offs, 0, true);
-
if (indyFightState) {
setIcon(1, (190 - 32), 150, 3, (indyFightRight? 0: ATTR1_FLIP_X), true);
// consolePrintf("%d\n", indyFightRight);
@@ -1631,7 +1805,7 @@ void setMainScreenScroll(int x, int y) {
BG3_CX = x + (((frameCount & 1) == 0)? 64: 0);
BG3_CY = y;
- if (!gameScreenSwap) {
+ if ((!gameScreenSwap) || (touchPadStyle)) {
touchX = x >> 8;
touchY = y >> 8;
}
@@ -1660,7 +1834,7 @@ void setMainScreenScale(int x, int y) {
BG3_YDY = y;
}
- if (!gameScreenSwap) {
+ if ((!gameScreenSwap) || (touchPadStyle)) {
touchScX = x;
touchScY = y;
}
@@ -1676,7 +1850,7 @@ void setZoomedScreenScroll(int x, int y, bool shake) {
touchY = y >> 8;
} else */{
- if (gameScreenSwap) {
+ if ((gameScreenSwap) && (!touchPadStyle)) {
touchX = x >> 8;
touchY = y >> 8;
}
@@ -1696,7 +1870,7 @@ void setZoomedScreenScale(int x, int y) {
} else */{
- if (gameScreenSwap) {
+ if ((gameScreenSwap) && (!touchPadStyle)) {
touchScX = x;
touchScY = y;
}
@@ -1757,18 +1931,22 @@ void VBlankHandler(void) {
frameCount++;
- if ((cursorEnable) && (mouseCursorVisible))
- {
+ if ((cursorEnable) && (mouseCursorVisible)) {
if (!keyboardEnable) {
storedMouseX = penX;
storedMouseY = penY;
}
- setIconMain(3, storedMouseX - mouseHotspotX, storedMouseY - mouseHotspotY, 8, 0, true);
- }
- else
- {
+ if (gameScreenSwap) {
+ setIcon(3, storedMouseX - mouseHotspotX, storedMouseY - mouseHotspotY, 8, 0, true);
+ setIconMain(3, 0, 0, 0, 0, false);
+ } else {
+ setIconMain(3, storedMouseX - mouseHotspotX, storedMouseY - mouseHotspotY, 8, 0, true);
+ setIcon(3, 0, 0, 0, 0, false);
+ }
+ } else {
setIconMain(3, 0, 0, 0, 0, false);
+ setIcon(3, 0, 0, 0, 0, false);
}
@@ -1826,7 +2004,7 @@ void VBlankHandler(void) {
SUB_BG3_YDX = 0;
SUB_BG3_YDY = (int) (subScreenHeight / 192.0f * 256);*/
- static int ratio = ( 320 << 8) / SCUMM_GAME_WIDTH;
+ static int ratio = (320 << 8) / SCUMM_GAME_WIDTH;
bool zooming = false;
@@ -1851,8 +2029,12 @@ void VBlankHandler(void) {
subScreenWidth = 256 >> 1;
subScreenHeight = 192 >> 1;
} else {
- subScreenWidth = (((SCUMM_GAME_HEIGHT * 256) / 192) * subScreenScale) >> 8;
- subScreenHeight = SCUMM_GAME_HEIGHT * subScreenScale >> 8;
+// subScreenWidth = (((SCUMM_GAME_HEIGHT * 256) / 192) * subScreenScale) >> 8;
+// subScreenHeight = SCUMM_GAME_HEIGHT * subScreenScale >> 8;
+
+
+ subScreenWidth = (256 * subScreenScale) >> 8;
+ subScreenHeight = (192 * subScreenScale) >> 8;
if ( ((subScreenWidth) > 256 - 8) && ((subScreenWidth) < 256 + 8) ) {
subScreenWidth = 256;
@@ -2215,43 +2397,141 @@ void penUpdate() {
// if (getKeysHeld() & KEY_L) consolePrintf("%d, %d penX=%d, penY=%d tz=%d\n", IPC->touchXpx, IPC->touchYpx, penX, penY, IPC->touchZ1);
- if ((penDownFrames > 1)) { // Is this right? Dunno, but it works for me.
+ bool penDownThisFrame = (IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0);
+ bool firstFrame = penDownFrames == 2;
+ static bool moved = false;
- if ((penHeld)) {
- penHeld = true;
- penDown = false;
+ if ((tapScreenClicks) && (!getKeyboardEnable()) && (getIsDisplayMode8Bit())) {
- if ((IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0)) {
- penX = IPC->touchXpx + touchXOffset;
- penY = IPC->touchYpx + touchYOffset;
+ if ((tapTimeout >= 0)) {
+ tapTimeout++;
+
+ if (((tapTimeout > 15) || (tapCount == 2)) && (tapCount > 0)) {
+ tapComplete = tapCount;
+ tapCount = 0;
+// consolePrintf("Taps: %d\n", tapComplete);
}
+ }
- } else {
- penDown = true;
- penHeld = true;
- penDownSaved = true;
+
- //if ( (ABS(penX - IPC->touchXpx) < 10) && (ABS(penY - IPC->touchYpx) < 10) ) {
- if ((IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0)) {
- penX = IPC->touchXpx;
- penY = IPC->touchYpx;
+ if ((penHeld) && (!penDownThisFrame)) {
+ if ((touchPadStyle) || (moved) || (tapCount == 1)) {
+ if ((penDownFrames > 0) && (penDownFrames < 6) && ((tapTimeout == -1) || (tapTimeout > 2))) {
+ tapCount++;
+ tapTimeout = 0;
+// consolePrintf("Tap! %d\n", penDownFrames);
+ moved = false;
+ }
}
- //}
}
+ }
- } else {
- if (penHeld) {
- penReleased = true;
- penReleasedSaved = true;
+
+
+ if ((touchPadStyle) && (getIsDisplayMode8Bit())) {
+
+ if ((penDownFrames > 0)) {
+
+
+ if ((penHeld)) {
+
+ if (penDownThisFrame)
+ {
+ if (penDownFrames >= 2) {
+ int diffX = IPC->touchXpx - penDownX;
+ int diffY = IPC->touchYpx - penDownY;
+
+ int speed = ABS(diffX) + ABS(diffY);
+
+ if ((ABS(diffX) < 35) && (ABS(diffY) < 35))
+ {
+
+ if (speed >= 8)
+ {
+ diffX *= ((speed >> 3) * touchPadSensitivity) >> 3;
+ diffY *= ((speed >> 3) * touchPadSensitivity) >> 3;
+ }
+
+ penX += diffX;
+ penY += diffY;
+ if (penX > 255) penX = 255;
+ if (penX < 0) penX = 0;
+ if (penY > 191) penY = 191;
+ if (penY < 0) penY = 0;
+ }
+
+// consolePrintf("x: %d y: %d\n", IPC->touchYpx - penDownY, IPC->touchYpx - penDownY);
+ penDownX = IPC->touchXpx;
+ penDownY = IPC->touchYpx;
+
+ }
+ }
+ else
+ {
+ }
+
+
+ } else {
+ penDown = true;
+ penHeld = true;
+ penDownSaved = true;
+
+ // First frame, so save pen positions
+ if (penDownThisFrame) {
+ penDownX = IPC->touchXpx;
+ penDownY = IPC->touchYpx;
+ }
+ }
+
} else {
- penReleased = false;
+ if (penHeld) {
+ penReleased = true;
+ penReleasedSaved = true;
+ } else {
+ penReleased = false;
+ }
+
+ penDown = false;
+ penHeld = false;
}
+ } else {
+ if ((penDownFrames > 1)) { // Is this right? Dunno, but it works for me.
+
+ if ((penHeld)) {
+ penHeld = true;
+ penDown = false;
+ } else {
+ penDown = true;
+ penHeld = true;
+ penDownSaved = true;
+ }
+
+ if ((IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0)) {
+ penX = IPC->touchXpx + touchXOffset;
+ penY = IPC->touchYpx + touchYOffset;
+ moved = true;
+ }
+
- penDown = false;
- penHeld = false;
+
+ } else {
+ if (penHeld) {
+ penReleased = true;
+ penReleasedSaved = true;
+ } else {
+ penReleased = false;
+ }
+
+ penDown = false;
+ penHeld = false;
+ }
+
+
}
+
if ((IPC->touchZ1 > 0) || ((penDownFrames == 2)) ) {
penDownLastFrame = true;
penDownFrames++;
@@ -2259,7 +2539,6 @@ void penUpdate() {
penDownLastFrame = false;
penDownFrames = 0;
}
-
}
int leftHandedSwap(int keys) {
@@ -2346,8 +2625,7 @@ int getPenX() {
int x = ((penX * touchScX) >> 8) + touchX;
x = x < 0? 0: (x > gameWidth - 1? gameWidth - 1: x);
- if (snapToBorder)
- {
+ if (snapToBorder) {
if (x < 8) x = 0;
if (x > gameWidth - 8) x = gameWidth - 1;
}
@@ -2359,8 +2637,7 @@ int getPenY() {
int y = ((penY * touchScY) >> 8) + touchY;
y = y < 0? 0: (y > gameHeight - 1? gameHeight - 1: y);
- if (snapToBorder)
- {
+ if (snapToBorder) {
if (y < 8) y = 0;
if (y > gameHeight - 8) y = gameHeight - 1;
}
@@ -2377,6 +2654,8 @@ GLvector getPenPos() {
return v;
}
+#ifdef GBA_SRAM_SAVE
+
void formatSramOption() {
consolePrintf("The following files are present in save RAM:\n");
DSSaveFileManager::instance()->listFiles();
@@ -2398,7 +2677,7 @@ void formatSramOption() {
}
}
}
-
+#endif
void setIndyFightState(bool st) {
indyFightState = st;
@@ -2496,8 +2775,6 @@ struct cardTranslate {
char dldiId[5];
};
-#define NUM_CARD_READERS 7
-
cardTranslate cardReaderTable[] = {
{DEVICE_TYPE_M3SD, DEVICE_M3SD, "M3SD"},
{DEVICE_TYPE_M3CF, DEVICE_M3CF, "M3CF"},
@@ -2519,13 +2796,13 @@ void reboot() {
consolePrintf("DLDI Device ID: %s\n", id);
- for (int r = 0; r < NUM_CARD_READERS; r++) {
+ for (int r = 0; r < ARRAYSIZE(cardReaderTable); r++) {
if (!stricmp(id, cardReaderTable[r].dldiId)) {
deviceType = cardReaderTable[r].cartResetId;
}
}
} else {
- for (int r = 0; r < NUM_CARD_READERS; r++) {
+ for (int r = 0; r < ARRAYSIZE(cardReaderTable); r++) {
if (disc_getDeviceId() == cardReaderTable[r].svmId) {
deviceType = cardReaderTable[r].cartResetId;
}
@@ -2573,13 +2850,66 @@ void powerOff() {
/////////////////
-int main(void)
-{
+
+void dsExceptionHandler() {
+ consolePrintf("Blue screen of death");
+ setExceptionHandler(NULL);
+
+
+ u32 currentMode = getCPSR() & 0x1f;
+ u32 thumbState = ((*(u32*)0x027FFD90) & 0x20);
+
+ u32 codeAddress, exceptionAddress = 0;
+
+ int offset = 8;
+
+ if ( currentMode == 0x17 ) {
+ consolePrintf("\x1b[10Cdata abort!\n\n");
+ codeAddress = exceptionRegisters[15] - offset;
+ if ( (codeAddress > 0x02000000 && codeAddress < 0x02400000) ||
+ (codeAddress > (u32)__itcm_start && codeAddress < (u32)(__itcm_start + 32768)) )
+ exceptionAddress = getExceptionAddress( codeAddress, thumbState);
+ else
+ exceptionAddress = codeAddress;
+
+ } else {
+ if (thumbState)
+ offset = 2;
+ else
+ offset = 4;
+ consolePrintf("\x1b[5Cundefined instruction!\n\n");
+ codeAddress = exceptionRegisters[15] - offset;
+ exceptionAddress = codeAddress;
+ }
+
+ consolePrintf(" pc: %08X addr: %08X\n\n",codeAddress,exceptionAddress);
+
+ int i;
+ for ( i=0; i < 8; i++ ) {
+ consolePrintf( " %s: %08X %s: %08X\n",
+ registerNames[i], exceptionRegisters[i],
+ registerNames[i+8],exceptionRegisters[i+8]);
+ }
+// u32 *stack = (u32 *)exceptionRegisters[13];
+// for ( i=0; i<10; i++ ) {
+// consolePrintf( "\x1b[%d;2H%08X: %08X %08X", i + 14, (u32)&stack[i*2],stack[i*2], stack[(i*2)+1] );
+// }
+
+ memoryReport();
+
+ while(1);
+}
+
+
+
+
+int main(void) {
soundCallback = NULL;
initHardware();
+ setExceptionHandler(dsExceptionHandler);
#ifdef USE_DEBUGGER
for (int r = 0; r < 150; r++) {
@@ -2663,36 +2993,33 @@ int main(void)
consolePrintf("-------------------------------\n");
consolePrintf("ScummVM DS\n");
consolePrintf("Ported by Neil Millstone\n");
- consolePrintf("Version 0.11.1 beta2");
+ consolePrintf("Version 0.13.0 SVN ");
#if defined(DS_BUILD_A)
consolePrintf("build A\n");
consolePrintf("Lucasarts SCUMM games (SCUMM)\n");
- consolePrintf("-------------------------------\n");
#elif defined(DS_BUILD_B)
consolePrintf("build B\n");
consolePrintf("BASS, QUEEN\n");
- consolePrintf("-------------------------------\n");
#elif defined(DS_BUILD_C)
consolePrintf("build C\n");
consolePrintf("Simon/Elvira/Waxworks (AGOS)\n");
- consolePrintf("-------------------------------\n");
#elif defined(DS_BUILD_D)
consolePrintf("build D\n");
consolePrintf("AGI, CINE, GOB\n");
- consolePrintf("-------------------------------\n");
#elif defined(DS_BUILD_E)
consolePrintf("build E\n");
consolePrintf("Inherit the Earth (SAGA)\n");
- consolePrintf("-------------------------------\n");
#elif defined(DS_BUILD_F)
consolePrintf("build F\n");
consolePrintf("The Legend of Kyrandia (KYRA)\n");
- consolePrintf("-------------------------------\n");
#elif defined(DS_BUILD_G)
- consolePrintf("build F\n");
- consolePrintf("Lure of the Temptress (LURE)\n");
- consolePrintf("-------------------------------\n");
+ consolePrintf("build G\n");
+ consolePrintf("Lure of the Tempress (LURE)\n");
+#elif defined(DS_BUILD_H)
+ consolePrintf("build H\n");
+ consolePrintf("Nippon Safes (PARALLATION)\n");
#endif
+ consolePrintf("-------------------------------\n");
consolePrintf("L/R + D-pad/pen: Scroll view\n");
consolePrintf("D-pad left: Left mouse button\n");
consolePrintf("D-pad right: Right mouse button\n");
@@ -2808,9 +3135,11 @@ int main(void)
g_system = new OSystem_DS();
assert(g_system);
+#ifdef GBA_SRAM_SAVE
if ((keysHeld() & KEY_L) && (keysHeld() & KEY_R)) {
formatSramOption();
}
+#endif
IPC->adpcm.semaphore = false;
@@ -2831,6 +3160,8 @@ int main(void)
const char *argv[] = {"/scummvmds", "--config=scummvmf.ini"};
#elif defined(DS_BUILD_G)
const char *argv[] = {"/scummvmds", "--config=scummvmg.ini"};
+#elif defined(DS_BUILD_H)
+ const char *argv[] = {"/scummvmds", "--config=scummvmh.ini"};
#endif
while (1) {
diff --git a/backends/platform/ds/arm9/source/dsmain.h b/backends/platform/ds/arm9/source/dsmain.h
index 43258b5c5d..ab74554917 100644
--- a/backends/platform/ds/arm9/source/dsmain.h
+++ b/backends/platform/ds/arm9/source/dsmain.h
@@ -38,7 +38,8 @@ enum controlType {
CONT_SIMON,
CONT_FUTURE_WARS,
CONT_AGI,
- CONT_GOBLINS
+ CONT_GOBLINS,
+ CONT_NIPPON,
};
struct gameListType {
@@ -56,6 +57,7 @@ int getPenX();
int getPenY();
GLvector getPenPos();
void consumePenEvents();
+controlType getControlType();
// Pad reading
int getKeysHeld();
@@ -64,6 +66,8 @@ int getKeysDown();
int getKeysReleased();
void consumeKeys();
int leftHandedSwap(int keys);
+void setGameScreenSwap(bool enable);
+void setSensitivity(int sensitivity);
// Video
void displayMode8Bit(); // Switch to 8-bit mode5
@@ -81,6 +85,7 @@ u16* getScalerBuffer();
void setTalkPos(int x, int y);
void setTopScreenTarget(int x, int y);
void set200PercentFixedScale(bool on);
+void setTopScreenZoom(int percentage);
// Timers
void setTimerCallback(OSystem_DS::TimerProc proc, int interval); // Setup a callback function at a regular interval
@@ -88,7 +93,9 @@ int getMillis(); // Return the current runtime in milliseconds
void doTimerCallback(); // Call callback function if required
// Sound
-void doSoundCallback(); // Call function if sound buffers need more data
+void doSoundCallback();
+void startSound(int freq, int buffer); // Start sound hardware
+// Call function if sound buffers need more data
void playSound(const void* data, u32 length, bool loop, bool adpcm = false, int rate = 22050); // Start a sound
void stopSound(int channel);
int getSoundFrequency();
@@ -131,6 +138,8 @@ void setIndyFightState(bool st);
bool getIndyFightState();
bool isCpuScalerEnabled();
void setCpuScalerEnable(bool enable);
+void setTrackPadStyleEnable(bool enable);
+void setTapScreenClicksEnable(bool enable);
// Display
bool getIsDisplayMode8Bit();
diff --git a/backends/platform/ds/arm9/source/dsoptions.cpp b/backends/platform/ds/arm9/source/dsoptions.cpp
index edb9c70580..2dbc4b842b 100644
--- a/backends/platform/ds/arm9/source/dsoptions.cpp
+++ b/backends/platform/ds/arm9/source/dsoptions.cpp
@@ -25,6 +25,7 @@
#include "gui/dialog.h"
#include "gui/newgui.h"
#include "gui/ListWidget.h"
+#include "gui/TabWidget.h"
#include "osystem_ds.h"
#include "engines/scumm/scumm.h"
#include "touchkeyboard.h"
@@ -41,8 +42,67 @@ namespace Scumm {
namespace DS {
-DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(5, 0, 320 - 5, 230 - 20) {
- addButton(this, 10, 175, "Close", GUI::kCloseCmd, 'C');
+DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) {
+
+ addButton(this, 10, 170, "Close", GUI::kCloseCmd, 'C');
+ _tab = new GUI::TabWidget(this, 5, 5, 300, 230 - 20 - 40 - 10);
+
+ _tab->addTab("Controls");
+
+ _leftHandedCheckbox = new GUI::CheckboxWidget(_tab, 5, 5, 130, 20, "Left handed mode", 0, 'L');
+ _indyFightCheckbox = new GUI::CheckboxWidget(_tab, 5, 20, 140, 20, "Indy fight controls", 0, 'I');
+ _showCursorCheckbox = new GUI::CheckboxWidget(_tab, 150, 5, 130, 20, "Show mouse cursor", 0, 'T');
+ _snapToBorderCheckbox = new GUI::CheckboxWidget(_tab, 150, 20, 130, 20, "Snap to edges", 0, 'T');
+
+ new GUI::StaticTextWidget(_tab, 20, 35, 100, 15, "Touch X Offset", GUI::kTextAlignLeft);
+ _touchX = new GUI::SliderWidget(_tab, 130, 35, 130, 12, 1);
+ _touchX->setMinValue(-8);
+ _touchX->setMaxValue(+8);
+ _touchX->setValue(0);
+ _touchX->setFlags(GUI::WIDGET_CLEARBG);
+
+ new GUI::StaticTextWidget(_tab, 20, 50, 100, 15, "Touch Y Offset", GUI::kTextAlignLeft);
+ _touchY = new GUI::SliderWidget(_tab, 130, 50, 130, 12, 2);
+ _touchY->setMinValue(-8);
+ _touchY->setMaxValue(+8);
+ _touchY->setValue(0);
+ _touchY->setFlags(GUI::WIDGET_CLEARBG);
+
+ new GUI::StaticTextWidget(_tab, 130 + 65 - 10, 65, 20, 15, "0", GUI::kTextAlignCenter);
+ new GUI::StaticTextWidget(_tab, 130 + 130 - 10, 65, 20, 15, "8", GUI::kTextAlignCenter);
+ new GUI::StaticTextWidget(_tab, 130 - 20, 65, 20, 15, "-8", GUI::kTextAlignCenter);
+
+
+ _touchPadStyle = new GUI::CheckboxWidget(_tab, 5, 80, 270, 20, "Use laptop trackpad-style cursor control", 0x20000001, 'T');
+ _screenTaps = new GUI::CheckboxWidget(_tab, 5, 95, 285, 20, "Tap for left click, double tap right click", 0x20000002, 'T');
+
+ _sensitivityLabel = new GUI::StaticTextWidget(_tab, 20, 110, 110, 15, "Sensitivity", GUI::kTextAlignLeft);
+ _sensitivity = new GUI::SliderWidget(_tab, 130, 110, 130, 12, 1);
+ _sensitivity->setMinValue(4);
+ _sensitivity->setMaxValue(16);
+ _sensitivity->setValue(8);
+ _sensitivity->setFlags(GUI::WIDGET_CLEARBG);
+
+ _tab->addTab("Graphics");
+
+ new GUI::StaticTextWidget(_tab, 5, 70, 180, 15, "Initial top screen scale:", GUI::kTextAlignLeft);
+
+ _100PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 85, 230, 20, "100%", 0x30000001, 'T');
+ _150PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 100, 230, 20, "150%", 0x30000002, 'T');
+ _200PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 115, 230, 20, "200%", 0x30000003, 'T');
+
+ new GUI::StaticTextWidget(_tab, 5, 5, 180, 15, "Main screen scaling:", GUI::kTextAlignLeft);
+
+ _hardScaler = new GUI::CheckboxWidget(_tab, 5, 20, 270, 20, "Hardware scale (fast, but low quality)", 0x10000001, 'T');
+ _cpuScaler = new GUI::CheckboxWidget(_tab, 5, 35, 270, 20, "Software scale (good quality, but slower)", 0x10000002, 'S');
+ _unscaledCheckbox = new GUI::CheckboxWidget(_tab, 5, 50, 270, 20, "Unscaled (you must scroll left and right)", 0x10000003, 'S');
+
+ _tab->addTab("General");
+
+ _highQualityAudioCheckbox = new GUI::CheckboxWidget(_tab, 5, 5, 250, 20, "High quality audio (slower) (reboot)", 0, 'T');
+ _disablePowerOff = new GUI::CheckboxWidget(_tab, 5, 20, 200, 20, "Disable power off", 0, 'T');
+
+ _tab->setActiveTab(0);
_radioButtonMode = false;
@@ -52,46 +112,17 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(5, 0, 320 - 5, 230 - 20) {
}
#endif
- new GUI::StaticTextWidget(this, 90, 10, 130, 15, "ScummVM DS Options", GUI::kTextAlignCenter);
+// new GUI::StaticTextWidget(this, 90, 10, 130, 15, "ScummVM DS Options", GUI::kTextAlignCenter);
- _leftHandedCheckbox = new GUI::CheckboxWidget(this, 5, 70, 130, 20, "Left handed mode", 0, 'L');
- _indyFightCheckbox = new GUI::CheckboxWidget(this, 5, 40, 200, 20, "Indy fighting controls", 0, 'I');
- _twoHundredPercentCheckbox = new GUI::CheckboxWidget(this, 5, 55, 230, 20, "Zoomed screen at fixed 200% zoom", 0, 'T');
- _highQualityAudioCheckbox = new GUI::CheckboxWidget(this, 5, 25, 250, 20, "High quality audio (slower) (reboot)", 0, 'T');
- _disablePowerOff = new GUI::CheckboxWidget(this, 5, 85, 130, 20, "Disable power off", 0, 'T');
- _showCursorCheckbox = new GUI::CheckboxWidget(this, 5, 100, 130, 20, "Show mouse cursor", 0, 'T');
//#ifdef ALLOW_CPU_SCALER
// _cpuScaler = new GUI::CheckboxWidget(this, 160, 115, 90, 20, "CPU scaler", 0, 'T');
//#endif
- new GUI::StaticTextWidget(this, 180, 70, 130, 15, "Main screen:", GUI::kTextAlignLeft);
-
- _hardScaler = new GUI::CheckboxWidget(this, 140, 85, 170, 20, "Hardware scale (fast)", 0x10000001, 'T');
- _cpuScaler = new GUI::CheckboxWidget(this, 140, 100, 170, 20, "Software scale (quality)", 0x10000002, 'S');
- _unscaledCheckbox = new GUI::CheckboxWidget(this, 140, 115, 170, 20, "Unscaled", 0x10000003, 'S');
- _snapToBorderCheckbox = new GUI::CheckboxWidget(this, 5, 115, 120, 20, "Snap to border", 0, 'T');
- new GUI::StaticTextWidget(this, 20, 145, 110, 15, "Touch X Offset", GUI::kTextAlignLeft);
- _touchX = new GUI::SliderWidget(this, 130, 145, 130, 12, 1);
- _touchX->setMinValue(-8);
- _touchX->setMaxValue(+8);
- _touchX->setValue(0);
- _touchX->setFlags(GUI::WIDGET_CLEARBG);
-
- new GUI::StaticTextWidget(this, 20, 160, 110, 15, "Touch Y Offset", GUI::kTextAlignLeft);
- _touchY = new GUI::SliderWidget(this, 130, 160, 130, 12, 2);
- _touchY->setMinValue(-8);
- _touchY->setMaxValue(+8);
- _touchY->setValue(0);
- _touchY->setFlags(GUI::WIDGET_CLEARBG);
-
- new GUI::StaticTextWidget(this, 130 + 65 - 10, 175, 20, 15, "0", GUI::kTextAlignCenter);
- new GUI::StaticTextWidget(this, 130 + 130 - 10, 175, 20, 15, "8", GUI::kTextAlignCenter);
- new GUI::StaticTextWidget(this, 130 - 10, 175, 20, 15, "-8", GUI::kTextAlignCenter);
#ifdef DS_SCUMM_BUILD
_delDialog = new Scumm::SaveLoadChooser("Delete game:", "Delete", false, Scumm::g_scumm);
@@ -125,10 +156,36 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(5, 0, 320 - 5, 230 - 20) {
_unscaledCheckbox->setState(false);
}
- if (ConfMan.hasKey("twohundredpercent", "ds")) {
- _twoHundredPercentCheckbox->setState(ConfMan.getBool("twohundredpercent", "ds"));
+
+ if (ConfMan.hasKey("topscreenzoom", "ds")) {
+
+ _100PercentCheckbox->setState(false);
+ _150PercentCheckbox->setState(false);
+ _200PercentCheckbox->setState(false);
+
+ switch (ConfMan.getInt("topscreenzoom", "ds"))
+ {
+ case 100: {
+ _100PercentCheckbox->setState(true);
+ break;
+ }
+
+ case 150: {
+ _150PercentCheckbox->setState(true);
+ break;
+ }
+
+ case 200: {
+ _200PercentCheckbox->setState(true);
+ break;
+ }
+ }
+
+ } else if (ConfMan.hasKey("twohundredpercent", "ds")) {
+ _200PercentCheckbox->setState(ConfMan.getBool("twohundredpercent", "ds"));
} else {
- _twoHundredPercentCheckbox->setState(false);
+ // No setting
+ _150PercentCheckbox->setState(true);
}
if (ConfMan.hasKey("22khzaudio", "ds")) {
@@ -165,6 +222,29 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(5, 0, 320 - 5, 230 - 20) {
_touchY->setValue(0);
}
+ if (ConfMan.hasKey("sensitivity", "ds")) {
+ _sensitivity->setValue(ConfMan.getInt("sensitivity", "ds"));
+ } else {
+ _sensitivity->setValue(8);
+ }
+
+ if (ConfMan.hasKey("touchpad", "ds")) {
+ _touchPadStyle->setState(ConfMan.getBool("touchpad", "ds"));
+ } else {
+ _touchPadStyle->setState(0);
+ }
+
+ if (ConfMan.hasKey("screentaps", "ds")) {
+ _screenTaps->setState(ConfMan.getBool("screentaps", "ds"));
+ } else {
+ _screenTaps->setState(0);
+ }
+
+ _screenTaps->setEnabled(!_touchPadStyle->getState());
+ _sensitivity->setEnabled(_touchPadStyle->getState());
+ _sensitivityLabel->setEnabled(_touchPadStyle->getState());
+ _sensitivityLabel->draw();
+
if (!_cpuScaler->getState() && !_unscaledCheckbox->getState()) {
_hardScaler->setState(true);
}
@@ -180,7 +260,7 @@ DSOptionsDialog::~DSOptionsDialog() {
void DSOptionsDialog::updateConfigManager() {
ConfMan.setBool("lefthanded", _leftHandedCheckbox->getState(), "ds");
ConfMan.setBool("unscaled", _unscaledCheckbox->getState(), "ds");
- ConfMan.setBool("twohundredpercent", _twoHundredPercentCheckbox->getState(), "ds");
+// ConfMan.setBool("twohundredpercent", _twoHundredPercentCheckbox->getState(), "ds");
ConfMan.setBool("22khzaudio", _highQualityAudioCheckbox->getState(), "ds");
ConfMan.setBool("disablepoweroff", _disablePowerOff->getState(), "ds");
#ifdef ALLOW_CPU_SCALER
@@ -190,6 +270,24 @@ void DSOptionsDialog::updateConfigManager() {
ConfMan.setInt("yoffset", _touchY->getValue(), "ds");
ConfMan.setBool("showcursor", _showCursorCheckbox->getState(), "ds");
ConfMan.setBool("snaptoborder", _snapToBorderCheckbox->getState(), "ds");
+ ConfMan.setBool("touchpad", _touchPadStyle->getState(), "ds");
+ ConfMan.setBool("screentaps", _screenTaps->getState(), "ds");
+ ConfMan.setInt("sensitivity", _sensitivity->getValue(), "ds");
+
+ u32 zoomLevel = 150;
+
+ if (_100PercentCheckbox->getState()) {
+ zoomLevel = 100;
+ } else if (_150PercentCheckbox->getState()) {
+ zoomLevel = 150;
+ } else if (_200PercentCheckbox->getState()) {
+ zoomLevel = 200;
+ }
+
+ consolePrintf("Saved zoom: %d\n", zoomLevel);
+
+ ConfMan.setInt("topscreenzoom", zoomLevel, "ds");
+
DS::setOptions();
}
@@ -227,6 +325,70 @@ void DSOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint
}
+ if ((!guard) && (_radioButtonMode))
+ {
+ guard = true;
+
+ if ((sender == _touchPadStyle) && (cmd == 0x20000001)) {
+
+ if (_touchPadStyle->getState()) {
+ // Swap screens when turning on trackpad style, it feels
+ // much more natural!
+ DS::setGameScreenSwap(true);
+
+ _screenTaps->setState(true);
+ _screenTaps->setEnabled(false);
+ _screenTaps->draw();
+ _sensitivity->setEnabled(true);
+ _sensitivityLabel->setEnabled(true);
+ _sensitivityLabel->draw();
+ _sensitivity->draw();
+ } else {
+ DS::setGameScreenSwap(false);
+
+ _screenTaps->setEnabled(true);
+ _screenTaps->setState(false);
+ _screenTaps->draw();
+ _sensitivity->setEnabled(false);
+ _sensitivityLabel->setEnabled(false);
+ _sensitivityLabel->draw();
+ _sensitivity->draw();
+ }
+ }
+
+ guard = false;
+ }
+
+ if ((!guard) && (_radioButtonMode)) {
+
+ guard = true;
+
+ if (cmd == 0x30000001) {
+ _100PercentCheckbox->setState(true);
+ _150PercentCheckbox->setState(false);
+ _200PercentCheckbox->setState(false);
+ DS::setTopScreenZoom(100);
+ }
+
+ if (cmd == 0x30000002) {
+ _100PercentCheckbox->setState(false);
+ _150PercentCheckbox->setState(true);
+ _200PercentCheckbox->setState(false);
+ DS::setTopScreenZoom(150);
+ }
+
+ if (cmd == 0x30000003) {
+ _100PercentCheckbox->setState(false);
+ _150PercentCheckbox->setState(false);
+ _200PercentCheckbox->setState(true);
+ DS::setTopScreenZoom(200);
+ }
+
+ guard = false;
+
+ }
+
+
if (cmd == GUI::kCloseCmd) {
updateConfigManager();
close();
@@ -297,6 +459,8 @@ void showOptionsDialog() {
}
void setOptions() {
+ static bool firstLoad = true;
+
ConfMan.addGameDomain("ds");
if (ConfMan.hasKey("lefthanded", "ds")) {
@@ -327,10 +491,16 @@ void setOptions() {
DS::setUnscaledMode(false);
}
- if (ConfMan.hasKey("twohundredpercent", "ds")) {
- DS::set200PercentFixedScale(ConfMan.getBool("twohundredpercent", "ds"));
- } else {
- DS::set200PercentFixedScale(false);
+ if (firstLoad) {
+ if (ConfMan.hasKey("topscreenzoom", "ds")) {
+ DS::setTopScreenZoom(ConfMan.getInt("topscreenzoom", "ds"));
+ } else {
+ if (ConfMan.hasKey("twohundredpercent", "ds")) {
+ DS::setTopScreenZoom(200);
+ } else {
+ DS::setTopScreenZoom(150);
+ }
+ }
}
if (ConfMan.hasKey("xoffset", "ds")) {
@@ -345,6 +515,12 @@ void setOptions() {
DS::setTouchXOffset(0);
}
+ if (ConfMan.hasKey("sensitivity", "ds")) {
+ DS::setSensitivity(ConfMan.getInt("sensitivity", "ds"));
+ } else {
+ DS::setSensitivity(8);
+ }
+
#ifdef ALLOW_CPU_SCALER
if (ConfMan.hasKey("cpu_scaler", "ds")) {
DS::setCpuScalerEnable(ConfMan.getBool("cpu_scaler", "ds"));
@@ -353,6 +529,33 @@ void setOptions() {
}
#endif
+ if (ConfMan.hasKey("screentaps", "ds")) {
+ DS::setTapScreenClicksEnable(ConfMan.getBool("screentaps", "ds"));
+ } else {
+ DS::setTapScreenClicksEnable(false);
+ }
+
+ if (ConfMan.hasKey("touchpad", "ds")) {
+ bool enable = ConfMan.getBool("touchpad", "ds");
+
+ DS::setTrackPadStyleEnable(enable);
+
+ if ((enable) and (firstLoad)) {
+ // If we've just booted up, want to swap screens when trackpad mode is in use
+ // but not every time we enter the options dialog.
+ DS::setGameScreenSwap(true);
+ }
+
+ if (enable) {
+ DS::setTapScreenClicksEnable(true);
+ }
+
+ } else {
+ DS::setTrackPadStyleEnable(false);
+ }
+
+
+ firstLoad = false;
}
}
diff --git a/backends/platform/ds/arm9/source/dsoptions.h b/backends/platform/ds/arm9/source/dsoptions.h
index 9cfa785ca8..e3ab2f55e0 100644
--- a/backends/platform/ds/arm9/source/dsoptions.h
+++ b/backends/platform/ds/arm9/source/dsoptions.h
@@ -30,6 +30,7 @@
#include "gui/object.h"
#include "gui/widget.h"
#include "gui/dialog.h"
+#include "gui/TabWidget.h"
#include "scumm/dialogs.h"
namespace DS {
@@ -45,11 +46,18 @@ protected:
void togglePause();
void updateConfigManager();
+ GUI::TabWidget* _tab;
+
+ GUI::StaticTextWidget* _sensitivityLabel;
+
GUI::SliderWidget* _touchX;
GUI::SliderWidget* _touchY;
+ GUI::SliderWidget* _sensitivity;
GUI::CheckboxWidget* _leftHandedCheckbox;
GUI::CheckboxWidget* _unscaledCheckbox;
- GUI::CheckboxWidget* _twoHundredPercentCheckbox;
+ GUI::CheckboxWidget* _100PercentCheckbox;
+ GUI::CheckboxWidget* _150PercentCheckbox;
+ GUI::CheckboxWidget* _200PercentCheckbox;
GUI::CheckboxWidget* _indyFightCheckbox;
GUI::CheckboxWidget* _highQualityAudioCheckbox;
GUI::CheckboxWidget* _disablePowerOff;
@@ -59,6 +67,9 @@ protected:
GUI::CheckboxWidget* _hardScaler;
GUI::CheckboxWidget* _cpuScaler;
+ GUI::CheckboxWidget* _touchPadStyle;
+ GUI::CheckboxWidget* _screenTaps;
+
#ifdef DS_SCUMM_BUILD
Scumm::SaveLoadChooser* _delDialog;
#endif
diff --git a/backends/platform/ds/arm9/source/gbampsave.cpp b/backends/platform/ds/arm9/source/gbampsave.cpp
index 9c8af81a6e..a53ab9739d 100644
--- a/backends/platform/ds/arm9/source/gbampsave.cpp
+++ b/backends/platform/ds/arm9/source/gbampsave.cpp
@@ -54,8 +54,8 @@ bool GBAMPSaveFile::eos() const {
return DS::std_feof(handle);
}
-void GBAMPSaveFile::skip(uint32 bytes) {
- DS::std_fseek(handle, bytes, SEEK_CUR);
+bool GBAMPSaveFile::skip(uint32 bytes) {
+ return DS::std_fseek(handle, bytes, SEEK_CUR) == 0;
}
void GBAMPSaveFile::flushSaveBuffer() {
@@ -67,11 +67,11 @@ void GBAMPSaveFile::flushSaveBuffer() {
}
}
-uint32 GBAMPSaveFile::pos() const {
+int32 GBAMPSaveFile::pos() const {
return DS::std_ftell(handle);
}
-uint32 GBAMPSaveFile::size() const {
+int32 GBAMPSaveFile::size() const {
int position = pos();
DS::std_fseek(handle, 0, SEEK_END);
int size = DS::std_ftell(handle);
@@ -79,8 +79,8 @@ uint32 GBAMPSaveFile::size() const {
return size;
}
-void GBAMPSaveFile::seek(int32 pos, int whence) {
- DS::std_fseek(handle, pos, whence);
+bool GBAMPSaveFile::seek(int32 pos, int whence) {
+ return DS::std_fseek(handle, pos, whence) == 0;
}
@@ -155,11 +155,13 @@ GBAMPSaveFile* GBAMPSaveFileManager::openSavefile(char const* name, bool saveOrL
sprintf(fileSpec, "%s/%s", getSavePath(), name);
}
-// consolePrintf(fileSpec);
+// consolePrintf("Opening the file: %s\n", fileSpec);
GBAMPSaveFile* sf = new GBAMPSaveFile(fileSpec, saveOrLoad);
if (sf->isOpen()) {
+// consolePrintf("Ok");
return sf;
} else {
+// consolePrintf("Fail");
delete sf;
return NULL;
}
@@ -192,8 +194,29 @@ Common::StringList GBAMPSaveFileManager::listSavefiles(const char *pattern) {
enum { TYPE_NO_MORE = 0, TYPE_FILE = 1, TYPE_DIR = 2 };
char name[256];
- DS::std_cwd((char*)getSavePath()); //TODO : Check this suspicious const-cast
-// consolePrintf("Save path: '%s', pattern: '%s'\n", getSavePath(),pattern);
+ {
+ char dir[128];
+ strcpy(dir, getSavePath());
+ char *realName = dir;
+
+ if ((strlen(dir) >= 4) && (dir[0] == 'm') && (dir[1] == 'p') && (dir[2] == ':') && (dir[3] == '/')) {
+ realName += 4;
+ }
+
+ // consolePrintf("Real cwd:%d\n", realName);
+
+ char* p = realName;
+ while (*p) {
+ if (*p == '\\') *p = '/';
+ p++;
+ }
+
+ // consolePrintf("Real cwd:%d\n", realName);
+ FAT_chdir(realName);
+
+ }
+
+// consolePrintf("Save path: '%s', pattern: '%s'\n", getSavePath(), pattern);
int fileType = FAT_FindFirstFileLFN(name);
@@ -206,7 +229,7 @@ Common::StringList GBAMPSaveFileManager::listSavefiles(const char *pattern) {
FAT_GetLongFilename(name);
- for (int r = 0; r < strlen(name); r++) {
+ for (int r = 0; name[r] != 0; r++) {
name[r] = tolower(name[r]);
}
diff --git a/backends/platform/ds/arm9/source/gbampsave.h b/backends/platform/ds/arm9/source/gbampsave.h
index d0cbc68bfd..6ddc4fd964 100644
--- a/backends/platform/ds/arm9/source/gbampsave.h
+++ b/backends/platform/ds/arm9/source/gbampsave.h
@@ -43,11 +43,11 @@ public:
virtual uint32 write(const void *buf, uint32 size);
virtual bool eos() const;
- virtual void skip(uint32 bytes);
+ virtual bool skip(uint32 bytes);
- virtual uint32 pos() const;
- virtual uint32 size() const;
- virtual void seek(int32 pos, int whence);
+ virtual int32 pos() const;
+ virtual int32 size() const;
+ virtual bool seek(int32 pos, int whence);
void flushSaveBuffer();
diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp
index 79b0c5390b..5ddcb50b15 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.cpp
+++ b/backends/platform/ds/arm9/source/osystem_ds.cpp
@@ -41,7 +41,8 @@
OSystem_DS* OSystem_DS::_instance = NULL;
OSystem_DS::OSystem_DS()
- : eventNum(0), lastPenFrame(0), queuePos(0), _mixer(NULL), _timer(NULL), _frameBufferExists(false)
+ : eventNum(0), lastPenFrame(0), queuePos(0), _mixer(NULL), _timer(NULL), _frameBufferExists(false),
+ _disableCursorPalette(true), _graphicsEnable(true)
{
// eventNum = 0;
// lastPenFrame = 0;
@@ -71,7 +72,13 @@ void OSystem_DS::initBackend() {
_timer = new DSTimerManager();
DS::setTimerCallback(&OSystem_DS::timerHandler, 10);
- _mixer->setOutputRate(11025 /*DS::getSoundFrequency()*/);
+ if (ConfMan.hasKey("22khzaudio", "ds") && ConfMan.getBool("22khzaudio", "ds")) {
+ DS::startSound(22050, 8192);
+ } else {
+ DS::startSound(11025, 4096);
+ }
+
+ _mixer->setOutputRate(DS::getSoundFrequency());
_mixer->setReady(true);
OSystem::initBackend();
@@ -79,7 +86,7 @@ void OSystem_DS::initBackend() {
bool OSystem_DS::hasFeature(Feature f) {
// consolePrintf("hasfeature\n");
- return (f == kFeatureVirtualKeyboard);
+ return (f == kFeatureVirtualKeyboard) || (f == kFeatureCursorHasPalette);
}
void OSystem_DS::setFeatureState(Feature f, bool enable) {
@@ -107,7 +114,7 @@ bool OSystem_DS::setGraphicsMode(int mode) {
}
bool OSystem_DS::setGraphicsMode(const char *name) {
-// consolePrintf("Set gfx mode %s\n", name);
+ consolePrintf("Set gfx mode %s\n", name);
return true;
}
@@ -116,8 +123,15 @@ int OSystem_DS::getGraphicsMode() const {
}
void OSystem_DS::initSize(uint width, uint height) {
-// consolePrintf("Set gfx mode %d x %d\n", width, height);
- DS::setGameSize(width, height);
+ // For Lost in Time, the title screen is displayed in 640x400.
+ // In order to support this game, the screen mode is set, but
+ // all draw calls are ignored until the game switches to 320x200.
+ if ((width == 640) && (height == 400)) {
+ _graphicsEnable = false;
+ } else {
+ _graphicsEnable = true;
+ DS::setGameSize(width, height);
+ }
}
int16 OSystem_DS::getHeight() {
@@ -129,9 +143,8 @@ int16 OSystem_DS::getWidth() {
}
void OSystem_DS::setPalette(const byte *colors, uint start, uint num) {
-// consolePrintf("Set palette %d, %d colours\n", start, num);
-//return;
- if (!DS::getIsDisplayMode8Bit()) return;
+// consolePrintf("Setpal %d, %d\n", start, num);
+
for (unsigned int r = start; r < start + num; r++) {
int red = *colors;
int green = *(colors + 1);
@@ -141,17 +154,44 @@ void OSystem_DS::setPalette(const byte *colors, uint start, uint num) {
green >>= 3;
blue >>= 3;
- if (r != 255)
+// if (r != 255)
{
- BG_PALETTE[r] = red | (green << 5) | (blue << 10);
- if (!DS::getKeyboardEnable()) {
- BG_PALETTE_SUB[r] = red | (green << 5) | (blue << 10);
+ u16 paletteValue = red | (green << 5) | (blue << 10);
+
+ if (DS::getIsDisplayMode8Bit()) {
+ BG_PALETTE[r] = paletteValue;
+ if (!DS::getKeyboardEnable()) {
+ BG_PALETTE_SUB[r] = paletteValue;
+ }
}
+
+ _palette[r] = paletteValue;
}
-// if (num == 16) consolePrintf("pal:%d r:%d g:%d b:%d\n", r, red, green, blue);
+ // if (num == 255) consolePrintf("pal:%d r:%d g:%d b:%d\n", r, red, green, blue);
+
+ colors += 4;
+ }
+}
+
+void OSystem_DS::setCursorPalette(const byte *colors, uint start, uint num) {
+
+// consolePrintf("Cursor palette set: start: %d, cols: %d\n", start, num);
+ for (unsigned int r = start; r < start + num; r++) {
+ int red = *colors;
+ int green = *(colors + 1);
+ int blue = *(colors + 2);
+
+ red >>= 3;
+ green >>= 3;
+ blue >>= 3;
+ u16 paletteValue = red | (green << 5) | (blue << 10);
+ _cursorPalette[r] = paletteValue;
+
colors += 4;
}
+
+ _disableCursorPalette = false;
}
bool OSystem_DS::grabRawScreen(Graphics::Surface* surf) {
@@ -184,9 +224,11 @@ void OSystem_DS::grabPalette(unsigned char *colors, uint start, uint num) {
}
+#define MISALIGNED16(ptr) (((u32) (ptr) & 1) != 0)
+
void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
-// consolePrintf("Copy rect %d, %d %d, %d ", x, y, w, h);
-
+ //consolePrintf("Copy rect %d, %d %d, %d ", x, y, w, h);
+ if (!_graphicsEnable) return;
if (w <= 1) return;
if (h < 0) return;
if (!DS::getIsDisplayMode8Bit()) return;
@@ -195,6 +237,9 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
s32 stride;
u16* bgSub = (u16 *) BG_GFX_SUB;
+ // The DS video RAM doesn't support 8-bit writes because Nintendo wanted
+ // to save a few pennies/euro cents on the hardware.
+
if (_frameBufferExists) {
bg = (u16 *) _framebuffer.pixels;
stride = _framebuffer.pitch;
@@ -203,46 +248,117 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
stride = DS::get8BitBackBufferStride();
}
- u16* src = (u16 *) buf;
-
- if (DS::getKeyboardEnable()) {
-
+ if (((pitch & 1) != 0) || ((w & 1) != 0) || (((int) (buf) & 1) != 0)) {
+
+ // Something is misaligned, so we have to use the slow but sure method
+
+ int by = 0;
+
for (int dy = y; dy < y + h; dy++) {
- u16* dest = bg + (dy * (stride >> 1)) + (x >> 1);
-
- DC_FlushRange(src, w << 1);
- DC_FlushRange(dest, w << 1);
- dmaCopyHalfWords(3, src, dest, w);
-
- src += pitch >> 1;
+ u8* dest = ((u8 *) (bg)) + (dy * stride) + x;
+ u8* destSub = ((u8 *) (bgSub)) + (dy * 512) + x;
+ u8* src = (u8 *) buf + (pitch * by);
+
+ u32 dx;
+
+ u32 pixelsLeft = w;
+
+ if (MISALIGNED16(dest)) {
+ // Read modify write
+
+ dest--;
+ u16 mix = *((u16 *) dest);
+
+ mix = (mix & 0x00FF) | (*src++ << 8);
+
+ *dest = mix;
+ *destSub = mix;
+
+ dest += 2;
+ destSub += 2;
+ pixelsLeft--;
+ }
+
+ // We can now assume dest is aligned
+ u16* dest16 = (u16 *) dest;
+ u16* destSub16 = (u16 *) destSub;
+
+ for (dx = 0; dx < pixelsLeft; dx+=2) {
+ u16 mix;
+
+ mix = *src + (*(src + 1) << 8);
+ *dest16++ = mix;
+ *destSub16++ = mix;
+ src += 2;
+ }
+
+ pixelsLeft -= dx;
+
+ // At the end we may have one pixel left over
+
+ if (pixelsLeft != 0) {
+ u16 mix = *dest16;
+
+ mix = (mix & 0x00FF) | ((*src++) << 8);
+
+ *dest16 = mix;
+ *destSub16 = mix;
+ }
+
+ by++;
+
}
-
+
+// consolePrintf("Slow method used!\n");
+
+
} else {
- for (int dy = y; dy < y + h; dy++) {
- u16* dest1 = bg + (dy * (stride >> 1)) + (x >> 1);
- u16* dest2 = bgSub + (dy << 8) + (x >> 1);
+
+ // Stuff is aligned to 16-bit boundaries, so it's safe to do DMA.
+
+ u16* src = (u16 *) buf;
+
+ if (DS::getKeyboardEnable()) {
+
+ for (int dy = y; dy < y + h; dy++) {
+ u16* dest = bg + (dy * (stride >> 1)) + (x >> 1);
- DC_FlushRange(src, w << 1);
- DC_FlushRange(dest1, w << 1);
- DC_FlushRange(dest2, w << 1);
-
- dmaCopyHalfWords(3, src, dest1, w);
- dmaCopyHalfWords(3, src, dest2, w);
-
- src += pitch >> 1;
- }
- }
+ DC_FlushRange(src, w << 1);
+ DC_FlushRange(dest, w << 1);
+ dmaCopyHalfWords(3, src, dest, w);
-// consolePrintf("Done\n");
+ while (dmaBusy(3));
+
+ src += pitch >> 1;
+ }
+
+ } else {
+ for (int dy = y; dy < y + h; dy++) {
+ u16* dest1 = bg + (dy * (stride >> 1)) + (x >> 1);
+ u16* dest2 = bgSub + (dy << 8) + (x >> 1);
+
+ DC_FlushRange(src, w << 1);
+ DC_FlushRange(dest1, w << 1);
+ DC_FlushRange(dest2, w << 1);
+
+ dmaCopyHalfWords(3, src, dest1, w);
-
+ if ((!_frameBufferExists) || (buf == _framebuffer.pixels)) {
+ dmaCopyHalfWords(2, src, dest2, w);
+ }
+ while (dmaBusy(2) || dmaBusy(3));
+
+ src += pitch >> 1;
+ }
+ }
+ }
+// consolePrintf("Done\n");
}
void OSystem_DS::updateScreen() {
- if ((_frameBufferExists) && (DS::getIsDisplayMode8Bit()))
- {
+ if ((_frameBufferExists) && (DS::getIsDisplayMode8Bit())) {
_frameBufferExists = false;
// Copy temp framebuffer back to screen
@@ -253,6 +369,12 @@ void OSystem_DS::updateScreen() {
DS::doSoundCallback();
// DS::doTimerCallback();
DS::addEventsToQueue();
+
+ // Force back buffer usage for Nippon Safes, as it doesn't double buffer it's output
+ if (DS::getControlType() == DS::CONT_NIPPON) {
+ OSystem_DS::instance()->lockScreen();
+ OSystem_DS::instance()->unlockScreen();
+ }
}
void OSystem_DS::setShakePos(int shakeOffset) {
@@ -334,7 +456,21 @@ void OSystem_DS::warpMouse(int x, int y) {
}
void OSystem_DS::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor, int targetCursorScale) {
- DS::setCursorIcon(buf, w, h, keycolor, hotspotX, hotspotY);
+ if ((w > 0) && (w < 64) && (h > 0) && (h < 64))
+ {
+ memcpy(_cursorImage, buf, w * h);
+ _cursorW = w;
+ _cursorH = h;
+ _cursorHotX = hotspotX;
+ _cursorHotY = hotspotY;
+ _cursorKey = keycolor;
+ _cursorScale = targetCursorScale;
+ refreshCursor();
+ }
+}
+
+void OSystem_DS::refreshCursor() {
+ DS::setCursorIcon(_cursorImage, _cursorW, _cursorH, _cursorKey, _cursorHotX, _cursorHotY);
}
void OSystem_DS::addEvent(Common::Event& e) {
@@ -489,7 +625,11 @@ Common::SaveFileManager* OSystem_DS::getSavefileManager() {
if (DS::isGBAMPAvailable() && (!forceSram)) {
return &mpSaveManager;
} else {
+#ifdef GBA_SRAM_SAVE
return &saveManager;
+#else
+ return NULL;
+#endif
}
}
diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h
index 8c8d661ad8..16c8f41491 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.h
+++ b/backends/platform/ds/arm9/source/osystem_ds.h
@@ -52,17 +52,32 @@ protected:
Common::Event eventQueue[96];
int queuePos;
+#ifdef GBA_SRAM_SAVE
DSSaveFileManager saveManager;
+#endif
GBAMPSaveFileManager mpSaveManager;
DSAudioMixer* _mixer;
DSTimerManager* _timer;
Graphics::Surface _framebuffer;
bool _frameBufferExists;
-
+ bool _graphicsEnable;
static OSystem_DS* _instance;
+
+ u16 _palette[256];
+ u16 _cursorPalette[256];
+
+ u8 _cursorImage[64 * 64];
+ uint _cursorW;
+ uint _cursorH;
+ int _cursorHotX;
+ int _cursorHotY;
+ byte _cursorKey;
+ int _cursorScale;
+
Graphics::Surface* createTempFrameBuffer();
+ bool _disableCursorPalette;
public:
typedef void (*SoundProc)(byte *buf, int len);
@@ -159,7 +174,16 @@ public:
virtual void clearAutoComplete();
virtual void setCharactersEntered(int count);
+ u16 getDSPaletteEntry(u32 entry) { return _palette[entry]; }
+ u16 getDSCursorPaletteEntry(u32 entry) { return !_disableCursorPalette? _cursorPalette[entry]: _palette[entry]; }
+
+ virtual void setCursorPalette(const byte *colors, uint start, uint num);
+
+ virtual void disableCursorPalette(bool dis) { _disableCursorPalette = dis; refreshCursor(); }
+
FilesystemFactory *getFilesystemFactory();
+
+ void refreshCursor();
};
static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
diff --git a/backends/platform/ds/arm9/source/portdefs.h b/backends/platform/ds/arm9/source/portdefs.h
index de7a5795f5..16f3d8cc9b 100644
--- a/backends/platform/ds/arm9/source/portdefs.h
+++ b/backends/platform/ds/arm9/source/portdefs.h
@@ -81,7 +81,10 @@ void consolePrintf(const char* s, ...);
#define ITCM_DATA __attribute__((section(".itcm")))
-
+// Since I can't change the engine at the moment (post lockdown) this define can go here.
+// This define changes the mouse-relative motion which doesn't make sense on a touch screen to
+// a more conventional form of input where the menus can be clicked on.
+#define LURE_CLICKABLE_MENUS
//#include "common/array.h"
//#include "common/str.h"
diff --git a/backends/platform/ds/arm9/source/ramsave.cpp b/backends/platform/ds/arm9/source/ramsave.cpp
index be355ce76f..a9f4e3d2fc 100644
--- a/backends/platform/ds/arm9/source/ramsave.cpp
+++ b/backends/platform/ds/arm9/source/ramsave.cpp
@@ -19,7 +19,9 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
- // Save in order 1,2,3,4,larger 2,5
+#ifdef GBA_SRAM_SAVE
+
+
#include "ramsave.h"
#include "nds.h"
#include "compressor/lz.h"
@@ -64,6 +66,7 @@ DSSaveFile::DSSaveFile(SCUMMSave* s, bool compressed, u8* data) {
}
isTempFile = false;
+ eosReached = false;
}
DSSaveFile::~DSSaveFile() {
@@ -167,11 +170,13 @@ int DSSaveFile::saveToSaveRAM(vu8* address) {
void DSSaveFile::reset() {
ptr = 0;
+ eosReached = false;
}
uint32 DSSaveFile::read(void *buf, uint32 size) {
if (ptr + size > save.size) {
size = save.size - ptr;
+ eosReached = true;
if (size < 0) size = 0;
}
memcpy(buf, saveData + ptr, size);
@@ -181,15 +186,15 @@ uint32 DSSaveFile::read(void *buf, uint32 size) {
return size;
}
-uint32 DSSaveFile::pos() const {
+int32 DSSaveFile::pos() const {
return ptr;
}
-uint32 DSSaveFile::size() const {
+int32 DSSaveFile::size() const {
return save.size;
}
-void DSSaveFile::seek(int32 pos, int whence) {
+bool DSSaveFile::seek(int32 pos, int whence) {
switch (whence) {
case SEEK_SET: {
ptr = pos;
@@ -204,15 +209,22 @@ void DSSaveFile::seek(int32 pos, int whence) {
break;
}
}
+ eosReached = false;
+ return true;
}
bool DSSaveFile::eos() const {
- return ptr >= (int) save.size;
+ return eosReached;
}
-void DSSaveFile::skip(uint32 bytes) {
+void DSSaveFile::clearErr() {
+ eosReached = false;
+}
+
+bool DSSaveFile::skip(uint32 bytes) {
ptr = ptr + bytes;
if (ptr > (int) save.size) ptr = save.size;
+ return true;
}
uint32 DSSaveFile::write(const void *buf, uint32 size) {
@@ -227,7 +239,7 @@ uint32 DSSaveFile::write(const void *buf, uint32 size) {
return size;
}
-bool DSSaveFile::matches(char* prefix, int num) {
+bool DSSaveFile::matches(const char *prefix, int num) {
char str[16];
if (isValid()) {
sprintf(str, "%s%02d", prefix, num);
@@ -241,7 +253,7 @@ bool DSSaveFile::matches(char* prefix, int num) {
}
}
-bool DSSaveFile::matches(char* filename) {
+bool DSSaveFile::matches(const char *filename) {
if (isValid()) {
return !strcmp(save.name, filename);
} else {
@@ -522,3 +534,5 @@ int DSSaveFileManager::getExtraData() {
return 0;
}
}
+
+#endif
diff --git a/backends/platform/ds/arm9/source/ramsave.h b/backends/platform/ds/arm9/source/ramsave.h
index f919da18db..034e957b7f 100644
--- a/backends/platform/ds/arm9/source/ramsave.h
+++ b/backends/platform/ds/arm9/source/ramsave.h
@@ -52,6 +52,7 @@ class DSSaveFile : public Common::InSaveFile, public Common::OutSaveFile {
SCUMMSave* origHeader;
bool isOpenFlag;
bool isTempFile;
+ bool eosReached;
public:
DSSaveFile();
@@ -62,11 +63,12 @@ public:
bool isOpen() const { return isOpenFlag; }
virtual bool eos() const;
- virtual void skip(uint32 size);
+ virtual void clearErr();
+ virtual bool skip(uint32 size);
- virtual uint32 pos() const;
- virtual uint32 size() const;
- virtual void seek(int32 pos, int whence);
+ virtual int32 pos() const;
+ virtual int32 size() const;
+ virtual bool seek(int32 pos, int whence);
uint32 read(void *buf, uint32 size);
uint32 write(const void *buf, uint32 size);
@@ -76,8 +78,8 @@ public:
bool isValid() { return save.isValid; }
bool isTemp() { return isTempFile; }
- bool matches(char* prefix, int num);
- bool matches(char* filename);
+ bool matches(const char *prefix, int num);
+ bool matches(const char *filename);
void clearData();
void compress();
diff --git a/backends/platform/ds/arm9/source/touchkeyboard.cpp b/backends/platform/ds/arm9/source/touchkeyboard.cpp
index 11832f4e3a..85f80fac92 100644
--- a/backends/platform/ds/arm9/source/touchkeyboard.cpp
+++ b/backends/platform/ds/arm9/source/touchkeyboard.cpp
@@ -402,6 +402,23 @@ void createKeyEvent(int keyNum, Common::Event& event)
}
}
+void releaseAllKeys() {
+ for (int r = 0; r < DS_NUM_KEYS; r++) {
+ if (keys[r].pressed) {
+ DS::setKeyHighlight(r, false);
+
+ OSystem_DS* system = OSystem_DS::instance();
+
+ Common::Event event;
+ createKeyEvent(r, event);
+ event.type = Common::EVENT_KEYUP;
+ system->addEvent(event);
+
+ keys[r].pressed = false;
+ }
+ }
+}
+
void addKeyboardEvents() {
bool resetShift = false;
@@ -446,7 +463,7 @@ void addKeyboardEvents() {
// consolePrintf("Key: %d\n", r);
if ((keys[r].character == Common::KEYCODE_INVALID)) {
// Close button
- DS::closed = true;
+ //DS::closed = true;
} else {
createKeyEvent(r, event);
}
@@ -492,9 +509,14 @@ void addKeyboardEvents() {
OSystem_DS* system = OSystem_DS::instance();
Common::Event event;
- createKeyEvent(r, event);
- event.type = Common::EVENT_KEYUP;
- system->addEvent(event);
+ if ((keys[r].character == Common::KEYCODE_INVALID)) {
+ // Close button
+ DS::closed = true;
+ } else {
+ createKeyEvent(r, event);
+ event.type = Common::EVENT_KEYUP;
+ system->addEvent(event);
+ }
keys[r].pressed = false;
diff --git a/backends/platform/ds/arm9/source/touchkeyboard.h b/backends/platform/ds/arm9/source/touchkeyboard.h
index 8a5fc728ce..91efbc1e9a 100644
--- a/backends/platform/ds/arm9/source/touchkeyboard.h
+++ b/backends/platform/ds/arm9/source/touchkeyboard.h
@@ -40,6 +40,7 @@ bool getKeyboardClosed();
void addAutoComplete(char* word);
void clearAutoComplete();
void setCharactersEntered(int count);
+void releaseAllKeys();
}
diff --git a/backends/platform/ds/logog.bmp b/backends/platform/ds/logog.bmp
new file mode 100644
index 0000000000..9c194d3f82
--- /dev/null
+++ b/backends/platform/ds/logog.bmp
Binary files differ
diff --git a/backends/platform/ds/makefile b/backends/platform/ds/makefile
index 3fb19e939c..a9fbb13637 100644
--- a/backends/platform/ds/makefile
+++ b/backends/platform/ds/makefile
@@ -36,3 +36,23 @@ allbuilds:
make all SCUMM_BUILD=f
make semiclean
make all SCUMM_BUILD=g
+ make semiclean
+ make all SCUMM_BUILD=h
+
+allbuildssafe:
+ make clean SCUMM_BUILD=a
+ make all SCUMM_BUILD=a
+ make clean SCUMM_BUILD=b
+ make all SCUMM_BUILD=b
+ make clean SCUMM_BUILD=c
+ make all SCUMM_BUILD=c
+ make clean SCUMM_BUILD=d
+ make all SCUMM_BUILD=d
+ make clean SCUMM_BUILD=e
+ make all SCUMM_BUILD=e
+ make clean SCUMM_BUILD=f
+ make all SCUMM_BUILD=f
+ make clean SCUMM_BUILD=g
+ make all SCUMM_BUILD=g
+ make clean SCUMM_BUILD=h
+ make all SCUMM_BUILD=h
diff --git a/backends/platform/iphone/iphone_keyboard.m b/backends/platform/iphone/iphone_keyboard.m
index bd4948e30a..fda481933d 100644
--- a/backends/platform/iphone/iphone_keyboard.m
+++ b/backends/platform/iphone/iphone_keyboard.m
@@ -54,8 +54,7 @@
@implementation SoftKeyboard
- (id)initWithFrame:(CGRect)frame {
- //self = [super initWithFrame:frame];
- self = [super initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, 0.0f)];
+ self = [super initWithFrame:frame];
inputDelegate = nil;
inputView = [[TextInputHandler alloc] initWithKeyboard:self];
return self;
diff --git a/backends/platform/iphone/iphone_main.m b/backends/platform/iphone/iphone_main.m
index b01e9f3f34..6b709b0803 100644
--- a/backends/platform/iphone/iphone_main.m
+++ b/backends/platform/iphone/iphone_main.m
@@ -79,10 +79,7 @@ int main(int argc, char** argv) {
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// hide the status bar
[UIHardware _setStatusBarHeight:0.0f];
- //[self setStatusBarMode:2 orientation:0 duration:0.0f fenceID:0];
-
- //[self setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:NO];
- [self setStatusBarHidden:YES animated:YES];
+ [self setStatusBarHidden:YES animated:NO];
_window = [[UIWindow alloc] initWithContentRect: [UIHardware fullScreenApplicationContentRect]];
[_window retain];
@@ -103,9 +100,13 @@ int main(int argc, char** argv) {
- (void)applicationResume:(GSEventRef)event {
[self removeApplicationBadge];
- [UIHardware _setStatusBarHeight:0.0f];
- [self setStatusBarHidden:YES animated:YES];
[_view applicationResume];
+
+ // Workaround, need to "hide" and unhide the statusbar to properly remove it,
+ // since the Springboard has put it back without apparently flagging our application.
+ [self setStatusBarHidden:NO animated:NO]; // hide status bar
+ [UIHardware _setStatusBarHeight:0.0f];
+ [self setStatusBarHidden:YES animated:NO]; // hide status bar
}
- (void)deviceOrientationChanged:(GSEvent *)event {
diff --git a/backends/platform/iphone/iphone_video.m b/backends/platform/iphone/iphone_video.m
index 89f159c1d9..910f14ab58 100644
--- a/backends/platform/iphone/iphone_video.m
+++ b/backends/platform/iphone/iphone_video.m
@@ -169,10 +169,6 @@ bool getLocalMouseCoords(CGPoint *point) {
nil
];
- if (_screenSurface != nil) {
- //[[sharedInstance _layer] removeSublayer: screenLayer];
- }
-
//("Allocating surface: %d\n", allocSize);
_screenSurface = CoreSurfaceBufferCreate((CFDictionaryRef)dict);
//printf("Surface created.\n");
@@ -205,10 +201,13 @@ bool getLocalMouseCoords(CGPoint *point) {
[screenLayer setFrame: _screenRect];
} else {
float ratio = (float)_height / (float)_width;
- _screenRect = CGRectMake(0, 0, _fullWidth, _fullWidth * ratio);
+ int height = _fullWidth * ratio;
+ //printf("Making rect (%u, %u)\n", _fullWidth, height);
+ _screenRect = CGRectMake(0, 0, _fullWidth - 1, height - 1);
[screenLayer setFrame: _screenRect];
- CGRect keyFrame = CGRectMake(0.0f, _screenRect.size.height, _fullWidth, _fullHeight - _screenRect.size.height);
+ //CGRect keyFrame = CGRectMake(0.0f, _screenRect.size.height, _fullWidth, _fullHeight - _screenRect.size.height);
+ CGRect keyFrame = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f);
if (_keyboardView == nil) {
_keyboardView = [[SoftKeyboard alloc] initWithFrame:keyFrame];
[_keyboardView setInputDelegate:self];
@@ -250,9 +249,6 @@ bool getLocalMouseCoords(CGPoint *point) {
[self lock];
id event = [_events objectAtIndex: 0];
- if (event == nil) {
- return nil;
- }
[_events removeObjectAtIndex: 0];
[self unlock];
diff --git a/backends/platform/iphone/osys_iphone.cpp b/backends/platform/iphone/osys_iphone.cpp
index 3d5571cf3a..521e91a87e 100644
--- a/backends/platform/iphone/osys_iphone.cpp
+++ b/backends/platform/iphone/osys_iphone.cpp
@@ -56,24 +56,27 @@ const OSystem::GraphicsMode OSystem_IPHONE::s_supportedGraphicsModes[] = {
AQCallbackStruct OSystem_IPHONE::s_AudioQueue;
SoundProc OSystem_IPHONE::s_soundCallback = NULL;
void *OSystem_IPHONE::s_soundParam = NULL;
-bool OSystem_IPHONE::s_is113OrHigher = false;
OSystem_IPHONE::OSystem_IPHONE() :
_savefile(NULL), _mixer(NULL), _timer(NULL), _offscreen(NULL),
_overlayVisible(false), _overlayBuffer(NULL), _fullscreen(NULL),
_mouseHeight(0), _mouseWidth(0), _mouseBuf(NULL), _lastMouseTap(0),
_secondaryTapped(false), _lastSecondaryTap(0), _screenOrientation(kScreenOrientationFlippedLandscape),
- _needEventRestPeriod(false), _mouseClickAndDragEnabled(false),
+ _needEventRestPeriod(false), _mouseClickAndDragEnabled(false), _touchpadModeEnabled(false),
_gestureStartX(-1), _gestureStartY(-1), _fullScreenIsDirty(false),
- _mouseDirty(false), _timeSuspended(0)
+ _mouseDirty(false), _timeSuspended(0), _lastDragPosX(-1), _lastDragPosY(-1)
+
{
_queuedInputEvent.type = (Common::EventType)0;
_lastDrawnMouseRect = Common::Rect(0, 0, 0, 0);
+
+ _fsFactory = new POSIXFilesystemFactory();
}
OSystem_IPHONE::~OSystem_IPHONE() {
AudioQueueDispose(s_AudioQueue.queue, true);
+ delete _fsFactory;
delete _savefile;
delete _mixer;
delete _timer;
@@ -665,8 +668,8 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) {
float xUnit, yUnit;
if (iPhone_fetchEvent(&eventType, &xUnit, &yUnit)) {
- int x;
- int y;
+ int x = 0;
+ int y = 0;
switch (_screenOrientation) {
case kScreenOrientationPortrait:
x = (int)(xUnit * _screenWidth);
@@ -684,334 +687,436 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) {
switch ((InputEvent)eventType) {
case kInputMouseDown:
- //printf("Mouse down at (%u, %u)\n", x, y);
-
- // Workaround: kInputMouseSecondToggled isn't always sent when the
- // secondary finger is lifted. Need to make sure we get out of that mode.
- _secondaryTapped = false;
-
- warpMouse(x, y);
- // event.type = Common::EVENT_MOUSEMOVE;
- // event.mouse.x = _mouseX;
- // event.mouse.y = _mouseY;
-
- if (_mouseClickAndDragEnabled) {
- event.type = Common::EVENT_LBUTTONDOWN;
- event.mouse.x = _mouseX;
- event.mouse.y = _mouseY;
- return true;
- } else {
- _lastMouseDown = curTime;
- }
- return false;
+ if (!handleEvent_mouseDown(event, x, y))
+ return false;
break;
- case kInputMouseUp:
- //printf("Mouse up at (%u, %u)\n", x, y);
- if (_mouseClickAndDragEnabled) {
- event.type = Common::EVENT_LBUTTONUP;
- event.mouse.x = _mouseX;
- event.mouse.y = _mouseY;
- } else {
- if (curTime - _lastMouseDown < 250) {
- event.type = Common::EVENT_LBUTTONDOWN;
- event.mouse.x = _mouseX;
- event.mouse.y = _mouseY;
-
- _queuedInputEvent.type = Common::EVENT_LBUTTONUP;
- _queuedInputEvent.mouse.x = _mouseX;
- _queuedInputEvent.mouse.y = _mouseY;
- _lastMouseTap = curTime;
- _needEventRestPeriod = true;
- } else
- return false;
- }
+ case kInputMouseUp:
+ if (!handleEvent_mouseUp(event, x, y))
+ return false;
break;
+
case kInputMouseDragged:
- //printf("Mouse dragged at (%u, %u)\n", x, y);
- if (_secondaryTapped) {
- if (_gestureStartX == -1 || _gestureStartY == -1) {
- return false;
- }
-
- int vecX = (x - _gestureStartX);
- int vecY = (y - _gestureStartY);
- int lengthSq = vecX * vecX + vecY * vecY;
- //printf("Lengthsq: %u\n", lengthSq);
-
- if (lengthSq > 15000) { // Long enough gesture to react upon.
- _gestureStartX = -1;
- _gestureStartY = -1;
-
- float vecLength = sqrt(lengthSq);
- float vecXNorm = vecX / vecLength;
- float vecYNorm = vecY / vecLength;
-
- //printf("Swipe vector: (%.2f, %.2f)\n", vecXNorm, vecYNorm);
-
- if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm > 0.75) {
- // Swipe down
- event.type = Common::EVENT_KEYDOWN;
- _queuedInputEvent.type = Common::EVENT_KEYUP;
-
- event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
- event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_F5;
- event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_F5;
- _needEventRestPeriod = true;
- } else if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm < -0.75) {
- // Swipe up
- _mouseClickAndDragEnabled = !_mouseClickAndDragEnabled;
- const char *dialogMsg;
- if (_mouseClickAndDragEnabled)
- dialogMsg = "Mouse-click-and-drag mode enabled.";
- else
- dialogMsg = "Mouse-click-and-drag mode disabled.";
- GUI::TimedMessageDialog dialog(dialogMsg, 1500);
- dialog.runModal();
- return false;
- } else if (vecXNorm > 0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) {
- // Swipe right
- // _secondaryTapped = !_secondaryTapped;
- // _gestureStartX = x;
- // _gestureStartY = y;
- //
- // GUI::TimedMessageDialog dialog("Forcing toggle of pressed state.", 1500);
- // dialog.runModal();
- return false;
- } else if (vecXNorm < -0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) {
- // Swipe left
- return false;
- } else
- return false;
- } else
- return false;
- } else {
- event.type = Common::EVENT_MOUSEMOVE;
- event.mouse.x = x;
- event.mouse.y = y;
- warpMouse(x, y);
- }
+ if (!handleEvent_mouseDragged(event, x, y))
+ return false;
break;
+
case kInputMouseSecondToggled:
_secondaryTapped = !_secondaryTapped;
//printf("Mouse second at (%u, %u). State now %s.\n", x, y, _secondaryTapped ? "on" : "off");
if (_secondaryTapped) {
- _lastSecondaryDown = curTime;
- _gestureStartX = x;
- _gestureStartY = y;
- if (_mouseClickAndDragEnabled) {
- event.type = Common::EVENT_LBUTTONUP;
- event.mouse.x = _mouseX;
- event.mouse.y = _mouseY;
-
- _queuedInputEvent.type = Common::EVENT_RBUTTONDOWN;
- _queuedInputEvent.mouse.x = _mouseX;
- _queuedInputEvent.mouse.y = _mouseY;
- }
- else
+ if (!handleEvent_secondMouseDown(event, x, y))
return false;
} else {
- if (curTime - _lastSecondaryDown < 250 ) {
- if (curTime - _lastSecondaryTap < 250 && !_overlayVisible) {
- event.type = Common::EVENT_KEYDOWN;
- _queuedInputEvent.type = Common::EVENT_KEYUP;
-
- event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
- event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_ESCAPE;
- event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_ESCAPE;
- _needEventRestPeriod = true;
- _lastSecondaryTap = 0;
- } else if (!_mouseClickAndDragEnabled) {
- event.type = Common::EVENT_RBUTTONDOWN;
- event.mouse.x = _mouseX;
- event.mouse.y = _mouseY;
- _queuedInputEvent.type = Common::EVENT_RBUTTONUP;
- _queuedInputEvent.mouse.x = _mouseX;
- _queuedInputEvent.mouse.y = _mouseY;
- _lastSecondaryTap = curTime;
- _needEventRestPeriod = true;
- }
- }
- if (_mouseClickAndDragEnabled) {
- event.type = Common::EVENT_RBUTTONUP;
- event.mouse.x = _mouseX;
- event.mouse.y = _mouseY;
- }
- }
- break;
- case kInputOrientationChanged:
- //printf("Orientation: %i", (int)xUnit);
-
- ScreenOrientation newOrientation;
- switch ((int)xUnit) {
- case 1:
- newOrientation = kScreenOrientationPortrait;
- break;
- case 3:
- newOrientation = kScreenOrientationLandscape;
- break;
- case 4:
- newOrientation = kScreenOrientationFlippedLandscape;
- break;
- default:
+ if (!handleEvent_secondMouseUp(event, x, y))
return false;
}
+ break;
-
- if (_screenOrientation != newOrientation) {
- _screenOrientation = newOrientation;
- if (_screenOrientation != kScreenOrientationPortrait)
- iPhone_initSurface(_screenHeight, _screenWidth, true);
- else
- iPhone_initSurface(_screenWidth, _screenHeight, false);
-
- dirtyFullScreen();
- updateScreen();
- }
+ case kInputOrientationChanged:
+ handleEvent_orientationChanged((int)xUnit);
+ return false;
break;
case kInputApplicationSuspended:
suspendLoop();
+ return false;
break;
- case kInputKeyPressed: {
- int keyPressed = (int)xUnit;
- int ascii = keyPressed;
- //printf("key: %i\n", keyPressed);
-
- // We remap some of the iPhone keyboard keys.
- // The first ten here are the row of symbols below the numeric keys.
- switch (keyPressed) {
- case 45:
- keyPressed = Common::KEYCODE_F1;
- ascii = Common::ASCII_F1;
- break;
- case 47:
- keyPressed = Common::KEYCODE_F2;
- ascii = Common::ASCII_F2;
- break;
- case 58:
- keyPressed = Common::KEYCODE_F3;
- ascii = Common::ASCII_F3;
- break;
- case 59:
- keyPressed = Common::KEYCODE_F4;
- ascii = Common::ASCII_F4;
- break;
- case 40:
- keyPressed = Common::KEYCODE_F5;
- ascii = Common::ASCII_F5;
- break;
- case 41:
- keyPressed = Common::KEYCODE_F6;
- ascii = Common::ASCII_F6;
- break;
- case 36:
- keyPressed = Common::KEYCODE_F7;
- ascii = Common::ASCII_F7;
- break;
- case 38:
- keyPressed = Common::KEYCODE_F8;
- ascii = Common::ASCII_F8;
- break;
- case 64:
- keyPressed = Common::KEYCODE_F9;
- ascii = Common::ASCII_F9;
- break;
- case 34:
- keyPressed = Common::KEYCODE_F10;
- ascii = Common::ASCII_F10;
- break;
- case 10:
- keyPressed = Common::KEYCODE_RETURN;
- ascii = Common::ASCII_RETURN;
- break;
- }
- event.type = Common::EVENT_KEYDOWN;
- _queuedInputEvent.type = Common::EVENT_KEYUP;
+ case kInputKeyPressed:
+ handleEvent_keyPressed(event, (int)xUnit);
+ break;
- event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
- event.kbd.keycode = _queuedInputEvent.kbd.keycode = (Common::KeyCode)keyPressed;
- event.kbd.ascii = _queuedInputEvent.kbd.ascii = ascii;
- _needEventRestPeriod = true;
+ case kInputSwipe:
+ if (!handleEvent_swipe(event, (int)xUnit))
+ return false;
break;
- }
- case kInputSwipe: {
- Common::KeyCode keycode = Common::KEYCODE_INVALID;
- switch (_screenOrientation) {
- case kScreenOrientationPortrait:
- switch ((UIViewSwipeDirection)xUnit) {
- case kUIViewSwipeUp:
- keycode = Common::KEYCODE_UP;
- break;
- case kUIViewSwipeDown:
- keycode = Common::KEYCODE_DOWN;
- break;
- case kUIViewSwipeLeft:
- keycode = Common::KEYCODE_LEFT;
- break;
- case kUIViewSwipeRight:
- keycode = Common::KEYCODE_RIGHT;
- break;
- default:
- return false;
- }
- break;
- case kScreenOrientationLandscape:
- switch ((UIViewSwipeDirection)xUnit) {
- case kUIViewSwipeUp:
- keycode = Common::KEYCODE_LEFT;
- break;
- case kUIViewSwipeDown:
- keycode = Common::KEYCODE_RIGHT;
- break;
- case kUIViewSwipeLeft:
- keycode = Common::KEYCODE_DOWN;
- break;
- case kUIViewSwipeRight:
- keycode = Common::KEYCODE_UP;
- break;
- default:
- return false;
- }
- break;
- case kScreenOrientationFlippedLandscape:
- switch ((UIViewSwipeDirection)xUnit) {
- case kUIViewSwipeUp:
- keycode = Common::KEYCODE_RIGHT;
- break;
- case kUIViewSwipeDown:
- keycode = Common::KEYCODE_LEFT;
- break;
- case kUIViewSwipeLeft:
- keycode = Common::KEYCODE_UP;
- break;
- case kUIViewSwipeRight:
- keycode = Common::KEYCODE_DOWN;
- break;
- default:
- return false;
- }
- break;
- }
+ default:
+ break;
+ }
+
+ return true;
+ }
+ return false;
+}
+
+bool OSystem_IPHONE::handleEvent_mouseDown(Common::Event &event, int x, int y) {
+ printf("Mouse down at (%u, %u)\n", x, y);
+
+ // Workaround: kInputMouseSecondToggled isn't always sent when the
+ // secondary finger is lifted. Need to make sure we get out of that mode.
+ _secondaryTapped = false;
+
+ if (_touchpadModeEnabled) {
+ _lastPadX = x;
+ _lastPadY = y;
+ } else
+ warpMouse(x, y);
+
+ if (_mouseClickAndDragEnabled) {
+ event.type = Common::EVENT_LBUTTONDOWN;
+ event.mouse.x = _mouseX;
+ event.mouse.y = _mouseY;
+ return true;
+ } else {
+ _lastMouseDown = getMillis();
+ }
+ return false;
+}
+
+bool OSystem_IPHONE::handleEvent_mouseUp(Common::Event &event, int x, int y) {
+ //printf("Mouse up at (%u, %u)\n", x, y);
+
+ if (_secondaryTapped) {
+ _secondaryTapped = false;
+ if (!handleEvent_secondMouseUp(event, x, y))
+ return false;
+ }
+ else if (_mouseClickAndDragEnabled) {
+ event.type = Common::EVENT_LBUTTONUP;
+ event.mouse.x = _mouseX;
+ event.mouse.y = _mouseY;
+ } else {
+ if (getMillis() - _lastMouseDown < 250) {
+ event.type = Common::EVENT_LBUTTONDOWN;
+ event.mouse.x = _mouseX;
+ event.mouse.y = _mouseY;
+
+ _queuedInputEvent.type = Common::EVENT_LBUTTONUP;
+ _queuedInputEvent.mouse.x = _mouseX;
+ _queuedInputEvent.mouse.y = _mouseY;
+ _lastMouseTap = getMillis();
+ _needEventRestPeriod = true;
+ } else
+ return false;
+ }
+
+ return true;
+}
+
+bool OSystem_IPHONE::handleEvent_secondMouseDown(Common::Event &event, int x, int y) {
+ _lastSecondaryDown = getMillis();
+ _gestureStartX = x;
+ _gestureStartY = y;
+
+ if (_mouseClickAndDragEnabled) {
+ event.type = Common::EVENT_LBUTTONUP;
+ event.mouse.x = _mouseX;
+ event.mouse.y = _mouseY;
+
+ _queuedInputEvent.type = Common::EVENT_RBUTTONDOWN;
+ _queuedInputEvent.mouse.x = _mouseX;
+ _queuedInputEvent.mouse.y = _mouseY;
+ }
+ else
+ return false;
+
+ return true;
+}
+
+bool OSystem_IPHONE::handleEvent_secondMouseUp(Common::Event &event, int x, int y) {
+ int curTime = getMillis();
+
+ if (curTime - _lastSecondaryDown < 400 ) {
+ //printf("Right tap!\n");
+ if (curTime - _lastSecondaryTap < 400 && !_overlayVisible) {
+ //printf("Right escape!\n");
+ event.type = Common::EVENT_KEYDOWN;
+ _queuedInputEvent.type = Common::EVENT_KEYUP;
+
+ event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
+ event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_ESCAPE;
+ event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_ESCAPE;
+ _needEventRestPeriod = true;
+ _lastSecondaryTap = 0;
+ } else if (!_mouseClickAndDragEnabled) {
+ //printf("Rightclick!\n");
+ event.type = Common::EVENT_RBUTTONDOWN;
+ event.mouse.x = _mouseX;
+ event.mouse.y = _mouseY;
+ _queuedInputEvent.type = Common::EVENT_RBUTTONUP;
+ _queuedInputEvent.mouse.x = _mouseX;
+ _queuedInputEvent.mouse.y = _mouseY;
+ _lastSecondaryTap = curTime;
+ _needEventRestPeriod = true;
+ } else {
+ //printf("Right nothing!\n");
+ return false;
+ }
+ }
+ if (_mouseClickAndDragEnabled) {
+ event.type = Common::EVENT_RBUTTONUP;
+ event.mouse.x = _mouseX;
+ event.mouse.y = _mouseY;
+ }
+
+ return true;
+}
+
+bool OSystem_IPHONE::handleEvent_mouseDragged(Common::Event &event, int x, int y) {
+ if (_lastDragPosX == x && _lastDragPosY == y)
+ return false;
+
+ _lastDragPosX = x;
+ _lastDragPosY = y;
+
+ //printf("Mouse dragged at (%u, %u)\n", x, y);
+ if (_secondaryTapped) {
+ if (_gestureStartX == -1 || _gestureStartY == -1) {
+ return false;
+ }
+
+ int vecX = (x - _gestureStartX);
+ int vecY = (y - _gestureStartY);
+ int lengthSq = vecX * vecX + vecY * vecY;
+ //printf("Lengthsq: %u\n", lengthSq);
+
+ if (lengthSq > 15000) { // Long enough gesture to react upon.
+ _gestureStartX = -1;
+ _gestureStartY = -1;
+
+ float vecLength = sqrt(lengthSq);
+ float vecXNorm = vecX / vecLength;
+ float vecYNorm = vecY / vecLength;
+
+ //printf("Swipe vector: (%.2f, %.2f)\n", vecXNorm, vecYNorm);
- event.kbd.keycode = _queuedInputEvent.kbd.keycode = keycode;
- event.kbd.ascii = _queuedInputEvent.kbd.ascii = 0;
+ if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm > 0.75) {
+ // Swipe down
event.type = Common::EVENT_KEYDOWN;
_queuedInputEvent.type = Common::EVENT_KEYUP;
+
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
+ event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_F5;
+ event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_F5;
_needEventRestPeriod = true;
- break;
- }
+ } else if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm < -0.75) {
+ // Swipe up
+ _mouseClickAndDragEnabled = !_mouseClickAndDragEnabled;
+ const char *dialogMsg;
+ if (_mouseClickAndDragEnabled)
+ dialogMsg = "Mouse-click-and-drag mode enabled.";
+ else
+ dialogMsg = "Mouse-click-and-drag mode disabled.";
+ GUI::TimedMessageDialog dialog(dialogMsg, 1500);
+ dialog.runModal();
+ return false;
- default:
- break;
+ } else if (vecXNorm > 0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) {
+ // Swipe right
+ _touchpadModeEnabled = !_touchpadModeEnabled;
+ const char *dialogMsg;
+ if (_touchpadModeEnabled)
+ dialogMsg = "Touchpad mode enabled.";
+ else
+ dialogMsg = "Touchpad mode disabled.";
+ GUI::TimedMessageDialog dialog(dialogMsg, 1500);
+ dialog.runModal();
+ return false;
+
+ } else if (vecXNorm < -0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) {
+ // Swipe left
+ return false;
+ } else
+ return false;
+ } else
+ return false;
+ } else {
+ int mouseNewPosX;
+ int mouseNewPosY;
+ if (_touchpadModeEnabled ) {
+ int deltaX = _lastPadX - x;
+ int deltaY = _lastPadY - y;
+ _lastPadX = x;
+ _lastPadY = y;
+
+ mouseNewPosX = (int)(_mouseX - deltaX / 0.5f);
+ mouseNewPosY = (int)(_mouseY - deltaY / 0.5f);
+
+ if (mouseNewPosX < 0)
+ mouseNewPosX = 0;
+ else if (mouseNewPosX > _screenWidth)
+ mouseNewPosX = _screenWidth;
+
+ if (mouseNewPosY < 0)
+ mouseNewPosY = 0;
+ else if (mouseNewPosY > _screenHeight)
+ mouseNewPosY = _screenHeight;
+
+ } else {
+ mouseNewPosX = x;
+ mouseNewPosY = y;
}
+
+ event.type = Common::EVENT_MOUSEMOVE;
+ event.mouse.x = mouseNewPosX;
+ event.mouse.y = mouseNewPosY;
+ warpMouse(mouseNewPosX, mouseNewPosY);
+ }
+
+ return true;
+}
- return true;
+void OSystem_IPHONE::handleEvent_orientationChanged(int orientation) {
+ //printf("Orientation: %i\n", orientation);
+
+ ScreenOrientation newOrientation;
+ switch (orientation) {
+ case 1:
+ newOrientation = kScreenOrientationPortrait;
+ break;
+ case 3:
+ newOrientation = kScreenOrientationLandscape;
+ break;
+ case 4:
+ newOrientation = kScreenOrientationFlippedLandscape;
+ break;
+ default:
+ return;
}
- return false;
+
+
+ if (_screenOrientation != newOrientation) {
+ _screenOrientation = newOrientation;
+ if (_screenOrientation != kScreenOrientationPortrait)
+ iPhone_initSurface(_screenHeight, _screenWidth, true);
+ else
+ iPhone_initSurface(_screenWidth, _screenHeight, false);
+
+ dirtyFullScreen();
+ updateScreen();
+ }
+}
+
+void OSystem_IPHONE::handleEvent_keyPressed(Common::Event &event, int keyPressed) {
+ int ascii = keyPressed;
+ //printf("key: %i\n", keyPressed);
+
+ // We remap some of the iPhone keyboard keys.
+ // The first ten here are the row of symbols below the numeric keys.
+ switch (keyPressed) {
+ case 45:
+ keyPressed = Common::KEYCODE_F1;
+ ascii = Common::ASCII_F1;
+ break;
+ case 47:
+ keyPressed = Common::KEYCODE_F2;
+ ascii = Common::ASCII_F2;
+ break;
+ case 58:
+ keyPressed = Common::KEYCODE_F3;
+ ascii = Common::ASCII_F3;
+ break;
+ case 59:
+ keyPressed = Common::KEYCODE_F4;
+ ascii = Common::ASCII_F4;
+ break;
+ case 40:
+ keyPressed = Common::KEYCODE_F5;
+ ascii = Common::ASCII_F5;
+ break;
+ case 41:
+ keyPressed = Common::KEYCODE_F6;
+ ascii = Common::ASCII_F6;
+ break;
+ case 36:
+ keyPressed = Common::KEYCODE_F7;
+ ascii = Common::ASCII_F7;
+ break;
+ case 38:
+ keyPressed = Common::KEYCODE_F8;
+ ascii = Common::ASCII_F8;
+ break;
+ case 64:
+ keyPressed = Common::KEYCODE_F9;
+ ascii = Common::ASCII_F9;
+ break;
+ case 34:
+ keyPressed = Common::KEYCODE_F10;
+ ascii = Common::ASCII_F10;
+ break;
+ case 10:
+ keyPressed = Common::KEYCODE_RETURN;
+ ascii = Common::ASCII_RETURN;
+ break;
+ }
+ event.type = Common::EVENT_KEYDOWN;
+ _queuedInputEvent.type = Common::EVENT_KEYUP;
+
+ event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
+ event.kbd.keycode = _queuedInputEvent.kbd.keycode = (Common::KeyCode)keyPressed;
+ event.kbd.ascii = _queuedInputEvent.kbd.ascii = ascii;
+ _needEventRestPeriod = true;
+}
+
+bool OSystem_IPHONE::handleEvent_swipe(Common::Event &event, int direction) {
+ Common::KeyCode keycode = Common::KEYCODE_INVALID;
+ switch (_screenOrientation) {
+ case kScreenOrientationPortrait:
+ switch ((UIViewSwipeDirection)direction) {
+ case kUIViewSwipeUp:
+ keycode = Common::KEYCODE_UP;
+ break;
+ case kUIViewSwipeDown:
+ keycode = Common::KEYCODE_DOWN;
+ break;
+ case kUIViewSwipeLeft:
+ keycode = Common::KEYCODE_LEFT;
+ break;
+ case kUIViewSwipeRight:
+ keycode = Common::KEYCODE_RIGHT;
+ break;
+ default:
+ return false;
+ }
+ break;
+ case kScreenOrientationLandscape:
+ switch ((UIViewSwipeDirection)direction) {
+ case kUIViewSwipeUp:
+ keycode = Common::KEYCODE_LEFT;
+ break;
+ case kUIViewSwipeDown:
+ keycode = Common::KEYCODE_RIGHT;
+ break;
+ case kUIViewSwipeLeft:
+ keycode = Common::KEYCODE_DOWN;
+ break;
+ case kUIViewSwipeRight:
+ keycode = Common::KEYCODE_UP;
+ break;
+ default:
+ return false;
+ }
+ break;
+ case kScreenOrientationFlippedLandscape:
+ switch ((UIViewSwipeDirection)direction) {
+ case kUIViewSwipeUp:
+ keycode = Common::KEYCODE_RIGHT;
+ break;
+ case kUIViewSwipeDown:
+ keycode = Common::KEYCODE_LEFT;
+ break;
+ case kUIViewSwipeLeft:
+ keycode = Common::KEYCODE_UP;
+ break;
+ case kUIViewSwipeRight:
+ keycode = Common::KEYCODE_DOWN;
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+
+ event.kbd.keycode = _queuedInputEvent.kbd.keycode = keycode;
+ event.kbd.ascii = _queuedInputEvent.kbd.ascii = 0;
+ event.type = Common::EVENT_KEYDOWN;
+ _queuedInputEvent.type = Common::EVENT_KEYUP;
+ event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
+ _needEventRestPeriod = true;
+
+ return true;
}
void OSystem_IPHONE::suspendLoop() {
@@ -1020,16 +1125,17 @@ void OSystem_IPHONE::suspendLoop() {
float xUnit, yUnit;
uint32 startTime = getMillis();
- AudioQueueStop(s_AudioQueue.queue, true);
-
+ stopSoundsystem();
+
while (!done) {
if (iPhone_fetchEvent(&eventType, &xUnit, &yUnit))
if ((InputEvent)eventType == kInputApplicationResumed)
done = true;
usleep(100000);
}
+
+ startSoundsystem();
- AudioQueueStart(s_AudioQueue.queue, NULL);
_timeSuspended += getMillis() - startTime;
}
@@ -1107,7 +1213,10 @@ void OSystem_IPHONE::setupMixer() {
s_soundCallback = mixCallback;
s_soundParam = this;
+ startSoundsystem();
+}
+void OSystem_IPHONE::startSoundsystem() {
s_AudioQueue.dataFormat.mSampleRate = AUDIO_SAMPLE_RATE;
s_AudioQueue.dataFormat.mFormatID = kAudioFormatLinearPCM;
s_AudioQueue.dataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
@@ -1147,6 +1256,17 @@ void OSystem_IPHONE::setupMixer() {
_mixer->setReady(true);
}
+void OSystem_IPHONE::stopSoundsystem() {
+ AudioQueueStop(s_AudioQueue.queue, true);
+
+ for (int i = 0; i < AUDIO_BUFFERS; i++) {
+ AudioQueueFreeBuffer(s_AudioQueue.queue, s_AudioQueue.buffers[i]);
+ }
+
+ AudioQueueDispose(s_AudioQueue.queue, true);
+ _mixer->setReady(false);
+}
+
int OSystem_IPHONE::getOutputSampleRate() const {
return AUDIO_SAMPLE_RATE;
}
@@ -1196,29 +1316,6 @@ const char* OSystem_IPHONE::getConfigPath() {
return SCUMMVM_PREFS_PATH;
}
-void OSystem_IPHONE::migrateApp() {
- // Migrate to the new 1.1.3 directory structure, if needed.
-
- FilesystemNode file("/var/mobile");
- if (file.exists() && file.isDirectory()) {
- // We have 1.1.3 or above.
- s_is113OrHigher = true;
- file = FilesystemNode(SCUMMVM_ROOT_PATH);
- if (!file.exists()) {
- system("mkdir " SCUMMVM_ROOT_PATH);
- system("mkdir " SCUMMVM_SAVE_PATH);
-
- // Copy over the prefs file
- system("cp " SCUMMVM_OLD_PREFS_PATH " " SCUMMVM_PREFS_PATH);
-
- file = FilesystemNode(SCUMMVM_OLD_SAVE_PATH);
- // Copy over old savegames to the new directory.
- if (file.exists() && file.isDirectory())
- system("cp " SCUMMVM_OLD_SAVE_PATH "/* " SCUMMVM_SAVE_PATH "/");
- }
- }
-}
-
void iphone_main(int argc, char *argv[]) {
//OSystem_IPHONE::migrateApp();
@@ -1239,6 +1336,8 @@ void iphone_main(int argc, char *argv[]) {
system("mkdir " SCUMMVM_ROOT_PATH);
system("mkdir " SCUMMVM_SAVE_PATH);
+ chdir("/var/mobile/");
+
g_system = OSystem_IPHONE_create();
assert(g_system);
diff --git a/backends/platform/iphone/osys_iphone.h b/backends/platform/iphone/osys_iphone.h
index c058686c8c..a9a3ddad65 100644
--- a/backends/platform/iphone/osys_iphone.h
+++ b/backends/platform/iphone/osys_iphone.h
@@ -35,14 +35,12 @@
#include <AudioToolbox/AudioQueue.h>
#define AUDIO_BUFFERS 3
-#define WAVE_BUFFER_SIZE 8192
+#define WAVE_BUFFER_SIZE 2048
#define AUDIO_SAMPLE_RATE 44100
#define SCUMMVM_ROOT_PATH "/var/mobile/Library/ScummVM"
#define SCUMMVM_SAVE_PATH SCUMMVM_ROOT_PATH "/Savegames"
-#define SCUMMVM_OLD_SAVE_PATH "/var/root/.scummvm"
#define SCUMMVM_PREFS_PATH SCUMMVM_ROOT_PATH "/Preferences"
-#define SCUMMVM_OLD_PREFS_PATH "/var/root/.scummvmrc"
typedef void (*SoundProc)(void *param, byte *buf, int len);
typedef int (*TimerProc)(int interval);
@@ -61,7 +59,6 @@ protected:
static AQCallbackStruct s_AudioQueue;
static SoundProc s_soundCallback;
static void *s_soundParam;
- static bool s_is113OrHigher;
Common::SaveFileManager *_savefile;
Audio::MixerImpl *_mixer;
@@ -97,6 +94,11 @@ protected:
long _lastSecondaryTap;
int _gestureStartX, _gestureStartY;
bool _mouseClickAndDragEnabled;
+ bool _touchpadModeEnabled;
+ int _lastPadX;
+ int _lastPadY;
+ int _lastDragPosX;
+ int _lastDragPosY;
int _timerCallbackNext;
int _timerCallbackTimer;
@@ -106,6 +108,8 @@ protected:
ScreenOrientation _screenOrientation;
bool _fullScreenIsDirty;
+ FilesystemFactory *_fsFactory;
+
public:
OSystem_IPHONE();
@@ -161,7 +165,7 @@ public:
virtual void quit();
- FilesystemFactory *getFilesystemFactory() { return &POSIXFilesystemFactory::instance(); }
+ FilesystemFactory *getFilesystemFactory() { return _fsFactory; }
virtual void getTimeAndDate(struct tm &t) const;
virtual void setWindowCaption(const char *caption);
@@ -170,7 +174,9 @@ public:
virtual Audio::Mixer *getMixer();
virtual Common::TimerManager *getTimerManager();
- static void migrateApp();
+ void startSoundsystem();
+ void stopSoundsystem();
+
static const char* getConfigPath();
protected:
@@ -182,6 +188,18 @@ protected:
void suspendLoop();
static void AQBufferCallback(void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB);
static int timerHandler(int t);
+
+ bool handleEvent_swipe(Common::Event &event, int direction);
+ void handleEvent_keyPressed(Common::Event &event, int keyPressed);
+ void handleEvent_orientationChanged(int orientation);
+
+ bool handleEvent_mouseDown(Common::Event &event, int x, int y);
+ bool handleEvent_mouseUp(Common::Event &event, int x, int y);
+
+ bool handleEvent_secondMouseDown(Common::Event &event, int x, int y);
+ bool handleEvent_secondMouseUp(Common::Event &event, int x, int y);
+
+ bool handleEvent_mouseDragged(Common::Event &event, int x, int y);
};
#endif
diff --git a/backends/platform/null/null.cpp b/backends/platform/null/null.cpp
index 463e9d7b2d..610f1d3a42 100644
--- a/backends/platform/null/null.cpp
+++ b/backends/platform/null/null.cpp
@@ -50,13 +50,12 @@
#include "backends/fs/windows/windows-fs-factory.h"
#endif
-
-
class OSystem_NULL : public OSystem {
protected:
Common::SaveFileManager *_savefile;
Audio::MixerImpl *_mixer;
Common::TimerManager *_timer;
+ FilesystemFactory *_fsFactory;
timeval _startTime;
public:
@@ -133,12 +132,23 @@ OSystem_NULL::OSystem_NULL() {
_savefile = 0;
_mixer = 0;
_timer = 0;
+
+ #if defined(__amigaos4__)
+ _fsFactory = new AmigaOSFilesystemFactory();
+ #elif defined(UNIX)
+ _fsFactory = new POSIXFilesystemFactory();
+ #elif defined(WIN32)
+ _fsFactory = new WindowsFilesystemFactory();
+ #else
+ #error Unknown and unsupported FS backend
+ #endif
}
OSystem_NULL::~OSystem_NULL() {
delete _savefile;
delete _mixer;
delete _timer;
+ delete _fsFactory;
}
void OSystem_NULL::initBackend() {
@@ -194,11 +204,11 @@ void OSystem_NULL::initSize(uint width, uint height) {
}
int16 OSystem_NULL::getHeight() {
- return 320;
+ return 200;
}
int16 OSystem_NULL::getWidth() {
- return 200;
+ return 320;
}
void OSystem_NULL::setPalette(const byte *colors, uint start, uint num) {
@@ -327,18 +337,9 @@ void OSystem_NULL::getTimeAndDate(struct tm &t) const {
}
FilesystemFactory *OSystem_NULL::getFilesystemFactory() {
- #if defined(__amigaos4__)
- return &AmigaOSFilesystemFactory::instance();
- #elif defined(UNIX)
- return &POSIXFilesystemFactory::instance();
- #elif defined(WIN32)
- return &WindowsFilesystemFactory::instance();
- #else
- #error Unknown and unsupported backend in OSystem_NULL::getFilesystemFactory
- #endif
+ return _fsFactory;
}
-
OSystem *OSystem_NULL_create() {
return new OSystem_NULL();
}
diff --git a/backends/platform/ps2/rawsavefile.cpp b/backends/platform/ps2/rawsavefile.cpp
index 03270ea9ce..aa3cc57fe7 100644
--- a/backends/platform/ps2/rawsavefile.cpp
+++ b/backends/platform/ps2/rawsavefile.cpp
@@ -31,6 +31,7 @@ RawReadFile::RawReadFile(McAccess *mcAccess) {
_size = -1;
_pos = 0;
_buf = NULL;
+ _eof = false;
}
RawReadFile::~RawReadFile(void) {
@@ -79,12 +80,16 @@ int RawReadFile::bufSeek(int ofs, int whence) {
_pos = 0;
else if (_pos > _size)
_pos = _size;
+
+ _eof = false;
return _pos;
}
int RawReadFile::bufRead(void *dest, int size) {
- if (_pos + size > _size)
+ if (_pos + size > _size) {
size = _size - _pos;
+ _eof = true;
+ }
memcpy(dest, _buf + _pos, size);
_pos += size;
return size;
@@ -94,7 +99,13 @@ int RawReadFile::bufSize(void) const {
return _size;
}
+bool RawReadFile::bufEof(void) const {
+ return _eof;
+}
+void RawReadFile::bufClearErr(void) const {
+ _eof = false;
+}
RawWriteFile::RawWriteFile(McAccess *mcAccess) {
_mcAccess = mcAccess;
diff --git a/backends/platform/ps2/rawsavefile.h b/backends/platform/ps2/rawsavefile.h
index b638d106ab..8e0dba4ab9 100644
--- a/backends/platform/ps2/rawsavefile.h
+++ b/backends/platform/ps2/rawsavefile.h
@@ -40,11 +40,14 @@ public:
int bufTell(void) const;
int bufSeek(int ofs, int whence);
int bufSize(void) const;
+ bool bufEof(void) const;
+ void bufClearErr(void);
protected:
McAccess *_mcAccess;
int _size;
uint8 *_buf;
int _pos;
+ bool _eof;
};
class RawWriteFile {
diff --git a/backends/platform/ps2/savefile.cpp b/backends/platform/ps2/savefile.cpp
index 5ee724cd3f..bfcaf0f57f 100644
--- a/backends/platform/ps2/savefile.cpp
+++ b/backends/platform/ps2/savefile.cpp
@@ -71,7 +71,7 @@ uint32 AutoSaveFile::write(const void *ptr, uint32 size) {
UclInSaveFile::UclInSaveFile(const char *filename, Gs2dScreen *screen, McAccess *mcAccess) : RawReadFile(mcAccess) {
_screen = screen;
- _ioFailed = true;
+ _err = true;
if (bufOpen(filename)) {
if ((_size > 8) && (*(uint32 *)_buf == UCL_MAGIC)) {
@@ -82,13 +82,13 @@ UclInSaveFile::UclInSaveFile(const char *filename, Gs2dScreen *screen, McAccess
free(_buf);
_buf = decBuf;
_size = resSize;
- _ioFailed = false;
+ _err = false;
_pos = 0;
} else
free(decBuf);
}
}
- if (_ioFailed) {
+ if (_err) {
if (_buf)
free(_buf);
_buf = NULL;
@@ -100,36 +100,39 @@ UclInSaveFile::~UclInSaveFile(void) {
_screen->wantAnim(false);
}
-bool UclInSaveFile::ioFailed(void) const {
- return _ioFailed;
+bool UclInSaveFile::err(void) const {
+ return _err;
}
-void UclInSaveFile::clearIOFailed(void) {
- _ioFailed = false;
+void UclInSaveFile::clearErr(void) {
+ _err = false;
+ bufClearErr();
}
bool UclInSaveFile::eos(void) const {
- return bufTell() == bufSize();
+ return bufEof();
}
-uint32 UclInSaveFile::pos(void) const {
+int32 UclInSaveFile::pos(void) const {
return bufTell();
}
-uint32 UclInSaveFile::size(void) const {
+int32 UclInSaveFile::size(void) const {
return bufSize();
}
-void UclInSaveFile::seek(int pos, int whence) {
+bool UclInSaveFile::seek(int pos, int whence) {
bufSeek(pos, whence);
+ return true;
}
uint32 UclInSaveFile::read(void *ptr, uint32 size) {
return (uint32)bufRead(ptr, (int)size);
}
-void UclInSaveFile::skip(uint32 offset) {
+bool UclInSaveFile::skip(uint32 offset) {
bufSeek(offset, SEEK_CUR);
+ return true;
}
UclOutSaveFile::UclOutSaveFile(const char *filename, OSystem_PS2 *system, Gs2dScreen *screen, McAccess *mc) : RawWriteFile(mc) {
@@ -137,7 +140,7 @@ UclOutSaveFile::UclOutSaveFile(const char *filename, OSystem_PS2 *system, Gs2dSc
_system = system;
strcpy(_fileName, filename);
- _ioFailed = !bufOpen(filename);
+ _err = !bufOpen(filename);
_wasFlushed = false;
}
@@ -146,7 +149,7 @@ UclOutSaveFile::~UclOutSaveFile(void) {
if (_pos != 0) {
printf("Engine didn't call SaveFile::flush()\n");
flush();
- if (ioFailed()) {
+ if (err()) {
// unable to save to memory card and it's too late to return an error code to the engine
_system->msgPrintf(5000, "!WARNING!\nCan't write to memory card.\nGame was NOT saved.");
printf("~UclOutSaveFile: Flush failed!\n");
@@ -160,20 +163,20 @@ uint32 UclOutSaveFile::write(const void *ptr, uint32 size) {
return size;
}
-bool UclOutSaveFile::ioFailed(void) const {
- return _ioFailed;
+bool UclOutSaveFile::err(void) const {
+ return _err;
}
-void UclOutSaveFile::clearIOFailed(void) {
- _ioFailed = false;
+void UclOutSaveFile::clearErr(void) {
+ _err = false;
}
-void UclOutSaveFile::flush(void) {
+bool UclOutSaveFile::flush(void) {
if (_pos != 0) {
if (_wasFlushed) {
printf("Multiple calls to UclOutSaveFile::flush!\n");
- _ioFailed = true;
- return;
+ _err = true;
+ return false;
}
uint32 compSize = _pos * 2;
uint8 *compBuf = (uint8*)memalign(64, compSize + 8);
@@ -188,11 +191,12 @@ void UclOutSaveFile::flush(void) {
_pos = compSize + 8;
if (!bufFlush()) {
printf("UclOutSaveFile::flush failed!\n");
- _ioFailed = true;
+ _err = true;
removeFile();
}
_wasFlushed = true;
}
+ return true;
}
/* ----------------------------------------- Glue Classes for POSIX Memory Card Access ----------------------------------------- */
@@ -216,11 +220,11 @@ uint32 Ps2McReadFile::write(const void *src, uint32 len) {
return 0;
}
-uint32 Ps2McReadFile::tell(void) {
+int32 Ps2McReadFile::tell(void) {
return bufTell();
}
-uint32 Ps2McReadFile::size(void) {
+int32 Ps2McReadFile::size(void) {
return bufSize();
}
@@ -253,11 +257,11 @@ uint32 Ps2McWriteFile::write(const void *src, uint32 len) {
return len;
}
-uint32 Ps2McWriteFile::tell(void) {
+int32 Ps2McWriteFile::tell(void) {
return bufTell();
}
-uint32 Ps2McWriteFile::size(void) {
+int32 Ps2McWriteFile::size(void) {
return bufTell();
}
@@ -267,6 +271,3 @@ int Ps2McWriteFile::seek(int32 offset, int origin) {
return 0;
}
-bool Ps2McWriteFile::eof(void) {
- return true;
-}
diff --git a/backends/platform/ps2/savefile.h b/backends/platform/ps2/savefile.h
index 4832b8c3fe..0c0cf922f4 100644
--- a/backends/platform/ps2/savefile.h
+++ b/backends/platform/ps2/savefile.h
@@ -41,14 +41,14 @@ public:
UclOutSaveFile(const char *filename, OSystem_PS2 *system, Gs2dScreen *screen, McAccess *mc);
virtual ~UclOutSaveFile(void);
virtual uint32 write(const void *ptr, uint32 size);
- virtual void flush(void);
- virtual bool ioFailed(void) const;
- virtual void clearIOFailed(void);
+ virtual bool flush(void);
+ virtual bool err(void) const;
+ virtual void clearErr(void);
private:
OSystem_PS2 *_system;
Gs2dScreen *_screen;
- bool _ioFailed, _wasFlushed;
+ bool _err, _wasFlushed;
char _fileName[128];
};
@@ -58,16 +58,16 @@ public:
virtual ~UclInSaveFile(void);
virtual bool eos(void) const;
virtual uint32 read(void *ptr, uint32 size);
- virtual bool ioFailed(void) const;
- virtual void clearIOFailed(void);
- virtual void skip(uint32 offset);
+ virtual bool err(void) const;
+ virtual void clearErr(void);
+ virtual bool skip(uint32 offset);
- virtual uint32 pos(void) const;
- virtual uint32 size(void) const;
- virtual void seek(int pos, int whence = SEEK_SET);
+ virtual int32 pos(void) const;
+ virtual int32 size(void) const;
+ virtual bool seek(int pos, int whence = SEEK_SET);
private:
Gs2dScreen *_screen;
- bool _ioFailed;
+ bool _err;
};
class AutoSaveFile : public Common::OutSaveFile {
@@ -75,9 +75,9 @@ public:
AutoSaveFile(Ps2SaveFileManager *saveMan, const char *filename);
~AutoSaveFile(void);
virtual uint32 write(const void *ptr, uint32 size);
- virtual void flush(void) {}
- virtual bool ioFailed(void) { return false; };
- virtual void clearIOFailed(void) {}
+ virtual bool flush(void) {}
+ virtual bool err(void) const { return false; }
+ virtual void clearErr(void) {}
private:
Ps2SaveFileManager *_saveMan;
char _fileName[256];
@@ -95,8 +95,8 @@ public:
virtual bool open(const char *name);
virtual uint32 read(void *dest, uint32 len);
virtual uint32 write(const void *src, uint32 len);
- virtual uint32 tell(void);
- virtual uint32 size(void);
+ virtual int32 tell(void);
+ virtual int32 size(void);
virtual int seek(int32 offset, int origin);
virtual bool eof(void);
};
@@ -108,10 +108,9 @@ public:
virtual bool open(const char *name);
virtual uint32 read(void *dest, uint32 len);
virtual uint32 write(const void *src, uint32 len);
- virtual uint32 tell(void);
- virtual uint32 size(void);
+ virtual int32 tell(void);
+ virtual int32 size(void);
virtual int seek(int32 offset, int origin);
- virtual bool eof(void);
};
#endif // __PS2_SAVEFILE__
diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp
index 6e9b5980d4..69be0abcb2 100644
--- a/backends/platform/psp/osys_psp.cpp
+++ b/backends/platform/psp/osys_psp.cpp
@@ -98,7 +98,20 @@ OSystem_PSP::~OSystem_PSP() {
void OSystem_PSP::initBackend() {
- _savefile = new DefaultSaveFileManager();
+ _savefile = new DefaultSaveFileManager("ms0:/scummvm_savegames");
+
+ const char *savePath = _savefile->getSavePath().c_str();
+
+ //check if the save directory exists
+ SceUID fd = sceIoDopen(savePath);
+ if (fd < 0) {
+ //No? then let's create it.
+ sceIoMkdir(savePath, 0777);
+ } else {
+ //it exists, so close it again.
+ sceIoDclose(fd);
+ }
+
_timer = new DefaultTimerManager();
setTimerCallback(&timer_handler, 10);
diff --git a/backends/platform/psp/osys_psp_gu.cpp b/backends/platform/psp/osys_psp_gu.cpp
index 7e36fe6db0..1aa3bcd438 100644
--- a/backends/platform/psp/osys_psp_gu.cpp
+++ b/backends/platform/psp/osys_psp_gu.cpp
@@ -94,19 +94,23 @@ OSystem_PSP_GU::OSystem_PSP_GU() {
//decompress keyboard data
uLongf kbdSize = KBD_DATA_SIZE;
keyboard_letters = (unsigned char *)memalign(16, KBD_DATA_SIZE);
- assert(Z_OK == uncompress((Bytef *)keyboard_letters, &kbdSize, (const Bytef *)keyboard_letters_compressed, size_keyboard_letters_compressed));
-
+ if (!uncompress((Bytef *)keyboard_letters, &kbdSize, (const Bytef *)keyboard_letters_compressed, size_keyboard_letters_compressed))
+ error("OSystem_PSP_GU: uncompressing keyboard_letters failed");
+
kbdSize = KBD_DATA_SIZE;
keyboard_letters_shift = (unsigned char *)memalign(16, KBD_DATA_SIZE);
- assert(Z_OK == uncompress((Bytef *)keyboard_letters_shift, &kbdSize, (const Bytef *)keyboard_letters_shift_compressed, size_keyboard_letters_shift_compressed));
+ if (!uncompress((Bytef *)keyboard_letters_shift, &kbdSize, (const Bytef *)keyboard_letters_shift_compressed, size_keyboard_letters_shift_compressed))
+ error("OSystem_PSP_GU: uncompressing keyboard_letters_shift failed");
kbdSize = KBD_DATA_SIZE;
keyboard_symbols = (unsigned char *)memalign(16, KBD_DATA_SIZE);
- assert(Z_OK == uncompress((Bytef *)keyboard_symbols, &kbdSize, (const Bytef *)keyboard_symbols_compressed, size_keyboard_symbols_compressed));
+ if (!uncompress((Bytef *)keyboard_symbols, &kbdSize, (const Bytef *)keyboard_symbols_compressed, size_keyboard_symbols_compressed))
+ error("OSystem_PSP_GU: uncompressing keyboard_symbols failed");
kbdSize = KBD_DATA_SIZE;
keyboard_symbols_shift = (unsigned char *)memalign(16, KBD_DATA_SIZE);
- assert(Z_OK == uncompress((Bytef *)keyboard_symbols_shift, &kbdSize, (const Bytef *)keyboard_symbols_shift_compressed, size_keyboard_symbols_shift_compressed));
+ if (!uncompress((Bytef *)keyboard_symbols_shift, &kbdSize, (const Bytef *)keyboard_symbols_shift_compressed, size_keyboard_symbols_shift_compressed))
+ error("OSystem_PSP_GU: uncompressing keyboard_symbols_shift failed");
_keyboardVisible = false;
_clut = (unsigned short*)(((unsigned int)clut256)|0x40000000);
diff --git a/backends/platform/psp/portdefs.h b/backends/platform/psp/portdefs.h
index af772230d7..1708a70c74 100644
--- a/backends/platform/psp/portdefs.h
+++ b/backends/platform/psp/portdefs.h
@@ -43,7 +43,6 @@
#include "trace.h"
-#define SCUMMVM_SAVEPATH "ms0:/scummvm_savegames"
#define BREAKPOINT asm("break\n")
diff --git a/backends/platform/psp/psp_main.cpp b/backends/platform/psp/psp_main.cpp
index d2ed59efbe..94ef63488d 100644
--- a/backends/platform/psp/psp_main.cpp
+++ b/backends/platform/psp/psp_main.cpp
@@ -122,16 +122,6 @@ int main(void)
{
SetupCallbacks();
- //check if the save directory exists
- SceUID fd = sceIoDopen(SCUMMVM_SAVEPATH);
- if (fd < 0) {
- //No? then let's create it.
- sceIoMkdir(SCUMMVM_SAVEPATH, 0777);
- } else {
- //it exists, so close it again.
- sceIoDclose(fd);
- }
-
static char *argv[] = { "scummvm", NULL };
static int argc = sizeof(argv)/sizeof(char *)-1;
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 5c3b87309d..9a6f294a55 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -32,9 +32,9 @@
#endif
#include "backends/platform/sdl/sdl.h"
+#include "common/archive.h"
#include "common/config-manager.h"
#include "common/events.h"
-#include "common/file.h"
#include "common/util.h"
#include "backends/saves/default/default-saves.h"
@@ -72,6 +72,9 @@
#define DEFAULT_CONFIG_FILE "scummvm.ini"
#endif
+#if defined(MACOSX) || defined(IPHONE)
+#include "CoreFoundation/CoreFoundation.h"
+#endif
static Uint32 timer_handler(Uint32 interval, void *param) {
@@ -196,6 +199,7 @@ OSystem_SDL::OSystem_SDL()
_soundMutex(0), _soundCond(0), _soundThread(0),
_soundThreadIsRunning(false), _soundThreadShouldQuit(false),
#endif
+ _fsFactory(0),
_savefile(0),
_mixer(0),
_timer(0),
@@ -213,6 +217,19 @@ OSystem_SDL::OSystem_SDL()
memset(&_mouseCurState, 0, sizeof(_mouseCurState));
_inited = false;
+
+
+ #if defined(__amigaos4__)
+ _fsFactory = new AmigaOSFilesystemFactory();
+ #elif defined(UNIX)
+ _fsFactory = new POSIXFilesystemFactory();
+ #elif defined(WIN32)
+ _fsFactory = new WindowsFilesystemFactory();
+ #elif defined(__SYMBIAN32__)
+ // Do nothing since its handled by the Symbian SDL inheritance
+ #else
+ #error Unknown and unsupported FS backend
+ #endif
}
OSystem_SDL::~OSystem_SDL() {
@@ -254,19 +271,42 @@ Common::SaveFileManager *OSystem_SDL::getSavefileManager() {
}
FilesystemFactory *OSystem_SDL::getFilesystemFactory() {
- #if defined(__amigaos4__)
- return &AmigaOSFilesystemFactory::instance();
- #elif defined(UNIX)
- return &POSIXFilesystemFactory::instance();
- #elif defined(WIN32)
- return &WindowsFilesystemFactory::instance();
- #elif defined(__SYMBIAN32__)
- // Do nothing since its handled by the Symbian SDL inheritance
- #else
- #error Unknown and unsupported backend in OSystem_SDL::getFilesystemFactory
- #endif
+ assert(_fsFactory);
+ return _fsFactory;
+}
+
+void OSystem_SDL::addSysArchivesToSearchSet(Common::SearchSet &s, uint priority) {
+
+#ifdef DATA_PATH
+ // Add the global DATA_PATH to the directory search list
+ // FIXME: We use depth = 4 for now, to match the old code. May want to change that
+ Common::FilesystemNode dataNode(DATA_PATH);
+ if (dataNode.exists() && dataNode.isDirectory()) {
+ Common::ArchivePtr dataArchive(new Common::FSDirectory(dataNode, 4));
+ s.add(DATA_PATH, dataArchive, priority);
+ }
+#endif
+
+#if defined(MACOSX) || defined(IPHONE)
+ // Get URL of the Resource directory of the .app bundle
+ CFURLRef fileUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
+ if (fileUrl) {
+ // Try to convert the URL to an absolute path
+ UInt8 buf[MAXPATHLEN];
+ if (CFURLGetFileSystemRepresentation(fileUrl, true, buf, sizeof(buf))) {
+ // Success: Add it to the search path
+ Common::String bundlePath((const char *)buf);
+ Common::ArchivePtr bundleArchive(new Common::FSDirectory(bundlePath));
+ s.add("__OSX_BUNDLE__", bundleArchive, priority);
+ }
+ CFRelease(fileUrl);
+ }
+
+#endif
+
}
+
static Common::String getDefaultConfigFileName() {
char configFile[MAXPATHLEN];
#if defined (WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
@@ -292,20 +332,19 @@ static Common::String getDefaultConfigFileName() {
CreateDirectory(configFile, NULL);
strcat(configFile, "\\" DEFAULT_CONFIG_FILE);
- if (fopen(configFile, "r") == NULL) {
+ FILE *tmp = NULL;
+ if ((tmp = fopen(configFile, "r")) == NULL) {
// Check windows directory
char oldConfigFile[MAXPATHLEN];
GetWindowsDirectory(oldConfigFile, MAXPATHLEN);
strcat(oldConfigFile, "\\" DEFAULT_CONFIG_FILE);
- if (fopen(oldConfigFile, "r")) {
- printf("The default location of the config file (scummvm.ini) in ScummVM has changed,\n");
- printf("under Windows NT4/2000/XP/Vista. You may want to consider moving your config\n");
- printf("file from the old default location:\n");
- printf("%s\n", oldConfigFile);
- printf("to the new default location:\n");
- printf("%s\n\n", configFile);
+ if ((tmp = fopen(oldConfigFile, "r"))) {
strcpy(configFile, oldConfigFile);
+
+ fclose(tmp);
}
+ } else {
+ fclose(tmp);
}
} else {
// Check windows directory
@@ -334,23 +373,13 @@ static Common::String getDefaultConfigFileName() {
}
Common::SeekableReadStream *OSystem_SDL::openConfigFileForReading() {
- Common::File *confFile = new Common::File();
- assert(confFile);
- if (!confFile->open(getDefaultConfigFileName())) {
- delete confFile;
- confFile = 0;
- }
- return confFile;
+ Common::FilesystemNode file(getDefaultConfigFileName());
+ return file.openForReading();
}
Common::WriteStream *OSystem_SDL::openConfigFileForWriting() {
- Common::DumpFile *confFile = new Common::DumpFile();
- assert(confFile);
- if (!confFile->open(getDefaultConfigFileName())) {
- delete confFile;
- confFile = 0;
- }
- return confFile;
+ Common::FilesystemNode file(getDefaultConfigFileName());
+ return file.openForWriting();
}
void OSystem_SDL::setWindowCaption(const char *caption) {
@@ -435,15 +464,21 @@ void OSystem_SDL::quit() {
}
void OSystem_SDL::setupIcon() {
- int w, h, ncols, nbytes, i;
- unsigned int rgba[256], icon[32 * 32];
- unsigned char mask[32][4];
+ int x, y, w, h, ncols, nbytes, i;
+ unsigned int rgba[256];
+ unsigned int *icon;
sscanf(scummvm_icon[0], "%d %d %d %d", &w, &h, &ncols, &nbytes);
- if ((w != 32) || (h != 32) || (ncols > 255) || (nbytes > 1)) {
- warning("Could not load the icon (%d %d %d %d)", w, h, ncols, nbytes);
+ if ((w > 512) || (h > 512) || (ncols > 255) || (nbytes > 1)) {
+ warning("Could not load the built-in icon (%d %d %d %d)", w, h, ncols, nbytes);
+ return;
+ }
+ icon = (unsigned int*)malloc(w*h*sizeof(unsigned int));
+ if (!icon) {
+ warning("Could not allocate temp storage for the built-in icon");
return;
}
+
for (i = 0; i < ncols; i++) {
unsigned char code;
char color[32];
@@ -457,26 +492,27 @@ void OSystem_SDL::setupIcon() {
sscanf(color + 1, "%06x", &col);
col |= 0xFF000000;
} else {
- warning("Could not load the icon (%d %s - %s) ", code, color, scummvm_icon[1 + i]);
+ warning("Could not load the built-in icon (%d %s - %s) ", code, color, scummvm_icon[1 + i]);
+ free(icon);
return;
}
rgba[code] = col;
}
- memset(mask, 0, sizeof(mask));
- for (h = 0; h < 32; h++) {
- const char *line = scummvm_icon[1 + ncols + h];
- for (w = 0; w < 32; w++) {
- icon[w + 32 * h] = rgba[(int)line[w]];
- if (rgba[(int)line[w]] & 0xFF000000) {
- mask[h][w >> 3] |= 1 << (7 - (w & 0x07));
- }
+ for (y = 0; y < h; y++) {
+ const char *line = scummvm_icon[1 + ncols + y];
+ for (x = 0; x < w; x++) {
+ icon[x + w * y] = rgba[(int)line[x]];
}
}
- SDL_Surface *sdl_surf = SDL_CreateRGBSurfaceFrom(icon, 32, 32, 32, 32 * 4, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000);
- SDL_WM_SetIcon(sdl_surf, (unsigned char *) mask);
+ SDL_Surface *sdl_surf = SDL_CreateRGBSurfaceFrom(icon, w, h, 32, w * 4, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000);
+ if (!sdl_surf) {
+ warning("SDL_CreateRGBSurfaceFrom(icon) failed");
+ }
+ SDL_WM_SetIcon(sdl_surf, NULL);
SDL_FreeSurface(sdl_surf);
+ free(icon);
}
OSystem::MutexRef OSystem_SDL::createMutex(void) {
@@ -515,7 +551,7 @@ void OSystem_SDL::mixerProducerThread() {
// Generate samples and put them into the next buffer
nextSoundBuffer = _activeSoundBuf ^ 1;
_mixer->mixCallback(_soundBuffers[nextSoundBuffer], _soundBufSize);
-
+
// Swap buffers
_activeSoundBuf = nextSoundBuffer;
}
@@ -559,7 +595,7 @@ void OSystem_SDL::deinitThreadedMixer() {
SDL_CondBroadcast(_soundCond);
SDL_WaitThread(_soundThread, NULL);
- // Kill the mutex & cond variables.
+ // Kill the mutex & cond variables.
// Attention: AT this point, the mixer callback must not be running
// anymore, else we will crash!
SDL_DestroyMutex(_soundMutex);
@@ -582,10 +618,10 @@ void OSystem_SDL::mixCallback(void *arg, byte *samples, int len) {
// Lock mutex, to ensure our data is not overwritten by the producer thread
SDL_LockMutex(this_->_soundMutex);
-
+
// Copy data from the current sound buffer
memcpy(samples, this_->_soundBuffers[this_->_activeSoundBuf], len);
-
+
// Unlock mutex and wake up the produced thread
SDL_UnlockMutex(this_->_soundMutex);
SDL_CondSignal(this_->_soundCond);
@@ -645,7 +681,7 @@ void OSystem_SDL::setupMixer() {
// even if it didn't. Probably only happens for "weird" rates, though.
_samplesPerSec = obtained.freq;
debug(1, "Output sample rate: %d Hz", _samplesPerSec);
-
+
// Tell the mixer that we are ready and start the sound processing
_mixer->setOutputRate(_samplesPerSec);
_mixer->setReady(true);
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index 1c1381ec5c..1cc0acbc29 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -209,6 +209,7 @@ public:
virtual Common::SaveFileManager *getSavefileManager();
virtual FilesystemFactory *getFilesystemFactory();
+ virtual void addSysArchivesToSearchSet(Common::SearchSet &s, uint priority = 0);
virtual Common::SeekableReadStream *openConfigFileForReading();
virtual Common::WriteStream *openConfigFileForWriting();
@@ -400,14 +401,13 @@ protected:
void deinitThreadedMixer();
#endif
-
+ FilesystemFactory *_fsFactory;
Common::SaveFileManager *_savefile;
Audio::MixerImpl *_mixer;
SDL_TimerID _timerID;
Common::TimerManager *_timer;
-
protected:
void addDirtyRgnAuto(const byte *buf);
void makeChecksums(const byte *buf);
diff --git a/backends/platform/symbian/AdaptAllMMPs.pl b/backends/platform/symbian/AdaptAllMMPs.pl
index b576bb3993..d7b5642f1c 100644
--- a/backends/platform/symbian/AdaptAllMMPs.pl
+++ b/backends/platform/symbian/AdaptAllMMPs.pl
@@ -27,7 +27,7 @@ chdir("../../../");
"mmp/scummvm_sword1.mmp",
"mmp/scummvm_sword2.mmp",
"mmp/scummvm_touche.mmp",
-
+ "mmp/scummvm_tinsel.mmp",
# Target Platform Project Files
"S60/ScummVM_S60.mmp",
@@ -83,6 +83,9 @@ my @excludes_graphics = (
"iff.cpp"
);
+my @excludes_gui = (
+);
+
# the USE_ARM_* defines not parsed correctly, exclude manually:
my @excludes_scumm = (
".*ARM.*", # the *ARM.s files are added in .mpp files based on WINS/ARM build!
@@ -95,7 +98,7 @@ my @excludes_scumm = (
#arseModule(mmpStr, dirStr, ifdefArray, [exclusionsArray])
ParseModule("_base", "base", \@section_empty); # now in ./TRG/ScummVM_TRG.mmp, these never change anyways...
ParseModule("_base", "common", \@section_empty);
-ParseModule("_base", "gui", \@section_empty);
+ParseModule("_base", "gui", \@section_empty, \@excludes_gui);
ParseModule("_base", "graphics", \@section_empty, \@excludes_graphics);
ParseModule("_base", "sound", \@section_empty, \@excludes_snd);
@@ -103,22 +106,23 @@ chdir("engines/");
ParseModule("_scumm", "scumm", \@sections_scumm, \@excludes_scumm );
ParseModule("_queen", "queen", \@section_empty);
ParseModule("_agos", "agos", \@section_empty);
-ParseModule("_sky", "sky", \@section_empty);
-ParseModule("_gob", "gob", \@section_empty);
+ParseModule("_sky", "sky", \@section_empty);
+ParseModule("_gob", "gob", \@section_empty);
ParseModule("_saga", "saga", \@section_empty);
ParseModule("_kyra", "kyra", \@section_empty);
ParseModule("_sword1", "sword1", \@section_empty);
ParseModule("_sword2", "sword2", \@section_empty);
ParseModule("_lure", "lure", \@section_empty);
ParseModule("_cine", "cine", \@section_empty);
-ParseModule("_agi", "agi", \@section_empty);
+ParseModule("_agi", "agi", \@section_empty);
ParseModule("_touche", "touche", \@section_empty);
ParseModule("_parallaction","parallaction",\@section_empty);
ParseModule("_cruise", "cruise", \@section_empty);
ParseModule("_drascula","drascula", \@section_empty);
ParseModule("_igor", "igor", \@section_empty);
ParseModule("_made", "made", \@section_empty);
-ParseModule("_m4", "m4", \@section_empty);
+ParseModule("_m4", "m4", \@section_empty);
+ParseModule("_tinsel", "tinsel", \@section_empty);
print "
=======================================================================================
Done. Enjoy :P
diff --git a/backends/platform/symbian/BuildPackageUpload_AllVersions.pl b/backends/platform/symbian/BuildPackageUpload_AllVersions.pl
index 94edbf4fcf..ba8afe5084 100644
--- a/backends/platform/symbian/BuildPackageUpload_AllVersions.pl
+++ b/backends/platform/symbian/BuildPackageUpload_AllVersions.pl
@@ -443,6 +443,10 @@ my $header = "
PrintMessage("Cleaning for $Target") if (!$ReallyQuiet);
system("bldmake bldfiles > NUL 2> NUL");
PrintErrorMessage("'bldmake bldfiles' exited with value " . ($? >> 8)) if ($? >> 8);
+
+ system("abld MAKEFILE $TargetName > NUL 2> NUL");
+ PrintErrorMessage("'abld MAKEFILE $TargetName' exited with value " . ($? >> 8)) if ($? >> 8);
+
system("abld CLEAN $TargetName UREL > NUL 2> NUL");
PrintErrorMessage("'abld CLEAN $TargetName urel' exited with value " . ($? >> 8)) if ($? >> 8);
# remove file so we are sure that after .lib generation we have a fresh copy!
@@ -455,10 +459,10 @@ my $header = "
my $OldSize = (-s $build_log_err);
$Redirection = ($RedirectSTDERR ? "2>> $build_log_err" : "");
- system("abld BUILD $TargetName UREL $Redirection >> $build_log_out");
+ system("abld TARGET $TargetName UREL $Redirection >> $build_log_out");
$OK = 0 if ($? >> 8);
# print " STDERR: ".((-s $build_log_err)-$OldSize)." bytes output written to $build_log_err\n+--------------------------------------------------------------------------------------\n" if ($OldSize != (-s $build_log_err));
- PrintErrorMessage("'abld BUILD $TargetName UREL' exited with value " . ($? >> 8)) if ($? >> 8);
+ PrintErrorMessage("'abld TARGET $TargetName UREL' exited with value " . ($? >> 8)) if ($? >> 8);
return 0 if (!$OK); # ABLD always returns ok :( grr
PrintMessage("Done.") if (!$ReallyQuiet);
@@ -475,7 +479,7 @@ my $header = "
}
else
{
- PrintErrorMessage("'abld BUILD $TargetName UREL' apparently failed.");
+ PrintErrorMessage("'abld TARGET $TargetName UREL' apparently failed.");
if ($HaltOnError)
{
PrintErrorMessage("Halting on error as requested!");
diff --git a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
index 12e5f8f0c4..8ba743674d 100644
--- a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
+++ b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl
@@ -3,14 +3,15 @@
@WorkingEngines = qw(
scumm agos sky queen gob saga drascula
- kyra lure agi touche parallaction
+ kyra lure agi touche parallaction cine
+ cruise igor made m4 tinsel sword1 sword2
);
+
@TestingEngines = qw(
- cruise igor made m4 cine
+
);
- @BrokenEngines = qw(
- sword1
- sword2
+
+ @BrokenEngines = qw(
);
@EnablableEngines = (@WorkingEngines, @TestingEngines);
@@ -29,20 +30,7 @@
# these are normally enabled for each variation
#$DefaultFeatures = qw(zlib,mad);
- $DefaultFeatures = qw(zlib,mad,tremor);
-
-
- # you can use these below for speed & clarity or override with custom settings
- $DefaultTopMacros = "
- MACRO USE_ZLIB // LIB:zlib.lib
- MACRO USE_MAD // LIB:libmad.lib
- MACRO USE_TREMOR // LIB:libtremor.lib
- ";
-
- $DefaultBottomMacros = "
- MACRO DISABLE_SWORD1 // LIB:scummvm_sword1.lib
- MACRO DISABLE_SWORD2 // LIB:scummvm_sword2.lib
- ";
+ $DefaultFeatures = qw(zlib,mad,tremor);
##################################################################################################################
##
@@ -186,6 +174,44 @@
# now you can add $VariationSets only built on this PC below this line :)
}
+ elsif ($ENV{'COMPUTERNAME'} eq "EMBEDDEV-LAPE") #################################################################
+ {
+ $Producer = "AnotherGuest";
+ $RedirectSTDERR = 1;
+ $HaltOnError = 0;
+ $SkipExistingPackages = 1;
+ $ReallyQuiet = 1;
+
+ #$FTP_Host = "host.com";
+ #$FTP_User = "ag@host.com";
+ #$FTP_Pass = "password";
+ #$FTP_Dir = "cvsbuilds";
+
+ #$SDK_RootDirs{'UIQ2'}= "D:\\UIQ2";
+ $SDK_RootDirs{'UIQ3'}= "G:\\UIQ3";
+ #$SDK_RootDirs{'S60v1'}= "D:\\S60v1";
+ #$SDK_RootDirs{'S60v2'}= "D:\\S60v2";
+ $SDK_RootDirs{'S60v3'}= "G:\\S60_3rd_FP1";
+ #$SDK_RootDirs{'S80'}= "D:\\S80";
+ #$SDK_RootDirs{'S90'}= "D:\\S90";
+ $ECompXL_BinDir= "D:\\ECompXL\\";
+ if (0) # so we can turn them on/off easily
+ {
+# $SDK_LibraryDirs{'ALL'}{'zlib.lib'} = "C:\\S\\zlib-1.2.2\\epoc";
+# $SDK_LibraryDirs{'ALL'}{'libmad.lib'} = "C:\\S\\libmad-0.15.1b\\group";
+# $SDK_LibraryDirs{'ALL'}{'libtremor.lib'}= "C:\\tremor\\epoc";
+ $SDK_LibraryDirs{'UIQ2'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\UIQ";
+ $SDK_LibraryDirs{'S60v1'}{'esdl.lib'} = $SDK_LibraryDirs{'S60v2'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S60";
+ $SDK_LibraryDirs{'S80'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S80";
+ $SDK_LibraryDirs{'S90'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S90";
+ $SDK_LibraryDirs{'S60v3'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S60\\S60V3";
+ $SDK_LibraryDirs{'UIQ3'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\UIQ\\UIQ3";
+ #$SDK_LibraryDirs{'ALL'}{'libmpeg2.lib'} = "C:\\S\\mpeg2dec-0.4.0\\epoc";
+ }
+
+ # now you can add $VariationSets only built on this PC below this line :)
+
+ }
else #########################################################################################################
{
print "ERROR: Computer name ".$ENV{'COMPUTERNAME'}." not recognized! Plz edit _LocalSettings.pl!";
@@ -245,15 +271,11 @@
}
# below here you could specify weird & experimental combinations, non-ready engines
- # a small version of the saga engine, because it is so big (no tremor,mad,zlib)
- #$VariationSets{'ALL'}{'saga_mini'} = "saga";
+ # Separate version for the broken sword engines (1&2)
+ $VariationSets{'ALL'}{'brokensword'} = "$DefaultFeatures sword1 sword2";
- # a smaller version of scumm without support for v7, v8 and HE games
- #$VariationSets{'ALL'}{'scumm_no78he'} = "$DefaultFeatures scumm";
-
- # maybe you feel lucky and want to test the sword engines? :P
- #$VariationSets{'S60v2'}{'test_sword'} = "$DefaultFeatures mpeg2 sword1 sword2";
- #$VariationSets{'UIQ2'}{'test_sword'} = "$DefaultFeatures mpeg2 sword1 sword2";
+ # Separate version for Scumm games (COMI) since memory usage might be high
+ $VariationSets{'ALL'}{'scumm'} = "$DefaultFeatures scumm scumm_7_8 he";
# for mega-fast-testing only plz! Warning: contains to engines!
#$VariationSets{'ALL'}{'fast_empty'} = "";
diff --git a/backends/platform/symbian/README b/backends/platform/symbian/README
index db46dae8de..1e011ec4a1 100644
--- a/backends/platform/symbian/README
+++ b/backends/platform/symbian/README
@@ -8,6 +8,18 @@
Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson
$Id$
+Using parts of snprintf.c by
+Mark Martinec <mark.martinec@ijs.si>, April 1999, June 2000
+Copyright © 1999,2000,2001,2002 Mark Martinec. All rights reserved.
+under these conditions:
+"Terms and conditions ...
+
+This program is free software; it is dual licensed, the terms of the "Frontier Artistic License" or
+the "GNU General Public License" can be chosen at your discretion.
+The chosen license then applies solely and in its entirety.
+Both licenses come with this Kit."
+
+
About ScummVM
--------------
diff --git a/backends/platform/symbian/S60/ScummVM_S60.mmp.in b/backends/platform/symbian/S60/ScummVM_S60.mmp.in
index 099b33ed95..35632d9c95 100644
--- a/backends/platform/symbian/S60/ScummVM_S60.mmp.in
+++ b/backends/platform/symbian/S60/ScummVM_S60.mmp.in
@@ -93,6 +93,7 @@ SOURCE backends\platform\symbian\src\ScummApp.cpp
SOURCE gui\Key.cpp
SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
+SOURCE gui\Dialog.cpp
// Special for graphics
source graphics\iff.cpp
diff --git a/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v1.pkg b/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v1.pkg
index bf3c69ae08..91649727df 100644
--- a/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v1.pkg
+++ b/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v1.pkg
@@ -16,7 +16,7 @@
; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
;
; $URL:$
-; $Id:$
+; $Id$
;
;
@@ -28,7 +28,7 @@
;&EN
; UID is the app's UID
-#{"ScummVM S60v1"},(0x101f9b57),0,120,0
+#{"ScummVM S60v1"},(0x101f9b57),0,130,0
; Platform type
(0x101F6F88), 0, 0, 0, {"Series60ProductID"}
diff --git a/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v2.pkg b/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v2.pkg
index 3f88ec918c..4547af0597 100644
--- a/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v2.pkg
+++ b/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v2.pkg
@@ -27,7 +27,7 @@
;&EN
; UID is the app's UID
-#{"ScummVM S60v2"},(0x101f9b57),0,120,0
+#{"ScummVM S60v2"},(0x101f9b57),0,130,0
; Platform type
(0x101F6F88), 0, 0, 0, {"Series60ProductID"}
diff --git a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in
index 8daf76138c..fae74a425a 100644
--- a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in
+++ b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in
@@ -116,6 +116,7 @@ SOURCE backends\platform\symbian\src\ScummApp.cpp
SOURCE gui\Key.cpp
SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
+SOURCE gui\Dialog.cpp
// Special for graphics
source graphics\iff.cpp
diff --git a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg
index 6bd1fbd047..1898ac1b58 100644
--- a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg
+++ b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg
@@ -34,7 +34,7 @@
:"ScummVM"
; UID is the app's UID
-#{"ScummVM S60v3"},(0xA0000657),0,120,0
+#{"ScummVM S60v3"},(0xA0000657),0,13,0
;Supports Series 60 v 3.0
[0x101F7961], 0, 0, 0, {"Series60ProductID"}
@@ -63,7 +63,7 @@
"..\..\..\..\dists\engine-data\sky.cpt"-"c:\data\scummvm\sky.cpt"
"..\..\..\..\dists\engine-data\igor.tbl"-"c:\data\scummvm\igor.tbl"
"..\..\..\..\dists\engine-data\lure.dat"-"c:\data\scummvm\lure.dat"
-"..\..\..\..\dists\engine-data\drascula.dat"-"c:\data\drascula.dat"
+"..\..\..\..\dists\engine-data\drascula.dat"-"c:\data\scummvm\drascula.dat"
; Config/log files: 'empty' will automagically be removed on uninstall
""-"c:\data\scummvm\scummvm.ini",FILENULL
diff --git a/backends/platform/symbian/S80/ScummVM_S80.mmp.in b/backends/platform/symbian/S80/ScummVM_S80.mmp.in
index 95879dd2af..1c8076fdc3 100644
--- a/backends/platform/symbian/S80/ScummVM_S80.mmp.in
+++ b/backends/platform/symbian/S80/ScummVM_S80.mmp.in
@@ -91,6 +91,7 @@ SOURCE backends\platform\symbian\src\ScummApp.cpp
SOURCE gui\Key.cpp
SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
+SOURCE gui\Dialog.cpp
// Special for graphics
source graphics\iff.cpp
diff --git a/backends/platform/symbian/S80/scummvm-CVS-SymbianS80.pkg b/backends/platform/symbian/S80/scummvm-CVS-SymbianS80.pkg
index 29e318a479..c6b3e6f82f 100644
--- a/backends/platform/symbian/S80/scummvm-CVS-SymbianS80.pkg
+++ b/backends/platform/symbian/S80/scummvm-CVS-SymbianS80.pkg
@@ -28,7 +28,7 @@
;&EN
; UID is the app's UID
-#{"ScummVM S80"},(0x101f9b57),0,120,0
+#{"ScummVM S80"},(0x101f9b57),0,130,0
; Platform type -- disabled: seems to be causing trouble
;(0x101F8ED2), 0, 0, 0, {"Series80ProductID"}
diff --git a/backends/platform/symbian/S90/Scummvm_S90.mmp.in b/backends/platform/symbian/S90/Scummvm_S90.mmp.in
index 47a3d9a1d4..8ace71b190 100644
--- a/backends/platform/symbian/S90/Scummvm_S90.mmp.in
+++ b/backends/platform/symbian/S90/Scummvm_S90.mmp.in
@@ -91,6 +91,7 @@ SOURCE backends\platform\symbian\src\ScummApp.cpp
SOURCE gui\Key.cpp
SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
+SOURCE gui\Dialog.cpp
// Special for graphics
source graphics\iff.cpp
diff --git a/backends/platform/symbian/S90/scummvm-CVS-SymbianS90.pkg b/backends/platform/symbian/S90/scummvm-CVS-SymbianS90.pkg
index 0173da7699..b578019979 100644
--- a/backends/platform/symbian/S90/scummvm-CVS-SymbianS90.pkg
+++ b/backends/platform/symbian/S90/scummvm-CVS-SymbianS90.pkg
@@ -28,7 +28,7 @@
;&EN
; UID is the app's UID
-#{"ScummVM S90"},(0x101f9b57),0,120,0
+#{"ScummVM S90"},(0x101f9b57),0,130,0
; Platform type -- disabled: seems to be causing trouble
;(0x101FBE04), 0, 0, 0, {"Series90ProductID"}
diff --git a/backends/platform/symbian/UIQ2/ScummVM_UIQ2.mmp.in b/backends/platform/symbian/UIQ2/ScummVM_UIQ2.mmp.in
index e9dff7b94f..9fab248799 100644
--- a/backends/platform/symbian/UIQ2/ScummVM_UIQ2.mmp.in
+++ b/backends/platform/symbian/UIQ2/ScummVM_UIQ2.mmp.in
@@ -89,6 +89,7 @@ SOURCE backends\platform\symbian\src\ScummApp.cpp
SOURCE gui\Key.cpp
SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
+SOURCE gui\Dialog.cpp
// Special for graphics
source graphics\iff.cpp
diff --git a/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2.pkg b/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2.pkg
index aca927eadd..a8b02d4099 100644
--- a/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2.pkg
+++ b/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2.pkg
@@ -16,7 +16,7 @@
; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
;
; $URL:$
-; $Id:$
+; $Id$
;
;
@@ -28,7 +28,7 @@
;&EN
; UID is the app's UID
-#{"ScummVM UIQ2"},(0x101f9b57),0,100,0
+#{"ScummVM UIQ2"},(0x101f9b57),0,130,0
; Platform type
(0x101F617B), 2, 0, 0, {"UIQ20ProductID"}
diff --git a/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2_SE.pkg b/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2_SE.pkg
index ecca51bd26..2d08bd01b2 100644
--- a/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2_SE.pkg
+++ b/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2_SE.pkg
@@ -6,7 +6,7 @@
;&EN
; UID is the app's UID
-#{"ScummVM SE"},(0x101f9b57),0,110,0
+#{"ScummVM SE"},(0x101f9b57),0,130,0
; Platform type
(0x101F617B), 2, 0, 0, {"UIQ20ProductID"}
diff --git a/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in b/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in
index cf3d0c1d7b..6053a72182 100644
--- a/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in
+++ b/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in
@@ -117,6 +117,7 @@ SOURCE backends\platform\symbian\src\ScummApp.cpp
SOURCE gui\Key.cpp
SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
+SOURCE gui\Dialog.cpp
// Special for graphics
source graphics\iff.cpp
diff --git a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg
index 0883c88a21..cdeb83f192 100644
--- a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg
+++ b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg
@@ -32,7 +32,7 @@
:"ScummVM"
; UID is the app's UID
-#{"ScummVM UIQ3"},(0xA0000657),0,120,0
+#{"ScummVM UIQ3"},(0xA0000657),0,13,0
; ProductID for UIQ 3.0
; Product/platform version UID, Major, Minor, Build, Product ID
diff --git a/backends/platform/symbian/mmp/scummvm_base.mmp.in b/backends/platform/symbian/mmp/scummvm_base.mmp.in
index d1c8878d4b..3277e34ba3 100644
--- a/backends/platform/symbian/mmp/scummvm_base.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_base.mmp.in
@@ -85,7 +85,6 @@ SOURCEPATH ..\..\..\..\gui
//SOURCE KeysDialog.cpp
//SOURCE Actions.cpp
-
SOURCEPATH ..\..\..\..\sound
//START_AUTO_OBJECTS_SOUND_//
@@ -108,7 +107,8 @@ SOURCE backends\saves\savefile.cpp
SOURCE backends\saves\default\default-saves.cpp
SOURCE backends\saves\compressed\compressed-saves.cpp
SOURCE engines\engine.cpp
-
-
-// backend specific includes
+SOURCE engines\dialogs.cpp
+SOURCE backends\fs\abstract-fs.cpp
+SOURCE backends\fs\symbian\symbianstream.cpp
// backend specific includes
+
diff --git a/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in b/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in
new file mode 100644
index 0000000000..3f68ec086e
--- /dev/null
+++ b/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in
@@ -0,0 +1,56 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL
+ * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System
+ * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer
+ * Copyright (C) 2005-2006 The ScummVM project
+ *
+ * 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.
+ *
+ */
+
+//
+// EPOC MMP makefile project for ScummVM
+//
+
+// *** Definitions
+
+TARGET scummvm_tinsel.lib
+TARGETTYPE lib
+OPTION MSVC /QIfist /Ob1 /Oy /GF // /QIfist disables use of __ftol2 to avoid linker probs with MS libc: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcrefQIfistSuppress_ftol.asp
+OPTION GCC -Wno-multichar -Wno-reorder // don't optimize for ARM, platform way too sensitive for that :( just turn off some common warnings
+OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char
+ALWAYS_BUILD_AS_ARM
+
+//START_AUTO_MACROS_SLAVE//
+
+// empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_MACROS_SLAVE//
+
+// *** SOURCE files
+
+SOURCEPATH ..\..\..\..\engines\tinsel
+
+//START_AUTO_OBJECTS_TINSEL_//
+
+ // empty base file, will be updated by Perl build scripts
+
+//STOP_AUTO_OBJECTS_TINSEL_//
+
+// *** Include paths
+
+USERINCLUDE ..\..\..\..\engines
+USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src
+SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src
diff --git a/backends/platform/symbian/src/SymbianActions.cpp b/backends/platform/symbian/src/SymbianActions.cpp
index 60e402632f..e71b242329 100644
--- a/backends/platform/symbian/src/SymbianActions.cpp
+++ b/backends/platform/symbian/src/SymbianActions.cpp
@@ -153,7 +153,7 @@ void SymbianActions::initInstanceGame() {
// Save
- if (is_simon || is_sword2 || is_gob || is_kyra || is_touche || is_feeble)
+ if (is_simon || is_sword2 || is_gob || is_kyra || is_feeble)
_action_enabled[ACTION_SAVE] = false;
else {
_action_enabled[ACTION_SAVE] = true;
diff --git a/backends/platform/symbian/src/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp
index 0ce44d1704..23876c5ec1 100644
--- a/backends/platform/symbian/src/SymbianOS.cpp
+++ b/backends/platform/symbian/src/SymbianOS.cpp
@@ -24,10 +24,12 @@
#include <eikenv.h> // for CEikonEnv::Static() @ Symbian::FatalError()
#include <sdlapp.h> // for CSDLApp::GetExecutablePathCStr() @ Symbian::GetExecutablePath()
+#include <bautils.h>
#include "backends/fs/symbian/symbian-fs-factory.h"
#include "backends/platform/symbian/src/SymbianOS.h"
#include "backends/platform/symbian/src/SymbianActions.h"
+#include "backends/saves/default/default-saves.h"
#include "common/config-manager.h"
#include "common/events.h"
#include "common/file.h"
@@ -45,16 +47,7 @@
#define DEFAULT_CONFIG_FILE "scummvm.ini"
-
-
-#define KInputBufferLength 128
-// Symbian libc file functionality in order to provide shared file handles
-struct TSymbianFileEntry {
- RFile iFileHandle;
- char iInputBuffer[KInputBufferLength];
- TInt iInputBufferLen;
- TInt iInputPos;
-};
+#define DEFAULT_SAVE_PATH "Savegames"
#define FILE void
@@ -123,10 +116,6 @@ void OSystem_SDL_Symbian::setFeatureState(Feature f, bool enable) {
}
}
-FilesystemFactory *OSystem_SDL_Symbian::getFilesystemFactory() {
- return &SymbianFilesystemFactory::instance();
-}
-
static Common::String getDefaultConfigFileName() {
char configFile[MAXPATHLEN];
strcpy(configFile, Symbian::GetExecutablePath());
@@ -135,36 +124,48 @@ static Common::String getDefaultConfigFileName() {
}
Common::SeekableReadStream *OSystem_SDL_Symbian::openConfigFileForReading() {
- Common::File *confFile = new Common::File();
- assert(confFile);
- if (!confFile->open(getDefaultConfigFileName())) {
- delete confFile;
- confFile = 0;
- }
- return confFile;
+ Common::FilesystemNode file(getDefaultConfigFileName());
+ return file.openForReading();
}
Common::WriteStream *OSystem_SDL_Symbian::openConfigFileForWriting() {
- Common::DumpFile *confFile = new Common::DumpFile();
- assert(confFile);
- if (!confFile->open(getDefaultConfigFileName())) {
- delete confFile;
- confFile = 0;
- }
- return confFile;
+ Common::FilesystemNode file(getDefaultConfigFileName());
+ return file.openForWriting();
}
-
OSystem_SDL_Symbian::zoneDesc OSystem_SDL_Symbian::_zones[TOTAL_ZONES] = {
{ 0, 0, 320, 145 },
{ 0, 145, 150, 55 },
{ 150, 145, 170, 55 }
};
OSystem_SDL_Symbian::OSystem_SDL_Symbian() :_channels(0),_stereo_mix_buffer(0) {
+ _RFs = &CEikonEnv::Static()->FsSession();
+ _fsFactory = new SymbianFilesystemFactory();
}
void OSystem_SDL_Symbian::initBackend() {
+ // First set the extrapath (for installed dat files etc)
ConfMan.set("extrapath", Symbian::GetExecutablePath());
+
+ // Calculate the default savepath
+ Common::String savePath;
+ savePath = Symbian::GetExecutablePath();
+ savePath += DEFAULT_SAVE_PATH "\\";
+ _savefile = new DefaultSaveFileManager(savePath);
+
+ // If savepath has not already been set then set it
+ if (!ConfMan.hasKey("savepath")) {
+ ConfMan.set("savepath", savePath);
+
+ }
+
+ // Ensure that the current set path (might have been altered by the user) exists
+ Common::String currentPath = ConfMan.get("savepath");
+ TFileName fname;
+ TPtrC8 ptr((const unsigned char*)currentPath.c_str(),currentPath.size());
+ fname.Copy(ptr);
+ BaflUtils::EnsurePathExistsL(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), fname);
+
ConfMan.setBool("FM_high_quality", false);
#if !defined(S60) || defined(S60V3) // S60 has low quality as default
ConfMan.setBool("FM_medium_quality", true);
@@ -488,223 +489,60 @@ void OSystem_SDL_Symbian::initZones() {
}
}
-FILE* symbian_fopen(const char* name, const char* mode) {
- TSymbianFileEntry* fileEntry = new TSymbianFileEntry;
- fileEntry->iInputPos = KErrNotFound;
-
- if (fileEntry != NULL) {
- TInt modeLen = strlen(mode);
-
- TPtrC8 namePtr((unsigned char*) name, strlen(name));
- TFileName tempFileName;
- tempFileName.Copy(namePtr);
-
- TInt fileMode = EFileRead;
-
- if (mode[0] == 'a')
- fileMode = EFileWrite;
-
- if (!((modeLen > 1 && mode[1] == 'b') || (modeLen > 2 && mode[2] == 'b'))) {
- fileMode |= EFileStreamText;
- }
-
- if ((modeLen > 1 && mode[1] == '+') || (modeLen > 2 && mode[2] == '+')) {
- fileMode = fileMode| EFileWrite;
- }
-
- fileMode = fileMode| EFileShareAny;
-
- switch(mode[0]) {
- case 'a':
- if (fileEntry->iFileHandle.Open(CEikonEnv::Static()->FsSession(), tempFileName, fileMode) != KErrNone) {
- if (fileEntry->iFileHandle.Create(CEikonEnv::Static()->FsSession(), tempFileName, fileMode) != KErrNone) {
- delete fileEntry;
- fileEntry = NULL;
- }
- }
- break;
- case 'r':
- if (fileEntry->iFileHandle.Open(CEikonEnv::Static()->FsSession(), tempFileName, fileMode) != KErrNone) {
- delete fileEntry;
- fileEntry = NULL;
- }
- break;
-
- case 'w':
- if (fileEntry->iFileHandle.Replace(CEikonEnv::Static()->FsSession(), tempFileName, fileMode) != KErrNone) {
- delete fileEntry;
- fileEntry = NULL;
- }
- break;
- }
+RFs& OSystem_SDL_Symbian::FsSession() {
+ return *_RFs;
+}
+
+// Symbian bsearch implementation is flawed
+void* scumm_bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) {
+ // Perform binary search
+ size_t lo = 0;
+ size_t hi = nmemb;
+ while (lo < hi) {
+ size_t mid = (lo + hi) / 2;
+ const void *p = ((const char *)base) + mid * size;
+ int tmp = (*compar)(key, p);
+ if (tmp < 0)
+ hi = mid;
+ else if (tmp > 0)
+ lo = mid + 1;
+ else
+ return (void *)p;
}
- return (FILE*) fileEntry;
-}
-
-void symbian_fclose(FILE* handle) {
- ((TSymbianFileEntry*)(handle))->iFileHandle.Close();
- delete (TSymbianFileEntry*)(handle);
+ return NULL;
}
-size_t symbian_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
- TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle));
- TUint32 totsize = size*numItems;
- TPtr8 pointer ( (unsigned char*) ptr, totsize);
-
- // Nothing cached and we want to load at least KInputBufferLength bytes
- if(totsize >= KInputBufferLength) {
- TUint32 totLength = 0;
- if(entry->iInputPos != KErrNotFound)
- {
- TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer+entry->iInputPos, entry->iInputBufferLen - entry->iInputPos, KInputBufferLength);
- pointer.Append(cacheBuffer);
- entry->iInputPos = KErrNotFound;
- totLength+=pointer.Length();
- pointer.Set(totLength+(unsigned char*) ptr, 0, totsize-totLength);
- }
-
- entry->iFileHandle.Read(pointer);
- totLength+=pointer.Length();
-
- pointer.Set((unsigned char*) ptr, totLength, totsize);
-
- }
- else {
- // Nothing in buffer
- if(entry->iInputPos == KErrNotFound) {
- TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer, KInputBufferLength);
- entry->iFileHandle.Read(cacheBuffer);
-
- if(cacheBuffer.Length() >= totsize) {
- pointer.Copy(cacheBuffer.Left(totsize));
- entry->iInputPos = totsize;
- entry->iInputBufferLen = cacheBuffer.Length();
- }
- else {
- pointer.Copy(cacheBuffer);
- entry->iInputPos = KErrNotFound;
- }
-
- }
- else {
- TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer, entry->iInputBufferLen, KInputBufferLength);
-
- if(entry->iInputPos+totsize < entry->iInputBufferLen) {
- pointer.Copy(cacheBuffer.Mid(entry->iInputPos, totsize));
- entry->iInputPos+=totsize;
- }
- else {
-
- pointer.Copy(cacheBuffer.Mid(entry->iInputPos, entry->iInputBufferLen-entry->iInputPos));
- cacheBuffer.SetLength(0);
- entry->iFileHandle.Read(cacheBuffer);
-
- if(cacheBuffer.Length() >= totsize-pointer.Length()) {
- TUint32 restSize = totsize-pointer.Length();
- pointer.Append(cacheBuffer.Left(restSize));
- entry->iInputPos = restSize;
- entry->iInputBufferLen = cacheBuffer.Length();
- }
- else {
- pointer.Append(cacheBuffer);
- entry->iInputPos = KErrNotFound;
- }
- }
- }
- }
-
- return pointer.Length()/size;
-}
-
-size_t symbian_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) {
- TPtrC8 pointer( (unsigned char*) ptr, size*numItems);
-
- ((TSymbianFileEntry*)(handle))->iInputPos = KErrNotFound;
- if (((TSymbianFileEntry*)(handle))->iFileHandle.Write(pointer) == KErrNone) {
- return numItems;
- }
-
- return 0;
-}
-
-bool symbian_feof(FILE* handle) {
- TInt pos = 0;
- TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle));
-
- if (entry->iFileHandle.Seek(ESeekCurrent, pos) == KErrNone) {
-
- TInt size = 0;
- if (entry->iFileHandle.Size(size) == KErrNone) {
- if(entry->iInputPos == KErrNotFound && pos == size)
- return true;
-
- if(entry->iInputPos != KErrNotFound && pos == size && entry->iInputPos == entry->iInputBufferLen)
- return true;
-
- return false;
- }
- }
- return true;
-}
-
-long int symbian_ftell(FILE* handle) {
- TInt pos = 0;
- TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle));
-
- entry->iFileHandle.Seek(ESeekCurrent, pos);
- if(entry->iInputPos != KErrNotFound)
- {
- pos+=(entry->iInputPos - entry->iInputBufferLen);
- }
- return pos;
-}
-
-int symbian_fseek(FILE* handle, long int offset, int whence) {
-
- TSeek seekMode = ESeekStart;
- TInt pos = offset;
- TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle));
-
- switch(whence) {
- case SEEK_SET:
- seekMode = ESeekStart;
- break;
- case SEEK_CUR:
- seekMode = ESeekCurrent;
- if(entry->iInputPos != KErrNotFound) {
- pos+=(entry->iInputPos - entry->iInputBufferLen);
- }
- break;
- case SEEK_END:
- seekMode = ESeekEnd;
- break;
-
- }
-
- entry->iInputPos = KErrNotFound;
-
- return entry->iFileHandle.Seek(seekMode, pos);
-}
-
-void symbian_clearerr(FILE* /*handle*/) {
+extern "C"
+{
+// Include the snprintf and vsnprintf implementations as 'C' code
+#include "vsnprintf.h"
}
/** Vibration support */
#ifdef USE_VIBRA_SE_PXXX
void OSystem_SDL_Symbian::initializeVibration() {
- _vibrationApi = SonyEricsson::CVibration::NewL();
+#ifdef UIQ3
+#else
+#endif
}
void OSystem_SDL_Symbian::vibrationOn(int vibraLength) {
- // initialize?
+#ifdef UIQ3
+ // initialize?
if (!_vibrationApi) _vibrationApi = SonyEricsson::CVibration::NewL();
// do it!
_vibrationApi->VibrationOn(1, 1, vibraLength);
+#else
+
+#endif
}
void OSystem_SDL_Symbian::vibrationOff() {
+#ifdef UIQ3
+#else
_vibrationApi->VibrationOff();
+#endif
}
#endif // USE_SE_PXX_VIBRA
diff --git a/backends/platform/symbian/src/SymbianOS.h b/backends/platform/symbian/src/SymbianOS.h
index 68a6fb492f..03d7fb972c 100644
--- a/backends/platform/symbian/src/SymbianOS.h
+++ b/backends/platform/symbian/src/SymbianOS.h
@@ -27,12 +27,8 @@
#include "backends/platform/sdl/sdl.h"
-/** Vibration support */
-#ifdef USE_VIBRA_SE_PXXX
-#include <vibration.h>
-#endif
-
#define TOTAL_ZONES 3
+class RFs;
class OSystem_SDL_Symbian : public OSystem_SDL {
public:
@@ -62,6 +58,9 @@ public:
// Overloaded from SDL_Commmon
void quit();
+
+ // Returns reference to File session
+ RFs& FsSession();
protected:
//
// The mixer callback function, passed on to OSystem::setSoundCallback().
@@ -70,7 +69,6 @@ protected:
//
static void symbianMixCallback(void *s, byte *samples, int len);
- virtual FilesystemFactory *getFilesystemFactory();
virtual Common::SeekableReadStream *openConfigFileForReading();
virtual Common::WriteStream *openConfigFileForWriting();
@@ -134,6 +132,7 @@ protected:
} zoneDesc;
static zoneDesc _zones[TOTAL_ZONES];
+ RFs* _RFs;
};
#endif
diff --git a/backends/platform/symbian/src/main_features.inl b/backends/platform/symbian/src/main_features.inl
deleted file mode 100644
index 30bbbea52c..0000000000
--- a/backends/platform/symbian/src/main_features.inl
+++ /dev/null
@@ -1,92 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL
- * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System
- * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer
- * Copyright (C) 2005-2006 The ScummVM project
- *
- * 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.
- *
- */
-
-#ifdef USE_VIBRA_SE_PXXX
- "Vibra "
-#endif
- "\n"
-
-// we want a list of supported engines visible in the program,
-// because we also release special builds with only one engine
-#ifdef ENABLE_SCUMM
- "SCUMM "
-#endif
-#ifdef ENABLE_AGOS
- "AGOS "
-#endif
-#ifdef ENABLE_SKY
- "Sky "
-#endif
-#ifdef ENABLE_QUEEN
- "Queen "
-#endif
-#ifdef ENABLE_GOB
- "Gob "
-#endif
-#ifdef ENABLE_SAGA
- "Saga "
-#endif
-#ifdef ENABLE_KYRA
- "Kyra "
-#endif
-#ifdef ENABLE_SWORD1
- "Sword1 "
-#endif
-#ifdef ENABLE_SWORD2
- "Sword2 "
-#endif
-#ifdef ENABLE_CINE
- "Cine "
-#endif
-#ifdef ENABLE_LURE
- "Lure "
-#endif
-#ifdef ENABLE_AGI
- "AGI "
-#endif
-#ifdef ENABLE_TOUCHE
- "Touche "
-#endif
-#ifdef ENABLE_DRASCULA
- "Drascula "
-#endif
-#ifdef ENABLE_IGOR
- "Igor "
-#endif
-#ifdef ENABLE_PARALLACTION
- "Parallaction "
-#endif
-#ifdef ENABLE_CRUISE
- "Cruise "
-#endif
-#ifdef ENABLE_MADE
- "MADE "
-#endif
-#ifdef ENABLE_M4
- "M4 "
-#endif
-
-
-
-
-
-
diff --git a/backends/platform/symbian/src/portdefs.h b/backends/platform/symbian/src/portdefs.h
index 4577824b33..ab8333c986 100644
--- a/backends/platform/symbian/src/portdefs.h
+++ b/backends/platform/symbian/src/portdefs.h
@@ -35,9 +35,6 @@
#include <e32std.h>
#include <math.h>
-//#define DISABLE_SCALERS // we only need 1x
-//#define DISABLE_HQ_SCALERS
-
#if defined(USE_TREMOR) && !defined(USE_VORBIS)
#define USE_VORBIS // make sure this one is defined together with USE_TREMOR!
#endif
@@ -107,56 +104,35 @@
*/
#elif defined (__WINS__) // WINS
+ extern "C" int symbian_snprintf(char *text, size_t maxlen, const char *fmt, ...);
+ extern "C" int symbian_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap);
+ #define snprintf(buf,len,args...) symbian_snprintf(buf,len,args)
+ #define vsnprintf(buf,len,format,valist) symbian_vsnprintf(buf,len,format,valist)
- // let's just blatantly ignore this for now and just get it to work :P but does n't work from the debug function
- int inline scumm_snprintf (char *str, unsigned long /*n*/, char const *fmt, ...) {
- va_list args;
- va_start(args, fmt);
- vsprintf(str, fmt, args);
- va_end(args);
- return strlen(str);
- }
-
- int inline scumm_vsnprintf (char *str, unsigned long /*n*/, char const *fmt, va_list valist) {
- vsprintf(str, fmt, valist);
- return strlen(str);
- }
-
- #define snprintf scumm_snprintf
- #define vsnprintf scumm_vsnprintf
void* symbian_malloc (size_t _size);
#define malloc symbian_malloc
#else // GCCE and the rest
- #define snprintf(buf,len,args...) sprintf(buf,args)
- #define vsnprintf(buf,len,format,valist) vsprintf(buf,format,valist)
+ extern "C" int symbian_snprintf(char *text, size_t maxlen, const char *fmt, ...);
+ extern "C" int symbian_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap);
+ #define snprintf(buf,len,args...) symbian_snprintf(buf,len,args)
+ #define vsnprintf(buf,len,format,valist) symbian_vsnprintf(buf,len,format,valist)
#endif
#ifndef __WINS__
#define USE_ARM_GFX_ASM
-#define ARM_USE_GFX_ASM
#define USE_ARM_SMUSH_ASM
#define USE_ARM_COSTUME_ASM
#define USE_ARM_SOUND_ASM
#endif
-// somehow nobody has this function...
-#define hypot(a, b) sqrt((a)*(a) + (b)*(b))
// Symbian bsearch implementation is flawed
-void inline *scumm_bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) {
- size_t i;
-
- for (i=0; i < nmemb; i++)
- if (compar(key, (void *)((size_t)base + size * i)) == 0)
- return (void *)((size_t)base + size * i);
- return NULL;
-}
-#define bsearch scumm_bsearch
+void *scumm_bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
+#define bsearch scumm_bsearch
// we cannot include SymbianOS.h everywhere, but this works too (functions code is in SymbianOS.cpp)
namespace Symbian {
extern void FatalError(const char *msg);
extern char* GetExecutablePath();
-#define DYNAMIC_MODULES 1
}
#endif
diff --git a/backends/platform/symbian/src/vsnprintf.h b/backends/platform/symbian/src/vsnprintf.h
new file mode 100644
index 0000000000..5ed04b1980
--- /dev/null
+++ b/backends/platform/symbian/src/vsnprintf.h
@@ -0,0 +1,668 @@
+/*
+ * This is the vsnprintf for scummvm/symbian implementation from the original snprintf.c,
+ * all support functions has been removed and vsnprintf renamed to symbian_vsnprintf
+ * snprintf.c - a portable implementation of snprintf
+ * According to the homepage this function could be licensed as either Frontier Aritistic or GPL.
+ *
+ * AUTHOR
+ * Mark Martinec <mark.martinec@ijs.si>, April 1999.
+ *
+ * Copyright 1999, Mark Martinec. All rights reserved.
+ *
+ * TERMS AND CONDITIONS
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the "Frontier Artistic License" which comes
+ * with this Kit.
+ *
+ * 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 Frontier Artistic License for more details.
+ *
+ * You should have received a copy of the Frontier Artistic License
+ * with this Kit in the file named LICENSE.txt .
+ * If not, I'll be glad to provide one.
+ *
+ * FEATURES
+ * - careful adherence to specs regarding flags, field width and precision;
+ * - good performance for large string handling (large format, large
+ * argument or large paddings). Performance is similar to system's sprintf
+ * and in several cases significantly better (make sure you compile with
+ * optimizations turned on, tell the compiler the code is strict ANSI
+ * if necessary to give it more freedom for optimizations);
+ * - return value semantics per ISO/IEC 9899:1999 ("ISO C99");
+ * - written in standard ISO/ANSI C - requires an ANSI C compiler.
+ *
+ * SUPPORTED CONVERSION SPECIFIERS AND DATA TYPES
+ *
+ * This snprintf only supports the following conversion specifiers:
+ * s, c, d, u, o, x, X, p (and synonyms: i, D, U, O - see below)
+ * with flags: '-', '+', ' ', '0' and '#'.
+ * An asterisk is supported for field width as well as precision.
+ *
+ * Length modifiers 'h' (short int), 'l' (long int),
+ * and 'll' (long long int) are supported.
+ * NOTE:
+ * If macro SNPRINTF_LONGLONG_SUPPORT is not defined (default) the
+ * length modifier 'll' is recognized but treated the same as 'l',
+ * which may cause argument value truncation! Defining
+ * SNPRINTF_LONGLONG_SUPPORT requires that your system's sprintf also
+ * handles length modifier 'll'. long long int is a language extension
+ * which may not be portable.
+ *
+ * Conversion of numeric data (conversion specifiers d, u, o, x, X, p)
+ * with length modifiers (none or h, l, ll) is left to the system routine
+ * sprintf, but all handling of flags, field width and precision as well as
+ * c and s conversions is done very carefully by this portable routine.
+ * If a string precision (truncation) is specified (e.g. %.8s) it is
+ * guaranteed the string beyond the specified precision will not be referenced.
+ *
+ * Length modifiers h, l and ll are ignored for c and s conversions (data
+ * types wint_t and wchar_t are not supported).
+ *
+ * The following common synonyms for conversion characters are supported:
+ * - i is a synonym for d
+ * - D is a synonym for ld, explicit length modifiers are ignored
+ * - U is a synonym for lu, explicit length modifiers are ignored
+ * - O is a synonym for lo, explicit length modifiers are ignored
+ * The D, O and U conversion characters are nonstandard, they are supported
+ * for backward compatibility only, and should not be used for new code.
+ *
+ * The following is specifically NOT supported:
+ * - flag ' (thousands' grouping character) is recognized but ignored
+ * - numeric conversion specifiers: f, e, E, g, G and synonym F,
+ * as well as the new a and A conversion specifiers
+ * - length modifier 'L' (long double) and 'q' (quad - use 'll' instead)
+ * - wide character/string conversions: lc, ls, and nonstandard
+ * synonyms C and S
+ * - writeback of converted string length: conversion character n
+ * - the n$ specification for direct reference to n-th argument
+ * - locales
+ *
+ * It is permitted for str_m to be zero, and it is permitted to specify NULL
+ * pointer for resulting string argument if str_m is zero (as per ISO C99).
+ *
+ * The return value is the number of characters which would be generated
+ * for the given input, excluding the trailing null. If this value
+ * is greater or equal to str_m, not all characters from the result
+ * have been stored in str, output bytes beyond the (str_m-1) -th character
+ * are discarded. If str_m is greater than zero it is guaranteed
+ * the resulting string will be null-terminated.
+ *
+ * NOTE that this matches the ISO C99, OpenBSD, and GNU C library 2.1,
+ * but is different from some older and vendor implementations,
+ * and is also different from XPG, XSH5, SUSv2 specifications.
+ * For historical discussion on changes in the semantics and standards
+ * of snprintf see printf(3) man page in the Linux programmers manual.
+ *
+ * Routines asprintf and vasprintf return a pointer (in the ptr argument)
+ * to a buffer sufficiently large to hold the resulting string. This pointer
+ * should be passed to free(3) to release the allocated storage when it is
+ * no longer needed. If sufficient space cannot be allocated, these functions
+ * will return -1 and set ptr to be a NULL pointer. These two routines are a
+ * GNU C library extensions (glibc).
+ *
+ * Routines asnprintf and vasnprintf are similar to asprintf and vasprintf,
+ * yet, like snprintf and vsnprintf counterparts, will write at most str_m-1
+ * characters into the allocated output string, the last character in the
+ * allocated buffer then gets the terminating null. If the formatted string
+ * length (the return value) is greater than or equal to the str_m argument,
+ * the resulting string was truncated and some of the formatted characters
+ * were discarded. These routines present a handy way to limit the amount
+ * of allocated memory to some sane value.
+ *
+ * AVAILABILITY
+ * http://www.ijs.si/software/snprintf/
+ *
+ * REVISION HISTORY
+ * 1999-04 V0.9 Mark Martinec
+ * - initial version, some modifications after comparing printf
+ * man pages for Digital Unix 4.0, Solaris 2.6 and HPUX 10,
+ * and checking how Perl handles sprintf (differently!);
+ * 1999-04-09 V1.0 Mark Martinec <mark.martinec@ijs.si>
+ * - added main test program, fixed remaining inconsistencies,
+ * added optional (long long int) support;
+ * 1999-04-12 V1.1 Mark Martinec <mark.martinec@ijs.si>
+ * - support the 'p' conversion (pointer to void);
+ * - if a string precision is specified
+ * make sure the string beyond the specified precision
+ * will not be referenced (e.g. by strlen);
+ * 1999-04-13 V1.2 Mark Martinec <mark.martinec@ijs.si>
+ * - support synonyms %D=%ld, %U=%lu, %O=%lo;
+ * - speed up the case of long format string with few conversions;
+ * 1999-06-30 V1.3 Mark Martinec <mark.martinec@ijs.si>
+ * - fixed runaway loop (eventually crashing when str_l wraps
+ * beyond 2^31) while copying format string without
+ * conversion specifiers to a buffer that is too short
+ * (thanks to Edwin Young <edwiny@autonomy.com> for
+ * spotting the problem);
+ * - added macros PORTABLE_SNPRINTF_VERSION_(MAJOR|MINOR)
+ * to snprintf.h
+ * 2000-02-14 V2.0 (never released) Mark Martinec <mark.martinec@ijs.si>
+ * - relaxed license terms: The Artistic License now applies.
+ * You may still apply the GNU GENERAL PUBLIC LICENSE
+ * as was distributed with previous versions, if you prefer;
+ * - changed REVISION HISTORY dates to use ISO 8601 date format;
+ * - added vsnprintf (patch also independently proposed by
+ * Caolan McNamara 2000-05-04, and Keith M Willenson 2000-06-01)
+ * 2000-06-27 V2.1 Mark Martinec <mark.martinec@ijs.si>
+ * - removed POSIX check for str_m<1; value 0 for str_m is
+ * allowed by ISO C99 (and GNU C library 2.1) - (pointed out
+ * on 2000-05-04 by Caolan McNamara, caolan@ csn dot ul dot ie).
+ * Besides relaxed license this change in standards adherence
+ * is the main reason to bump up the major version number;
+ * - added nonstandard routines asnprintf, vasnprintf, asprintf,
+ * vasprintf that dynamically allocate storage for the
+ * resulting string; these routines are not compiled by default,
+ * see comments where NEED_V?ASN?PRINTF macros are defined;
+ * - autoconf contributed by Caolan McNamara
+ * 2000-10-06 V2.2 Mark Martinec <mark.martinec@ijs.si>
+ * - BUG FIX: the %c conversion used a temporary variable
+ * that was no longer in scope when referenced,
+ * possibly causing incorrect resulting character;
+ * - BUG FIX: make precision and minimal field width unsigned
+ * to handle huge values (2^31 <= n < 2^32) correctly;
+ * also be more careful in the use of signed/unsigned/size_t
+ * internal variables - probably more careful than many
+ * vendor implementations, but there may still be a case
+ * where huge values of str_m, precision or minimal field
+ * could cause incorrect behaviour;
+ * - use separate variables for signed/unsigned arguments,
+ * and for short/int, long, and long long argument lengths
+ * to avoid possible incompatibilities on certain
+ * computer architectures. Also use separate variable
+ * arg_sign to hold sign of a numeric argument,
+ * to make code more transparent;
+ * - some fiddling with zero padding and "0x" to make it
+ * Linux compatible;
+ * - systematically use macros fast_memcpy and fast_memset
+ * instead of case-by-case hand optimization; determine some
+ * breakeven string lengths for different architectures;
+ * - terminology change: 'format' -> 'conversion specifier',
+ * 'C9x' -> 'ISO/IEC 9899:1999 ("ISO C99")',
+ * 'alternative form' -> 'alternate form',
+ * 'data type modifier' -> 'length modifier';
+ * - several comments rephrased and new ones added;
+ * - make compiler not complain about 'credits' defined but
+ * not used;
+ */
+/* ============================================= */
+/* NO USER SERVICABLE PARTS FOLLOWING THIS POINT */
+/* ============================================= */
+
+#define PORTABLE_SNPRINTF_VERSION_MAJOR 2
+#define PORTABLE_SNPRINTF_VERSION_MINOR 2
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <errno.h>
+#ifdef isdigit
+#undef isdigit
+#endif
+#define isdigit(c) ((c) >= '0' && (c) <= '9')
+
+#ifndef breakeven_point
+# define breakeven_point 6 /* some reasonable one-size-fits-all value */
+#endif
+
+#define fast_memcpy(d,s,n) \
+{ register size_t nn = (size_t)(n); \
+ if (nn >= breakeven_point) memcpy((d), (s), nn); \
+ else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
+ register char *dd; register const char *ss; \
+for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } }
+
+#define fast_memset(d,c,n) \
+{ register size_t nn = (size_t)(n); \
+ if (nn >= breakeven_point) memset((d), (int)(c), nn); \
+ else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
+ register char *dd; register const int cc=(int)(c); \
+for (dd=(d); nn>0; nn--) *dd++ = cc; } }
+
+
+/* declarations */
+
+static char credits[] = "\n\
+@(#)snprintf.c, v2.2: Mark Martinec, <mark.martinec@ijs.si>\n\
+@(#)snprintf.c, v2.2: Copyright 1999, Mark Martinec. Frontier Artistic License applies.\n\
+@(#)snprintf.c, v2.2: http://www.ijs.si/software/snprintf/\n";
+int symbian_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) {
+
+ size_t str_l = 0;
+ const char *p = fmt;
+
+ /* In contrast with POSIX, the ISO C99 now says
+ * that str can be NULL and str_m can be 0.
+ * This is more useful than the old: if (str_m < 1) return -1; */
+
+ if (!p) p = "";
+ while (*p) {
+ if (*p != '%') {
+ /* if (str_l < str_m) str[str_l++] = *p++; -- this would be sufficient */
+ /* but the following code achieves better performance for cases
+ * where format string is long and contains few conversions */
+ const char *q = strchr(p+1,'%');
+ size_t n = !q ? strlen(p) : (q-p);
+ if (str_l < str_m) {
+ size_t avail = str_m-str_l;
+ fast_memcpy(str+str_l, p, (n>avail?avail:n));
+ }
+ p += n; str_l += n;
+ } else {
+ const char *starting_p;
+ size_t min_field_width = 0, precision = 0;
+ int zero_padding = 0, precision_specified = 0, justify_left = 0;
+ int alternate_form = 0, force_sign = 0;
+ int space_for_positive = 1; /* If both the ' ' and '+' flags appear,
+ the ' ' flag should be ignored. */
+ char length_modifier = '\0'; /* allowed values: \0, h, l, L */
+ char tmp[32];/* temporary buffer for simple numeric->string conversion */
+
+ const char *str_arg; /* string address in case of string argument */
+ size_t str_arg_l; /* natural field width of arg without padding
+ and sign */
+ unsigned char uchar_arg;
+ /* unsigned char argument value - only defined for c conversion.
+ N.B. standard explicitly states the char argument for
+ the c conversion is unsigned */
+
+ size_t number_of_zeros_to_pad = 0;
+ /* number of zeros to be inserted for numeric conversions
+ as required by the precision or minimal field width */
+
+ size_t zero_padding_insertion_ind = 0;
+ /* index into tmp where zero padding is to be inserted */
+
+ char fmt_spec = '\0';
+ /* current conversion specifier character */
+
+ str_arg = credits;/* just to make compiler happy (defined but not used)*/
+ str_arg = NULL;
+ starting_p = p; p++; /* skip '%' */
+ /* parse flags */
+ while (*p == '0' || *p == '-' || *p == '+' ||
+ *p == ' ' || *p == '#' || *p == '\'') {
+ switch (*p) {
+ case '0': zero_padding = 1; break;
+ case '-': justify_left = 1; break;
+ case '+': force_sign = 1; space_for_positive = 0; break;
+ case ' ': force_sign = 1;
+ /* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */
+ break;
+ case '#': alternate_form = 1; break;
+ case '\'': break;
+ }
+ p++;
+ }
+ /* If the '0' and '-' flags both appear, the '0' flag should be ignored. */
+
+ /* parse field width */
+ if (*p == '*') {
+ int j;
+ p++; j = va_arg(ap, int);
+ if (j >= 0) min_field_width = j;
+ else { min_field_width = -j; justify_left = 1; }
+ } else if (isdigit((int)(*p))) {
+ /* size_t could be wider than unsigned int;
+ make sure we treat argument like common implementations do */
+ unsigned int uj = *p++ - '0';
+ while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0');
+ min_field_width = uj;
+ }
+ /* parse precision */
+ if (*p == '.') {
+ p++; precision_specified = 1;
+ if (*p == '*') {
+ int j = va_arg(ap, int);
+ p++;
+ if (j >= 0) precision = j;
+ else {
+ precision_specified = 0; precision = 0;
+ /* NOTE:
+ * Solaris 2.6 man page claims that in this case the precision
+ * should be set to 0. Digital Unix 4.0, HPUX 10 and BSD man page
+ * claim that this case should be treated as unspecified precision,
+ * which is what we do here.
+ */
+ }
+ } else if (isdigit((int)(*p))) {
+ /* size_t could be wider than unsigned int;
+ make sure we treat argument like common implementations do */
+ unsigned int uj = *p++ - '0';
+ while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0');
+ precision = uj;
+ }
+ }
+ /* parse 'h', 'l' and 'll' length modifiers */
+ if (*p == 'h' || *p == 'l') {
+ length_modifier = *p; p++;
+ if (length_modifier == 'l' && *p == 'l') { /* double l = long long */
+#ifdef SNPRINTF_LONGLONG_SUPPORT
+ length_modifier = '2'; /* double l encoded as '2' */
+#else
+ length_modifier = 'l'; /* treat it as a single 'l' */
+#endif
+ p++;
+ }
+ }
+ fmt_spec = *p;
+ /* common synonyms: */
+ switch (fmt_spec) {
+ case 'i': fmt_spec = 'd'; break;
+ case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
+ case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
+ case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
+ default: break;
+ }
+ /* get parameter value, do initial processing */
+ switch (fmt_spec) {
+ case '%': /* % behaves similar to 's' regarding flags and field widths */
+ case 'c': /* c behaves similar to 's' regarding flags and field widths */
+ case 's':
+ length_modifier = '\0'; /* wint_t and wchar_t not supported */
+ /* the result of zero padding flag with non-numeric conversion specifier*/
+ /* is undefined. Solaris and HPUX 10 does zero padding in this case, */
+ /* Digital Unix and Linux does not. */
+ zero_padding = 0; /* turn zero padding off for string conversions */
+ str_arg_l = 1;
+ switch (fmt_spec) {
+ case '%':
+ str_arg = p; break;
+ case 'c': {
+ int j = va_arg(ap, int);
+ uchar_arg = (unsigned char) j; /* standard demands unsigned char */
+ str_arg = (const char *) &uchar_arg;
+ break;
+ }
+ case 's':
+ str_arg = va_arg(ap, const char *);
+ if (!str_arg) str_arg_l = 0;
+ /* make sure not to address string beyond the specified precision !!! */
+ else if (!precision_specified) str_arg_l = strlen(str_arg);
+ /* truncate string if necessary as requested by precision */
+ else if (precision == 0) str_arg_l = 0;
+ else {
+ /* memchr on HP does not like n > 2^31 !!! */
+ const char *q = (const char*) memchr(str_arg, '\0',
+ precision <= 0x7fffffff ? precision : 0x7fffffff);
+ str_arg_l = !q ? precision : (q-str_arg);
+ }
+ break;
+ default: break;
+ }
+ break;
+ case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': {
+ /* NOTE: the u, o, x, X and p conversion specifiers imply
+ the value is unsigned; d implies a signed value */
+
+ int arg_sign = 0;
+ /* 0 if numeric argument is zero (or if pointer is NULL for 'p'),
+ +1 if greater than zero (or nonzero for unsigned arguments),
+ -1 if negative (unsigned argument is never negative) */
+
+ int int_arg = 0; unsigned int uint_arg = 0;
+ /* only defined for length modifier h, or for no length modifiers */
+
+ long int long_arg = 0; unsigned long int ulong_arg = 0;
+ /* only defined for length modifier l */
+
+ void *ptr_arg = NULL;
+ /* pointer argument value -only defined for p conversion */
+
+#ifdef SNPRINTF_LONGLONG_SUPPORT
+ long long int long_long_arg = 0;
+ unsigned long long int ulong_long_arg = 0;
+ /* only defined for length modifier ll */
+#endif
+ if (fmt_spec == 'p') {
+ /* HPUX 10: An l, h, ll or L before any other conversion character
+ * (other than d, i, u, o, x, or X) is ignored.
+ * Digital Unix:
+ * not specified, but seems to behave as HPUX does.
+ * Solaris: If an h, l, or L appears before any other conversion
+ * specifier (other than d, i, u, o, x, or X), the behavior
+ * is undefined. (Actually %hp converts only 16-bits of address
+ * and %llp treats address as 64-bit data which is incompatible
+ * with (void *) argument on a 32-bit system).
+ */
+ length_modifier = '\0';
+ ptr_arg = va_arg(ap, void *);
+ if (ptr_arg != NULL) arg_sign = 1;
+ } else if (fmt_spec == 'd') { /* signed */
+ switch (length_modifier) {
+ case '\0':
+ case 'h':
+ /* It is non-portable to specify a second argument of char or short
+ * to va_arg, because arguments seen by the called function
+ * are not char or short. C converts char and short arguments
+ * to int before passing them to a function.
+ */
+ int_arg = va_arg(ap, int);
+ if (int_arg > 0) arg_sign = 1;
+ else if (int_arg < 0) arg_sign = -1;
+ break;
+ case 'l':
+ long_arg = va_arg(ap, long int);
+ if (long_arg > 0) arg_sign = 1;
+ else if (long_arg < 0) arg_sign = -1;
+ break;
+#ifdef SNPRINTF_LONGLONG_SUPPORT
+ case '2':
+ long_long_arg = va_arg(ap, long long int);
+ if (long_long_arg > 0) arg_sign = 1;
+ else if (long_long_arg < 0) arg_sign = -1;
+ break;
+#endif
+ }
+ } else { /* unsigned */
+ switch (length_modifier) {
+ case '\0':
+ case 'h':
+ uint_arg = va_arg(ap, unsigned int);
+ if (uint_arg) arg_sign = 1;
+ break;
+ case 'l':
+ ulong_arg = va_arg(ap, unsigned long int);
+ if (ulong_arg) arg_sign = 1;
+ break;
+#ifdef SNPRINTF_LONGLONG_SUPPORT
+ case '2':
+ ulong_long_arg = va_arg(ap, unsigned long long int);
+ if (ulong_long_arg) arg_sign = 1;
+ break;
+#endif
+ }
+ }
+ str_arg = tmp; str_arg_l = 0;
+ /* NOTE:
+ * For d, i, u, o, x, and X conversions, if precision is specified,
+ * the '0' flag should be ignored. This is so with Solaris 2.6,
+ * Digital UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl.
+ */
+ if (precision_specified) zero_padding = 0;
+ if (fmt_spec == 'd') {
+ if (force_sign && arg_sign >= 0)
+ tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
+ /* leave negative numbers for sprintf to handle,
+ to avoid handling tricky cases like (short int)(-32768) */
+ } else if (alternate_form) {
+ if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') )
+ { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; }
+ /* alternate form should have no effect for p conversion, but ... */
+ }
+ zero_padding_insertion_ind = str_arg_l;
+ if (!precision_specified) precision = 1; /* default precision is 1 */
+ if (precision == 0 && arg_sign == 0
+ ) {
+ /* converted to null string */
+ /* When zero value is formatted with an explicit precision 0,
+ the resulting formatted string is empty (d, i, u, o, x, X, p). */
+ } else {
+ char f[5]; int f_l = 0;
+ f[f_l++] = '%'; /* construct a simple format string for sprintf */
+ if (!length_modifier) { }
+ else if (length_modifier=='2') { f[f_l++] = 'l'; f[f_l++] = 'l'; }
+ else f[f_l++] = length_modifier;
+ f[f_l++] = fmt_spec; f[f_l++] = '\0';
+ if (fmt_spec == 'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg);
+ else if (fmt_spec == 'd') { /* signed */
+ switch (length_modifier) {
+ case '\0':
+ case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg); break;
+ case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg); break;
+#ifdef SNPRINTF_LONGLONG_SUPPORT
+ case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,long_long_arg); break;
+#endif
+ }
+ } else { /* unsigned */
+ switch (length_modifier) {
+ case '\0':
+ case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, uint_arg); break;
+ case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, ulong_arg); break;
+#ifdef SNPRINTF_LONGLONG_SUPPORT
+ case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,ulong_long_arg);break;
+#endif
+ }
+ }
+ /* include the optional minus sign and possible "0x"
+ in the region before the zero padding insertion point */
+ if (zero_padding_insertion_ind < str_arg_l &&
+ tmp[zero_padding_insertion_ind] == '-') {
+ zero_padding_insertion_ind++;
+ }
+ if (zero_padding_insertion_ind+1 < str_arg_l &&
+ tmp[zero_padding_insertion_ind] == '0' &&
+ (tmp[zero_padding_insertion_ind+1] == 'x' ||
+ tmp[zero_padding_insertion_ind+1] == 'X') ) {
+ zero_padding_insertion_ind += 2;
+ }
+ }
+ { size_t num_of_digits = str_arg_l - zero_padding_insertion_ind;
+ if (alternate_form && fmt_spec == 'o'
+ /* unless zero is already the first character */
+ && !(zero_padding_insertion_ind < str_arg_l
+ && tmp[zero_padding_insertion_ind] == '0')
+ ) { /* assure leading zero for alternate-form octal numbers */
+ if (!precision_specified || precision < num_of_digits+1) {
+ /* precision is increased to force the first character to be zero,
+ except if a zero value is formatted with an explicit precision
+ of zero */
+ precision = num_of_digits+1; precision_specified = 1;
+ }
+ }
+ /* zero padding to specified precision? */
+ if (num_of_digits < precision)
+ number_of_zeros_to_pad = precision - num_of_digits;
+ }
+ /* zero padding to specified minimal field width? */
+ if (!justify_left && zero_padding) {
+ int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
+ if (n > 0) number_of_zeros_to_pad += n;
+ }
+ break;
+ }
+ default: /* unrecognized conversion specifier, keep format string as-is*/
+ zero_padding = 0; /* turn zero padding off for non-numeric convers. */
+ justify_left = 1; min_field_width = 0; /* reset flags */
+ /* discard the unrecognized conversion, just keep *
+ * the unrecognized conversion character */
+ str_arg = p; str_arg_l = 0;
+ if (*p) str_arg_l++; /* include invalid conversion specifier unchanged
+ if not at end-of-string */
+ break;
+ }
+ if (*p) p++; /* step over the just processed conversion specifier */
+ /* insert padding to the left as requested by min_field_width;
+ this does not include the zero padding in case of numerical conversions*/
+ if (!justify_left) { /* left padding with blank or zero */
+ int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
+ if (n > 0) {
+ if (str_l < str_m) {
+ size_t avail = str_m-str_l;
+ fast_memset(str+str_l, (zero_padding?'0':' '), (n>avail?avail:n));
+ }
+ str_l += n;
+ }
+ }
+ /* zero padding as requested by the precision or by the minimal field width
+ * for numeric conversions required? */
+ if (number_of_zeros_to_pad <= 0) {
+ /* will not copy first part of numeric right now, *
+ * force it to be copied later in its entirety */
+ zero_padding_insertion_ind = 0;
+ } else {
+ /* insert first part of numerics (sign or '0x') before zero padding */
+ int n = zero_padding_insertion_ind;
+ if (n > 0) {
+ if (str_l < str_m) {
+ size_t avail = str_m-str_l;
+ fast_memcpy(str+str_l, str_arg, (n>avail?avail:n));
+ }
+ str_l += n;
+ }
+ /* insert zero padding as requested by the precision or min field width */
+ n = number_of_zeros_to_pad;
+ if (n > 0) {
+ if (str_l < str_m) {
+ size_t avail = str_m-str_l;
+ fast_memset(str+str_l, '0', (n>avail?avail:n));
+ }
+ str_l += n;
+ }
+ }
+ /* insert formatted string
+ * (or as-is conversion specifier for unknown conversions) */
+ { int n = str_arg_l - zero_padding_insertion_ind;
+ if (n > 0) {
+ if (str_l < str_m) {
+ size_t avail = str_m-str_l;
+ fast_memcpy(str+str_l, str_arg+zero_padding_insertion_ind,
+ (n>avail?avail:n));
+ }
+ str_l += n;
+ }
+ }
+ /* insert right padding */
+ if (justify_left) { /* right blank padding to the field width */
+ int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
+ if (n > 0) {
+ if (str_l < str_m) {
+ size_t avail = str_m-str_l;
+ fast_memset(str+str_l, ' ', (n>avail?avail:n));
+ }
+ str_l += n;
+ }
+ }
+ }
+ }
+ if (str_m > 0) { /* make sure the string is null-terminated
+ even at the expense of overwriting the last character
+ (shouldn't happen, but just in case) */
+ str[str_l <= str_m-1 ? str_l : str_m-1] = '\0';
+ }
+ /* Return the number of characters formatted (excluding trailing null
+ * character), that is, the number of characters that would have been
+ * written to the buffer if it were large enough.
+ *
+ * The value of str_l should be returned, but str_l is of unsigned type
+ * size_t, and snprintf is int, possibly leading to an undetected
+ * integer overflow, resulting in a negative return value, which is illegal.
+ * Both XSH5 and ISO C99 (at least the draft) are silent on this issue.
+ * Should errno be set to EOVERFLOW and EOF returned in this case???
+ */
+ return (int) str_l;
+}
+
+int symbian_snprintf(char *text, size_t maxlen, const char *fmt, ...) {
+ va_list ap;
+ int retval;
+
+ va_start(ap, fmt);
+ retval = symbian_vsnprintf(text, maxlen, fmt, ap);
+ va_end(ap);
+
+ return retval;
+}
diff --git a/backends/platform/wince/CEActionsPocket.cpp b/backends/platform/wince/CEActionsPocket.cpp
index 3626c4c10b..7f78517762 100644
--- a/backends/platform/wince/CEActionsPocket.cpp
+++ b/backends/platform/wince/CEActionsPocket.cpp
@@ -147,7 +147,7 @@ void CEActionsPocket::initInstanceGame() {
_key_action[POCKET_ACTION_PAUSE].setKey(VK_SPACE);
_action_enabled[POCKET_ACTION_PAUSE] = true;
// Save
- if (is_simon || is_sword2 || is_gob || is_kyra || is_touche || is_feeble)
+ if (is_simon || is_sword2 || is_gob || is_kyra || is_feeble)
_action_enabled[POCKET_ACTION_SAVE] = false;
else if (is_queen) {
_action_enabled[POCKET_ACTION_SAVE] = true;
diff --git a/backends/platform/wince/CEActionsSmartphone.cpp b/backends/platform/wince/CEActionsSmartphone.cpp
index 87f73f5a66..0c4113cc0c 100644
--- a/backends/platform/wince/CEActionsSmartphone.cpp
+++ b/backends/platform/wince/CEActionsSmartphone.cpp
@@ -130,7 +130,7 @@ void CEActionsSmartphone::initInstanceGame() {
// Initialize keys for different actions
// Save
- if (is_simon || is_sword2 || is_gob || is_kyra || is_touche || is_feeble)
+ if (is_simon || is_sword2 || is_gob || is_kyra || is_feeble)
_action_enabled[SMARTPHONE_ACTION_SAVE] = false;
else if (is_queen) {
_action_enabled[SMARTPHONE_ACTION_SAVE] = true;
diff --git a/backends/platform/wince/CELauncherDialog.cpp b/backends/platform/wince/CELauncherDialog.cpp
index edfdad84b3..7e306be114 100644
--- a/backends/platform/wince/CELauncherDialog.cpp
+++ b/backends/platform/wince/CELauncherDialog.cpp
@@ -72,10 +72,10 @@ void CELauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 d
}
}
-void CELauncherDialog::automaticScanDirectory(const FilesystemNode &node) {
+void CELauncherDialog::automaticScanDirectory(const Common::FilesystemNode &node) {
// First check if we have a recognized game in the current directory
- FSList files;
- node.getChildren(files, FilesystemNode::kListFilesOnly);
+ Common::FSList files;
+ node.getChildren(files, Common::FilesystemNode::kListFilesOnly);
// detect
GameList candidates(EngineMan.detectGames(files));
// insert
@@ -85,9 +85,9 @@ void CELauncherDialog::automaticScanDirectory(const FilesystemNode &node) {
addGameToConf(result);
}
// Then recurse on the subdirectories
- FSList dirs;
- node.getChildren(dirs, FilesystemNode::kListDirectoriesOnly);
- for (FSList::const_iterator currentDir = dirs.begin(); currentDir != dirs.end(); ++currentDir)
+ Common::FSList dirs;
+ node.getChildren(dirs, Common::FilesystemNode::kListDirectoriesOnly);
+ for (Common::FSList::const_iterator currentDir = dirs.begin(); currentDir != dirs.end(); ++currentDir)
automaticScanDirectory(*currentDir);
}
diff --git a/backends/platform/wince/CELauncherDialog.h b/backends/platform/wince/CELauncherDialog.h
index 55d177bcb8..a5f3fd0d43 100644
--- a/backends/platform/wince/CELauncherDialog.h
+++ b/backends/platform/wince/CELauncherDialog.h
@@ -36,7 +36,7 @@ public:
virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
protected:
void addGame();
- void automaticScanDirectory(const FilesystemNode &node);
+ void automaticScanDirectory(const Common::FilesystemNode &node);
};
typedef GUI::LauncherDialog GUILauncherDialog;
diff --git a/backends/platform/wince/Makefile b/backends/platform/wince/Makefile
index 4400d50e3a..9f040bbed1 100644
--- a/backends/platform/wince/Makefile
+++ b/backends/platform/wince/Makefile
@@ -45,8 +45,8 @@ ENABLE_DRASCULA = STATIC_PLUGIN
USE_MAD = 1
USE_MPEG2 = 1
-USE_TREMOR = 1
-#USE_TREMOLO = 1
+#USE_TREMOR = 1
+USE_TREMOLO = 1
USE_FLAC = 1
USE_ZLIB = 1
@@ -139,7 +139,7 @@ LIBS += -ltremorce
endif
ifdef USE_TREMOLO
-DEFINES += -DUSE_TREMOR -DUSE_VORBIS
+DEFINES += -DUSE_TREMOR -DUSE_VORBIS -DUSE_TREMOLO
INCLUDES += -Ilibs/include/tremolo
LIBS += -llibTremolo
endif
diff --git a/backends/platform/wince/README-WinCE.txt b/backends/platform/wince/README-WinCE.txt
index f4cb00dcfa..86c627d764 100644
--- a/backends/platform/wince/README-WinCE.txt
+++ b/backends/platform/wince/README-WinCE.txt
@@ -1,29 +1,28 @@
ScummVM Windows CE FAQ
Last updated: $Date$
-Release version: 0.11.0
+Release version: 0.12.0
------------------------------------------------------------------------
New in this version
-------------------
-0.11.0
-- Redesigned 'Free Look' action (Pocket PCs)
-In order to accommodate for the requirements of the lure engine, the
-usage characteristics of the 'Free Look' action have been improved. The
-new behavior is available for use in all engines, but is is *strongly*
-recommended for at least when playing 'Lure of the Temptress'. By using
-the new scheme, when in 'Free Look' mode, it is now possible to enter
-left clicks by clicking a second time near the current location of the
-mouse pointer. Left and Right clicks at the current point location
-are also available by using the respective actions' bound key.
+0.12.0:
+- Improved SMUSH support (deprecated 'Smush_force_redraw' option)
+No skipped frames in Full Throttle action sequences. The 'Smush_force_redraw'
+option is not needed/honored anymore.
-- Reduced optimization build
-The ScummVM executable has grown quite large, prohibiting some devices
-from running memory demanding games (or any games at all). Code
-optimization level has been reduced to offset the growth of the executable.
-Games run slightly slower. This will be addressed before next release.
+- Fixed MultiFuntion key in Full Throttle
-- Several bugfixes
+- Improved sound output
+Fixed a long standing bug which led to distorted sound output in all games.
+
+- Switched to faster ogg vorbis library
+Robin Watts' libTremolo is used for ogg vorbis (tremor) replay. Info patch
+by Lostech.
+
+- New right click through double tap inhibiting option
+Check out the 'no_doubletap_rightclick' option if double-tapping as a right
+click input method annoys you. Patch by spookypeanut.
------------------------------------------------------------------------
@@ -109,10 +108,10 @@ and report your success ...
How do I install ScummVM for Windows CE ?
-----------------------------------------
-Simple! Unpack the release package on your desktop pc, then copy all its contents
-to a folder on your device. Typically, you should at least have scummvm.exe,
-modern.ini and modern.zip in the same directory. Finally, upload your beloved games
-and fire it up :-)
+Simple! Unpack the release package on your desktop pc, then copy all its
+contents to a folder on your device. Typically, you should at least have
+scummvm.exe, modern.ini and modern.zip in the same directory. Finally, upload
+your beloved games and fire it up :-)
Some devices (like Pocket PC 2000) require GAPI to be present.
@@ -184,18 +183,19 @@ The following actions are available :
* Right click : acts as a right mouse button click
* Cursor : hide or display the mouse cursor
* Free look : go in or out of free-look mode. In this mode, you can tap
- the screen to look for interesting locations without walking.
- Cling a second time near the pointer's location equals to left click.
+ the screen to look for interesting locations without
+ walking. Click a second time near the pointer's location
+ equals to a left click.
* Zoom up : magnify the upper part of the screen for 640x480 games
rendered on a QVGA device.
* Zoom down : magnify the lower part of the screen for 640x480 games
rendered on a QVGA device.
- * Multi Function : this key performs a different function depending on the game
- : Full Throttle -> win an action sequence (cheat)
- : Fate of Atlantis -> sucker punch (cheat)
- : Bargon -> F1 (start the game)
- : All AGI games -> bring up the predictive input dialog
- * Bind keys : map a key action to a device button
+ * Multi Function : performs a different function depending on the game :
+ Full Throttle -> win an action sequence (cheat)
+ Fate of Atlantis -> sucker punch (cheat)
+ Bargon -> F1 (start the game)
+ All AGI games -> bring up the predictive input dialog
+ * Bind keys map a key action to a device button
* Up,Down,Left :
Right, : emulate mouse/stylus behavior
Left Click :
@@ -245,11 +245,11 @@ the list of available actions for Smartphones:
* Skip : skip a non interactive sequence, the current dialog or
behaves like the ESC key on a regular keyboard
* Zone : switch between the 3 different mouse zones
- * Multi Function : this key performs a different function depending on the game
- : Full Throttle -> win an action sequence (cheat)
- : Fate of Atlantis -> sucker punch (cheat)
- : Bargon -> F1 (start the game)
- : All AGI games -> bring up the predictive input dialog
+ * Multi Function : performs a different function depending on the game
+ Full Throttle -> win an action sequence (cheat)
+ Fate of Atlantis -> sucker punch (cheat)
+ Bargon -> F1 (start the game)
+ All AGI games -> bring up the predictive input dialog
* Bind keys : map a key action to a device button
* Keyboard : hide or display the virtual keyboard
* Rotate : rotate the screen (also rotates dpad keys)
@@ -287,32 +287,34 @@ Some parameters are specific to this port :
Game specific sections (f.e. [monkey2]) - performance options
- * high_sample_rate bool Desktop quality (22 kHz) sound output if set.
- 11 kHz otherwise. The default is 11 kHz.
- If you have a fast device, you can set this to
- true to enjoy better sound effects and music.
+ * high_sample_rate bool Desktop quality (22 kHz) sound output if
+ set. The default is 11 kHz.
+ If you have a fast device, you can set this
+ to true to enjoy better sound effects and
+ music.
* FM_high_quality bool Desktop quality FM synthesis if set. Lower
- quality otherwise. The default is low quality.
- You can change this if you have a fast device.
- * sound_thread_priority int Set the priority of the sound thread (0, 1, 2).
- Depending on the release, this is set to 1
- internally (above normal). If you get sound
- stuttering try setting this to a higher value.
+ quality otherwise. The default is low
+ quality. You can change this if you have a
+ fast device.
+ * sound_thread_priority int Set the priority of the sound thread (0, 1,
+ 2). Depending on the release, this is set
+ to 1 internally (above normal).
+ If you get sound stuttering try setting
+ this to a higher value.
Set to 0 if your device is fast enough or if
- you prefer better audio/video synchronization.
- * Smush_force_redraw int Force a Smush frame redraw every X missed
- frames. Mainly used for Full Throttle action
- sequences. Setting it lower gives more
- priority to screen redraws. Setting it higher
- gives more priority to stylus/keyboard input.
- The default is 30.
+ you prefer better audio/video sync.
Game specific sections (f.e. [monkey2]) - game options
- * landscape int 0: Portrait, 1: Landscape, 2: Inverse Landscape
- You can also use this in the [scummvm] section
- in QVGA Pocket PCs to display the launcher in
- landscape, for example, at startup.
+ * landscape int 0: Portrait, 1: Landscape,
+ 2: Inverse Landscape.
+ You can also use this in the [scummvm]
+ section to display the launcher in landscape
+ for example, at startup.
+ * no_doubletap_rightclick int 1: Turn off the default behavior of
+ simulating a right-click when the screen is
+ double-tapped.
+
[scummvm] section - keys definition
@@ -335,18 +337,18 @@ You can tweak these parameters to customize how the cursor is handled.
consider being repeated.
* repeatX int Number of key repeat events before changing
horizontal cursor behaviour.
- * stepX1 int Horizontal cursor offset value when the key is
- not repeated.
- * stepX2 int Horizontal cursor offset value when the key is
- repeated less than repeatX.
- * stepX3 int Horizontal cursor offset value when the key is
- repeated more than repeatX.
+ * stepX1 int Horizontal cursor offset value when the key
+ is not repeated.
+ * stepX2 int Horizontal cursor offset value when the key
+ is repeated less than repeatX.
+ * stepX3 int Horizontal cursor offset value when the key
+ is repeated more than repeatX.
* repeatY int Number of key repeat events before changing
- vertical cursor behaviour.
+ vertical cursor behavior.
* stepY1 int Vertical cursor offset value when the key is
not repeated.
- * stepY2 int Horizontal cursor offset value when the key is
- repeated less than repeatY.
+ * stepY2 int Horizontal cursor offset value when the key
+ is repeated less than repeatY.
* stepY3 int Vertical cursor offset value when the key is
repeated more than repeatY.
@@ -361,8 +363,8 @@ Game specific questions
I need to press a special key
-----------------------------
-Bring up the virtual keyboard. On Smartphones take a look at the Keyboard action above.
-On Pocket PCs it's easier to double-tap at the top of the screen.
+Bring up the virtual keyboard. On Smartphones take a look at the Keyboard
+action above. On Pocket PCs it's easier to double-tap at the top of the screen.
The panel is obscuring the playfield area
-----------------------------------------
@@ -383,17 +385,18 @@ Bind and use the quit action to quit.
I cannot rotate the screen to landscape/inverse landscape
---------------------------------------------------------
-Depending on the video driver, ScummVM may opt to not provide such functionality.
-In general, when ScummVM starts in normal "portrait" orientation, the device driver
-reports better display characteristics and you should consider launching from portrait.
+Depending on the video driver, ScummVM may opt to not provide such
+functionality. In general, when ScummVM starts in normal "portrait"
+orientation, the device driver reports better display characteristics and you
+should consider launching from portrait.
I'm having problems. Is there diagnostic output available ?
-----------------------------------------------------------
Insert a line in the [scummvm] section of scummvm.ini with the following:
debuglevel=1
-Run ScummVM. When it closes scummvm_stdout.txt and scummvm_stderr.txt files will be
-available at the program directory (see section above).
+Run ScummVM. When it closes scummvm_stdout.txt and scummvm_stderr.txt files
+will be available at the program directory (see section above).
ScummVM crashes and returns to desktop
--------------------------------------
@@ -548,18 +551,19 @@ Use the Multi Function action.
-- AGI engine games --
----------------------
-Do you expect me to play these games on keyboard less devices ?
+Do you expect me to play these games on keyboard-less devices ?
---------------------------------------------------------------
Sure we do :-)
-If you want to get some mileage on your stylus you can use the virtual keyboard.
-There is a very useful alternative though, the AGI engine's predictive input dialog.
-It requires a dictionary to be present. Just tap on the command line or use the
-Multi Function action to bring it up. On Smartphones, when the dialog is shown
-all key mapping is disabled temporarily (including mouse emulation). Input is
-performed either by pressing the phone's numeric keypad keys and dpad enter to
-close the dialog, or by navigating the buttons using the dpad arrows and pressing
-with dpad enter. Check the main Readme file for more information on this.
+If you want to get some mileage on your stylus you can use the virtual
+keyboard. There is a very useful alternative though, the AGI engine's
+predictive input dialog. It requires a dictionary to be present. Just tap on
+the command line or use the Multi Function action to bring it up. On
+Smartphones, when the dialog is shown all key mapping is disabled temporarily
+(including mouse emulation). Input is performed either by pressing the phone's
+numeric keypad keys and dpad enter to close the dialog, or by navigating the
+buttons using the dpad arrows and pressing with dpad enter. Check the main
+Readme file for more information on this.
---------------------------
-- Lure of the Temptress --
@@ -595,8 +599,9 @@ I think I found a bug, ScummVM crashes in ...
See the "Reporting Bugs" section in ScummVM readme.
-If you have a Pocket PC or Handheld PC, be sure to include its resolution (obtained
-on the second dialog displayed on the "About" menu) in your bug report.
+If you have a Pocket PC or Handheld PC, be sure to include its resolution
+(obtained on the second dialog displayed on the "About" menu) in your bug
+report.
If you cannot reproduce this bug on another ScummVM version, you can cross
post your bug report on ScummVM forums.
@@ -619,6 +624,26 @@ http://www.scummvm.org/
Old news follow ...
------------------------------------------------------------------------
+0.11.0:
+- Redesigned 'Free Look' action (Pocket PCs)
+In order to accommodate for the requirements of the lure engine, the
+usage characteristics of the 'Free Look' action have been improved. The
+new behavior is available for use in all engines, but is is *strongly*
+recommended for at least when playing 'Lure of the Temptress'. By using
+the new scheme, when in 'Free Look' mode, it is now possible to enter
+left clicks by clicking a second time near the current location of the
+mouse pointer. Left and Right clicks at the current point location
+are also available by using the respective actions' bound key.
+
+- Reduced optimization build
+The ScummVM executable has grown quite large, prohibiting some devices
+from running memory demanding games (or any games at all). Code
+optimization level has been reduced to offset the growth of the executable.
+Games run slightly slower. This will be addressed before next release.
+
+- Several bugfixes
+
+
0.10.0:
Major improvements have taken place in this version, mostly for behind-
the-scenes stuff. First, we have migrated to GCC for building the Windows
diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp
index 48f157f6ff..f09a483086 100644
--- a/backends/platform/wince/wince-sdl.cpp
+++ b/backends/platform/wince/wince-sdl.cpp
@@ -461,7 +461,7 @@ OSystem_WINCE3::OSystem_WINCE3() : OSystem_SDL(),
_orientationLandscape(0), _newOrientation(0), _panelInitialized(false),
_panelVisible(true), _panelStateForced(false), _forceHideMouse(false), _unfilteredkeys(false),
_freeLook(false), _forcePanelInvisible(false), _toolbarHighDrawn(false), _zoomUp(false), _zoomDown(false),
- _scalersChanged(false), _lastKeyPressed(0), _tapTime(0), _closeClick(false),
+ _scalersChanged(false), _lastKeyPressed(0), _tapTime(0), _closeClick(false), _noDoubleTapRMB(false),
_saveToolbarState(false), _saveActiveToolbar(NAME_MAIN_PANEL), _rbutton(false), _hasfocus(true),
_usesEmulatedMouse(false), _mouseBackupOld(NULL), _mouseBackupToolbar(NULL), _mouseBackupDim(0)
{
@@ -1059,14 +1059,11 @@ void OSystem_WINCE3::update_game_settings() {
panel->setVisible(false);
_saveToolbarState = true;
-
- // Set Smush Force Redraw rate for Full Throttle
- if (!ConfMan.hasKey("Smush_force_redraw")) {
- ConfMan.setInt("Smush_force_redraw", 30);
- ConfMan.flushToDisk();
- }
}
+ if (ConfMan.hasKey("no_doubletap_rightclick"))
+ _noDoubleTapRMB = ConfMan.getBool("no_doubletap_rightclick");
+
compute_sample_rate();
}
@@ -2340,7 +2337,7 @@ bool OSystem_WINCE3::pollEvent(Common::Event &event) {
if (_closeClick && (GetTickCount() - _tapTime < 1000)) {
if (event.mouse.y <= 20 && _panelInitialized) { // top of screen (show panel)
swap_panel_visibility();
- } else { // right click
+ } else if (!_noDoubleTapRMB) { // right click
event.type = Common::EVENT_RBUTTONDOWN;
_rbutton = true;
}
diff --git a/backends/platform/wince/wince-sdl.h b/backends/platform/wince/wince-sdl.h
index 8853c156d8..ece8c9b7b1 100644
--- a/backends/platform/wince/wince-sdl.h
+++ b/backends/platform/wince/wince-sdl.h
@@ -200,6 +200,7 @@ private:
bool _zoomUp; // zooming up mode
bool _zoomDown; // zooming down mode
+ bool _noDoubleTapRMB; // disable double tap -> rmb click
bool _rbutton; // double tap -> right button simulation
bool _closeClick; // flag when taps are spatially close together
diff --git a/backends/saves/compressed/compressed-saves.cpp b/backends/saves/compressed/compressed-saves.cpp
index 150cf5c47d..11cb1689cd 100644
--- a/backends/saves/compressed/compressed-saves.cpp
+++ b/backends/saves/compressed/compressed-saves.cpp
@@ -23,278 +23,14 @@
*
*/
-#include "common/savefile.h"
-#include "common/util.h"
+#include "common/zlib.h"
#include "backends/saves/compressed/compressed-saves.h"
-#if defined(USE_ZLIB)
-#include <zlib.h>
-
-#if ZLIB_VERNUM < 0x1204
-#error Version 1.2.0.4 or newer of zlib is required for this code
-#endif
-
-/**
- * A simple wrapper class which can be used to wrap around an arbitrary
- * other InSaveFile and will then provide on-the-fly decompression support.
- * Assumes the compressed data to be in gzip format.
- */
-class CompressedInSaveFile : public Common::InSaveFile {
-protected:
- enum {
- BUFSIZE = 16384 // 1 << MAX_WBITS
- };
-
- byte _buf[BUFSIZE];
-
- Common::InSaveFile *_wrapped;
- z_stream _stream;
- int _zlibErr;
- uint32 _pos;
- uint32 _origSize;
-
-public:
-
- CompressedInSaveFile(Common::InSaveFile *w) : _wrapped(w) {
- assert(w != 0);
-
- _stream.zalloc = Z_NULL;
- _stream.zfree = Z_NULL;
- _stream.opaque = Z_NULL;
-
- // Verify file header is correct once more
- w->seek(0, SEEK_SET);
- uint16 header = w->readUint16BE();
- assert(header == 0x1F8B ||
- ((header & 0x0F00) == 0x0800 && header % 31 == 0));
-
- if (header == 0x1F8B) {
- // Retrieve the original file size
- w->seek(-4, SEEK_END);
- _origSize = w->readUint32LE();
- } else {
- // Original size not available in zlib format
- _origSize = 0;
- }
- _pos = 0;
- w->seek(0, SEEK_SET);
-
- // Adding 32 to windowBits indicates to zlib that it is supposed to
- // automatically detect whether gzip or zlib headers are used for
- // the compressed file. This feature was added in zlib 1.2.0.4,
- // released 10 August 2003.
- // Note: This is *crucial* for savegame compatibility, do *not* remove!
- _zlibErr = inflateInit2(&_stream, MAX_WBITS + 32);
- if (_zlibErr != Z_OK)
- return;
-
- // Setup input buffer
- _stream.next_in = _buf;
- _stream.avail_in = 0;
- }
-
- ~CompressedInSaveFile() {
- inflateEnd(&_stream);
- delete _wrapped;
- }
-
- bool ioFailed() const { return (_zlibErr != Z_OK) && (_zlibErr != Z_STREAM_END); }
- void clearIOFailed() { /* errors here are not recoverable! */ }
-
- uint32 read(void *dataPtr, uint32 dataSize) {
- _stream.next_out = (byte *)dataPtr;
- _stream.avail_out = dataSize;
-
- // Keep going while we get no error
- while (_zlibErr == Z_OK && _stream.avail_out) {
- if (_stream.avail_in == 0 && !_wrapped->eos()) {
- // If we are out of input data: Read more data, if available.
- _stream.next_in = _buf;
- _stream.avail_in = _wrapped->read(_buf, BUFSIZE);
- }
- _zlibErr = inflate(&_stream, Z_NO_FLUSH);
- }
-
- // Update the position counter
- _pos += dataSize - _stream.avail_out;
-
- return dataSize - _stream.avail_out;
- }
-
- bool eos() const {
- return (_zlibErr == Z_STREAM_END);
- //return _pos == _origSize;
- }
- uint32 pos() const {
- return _pos;
- }
- uint32 size() const {
- return _origSize;
- }
- void seek(int32 offset, int whence = SEEK_SET) {
- int32 newPos = 0;
- switch(whence) {
- case SEEK_END:
- newPos = size() - offset;
- break;
- case SEEK_SET:
- newPos = offset;
- break;
- case SEEK_CUR:
- newPos = _pos + offset;
- }
- offset = newPos - _pos;
-
- if (offset < 0)
- error("Backward seeking not supported in compressed savefiles");
-
- // We could implement backward seeking, but it is tricky to do efficiently.
- // A simple solution would be to restart the whole decompression from the
- // start of the file. Or we could decompress the whole file in one go
- // in the constructor, and wrap it into a MemoryReadStream -- but that
- // would be rather wasteful. As long as we don't need it, I'd rather not
- // implement this at all. -- Fingolfin
-
- // Skip the given amount of data (very inefficient if one tries to skip
- // huge amounts of data, but usually client code will only skip a few
- // bytes, so this should be fine.
- byte tmpBuf[1024];
- while (!ioFailed() && offset > 0) {
- offset -= read(tmpBuf, MIN((int32)sizeof(tmpBuf), offset));
- }
- }
-};
-
-/**
- * A simple wrapper class which can be used to wrap around an arbitrary
- * other OutSaveFile and will then provide on-the-fly compression support.
- * The compressed data is written in the gzip format.
- */
-class CompressedOutSaveFile : public Common::OutSaveFile {
-protected:
- enum {
- BUFSIZE = 16384 // 1 << MAX_WBITS
- };
-
- byte _buf[BUFSIZE];
- Common::OutSaveFile *_wrapped;
- z_stream _stream;
- int _zlibErr;
-
- void processData(int flushType) {
- // This function is called by both write() and finalize().
- while (_zlibErr == Z_OK && (_stream.avail_in || flushType == Z_FINISH)) {
- if (_stream.avail_out == 0) {
- if (_wrapped->write(_buf, BUFSIZE) != BUFSIZE) {
- _zlibErr = Z_ERRNO;
- break;
- }
- _stream.next_out = _buf;
- _stream.avail_out = BUFSIZE;
- }
- _zlibErr = deflate(&_stream, flushType);
- }
- }
-
-public:
- CompressedOutSaveFile(Common::OutSaveFile *w) : _wrapped(w) {
- assert(w != 0);
- _stream.zalloc = Z_NULL;
- _stream.zfree = Z_NULL;
- _stream.opaque = Z_NULL;
-
- // Adding 16 to windowBits indicates to zlib that it is supposed to
- // write gzip headers. This feature was added in zlib 1.2.0.4,
- // released 10 August 2003.
- // Note: This is *crucial* for savegame compatibility, do *not* remove!
- _zlibErr = deflateInit2(&_stream,
- Z_DEFAULT_COMPRESSION,
- Z_DEFLATED,
- MAX_WBITS + 16,
- 8,
- Z_DEFAULT_STRATEGY);
- assert(_zlibErr == Z_OK);
-
- _stream.next_out = _buf;
- _stream.avail_out = BUFSIZE;
- _stream.avail_in = 0;
- _stream.next_in = 0;
- }
-
- ~CompressedOutSaveFile() {
- finalize();
- deflateEnd(&_stream);
- delete _wrapped;
- }
-
- bool ioFailed() const {
- return (_zlibErr != Z_OK && _zlibErr != Z_STREAM_END) || _wrapped->ioFailed();
- }
-
- void clearIOFailed() {
- // Note: we don't reset the _zlibErr here, as it is not
- // clear in general ho
- _wrapped->clearIOFailed();
- }
-
- void finalize() {
- if (_zlibErr != Z_OK)
- return;
-
- // Process whatever remaining data there is.
- processData(Z_FINISH);
-
- // Since processData only writes out blocks of size BUFSIZE,
- // we may have to flush some stragglers.
- uint remainder = BUFSIZE - _stream.avail_out;
- if (remainder > 0) {
- if (_wrapped->write(_buf, remainder) != remainder) {
- _zlibErr = Z_ERRNO;
- }
- }
-
- // Finalize the wrapped savefile, too
- _wrapped->finalize();
- }
-
- uint32 write(const void *dataPtr, uint32 dataSize) {
- if (ioFailed())
- return 0;
-
- // Hook in the new data ...
- // Note: We need to make a const_cast here, as zlib is not aware
- // of the const keyword.
- _stream.next_in = const_cast<byte *>((const byte *)dataPtr);
- _stream.avail_in = dataSize;
-
- // ... and flush it to disk
- processData(Z_NO_FLUSH);
-
- return dataSize - _stream.avail_in;
- }
-};
-
-#endif // USE_ZLIB
Common::InSaveFile *wrapInSaveFile(Common::InSaveFile *toBeWrapped) {
-#if defined(USE_ZLIB)
- if (toBeWrapped) {
- uint16 header = toBeWrapped->readUint16BE();
- bool isCompressed = (header == 0x1F8B ||
- ((header & 0x0F00) == 0x0800 &&
- header % 31 == 0));
- toBeWrapped->seek(-2, SEEK_CUR);
- if (isCompressed)
- return new CompressedInSaveFile(toBeWrapped);
- }
-#endif
- return toBeWrapped;
+ return Common::wrapCompressedReadStream(toBeWrapped);
}
Common::OutSaveFile *wrapOutSaveFile(Common::OutSaveFile *toBeWrapped) {
-#if defined(USE_ZLIB)
- if (toBeWrapped)
- return new CompressedOutSaveFile(toBeWrapped);
-#endif
- return toBeWrapped;
+ return Common::wrapCompressedWriteStream(toBeWrapped);
}
diff --git a/backends/saves/default/default-saves.cpp b/backends/saves/default/default-saves.cpp
index dc5e8adca7..0cfd265890 100644
--- a/backends/saves/default/default-saves.cpp
+++ b/backends/saves/default/default-saves.cpp
@@ -28,7 +28,6 @@
#include "common/savefile.h"
#include "common/util.h"
#include "common/fs.h"
-#include "common/file.h"
#include "common/config-manager.h"
#include "backends/saves/default/default-saves.h"
#include "backends/saves/compressed/compressed-saves.h"
@@ -37,7 +36,7 @@
#include <string.h>
#include <errno.h>
-#if defined(UNIX) || defined(__SYMBIAN32__)
+#if defined(UNIX)
#include <sys/stat.h>
#endif
@@ -47,8 +46,6 @@
#else
#define DEFAULT_SAVE_PATH ".scummvm"
#endif
-#elif defined(__SYMBIAN32__)
-#define DEFAULT_SAVE_PATH "Savegames"
#endif
DefaultSaveFileManager::DefaultSaveFileManager() {
@@ -64,10 +61,6 @@ DefaultSaveFileManager::DefaultSaveFileManager() {
savePath += "/" DEFAULT_SAVE_PATH;
ConfMan.registerDefault("savepath", savePath);
}
-#elif defined(__SYMBIAN32__)
- savePath = Symbian::GetExecutablePath();
- savePath += DEFAULT_SAVE_PATH "\\";
- ConfMan.registerDefault("savepath", savePath);
#endif
#endif // #ifdef DEFAULT_SAVE_PATH
}
@@ -78,13 +71,13 @@ DefaultSaveFileManager::DefaultSaveFileManager(const Common::String &defaultSave
Common::StringList DefaultSaveFileManager::listSavefiles(const char *pattern) {
- FilesystemNode savePath(getSavePath());
- FSList savefiles;
+ Common::FilesystemNode savePath(getSavePath());
+ Common::FSList savefiles;
Common::StringList results;
Common::String search(pattern);
if (savePath.lookupFile(savefiles, search, false, true, 0)) {
- for (FSList::const_iterator file = savefiles.begin(); file != savefiles.end(); ++file) {
+ for (Common::FSList::const_iterator file = savefiles.begin(); file != savefiles.end(); ++file) {
results.push_back(file->getName());
}
}
@@ -92,11 +85,11 @@ Common::StringList DefaultSaveFileManager::listSavefiles(const char *pattern) {
return results;
}
-void DefaultSaveFileManager::checkPath(const FilesystemNode &dir) {
+void DefaultSaveFileManager::checkPath(const Common::FilesystemNode &dir) {
const Common::String path = dir.getPath();
clearError();
-#if defined(UNIX) || defined(__SYMBIAN32__)
+#if defined(UNIX)
struct stat sb;
// Check whether the dir exists
@@ -108,11 +101,9 @@ void DefaultSaveFileManager::checkPath(const FilesystemNode &dir) {
case EACCES:
setError(SFM_DIR_ACCESS, "Search or write permission denied: "+path);
break;
-#if !defined(__SYMBIAN32__)
case ELOOP:
setError(SFM_DIR_LOOP, "Too many symbolic links encountered while traversing the path: "+path);
break;
-#endif
case ENAMETOOLONG:
setError(SFM_DIR_NAMETOOLONG, "The path name is too long: "+path);
break;
@@ -130,11 +121,9 @@ void DefaultSaveFileManager::checkPath(const FilesystemNode &dir) {
case EMLINK:
setError(SFM_DIR_LINKMAX, "The link count of the parent directory would exceed {LINK_MAX}: "+path);
break;
-#if !defined(__SYMBIAN32__)
case ELOOP:
setError(SFM_DIR_LOOP, "Too many symbolic links encountered while traversing the path: "+path);
break;
-#endif
case ENAMETOOLONG:
setError(SFM_DIR_NAMETOOLONG, "The path name is too long: "+path);
break;
@@ -173,11 +162,11 @@ void DefaultSaveFileManager::checkPath(const FilesystemNode &dir) {
Common::InSaveFile *DefaultSaveFileManager::openForLoading(const char *filename) {
// Ensure that the savepath is valid. If not, generate an appropriate error.
- FilesystemNode savePath(getSavePath());
+ Common::FilesystemNode savePath(getSavePath());
checkPath(savePath);
if (getError() == SFM_NO_ERROR) {
- FilesystemNode file = savePath.getChild(filename);
+ Common::FilesystemNode file = savePath.getChild(filename);
// Open the file for reading
Common::SeekableReadStream *sf = file.openForReading();
@@ -190,11 +179,11 @@ Common::InSaveFile *DefaultSaveFileManager::openForLoading(const char *filename)
Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const char *filename) {
// Ensure that the savepath is valid. If not, generate an appropriate error.
- FilesystemNode savePath(getSavePath());
+ Common::FilesystemNode savePath(getSavePath());
checkPath(savePath);
if (getError() == SFM_NO_ERROR) {
- FilesystemNode file = savePath.getChild(filename);
+ Common::FilesystemNode file = savePath.getChild(filename);
// Open the file for saving
Common::WriteStream *sf = file.openForWriting();
@@ -208,8 +197,8 @@ Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const char *filename)
bool DefaultSaveFileManager::removeSavefile(const char *filename) {
clearError();
- FilesystemNode savePath(getSavePath());
- FilesystemNode file = savePath.getChild(filename);
+ Common::FilesystemNode savePath(getSavePath());
+ Common::FilesystemNode file = savePath.getChild(filename);
// TODO: Add new method FilesystemNode::remove()
if (remove(file.getPath().c_str()) != 0) {
diff --git a/backends/saves/default/default-saves.h b/backends/saves/default/default-saves.h
index 97845c4623..c02ce588c2 100644
--- a/backends/saves/default/default-saves.h
+++ b/backends/saves/default/default-saves.h
@@ -28,6 +28,7 @@
#include "common/savefile.h"
#include "common/str.h"
+#include "common/fs.h"
/**
* Provides a default savefile manager implementation for common platforms.
@@ -54,7 +55,7 @@ protected:
* Checks the given path for read access, existence, etc.
* Sets the internal error and error message accordingly.
*/
- void checkPath(const FilesystemNode &dir);
+ void checkPath(const Common::FilesystemNode &dir);
};
#endif