aboutsummaryrefslogtreecommitdiff
path: root/backends/fs
diff options
context:
space:
mode:
authorJoost Peters2009-08-17 12:57:37 +0000
committerJoost Peters2009-08-17 12:57:37 +0000
commit62bcb2e51b45e744d0b27b124179cb6ec435188d (patch)
tree1abfe70cf002ed9649293607de019bab518cd38d /backends/fs
parente548e71ba1092a1091da79c5d4652c9d52578e65 (diff)
downloadscummvm-rg350-62bcb2e51b45e744d0b27b124179cb6ec435188d.tar.gz
scummvm-rg350-62bcb2e51b45e744d0b27b124179cb6ec435188d.tar.bz2
scummvm-rg350-62bcb2e51b45e744d0b27b124179cb6ec435188d.zip
Commit (slightly) modified version of patch #2831248: Allow suspend/resume for PSP
svn-id: r43477
Diffstat (limited to 'backends/fs')
-rw-r--r--backends/fs/psp/psp-fs-factory.cpp8
-rw-r--r--backends/fs/psp/psp-fs.cpp62
-rw-r--r--backends/fs/psp/psp-stream.cpp230
-rw-r--r--backends/fs/psp/psp-stream.h70
4 files changed, 360 insertions, 10 deletions
diff --git a/backends/fs/psp/psp-fs-factory.cpp b/backends/fs/psp/psp-fs-factory.cpp
index 27bee4de86..7ed84de034 100644
--- a/backends/fs/psp/psp-fs-factory.cpp
+++ b/backends/fs/psp/psp-fs-factory.cpp
@@ -34,7 +34,13 @@ AbstractFSNode *PSPFilesystemFactory::makeRootFileNode() const {
AbstractFSNode *PSPFilesystemFactory::makeCurrentDirectoryFileNode() const {
char buf[MAXPATHLEN];
- return getcwd(buf, MAXPATHLEN) ? new PSPFilesystemNode(buf) : NULL;
+ char * ret = 0;
+
+ PowerMan.beginCriticalSection();
+ ret = getcwd(buf, MAXPATHLEN);
+ PowerMan.endCriticalSection();
+
+ return (ret ? new PSPFilesystemNode(buf) : NULL);
}
AbstractFSNode *PSPFilesystemFactory::makeFileNodePath(const Common::String &path) const {
diff --git a/backends/fs/psp/psp-fs.cpp b/backends/fs/psp/psp-fs.cpp
index f5ff65c9fa..03247e86ad 100644
--- a/backends/fs/psp/psp-fs.cpp
+++ b/backends/fs/psp/psp-fs.cpp
@@ -26,7 +26,8 @@
#include "engines/engine.h"
#include "backends/fs/abstract-fs.h"
-#include "backends/fs/stdiostream.h"
+#include "backends/fs/psp/psp-stream.h"
+#include "backends/platform/psp/powerman.h"
#include <sys/stat.h>
#include <unistd.h>
@@ -35,6 +36,9 @@
#define ROOT_PATH "ms0:/"
+#include "backends/platform/psp/trace.h"
+
+
/**
* Implementation of the ScummVM file system API based on PSPSDK API.
*
@@ -61,13 +65,13 @@ public:
*/
PSPFilesystemNode(const Common::String &p, bool verify = true);
- virtual bool exists() const { return access(_path.c_str(), F_OK) == 0; }
+ virtual bool exists() const;
virtual Common::String getDisplayName() const { return _displayName; }
virtual Common::String 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 bool isReadable() const;
+ virtual bool isWritable() const;
virtual AbstractFSNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
@@ -94,11 +98,44 @@ PSPFilesystemNode::PSPFilesystemNode(const Common::String &p, bool verify) {
if (verify) {
struct stat st;
+ PowerMan.beginCriticalSection();
_isValid = (0 == stat(_path.c_str(), &st));
+ PowerMan.endCriticalSection();
_isDirectory = S_ISDIR(st.st_mode);
}
}
+bool PSPFilesystemNode::exists() const {
+ int ret = 0;
+
+ PowerMan.beginCriticalSection(); // Make sure to block in case of suspend
+ ret = access(_path.c_str(), F_OK);
+ PowerMan.endCriticalSection();
+
+ return ret == 0;
+}
+
+bool PSPFilesystemNode::isReadable() const {
+ int ret = 0;
+
+ PowerMan.beginCriticalSection(); // Make sure to block in case of suspend
+ ret = access(_path.c_str(), R_OK);
+ PowerMan.endCriticalSection();
+
+ return ret == 0;
+}
+
+bool PSPFilesystemNode::isWritable() const {
+ int ret = 0;
+
+ PowerMan.beginCriticalSection(); // Make sure to block in case of suspend
+ ret = access(_path.c_str(), W_OK);
+ PowerMan.endCriticalSection();
+
+ return ret == 0;
+}
+
+
AbstractFSNode *PSPFilesystemNode::getChild(const Common::String &n) const {
// FIXME: Pretty lame implementation! We do no error checking to speak
// of, do not check if this is a special node, etc.
@@ -117,6 +154,10 @@ bool PSPFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool
//TODO: honor the hidden flag
+ bool ret = true;
+
+ PowerMan.beginCriticalSection(); // Make sure to block in case of suspend
+
int dfd = sceIoDopen(_path.c_str());
if (dfd > 0) {
SceIoDirent dir;
@@ -149,10 +190,13 @@ bool PSPFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool
}
sceIoDclose(dfd);
- return true;
- } else {
- return false;
+ ret = true;
+ } else { // dfd <= 0
+ ret = false;
}
+
+ PowerMan.endCriticalSection();
+ return ret;
}
AbstractFSNode *PSPFilesystemNode::getParent() const {
@@ -166,11 +210,11 @@ AbstractFSNode *PSPFilesystemNode::getParent() const {
}
Common::SeekableReadStream *PSPFilesystemNode::createReadStream() {
- return StdioStream::makeFromPath(getPath().c_str(), false);
+ return PSPIoStream::makeFromPath(getPath(), false);
}
Common::WriteStream *PSPFilesystemNode::createWriteStream() {
- return StdioStream::makeFromPath(getPath().c_str(), true);
+ return PSPIoStream::makeFromPath(getPath(), true);
}
#endif //#ifdef __PSP__
diff --git a/backends/fs/psp/psp-stream.cpp b/backends/fs/psp/psp-stream.cpp
new file mode 100644
index 0000000000..fac4067f46
--- /dev/null
+++ b/backends/fs/psp/psp-stream.cpp
@@ -0,0 +1,230 @@
+/* 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$
+ *
+ */
+#ifdef __PSP__
+
+#include "backends/fs/psp/psp-stream.h"
+#include "backends/platform/psp/trace.h"
+#include <errno.h>
+
+PSPIoStream::PSPIoStream(const Common::String &path, bool writeMode)
+: StdioStream((void *)1), _path(path), _writeMode(writeMode) {
+
+ assert(!path.empty());
+
+ _handle = (void *)0; // Need to do this since base class asserts not 0.
+
+ PowerMan.registerSuspend(this); // Register with the powermanager to be suspended
+
+}
+
+PSPIoStream::~PSPIoStream() {
+ PowerMan.unregisterSuspend(this); // Unregister with powermanager to be suspended
+ // Must do this before fclose() or resume() will reopen.
+
+ fclose((FILE *)_handle);
+}
+
+// Function to open the file pointed to by the path.
+//
+//
+void * PSPIoStream::open() {
+ if (PowerMan.beginCriticalSection()==PowerManager::Blocked) {
+ // No need to open. Just return the _handle resume() already opened.
+ PSPDebugTrace("Suspended in PSPIoStream::open\n");
+ } else {
+ _handle = fopen(_path.c_str(), _writeMode ? "wb" : "rb"); // open
+ }
+
+ PowerMan.endCriticalSection();
+
+ return _handle;
+}
+
+bool PSPIoStream::err() const {
+ bool ret;
+
+ if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ PSPDebugTrace("Suspended in PSPIoStream::err()\n");
+
+ ret = ferror((FILE *)_handle) != 0;
+
+ PowerMan.endCriticalSection();
+
+ return ret;
+}
+
+void PSPIoStream::clearErr() {
+ if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ PSPDebugTrace("Suspended in PSPIoStream::clearErr()\n");
+
+ clearerr((FILE *)_handle);
+
+ PowerMan.endCriticalSection();
+}
+
+bool PSPIoStream::eos() const {
+ bool ret;
+
+ if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ PSPDebugTrace("Suspended in PSPIoStream::eos()\n");
+
+ ret = feof((FILE *)_handle) != 0;
+
+ PowerMan.endCriticalSection();
+
+ return ret;
+}
+
+int32 PSPIoStream::pos() const {
+ int32 ret;
+
+ if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ PSPDebugTrace("Suspended in PSPIoStream::pos()\n");
+
+ ret = ftell((FILE *)_handle);
+
+ PowerMan.endCriticalSection();
+
+ return ret;
+}
+
+
+int32 PSPIoStream::size() const {
+ if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ PSPDebugTrace("Suspended in PSPIoStream::size()\n");
+
+ int32 oldPos = ftell((FILE *)_handle);
+ fseek((FILE *)_handle, 0, SEEK_END);
+ int32 length = ftell((FILE *)_handle);
+ fseek((FILE *)_handle, oldPos, SEEK_SET);
+
+ PowerMan.endCriticalSection();
+
+ return length;
+}
+
+bool PSPIoStream::seek(int32 offs, int whence) {
+ int ret = 0;
+
+ // Check if we can access the file
+ if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ PSPDebugTrace("Suspended in PSPIoStream::seek()\n");
+
+ ret = fseek((FILE *)_handle, offs, whence);
+
+ PowerMan.endCriticalSection();
+
+ return ret == 0;
+}
+
+uint32 PSPIoStream::read(void *ptr, uint32 len) {
+ int ret = 0;
+
+ // Check if we can access the file
+ if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ PSPDebugTrace("Suspended in PSPIoStream::read()\n");
+
+ ret = fread((byte *)ptr, 1, len, (FILE *)_handle);
+
+ PowerMan.endCriticalSection();
+
+ return ret;
+}
+
+uint32 PSPIoStream::write(const void *ptr, uint32 len) {
+ int ret = 0;
+
+ // Check if we can access the file
+ if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ PSPDebugTrace("Suspended in PSPIoStream::read()\n");
+
+ ret = fwrite(ptr, 1, len, (FILE *)_handle);
+
+ PowerMan.endCriticalSection();
+
+ return ret;
+}
+
+bool PSPIoStream::flush() {
+ int ret = 0;
+
+ // Check if we can access the file
+ if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ PSPDebugTrace("Suspended in PSPIoStream::read()\n");
+
+ ret = fflush((FILE *)_handle);
+
+ PowerMan.endCriticalSection();
+
+ return ret == 0;
+}
+
+// For the PSP, since we're building in suspend support, we moved opening
+// the actual file to an open function since we need an actual PSPIoStream object to suspend.
+//
+PSPIoStream *PSPIoStream::makeFromPath(const Common::String &path, bool writeMode) {
+ PSPIoStream *stream = new PSPIoStream(path, writeMode);
+
+ if (stream->open() > 0) {
+ return stream;
+ } else {
+ delete stream;
+ return 0;
+ }
+}
+
+/*
+ * Function to suspend the IO stream (called by PowerManager)
+ */
+int PSPIoStream::suspend() {
+ if (_handle > 0) {
+ _pos = ftell((FILE *)_handle); // Save our position
+ fclose((FILE *)_handle); // close our file descriptor
+ _handle = 0; // Set handle to null
+ }
+
+ return 0;
+}
+
+/*
+ * Function to resume the IO stream (called by Power Manager)
+ */
+int PSPIoStream::resume() {
+ int ret = 0;
+
+ // We reopen our file descriptor
+ _handle = fopen(_path.c_str(), _writeMode ? "wb" : "rb");
+ if (_handle <= 0) {
+ PSPDebugTrace("PSPIoStream::resume(): Couldn't reopen file %s\n", _path.c_str());
+ ret = -1;;
+ }
+
+ // Resume our previous position
+ if(_handle > 0) fseek((FILE *)_handle, _pos, SEEK_SET);
+
+ return ret;
+}
+
+#endif /* __PSP__ */
diff --git a/backends/fs/psp/psp-stream.h b/backends/fs/psp/psp-stream.h
new file mode 100644
index 0000000000..0363c92416
--- /dev/null
+++ b/backends/fs/psp/psp-stream.h
@@ -0,0 +1,70 @@
+/* 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 PSPSTREAM_H_
+#define PSPSTREAM_H_
+
+#include "backends/fs/stdiostream.h"
+#include "backends/platform/psp/powerman.h"
+#include "common/list.h"
+
+/*
+ * Class to handle special suspend/resume needs of PSP IO Streams
+ */
+class PSPIoStream : public StdioStream, public Suspendable {
+protected:
+ Common::String _path; /* Need to maintain for reopening after suspend */
+ bool _writeMode; /* "" */
+ unsigned int _pos; /* "" */
+
+public:
+ /**
+ * Given a path, invoke fopen on that path and wrap the result in a
+ * PSPIoStream instance.
+ */
+ static PSPIoStream *makeFromPath(const Common::String &path, bool writeMode);
+
+ PSPIoStream(const Common::String &path, bool writeMode);
+ virtual ~PSPIoStream();
+
+ void * open(); // open the file pointed to by the file path
+
+ bool err() const;
+ void clearErr();
+ bool eos() const;
+
+ virtual uint32 write(const void *dataPtr, uint32 dataSize);
+ virtual bool flush();
+
+ virtual int32 pos() const;
+ virtual int32 size() const;
+ virtual bool seek(int32 offs, int whence = SEEK_SET);
+ virtual uint32 read(void *dataPtr, uint32 dataSize);
+
+ int suspend(); /* Suspendable interface (power manager) */
+ int resume(); /* " " */
+};
+
+#endif /* PSPSTREAM_H_ */