Пример #1
0
uint32 CGIF::ProcessPacket(uint8* memory, uint32 address, uint32 end, const CGsPacketMetadata& packetMetadata)
{
	std::unique_lock<std::mutex> pathLock(m_pathMutex);
	static CGSHandler::RegisterWriteList writeList;

#ifdef PROFILE
	CProfilerZone profilerZone(m_gifProfilerZone);
#endif

#ifdef _DEBUG
	CLog::GetInstance().Print(LOG_NAME, "Received GIF packet on path %d at 0x%0.8X of 0x%0.8X bytes.\r\n", 
		packetMetadata.pathIndex, address, end - address);
#endif

	writeList.clear();

	uint32 start = address;
	while(address < end)
	{
		if(m_loops == 0)
		{
			if(m_eop)
			{
				m_eop = false;
				break;
			}

			//We need to update the registers
			TAG tag = *reinterpret_cast<TAG*>(&memory[address]);
			address += 0x10;

			m_loops		= tag.loops;
			m_cmd		= tag.cmd;
			m_regs		= tag.nreg;
			m_regList	= tag.regs;
			m_eop		= (tag.eop != 0);

			if(m_cmd != 1)
			{
				if(tag.pre != 0)
				{
					writeList.push_back(CGSHandler::RegisterWrite(GS_REG_PRIM, static_cast<uint64>(tag.prim)));
				}
			}

			if(m_regs == 0) m_regs = 0x10;
			m_regsTemp = m_regs;
			continue;
		}
		switch(m_cmd)
		{
		case 0x00:
			address += ProcessPacked(writeList, memory, address, end);
			break;
		case 0x01:
			address += ProcessRegList(writeList, memory, address, end);
			break;
		case 0x02:
		case 0x03:
			address += ProcessImage(memory, address, end);
			break;
		}
	}

	if(m_loops == 0)
	{
		if(m_eop)
		{
			m_eop = false;
		}
	}

	if((m_gs != nullptr) && !writeList.empty())
	{
		m_gs->WriteRegisterMassively(writeList.data(), static_cast<unsigned int>(writeList.size()), &packetMetadata);
	}

#ifdef _DEBUG
	CLog::GetInstance().Print(LOG_NAME, "Processed 0x%0.8X bytes.\r\n", address - start);
#endif

	return address - start;
}
Пример #2
0
uint32 CGIF::ProcessPacket(uint8* memory, uint32 address, uint32 end, const CGsPacketMetadata& packetMetadata)
{
	std::unique_lock<std::mutex> pathLock(m_pathMutex);
	static CGSHandler::RegisterWriteList writeList;
	static const auto flushWriteList =
		[] (CGSHandler* gs, const CGsPacketMetadata& packetMetadata)
		{
			if((gs != nullptr) && !writeList.empty())
			{
				gs->WriteRegisterMassively(writeList.data(), static_cast<unsigned int>(writeList.size()), &packetMetadata);
			}
			writeList.clear();
		};

#ifdef PROFILE
	CProfilerZone profilerZone(m_gifProfilerZone);
#endif

#if defined(_DEBUG) && defined(DEBUGGER_INCLUDED)
	CLog::GetInstance().Print(LOG_NAME, "Received GIF packet on path %d at 0x%0.8X of 0x%0.8X bytes.\r\n", 
		packetMetadata.pathIndex, address, end - address);
#endif

	writeList.clear();

	uint32 start = address;
	while(address < end)
	{
		if(m_loops == 0)
		{
			if(m_eop)
			{
				m_eop = false;
				break;
			}

			//We need to update the registers
			TAG tag = *reinterpret_cast<TAG*>(&memory[address]);
			address += 0x10;

			m_loops		= tag.loops;
			m_cmd		= tag.cmd;
			m_regs		= tag.nreg;
			m_regList	= tag.regs;
			m_eop		= (tag.eop != 0);

			if(m_cmd != 1)
			{
				if(tag.pre != 0)
				{
					writeList.push_back(CGSHandler::RegisterWrite(GS_REG_PRIM, static_cast<uint64>(tag.prim)));
				}
			}

			if(m_regs == 0) m_regs = 0x10;
			m_regsTemp = m_regs;
			continue;
		}
		switch(m_cmd)
		{
		case 0x00:
			address += ProcessPacked(writeList, memory, address, end);
			break;
		case 0x01:
			address += ProcessRegList(writeList, memory, address, end);
			break;
		case 0x02:
		case 0x03:
			//We need to flush our list here because image data can be embedded in a GIF packet
			//that specifies pixel transfer information in GS registers (and that has to be send first)
			//This is done by FFX
			flushWriteList(m_gs, packetMetadata);
			address += ProcessImage(memory, address, end);
			break;
		}
	}

	if(m_loops == 0)
	{
		if(m_eop)
		{
			m_eop = false;
		}
	}

	flushWriteList(m_gs, packetMetadata);

#ifdef _DEBUG
	CLog::GetInstance().Print(LOG_NAME, "Processed 0x%0.8X bytes.\r\n", address - start);
#endif

	return address - start;
}