mirror of https://github.com/PCSX2/pcsx2.git
Clang: Format Gif.cpp, Vif_Codes.cpp, Vif.cpp
This commit is contained in:
parent
88edd1acd6
commit
88a53f013e
176
pcsx2/Gif.cpp
176
pcsx2/Gif.cpp
|
@ -29,38 +29,48 @@
|
|||
__aligned16 GIF_Fifo gif_fifo;
|
||||
__aligned16 gifStruct gif;
|
||||
|
||||
static __fi void GifDMAInt(int cycles) {
|
||||
if (dmacRegs.ctrl.MFD == MFD_GIF) {
|
||||
static __fi void GifDMAInt(int cycles)
|
||||
{
|
||||
if (dmacRegs.ctrl.MFD == MFD_GIF)
|
||||
{
|
||||
if (!(cpuRegs.interrupt & (1 << DMAC_MFIFO_GIF)) || cpuRegs.eCycle[DMAC_MFIFO_GIF] < (u32)cycles)
|
||||
{
|
||||
CPU_INT(DMAC_MFIFO_GIF, cycles);
|
||||
}
|
||||
} else if (!(cpuRegs.interrupt & (1 << DMAC_GIF)) || cpuRegs.eCycle[DMAC_GIF] < (u32)cycles)
|
||||
}
|
||||
else if (!(cpuRegs.interrupt & (1 << DMAC_GIF)) || cpuRegs.eCycle[DMAC_GIF] < (u32)cycles)
|
||||
{
|
||||
CPU_INT(DMAC_GIF, cycles);
|
||||
}
|
||||
}
|
||||
__fi void clearFIFOstuff(bool full) {
|
||||
__fi void clearFIFOstuff(bool full)
|
||||
{
|
||||
CSRreg.FIFO = full ? CSR_FIFO_FULL : CSR_FIFO_EMPTY;
|
||||
}
|
||||
|
||||
//I suspect this is GS side which should really be handled by GS which also doesn't current have a fifo, but we can guess from our fifo
|
||||
static __fi void CalculateFIFOCSR() {
|
||||
if (gifRegs.stat.FQC >= 15) {
|
||||
static __fi void CalculateFIFOCSR()
|
||||
{
|
||||
if (gifRegs.stat.FQC >= 15)
|
||||
{
|
||||
CSRreg.FIFO = CSR_FIFO_FULL;
|
||||
}
|
||||
else if (gifRegs.stat.FQC == 0) {
|
||||
else if (gifRegs.stat.FQC == 0)
|
||||
{
|
||||
CSRreg.FIFO = CSR_FIFO_EMPTY;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
CSRreg.FIFO = CSR_FIFO_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CheckPaths() {
|
||||
bool CheckPaths()
|
||||
{
|
||||
// Can't do Path 3, so try dma again later...
|
||||
if (!gifUnit.CanDoPath3()) {
|
||||
if (!gifUnit.CanDoPath3())
|
||||
{
|
||||
if (!gifUnit.Path3Masked())
|
||||
{
|
||||
//DevCon.Warning("Path3 stalled APATH %x PSE %x DIR %x Signal %x", gifRegs.stat.APATH, gifRegs.stat.PSE, gifRegs.stat.DIR, gifUnit.gsSIGNAL.queued);
|
||||
|
@ -83,13 +93,13 @@ void GIF_Fifo::init()
|
|||
gif.gscycles = 0;
|
||||
gif.prevcycles = 0;
|
||||
gif.mfifocycles = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int GIF_Fifo::write_fifo(u32* pMem, int size)
|
||||
{
|
||||
if (fifoSize == 16) {
|
||||
if (fifoSize == 16)
|
||||
{
|
||||
//GIF_LOG("GIF FIFO Full");
|
||||
return 0;
|
||||
}
|
||||
|
@ -130,7 +140,8 @@ int GIF_Fifo::read_fifo()
|
|||
|
||||
GIF_LOG("GIF FIFO Read %d QW from FIFO Current Size %d", sizeRead, fifoSize);
|
||||
|
||||
if (sizeRead < fifoSize) {
|
||||
if (sizeRead < fifoSize)
|
||||
{
|
||||
if (sizeRead > 0)
|
||||
{
|
||||
int copyAmount = fifoSize - sizeRead;
|
||||
|
@ -160,16 +171,20 @@ int GIF_Fifo::read_fifo()
|
|||
return sizeRead;
|
||||
}
|
||||
|
||||
void incGifChAddr(u32 qwc) {
|
||||
if (gifch.chcr.STR) {
|
||||
void incGifChAddr(u32 qwc)
|
||||
{
|
||||
if (gifch.chcr.STR)
|
||||
{
|
||||
gifch.madr += qwc * 16;
|
||||
gifch.qwc -= qwc;
|
||||
hwDmacSrcTadrInc(gifch);
|
||||
}
|
||||
else DevCon.Error("incGifAddr() Error!");
|
||||
else
|
||||
DevCon.Error("incGifAddr() Error!");
|
||||
}
|
||||
|
||||
__fi void gifCheckPathStatus() {
|
||||
__fi void gifCheckPathStatus()
|
||||
{
|
||||
|
||||
if (gifRegs.stat.APATH == 3)
|
||||
{
|
||||
|
@ -177,7 +192,8 @@ __fi void gifCheckPathStatus() {
|
|||
gifRegs.stat.OPH = 0;
|
||||
if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE || gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT)
|
||||
{
|
||||
if (gifUnit.checkPaths(1, 1, 0)) gifUnit.Execute(false, true);
|
||||
if (gifUnit.checkPaths(1, 1, 0))
|
||||
gifUnit.Execute(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,20 +218,23 @@ __fi void gifInterrupt()
|
|||
// Make sure it loops if the GIF packet is empty to prepare for the next packet
|
||||
// or end if it was the end of a packet.
|
||||
// This must trigger after VIF retriggers as VIf might instantly mask Path3
|
||||
if (!gifUnit.Path3Masked() || gifch.qwc == 0) {
|
||||
if (!gifUnit.Path3Masked() || gifch.qwc == 0)
|
||||
{
|
||||
GifDMAInt(16);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (dmacRegs.ctrl.MFD == MFD_GIF) { // GIF MFIFO
|
||||
if (dmacRegs.ctrl.MFD == MFD_GIF)
|
||||
{ // GIF MFIFO
|
||||
//Console.WriteLn("GIF MFIFO");
|
||||
gifMFIFOInterrupt();
|
||||
return;
|
||||
}
|
||||
|
||||
if (gifUnit.gsSIGNAL.queued) {
|
||||
if (gifUnit.gsSIGNAL.queued)
|
||||
{
|
||||
GIF_LOG("Path 3 Paused");
|
||||
GifDMAInt(128);
|
||||
if (gif_fifo.fifoSize == 16)
|
||||
|
@ -237,7 +256,8 @@ __fi void gifInterrupt()
|
|||
if (vif1Regs.stat.VGW)
|
||||
{
|
||||
// Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back.
|
||||
if (!(cpuRegs.interrupt & (1 << DMAC_VIF1))) {
|
||||
if (!(cpuRegs.interrupt & (1 << DMAC_VIF1)))
|
||||
{
|
||||
CPU_INT(DMAC_VIF1, 1);
|
||||
}
|
||||
}
|
||||
|
@ -247,10 +267,13 @@ __fi void gifInterrupt()
|
|||
return;
|
||||
}
|
||||
|
||||
if (!(gifch.chcr.STR)) return;
|
||||
if (!(gifch.chcr.STR))
|
||||
return;
|
||||
|
||||
if ((gifch.qwc > 0) || (!gif.gspath3done)) {
|
||||
if (!dmacRegs.ctrl.DMAE) {
|
||||
if ((gifch.qwc > 0) || (!gif.gspath3done))
|
||||
{
|
||||
if (!dmacRegs.ctrl.DMAE)
|
||||
{
|
||||
Console.Warning("gs dma masked, re-scheduling...");
|
||||
// Re-raise the int shortly in the future
|
||||
GifDMAInt(64);
|
||||
|
@ -272,7 +295,8 @@ __fi void gifInterrupt()
|
|||
GIF_LOG("GIF DMA End QWC in fifo %x APATH = %x OPH = %x state = %x", gifRegs.stat.FQC, gifRegs.stat.APATH, gifRegs.stat.OPH, gifUnit.gifPath[GIF_PATH_3].state);
|
||||
}
|
||||
|
||||
static u32 WRITERING_DMA(u32 *pMem, u32 qwc) {
|
||||
static u32 WRITERING_DMA(u32* pMem, u32 qwc)
|
||||
{
|
||||
u32 originalQwc = qwc;
|
||||
|
||||
if (gifRegs.stat.IMT)
|
||||
|
@ -305,11 +329,13 @@ static u32 WRITERING_DMA(u32 *pMem, u32 qwc) {
|
|||
return size;
|
||||
}
|
||||
|
||||
static __fi void GIFchain() {
|
||||
static __fi void GIFchain()
|
||||
{
|
||||
tDMA_TAG* pMem;
|
||||
|
||||
pMem = dmaGetAddr(gifch.madr, false);
|
||||
if (pMem == NULL) {
|
||||
if (pMem == NULL)
|
||||
{
|
||||
// Must increment madr and clear qwc, else it loops
|
||||
gifch.madr += gifch.qwc * 16;
|
||||
gifch.qwc = 0;
|
||||
|
@ -326,7 +352,8 @@ static __fi void GIFchain() {
|
|||
|
||||
static __fi bool checkTieBit(tDMA_TAG*& ptag)
|
||||
{
|
||||
if (gifch.chcr.TIE && ptag->IRQ) {
|
||||
if (gifch.chcr.TIE && ptag->IRQ)
|
||||
{
|
||||
GIF_LOG("dmaIrq Set");
|
||||
gif.gspath3done = true;
|
||||
return true;
|
||||
|
@ -338,7 +365,8 @@ static __fi tDMA_TAG* ReadTag()
|
|||
{
|
||||
tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); // Set memory pointer to TADR
|
||||
|
||||
if (!(gifch.transfer("Gif", ptag))) return NULL;
|
||||
if (!(gifch.transfer("Gif", ptag)))
|
||||
return NULL;
|
||||
|
||||
gifch.madr = ptag[1]._u32; // MADR = ADDR field + SPR
|
||||
gif.gscycles += 2; // Add 1 cycles from the QW read for the tag
|
||||
|
@ -360,19 +388,23 @@ static __fi tDMA_TAG* ReadTag2()
|
|||
|
||||
void GIFdma()
|
||||
{
|
||||
while (gifch.qwc > 0 || !gif.gspath3done) {
|
||||
while (gifch.qwc > 0 || !gif.gspath3done)
|
||||
{
|
||||
tDMA_TAG* ptag;
|
||||
gif.gscycles = gif.prevcycles;
|
||||
|
||||
if (gifRegs.ctrl.PSE) { // Temporarily stop
|
||||
if (gifRegs.ctrl.PSE)
|
||||
{ // Temporarily stop
|
||||
Console.WriteLn("Gif dma temp paused? (non MFIFO GIF)");
|
||||
GifDMAInt(16);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((dmacRegs.ctrl.STD == STD_GIF) && (gif.prevcycles != 0)) {
|
||||
if ((dmacRegs.ctrl.STD == STD_GIF) && (gif.prevcycles != 0))
|
||||
{
|
||||
//Console.WriteLn("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3, gifch.madr, psHu32(DMAC_STADR));
|
||||
if ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR) {
|
||||
if ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR)
|
||||
{
|
||||
GifDMAInt(4);
|
||||
gif.gscycles = 0;
|
||||
return;
|
||||
|
@ -384,7 +416,8 @@ void GIFdma()
|
|||
if ((gifch.chcr.MOD == CHAIN_MODE) && (!gif.gspath3done) && gifch.qwc == 0) // Chain Mode
|
||||
{
|
||||
ptag = ReadTag();
|
||||
if (ptag == NULL) return;
|
||||
if (ptag == NULL)
|
||||
return;
|
||||
//DevCon.Warning("GIF Reading Tag MSK = %x", vif1Regs.mskpath3);
|
||||
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr);
|
||||
gifRegs.stat.FQC = std::min((u32)0x10, gifch.qwc);
|
||||
|
@ -433,13 +466,16 @@ void dmaGIF()
|
|||
|
||||
gif.gspath3done = false; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :)
|
||||
|
||||
if (gifch.chcr.MOD == NORMAL_MODE) { // Else it really is a normal transfer and we want to quit, else it gets confused with chains
|
||||
if (gifch.chcr.MOD == NORMAL_MODE)
|
||||
{ // Else it really is a normal transfer and we want to quit, else it gets confused with chains
|
||||
gif.gspath3done = true;
|
||||
}
|
||||
|
||||
if(gifch.chcr.MOD == CHAIN_MODE && gifch.qwc > 0) {
|
||||
if (gifch.chcr.MOD == CHAIN_MODE && gifch.qwc > 0)
|
||||
{
|
||||
//DevCon.Warning(L"GIF QWC on Chain " + gifch.chcr.desc());
|
||||
if ((gifch.chcr.tag().ID == TAG_REFE) || (gifch.chcr.tag().ID == TAG_END) || (gifch.chcr.tag().IRQ && gifch.chcr.TIE)) {
|
||||
if ((gifch.chcr.tag().ID == TAG_REFE) || (gifch.chcr.tag().ID == TAG_END) || (gifch.chcr.tag().IRQ && gifch.chcr.TIE))
|
||||
{
|
||||
gif.gspath3done = true;
|
||||
}
|
||||
}
|
||||
|
@ -453,11 +489,13 @@ static u32 QWCinGIFMFIFO(u32 DrainADDR)
|
|||
|
||||
SPR_LOG("GIF MFIFO Requesting %x QWC from the MFIFO Base %x, SPR MADR %x Drain %x", gifch.qwc, dmacRegs.rbor.ADDR, spr0ch.madr, DrainADDR);
|
||||
// Calculate what we have in the fifo.
|
||||
if (DrainADDR <= spr0ch.madr) {
|
||||
if (DrainADDR <= spr0ch.madr)
|
||||
{
|
||||
// Drain is below the write position, calculate the difference between them
|
||||
ret = (spr0ch.madr - DrainADDR) >> 4;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
u32 limit = dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16;
|
||||
// Drain is higher than SPR so it has looped round,
|
||||
// calculate from base to the SPR tag addr and what is left in the top of the ring
|
||||
|
@ -478,7 +516,8 @@ static __fi bool mfifoGIFrbTransfer()
|
|||
return true;
|
||||
|
||||
u8* src = (u8*)PSM(gifch.madr);
|
||||
if (src == NULL) return false;
|
||||
if (src == NULL)
|
||||
return false;
|
||||
|
||||
u32 MFIFOUntilEnd = ((dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16) - gifch.madr) >> 4;
|
||||
bool needWrap = MFIFOUntilEnd < qwc;
|
||||
|
@ -497,7 +536,8 @@ static __fi bool mfifoGIFrbTransfer()
|
|||
uint secondTransQWC = qwc - MFIFOUntilEnd;
|
||||
|
||||
src = (u8*)PSM(dmacRegs.rbor.ADDR);
|
||||
if (src == NULL) return false;
|
||||
if (src == NULL)
|
||||
return false;
|
||||
|
||||
transferred2 = WRITERING_DMA((u32*)src, secondTransQWC); // Second part
|
||||
|
||||
|
@ -520,7 +560,8 @@ static __fi void mfifoGIFchain()
|
|||
|
||||
if ((gifch.madr & ~dmacRegs.rbsr.RMSK) == dmacRegs.rbor.ADDR)
|
||||
{
|
||||
if (QWCinGIFMFIFO(gifch.madr) == 0) {
|
||||
if (QWCinGIFMFIFO(gifch.madr) == 0)
|
||||
{
|
||||
SPR_LOG("GIF FIFO EMPTY before transfer");
|
||||
gif.gifstate = GIF_STATE_EMPTY;
|
||||
gif.mfifocycles += 4;
|
||||
|
@ -540,7 +581,8 @@ static __fi void mfifoGIFchain()
|
|||
gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK);
|
||||
gifch.tadr = gifch.madr;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
SPR_LOG("Non-MFIFO Location transfer doing %x Total QWC", gifch.qwc);
|
||||
tDMA_TAG* pMem = dmaGetAddr(gifch.madr, false);
|
||||
if (pMem == NULL)
|
||||
|
@ -557,13 +599,15 @@ static __fi void mfifoGIFchain()
|
|||
return;
|
||||
}
|
||||
|
||||
static u32 qwctag(u32 mask) {
|
||||
static u32 qwctag(u32 mask)
|
||||
{
|
||||
return (dmacRegs.rbor.ADDR + (mask & dmacRegs.rbsr.RMSK));
|
||||
}
|
||||
|
||||
void mfifoGifMaskMem(int id)
|
||||
{
|
||||
switch (id) {
|
||||
switch (id)
|
||||
{
|
||||
// These five transfer data following the tag, need to check its within the buffer (Front Mission 4)
|
||||
case TAG_CNT:
|
||||
case TAG_NEXT:
|
||||
|
@ -574,8 +618,8 @@ void mfifoGifMaskMem(int id)
|
|||
{
|
||||
SPR_LOG("GIF MFIFO MADR below bottom of ring buffer, wrapping GIF MADR = %x Ring Bottom %x", gifch.madr, dmacRegs.rbor.ADDR);
|
||||
gifch.madr = qwctag(gifch.madr);
|
||||
} else
|
||||
if(gifch.madr > (dmacRegs.rbor.ADDR + (u32)dmacRegs.rbsr.RMSK)) // Usual scenario is the tag is near the end (Front Mission 4)
|
||||
}
|
||||
else if (gifch.madr > (dmacRegs.rbor.ADDR + (u32)dmacRegs.rbsr.RMSK)) // Usual scenario is the tag is near the end (Front Mission 4)
|
||||
{
|
||||
SPR_LOG("GIF MFIFO MADR outside top of ring buffer, wrapping GIF MADR = %x Ring Top %x", gifch.madr, (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK) + 16);
|
||||
gifch.madr = qwctag(gifch.madr);
|
||||
|
@ -592,16 +636,19 @@ void mfifoGIFtransfer()
|
|||
tDMA_TAG* ptag;
|
||||
gif.mfifocycles = 0;
|
||||
|
||||
if (gifRegs.ctrl.PSE) { // Temporarily stop
|
||||
if (gifRegs.ctrl.PSE)
|
||||
{ // Temporarily stop
|
||||
Console.WriteLn("Gif dma temp paused?");
|
||||
CPU_INT(DMAC_MFIFO_GIF, 16);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gifch.qwc == 0) {
|
||||
if (gifch.qwc == 0)
|
||||
{
|
||||
gifch.tadr = qwctag(gifch.tadr);
|
||||
|
||||
if (QWCinGIFMFIFO(gifch.tadr) == 0) {
|
||||
if (QWCinGIFMFIFO(gifch.tadr) == 0)
|
||||
{
|
||||
SPR_LOG("GIF FIFO EMPTY before tag read");
|
||||
gif.gifstate = GIF_STATE_EMPTY;
|
||||
GifDMAInt(4);
|
||||
|
@ -630,7 +677,8 @@ void mfifoGIFtransfer()
|
|||
|
||||
gifch.tadr = qwctag(gifch.tadr);
|
||||
|
||||
if ((gifch.chcr.TIE) && (ptag->IRQ)) {
|
||||
if ((gifch.chcr.TIE) && (ptag->IRQ))
|
||||
{
|
||||
SPR_LOG("dmaIrq Set");
|
||||
gif.gspath3done = true;
|
||||
}
|
||||
|
@ -648,7 +696,8 @@ void gifMFIFOInterrupt()
|
|||
//DevCon.Warning("gifMFIFOInterrupt");
|
||||
gif.mfifocycles = 0;
|
||||
|
||||
if (dmacRegs.ctrl.MFD != MFD_GIF) { // GIF not in MFIFO anymore, come out.
|
||||
if (dmacRegs.ctrl.MFD != MFD_GIF)
|
||||
{ // GIF not in MFIFO anymore, come out.
|
||||
DevCon.WriteLn("GIF Leaving MFIFO - Report if any errors");
|
||||
gifInterrupt();
|
||||
return;
|
||||
|
@ -667,14 +716,16 @@ void gifMFIFOInterrupt()
|
|||
// Make sure it loops if the GIF packet is empty to prepare for the next packet
|
||||
// or end if it was the end of a packet.
|
||||
// This must trigger after VIF retriggers as VIf might instantly mask Path3
|
||||
if (!gifUnit.Path3Masked() || gifch.qwc == 0) {
|
||||
if (!gifUnit.Path3Masked() || gifch.qwc == 0)
|
||||
{
|
||||
GifDMAInt(16);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (gifUnit.gsSIGNAL.queued) {
|
||||
if (gifUnit.gsSIGNAL.queued)
|
||||
{
|
||||
GifDMAInt(128);
|
||||
return;
|
||||
}
|
||||
|
@ -692,7 +743,8 @@ void gifMFIFOInterrupt()
|
|||
// Make sure it loops if the GIF packet is empty to prepare for the next packet
|
||||
// or end if it was the end of a packet.
|
||||
// This must trigger after VIF retriggers as VIf might instantly mask Path3
|
||||
if (!gifUnit.Path3Masked() || gifch.qwc == 0) {
|
||||
if (!gifUnit.Path3Masked() || gifch.qwc == 0)
|
||||
{
|
||||
GifDMAInt(16);
|
||||
}
|
||||
return;
|
||||
|
@ -714,7 +766,8 @@ void gifMFIFOInterrupt()
|
|||
if (vif1Regs.stat.VGW)
|
||||
{
|
||||
//Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back.
|
||||
if (!(cpuRegs.interrupt & (1 << DMAC_VIF1))) {
|
||||
if (!(cpuRegs.interrupt & (1 << DMAC_VIF1)))
|
||||
{
|
||||
CPU_INT(DMAC_VIF1, 1);
|
||||
}
|
||||
}
|
||||
|
@ -727,7 +780,8 @@ void gifMFIFOInterrupt()
|
|||
if (!gifch.chcr.STR)
|
||||
return;
|
||||
|
||||
if (spr0ch.madr == gifch.tadr || (gif.gifstate & GIF_STATE_EMPTY)) {
|
||||
if (spr0ch.madr == gifch.tadr || (gif.gifstate & GIF_STATE_EMPTY))
|
||||
{
|
||||
gif.gifstate = GIF_STATE_EMPTY; // In case of madr = tadr we need to set it
|
||||
FireMFIFOEmpty();
|
||||
|
||||
|
@ -735,7 +789,8 @@ void gifMFIFOInterrupt()
|
|||
return;
|
||||
}
|
||||
|
||||
if (gifch.qwc > 0 || !gif.gspath3done) {
|
||||
if (gifch.qwc > 0 || !gif.gspath3done)
|
||||
{
|
||||
|
||||
mfifoGIFtransfer();
|
||||
return;
|
||||
|
@ -754,7 +809,8 @@ void gifMFIFOInterrupt()
|
|||
DMA_LOG("GIF MFIFO DMA End");
|
||||
}
|
||||
|
||||
void SaveStateBase::gifDmaFreeze() {
|
||||
void SaveStateBase::gifDmaFreeze()
|
||||
{
|
||||
// Note: mfifocycles is not a persistent var, so no need to save it here.
|
||||
FreezeTag("GIFdma");
|
||||
Freeze(gif.gifstate);
|
||||
|
|
140
pcsx2/Vif.cpp
140
pcsx2/Vif.cpp
|
@ -71,7 +71,8 @@ void SaveStateBase::vif1Freeze()
|
|||
// Vif0/Vif1 Write32
|
||||
//------------------------------------------------------------------
|
||||
|
||||
__fi void vif0FBRST(u32 value) {
|
||||
__fi void vif0FBRST(u32 value)
|
||||
{
|
||||
VIF_LOG("VIF0_FBRST write32 0x%8.8x", value);
|
||||
|
||||
if (value & 0x1) // Reset Vif.
|
||||
|
@ -140,12 +141,14 @@ __fi void vif0FBRST(u32 value) {
|
|||
{
|
||||
g_vif0Cycles = 0;
|
||||
// loop necessary for spiderman
|
||||
if(vif0ch.chcr.STR) CPU_INT(DMAC_VIF0, 0); // Gets the timing right - Flatout
|
||||
if (vif0ch.chcr.STR)
|
||||
CPU_INT(DMAC_VIF0, 0); // Gets the timing right - Flatout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__fi void vif1FBRST(u32 value) {
|
||||
__fi void vif1FBRST(u32 value)
|
||||
{
|
||||
VIF_LOG("VIF1_FBRST write32 0x%8.8x", value);
|
||||
|
||||
if (FBRST(value).RST) // Reset Vif.
|
||||
|
@ -222,14 +225,16 @@ __fi void vif1FBRST(u32 value) {
|
|||
case MFD_VIF1:
|
||||
//Console.WriteLn("MFIFO Stall");
|
||||
//MFIFO active and not empty
|
||||
if(vif1ch.chcr.STR && !vif1Regs.stat.test(VIF1_STAT_FDR)) CPU_INT(DMAC_MFIFO_VIF, 0);
|
||||
if (vif1ch.chcr.STR && !vif1Regs.stat.test(VIF1_STAT_FDR))
|
||||
CPU_INT(DMAC_MFIFO_VIF, 0);
|
||||
break;
|
||||
|
||||
case NO_MFD:
|
||||
case MFD_RESERVED:
|
||||
case MFD_GIF: // Wonder if this should be with VIF?
|
||||
// Gets the timing right - Flatout
|
||||
if(vif1ch.chcr.STR && !vif1Regs.stat.test(VIF1_STAT_FDR)) CPU_INT(DMAC_VIF1, 0);
|
||||
if (vif1ch.chcr.STR && !vif1Regs.stat.test(VIF1_STAT_FDR))
|
||||
CPU_INT(DMAC_VIF1, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -238,14 +243,17 @@ __fi void vif1FBRST(u32 value) {
|
|||
}
|
||||
}
|
||||
|
||||
__fi void vif1STAT(u32 value) {
|
||||
__fi void vif1STAT(u32 value)
|
||||
{
|
||||
VIF_LOG("VIF1_STAT write32 0x%8.8x", value);
|
||||
|
||||
/* Only FDR bit is writable, so mask the rest */
|
||||
if ((vif1Regs.stat.FDR) ^ ((tVIF_STAT&)value).FDR) {
|
||||
if ((vif1Regs.stat.FDR) ^ ((tVIF_STAT&)value).FDR)
|
||||
{
|
||||
bool isStalled = false;
|
||||
// different so can't be stalled
|
||||
if (vif1Regs.stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS)) {
|
||||
if (vif1Regs.stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
|
||||
{
|
||||
DbgCon.WriteLn("changing dir when vif1 fifo stalled done = %x qwc = %x stat = %x", vif1.done, vif1ch.qwc, vif1Regs.stat._u32);
|
||||
isStalled = true;
|
||||
}
|
||||
|
@ -255,7 +263,8 @@ __fi void vif1STAT(u32 value) {
|
|||
//Hotwheels had this in the "direction when stalled" area, however Sled Storm seems to keep an eye on the dma
|
||||
//position, as we clear it and set it to the end well before the interrupt, the game assumes it's finished,
|
||||
//then proceeds to reverse the dma before we have even done it ourselves. So lets just make sure VIF is ready :)
|
||||
if (vif1ch.qwc > 0 || isStalled == false){
|
||||
if (vif1ch.qwc > 0 || isStalled == false)
|
||||
{
|
||||
vif1ch.qwc = 0;
|
||||
hwDmacIrq(DMAC_VIF1);
|
||||
vif1ch.chcr.STR = false;
|
||||
|
@ -277,32 +286,58 @@ __fi void vif1STAT(u32 value) {
|
|||
|
||||
vif1Regs.stat.FQC = std::min((u32)16, vif1.GSLastDownloadSize);
|
||||
//Console.Warning("Reversing VIF Transfer for %x QWC", vif1.GSLastDownloadSize);
|
||||
|
||||
}
|
||||
else // Memory transferring to Vif.
|
||||
{
|
||||
//Sometimes the value from the GS is bigger than vif wanted, so it just sets it back and cancels it.
|
||||
//Other times it can read it off ;)
|
||||
vif1Regs.stat.FQC = 0;
|
||||
if (vif1ch.chcr.STR) CPU_INT(DMAC_VIF1, 0);
|
||||
if (vif1ch.chcr.STR)
|
||||
CPU_INT(DMAC_VIF1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#define caseVif(x) (idx ? VIF1_##x : VIF0_##x)
|
||||
|
||||
_vifT __fi u32 vifRead32(u32 mem) {
|
||||
_vifT __fi u32 vifRead32(u32 mem)
|
||||
{
|
||||
vifStruct& vif = MTVU_VifX;
|
||||
bool wait = idx && THREAD_VU1;
|
||||
switch (mem) {
|
||||
case caseVif(ROW0): if (wait) vu1Thread.WaitVU(); return vif.MaskRow._u32[0];
|
||||
case caseVif(ROW1): if (wait) vu1Thread.WaitVU(); return vif.MaskRow._u32[1];
|
||||
case caseVif(ROW2): if (wait) vu1Thread.WaitVU(); return vif.MaskRow._u32[2];
|
||||
case caseVif(ROW3): if (wait) vu1Thread.WaitVU(); return vif.MaskRow._u32[3];
|
||||
switch (mem)
|
||||
{
|
||||
case caseVif(ROW0):
|
||||
if (wait)
|
||||
vu1Thread.WaitVU();
|
||||
return vif.MaskRow._u32[0];
|
||||
case caseVif(ROW1):
|
||||
if (wait)
|
||||
vu1Thread.WaitVU();
|
||||
return vif.MaskRow._u32[1];
|
||||
case caseVif(ROW2):
|
||||
if (wait)
|
||||
vu1Thread.WaitVU();
|
||||
return vif.MaskRow._u32[2];
|
||||
case caseVif(ROW3):
|
||||
if (wait)
|
||||
vu1Thread.WaitVU();
|
||||
return vif.MaskRow._u32[3];
|
||||
|
||||
case caseVif(COL0): if (wait) vu1Thread.WaitVU(); return vif.MaskCol._u32[0];
|
||||
case caseVif(COL1): if (wait) vu1Thread.WaitVU(); return vif.MaskCol._u32[1];
|
||||
case caseVif(COL2): if (wait) vu1Thread.WaitVU(); return vif.MaskCol._u32[2];
|
||||
case caseVif(COL3): if (wait) vu1Thread.WaitVU(); return vif.MaskCol._u32[3];
|
||||
case caseVif(COL0):
|
||||
if (wait)
|
||||
vu1Thread.WaitVU();
|
||||
return vif.MaskCol._u32[0];
|
||||
case caseVif(COL1):
|
||||
if (wait)
|
||||
vu1Thread.WaitVU();
|
||||
return vif.MaskCol._u32[1];
|
||||
case caseVif(COL2):
|
||||
if (wait)
|
||||
vu1Thread.WaitVU();
|
||||
return vif.MaskCol._u32[2];
|
||||
case caseVif(COL3):
|
||||
if (wait)
|
||||
vu1Thread.WaitVU();
|
||||
return vif.MaskCol._u32[3];
|
||||
}
|
||||
|
||||
return psHu32(mem);
|
||||
|
@ -310,10 +345,12 @@ _vifT __fi u32 vifRead32(u32 mem) {
|
|||
|
||||
// returns FALSE if no writeback is needed (or writeback is handled internally)
|
||||
// returns TRUE if the caller should writeback the value to the eeHw register map.
|
||||
_vifT __fi bool vifWrite32(u32 mem, u32 value) {
|
||||
_vifT __fi bool vifWrite32(u32 mem, u32 value)
|
||||
{
|
||||
vifStruct& vif = GetVifX;
|
||||
|
||||
switch (mem) {
|
||||
switch (mem)
|
||||
{
|
||||
case caseVif(MARK):
|
||||
VIF_LOG("VIF%d_MARK write32 0x%8.8x", idx, value);
|
||||
vifXRegs.stat.MRK = false;
|
||||
|
@ -321,12 +358,15 @@ _vifT __fi bool vifWrite32(u32 mem, u32 value) {
|
|||
break;
|
||||
|
||||
case caseVif(FBRST):
|
||||
if (!idx) vif0FBRST(value);
|
||||
else vif1FBRST(value);
|
||||
if (!idx)
|
||||
vif0FBRST(value);
|
||||
else
|
||||
vif1FBRST(value);
|
||||
return false;
|
||||
|
||||
case caseVif(STAT):
|
||||
if (idx) { // Only Vif1 does this stuff?
|
||||
if (idx)
|
||||
{ // Only Vif1 does this stuff?
|
||||
vif1STAT(value);
|
||||
}
|
||||
return false;
|
||||
|
@ -336,15 +376,47 @@ _vifT __fi bool vifWrite32(u32 mem, u32 value) {
|
|||
// standard register writes -- handled by caller.
|
||||
break;
|
||||
|
||||
case caseVif(ROW0): vif.MaskRow._u32[0] = value; if (idx && THREAD_VU1) vu1Thread.WriteRow(vif); return false;
|
||||
case caseVif(ROW1): vif.MaskRow._u32[1] = value; if (idx && THREAD_VU1) vu1Thread.WriteRow(vif); return false;
|
||||
case caseVif(ROW2): vif.MaskRow._u32[2] = value; if (idx && THREAD_VU1) vu1Thread.WriteRow(vif); return false;
|
||||
case caseVif(ROW3): vif.MaskRow._u32[3] = value; if (idx && THREAD_VU1) vu1Thread.WriteRow(vif); return false;
|
||||
case caseVif(ROW0):
|
||||
vif.MaskRow._u32[0] = value;
|
||||
if (idx && THREAD_VU1)
|
||||
vu1Thread.WriteRow(vif);
|
||||
return false;
|
||||
case caseVif(ROW1):
|
||||
vif.MaskRow._u32[1] = value;
|
||||
if (idx && THREAD_VU1)
|
||||
vu1Thread.WriteRow(vif);
|
||||
return false;
|
||||
case caseVif(ROW2):
|
||||
vif.MaskRow._u32[2] = value;
|
||||
if (idx && THREAD_VU1)
|
||||
vu1Thread.WriteRow(vif);
|
||||
return false;
|
||||
case caseVif(ROW3):
|
||||
vif.MaskRow._u32[3] = value;
|
||||
if (idx && THREAD_VU1)
|
||||
vu1Thread.WriteRow(vif);
|
||||
return false;
|
||||
|
||||
case caseVif(COL0): vif.MaskCol._u32[0] = value; if (idx && THREAD_VU1) vu1Thread.WriteCol(vif); return false;
|
||||
case caseVif(COL1): vif.MaskCol._u32[1] = value; if (idx && THREAD_VU1) vu1Thread.WriteCol(vif); return false;
|
||||
case caseVif(COL2): vif.MaskCol._u32[2] = value; if (idx && THREAD_VU1) vu1Thread.WriteCol(vif); return false;
|
||||
case caseVif(COL3): vif.MaskCol._u32[3] = value; if (idx && THREAD_VU1) vu1Thread.WriteCol(vif); return false;
|
||||
case caseVif(COL0):
|
||||
vif.MaskCol._u32[0] = value;
|
||||
if (idx && THREAD_VU1)
|
||||
vu1Thread.WriteCol(vif);
|
||||
return false;
|
||||
case caseVif(COL1):
|
||||
vif.MaskCol._u32[1] = value;
|
||||
if (idx && THREAD_VU1)
|
||||
vu1Thread.WriteCol(vif);
|
||||
return false;
|
||||
case caseVif(COL2):
|
||||
vif.MaskCol._u32[2] = value;
|
||||
if (idx && THREAD_VU1)
|
||||
vu1Thread.WriteCol(vif);
|
||||
return false;
|
||||
case caseVif(COL3):
|
||||
vif.MaskCol._u32[3] = value;
|
||||
if (idx && THREAD_VU1)
|
||||
vu1Thread.WriteCol(vif);
|
||||
return false;
|
||||
}
|
||||
|
||||
// fall-through case: issue standard writeback behavior.
|
||||
|
|
|
@ -27,7 +27,11 @@
|
|||
#define pass2 if (pass == 1)
|
||||
#define pass3 if (pass == 2)
|
||||
#define pass1or2 if (pass == 0 || pass == 1)
|
||||
#define vif1Only() { if (!idx) return vifCode_Null<idx>(pass, (u32*)data); }
|
||||
#define vif1Only() \
|
||||
{ \
|
||||
if (!idx) \
|
||||
return vifCode_Null<idx>(pass, (u32*)data); \
|
||||
}
|
||||
vifOp(vifCode_Null);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -41,8 +45,10 @@ __ri void vifExecQueue(int idx)
|
|||
|
||||
GetVifX.queued_program = false;
|
||||
|
||||
if (!idx) vu0ExecMicro(vif0.queued_pc);
|
||||
else vu1ExecMicro(vif1.queued_pc);
|
||||
if (!idx)
|
||||
vu0ExecMicro(vif0.queued_pc);
|
||||
else
|
||||
vu1ExecMicro(vif1.queued_pc);
|
||||
|
||||
// Hack for Wakeboarding Unleashed, game runs a VU program in parallel with a VIF unpack list.
|
||||
// The start of the VU program clears the VU memory, while VIF populates it from behind, so we need to get the clear out of the way.
|
||||
|
@ -53,40 +59,48 @@ __ri void vifExecQueue(int idx)
|
|||
}*/
|
||||
}
|
||||
|
||||
static __fi void vifFlush(int idx) {
|
||||
static __fi void vifFlush(int idx)
|
||||
{
|
||||
vifExecQueue(idx);
|
||||
|
||||
if (!idx) vif0FLUSH();
|
||||
else vif1FLUSH();
|
||||
if (!idx)
|
||||
vif0FLUSH();
|
||||
else
|
||||
vif1FLUSH();
|
||||
|
||||
vifExecQueue(idx);
|
||||
}
|
||||
|
||||
static __fi void vuExecMicro(int idx, u32 addr) {
|
||||
static __fi void vuExecMicro(int idx, u32 addr)
|
||||
{
|
||||
VIFregisters& vifRegs = vifXRegs;
|
||||
|
||||
vifFlush(idx);
|
||||
if (GetVifX.waitforvu)
|
||||
return;
|
||||
|
||||
if (vifRegs.itops > (idx ? 0x3ffu : 0xffu)) {
|
||||
if (vifRegs.itops > (idx ? 0x3ffu : 0xffu))
|
||||
{
|
||||
Console.WriteLn("VIF%d ITOP overrun! %x", idx, vifRegs.itops);
|
||||
vifRegs.itops &= (idx ? 0x3ffu : 0xffu);
|
||||
}
|
||||
|
||||
vifRegs.itop = vifRegs.itops;
|
||||
|
||||
if (idx) {
|
||||
if (idx)
|
||||
{
|
||||
// in case we're handling a VIF1 execMicro, set the top with the tops value
|
||||
vifRegs.top = vifRegs.tops & 0x3ff;
|
||||
|
||||
// is DBF flag set in VIF_STAT?
|
||||
if (vifRegs.stat.DBF) {
|
||||
if (vifRegs.stat.DBF)
|
||||
{
|
||||
// it is, so set tops with base, and clear the stat DBF flag
|
||||
vifRegs.tops = vifRegs.base;
|
||||
vifRegs.stat.DBF = false;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
// it is not, so set tops with base + offset, and set stat DBF flag
|
||||
vifRegs.tops = vifRegs.base + vifRegs.ofst;
|
||||
vifRegs.stat.DBF = true;
|
||||
|
@ -127,22 +141,32 @@ void ExecuteVU(int idx)
|
|||
// Vif0/Vif1 Code Implementations
|
||||
//------------------------------------------------------------------
|
||||
|
||||
vifOp(vifCode_Base) {
|
||||
vifOp(vifCode_Base)
|
||||
{
|
||||
vif1Only();
|
||||
pass1 { vif1Regs.base = vif1Regs.code & 0x3ff; vif1.cmd = 0; vif1.pass = 0; }
|
||||
pass1
|
||||
{
|
||||
vif1Regs.base = vif1Regs.code & 0x3ff;
|
||||
vif1.cmd = 0;
|
||||
vif1.pass = 0;
|
||||
}
|
||||
pass3 { VifCodeLog("Base"); }
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDirectHL) {
|
||||
template <int idx>
|
||||
__fi int _vifCode_Direct(int pass, const u8* data, bool isDirectHL)
|
||||
{
|
||||
vif1Only();
|
||||
pass1 {
|
||||
pass1
|
||||
{
|
||||
int vifImm = (u16)vif1Regs.code;
|
||||
vif1.tag.size = vifImm ? (vifImm * 4) : (65536 * 4);
|
||||
vif1.pass = 1;
|
||||
return 1;
|
||||
}
|
||||
pass2 {
|
||||
pass2
|
||||
{
|
||||
const char* name = isDirectHL ? "DirectHL" : "Direct";
|
||||
GIF_TRANSFER_TYPE tranType = isDirectHL ? GIF_TRANS_DIRECTHL : GIF_TRANS_DIRECT;
|
||||
uint size = std::min(vif1.vifpacketsize, vif1.tag.size) * 4; // Get size in bytes
|
||||
|
@ -151,9 +175,12 @@ template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDire
|
|||
vif1.tag.size -= ret / 4; // Convert to u32's
|
||||
vif1Regs.stat.VGW = false;
|
||||
|
||||
if (ret & 3) DevCon.Warning("Vif %s: Ret wasn't a multiple of 4!", name); // Shouldn't happen
|
||||
if (size == 0) DevCon.Warning("Vif %s: No Data Transfer?", name); // Can this happen?
|
||||
if (size != ret) { // Stall if gif didn't process all the data (path2 queued)
|
||||
if (ret & 3)
|
||||
DevCon.Warning("Vif %s: Ret wasn't a multiple of 4!", name); // Shouldn't happen
|
||||
if (size == 0)
|
||||
DevCon.Warning("Vif %s: No Data Transfer?", name); // Can this happen?
|
||||
if (size != ret)
|
||||
{ // Stall if gif didn't process all the data (path2 queued)
|
||||
GUNIT_WARN("Vif %s: Stall! [size=%d][ret=%d]", name, size, ret);
|
||||
//gifUnit.PrintInfo();
|
||||
vif1.vifstalled.enabled = VifStallEnable(vif1ch);
|
||||
|
@ -161,7 +188,8 @@ template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDire
|
|||
vif1Regs.stat.VGW = true;
|
||||
return 0;
|
||||
}
|
||||
if (vif1.tag.size == 0) {
|
||||
if (vif1.tag.size == 0)
|
||||
{
|
||||
vif1.cmd = 0;
|
||||
vif1.pass = 0;
|
||||
vif1.vifstalled.enabled = VifStallEnable(vif1ch);
|
||||
|
@ -172,24 +200,29 @@ template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDire
|
|||
return 0;
|
||||
}
|
||||
|
||||
vifOp(vifCode_Direct) {
|
||||
vifOp(vifCode_Direct)
|
||||
{
|
||||
pass3 { VifCodeLog("Direct"); }
|
||||
return _vifCode_Direct<idx>(pass, (u8*)data, 0);
|
||||
}
|
||||
|
||||
vifOp(vifCode_DirectHL) {
|
||||
vifOp(vifCode_DirectHL)
|
||||
{
|
||||
pass3 { VifCodeLog("DirectHL"); }
|
||||
return _vifCode_Direct<idx>(pass, (u8*)data, 1);
|
||||
}
|
||||
|
||||
vifOp(vifCode_Flush) {
|
||||
vifOp(vifCode_Flush)
|
||||
{
|
||||
vif1Only();
|
||||
//vifStruct& vifX = GetVifX;
|
||||
pass1or2 {
|
||||
pass1or2
|
||||
{
|
||||
bool p1or2 = (gifRegs.stat.APATH != 0 && gifRegs.stat.APATH != 3);
|
||||
vif1Regs.stat.VGW = false;
|
||||
vifFlush(idx);
|
||||
if (gifUnit.checkPaths(1,1,0) || p1or2) {
|
||||
if (gifUnit.checkPaths(1, 1, 0) || p1or2)
|
||||
{
|
||||
GUNIT_WARN("Vif Flush: Stall!");
|
||||
//gifUnit.PrintInfo();
|
||||
vif1Regs.stat.VGW = true;
|
||||
|
@ -197,17 +230,20 @@ vifOp(vifCode_Flush) {
|
|||
vif1.vifstalled.value = VIF_TIMING_BREAK;
|
||||
return 0;
|
||||
}
|
||||
else vif1.cmd = 0;
|
||||
else
|
||||
vif1.cmd = 0;
|
||||
vif1.pass = 0;
|
||||
}
|
||||
pass3 { VifCodeLog("Flush"); }
|
||||
return 1;
|
||||
}
|
||||
|
||||
vifOp(vifCode_FlushA) {
|
||||
vifOp(vifCode_FlushA)
|
||||
{
|
||||
vif1Only();
|
||||
//vifStruct& vifX = GetVifX;
|
||||
pass1or2 {
|
||||
pass1or2
|
||||
{
|
||||
//Gif_Path& p3 = gifUnit.gifPath[GIF_PATH_3];
|
||||
u32 gifBusy = gifUnit.checkPaths(1, 1, 1) || (gifRegs.stat.APATH != 0);
|
||||
//bool doStall = false;
|
||||
|
@ -221,7 +257,6 @@ vifOp(vifCode_FlushA) {
|
|||
vif1.vifstalled.enabled = VifStallEnable(vif1ch);
|
||||
vif1.vifstalled.value = VIF_TIMING_BREAK;
|
||||
return 0;
|
||||
|
||||
}
|
||||
vif1.cmd = 0;
|
||||
vif1.pass = 0;
|
||||
|
@ -231,22 +266,36 @@ vifOp(vifCode_FlushA) {
|
|||
}
|
||||
|
||||
// ToDo: FixMe
|
||||
vifOp(vifCode_FlushE) {
|
||||
vifOp(vifCode_FlushE)
|
||||
{
|
||||
vifStruct& vifX = GetVifX;
|
||||
pass1 { vifFlush(idx); vifX.cmd = 0; vifX.pass = 0;}
|
||||
pass1
|
||||
{
|
||||
vifFlush(idx);
|
||||
vifX.cmd = 0;
|
||||
vifX.pass = 0;
|
||||
}
|
||||
pass3 { VifCodeLog("FlushE"); }
|
||||
return 1;
|
||||
}
|
||||
|
||||
vifOp(vifCode_ITop) {
|
||||
pass1 { vifXRegs.itops = vifXRegs.code & 0x3ff; GetVifX.cmd = 0; GetVifX.pass = 0; }
|
||||
vifOp(vifCode_ITop)
|
||||
{
|
||||
pass1
|
||||
{
|
||||
vifXRegs.itops = vifXRegs.code & 0x3ff;
|
||||
GetVifX.cmd = 0;
|
||||
GetVifX.pass = 0;
|
||||
}
|
||||
pass3 { VifCodeLog("ITop"); }
|
||||
return 1;
|
||||
}
|
||||
|
||||
vifOp(vifCode_Mark) {
|
||||
vifOp(vifCode_Mark)
|
||||
{
|
||||
vifStruct& vifX = GetVifX;
|
||||
pass1 {
|
||||
pass1
|
||||
{
|
||||
vifXRegs.mark = (u16)vifXRegs.code;
|
||||
vifXRegs.stat.MRK = true;
|
||||
vifX.cmd = 0;
|
||||
|
@ -256,7 +305,8 @@ vifOp(vifCode_Mark) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static __fi void _vifCode_MPG(int idx, u32 addr, const u32 *data, int size) {
|
||||
static __fi void _vifCode_MPG(int idx, u32 addr, const u32* data, int size)
|
||||
{
|
||||
VURegs& VUx = idx ? VU1 : VU0;
|
||||
vifStruct& vifX = GetVifX;
|
||||
u16 vuMemSize = idx ? 0x4000 : 0x1000;
|
||||
|
@ -264,7 +314,8 @@ static __fi void _vifCode_MPG(int idx, u32 addr, const u32 *data, int size) {
|
|||
|
||||
vifExecQueue(idx);
|
||||
|
||||
if (idx && THREAD_VU1) {
|
||||
if (idx && THREAD_VU1)
|
||||
{
|
||||
if ((addr + size * 4) > vuMemSize)
|
||||
{
|
||||
vu1Thread.WriteMicroMem(addr, (u8*)data, vuMemSize - addr);
|
||||
|
@ -285,8 +336,10 @@ static __fi void _vifCode_MPG(int idx, u32 addr, const u32 *data, int size) {
|
|||
if ((addr + size * 4) > vuMemSize)
|
||||
{
|
||||
//DevCon.Warning("Handling split MPG");
|
||||
if (!idx) CpuVU0->Clear(addr, vuMemSize - addr);
|
||||
else CpuVU1->Clear(addr, vuMemSize - addr);
|
||||
if (!idx)
|
||||
CpuVU0->Clear(addr, vuMemSize - addr);
|
||||
else
|
||||
CpuVU1->Clear(addr, vuMemSize - addr);
|
||||
|
||||
memcpy(VUx.Micro + addr, data, vuMemSize - addr);
|
||||
size -= (vuMemSize - addr) / 4;
|
||||
|
@ -301,40 +354,50 @@ static __fi void _vifCode_MPG(int idx, u32 addr, const u32 *data, int size) {
|
|||
//Faster without.
|
||||
//if (memcmp_mmx(VUx.Micro + addr, data, size*4)) {
|
||||
// Clear VU memory before writing!
|
||||
if (!idx) CpuVU0->Clear(addr, size*4);
|
||||
else CpuVU1->Clear(addr, size*4);
|
||||
if (!idx)
|
||||
CpuVU0->Clear(addr, size * 4);
|
||||
else
|
||||
CpuVU1->Clear(addr, size * 4);
|
||||
memcpy(VUx.Micro + addr, data, size * 4); //from tests, memcpy is 1fps faster on Grandia 3 than memcpy
|
||||
|
||||
vifX.tag.addr += size * 4;
|
||||
}
|
||||
}
|
||||
|
||||
vifOp(vifCode_MPG) {
|
||||
vifOp(vifCode_MPG)
|
||||
{
|
||||
vifStruct& vifX = GetVifX;
|
||||
pass1 {
|
||||
pass1
|
||||
{
|
||||
int vifNum = (u8)(vifXRegs.code >> 16);
|
||||
vifX.tag.addr = (u16)(vifXRegs.code << 3) & (idx ? 0x3fff : 0xfff);
|
||||
vifX.tag.size = vifNum ? (vifNum * 2) : 512;
|
||||
vifFlush(idx);
|
||||
|
||||
if(vifX.vifstalled.enabled) return 0;
|
||||
if (vifX.vifstalled.enabled)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
vifX.pass = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
pass2 {
|
||||
if (vifX.vifpacketsize < vifX.tag.size) { // Partial Transfer
|
||||
if((vifX.tag.addr + vifX.vifpacketsize*4) > (idx ? 0x4000 : 0x1000)) {
|
||||
pass2
|
||||
{
|
||||
if (vifX.vifpacketsize < vifX.tag.size)
|
||||
{ // Partial Transfer
|
||||
if ((vifX.tag.addr + vifX.vifpacketsize * 4) > (idx ? 0x4000 : 0x1000))
|
||||
{
|
||||
//DevCon.Warning("Vif%d MPG Split Overflow", idx);
|
||||
}
|
||||
_vifCode_MPG(idx, vifX.tag.addr, data, vifX.vifpacketsize);
|
||||
vifX.tag.size -= vifX.vifpacketsize; //We can do this first as its passed as a pointer
|
||||
return vifX.vifpacketsize;
|
||||
}
|
||||
else { // Full Transfer
|
||||
if((vifX.tag.addr + vifX.tag.size*4) > (idx ? 0x4000 : 0x1000)) {
|
||||
else
|
||||
{ // Full Transfer
|
||||
if ((vifX.tag.addr + vifX.tag.size * 4) > (idx ? 0x4000 : 0x1000))
|
||||
{
|
||||
//DevCon.Warning("Vif%d MPG Split Overflow full %x", idx, vifX.tag.addr + vifX.tag.size*4);
|
||||
}
|
||||
_vifCode_MPG(idx, vifX.tag.addr, data, vifX.tag.size);
|
||||
|
@ -349,9 +412,11 @@ vifOp(vifCode_MPG) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
vifOp(vifCode_MSCAL) {
|
||||
vifOp(vifCode_MSCAL)
|
||||
{
|
||||
vifStruct& vifX = GetVifX;
|
||||
pass1 {
|
||||
pass1
|
||||
{
|
||||
vifFlush(idx);
|
||||
|
||||
if (!vifX.waitforvu)
|
||||
|
@ -374,12 +439,15 @@ vifOp(vifCode_MSCAL) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
vifOp(vifCode_MSCALF) {
|
||||
vifOp(vifCode_MSCALF)
|
||||
{
|
||||
vifStruct& vifX = GetVifX;
|
||||
pass1or2 {
|
||||
pass1or2
|
||||
{
|
||||
vifXRegs.stat.VGW = false;
|
||||
vifFlush(idx);
|
||||
if (u32 a = gifUnit.checkPaths(1,1,0)) {
|
||||
if (u32 a = gifUnit.checkPaths(1, 1, 0))
|
||||
{
|
||||
GUNIT_WARN("Vif MSCALF: Stall! [%d,%d]", !!(a & 1), !!(a & 2));
|
||||
vif1Regs.stat.VGW = true;
|
||||
vifX.vifstalled.enabled = VifStallEnable(vifXch);
|
||||
|
@ -397,9 +465,11 @@ vifOp(vifCode_MSCALF) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
vifOp(vifCode_MSCNT) {
|
||||
vifOp(vifCode_MSCNT)
|
||||
{
|
||||
vifStruct& vifX = GetVifX;
|
||||
pass1 {
|
||||
pass1
|
||||
{
|
||||
vifFlush(idx);
|
||||
if (!vifX.waitforvu)
|
||||
{
|
||||
|
@ -420,13 +490,16 @@ vifOp(vifCode_MSCNT) {
|
|||
}
|
||||
|
||||
// ToDo: FixMe
|
||||
vifOp(vifCode_MskPath3) {
|
||||
vifOp(vifCode_MskPath3)
|
||||
{
|
||||
vif1Only();
|
||||
pass1 {
|
||||
pass1
|
||||
{
|
||||
vif1Regs.mskpath3 = (vif1Regs.code >> 15) & 0x1;
|
||||
gifRegs.stat.M3P = (vif1Regs.code >> 15) & 0x1;
|
||||
GUNIT_LOG("Vif1 - MskPath3 [p3 = %s]", vif1Regs.mskpath3 ? "masked" : "enabled");
|
||||
if(!vif1Regs.mskpath3) {
|
||||
if (!vif1Regs.mskpath3)
|
||||
{
|
||||
GUNIT_WARN("VIF MSKPATH3 off Path3 triggering!");
|
||||
gifInterrupt();
|
||||
}
|
||||
|
@ -437,8 +510,10 @@ vifOp(vifCode_MskPath3) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
vifOp(vifCode_Nop) {
|
||||
pass1 {
|
||||
vifOp(vifCode_Nop)
|
||||
{
|
||||
pass1
|
||||
{
|
||||
GetVifX.cmd = 0;
|
||||
GetVifX.pass = 0;
|
||||
vifExecQueue(idx);
|
||||
|
@ -457,11 +532,14 @@ vifOp(vifCode_Nop) {
|
|||
}
|
||||
|
||||
// ToDo: Review Flags
|
||||
vifOp(vifCode_Null) {
|
||||
vifOp(vifCode_Null)
|
||||
{
|
||||
vifStruct& vifX = GetVifX;
|
||||
pass1 {
|
||||
pass1
|
||||
{
|
||||
// if ME1, then force the vif to interrupt
|
||||
if (!(vifXRegs.err.ME1)) { // Ignore vifcode and tag mismatch error
|
||||
if (!(vifXRegs.err.ME1))
|
||||
{ // Ignore vifcode and tag mismatch error
|
||||
Console.WriteLn("Vif%d: Unknown VifCmd! [%x]", idx, vifX.cmd);
|
||||
vifXRegs.stat.ER1 = true;
|
||||
vifX.vifstalled.enabled = VifStallEnable(vifXch);
|
||||
|
@ -472,16 +550,19 @@ vifOp(vifCode_Null) {
|
|||
vifX.pass = 0;
|
||||
|
||||
//If the top bit was set to interrupt, we don't want it to take commands from a bad code
|
||||
if (vifXRegs.code & 0x80000000) vifX.irq = 0;
|
||||
if (vifXRegs.code & 0x80000000)
|
||||
vifX.irq = 0;
|
||||
}
|
||||
pass2 { Console.Error("Vif%d bad vifcode! [CMD = %x]", idx, vifX.cmd); }
|
||||
pass3 { VifCodeLog("Null"); }
|
||||
return 1;
|
||||
}
|
||||
|
||||
vifOp(vifCode_Offset) {
|
||||
vifOp(vifCode_Offset)
|
||||
{
|
||||
vif1Only();
|
||||
pass1 {
|
||||
pass1
|
||||
{
|
||||
vif1Regs.stat.DBF = false;
|
||||
vif1Regs.ofst = vif1Regs.code & 0x3ff;
|
||||
vif1Regs.tops = vif1Regs.base;
|
||||
|
@ -492,14 +573,17 @@ vifOp(vifCode_Offset) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
template<int idx> static __fi int _vifCode_STColRow(const u32* data, u32* pmem2) {
|
||||
template <int idx>
|
||||
static __fi int _vifCode_STColRow(const u32* data, u32* pmem2)
|
||||
{
|
||||
vifStruct& vifX = GetVifX;
|
||||
|
||||
int ret = std::min(4 - vifX.tag.addr, vifX.vifpacketsize);
|
||||
pxAssume(vifX.tag.addr < 4);
|
||||
pxAssume(ret > 0);
|
||||
|
||||
switch (ret) {
|
||||
switch (ret)
|
||||
{
|
||||
case 4:
|
||||
pmem2[3] = data[3];
|
||||
[[fallthrough]];
|
||||
|
@ -528,15 +612,18 @@ template<int idx> static __fi int _vifCode_STColRow(const u32* data, u32* pmem2)
|
|||
return ret;
|
||||
}
|
||||
|
||||
vifOp(vifCode_STCol) {
|
||||
vifOp(vifCode_STCol)
|
||||
{
|
||||
vifStruct& vifX = GetVifX;
|
||||
pass1 {
|
||||
pass1
|
||||
{
|
||||
vifX.tag.addr = 0;
|
||||
vifX.tag.size = 4;
|
||||
vifX.pass = 1;
|
||||
return 1;
|
||||
}
|
||||
pass2 {
|
||||
pass2
|
||||
{
|
||||
u32 ret = _vifCode_STColRow<idx>(data, &vifX.MaskCol._u32[vifX.tag.addr]);
|
||||
if (idx && vifX.tag.size == 0)
|
||||
vu1Thread.WriteCol(vifX);
|
||||
|
@ -546,15 +633,18 @@ vifOp(vifCode_STCol) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
vifOp(vifCode_STRow) {
|
||||
vifOp(vifCode_STRow)
|
||||
{
|
||||
vifStruct& vifX = GetVifX;
|
||||
pass1 {
|
||||
pass1
|
||||
{
|
||||
vifX.tag.addr = 0;
|
||||
vifX.tag.size = 4;
|
||||
vifX.pass = 1;
|
||||
return 1;
|
||||
}
|
||||
pass2 {
|
||||
pass2
|
||||
{
|
||||
u32 ret = _vifCode_STColRow<idx>(data, &vifX.MaskRow._u32[vifX.tag.addr]);
|
||||
if (idx && vifX.tag.size == 0)
|
||||
vu1Thread.WriteRow(vifX);
|
||||
|
@ -564,9 +654,11 @@ vifOp(vifCode_STRow) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
vifOp(vifCode_STCycl) {
|
||||
vifOp(vifCode_STCycl)
|
||||
{
|
||||
vifStruct& vifX = GetVifX;
|
||||
pass1 {
|
||||
pass1
|
||||
{
|
||||
vifXRegs.cycle.cl = (u8)(vifXRegs.code);
|
||||
vifXRegs.cycle.wl = (u8)(vifXRegs.code >> 8);
|
||||
vifX.cmd = 0;
|
||||
|
@ -576,16 +668,34 @@ vifOp(vifCode_STCycl) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
vifOp(vifCode_STMask) {
|
||||
vifOp(vifCode_STMask)
|
||||
{
|
||||
vifStruct& vifX = GetVifX;
|
||||
pass1 { vifX.tag.size = 1; vifX.pass = 1; return 1; }
|
||||
pass2 { vifXRegs.mask = data[0]; vifX.tag.size = 0; vifX.cmd = 0; vifX.pass = 0;}
|
||||
pass1
|
||||
{
|
||||
vifX.tag.size = 1;
|
||||
vifX.pass = 1;
|
||||
return 1;
|
||||
}
|
||||
pass2
|
||||
{
|
||||
vifXRegs.mask = data[0];
|
||||
vifX.tag.size = 0;
|
||||
vifX.cmd = 0;
|
||||
vifX.pass = 0;
|
||||
}
|
||||
pass3 { VifCodeLog("STMask"); }
|
||||
return 1;
|
||||
}
|
||||
|
||||
vifOp(vifCode_STMod) {
|
||||
pass1 { vifXRegs.mode = vifXRegs.code & 0x3; GetVifX.cmd = 0; GetVifX.pass = 0;}
|
||||
vifOp(vifCode_STMod)
|
||||
{
|
||||
pass1
|
||||
{
|
||||
vifXRegs.mode = vifXRegs.code & 0x3;
|
||||
GetVifX.cmd = 0;
|
||||
GetVifX.pass = 0;
|
||||
}
|
||||
pass3 { VifCodeLog("STMod"); }
|
||||
return 1;
|
||||
}
|
||||
|
@ -596,20 +706,25 @@ static uint calc_addr(bool flg)
|
|||
VIFregisters& vifRegs = vifXRegs;
|
||||
|
||||
uint retval = vifRegs.code;
|
||||
if (idx && flg) retval += vifRegs.tops;
|
||||
if (idx && flg)
|
||||
retval += vifRegs.tops;
|
||||
return retval & (idx ? 0x3ff : 0xff);
|
||||
}
|
||||
|
||||
vifOp(vifCode_Unpack) {
|
||||
pass1 {
|
||||
vifOp(vifCode_Unpack)
|
||||
{
|
||||
pass1
|
||||
{
|
||||
vifUnpackSetup<idx>(data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
pass2 {
|
||||
pass2
|
||||
{
|
||||
return nVifUnpack<idx>((u8*)data);
|
||||
}
|
||||
pass3 {
|
||||
pass3
|
||||
{
|
||||
vifStruct& vifX = GetVifX;
|
||||
VIFregisters& vifRegs = vifXRegs;
|
||||
uint vl = vifX.cmd & 0x03;
|
||||
|
@ -621,8 +736,7 @@ vifOp(vifCode_Unpack) {
|
|||
VifCodeLog("Unpack %s_%u (%s) @ 0x%04X%s (cl=%u wl=%u num=0x%02X)",
|
||||
vntbl[vn], vltbl[vl], (vifX.cmd & 0x10) ? "masked" : "unmasked",
|
||||
calc_addr<idx>(flg), flg ? "(FLG)" : "",
|
||||
vifRegs.cycle.cl, vifRegs.cycle.wl, (vifXRegs.code >> 16) & 0xff
|
||||
);
|
||||
vifRegs.cycle.cl, vifRegs.cycle.wl, (vifXRegs.code >> 16) & 0xff);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue