예제 #1
0
void Ps2File::cacheReadSync() {
	if (_cacheOpRunning) {
		int res = fio.sync(_fd);
		assert(res >= 0);
		_bytesInCache += res;
		_physFilePos += res;
		_cacheOpRunning = false;
	}
}
예제 #2
0
Ps2WriteFile::~Ps2WriteFile(void) {
	if ((_fd >= 0) && (_bytesInCache)) {
		fio.write(_fd, _cacheBuf, _bytesInCache);
		int wrRes = fio.sync(_fd);
		if (wrRes != (int)_bytesInCache) // too late to return an error
			printf("Cache flush on fclose(): Unable to write %d cached bytes to mc, only %d bytes written\n", _bytesInCache, wrRes);
	}
	if (_fd >= 0)
		fio.close(_fd);
	free(_cacheBuf);
}
예제 #3
0
uint32 Ps2ReadFile::read(void *dest, uint32 len) {
	WaitSema(_sema);
	uint8 *destBuf = (uint8*)dest;
	if ((_filePos < _cachePos) || (_filePos + len > _cachePos + _bytesInCache))
		cacheReadSync(); // we have to read from CD, sync cache.

	while (len && (_filePos != _fileSize)) {
		if ((_filePos >= _cachePos) && (_filePos < _cachePos + _bytesInCache)) { // read from cache
			uint32 staPos = (_cacheOfs + (_filePos - _cachePos)) % CACHE_SIZE;
			uint32 cpyLen = _bytesInCache - (_filePos - _cachePos);
			if (cpyLen > len)
				cpyLen = len;
			if (staPos + cpyLen > CACHE_SIZE)
				cpyLen = CACHE_SIZE - staPos;

			assert(cpyLen);
			memcpy(destBuf, _cacheBuf + staPos, cpyLen);
			_filePos += cpyLen;
			destBuf += cpyLen;
			_readBytesBlock += len;
			len -= cpyLen;
		} else { // cache miss
			assert(!_cacheOpRunning);
			if (_physFilePos != _filePos) {
				if ((_filePos < _physFilePos) || (_filePos > _physFilePos + (CACHE_SIZE / 2)))
					_readBytesBlock = 0; // reset cache hit count

				_physFilePos = _filePos & ~READ_ALIGN_MASK;
				if (fio.seek(_fd, _physFilePos, SEEK_SET) != (int)_physFilePos)
					break; // read beyond EOF
			}

			int doRead = len + (_filePos - _physFilePos);
			doRead = (doRead + READ_ALIGN_MASK) & ~READ_ALIGN_MASK;

			if (doRead > MAX_READ_STEP)
				doRead = MAX_READ_STEP;
			if (doRead < 2048)
				doRead = 2048;

			fio.read(_fd, _cacheBuf, doRead);
			_cachePos = _physFilePos;
			_cacheOfs = 0;
			_bytesInCache = fio.sync(_fd);
			_physFilePos += _bytesInCache;
			if (!_bytesInCache)
				break; // EOF
		}
	}
	cacheReadAhead();
	SignalSema(_sema);
	return destBuf - (uint8*)dest;
}
예제 #4
0
Ps2File::~Ps2File() {
	uint32 w;
	if (_fd >= 0) {

		if (_mode != O_RDONLY) {
			fio.seek(_fd, 0, SEEK_SET);
			fio.write(_fd, _cacheBuf, _filePos);
			w = fio.sync(_fd);
			dbg_printf("flushed wbuf: %x of %x\n", w, _filePos);
		}

		fio.close(_fd);
		uint32 r = fio.sync(_fd);
		dbg_printf("close [%d] - sync'd = %d\n", _fd, r);
	}

	free(_cacheBuf);

#ifdef __PS2_FILE_SEMA__
	DeleteSema(_sema);
#endif
}
예제 #5
0
uint32 Ps2WriteFile::write(const void *src, uint32 len) {
	uint32 size = len;
	uint8 *srcBuf = (uint8*)src;
	while (size) {
		uint32 doCpy = (len > CACHE_SIZE - _bytesInCache) ? (CACHE_SIZE - _bytesInCache) : len;
		if (doCpy) {
			memcpy(_cacheBuf + _bytesInCache, srcBuf, doCpy);
			_bytesInCache += doCpy;
			srcBuf += doCpy;
			size -= doCpy;
		}

		if (_bytesInCache == CACHE_SIZE) {
			fio.write(_fd, _cacheBuf, _bytesInCache);
			if (fio.sync(_fd) != (int)_bytesInCache) {
				printf("Unable to flush %d cached bytes to memory card!\n", _bytesInCache);
				return 0;
			}
			_filePos += _bytesInCache;
			_bytesInCache = 0;
		}
	}
	return len;
}
예제 #6
0
bool Ps2File::open(const char *name, int mode) {
#if 1
	_fd = fio.open(name, mode);

	dbg_printf("open %s [%d]\n", name, _fd);

	if (_fd >= 0) {
		_mode = mode;
		_filePos = 0;

		if (_mode == O_RDONLY) {
			_fileSize = fio.seek(_fd, 0, SEEK_END);
			fio.seek(_fd, 0, SEEK_SET);
		}
		else
			_fileSize = 0;

		dbg_printf("  _mode = %x\n", _mode);
		dbg_printf("  _fileSize = %d\n", _fileSize);
		// dbg_printf("  _filePos = %d\n", _filePos);

		return true;
	}

	return false;
#else
	uint32 r;

	// hack: FIO does not reports size for RW (?)
	_fd = fio.open(name, O_RDONLY);
	if (_fd >= 0) {
		_fileSize = fio.seek(_fd, 0, SEEK_END);
		fio.seek(_fd, 0, SEEK_SET); /* rewind ! */

		if (_fileSize && mode != O_RDONLY) {
			fio.read(_fd, _cacheBuf, _fileSize);
			r = fio.sync(_fd);
			dbg_printf(" sz=%d, read=%d\n", _fileSize, r);
			assert(r == _fileSize);
		}

		fio.close(_fd);
	}
	else
		_fileSize = 0; /* new file */

	_fd = fio.open(name, mode);

	dbg_printf("open %s [%d]\n", name, _fd);

	if (_fd >= 0) {
		_mode = mode;
		_filePos = 0;

		if (_fileSize) { /* existing data */
			if (mode == O_RDONLY) {
				/* DANGER: for w* modes it will truncate your fine files */
				fio.seek(_fd, 0, SEEK_SET);
			}
			else if (_mode & O_APPEND) {
				fio.seek(_fd, 0, _fileSize);
				_filePos = _fileSize;
			}
			#if 0 /* file already trunc'd when opened as w* -> moved up */
			if (mode != O_RDONLY) {
				fio.read(_fd, _cacheBuf, _fileSize);
				r = fio.sync(_fd);
				dbg_printf(" sz=%d, read=%d\n", _fileSize, r);
				assert(r == _fileSize);
				// _fileSize = fio.seek(_fd, 0, SEEK_END);
			}
			#endif
		}

		dbg_printf("  _mode = %x\n", _mode);
		dbg_printf("  _fileSize = %d\n", _fileSize);
		dbg_printf("  _filePos = %d\n", _filePos);

		return true;
	} else
		return false;
#endif
}
예제 #7
0
uint32 Ps2File::read(void *dest, uint32 len) {
	// uint32 r=0, d=0, ds=0, sz=0;
#ifdef __PS2_FILE_SEMA__
	WaitSema(_sema);
#endif

#ifdef __PS2_FILE_DEBUG__
	dbg_printf("read (1) : _filePos = %d\n", _filePos);
	dbg_printf("read (1) : _cachePos = %d\n", _cachePos);
#endif

	if (len == 0) {
#ifdef __PS2_FILE_SEMA__
		SignalSema(_sema);
#endif
		return 0;
	}

	if (_filePos >= _fileSize) {
		_eof = true;
#ifdef __PS2_FILE_SEMA__
		SignalSema(_sema);
#endif
		return 0;
	}

	if ((_filePos+len) > _fileSize) {
		len = _fileSize-_filePos;
		_eof = true;
	}

	uint8 *destBuf = (uint8 *)dest;
	if ((_filePos < _cachePos) || (_filePos + len > _cachePos + _bytesInCache))
		cacheReadSync(); // we have to read from CD, sync cache.

	while (len && (_filePos != _fileSize)) {
		if ((_filePos >= _cachePos) && (_filePos < _cachePos + _bytesInCache)) { // read from cache
			uint32 staPos = (_cacheOfs + (_filePos - _cachePos)) % CACHE_SIZE;
			uint32 cpyLen = _bytesInCache - (_filePos - _cachePos);
			if (cpyLen > len)
				cpyLen = len;
			if (staPos + cpyLen > CACHE_SIZE)
				cpyLen = CACHE_SIZE - staPos;

			assert(cpyLen);
			memcpy(destBuf, _cacheBuf + staPos, cpyLen);
			_filePos += cpyLen;
			destBuf += cpyLen;
			_readBytesBlock += len;
			len -= cpyLen;
		} else { // cache miss
			assert(!_cacheOpRunning);
			if (_physFilePos != _filePos) {
				if ((_filePos < _physFilePos) || (_filePos > _physFilePos + (CACHE_SIZE / 2)))
					_readBytesBlock = 0; // reset cache hit count

				_physFilePos = _filePos & ~READ_ALIGN_MASK;
				if (fio.seek(_fd, _physFilePos, SEEK_SET) != (int)_physFilePos)
					break; // read beyond EOF
			}

			int doRead = len + (_filePos - _physFilePos);
			doRead = (doRead + READ_ALIGN_MASK) & ~READ_ALIGN_MASK;

			if (doRead > MAX_READ_STEP)
				doRead = MAX_READ_STEP;
			if (doRead < 2048)
				doRead = 2048;

			fio.read(_fd, _cacheBuf, doRead);
			_cachePos = _physFilePos;
			_cacheOfs = 0;
			_bytesInCache = fio.sync(_fd);
			_physFilePos += _bytesInCache;
			if (!_bytesInCache)
				break; // EOF
		}
	}
#ifndef ENABLE_PROFILING
	// doesn't play nice with -pg
	cacheReadAhead();
#endif
#ifdef __PS2_FILE_SEMA__
	SignalSema(_sema);
#endif
	return destBuf - (uint8 *)dest;
}