aboutsummaryrefslogtreecommitdiff
path: root/backends/fs/psp/psp-stream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'backends/fs/psp/psp-stream.cpp')
-rw-r--r--backends/fs/psp/psp-stream.cpp291
1 files changed, 80 insertions, 211 deletions
diff --git a/backends/fs/psp/psp-stream.cpp b/backends/fs/psp/psp-stream.cpp
index 9bcbe9d7cf..8cb7dfea17 100644
--- a/backends/fs/psp/psp-stream.cpp
+++ b/backends/fs/psp/psp-stream.cpp
@@ -32,48 +32,28 @@
#include <errno.h>
-#define MIN2(a,b) ((a < b) ? a : b)
-#define MIN3(a,b,c) ( (a < b) ? (a < c ? a : c) : (b < c ? b : c) )
-
-//#define __PSP_PRINT_TO_FILE__ /* For debugging suspend stuff, we have no screen output */
-//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
+//#define __PSP_PRINT_TO_FILE__
+//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
//#define __PSP_DEBUG_PRINT__ /* For debug printouts */
-
#include "backends/platform/psp/trace.h"
-//#define DEBUG_BUFFERS /* to see the contents of the buffers being read */
-
-#ifdef DEBUG_BUFFERS
-void printBuffer(byte *ptr, uint32 len) {
- uint32 printLen = len <= 10 ? len : 10;
-
- for (int i = 0; i < printLen; i++) {
- PSP_INFO_PRINT("%x ", ptr[i]);
- }
-
- if (len > 10) {
- PSP_INFO_PRINT("... ");
- for (int i = len - 10; i < len; i++)
- PSP_INFO_PRINT("%x ", ptr[i]);
- }
-
- PSP_INFO_PRINT("\n");
-}
-#endif
-
-
PSPIoStream::PSPIoStream(const Common::String &path, bool writeMode)
- : StdioStream((void *)1), _path(path), _writeMode(writeMode),
- _ferror(false), _pos(0),
- _physicalPos(0), _fileSize(0), _inCache(false), _eos(false),
- _cacheStartOffset(-1), _cache(0),
- _errorSuspend(0), _errorSource(0),
- _errorPos(0), _errorHandle(0), _suspendCount(0) {
+ : StdioStream((void *)1), _path(path), _writeMode(writeMode) {
DEBUG_ENTER_FUNC();
- // assert(!path.empty()); // do we need this?
+ assert(!path.empty());
_handle = (void *)0; // Need to do this since base class asserts not 0.
+ _ferror = false;
+ _feof = false;
+ _pos = 0;
+
+ /* for error checking */
+ _errorSuspend = 0;
+ _errorSource = 0;
+ _errorPos = 0;
+ _errorHandle = 0;
+ _suspendCount = 0;
}
PSPIoStream::~PSPIoStream() {
@@ -83,12 +63,9 @@ PSPIoStream::~PSPIoStream() {
PSP_DEBUG_PRINT_FUNC("Suspended\n");
PowerMan.unregisterSuspend(this); // Unregister with powermanager to be suspended
- // Must do this before fclose() or resume() will reopen.
+ // Must do this before fclose() or resume() will reopen.
- fclose((FILE *)_handle); // We don't need a critical section. Worst case, the handle gets closed on its own
-
- if (_cache)
- free(_cache);
+ fclose((FILE *)_handle); // We don't need a critical section(?). Worst case, the handle gets closed on its own
PowerMan.endCriticalSection();
}
@@ -105,16 +82,6 @@ void *PSPIoStream::open() {
_handle = fopen(_path.c_str(), _writeMode ? "wb" : "rb"); // open
- if (_handle) {
- // Get the file size
- fseek((FILE *)_handle, 0, SEEK_END); // go to the end
- _fileSize = ftell((FILE *)_handle);
- fseek((FILE *)_handle, 0, SEEK_SET); // back to the beginning
-
- // Allocate the cache
- _cache = (char *)memalign(64, CACHE_SIZE);
- }
-
PowerMan.registerSuspend(this); // Register with the powermanager to be suspended
PowerMan.endCriticalSection();
@@ -124,183 +91,100 @@ void *PSPIoStream::open() {
bool PSPIoStream::err() const {
DEBUG_ENTER_FUNC();
-
- if (_ferror) // We dump since no printing to screen with suspend
- PSP_ERROR("mem_ferror[%d], source[%d], suspend error[%d], pos[%d], \
- _errorPos[%d], _errorHandle[%p], suspendCount[%d]\n",
- _ferror, _errorSource, _errorSuspend, _pos,
- _errorPos, _errorHandle, _suspendCount);
+ if (_ferror)
+ PSP_ERROR("mem_ferror[%d], source[%d], suspend error[%d], pos[%d], _errorPos[%d], _errorHandle[%p], suspendCount[%d]\n",
+ _ferror, _errorSource, _errorSuspend, _pos, _errorPos, _errorHandle, _suspendCount);
return _ferror;
}
void PSPIoStream::clearErr() {
- _ferror = false;
+ _ferror = false; // Remove regular error bit
}
bool PSPIoStream::eos() const {
- return _eos;
+ return _feof;
}
int32 PSPIoStream::pos() const {
return _pos;
}
+
int32 PSPIoStream::size() const {
- return _fileSize;
+ DEBUG_ENTER_FUNC();
+ if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ PSP_DEBUG_PRINT_FUNC("Suspended\n");
+
+ fseek((FILE *)_handle, 0, SEEK_END);
+ int32 length = ftell((FILE *)_handle);
+ fseek((FILE *)_handle, _pos, SEEK_SET);
+
+ if (_pos < 0 || length < 0) { // Check for errors
+ _errorSource = 2;
+ PSP_ERROR("pos[%d] or length[%d] < 0!\n", _pos, length);
+ _ferror = true;
+ length = -1; // If our oldPos is bad, we want length to be bad too to signal
+ clearerr((FILE *)_handle);
+ }
+
+ PowerMan.endCriticalSection();
+
+ return length;
}
bool PSPIoStream::seek(int32 offs, int whence) {
DEBUG_ENTER_FUNC();
- PSP_DEBUG_PRINT_FUNC("offset[0x%x], whence[%d], _pos[0x%x], _physPos[0x%x]\n", offs, whence, _pos, _physicalPos);
- _eos = false;
-
- int32 posToSearchFor = 0;
- switch (whence) {
- case SEEK_CUR:
- posToSearchFor = _pos;
- break;
- case SEEK_END:
- posToSearchFor = _fileSize; // unsure. Does it take us here or to EOS - 1?
- break;
- }
- posToSearchFor += offs;
-
- // Check for bad values
- if (posToSearchFor < 0) {
- _ferror = true;
- return false;
- }
-
- if (posToSearchFor > _fileSize) {
+
+ // Check if we can access the file
+ if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ PSP_DEBUG_PRINT_FUNC("Suspended\n");
+
+ int ret = fseek((FILE *)_handle, offs, whence);
+
+ if (ret != 0) {
_ferror = true;
- _eos = true;
- return false;
+ PSP_ERROR("fseek returned with [%d], non-zero\n", ret);
+ clearerr((FILE *)_handle);
+ _feof = feof((FILE *)_handle);
+ _errorSource = 3;
+ } else { // everything ok
+ _feof = false; // Reset eof flag since we know it was ok
}
-
- // See if we can find it in cache
- if (isOffsetInCache(posToSearchFor)) {
- PSP_DEBUG_PRINT("seek offset[0x%x] found in cache. Cache starts[0x%x]\n", posToSearchFor, _cacheStartOffset);
- _inCache = true;
- } else { // not in cache
- _inCache = false;
- }
- _pos = posToSearchFor;
- return true;
+
+ _pos = ftell((FILE *)_handle); // update pos
+
+ PowerMan.endCriticalSection();
+
+ return (ret == 0);
}
uint32 PSPIoStream::read(void *ptr, uint32 len) {
DEBUG_ENTER_FUNC();
- PSP_DEBUG_PRINT_FUNC("filename[%s], len[0x%x], ptr[%p]\n", _path.c_str(), len, ptr);
-
- if (_ferror || _eos)
- return 0;
-
- byte *destPtr = (byte *)ptr;
- uint32 lenFromFile = len; // how much we read from the actual file
- uint32 lenFromCache = 0; // how much we read from cache
- uint32 lenRemainingInFile = _fileSize - _pos;
-
- if (lenFromFile > lenRemainingInFile) {
- lenFromFile = lenRemainingInFile;
- _eos = true;
- }
-
- // Are we in cache?
- if (_inCache && isCacheValid()) {
- uint32 offsetInCache = _pos - _cacheStartOffset;
- // We can read at most what's in the cache or the remaining size of the file
- lenFromCache = MIN2(lenFromFile, CACHE_SIZE - offsetInCache); // unsure
-
- PSP_DEBUG_PRINT("reading 0x%x bytes from cache to %p. pos[0x%x] physPos[0x%x] cacheStart[0x%x]\n", lenFromCache, destPtr, _pos, _physicalPos, _cacheStartOffset);
-
- memcpy(destPtr, &_cache[offsetInCache], lenFromCache);
- _pos += lenFromCache;
-
- if (lenFromCache < lenFromFile) { // there's more to copy from the file
- lenFromFile -= lenFromCache;
- lenRemainingInFile -= lenFromCache; // since we moved pos
- destPtr += lenFromCache;
- } else { // we're done
-#ifdef DEBUG_BUFFERS
- printBuffer((byte *)ptr, len);
-#endif
-
- return lenFromCache; // how much we actually read
- }
- }
-
+ // Check if we can access the file
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
PSP_DEBUG_PRINT_FUNC("Suspended\n");
-
-
- synchronizePhysicalPos(); // we need to update our physical position
-
- if (lenFromFile <= MIN_READ_SIZE) { // We load the cache in case the read is small enough
- // This optimization is based on the principle that reading 1 byte is as expensive as 1000 bytes
- uint32 lenToCopyToCache = MIN2((uint32)MIN_READ_SIZE, lenRemainingInFile); // at most remaining file size
-
- PSP_DEBUG_PRINT("filling cache with 0x%x bytes from physicalPos[0x%x]. cacheStart[0x%x], pos[0x%x], fileSize[0x%x]\n", lenToCopyToCache, _physicalPos, _cacheStartOffset, _pos, _fileSize);
-
- size_t ret = fread(_cache, 1, lenToCopyToCache, (FILE *)_handle);
- if (ret != lenToCopyToCache) {
- PSP_ERROR("in filling cache, failed to get 0x%x bytes. Only got 0x%x\n", lenToCopyToCache, ret);
- _ferror = true;
- clearerr((FILE *)_handle);
- }
- _cacheStartOffset = _physicalPos;
- _inCache = true;
-
- _physicalPos += ret;
-
- PSP_DEBUG_PRINT("copying 0x%x bytes from cache to %p\n", lenFromFile, destPtr);
-
- // Copy to the destination buffer from cache
- memcpy(destPtr, _cache, lenFromFile);
- _pos += lenFromFile;
-
- } else { // Too big for cache. No caching
- PSP_DEBUG_PRINT("reading 0x%x bytes from file to %p. Pos[0x%x], physPos[0x%x]\n", lenFromFile, destPtr, _pos, _physicalPos);
- size_t ret = fread(destPtr, 1, lenFromFile, (FILE *)_handle);
-
- _physicalPos += ret; // Update pos
- _pos = _physicalPos;
-
- if (ret != lenFromFile) { // error
- PSP_ERROR("fread returned [0x%x] instead of len[0x%x]\n", ret, lenFromFile);
+
+ PSP_DEBUG_PRINT_FUNC("filename[%s], len[%d]\n", _path.c_str(), len);
+
+ size_t ret = fread((byte *)ptr, 1, len, (FILE *)_handle);
+
+ _pos += ret; // Update pos
+
+ if (ret != len) { // Check for eof
+ _feof = feof((FILE *)_handle);
+ if (!_feof) { // It wasn't an eof. Must be an error
_ferror = true;
clearerr((FILE *)_handle);
- _errorSource = 4;
+ _pos = ftell((FILE *)_handle); // Update our position
+ _errorSource = 4;
+ PSP_ERROR("fread returned ret[%d] instead of len[%d]\n", ret, len);
}
- _inCache = false;
}
PowerMan.endCriticalSection();
-#ifdef DEBUG_BUFFERS
- printBuffer((byte *)ptr, len);
-#endif
-
- return lenFromCache + lenFromFile; // total of what was copied
-}
-
-// TODO: Test if seeking backwards/forwards has any effect on performance
-inline bool PSPIoStream::synchronizePhysicalPos() {
- if (_pos != _physicalPos) {
- if (fseek((FILE *)_handle, _pos - _physicalPos, SEEK_CUR) != 0)
- return false;
- _physicalPos = _pos;
- }
-
- return true;
-}
-
-inline bool PSPIoStream::isOffsetInCache(uint32 offset) {
- if (_cacheStartOffset != -1 &&
- offset >= (uint32)_cacheStartOffset &&
- offset < (uint32)(_cacheStartOffset + CACHE_SIZE))
- return true;
- return false;
+ return ret;
}
uint32 PSPIoStream::write(const void *ptr, uint32 len) {
@@ -309,30 +193,18 @@ uint32 PSPIoStream::write(const void *ptr, uint32 len) {
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
PSP_DEBUG_PRINT_FUNC("Suspended\n");
- PSP_DEBUG_PRINT_FUNC("filename[%s], len[0x%x]\n", _path.c_str(), len);
+ PSP_DEBUG_PRINT_FUNC("filename[%s], len[%d]\n", _path.c_str(), len);
- if (_ferror)
- return 0;
-
- _eos = false; // we can't have eos with write
- synchronizePhysicalPos();
-
size_t ret = fwrite(ptr, 1, len, (FILE *)_handle);
- // If we're making the file bigger, adjust the size
- if (_physicalPos + (int)ret > _fileSize)
- _fileSize = _physicalPos + ret;
- _physicalPos += ret;
- _pos = _physicalPos;
- _inCache = false;
- _cacheStartOffset = -1; // invalidate cache
+ _pos += ret;
if (ret != len) { // Set error
_ferror = true;
clearerr((FILE *)_handle);
_pos = ftell((FILE *)_handle); // Update pos
_errorSource = 5;
- PSP_ERROR("fwrite returned[0x%x] instead of len[0x%x]\n", ret, len);
+ PSP_ERROR("fwrite returned[%d] instead of len[%d]\n", ret, len);
}
PowerMan.endCriticalSection();
@@ -352,7 +224,7 @@ bool PSPIoStream::flush() {
_ferror = true;
clearerr((FILE *)_handle);
_errorSource = 6;
- PSP_ERROR("fflush returned ret[%d]\n", ret);
+ PSP_ERROR("fflush returned ret[%u]\n", ret);
}
PowerMan.endCriticalSection();
@@ -414,9 +286,6 @@ int PSPIoStream::resume() {
// Resume our previous position
if (_handle > 0 && _pos > 0) {
ret = fseek((FILE *)_handle, _pos, SEEK_SET);
-
- _physicalPos = _pos;
- _inCache = false;
if (ret != 0) { // Check for problem
_errorSuspend = ResumeError;