2007-12-07 00:26:56 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <algorithm>
|
|
|
|
#include "GIF.h"
|
|
|
|
#include "uint128.h"
|
2008-01-15 20:27:44 +00:00
|
|
|
#include "Ps2Const.h"
|
2007-12-07 00:26:56 +00:00
|
|
|
#include "Profiler.h"
|
|
|
|
#include "Log.h"
|
|
|
|
|
2012-12-23 21:35:04 +00:00
|
|
|
#define LOG_NAME ("gif")
|
2007-12-07 00:26:56 +00:00
|
|
|
|
|
|
|
#ifdef PROFILE
|
|
|
|
#define PROFILE_GIFZONE "GIF"
|
|
|
|
#endif
|
|
|
|
|
2012-06-03 22:54:29 +00:00
|
|
|
CGIF::CGIF(CGSHandler*& gs, uint8* ram, uint8* spr)
|
|
|
|
: m_gs(gs)
|
|
|
|
, m_ram(ram)
|
|
|
|
, m_spr(spr)
|
|
|
|
, m_nLoops(0)
|
|
|
|
, m_nCmd(0)
|
|
|
|
, m_nRegs(0)
|
|
|
|
, m_nRegsTemp(0)
|
|
|
|
, m_nRegList(0)
|
|
|
|
, m_nEOP(false)
|
|
|
|
, m_nQTemp(0)
|
2007-12-07 00:26:56 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CGIF::~CGIF()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGIF::Reset()
|
|
|
|
{
|
|
|
|
m_nLoops = 0;
|
|
|
|
m_nCmd = 0;
|
|
|
|
m_nEOP = false;
|
|
|
|
}
|
|
|
|
|
2008-04-07 00:51:28 +00:00
|
|
|
uint32 CGIF::ProcessPacked(CGSHandler::RegisterWriteList& writeList, uint8* pMemory, uint32 nAddress, uint32 nEnd)
|
2007-12-07 00:26:56 +00:00
|
|
|
{
|
2011-03-28 02:23:11 +00:00
|
|
|
uint32 nStart = nAddress;
|
2007-12-07 00:26:56 +00:00
|
|
|
|
|
|
|
while((m_nLoops != 0) && (nAddress < nEnd))
|
|
|
|
{
|
|
|
|
while((m_nRegsTemp != 0) && (nAddress < nEnd))
|
|
|
|
{
|
2011-03-28 02:23:11 +00:00
|
|
|
uint64 nTemp;
|
|
|
|
uint32 nRegDesc = (uint32)((m_nRegList >> ((m_nRegs - m_nRegsTemp) * 4)) & 0x0F);
|
2007-12-07 00:26:56 +00:00
|
|
|
|
2011-03-28 02:23:11 +00:00
|
|
|
uint128 nPacket = *(uint128*)&pMemory[nAddress];
|
2007-12-07 00:26:56 +00:00
|
|
|
nAddress += 0x10;
|
|
|
|
|
|
|
|
m_nRegsTemp--;
|
|
|
|
|
|
|
|
switch(nRegDesc)
|
|
|
|
{
|
2012-06-03 22:54:29 +00:00
|
|
|
case 0x00:
|
|
|
|
//PRIM
|
|
|
|
writeList.push_back(CGSHandler::RegisterWrite(GS_REG_PRIM, nPacket.nV0));
|
|
|
|
break;
|
2007-12-07 00:26:56 +00:00
|
|
|
case 0x01:
|
|
|
|
//RGBA
|
|
|
|
nTemp = (nPacket.nV[0] & 0xFF);
|
|
|
|
nTemp |= (nPacket.nV[1] & 0xFF) << 8;
|
|
|
|
nTemp |= (nPacket.nV[2] & 0xFF) << 16;
|
|
|
|
nTemp |= (nPacket.nV[3] & 0xFF) << 24;
|
|
|
|
nTemp |= ((uint64)m_nQTemp << 32);
|
2012-06-03 22:54:29 +00:00
|
|
|
writeList.push_back(CGSHandler::RegisterWrite(GS_REG_RGBAQ, nTemp));
|
2007-12-07 00:26:56 +00:00
|
|
|
break;
|
|
|
|
case 0x02:
|
|
|
|
//ST
|
|
|
|
m_nQTemp = nPacket.nV2;
|
2012-06-03 22:54:29 +00:00
|
|
|
writeList.push_back(CGSHandler::RegisterWrite(GS_REG_ST, nPacket.nD0));
|
2007-12-07 00:26:56 +00:00
|
|
|
break;
|
|
|
|
case 0x03:
|
|
|
|
//UV
|
|
|
|
nTemp = (nPacket.nV[0] & 0x7FFF);
|
|
|
|
nTemp |= (nPacket.nV[1] & 0x7FFF) << 16;
|
2012-06-03 22:54:29 +00:00
|
|
|
writeList.push_back(CGSHandler::RegisterWrite(GS_REG_UV, nTemp));
|
2007-12-07 00:26:56 +00:00
|
|
|
break;
|
|
|
|
case 0x04:
|
|
|
|
//XYZF2
|
|
|
|
nTemp = (nPacket.nV[0] & 0xFFFF);
|
|
|
|
nTemp |= (nPacket.nV[1] & 0xFFFF) << 16;
|
|
|
|
nTemp |= (uint64)(nPacket.nV[2] & 0x0FFFFFF0) << 28;
|
|
|
|
nTemp |= (uint64)(nPacket.nV[3] & 0x00000FF0) << 52;
|
|
|
|
if(nPacket.nV[3] & 0x8000)
|
|
|
|
{
|
2012-06-03 22:54:29 +00:00
|
|
|
writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZF3, nTemp));
|
2007-12-07 00:26:56 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-06-03 22:54:29 +00:00
|
|
|
writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZF2, nTemp));
|
2007-12-07 00:26:56 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x05:
|
|
|
|
//XYZ2
|
|
|
|
nTemp = (nPacket.nV[0] & 0xFFFF);
|
|
|
|
nTemp |= (nPacket.nV[1] & 0xFFFF) << 16;
|
|
|
|
nTemp |= (uint64)(nPacket.nV[2] & 0xFFFFFFFF) << 32;
|
|
|
|
if(nPacket.nV[3] & 0x8000)
|
|
|
|
{
|
2012-06-03 22:54:29 +00:00
|
|
|
writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZ3, nTemp));
|
2007-12-07 00:26:56 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-06-03 22:54:29 +00:00
|
|
|
writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZ2, nTemp));
|
2007-12-07 00:26:56 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x06:
|
|
|
|
//TEX0_1
|
2012-06-03 22:54:29 +00:00
|
|
|
writeList.push_back(CGSHandler::RegisterWrite(GS_REG_TEX0_1, nPacket.nD0));
|
|
|
|
break;
|
2012-06-24 19:06:28 +00:00
|
|
|
case 0x07:
|
|
|
|
//TEX0_2
|
|
|
|
writeList.push_back(CGSHandler::RegisterWrite(GS_REG_TEX0_2, nPacket.nD0));
|
|
|
|
break;
|
2012-06-03 22:54:29 +00:00
|
|
|
case 0x08:
|
|
|
|
//CLAMP_1
|
|
|
|
writeList.push_back(CGSHandler::RegisterWrite(GS_REG_CLAMP_1, nPacket.nD0));
|
2007-12-07 00:26:56 +00:00
|
|
|
break;
|
2011-11-15 03:07:04 +00:00
|
|
|
case 0x0D:
|
2012-06-03 22:54:29 +00:00
|
|
|
//XYZ3
|
|
|
|
writeList.push_back(CGSHandler::RegisterWrite(GS_REG_XYZ3, nPacket.nD0));
|
2011-11-15 03:07:04 +00:00
|
|
|
break;
|
2007-12-07 00:26:56 +00:00
|
|
|
case 0x0E:
|
|
|
|
//A + D
|
2007-12-09 03:26:33 +00:00
|
|
|
if(m_gs != NULL)
|
|
|
|
{
|
2012-06-03 22:54:29 +00:00
|
|
|
writeList.push_back(CGSHandler::RegisterWrite(static_cast<uint8>(nPacket.nD1), nPacket.nD0));
|
2007-12-09 03:26:33 +00:00
|
|
|
}
|
2007-12-07 00:26:56 +00:00
|
|
|
break;
|
2012-06-03 22:54:29 +00:00
|
|
|
case 0x0F:
|
|
|
|
//NOP
|
|
|
|
break;
|
2007-12-07 00:26:56 +00:00
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_nRegsTemp == 0)
|
|
|
|
{
|
|
|
|
m_nLoops--;
|
|
|
|
m_nRegsTemp = m_nRegs;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return nAddress - nStart;
|
|
|
|
}
|
|
|
|
|
2008-04-07 00:51:28 +00:00
|
|
|
uint32 CGIF::ProcessRegList(CGSHandler::RegisterWriteList& writeList, uint8* pMemory, uint32 nAddress, uint32 nEnd)
|
2007-12-07 00:26:56 +00:00
|
|
|
{
|
2012-06-03 22:54:29 +00:00
|
|
|
uint32 nStart = nAddress;
|
2007-12-07 00:26:56 +00:00
|
|
|
|
|
|
|
while(m_nLoops != 0)
|
|
|
|
{
|
2008-02-29 02:11:27 +00:00
|
|
|
for(uint32 j = 0; j < m_nRegs; j++)
|
2007-12-07 00:26:56 +00:00
|
|
|
{
|
|
|
|
assert(nAddress < nEnd);
|
|
|
|
|
2012-06-03 22:54:29 +00:00
|
|
|
uint128 nPacket;
|
2008-02-29 02:11:27 +00:00
|
|
|
uint32 nRegDesc = (uint32)((m_nRegList >> (j * 4)) & 0x0F);
|
2007-12-07 00:26:56 +00:00
|
|
|
|
|
|
|
nPacket.nV[0] = *(uint32*)&pMemory[nAddress + 0x00];
|
|
|
|
nPacket.nV[1] = *(uint32*)&pMemory[nAddress + 0x04];
|
|
|
|
nAddress += 0x08;
|
|
|
|
|
|
|
|
if(nRegDesc == 0x0F) continue;
|
|
|
|
|
2012-06-03 22:54:29 +00:00
|
|
|
writeList.push_back(CGSHandler::RegisterWrite(static_cast<uint8>(nRegDesc), nPacket.nD0));
|
2007-12-07 00:26:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
m_nLoops--;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Align on qword boundary
|
2011-11-15 03:07:04 +00:00
|
|
|
if(nAddress & 0x0F)
|
2007-12-07 00:26:56 +00:00
|
|
|
{
|
|
|
|
nAddress += 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nAddress - nStart;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CGIF::ProcessImage(uint8* pMemory, uint32 nAddress, uint32 nEnd)
|
|
|
|
{
|
2011-11-22 02:52:52 +00:00
|
|
|
uint16 nTotalLoops = static_cast<uint16>((nEnd - nAddress) / 0x10);
|
|
|
|
nTotalLoops = std::min<uint16>(nTotalLoops, m_nLoops);
|
2007-12-07 00:26:56 +00:00
|
|
|
|
2007-12-09 03:26:33 +00:00
|
|
|
if(m_gs != NULL)
|
|
|
|
{
|
|
|
|
m_gs->FeedImageData(pMemory + nAddress, nTotalLoops * 0x10);
|
|
|
|
}
|
2007-12-07 00:26:56 +00:00
|
|
|
|
|
|
|
m_nLoops -= nTotalLoops;
|
|
|
|
|
|
|
|
return (nTotalLoops * 0x10);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CGIF::ProcessPacket(uint8* pMemory, uint32 nAddress, uint32 nEnd)
|
|
|
|
{
|
2011-11-15 03:07:04 +00:00
|
|
|
boost::mutex::scoped_lock pathLock(m_pathMutex);
|
2012-06-03 22:54:29 +00:00
|
|
|
static CGSHandler::RegisterWriteList writeList;
|
2007-12-07 00:26:56 +00:00
|
|
|
|
|
|
|
#ifdef PROFILE
|
2012-12-23 21:35:04 +00:00
|
|
|
CProfilerZone profilerZone(PROFILE_GIFZONE);
|
2007-12-07 00:26:56 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
2012-06-03 22:54:29 +00:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Received GIF packet at 0x%0.8X of 0x%0.8X bytes.\r\n", nAddress, nEnd - nAddress);
|
2007-12-07 00:26:56 +00:00
|
|
|
#endif
|
|
|
|
|
2012-06-03 22:54:29 +00:00
|
|
|
writeList.clear();
|
2008-03-29 16:38:35 +00:00
|
|
|
|
2012-06-03 22:54:29 +00:00
|
|
|
uint32 nStart = nAddress;
|
2007-12-07 00:26:56 +00:00
|
|
|
while(nAddress < nEnd)
|
|
|
|
{
|
|
|
|
if(m_nLoops == 0)
|
|
|
|
{
|
|
|
|
if(m_nEOP)
|
|
|
|
{
|
|
|
|
m_nEOP = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
//We need to update the registers
|
2008-04-03 00:34:17 +00:00
|
|
|
uint128 nPacket = *reinterpret_cast<uint128*>(&pMemory[nAddress]);
|
2007-12-07 00:26:56 +00:00
|
|
|
nAddress += 0x10;
|
|
|
|
|
|
|
|
m_nLoops = (uint16)((nPacket.nV0 >> 0) & 0x7FFF);
|
|
|
|
m_nCmd = ( uint8)((nPacket.nV1 >> 26) & 0x0003);
|
|
|
|
m_nRegs = ( uint8)((nPacket.nV1 >> 28) & 0x000F);
|
|
|
|
m_nRegList = nPacket.nD1;
|
|
|
|
m_nEOP = (nPacket.nV0 & 0x8000) != 0;
|
|
|
|
|
|
|
|
if(m_nCmd != 1)
|
|
|
|
{
|
|
|
|
if(nPacket.nV1 & 0x4000)
|
|
|
|
{
|
2012-06-03 22:54:29 +00:00
|
|
|
writeList.push_back(CGSHandler::RegisterWrite(GS_REG_PRIM, (uint16)(nPacket.nV1 >> 15) & 0x3FF));
|
2007-12-07 00:26:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_nRegs == 0) m_nRegs = 0x10;
|
|
|
|
m_nRegsTemp = m_nRegs;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
switch(m_nCmd)
|
|
|
|
{
|
|
|
|
case 0x00:
|
2008-04-07 00:51:28 +00:00
|
|
|
nAddress += ProcessPacked(writeList, pMemory, nAddress, nEnd);
|
2007-12-07 00:26:56 +00:00
|
|
|
break;
|
|
|
|
case 0x01:
|
2008-04-07 00:51:28 +00:00
|
|
|
nAddress += ProcessRegList(writeList, pMemory, nAddress, nEnd);
|
2007-12-07 00:26:56 +00:00
|
|
|
break;
|
|
|
|
case 0x02:
|
|
|
|
case 0x03:
|
|
|
|
nAddress += ProcessImage(pMemory, nAddress, nEnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_nLoops == 0)
|
|
|
|
{
|
|
|
|
if(m_nEOP)
|
|
|
|
{
|
|
|
|
m_nEOP = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-30 07:22:48 +00:00
|
|
|
if(m_gs != NULL && !writeList.empty())
|
2012-06-03 22:54:29 +00:00
|
|
|
{
|
2013-05-30 07:22:48 +00:00
|
|
|
m_gs->WriteRegisterMassively(writeList.data(), static_cast<unsigned int>(writeList.size()));
|
2012-06-03 22:54:29 +00:00
|
|
|
}
|
2008-03-29 16:38:35 +00:00
|
|
|
|
2011-11-15 03:07:04 +00:00
|
|
|
#ifdef _DEBUG
|
2012-06-03 22:54:29 +00:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Processed 0x%0.8X bytes.\r\n", nAddress - nStart);
|
2011-11-15 03:07:04 +00:00
|
|
|
#endif
|
|
|
|
|
2012-06-03 22:54:29 +00:00
|
|
|
return nAddress - nStart;
|
2007-12-07 00:26:56 +00:00
|
|
|
}
|
|
|
|
|
2008-01-12 01:27:04 +00:00
|
|
|
uint32 CGIF::ReceiveDMA(uint32 nAddress, uint32 nQWC, uint32 unused, bool nTagIncluded)
|
2007-12-07 00:26:56 +00:00
|
|
|
{
|
2009-12-11 06:15:52 +00:00
|
|
|
uint8* pMemory(NULL);
|
|
|
|
uint32 nSize = nQWC * 0x10;
|
2007-12-07 00:26:56 +00:00
|
|
|
|
2012-06-03 22:54:29 +00:00
|
|
|
if(nTagIncluded)
|
|
|
|
{
|
|
|
|
assert(nQWC >= 0);
|
|
|
|
nSize -= 0x10;
|
|
|
|
nAddress += 0x10;
|
|
|
|
}
|
2007-12-07 00:26:56 +00:00
|
|
|
|
|
|
|
if(nAddress & 0x80000000)
|
|
|
|
{
|
|
|
|
pMemory = m_spr;
|
2012-09-12 01:03:53 +00:00
|
|
|
nAddress &= PS2::EE_SPR_SIZE - 1;
|
2007-12-07 00:26:56 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pMemory = m_ram;
|
|
|
|
}
|
|
|
|
|
2008-04-30 01:13:31 +00:00
|
|
|
uint32 nEnd = nAddress + nSize;
|
2007-12-07 00:26:56 +00:00
|
|
|
|
|
|
|
while(nAddress < nEnd)
|
|
|
|
{
|
|
|
|
nAddress += ProcessPacket(pMemory, nAddress, nEnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
return nQWC;
|
|
|
|
}
|