Ps2ReadFile::~Ps2ReadFile(void) { if (_cacheOpRunning) cacheReadSync(); free(_cacheBuf); if (_fd >= 0) fio.close(_fd); DeleteSema(_sema); }
void Ps2File::cacheReadAhead() { if (_cacheOpRunning) { // there's already some cache read running if (fio.poll(_fd)) // did it finish? cacheReadSync(); // yes. } if ((!_cacheOpRunning) && ((_readBytesBlock >= CACHE_READ_THRESHOLD) || _stream) && fio.fioAvail()) { // the engine seems to do sequential reads and there are no other I/Os going on. read ahead. uint32 cachePosEnd = _cachePos + _bytesInCache; if (_cachePos > _filePos) return; // there was a seek in the meantime, don't cache. if (cachePosEnd - _filePos >= CACHE_FILL_MIN) return; // cache is full enough. if (cachePosEnd == _fileSize) return; // can't read beyond EOF. assert(cachePosEnd < _fileSize); if (_cachePos + _bytesInCache <= _filePos) { _cacheOfs = _bytesInCache = 0; _cachePos = cachePosEnd = _filePos & ~READ_ALIGN_MASK; assert(_filePos == _physFilePos); } else { uint32 cacheDiff = _filePos - _cachePos; assert(_bytesInCache >= cacheDiff); cacheDiff &= ~READ_ALIGN_MASK; _bytesInCache -= cacheDiff; _cachePos += cacheDiff; _cacheOfs = (_cacheOfs + cacheDiff) % CACHE_SIZE; } if (_physFilePos != cachePosEnd) { sioprintf("unexpected _physFilePos %d cache %d %d\n", _physFilePos, _cacheOfs, _bytesInCache); // assert(!(cachePosEnd & READ_ALIGN_MASK)); // romeo _physFilePos = fio.seek(_fd, cachePosEnd, SEEK_SET); if (_physFilePos != cachePosEnd) { sioprintf("cache seek error: seek to %d instead of %d, fs = %d\n", _physFilePos, cachePosEnd, _fileSize); return; } } uint32 cacheDest = (_cacheOfs + _bytesInCache) % CACHE_SIZE; uint32 cacheRead = CACHE_SIZE - _bytesInCache; if (cacheDest + cacheRead > CACHE_SIZE) cacheRead = CACHE_SIZE - cacheDest; if (cacheRead > MAX_READ_STEP) cacheRead = MAX_READ_STEP; assert((!(cacheRead & READ_ALIGN_MASK)) && cacheRead); _cacheOpRunning = true; fio.read(_fd, _cacheBuf + cacheDest, cacheRead); } }
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; }
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; }