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; }
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; }