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; +}  | 
