2006-06-15 04:19:30 +00:00
|
|
|
#include <assert.h>
|
|
|
|
#include "VIF.h"
|
2008-03-22 02:37:01 +00:00
|
|
|
#include "VPU.h"
|
|
|
|
#include "VPU1.h"
|
2006-06-15 04:19:30 +00:00
|
|
|
#include "GIF.h"
|
2006-07-18 12:08:40 +00:00
|
|
|
#include "Profiler.h"
|
2008-03-21 01:53:44 +00:00
|
|
|
#include "Ps2Const.h"
|
2008-03-22 02:37:01 +00:00
|
|
|
#include "RegisterStateFile.h"
|
2006-07-18 12:08:40 +00:00
|
|
|
|
|
|
|
#ifdef PROFILE
|
|
|
|
#define PROFILE_VIFZONE "VIF"
|
|
|
|
#define PROFILE_VU1ZONE "VU0"
|
|
|
|
#endif
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2008-03-22 02:37:01 +00:00
|
|
|
#define STATE_REGS_XML ("vif/regs.xml")
|
|
|
|
#define STATE_REGS_VPU_STAT ("VPU_STAT")
|
|
|
|
|
2006-06-15 04:19:30 +00:00
|
|
|
using namespace Framework;
|
2008-03-21 01:53:44 +00:00
|
|
|
using namespace std;
|
|
|
|
using namespace boost;
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2006-07-04 22:07:57 +00:00
|
|
|
//REMOVE
|
|
|
|
static int nExecTimes = 0;
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2008-03-21 01:53:44 +00:00
|
|
|
CVIF::CVIF(CGIF& gif, uint8* ram, const VPUINIT& vpu0Init, const VPUINIT& vpu1Init) :
|
|
|
|
m_gif(gif),
|
2008-06-23 01:35:05 +00:00
|
|
|
m_ram(ram),
|
|
|
|
m_VPU_STAT(0)
|
2008-03-21 01:53:44 +00:00
|
|
|
{
|
2008-03-22 02:37:01 +00:00
|
|
|
m_pVPU[0] = new CVPU(*this, 0, vpu0Init);
|
|
|
|
m_pVPU[1] = new CVPU1(*this, 1, vpu1Init);
|
2008-06-15 19:55:28 +00:00
|
|
|
for(unsigned int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
m_stream[i] = new CFifoStream(ram);
|
|
|
|
}
|
2008-06-23 01:35:05 +00:00
|
|
|
Reset();
|
2008-03-21 01:53:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CVIF::~CVIF()
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
2008-03-21 01:53:44 +00:00
|
|
|
for(unsigned int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
delete m_pVPU[i];
|
2008-06-15 19:55:28 +00:00
|
|
|
delete m_stream[i];
|
2008-03-21 01:53:44 +00:00
|
|
|
}
|
|
|
|
}
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2008-04-09 03:08:32 +00:00
|
|
|
void CVIF::JoinThreads()
|
|
|
|
{
|
|
|
|
m_pVPU[0]->JoinThread();
|
|
|
|
m_pVPU[1]->JoinThread();
|
|
|
|
}
|
|
|
|
|
2006-06-15 04:19:30 +00:00
|
|
|
void CVIF::Reset()
|
|
|
|
{
|
2008-06-15 19:55:28 +00:00
|
|
|
for(unsigned int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
m_stream[i]->Flush();
|
|
|
|
m_pVPU[i]->Reset();
|
|
|
|
}
|
2008-03-21 01:53:44 +00:00
|
|
|
m_VPU_STAT = 0;
|
2006-06-15 04:19:30 +00:00
|
|
|
}
|
|
|
|
|
2008-03-22 02:37:01 +00:00
|
|
|
void CVIF::SaveState(CZipArchiveWriter& archive)
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
2008-03-22 02:37:01 +00:00
|
|
|
{
|
|
|
|
CRegisterStateFile* registerFile = new CRegisterStateFile(STATE_REGS_XML);
|
|
|
|
registerFile->SetRegister32(STATE_REGS_VPU_STAT, m_VPU_STAT);
|
|
|
|
archive.InsertFile(registerFile);
|
|
|
|
}
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2008-03-22 02:37:01 +00:00
|
|
|
m_pVPU[0]->SaveState(archive);
|
|
|
|
m_pVPU[1]->SaveState(archive);
|
2006-06-15 04:19:30 +00:00
|
|
|
}
|
|
|
|
|
2008-03-22 02:37:01 +00:00
|
|
|
void CVIF::LoadState(CZipArchiveReader& archive)
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
2008-03-22 02:37:01 +00:00
|
|
|
CRegisterStateFile registerFile(*archive.BeginReadFile(STATE_REGS_XML));
|
|
|
|
m_VPU_STAT = registerFile.GetRegister32(STATE_REGS_VPU_STAT);
|
2006-06-15 04:19:30 +00:00
|
|
|
|
2008-03-22 02:37:01 +00:00
|
|
|
m_pVPU[0]->LoadState(archive);
|
|
|
|
m_pVPU[1]->LoadState(archive);
|
2006-06-15 04:19:30 +00:00
|
|
|
}
|
|
|
|
|
2008-06-15 19:55:28 +00:00
|
|
|
uint32 CVIF::ReceiveDMA0(uint32 address, uint32 qwc, bool tagIncluded)
|
|
|
|
{
|
|
|
|
unsigned int vpuNumber = 0;
|
|
|
|
// if(IsVU1Running())
|
|
|
|
// {
|
|
|
|
// thread::yield();
|
|
|
|
// return 0;
|
|
|
|
// }
|
|
|
|
|
|
|
|
m_stream[vpuNumber]->SetDmaParams(address, qwc * 0x10);
|
|
|
|
if(tagIncluded)
|
|
|
|
{
|
|
|
|
m_stream[vpuNumber]->Read(NULL, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_pVPU[vpuNumber]->ProcessPacket(*m_stream[vpuNumber]);
|
|
|
|
|
|
|
|
uint32 remainingSize = m_stream[vpuNumber]->GetSize();
|
|
|
|
assert((remainingSize & 0x0F) == 0);
|
|
|
|
remainingSize /= 0x10;
|
|
|
|
return qwc - remainingSize;
|
|
|
|
}
|
|
|
|
|
2006-06-15 04:19:30 +00:00
|
|
|
uint32 CVIF::ReceiveDMA1(uint32 nAddress, uint32 nQWC, bool nTagIncluded)
|
|
|
|
{
|
2008-06-15 19:55:28 +00:00
|
|
|
unsigned int vpuNumber = 1;
|
|
|
|
|
2008-03-29 16:38:35 +00:00
|
|
|
if(IsVU1Running())
|
|
|
|
{
|
2008-03-30 22:12:52 +00:00
|
|
|
thread::yield();
|
2008-03-29 16:38:35 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-06-15 19:55:28 +00:00
|
|
|
m_stream[vpuNumber]->SetDmaParams(nAddress, nQWC * 0x10);
|
2008-03-29 16:38:35 +00:00
|
|
|
if(nTagIncluded)
|
|
|
|
{
|
2008-06-15 19:55:28 +00:00
|
|
|
m_stream[vpuNumber]->Read(NULL, 8);
|
2008-03-29 16:38:35 +00:00
|
|
|
}
|
|
|
|
|
2008-06-15 19:55:28 +00:00
|
|
|
m_pVPU[vpuNumber]->ProcessPacket(*m_stream[vpuNumber]);
|
2006-07-18 12:08:40 +00:00
|
|
|
|
|
|
|
#ifdef PROFILE
|
|
|
|
CProfiler::GetInstance().BeginZone(PROFILE_VIFZONE);
|
|
|
|
#endif
|
|
|
|
|
2008-03-29 16:38:35 +00:00
|
|
|
// if(nTagIncluded)
|
|
|
|
// {
|
|
|
|
// nQWC = m_pVPU[1]->ProcessPacket(nAddress + 8, (nQWC * 0x10) - 8);
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// nQWC = m_pVPU[1]->ProcessPacket(nAddress, nQWC * 0x10);
|
|
|
|
// }
|
2006-07-18 12:08:40 +00:00
|
|
|
|
|
|
|
#ifdef PROFILE
|
|
|
|
CProfiler::GetInstance().EndZone();
|
|
|
|
#endif
|
|
|
|
|
2008-06-15 19:55:28 +00:00
|
|
|
uint32 remainingSize = m_stream[vpuNumber]->GetSize();
|
2008-03-29 16:38:35 +00:00
|
|
|
assert((remainingSize & 0x0F) == 0);
|
|
|
|
remainingSize /= 0x10;
|
|
|
|
return nQWC - remainingSize;
|
2006-06-15 04:19:30 +00:00
|
|
|
}
|
|
|
|
|
2008-06-15 19:55:28 +00:00
|
|
|
uint32 CVIF::GetITop0() const
|
|
|
|
{
|
|
|
|
return m_pVPU[0]->GetITOP();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CVIF::GetITop1() const
|
|
|
|
{
|
|
|
|
return m_pVPU[1]->GetITOP();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CVIF::GetTop1() const
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
|
|
|
return m_pVPU[1]->GetTOP();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVIF::StopVU(CMIPS* pCtx)
|
|
|
|
{
|
2008-03-21 01:53:44 +00:00
|
|
|
if(pCtx == &m_pVPU[1]->GetContext())
|
|
|
|
{
|
2006-06-15 04:19:30 +00:00
|
|
|
m_VPU_STAT &= ~STAT_VBS1;
|
2008-03-21 01:53:44 +00:00
|
|
|
}
|
2006-06-15 04:19:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CVIF::ProcessXGKICK(uint32 nAddress)
|
|
|
|
{
|
2008-06-23 01:35:05 +00:00
|
|
|
nAddress &= 0x3FF;
|
2006-06-15 04:19:30 +00:00
|
|
|
nAddress *= 0x10;
|
|
|
|
|
2008-06-23 01:35:05 +00:00
|
|
|
// assert(nAddress < PS2::VUMEM1SIZE);
|
|
|
|
|
2008-03-21 01:53:44 +00:00
|
|
|
m_gif.ProcessPacket(m_pVPU[1]->GetVuMemory(), nAddress, PS2::VUMEM1SIZE);
|
2006-06-15 04:19:30 +00:00
|
|
|
}
|
|
|
|
|
2008-06-15 19:55:28 +00:00
|
|
|
bool CVIF::IsVu0DebuggingEnabled() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CVIF::IsVu1DebuggingEnabled() const
|
2008-03-29 16:38:35 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-06-15 19:55:28 +00:00
|
|
|
bool CVIF::IsVU0Running() const
|
|
|
|
{
|
|
|
|
return m_pVPU[0]->IsRunning();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CVIF::IsVU1Running() const
|
2006-06-15 04:19:30 +00:00
|
|
|
{
|
2008-06-15 19:55:28 +00:00
|
|
|
return m_pVPU[1]->IsRunning();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVIF::SingleStepVU0()
|
|
|
|
{
|
|
|
|
if(!IsVu0DebuggingEnabled())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!IsVU0Running())
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
m_pVPU[0]->SingleStep();
|
2006-06-15 04:19:30 +00:00
|
|
|
}
|
|
|
|
|
2008-03-22 02:37:01 +00:00
|
|
|
void CVIF::SingleStepVU1()
|
2008-03-21 01:53:44 +00:00
|
|
|
{
|
2008-06-15 19:55:28 +00:00
|
|
|
if(!IsVu1DebuggingEnabled())
|
2008-03-29 16:38:35 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-03-22 02:37:01 +00:00
|
|
|
if(!IsVU1Running())
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
m_pVPU[1]->SingleStep();
|
2008-03-21 01:53:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint8* CVIF::GetRam() const
|
|
|
|
{
|
|
|
|
return m_ram;
|
|
|
|
}
|
|
|
|
|
|
|
|
CGIF& CVIF::GetGif() const
|
|
|
|
{
|
|
|
|
return m_gif;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CVIF::GetStat() const
|
|
|
|
{
|
|
|
|
return m_VPU_STAT;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVIF::SetStat(uint32 stat)
|
|
|
|
{
|
|
|
|
m_VPU_STAT = stat;
|
|
|
|
}
|
2008-03-29 16:38:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
CVIF::CFifoStream::CFifoStream(uint8* ram) :
|
|
|
|
m_ram(ram),
|
|
|
|
m_address(0),
|
|
|
|
m_endAddress(0),
|
|
|
|
m_nextAddress(0),
|
|
|
|
m_position(BUFFERSIZE)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
CVIF::CFifoStream::~CFifoStream()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVIF::CFifoStream::Read(void* buffer, uint32 size)
|
|
|
|
{
|
|
|
|
uint8* readBuffer = reinterpret_cast<uint8*>(buffer);
|
|
|
|
while(size != 0)
|
|
|
|
{
|
|
|
|
SyncBuffer();
|
|
|
|
uint32 read = min(size, BUFFERSIZE - m_position);
|
|
|
|
if(readBuffer != NULL)
|
|
|
|
{
|
|
|
|
memcpy(readBuffer, reinterpret_cast<uint8*>(&m_buffer) + m_position, read);
|
|
|
|
readBuffer += read;
|
|
|
|
}
|
|
|
|
m_position += read;
|
|
|
|
size -= read;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVIF::CFifoStream::Flush()
|
|
|
|
{
|
|
|
|
m_position = BUFFERSIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVIF::CFifoStream::SetDmaParams(uint32 address, uint32 qwc)
|
|
|
|
{
|
|
|
|
m_address = address;
|
|
|
|
m_nextAddress = address;
|
|
|
|
m_endAddress = address + qwc;
|
2008-04-23 00:15:51 +00:00
|
|
|
SyncBuffer();
|
2008-03-29 16:38:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CVIF::CFifoStream::GetAddress() const
|
|
|
|
{
|
|
|
|
return m_address + m_position;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CVIF::CFifoStream::GetSize() const
|
|
|
|
{
|
|
|
|
return m_endAddress - GetAddress();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVIF::CFifoStream::Align32()
|
|
|
|
{
|
2008-06-15 19:55:28 +00:00
|
|
|
unsigned int remainBytes = GetAddress() & 0x03;
|
|
|
|
if(remainBytes == 0) return;
|
|
|
|
Read(NULL, 4 - remainBytes);
|
2008-03-29 16:38:35 +00:00
|
|
|
assert((GetAddress() & 0x03) == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CVIF::CFifoStream::SyncBuffer()
|
|
|
|
{
|
|
|
|
if(m_position >= BUFFERSIZE)
|
|
|
|
{
|
|
|
|
if(m_nextAddress >= m_endAddress)
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
m_address = m_nextAddress;
|
|
|
|
m_buffer = *reinterpret_cast<uint128*>(&m_ram[m_nextAddress]);
|
|
|
|
m_nextAddress += 0x10;
|
|
|
|
m_position = 0;
|
|
|
|
}
|
|
|
|
}
|