size_t VirtualDiscFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size) {
	EntryMap::iterator iter = entries.find(handle);
	if (iter != entries.end())
	{
		// it's the whole iso... it could reference any of the files on the disc.
		// For now let's just open and close the files on demand. Can certainly be done
		// better though
		if (iter->second.type == VFILETYPE_ISO)
		{
			int fileIndex = getFileListIndex(iter->second.curOffset,size*2048,true);
			if (fileIndex == -1)
			{
				ERROR_LOG(FILESYS,"VirtualDiscFileSystem: Reading from unknown address in %08x at %08llx", handle, iter->second.curOffset);
				return 0;
			}

			OpenFileEntry temp;
			if (fileList[fileIndex].handler != NULL) {
				temp.handler = fileList[fileIndex].handler;
			}
			bool success = temp.Open(basePath, fileList[fileIndex].fileName, FILEACCESS_READ);

			if (!success)
			{
				ERROR_LOG(FILESYS,"VirtualDiscFileSystem: Error opening file %s", fileList[fileIndex].fileName.c_str());
				return 0;
			}

			u32 startOffset = (iter->second.curOffset-fileList[fileIndex].firstBlock)*2048;
			size_t bytesRead;

			temp.Seek(startOffset, FILEMOVE_BEGIN);

			u32 remainingSize = fileList[fileIndex].totalSize-startOffset;
			if (remainingSize < size * 2048)
			{
				// the file doesn't fill the whole last sector
				// read what's there and zero fill the rest like on a real disc
				bytesRead = temp.Read(pointer, remainingSize);
				memset(&pointer[bytesRead], 0, size * 2048 - bytesRead);
			} else {
				bytesRead = temp.Read(pointer, size * 2048);
			}

			temp.Close();

			iter->second.curOffset += size;
			return size;
		}

		size_t bytesRead = iter->second.Read(pointer, size);
		iter->second.curOffset += bytesRead;
		return bytesRead;
	} else {
		//This shouldn't happen...
		ERROR_LOG(FILESYS,"VirtualDiscFileSystem: Cannot read file that hasn't been opened: %08x", handle);
		return 0;
	}
}
void VirtualDiscFileSystem::DoState(PointerWrap &p)
{
	auto s = p.Section("VirtualDiscFileSystem", 1);
	if (!s)
		return;

	int fileListSize = (int)fileList.size();
	int entryCount = (int)entries.size();

	p.Do(fileListSize);
	p.Do(entryCount);
	p.Do(currentBlockIndex);

	FileListEntry dummy = {""};
	fileList.resize(fileListSize, dummy);

	for (int i = 0; i < fileListSize; i++)
	{
		p.Do(fileList[i].fileName);
		p.Do(fileList[i].firstBlock);
		p.Do(fileList[i].totalSize);
	}

	if (p.mode == p.MODE_READ)
	{
		entries.clear();

		for (int i = 0; i < entryCount; i++)
		{
			u32 fd = 0;
			OpenFileEntry of;

			p.Do(fd);
			p.Do(of.fileIndex);
			p.Do(of.type);
			p.Do(of.curOffset);
			p.Do(of.startOffset);
			p.Do(of.size);

			// open file
			if (of.type != VFILETYPE_ISO) {
				if (fileList[of.fileIndex].handler != NULL) {
					of.handler = fileList[of.fileIndex].handler;
				}

				bool success = of.Open(basePath, fileList[of.fileIndex].fileName, FILEACCESS_READ);
				if (!success) {
					ERROR_LOG(FILESYS, "Failed to create file handle for %s.", fileList[of.fileIndex].fileName.c_str());
				} else {
					if (of.type == VFILETYPE_LBN) {
						of.Seek(of.curOffset + of.startOffset, FILEMOVE_BEGIN);
					} else {
						of.Seek(of.curOffset, FILEMOVE_BEGIN);
					}
				}
			}

			entries[fd] = of;
		}
	} else {
		for (EntryMap::iterator it = entries.begin(), end = entries.end(); it != end; ++it)
		{
			OpenFileEntry &of = it->second;

			p.Do(it->first);
			p.Do(of.fileIndex);
			p.Do(of.type);
			p.Do(of.curOffset);
			p.Do(of.startOffset);
			p.Do(of.size);
		}
	}

	// We don't savestate handlers (loaded on fs load), but if they change, it may not load properly.
}
u32 VirtualDiscFileSystem::OpenFile(std::string filename, FileAccess access, const char *devicename)
{
	OpenFileEntry entry;
	entry.curOffset = 0;
	entry.size = 0;
	entry.startOffset = 0;

	if (filename == "")
	{
		entry.type = VFILETYPE_ISO;
		entry.fileIndex = -1;

		u32 newHandle = hAlloc->GetNewHandle();
		entries[newHandle] = entry;

		return newHandle;
	}

	if (filename.compare(0,8,"/sce_lbn") == 0)
	{
		u32 sectorStart = 0xFFFFFFFF, readSize = 0xFFFFFFFF;
		parseLBN(filename, &sectorStart, &readSize);

		entry.type = VFILETYPE_LBN;
		entry.size = readSize;

		int fileIndex = getFileListIndex(sectorStart,readSize);
		if (fileIndex == -1)
		{
			ERROR_LOG(FILESYS, "VirtualDiscFileSystem: sce_lbn used without calling fileinfo.");
			return 0;
		}
		entry.fileIndex = (u32)fileIndex;

		entry.startOffset = (sectorStart-fileList[entry.fileIndex].firstBlock)*2048;

		// now we just need an actual file handle
		if (fileList[entry.fileIndex].handler != NULL) {
			entry.handler = fileList[entry.fileIndex].handler;
		}
		bool success = entry.Open(basePath, fileList[entry.fileIndex].fileName, FILEACCESS_READ);

		if (!success) {
#ifdef _WIN32
			ERROR_LOG(FILESYS, "VirtualDiscFileSystem::OpenFile: FAILED, %i", GetLastError());
#else
			ERROR_LOG(FILESYS, "VirtualDiscFileSystem::OpenFile: FAILED");
#endif
			return 0;
		}

		// seek to start
		entry.Seek(entry.startOffset, FILEMOVE_BEGIN);

		u32 newHandle = hAlloc->GetNewHandle();
		entries[newHandle] = entry;

		return newHandle;
	}

	entry.type = VFILETYPE_NORMAL;
	entry.fileIndex = getFileListIndex(filename);

	if (entry.fileIndex != (u32)-1 && fileList[entry.fileIndex].handler != NULL) {
		entry.handler = fileList[entry.fileIndex].handler;
	}
	bool success = entry.Open(basePath, filename, access);

	if (!success) {
#ifdef _WIN32
		ERROR_LOG(FILESYS, "VirtualDiscFileSystem::OpenFile: FAILED, %i - access = %i", GetLastError(), (int)access);
#else
		ERROR_LOG(FILESYS, "VirtualDiscFileSystem::OpenFile: FAILED, access = %i", (int)access);
#endif
		//wwwwaaaaahh!!
		return 0;
	} else {
		u32 newHandle = hAlloc->GetNewHandle();
		entries[newHandle] = entry;

		return newHandle;
	}
}
示例#4
0
size_t VirtualDiscFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size, int &usec) {
	EntryMap::iterator iter = entries.find(handle);
	if (iter != entries.end()) {
		if (size < 0) {
			ERROR_LOG_REPORT(FILESYS, "Invalid read for %lld bytes from virtual umd", size);
			return 0;
		}

		// it's the whole iso... it could reference any of the files on the disc.
		// For now let's just open and close the files on demand. Can certainly be done
		// better though
		if (iter->second.type == VFILETYPE_ISO)
		{
			int fileIndex = getFileListIndex(iter->second.curOffset,size*2048,true);
			if (fileIndex == -1)
			{
				ERROR_LOG(FILESYS,"VirtualDiscFileSystem: Reading from unknown address in %08x at %08llx", handle, iter->second.curOffset);
				return 0;
			}

			OpenFileEntry temp;
			if (fileList[fileIndex].handler != NULL) {
				temp.handler = fileList[fileIndex].handler;
			}
			bool success = temp.Open(basePath, fileList[fileIndex].fileName, FILEACCESS_READ);

			if (!success)
			{
				ERROR_LOG(FILESYS,"VirtualDiscFileSystem: Error opening file %s", fileList[fileIndex].fileName.c_str());
				return 0;
			}

			u32 startOffset = (iter->second.curOffset-fileList[fileIndex].firstBlock)*2048;
			size_t bytesRead;

			temp.Seek(startOffset, FILEMOVE_BEGIN);

			u32 remainingSize = fileList[fileIndex].totalSize-startOffset;
			if (remainingSize < size * 2048)
			{
				// the file doesn't fill the whole last sector
				// read what's there and zero fill the rest like on a real disc
				bytesRead = temp.Read(pointer, remainingSize);
				memset(&pointer[bytesRead], 0, size * 2048 - bytesRead);
			} else {
				bytesRead = temp.Read(pointer, size * 2048);
			}

			temp.Close();

			iter->second.curOffset += size;
			// TODO: This probably isn't enough...
			if (abs((int)lastReadBlock_ - (int)iter->second.curOffset) > 100) {
				// This is an estimate, sometimes it takes 1+ seconds, but it definitely takes time.
				usec = 100000;
			}
			lastReadBlock_ = iter->second.curOffset;
			return size;
		}

		if (iter->second.type == VFILETYPE_LBN && iter->second.curOffset + size > iter->second.size) {
			// Clamp to the remaining size, but read what we can.
			const s64 newSize = iter->second.size - iter->second.curOffset;
			WARN_LOG(FILESYS, "VirtualDiscFileSystem: Reading beyond end of file, clamping size %lld to %lld", size, newSize);
			size = newSize;
		}

		size_t bytesRead = iter->second.Read(pointer, size);
		iter->second.curOffset += bytesRead;
		return bytesRead;
	} else {
		//This shouldn't happen...
		ERROR_LOG(FILESYS,"VirtualDiscFileSystem: Cannot read file that hasn't been opened: %08x", handle);
		return 0;
	}
}