diff options
author | Robert Göffringmann | 2008-03-03 00:41:59 +0000 |
---|---|---|
committer | Robert Göffringmann | 2008-03-03 00:41:59 +0000 |
commit | 3b27b9fa438611c3a05fcf2d07a3dfde6be192fa (patch) | |
tree | 8605c47d67b779fb33ce4dda3a64a7d3caecdb4d /backends/platform/ps2/savefile.cpp | |
parent | fc91de07dfdfe6bd29edadf739f324f30f5624d0 (diff) | |
download | scummvm-rg350-3b27b9fa438611c3a05fcf2d07a3dfde6be192fa.tar.gz scummvm-rg350-3b27b9fa438611c3a05fcf2d07a3dfde6be192fa.tar.bz2 scummvm-rg350-3b27b9fa438611c3a05fcf2d07a3dfde6be192fa.zip |
the ps2 changes from the 0.11.1 release, plus some bugfixes and cleanup.
svn-id: r31034
Diffstat (limited to 'backends/platform/ps2/savefile.cpp')
-rw-r--r-- | backends/platform/ps2/savefile.cpp | 815 |
1 files changed, 137 insertions, 678 deletions
diff --git a/backends/platform/ps2/savefile.cpp b/backends/platform/ps2/savefile.cpp index 425a4ae09f..5ee724cd3f 100644 --- a/backends/platform/ps2/savefile.cpp +++ b/backends/platform/ps2/savefile.cpp @@ -32,192 +32,15 @@ #include <ucl/ucl.h> #include <libmc.h> #include "backends/platform/ps2/savefile.h" +#include "backends/platform/ps2/rawsavefile.h" #include "backends/platform/ps2/Gs2dScreen.h" #include "backends/platform/ps2/systemps2.h" -#include "common/scummsys.h" - -extern void *_gp; +#include "backends/platform/ps2/savefilemgr.h" +#include "backends/platform/ps2/ps2debug.h" +#include "backends/fs/abstract-fs.h" #define UCL_MAGIC 0x314C4355 -#define PORT 0 -#define SLOT 0 -// port 0, slot 0: memory card in first slot. - -void sioprintf(const char *zFormat, ...); - -class McAccess { -public: - McAccess(int port, int slot); - ~McAccess(void); - int open(const char *name, int mode); - int close(int fd); - int size(int fd); - int read(int fd, void *buf, int size); - int write(int fd, const void *buf, int size); - int mkDir(const char *name); - int getDir(const char *name, unsigned int mode, int max, void *dest); - int getInfo(int *type, int *free, int *format); - int remove(const char *name); -private: - int _sema; - int _port, _slot; -}; - -McAccess::McAccess(int port, int slot) { - _port = port; - _slot = slot; - ee_sema_t newSema; - newSema.init_count = 1; - newSema.max_count = 1; - _sema = CreateSema(&newSema); - - assert(mcInit(MC_TYPE_MC) >= 0); -} - -McAccess::~McAccess(void) { - DeleteSema(_sema); -} - -int McAccess::open(const char *name, int mode) { - int res; - WaitSema(_sema); - mcOpen(_port, _slot, name, mode); - mcSync(0, NULL, &res); - SignalSema(_sema); - return res; -} - -int McAccess::close(int fd) { - int res; - WaitSema(_sema); - mcClose(fd); - mcSync(0, NULL, &res); - SignalSema(_sema); - return res; -} - -int McAccess::size(int fd) { - int res, size; - WaitSema(_sema); - mcSeek(fd, 0, SEEK_END); - mcSync(0, NULL, &size); - mcSeek(fd, 0, SEEK_SET); - mcSync(0, NULL, &res); - SignalSema(_sema); - assert(res == 0); - return size; -} - -int McAccess::read(int fd, void *buf, int size) { - int res; - WaitSema(_sema); - mcRead(fd, buf, size); - mcSync(0, NULL, &res); - SignalSema(_sema); - return res; -} - -int McAccess::write(int fd, const void *buf, int size) { - int res; - WaitSema(_sema); - mcWrite(fd, buf, size); - mcSync(0, NULL, &res); - SignalSema(_sema); - return res; -} - -int McAccess::mkDir(const char *name) { - int res; - WaitSema(_sema); - mcMkDir(_port, _slot, name); - mcSync(0, NULL, &res); - SignalSema(_sema); - return res; -} - -int McAccess::remove(const char *name) { - int res; - WaitSema(_sema); - mcDelete(_port, _slot, name); - mcSync(0, NULL, &res); - SignalSema(_sema); - return res; -} - -int McAccess::getDir(const char *name, unsigned int mode, int max, void *dest) { - int res; - WaitSema(_sema); - mcGetDir(_port, _slot, name, mode, max, (mcTable*)dest); - mcSync(0, NULL, &res); - SignalSema(_sema); - return res; -} - -int McAccess::getInfo(int *type, int *free, int *format) { - int res; - WaitSema(_sema); - mcGetInfo(_port, _slot, type, free, format); - mcSync(0, NULL, &res); - SignalSema(_sema); - return res; -} - -class UclOutSaveFile : public Common::OutSaveFile { -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); -private: - OSystem_PS2 *_system; - Gs2dScreen *_screen; - McAccess *_mc; - int _fd; - uint8 *_buf; - uint32 _bufSize, _bufPos; - bool _ioFailed, _wasFlushed; - char _fileName[128]; -}; - -class UclInSaveFile : public Common::InSaveFile { -public: - UclInSaveFile(const char *filename, Gs2dScreen *screen, McAccess *mc); - 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 uint32 pos(void) const; - virtual uint32 size(void) const; - virtual void seek(int pos, int whence = SEEK_SET); -private: - Gs2dScreen *_screen; - McAccess *_mc; - uint8 *_buf; - uint32 _bufSize, _bufPos; - bool _ioFailed; -}; - -class AutoSaveFile : public Common::OutSaveFile { -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) {} -private: - Ps2SaveFileManager *_saveMan; - char _fileName[256]; - uint8 *_buf; - uint32 _bufSize, _bufPos; -}; - AutoSaveFile::AutoSaveFile(Ps2SaveFileManager *saveMan, const char *filename) { strcpy(_fileName, filename); _saveMan = saveMan; @@ -244,400 +67,36 @@ uint32 AutoSaveFile::write(const void *ptr, uint32 size) { return size; } -#define MAX_MC_ENTRIES 16 - -void runSaveThread(Ps2SaveFileManager *param); -Ps2SaveFileManager::Ps2SaveFileManager(OSystem_PS2 *system, Gs2dScreen *screen) { - _system = system; +UclInSaveFile::UclInSaveFile(const char *filename, Gs2dScreen *screen, McAccess *mcAccess) : RawReadFile(mcAccess) { _screen = screen; - _mc = new McAccess(0, 0); - - _mcDirList = (mcTable*)memalign(64, MAX_MC_ENTRIES * sizeof(mcTable)); - _mcDirName[0] = '\0'; - _mcCheckTime = 0; - _mcNeedsUpdate = true; - - for (int mcCheckCount = 0; mcCheckCount < 3; mcCheckCount++) { - /* retry mcGetInfo 3 times. It slows down startup without mc considerably, - but cheap 3rd party memory cards apparently fail to get detected once in a while */ - - int mcType, mcFree, mcFormat; - int res = _mc->getInfo(&mcType, &mcFree, &mcFormat); - - if ((res == 0) || (res == -1)) { // mc okay - _mcPresent = true; - printf("MC okay, result = %d. Type %d, Free %d, Format %d\n", res, mcType, mcFree, mcFormat); - checkMainDirectory(); - break; - } else { - _mcPresent = false; - printf("MC failed, not present or not formatted, code %d\n", res); - } - } - - // create save thread - ee_sema_t newSema; - newSema.init_count = 0; - newSema.max_count = 1; - _autoSaveSignal = CreateSema(&newSema); - _autoSaveBuf = NULL; - _autoSaveSize = 0; - _systemQuit = false; - - ee_thread_t saveThread, thisThread; - ReferThreadStatus(GetThreadId(), &thisThread); - - saveThread.initial_priority = thisThread.current_priority + 1; - saveThread.stack_size = 8 * 1024; - _autoSaveStack = malloc(saveThread.stack_size); - saveThread.stack = _autoSaveStack; - saveThread.func = (void *)runSaveThread; - saveThread.gp_reg = &_gp; - - _autoSaveTid = CreateThread(&saveThread); - assert(_autoSaveTid >= 0); - StartThread(_autoSaveTid, this); -} - -Ps2SaveFileManager::~Ps2SaveFileManager(void) { -} - -void Ps2SaveFileManager::checkMainDirectory(void) { - // verify that the main directory (scummvm config + icon) exists - int ret, fd; - _mcNeedsUpdate = true; - ret = _mc->getDir("/ScummVM/*", 0, MAX_MC_ENTRIES, _mcDirList); - printf("/ScummVM/* res = %d\n", ret); - if (ret <= 0) { // assume directory doesn't exist - printf("Dir doesn't exist\n"); - ret = _mc->mkDir("/ScummVM"); - if (ret >= 0) { - fd = _mc->open("/ScummVM/scummvm.icn", O_WRONLY | O_CREAT); - if (fd >= 0) { - uint16 icoSize; - uint16 *icoBuf = decompressIconData(&icoSize); - ret = _mc->write(fd, icoBuf, icoSize * 2); - _mc->close(fd); - free(icoBuf); - - printf(".icn written\n"); - setupIcon("/ScummVM/icon.sys", "scummvm.icn", "ScummVM", "Configuration"); - } else - printf("Can't create icon file: %d\n", fd); - } else - printf("can't create scummvm directory: %d\n", ret); - } -} - -void Ps2SaveFileManager::splitPath(const char *fileName, char *dir, char *name) { - strcpy(dir, fileName); - char *ext = strchr(dir, '.'); - if (ext) { - *ext = '\0'; - ext++; - } - if (ext && *ext) - sprintf(name, "%s.ucl", ext); - else - strcpy(name, "save.ucl"); -} - -bool Ps2SaveFileManager::mcReadyForDir(const char *dir) { - if (_mcNeedsUpdate || ((_system->getMillis() - _mcCheckTime) > 2000) || !_mcPresent) { - // check if memory card was exchanged/removed in the meantime - int mcType, mcFree, mcFormat, mcResult; - mcResult = _mc->getInfo(&mcType, &mcFree, &mcFormat); - if (mcResult != 0) { // memory card was exchanged - _mcNeedsUpdate = true; - if (mcResult == -1) { // yes, it was exchanged - checkMainDirectory(); // make sure ScummVM dir and icon are there - } else { // no memorycard in slot or not formatted or something like that - _mcPresent = false; - printf("MC not found, error code %d\n", mcResult); - return false; - } - } - _mcPresent = true; - _mcCheckTime = _system->getMillis(); - } - if (_mcNeedsUpdate || strcmp(_mcDirName, dir)) { - strcpy(_mcDirName, dir); - char dirStr[256]; - sprintf(dirStr, "/ScummVM-%s/*", dir); - _mcEntries = _mc->getDir(dirStr, 0, MAX_MC_ENTRIES, _mcDirList); - _mcNeedsUpdate = false; - } - return (_mcEntries >= 0); -} - -Common::InSaveFile *Ps2SaveFileManager::openForLoading(const char *filename) { - _screen->wantAnim(true); - - char dir[256], name[256]; - splitPath(filename, dir, name); - if (mcReadyForDir(dir)) { - bool fileExists = false; - for (int i = 0; i < _mcEntries; i++) - if (strcmp(name, (char*)_mcDirList[i].name) == 0) - fileExists = true; - if (fileExists) { - char fullName[256]; - sprintf(fullName, "/ScummVM-%s/%s", dir, name); - UclInSaveFile *file = new UclInSaveFile(fullName, _screen, _mc); - if (file) { - if (!file->ioFailed()) - return file; - else - delete file; - } - } else - printf("file %s (%s) doesn't exist\n", filename, name); - } - _screen->wantAnim(false); - return NULL; -} - -Common::OutSaveFile *Ps2SaveFileManager::openForSaving(const char *filename) { - int res; - char dir[256], name[256]; - - _screen->wantAnim(true); - splitPath(filename, dir, name); - - if (!mcReadyForDir(dir)) { - if (_mcPresent) { // directory doesn't seem to exist yet - char fullPath[256]; - sprintf(fullPath, "/ScummVM-%s", dir); - res = _mc->mkDir(fullPath); - char icoSysDest[256], saveDesc[256]; - sprintf(icoSysDest, "%s/icon.sys", fullPath); - strcpy(saveDesc, dir); - if ((saveDesc[0] >= 'a') && (saveDesc[0] <= 'z')) - saveDesc[0] += 'A' - 'a'; - setupIcon(icoSysDest, "../ScummVM/scummvm.icn", saveDesc, "Savegames"); - } - } - - if (_mcPresent) { - char fullPath[256]; - sprintf(fullPath, "/ScummVM-%s/%s", dir, name); - if (strstr(filename, ".s00") || strstr(filename, ".ASD") || strstr(filename, ".asd")) { - // this is an autosave - AutoSaveFile *file = new AutoSaveFile(this, fullPath); - return file; - } else { - UclOutSaveFile *file = new UclOutSaveFile(fullPath, _system, _screen, _mc); - if (!file->ioFailed()) { - // we're creating a file, mc will have to be updated next time - _mcNeedsUpdate = true; - return file; + _ioFailed = true; + + if (bufOpen(filename)) { + if ((_size > 8) && (*(uint32 *)_buf == UCL_MAGIC)) { + uint32 resSize = *(uint32 *)(_buf + 4); + uint8 *decBuf = (uint8 *)malloc(resSize + 2048); + int res = ucl_nrv2e_decompress_8(_buf + 8, _size - 8, decBuf, &resSize, NULL); + if ((res >= 0) && (resSize == *(uint32 *)(_buf + 4))) { + free(_buf); + _buf = decBuf; + _size = resSize; + _ioFailed = false; + _pos = 0; } else - delete file; - } - } - - _screen->wantAnim(false); - return NULL; -} - -void Ps2SaveFileManager::removeSavefile(const char *filename) { - TODO: Implement this. -} - -Common::StringList Ps2SaveFileManager::listSavefiles(const char *pattern) { - TODO: Implement this. If you don't understand what it should do, just ask - (e.g. on scummvm-devel or Fingolfin). It should be pretty simple if you - use Common::matchString from common/util.h and read the Doxygen docs, - then combine this with the old code below... - -/* -void Ps2SaveFileManager::listSavefiles(const char *prefix, bool *marks, int num) { - _screen->wantAnim(true); - - int mcType, mcFree, mcFormat, mcResult; - mcResult = _mc->getInfo(&mcType, &mcFree, &mcFormat); - - memset(marks, false, num * sizeof(bool)); - - if ((mcResult == 0) || (mcResult == -1)) { - // there's a memory card in the slot. - if (mcResult == -1) - _mcNeedsUpdate = true; - - mcTable *mcEntries = (mcTable*)memalign(64, sizeof(mcTable) * MAX_MC_ENTRIES); - - char dirStr[256], ext[256], mcSearchStr[256]; - strcpy(dirStr, prefix); - char *pos = strchr(dirStr, '.'); - if (pos) { - strcpy(ext, pos + 1); - *pos = '\0'; - } else - ext[0] = '\0'; - sprintf(mcSearchStr, "/ScummVM-%s/%s*", dirStr, ext); - - int numEntries = _mc->getDir(mcSearchStr, 0, MAX_MC_ENTRIES, mcEntries); - - int searchLen = strlen(ext); - for (int i = 0; i < numEntries; i++) - if ((((char*)mcEntries[i].name)[0] != '.') && stricmp((char*)mcEntries[i].name, "icon.sys")) { - char *stopCh; - int destNum = (int)strtoul((char*)mcEntries[i].name + searchLen, &stopCh, 10); - if ((!stopCh) || strcmp(stopCh, ".ucl")) - printf("unexpected end %s in name %s, search %s\n", stopCh, (char*)mcEntries[i].name, prefix); - if (destNum < num) - marks[destNum] = true; - } - free(mcEntries); - } - _screen->wantAnim(false); -} -*/ - - -bool Ps2SaveFileManager::setupIcon(const char *dest, const char *ico, const char *descr1, const char *descr2) { - mcIcon icon_sys; - memset(&icon_sys, 0, sizeof(mcIcon)); - memcpy(icon_sys.head, "PS2D", 4); - char title[256]; - if (!stricmp("SAVEGAME", descr1)) { // these are broken sword 1 savegames - sprintf(title, "BSword1\n%s", descr2); - icon_sys.nlOffset = 8; - } else { - sprintf(title, "%s\n%s", descr1, descr2); - icon_sys.nlOffset = strlen(descr1) + 1; - } - strcpy_sjis((short*)&(icon_sys.title), title); - icon_sys.trans = 0x10; - memcpy(icon_sys.bgCol, _bgcolor, sizeof(_bgcolor)); - memcpy(icon_sys.lightDir, _lightdir, sizeof(_lightdir)); - memcpy(icon_sys.lightCol, _lightcol, sizeof(_lightcol)); - memcpy(icon_sys.lightAmbient, _ambient, sizeof(_ambient)); - strcpy((char*)icon_sys.view, ico); - strcpy((char*)icon_sys.copy, ico); - strcpy((char*)icon_sys.del, ico); - - int fd, res; - fd = _mc->open(dest, O_WRONLY | O_CREAT); - if (fd >= 0) { - res = _mc->write(fd, &icon_sys, sizeof(icon_sys)); - _mc->close(fd); - return (res == sizeof(icon_sys)); - } else - return false; -} - -uint16 *Ps2SaveFileManager::decompressIconData(uint16 *size) { - uint16 inPos = 1; - uint16 *rleData = (uint16*)_rleIcoData; - uint16 resSize = rleData[0]; - uint16 *resData = (uint16*)malloc(resSize * sizeof(uint16)); - uint16 outPos = 0; - while (outPos < resSize) { - uint16 len = rleData[inPos++]; - while (len--) - resData[outPos++] = 0x7FFF; - len = rleData[inPos++]; - while (len--) - resData[outPos++] = rleData[inPos++]; - } - *size = resSize; - assert(outPos == resSize); - return resData; -} - -void runSaveThread(Ps2SaveFileManager *param) { - param->saveThread(); -} - -void Ps2SaveFileManager::writeSaveNonblocking(char *name, void *buf, uint32 size) { - if (buf && size && !_systemQuit) { - strcpy(_autoSaveName, name); - assert(!_autoSaveBuf); - _autoSaveBuf = (uint8*)malloc(size); - memcpy(_autoSaveBuf, buf, size); - _autoSaveSize = size; - SignalSema(_autoSaveSignal); - } -} - -void Ps2SaveFileManager::saveThread(void) { - while (!_systemQuit) { - WaitSema(_autoSaveSignal); - if (_autoSaveBuf && _autoSaveSize) { - UclOutSaveFile *outSave = new UclOutSaveFile(_autoSaveName, _system, _screen, _mc); - if (!outSave->ioFailed()) { - outSave->write(_autoSaveBuf, _autoSaveSize); - outSave->flush(); - } - if (outSave->ioFailed()) - _system->msgPrintf(5000, "Writing autosave to %s failed", _autoSaveName); - delete outSave; - free(_autoSaveBuf); - _autoSaveBuf = NULL; - _autoSaveSize = 0; - _mcNeedsUpdate = true; // we've created a file, mc will have to be updated - _screen->wantAnim(false); - } - } - ExitThread(); -} - -void Ps2SaveFileManager::quit(void) { - _systemQuit = true; - ee_thread_t statSave, statThis; - ReferThreadStatus(GetThreadId(), &statThis); - ChangeThreadPriority(_autoSaveTid, statThis.current_priority - 1); - - do { // wait until thread called ExitThread() - SignalSema(_autoSaveSignal); - ReferThreadStatus(_autoSaveTid, &statSave); - } while (statSave.status != 0x10); - - DeleteThread(_autoSaveTid); - free(_autoSaveStack); -} - -UclInSaveFile::UclInSaveFile(const char *filename, Gs2dScreen *screen, McAccess *mc) { - _screen = screen; - _mc = mc; - int fd = _mc->open(filename, O_RDONLY); - _buf = NULL; - _bufSize = _bufPos = 0; - _ioFailed = false; - - if (fd >= 0) { - int srcSize = _mc->size(fd); - if (srcSize > 8) { - int res; - uint8 *tmpBuf = (uint8*)memalign(64, srcSize); - res = _mc->read(fd, tmpBuf, srcSize); - if ((res == srcSize) && (*(uint32*)tmpBuf == UCL_MAGIC)) { - uint32 resLen = _bufSize = *(uint32*)(tmpBuf + 4); - _buf = (uint8*)malloc(_bufSize + 2048); - res = ucl_nrv2e_decompress_8(tmpBuf + 8, srcSize - 8, _buf, &resLen, NULL); - if ((res < 0) || (resLen != _bufSize)) { - printf("Unable to decompress file %s (%d -> %d) error code %d\n", filename, srcSize, _bufSize, res); - free(_buf); - _buf = NULL; - _bufSize = 0; - } - } - free(tmpBuf); + free(decBuf); } - _mc->close(fd); } - if (!_buf) { - printf("Invalid savegame %s\n", filename); - _ioFailed = true; + if (_ioFailed) { + if (_buf) + free(_buf); + _buf = NULL; + _size = -1; } } UclInSaveFile::~UclInSaveFile(void) { - if (_buf) - free(_buf); _screen->wantAnim(false); } @@ -650,98 +109,57 @@ void UclInSaveFile::clearIOFailed(void) { } bool UclInSaveFile::eos(void) const { - return _bufPos == _bufSize; + return bufTell() == bufSize(); } uint32 UclInSaveFile::pos(void) const { - return _bufPos; + return bufTell(); } uint32 UclInSaveFile::size(void) const { - return _bufSize; + return bufSize(); } void UclInSaveFile::seek(int pos, int whence) { - int destPos; - switch (whence) { - case SEEK_SET: - destPos = pos; - break; - case SEEK_CUR: - destPos = _bufPos + pos; - break; - case SEEK_END: - destPos = _bufSize + pos; - break; - default: - return; - } - if ((destPos >= 0) && (destPos <= (int)_bufSize)) - _bufPos = (uint32)destPos; + bufSeek(pos, whence); } uint32 UclInSaveFile::read(void *ptr, uint32 size) { - if (_buf) { - uint32 bytesRemain = _bufSize - _bufPos; - if (size > bytesRemain) { - size = bytesRemain; - _ioFailed = true; - } - memcpy(ptr, _buf + _bufPos, size); - _bufPos += size; - return size; - } else { - _ioFailed = true; - return 0; - } + return (uint32)bufRead(ptr, (int)size); } void UclInSaveFile::skip(uint32 offset) { - if (_buf) { - if (_bufPos + offset <= _bufSize) - _bufPos += offset; - else - _bufPos = _bufSize; - } + bufSeek(offset, SEEK_CUR); } -UclOutSaveFile::UclOutSaveFile(const char *filename, OSystem_PS2 *system, Gs2dScreen *screen, McAccess *mc) { +UclOutSaveFile::UclOutSaveFile(const char *filename, OSystem_PS2 *system, Gs2dScreen *screen, McAccess *mc) : RawWriteFile(mc) { _screen = screen; _system = system; - _mc = mc; - _bufPos = 0; - _fd = _mc->open(filename, O_WRONLY | O_CREAT); - if (_fd >= 0) { - _bufSize = 65536; - _buf = (uint8*)malloc(_bufSize); - _ioFailed = false; - strcpy(_fileName, filename); - } else { - _ioFailed = true; - _bufSize = 0; - _buf = NULL; - } + strcpy(_fileName, filename); + + _ioFailed = !bufOpen(filename); + _wasFlushed = false; } UclOutSaveFile::~UclOutSaveFile(void) { - if (_buf) { - if (_bufPos) { - printf("Engine didn't call SaveFile::flush()\n"); - flush(); - if (ioFailed()) { - // 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"); - } + if (_pos != 0) { + printf("Engine didn't call SaveFile::flush()\n"); + flush(); + if (ioFailed()) { + // 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"); } - free(_buf); } - if (_fd >= 0) - _mc->close(_fd); _screen->wantAnim(false); } +uint32 UclOutSaveFile::write(const void *ptr, uint32 size) { + bufWrite(ptr, (int)size); + return size; +} + bool UclOutSaveFile::ioFailed(void) const { return _ioFailed; } @@ -751,63 +169,104 @@ void UclOutSaveFile::clearIOFailed(void) { } void UclOutSaveFile::flush(void) { - int res; - - if (_bufPos) { + if (_pos != 0) { if (_wasFlushed) { - // the engine flushed this file and afterwards wrote more data. - // this is unsupported because it results in savefiles that consist - // of two or more compressed segments. - printf("Error: 2nd call to UclOutSaveFile::flush!\n"); - res = -1; - } else { - uint32 compSize = _bufPos * 2; - uint8 *compBuf = (uint8*)memalign(64, compSize + 8); - *(uint32*)(compBuf + 0) = UCL_MAGIC; - *(uint32*)(compBuf + 4) = _bufPos; // uncompressed size - res = ucl_nrv2e_99_compress(_buf, _bufPos, compBuf + 8, &compSize, NULL, 10, NULL, NULL); - if (res >= 0) { - res = _mc->write(_fd, compBuf, compSize + 8); - if (res != (int)compSize + 8) { - printf("flush: write failed, %d != %d\n", res, compSize + 8); - res = -1; - } - } else - printf("Unable to compress %d bytes of savedata, errorcode %d\n", _bufPos, res); - free(compBuf); - _bufPos = 0; + printf("Multiple calls to UclOutSaveFile::flush!\n"); + _ioFailed = true; + return; } + uint32 compSize = _pos * 2; + uint8 *compBuf = (uint8*)memalign(64, compSize + 8); + *(uint32*)(compBuf + 0) = UCL_MAGIC; + *(uint32*)(compBuf + 4) = _pos; // uncompressed size + int res = ucl_nrv2e_99_compress(_buf, _pos, compBuf + 8, &compSize, NULL, 10, NULL, NULL); + assert(res >= 0); - if (res < 0) { - _ioFailed = true; + free(_buf); + _buf = compBuf; + _size = _pos * 2; + _pos = compSize + 8; + if (!bufFlush()) { printf("UclOutSaveFile::flush failed!\n"); - if (_fd >= 0) { - // the file is broken; delete it - _mc->close(_fd); - res = _mc->remove(_fileName); - if (res == 0) - printf("File %s: remove ok\n", _fileName); - else - printf("File %s: remove error %d\n", _fileName, res); - _fd = -1; - } + _ioFailed = true; + removeFile(); } + _wasFlushed = true; } } -uint32 UclOutSaveFile::write(const void *ptr, uint32 size) { - assert(_bufPos <= _bufSize); - uint32 bytesFree = _bufSize - _bufPos; - if (bytesFree < size) { - uint32 allocBytes = (size > 32 * 1024) ? size : 32 * 1024; - _bufSize += allocBytes; - _buf = (uint8*)realloc(_buf, _bufSize); - bytesFree = _bufSize - _bufPos; - } - assert(bytesFree >= size); - memcpy(_buf + _bufPos, ptr, size); - _bufPos += size; - return size; +/* ----------------------------------------- Glue Classes for POSIX Memory Card Access ----------------------------------------- */ + +Ps2McReadFile::Ps2McReadFile(Ps2SaveFileManager *saveMan) : RawReadFile(saveMan->getMcAccess()), Ps2File(-1) { } +Ps2McReadFile::~Ps2McReadFile(void) { +} +bool Ps2McReadFile::open(const char *name) { + return bufOpen(name); +} + +uint32 Ps2McReadFile::read(void *dest, uint32 len) { + return (uint32)bufRead(dest, (int)len); +} + +uint32 Ps2McReadFile::write(const void *src, uint32 len) { + printf("Write access on Ps2McReadFile!\n"); + return 0; +} + +uint32 Ps2McReadFile::tell(void) { + return bufTell(); +} + +uint32 Ps2McReadFile::size(void) { + return bufSize(); +} + +int Ps2McReadFile::seek(int32 offset, int origin) { + return bufSeek(offset, origin); +} + +bool Ps2McReadFile::eof(void) { + return bufTell() == bufSize(); +} + + +Ps2McWriteFile::Ps2McWriteFile(Ps2SaveFileManager *saveMan) : RawWriteFile(saveMan->getMcAccess()), Ps2File(-1) { +} + +Ps2McWriteFile::~Ps2McWriteFile() { +} + +bool Ps2McWriteFile::open(const char *name) { + return bufOpen(name); +} + +uint32 Ps2McWriteFile::read(void *dest, uint32 len) { + printf("Read request on Ps2McWriteFile!\n"); + return 0; +} + +uint32 Ps2McWriteFile::write(const void *src, uint32 len) { + bufWrite(src, (int)len); + return len; +} + +uint32 Ps2McWriteFile::tell(void) { + return bufTell(); +} + +uint32 Ps2McWriteFile::size(void) { + return bufTell(); +} + +int Ps2McWriteFile::seek(int32 offset, int origin) { + printf("SEEK Request on Ps2McWriteFile!\n"); + SleepThread(); + return 0; +} + +bool Ps2McWriteFile::eof(void) { + return true; +} |