Пример #1
0
uint32 CGIF::ProcessRegList(CGSHandler::RegisterWriteList& writeList, uint8* memory, uint32 address, uint32 end)
{
	uint32 start = address;

	while(m_loops != 0)
	{
		for(uint32 j = 0; j < m_regs; j++)
		{
			assert(address < end);

			uint128 packet;
			uint32 nRegDesc = (uint32)((m_regList >> (j * 4)) & 0x0F);

			packet.nV[0] = *(uint32*)&memory[address + 0x00];
			packet.nV[1] = *(uint32*)&memory[address + 0x04];
			address += 0x08;

			if(nRegDesc == 0x0F) continue;

			writeList.push_back(CGSHandler::RegisterWrite(static_cast<uint8>(nRegDesc), packet.nD0));
		}

		m_loops--;
	}

	//Align on qword boundary
	if(address & 0x0F)
	{
		address += 8;
	}

	return address - start;
}
Пример #2
0
uint32 CGIF::ProcessPacked(CGSHandler::RegisterWriteList& writeList, uint8* memory, uint32 address, uint32 end)
{
	uint32 start = address;

	while((m_loops != 0) && (address < end))
	{
		while((m_regsTemp != 0) && (address < end))
		{
			uint64 temp = 0;
			uint32 regDesc = (uint32)((m_regList >> ((m_regs - m_regsTemp) * 4)) & 0x0F);

			uint128 packet = *(uint128*)&memory[address];
			address += 0x10;

			m_regsTemp--;

			switch(regDesc)
			{
			case 0x00:
				//PRIM
				writeList.push_back(CGSHandler::RegisterWrite(GS_REG_PRIM, packet.nV0));
				break;
			case 0x01:
				//RGBA
				temp  = (packet.nV[0] & 0xFF);
				temp |= (packet.nV[1] & 0xFF) << 8;
				temp |= (packet.nV[2] & 0xFF) << 16;
				temp |= (packet.nV[3] & 0xFF) << 24;
				temp |= ((uint64)m_qtemp << 32);
				writeList.push_back(CGSHandler::RegisterWrite(GS_REG_RGBAQ, temp));
				break;
			case 0x02:
				//ST
				m_qtemp = packet.nV2;
				writeList.push_back(CGSHandler::RegisterWrite(GS_REG_ST, packet.nD0));
				break;
			case 0x03:
				//UV
				temp  = (packet.nV[0] & 0x7FFF);
				temp |= (packet.nV[1] & 0x7FFF) << 16;
				writeList.push_back(CGSHandler::RegisterWrite(GS_REG_UV, temp));
				break;
			case 0x04:
				//XYZF2
				temp  = (packet.nV[0] & 0xFFFF);
				temp |= (packet.nV[1] & 0xFFFF) << 16;
				temp |= (uint64)(packet.nV[2] & 0x0FFFFFF0) << 28;
				temp |= (uint64)(packet.nV[3] & 0x00000FF0) << 52;
				if(packet.nV[3] & 0x8000)
				{
					writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZF3, temp));
				}
				else
				{
					writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZF2, temp));
				}
				break;
			case 0x05:
				//XYZ2
				temp  = (packet.nV[0] & 0xFFFF);
				temp |= (packet.nV[1] & 0xFFFF) << 16;
				temp |= (uint64)(packet.nV[2] & 0xFFFFFFFF) << 32;
				if(packet.nV[3] & 0x8000)
				{
					writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZ3, temp));
				}
				else
				{
					writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZ2, temp));
				}
				break;
			case 0x06:
				//TEX0_1
				writeList.push_back(CGSHandler::RegisterWrite(GS_REG_TEX0_1, packet.nD0));
				break;
			case 0x07:
				//TEX0_2
				writeList.push_back(CGSHandler::RegisterWrite(GS_REG_TEX0_2, packet.nD0));
				break;
			case 0x08:
				//CLAMP_1
				writeList.push_back(CGSHandler::RegisterWrite(GS_REG_CLAMP_1, packet.nD0));
				break;
			case 0x0D:
				//XYZ3
				writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZ3, packet.nD0));
				break;
			case 0x0E:
				//A + D
				if(m_gs != NULL)
				{
					writeList.push_back(CGSHandler::RegisterWrite(static_cast<uint8>(packet.nD1), packet.nD0));
				}
				break;
			case 0x0F:
				//NOP
				break;
			default:
				assert(0);
				break;
			}
		}

		if(m_regsTemp == 0)
		{
			m_loops--;
			m_regsTemp = m_regs;
		}

	}

	return address - start;
}
Пример #3
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;
}
Пример #4
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;
}