Пример #1
0
void CDdsImage::Read(Framework::CStream& inputStream)
{
	uint32 signature = inputStream.Read32();
	if(signature != ' SDD')
	{
		assert(0);
		throw std::runtime_error("Invalid DDS image (Invalid signature).");
	}

	inputStream.Read(&m_header, sizeof(DDS_HEADER));
	if(m_header.size != sizeof(DDS_HEADER))
	{
		assert(0);
		throw std::runtime_error("Invalid DDS image (Invalid header size).");
	}

	if(m_header.ddspf.size != sizeof(DDS_PIXELFORMAT))
	{
		assert(0);
		throw std::runtime_error("Invalid DDS image (Invalid header size).");
	}

	const uint32 mandatoryFlags = DDS_HEADER_FLAG_CAPS | DDS_HEADER_FLAG_HEIGHT | DDS_HEADER_FLAG_WIDTH | DDS_HEADER_FLAG_PIXELFORMAT;
	if((m_header.flags & mandatoryFlags) != mandatoryFlags)
	{
		assert(0);
		throw std::runtime_error("Invalid DDS image (Missing flags).");
	}

	assert((m_header.ddspf.flags & (DDS_PIXELFORMAT_FLAG_RGB | DDS_PIXELFORMAT_FLAG_ALPHAPIXELS)) != 0);

	uint32 surfaceSize = (m_header.ddspf.rgbBitCount / 8) * m_header.width * m_header.height;

	if(m_header.caps2 & DDS_HEADER_CAP2_CUBEMAP)
	{
		const uint32 fullCubeMapFlags = 
			DDS_HEADER_CAP2_CUBEMAP_POSITIVE_X | DDS_HEADER_CAP2_CUBEMAP_NEGATIVE_X |
			DDS_HEADER_CAP2_CUBEMAP_POSITIVE_Y | DDS_HEADER_CAP2_CUBEMAP_NEGATIVE_Y |
			DDS_HEADER_CAP2_CUBEMAP_POSITIVE_Z | DDS_HEADER_CAP2_CUBEMAP_NEGATIVE_Z;
		assert((m_header.caps2 & fullCubeMapFlags) == fullCubeMapFlags);

		for(unsigned int i = 0; i < 6; i++)
		{
			SurfaceByteArray surface(surfaceSize);
			inputStream.Read(surface.data(), surfaceSize);
			m_surfaces.push_back(std::move(surface));
		}
	}
}
Пример #2
0
void CTextureSection::Read(Framework::CStream& inputStream)
{
	CBaseSection::Read(inputStream);
	inputStream.Read(m_header, sizeof(m_header));

	auto gtex = std::make_shared<CGtexData>();
	AddChild(gtex);
	gtex->Read(inputStream);
}
Пример #3
0
CDialog::DIALOGTEMPLATE CDialog::ReadDialogTemplate(Framework::CStream& stream)
{
	DIALOGTEMPLATE dialog;

	dialog.dlgVer		= stream.Read16();
	dialog.signature	= stream.Read16();

	assert(dialog.dlgVer == 1);
	assert(dialog.signature == 0xFFFF);

	dialog.helpID		= stream.Read32();
	dialog.exStyle		= stream.Read32();
	dialog.style		= stream.Read32();
	dialog.cDlgItems	= stream.Read16();
	dialog.x			= stream.Read16();
	dialog.y			= stream.Read16();
	dialog.cx			= stream.Read16();
	dialog.cy			= stream.Read16();
	
	assert((stream.Tell() & 0x01) == 0);
	dialog.menu			= ReadSzOrOrd(stream);
	
	assert((stream.Tell() & 0x01) == 0);
	dialog.windowClass	= ReadSzOrOrd(stream);
	
	assert((stream.Tell() & 0x01) == 0);
	dialog.title		= ReadString(stream);
	
	dialog.pointsize	= stream.Read16();
	dialog.weight		= stream.Read16();
	dialog.italic		= stream.Read8();
	dialog.charset		= stream.Read8();

	assert((stream.Tell() & 0x01) == 0);
	dialog.typeface		= ReadString(stream);

	//Struct has padding for alignment to DWORD boundary (only if there's other items to read)
	if(stream.GetRemainingLength() != 0)
	{
		auto currentBytePos = stream.Tell() & 0x3;
		if(currentBytePos != 0)
		{
			stream.Seek(4 - currentBytePos, Framework::STREAM_SEEK_CUR);
		}
		assert((stream.Tell() & 0x03) == 0);
	}

	uint32 itemDataLength = static_cast<uint32>(stream.GetRemainingLength());
	if(itemDataLength != 0)
	{
		dialog.dialogItemData.resize(itemDataLength);
		stream.Read(&dialog.dialogItemData[0], itemDataLength);
	}

	return dialog;
}
Пример #4
0
CBspFile::CBspFile(Framework::CStream& inputStream)
{
	uint8 signature[4];
	inputStream.Read(signature, 4);
	if(memcmp(signature, "IBSP", 4))
	{
		throw std::runtime_error("Invalid BSP. Bad signature.");
	}
	
	uint32 version = inputStream.Read32();
	assert(version == 0x2E);

	DIRENTRY dirEntries[DIRENTRY_COUNT];
	for(unsigned int i = 0; i < DIRENTRY_COUNT; i++)
	{
		dirEntries[i].offset = inputStream.Read32();
		dirEntries[i].length = inputStream.Read32();
	}

	ReadLumpData(inputStream, dirEntries[LUMP_ENTITIES], m_entities);
	ReadLumpData(inputStream, dirEntries[LUMP_PLANES], m_planes);
	ReadLumpData(inputStream, dirEntries[LUMP_NODES], m_nodes);
	ReadLumpData(inputStream, dirEntries[LUMP_LEAVES], m_leaves);
	ReadLumpData(inputStream, dirEntries[LUMP_LEAFFACES], m_leafFaces);
	ReadLumpData(inputStream, dirEntries[LUMP_TEXTURES], m_textures);
	ReadLumpData(inputStream, dirEntries[LUMP_VERTICES], m_vertices);
	ReadLumpData(inputStream, dirEntries[LUMP_MESHVERTICES], m_meshVertices);
	ReadLumpData(inputStream, dirEntries[LUMP_EFFECTS], m_effects);
	ReadLumpData(inputStream, dirEntries[LUMP_FACES], m_faces);
	ReadLumpData(inputStream, dirEntries[LUMP_LIGHTMAPS], m_lightMaps);

	//Read VISDATA
	{
		inputStream.Seek(dirEntries[LUMP_VISDATA].offset, Framework::STREAM_SEEK_SET);
		m_visData.vectorCount = inputStream.Read32();
		m_visData.vectorSize = inputStream.Read32();
		uint32 visDataSize = m_visData.vectorCount * m_visData.vectorSize;
		m_visData.vectors.resize(visDataSize);
		inputStream.Read(&m_visData.vectors[0], visDataSize);
	}
}
Пример #5
0
void CPatchFile::ExtractCompressed(Framework::CStream& outputStream, Framework::CStream& inputStream, uint32 compressedSize)
{
	z_stream zStream;
	zStream.zalloc = Z_NULL;
	zStream.zfree = Z_NULL;
	zStream.opaque = Z_NULL;
	zStream.avail_in = 0;
	zStream.next_in = Z_NULL;
	if(inflateInit(&zStream) != Z_OK)
	{
		throw std::runtime_error("zlib stream initialization error.");
	}

	const uint32 bufferSize = 0x4000;
	uint8 inBuffer[bufferSize];
	uint8 outBuffer[bufferSize];

	while(1)
	{
		if(zStream.avail_in == 0)
		{
			if(compressedSize == 0)
			{
				//EOF
				break;
			}
			uint32 toRead = std::min<uint32>(bufferSize, compressedSize);
			inputStream.Read(inBuffer, toRead);
			compressedSize -= toRead;
			zStream.avail_in = toRead;
			zStream.next_in = inBuffer;
		}

		zStream.avail_out = bufferSize;
		zStream.next_out = outBuffer;

		int ret = inflate(&zStream, Z_NO_FLUSH);
		if(ret < 0)
		{
			throw std::runtime_error("Error occured while inflating.");
			break;
		}

		int have = bufferSize - zStream.avail_out;
		outputStream.Write(outBuffer, have);
		if(ret == Z_STREAM_END)
		{
			break;
		}
	} 

	inflateEnd(&zStream);
}
Пример #6
0
void CPatchFile::ExtractUncompressed(Framework::CStream& outputStream, Framework::CStream& inputStream, uint32 compressedSize)
{
	const uint32 bufferSize = 0x4000;
	uint8 buffer[bufferSize];
	while(compressedSize != 0)
	{
		uint32 toRead = std::min<uint32>(bufferSize, compressedSize);
		inputStream.Read(buffer, toRead);
		outputStream.Write(buffer, toRead);
		compressedSize -= toRead;
	}
}
Пример #7
0
void CPatchFile::ExecuteDELD(Framework::CStream& stream)
{
	uint32 pathSize = stream.Read32_MSBF();
	std::vector<char> pathData(pathSize);
	stream.Read(pathData.data(), pathSize);
	std::string path(std::begin(pathData), std::end(pathData));

	uint32 otherData[4];
	stream.Read(otherData, sizeof(otherData));

	auto fullDirPath = m_gameLocationPath / path;
	fullDirPath.make_preferred();

	if(!boost::filesystem::exists(fullDirPath))
	{
		m_result.messages.push_back(string_format("Warning: Directory '%s' deletion requested but directory doesn't exist.", 
			fullDirPath.string().c_str()
		));
	}
	else
	{
		boost::filesystem::remove_all(fullDirPath);
	}
}
Пример #8
0
uint32 CIoman::Read(uint32 handle, uint32 size, void* buffer)
{
	CLog::GetInstance().Print(LOG_NAME, "Read(handle = %d, size = 0x%X, buffer = ptr);\r\n", handle, size);

	uint32 result = 0xFFFFFFFF;
	try
	{
		Framework::CStream* stream = GetFileStream(handle);
		result = static_cast<uint32>(stream->Read(buffer, size));
	}
	catch(const std::exception& except)
	{
		CLog::GetInstance().Print(LOG_NAME, "%s: Error occured while trying to read file : %s\r\n", __FUNCTION__, except.what());
	}
	return result;
}
Пример #9
0
void CPatchFile::DoExecute(Framework::CStream& stream)
{
	uint8 patchHeader[0x10];
	stream.Read(patchHeader, sizeof(patchHeader));

	if(
		patchHeader[0] != 0x91 && 
		patchHeader[1] != 'Z' && 
		patchHeader[2] != 'I' &&
		patchHeader[3] != 'P' &&
		patchHeader[4] != 'A' && 
		patchHeader[5] != 'T' &&
		patchHeader[6] != 'C' &&
		patchHeader[7] != 'H')
	{
		throw std::runtime_error("Invalid patch file.");
	}

	while(1)
	{
		char command[5];
		stream.Read(command, 4);
		command[4] = 0;
		if(stream.IsEOF()) break;
		if(!strcmp(command, "FHDR"))
		{
			ExecuteFHDR(stream);
		}
		else if(!strcmp(command, "DIFF"))
		{
			ExecuteDIFF(stream);
		}
		else if(!strcmp(command, "HIST"))
		{
			ExecuteHIST(stream);
		}
		else if(!strcmp(command, "APLY"))
		{
			ExecuteAPLY(stream);
		}
		else if(!strcmp(command, "ADIR"))
		{
			ExecuteADIR(stream);
		}
		else if(!strcmp(command, "DELD"))
		{
			ExecuteDELD(stream);
		}
		else if(!strcmp(command, "ETRY"))
		{
			ExecuteETRY(stream);
		}
		else
		{
			throw std::runtime_error("Unhandled command encountered.");
		}
		if(stream.IsEOF()) break;
	}

	m_result.succeeded = true;
}
Пример #10
0
void CPatchFile::ExecuteETRY(Framework::CStream& inputStream)
{
	uint32 pathSize = inputStream.Read32_MSBF();
	std::vector<char> pathData(pathSize);
	inputStream.Read(pathData.data(), pathSize);
	std::string path(std::begin(pathData), std::end(pathData));

	auto fullFilePath = m_gameLocationPath / path;
	auto fullFileDirectory = fullFilePath;
	fullFileDirectory.remove_leaf();
	fullFileDirectory.make_preferred();
	fullFilePath.make_preferred();

	if(!boost::filesystem::exists(fullFileDirectory))
	{
		m_result.messages.push_back(string_format("Warning: Directory '%s' doesn't exist. Creating.", 
			fullFileDirectory.string().c_str()
		));
		boost::filesystem::create_directories(fullFileDirectory);
	}

	if(!boost::filesystem::exists(fullFilePath))
	{
		m_result.messages.push_back(string_format("Warning: File '%s' doesn't exist. Creating.", fullFilePath.string().c_str()));
	}

	uint32 itemCount = inputStream.Read32_MSBF();
	for(unsigned int i = 0; i < itemCount; i++)
	{
		//0x41 = last hash, 0x44 = first hash, 0x4D = both hashes?
		uint32 hashMode = inputStream.Read32();
		assert(hashMode == 0x41 || hashMode == 0x44 || hashMode == 0x4D);

		uint8 srcFileHash[0x14];
		uint8 dstFileHash[0x14];
		inputStream.Read(srcFileHash, sizeof(srcFileHash));
		inputStream.Read(dstFileHash, sizeof(dstFileHash));

		//4E is no compression
		//5A is zlib compression
		uint32 compressionMode = inputStream.Read32();
		assert((compressionMode == 0x4E) || (compressionMode == 0x5A));

		uint32 compressedFileSize = inputStream.Read32_MSBF();
		uint32 previousFileSize = inputStream.Read32_MSBF();
		uint32 newFileSize = inputStream.Read32_MSBF();

		if(i != (itemCount - 1))
		{
			assert(compressedFileSize == 0);
		}
		if(compressedFileSize == 0) continue;

		//Data starts here
		{
			//Retrying here because explorer.exe can sometimes open the ffxiv*.exe files to load
			//the icons making the open operation fail if we need to patch it again.
			
			auto outputStream = CreateOutputStdStreamWithRetry(fullFilePath.native());
			if(compressionMode == 0x4E)
			{
				ExtractUncompressed(outputStream, inputStream, compressedFileSize);
			}
			else if(compressionMode == 0x5A)
			{
				ExtractCompressed(outputStream, inputStream, compressedFileSize);
			}
			else
			{
				throw std::runtime_error("Unknown compression type.");
			}
		}
	}

	inputStream.Seek(0x08, Framework::STREAM_SEEK_CUR);
}
Пример #11
0
void CPatchFile::ExecuteAPLY(Framework::CStream& stream)
{
	uint32 values[5];
	stream.Read(values, sizeof(values));
}
Пример #12
0
void CBaseSection::Read(Framework::CStream& inputStream)
{
	inputStream.Read(&m_header, sizeof(SEDB_HEADER));
	assert(m_header.sectionId == 'BDES');
}
Пример #13
0
void CStreamChunk::ReadStream(Framework::CStream& inputStream)
{
	m_data.resize(m_vertexCount * m_bytesPerVertex);
	inputStream.Read(m_data.data(), m_vertexCount * m_bytesPerVertex);
}
Пример #14
0
void CResourceSection::Read(Framework::CStream& inputStream)
{
	CBaseSection::Read(inputStream);

	SEDBRES_HEADER header = {};
	inputStream.Read(&header, sizeof(SEDBRES_HEADER));

	std::vector<SEDBRES_ENTRY> entries;
	entries.resize(header.resourceCount);
	inputStream.Read(entries.data(), header.resourceCount * sizeof(SEDBRES_ENTRY));

	uint64 basePosition = inputStream.Tell();

	assert(header.resourceCount >= 2);

	const auto& resourceTypeEntry = entries[header.resourceCount - 2];
	const auto& resourceIdEntry = entries[header.resourceCount - 1];

	std::vector<uint32> resourceTypes;
	resourceTypes.resize(header.resourceCount);
	inputStream.Seek(basePosition + resourceTypeEntry.offset, Framework::STREAM_SEEK_SET);
	inputStream.Read(resourceTypes.data(), sizeof(uint32) * header.resourceCount);

	//Read resource ids
	std::vector<std::string> resourceIds;
	for(unsigned int i = 0; i < header.resourceCount; i++)
	{
		inputStream.Seek(basePosition + resourceIdEntry.offset + (i * 0x10), Framework::STREAM_SEEK_SET);
		resourceIds.push_back(inputStream.ReadString());
	}

	//Read string table
	inputStream.Seek(basePosition + header.stringsOffset, Framework::STREAM_SEEK_SET);
	std::vector<std::string> strings;
	for(unsigned int i = 0; i < header.stringCount; i++)
	{
		strings.push_back(inputStream.ReadString());
	}

	for(unsigned int i = 0; i < header.resourceCount; i++)
	{
		const auto& entry = entries[i];
		if(entry.type == 0 || entry.size == 0) continue;
		uint32 resourceType = resourceTypes[i];
		inputStream.Seek(basePosition + entry.offset, Framework::STREAM_SEEK_SET);
		SectionPtr section;
		switch(resourceType)
		{
		case '\0trb':
		case '\0bin':
			section = std::make_shared<CResourceSection>();
			break;
		case 'sdrb':
			section = std::make_shared<CShaderSection>();
			break;
		case '\0wrb':
			section = std::make_shared<CModelSection>();
			break;
		case '\0skl':
			section = std::make_shared<CSkeletonSection>();
			break;
		case '\0phb':
			section = std::make_shared<CPhbSection>();
			break;
		case '\0txb':
			section = std::make_shared<CTextureSection>();
			break;
		default:
			assert(0);
			break;
		}
		if(section)
		{
			AddChild(section);
			section->Read(inputStream);
			section->SetResourceId(resourceIds[i]);
			section->SetResourcePath(strings[i]);
		}
	}

	inputStream.Seek(basePosition, Framework::STREAM_SEEK_SET);
}
Пример #15
0
void CSave::ReadName(Framework::CStream& inputStream)
{
    char sNameSJIS[68];
    inputStream.Read(sNameSJIS, 68);
    m_sName = string_cast_sjis(sNameSJIS);
}