mirror of
https://github.com/libretro/Play-.git
synced 2025-03-03 16:57:03 +00:00
Added support for interleave DMA transfer mode.
This commit is contained in:
parent
c38bfc2e21
commit
eb66e94752
@ -12,6 +12,7 @@
|
||||
#define STATE_REGS_CTRL ("D_CTRL")
|
||||
#define STATE_REGS_STAT ("D_STAT")
|
||||
#define STATE_REGS_PCR ("D_PCR")
|
||||
#define STATE_REGS_SQWC ("D_SQWC")
|
||||
#define STATE_REGS_RBSR ("D_RBSR")
|
||||
#define STATE_REGS_RBOR ("D_RBOR")
|
||||
#define STATE_REGS_D8_SADR ("D8_SADR")
|
||||
@ -79,6 +80,7 @@ void CDMAC::Reset()
|
||||
m_D_STAT = 0;
|
||||
m_D_ENABLE = 0;
|
||||
m_D_PCR = 0;
|
||||
m_D_SQWC <<= 0;
|
||||
m_D_RBSR = 0;
|
||||
m_D_RBOR = 0;
|
||||
|
||||
@ -412,6 +414,10 @@ uint32 CDMAC::GetRegister(uint32 nAddress)
|
||||
return m_D_PCR;
|
||||
break;
|
||||
|
||||
case D_SQWC:
|
||||
return m_D_SQWC;
|
||||
break;
|
||||
|
||||
case D_ENABLER + 0x0:
|
||||
return m_D_ENABLE;
|
||||
break;
|
||||
@ -788,6 +794,14 @@ void CDMAC::SetRegister(uint32 nAddress, uint32 nData)
|
||||
case D_PCR + 0xC:
|
||||
break;
|
||||
|
||||
case D_SQWC + 0x0:
|
||||
m_D_SQWC <<= nData;
|
||||
break;
|
||||
case D_SQWC + 0x4:
|
||||
case D_SQWC + 0x8:
|
||||
case D_SQWC + 0xC:
|
||||
break;
|
||||
|
||||
case D_RBSR + 0x0:
|
||||
m_D_RBSR = nData;
|
||||
assert((m_D_RBSR & 0xF) == 0);
|
||||
@ -831,6 +845,7 @@ void CDMAC::LoadState(Framework::CZipArchiveReader& archive)
|
||||
m_D_CTRL <<= registerFile.GetRegister32(STATE_REGS_CTRL);
|
||||
m_D_STAT = registerFile.GetRegister32(STATE_REGS_STAT);
|
||||
m_D_PCR = registerFile.GetRegister32(STATE_REGS_PCR);
|
||||
m_D_SQWC <<= registerFile.GetRegister32(STATE_REGS_SQWC);
|
||||
m_D_RBSR = registerFile.GetRegister32(STATE_REGS_RBSR);
|
||||
m_D_RBOR = registerFile.GetRegister32(STATE_REGS_RBOR);
|
||||
m_D8_SADR = registerFile.GetRegister32(STATE_REGS_D8_SADR);
|
||||
@ -850,6 +865,7 @@ void CDMAC::SaveState(Framework::CZipArchiveWriter& archive)
|
||||
registerFile->SetRegister32(STATE_REGS_CTRL, m_D_CTRL);
|
||||
registerFile->SetRegister32(STATE_REGS_STAT, m_D_STAT);
|
||||
registerFile->SetRegister32(STATE_REGS_PCR, m_D_PCR);
|
||||
registerFile->SetRegister32(STATE_REGS_SQWC, m_D_SQWC);
|
||||
registerFile->SetRegister32(STATE_REGS_RBSR, m_D_RBSR);
|
||||
registerFile->SetRegister32(STATE_REGS_RBOR, m_D_RBOR);
|
||||
registerFile->SetRegister32(STATE_REGS_D8_SADR, m_D8_SADR);
|
||||
@ -963,6 +979,9 @@ void CDMAC::DisassembleGet(uint32 nAddress)
|
||||
case D_PCR:
|
||||
CLog::GetInstance().Print(LOG_NAME, "= D_PCR.\r\n");
|
||||
break;
|
||||
case D_SQWC:
|
||||
CLog::GetInstance().Print(LOG_NAME, "= D_SQWC.\r\n");
|
||||
break;
|
||||
case D_ENABLER:
|
||||
CLog::GetInstance().Print(LOG_NAME, "= D_ENABLER.\r\n");
|
||||
break;
|
||||
@ -1078,6 +1097,9 @@ void CDMAC::DisassembleSet(uint32 nAddress, uint32 nData)
|
||||
case D_PCR:
|
||||
CLog::GetInstance().Print(LOG_NAME, "D_PCR = 0x%0.8X.\r\n", nData);
|
||||
break;
|
||||
case D_SQWC:
|
||||
CLog::GetInstance().Print(LOG_NAME, "D_SQWC = 0x%0.8X.\r\n", nData);
|
||||
break;
|
||||
case D_RBSR:
|
||||
CLog::GetInstance().Print(LOG_NAME, "D_RBSR = 0x%0.8X.\r\n", nData);
|
||||
break;
|
||||
|
@ -75,6 +75,7 @@ public:
|
||||
D_CTRL = 0x1000E000,
|
||||
D_STAT = 0x1000E010,
|
||||
D_PCR = 0x1000E020,
|
||||
D_SQWC = 0x1000E030,
|
||||
D_RBSR = 0x1000E040,
|
||||
D_RBOR = 0x1000E050,
|
||||
|
||||
@ -130,6 +131,15 @@ private:
|
||||
};
|
||||
static_assert(sizeof(D_CTRL_REG) == sizeof(uint32), "Size of D_CTRL_REG struct must be 4 bytes.");
|
||||
|
||||
struct D_SQWC_REG : public convertible<uint32>
|
||||
{
|
||||
unsigned int sqwc : 8;
|
||||
unsigned int reserved0 : 8;
|
||||
unsigned int tqwc : 8;
|
||||
unsigned int reserved1 : 8;
|
||||
};
|
||||
static_assert(sizeof(D_SQWC_REG) == sizeof(uint32), "Size of D_SQWC_REG struct must be 4 bytes.");
|
||||
|
||||
uint64 FetchDMATag(uint32);
|
||||
|
||||
uint32 ReceiveDMA8(uint32, uint32, uint32, bool);
|
||||
@ -141,6 +151,7 @@ private:
|
||||
uint32 m_D_STAT;
|
||||
uint32 m_D_ENABLE;
|
||||
uint32 m_D_PCR;
|
||||
D_SQWC_REG m_D_SQWC;
|
||||
uint32 m_D_RBSR;
|
||||
uint32 m_D_RBOR;
|
||||
|
||||
|
@ -127,6 +127,18 @@ void CChannel::Execute()
|
||||
case 0x00:
|
||||
ExecuteNormal();
|
||||
break;
|
||||
case 0x02:
|
||||
assert((m_nNumber == CDMAC::CHANNEL_ID_FROM_SPR) || (m_nNumber == CDMAC::CHANNEL_ID_TO_SPR));
|
||||
if((m_dmac.m_D_SQWC.sqwc == 0) || (m_dmac.m_D_SQWC.tqwc == 0))
|
||||
{
|
||||
//If SQWC or TQWC is 0, execute normally
|
||||
ExecuteNormal();
|
||||
}
|
||||
else
|
||||
{
|
||||
ExecuteInterleave();
|
||||
}
|
||||
break;
|
||||
case 0x01:
|
||||
case 0x03: //FFXII uses 3 here, assuming source chain mode
|
||||
ExecuteSourceChain();
|
||||
@ -173,6 +185,32 @@ void CChannel::ExecuteNormal()
|
||||
}
|
||||
}
|
||||
|
||||
void CChannel::ExecuteInterleave()
|
||||
{
|
||||
assert((m_nQWC % m_dmac.m_D_SQWC.tqwc) == 0);
|
||||
while(1)
|
||||
{
|
||||
//Transfer
|
||||
{
|
||||
uint32 qwc = m_dmac.m_D_SQWC.tqwc;
|
||||
uint32 recv = m_pReceive(m_nMADR, qwc, 0, false);
|
||||
assert(recv == qwc);
|
||||
|
||||
m_nMADR += recv * 0x10;
|
||||
m_nQWC -= recv;
|
||||
}
|
||||
|
||||
//Skip
|
||||
m_nMADR += m_dmac.m_D_SQWC.sqwc * 0x10;
|
||||
|
||||
if(m_nQWC == 0)
|
||||
{
|
||||
ClearSTR();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CChannel::ExecuteSourceChain()
|
||||
{
|
||||
//Execute current
|
||||
|
@ -52,6 +52,7 @@ namespace Dmac
|
||||
void WriteCHCR(uint32);
|
||||
void Execute();
|
||||
void ExecuteNormal();
|
||||
void ExecuteInterleave();
|
||||
void ExecuteSourceChain();
|
||||
void SetReceiveHandler(const DmaReceiveHandler&);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user