diff options
Diffstat (limited to 'backends/fs/psp/psp-stream.cpp')
-rw-r--r-- | backends/fs/psp/psp-stream.cpp | 291 |
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; |