A bunch of IPU.cpp now uses Tags.h. Ironed out a few things in Tags.h.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1625 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
arcum42 2009-08-15 09:51:23 +00:00
parent fb3f07b2d6
commit b6cce7c560
2 changed files with 87 additions and 66 deletions

View File

@ -37,7 +37,7 @@ using namespace std; // for min / max
//#define IPU_INT0_FROM() CPU_INT( DMAC_FROM_IPU, 0 ) //#define IPU_INT0_FROM() CPU_INT( DMAC_FROM_IPU, 0 )
// IPU Inline'd IRQs : Calls the IPU interrupt handlers directly instead of // IPU Inline'd IRQs : Calls the IPU interrupt handlers directly instead of
// feeding them through the EE's branch test. (see IPU.H for details) // feeding them through the EE's branch test. (see IPU.h for details)
#ifdef IPU_INLINE_IRQS #ifdef IPU_INLINE_IRQS
# define IPU_INT_TO( cycles ) ipu1Interrupt() # define IPU_INT_TO( cycles ) ipu1Interrupt()
@ -811,7 +811,7 @@ void IPUCMD_WRITE(u32 val)
case SCE_IPU_FDEC: case SCE_IPU_FDEC:
IPU_LOG("IPU FDEC command. Skip 0x%X bits, FIFO 0x%X qwords, BP 0x%X, FP %d, CHCR 0x%x, %x", IPU_LOG("IPU FDEC command. Skip 0x%X bits, FIFO 0x%X qwords, BP 0x%X, FP %d, CHCR 0x%x, %x",
val & 0x3f, g_BP.IFC, (int)g_BP.BP, g_BP.FP, ((DMACh*)&PS2MEM_HW[0xb400])->chcr, cpuRegs.pc); val & 0x3f, g_BP.IFC, (int)g_BP.BP, g_BP.FP, ipu1dma->chcr, cpuRegs.pc);
g_BP.BP += val & 0x3F; g_BP.BP += val & 0x3F;
if (ipuFDEC(val)) return; if (ipuFDEC(val)) return;
ipuRegs->cmd.BUSY = 0x80000000; ipuRegs->cmd.BUSY = 0x80000000;
@ -840,7 +840,7 @@ void IPUCMD_WRITE(u32 val)
if (ipuCSC(ipuRegs->cmd.DATA)) if (ipuCSC(ipuRegs->cmd.DATA))
{ {
if (ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) IPU_INT0_FROM(); if (ipu0dma->qwc > 0 && (CHCR::STR(ipu0dma))) IPU_INT0_FROM();
return; return;
} }
break; break;
@ -855,7 +855,7 @@ void IPUCMD_WRITE(u32 val)
if (ipuIDEC(val)) if (ipuIDEC(val))
{ {
// idec done, ipu0 done too // idec done, ipu0 done too
if (ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) IPU_INT0_FROM(); if (ipu0dma->qwc > 0 && (CHCR::STR(ipu0dma))) IPU_INT0_FROM();
return; return;
} }
ipuRegs->topbusy = 0x80000000; ipuRegs->topbusy = 0x80000000;
@ -867,7 +867,7 @@ void IPUCMD_WRITE(u32 val)
case SCE_IPU_BDEC: case SCE_IPU_BDEC:
if (ipuBDEC(val)) if (ipuBDEC(val))
{ {
if (ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) IPU_INT0_FROM(); if (ipu0dma->qwc > 0 && (CHCR::STR(ipu0dma))) IPU_INT0_FROM();
if (ipuRegs->ctrl.SCD || ipuRegs->ctrl.ECD) hwIntcIrq(INTC_IPU); if (ipuRegs->ctrl.SCD || ipuRegs->ctrl.ECD) hwIntcIrq(INTC_IPU);
return; return;
} }
@ -931,7 +931,7 @@ void IPUWorker()
hwIntcIrq(INTC_IPU); hwIntcIrq(INTC_IPU);
return; return;
} }
if ((ipu0dma->qwc > 0) && (ipu0dma->chcr & 0x100)) IPU_INT0_FROM(); if ((ipu0dma->qwc > 0) && (CHCR::STR(ipu0dma))) IPU_INT0_FROM();
break; break;
case SCE_IPU_PACK: case SCE_IPU_PACK:
@ -957,7 +957,7 @@ void IPUWorker()
ipuCurCmd = 0xffffffff; ipuCurCmd = 0xffffffff;
// CHECK!: IPU0dma remains when IDEC is done, so we need to clear it // CHECK!: IPU0dma remains when IDEC is done, so we need to clear it
if ((ipu0dma->qwc > 0) && (ipu0dma->chcr & 0x100)) IPU_INT0_FROM(); if ((ipu0dma->qwc > 0) && (CHCR::STR(ipu0dma))) IPU_INT0_FROM();
s_routine = NULL; s_routine = NULL;
break; break;
@ -974,7 +974,7 @@ void IPUWorker()
ipuRegs->cmd.BUSY = 0; ipuRegs->cmd.BUSY = 0;
ipuCurCmd = 0xffffffff; ipuCurCmd = 0xffffffff;
if ((ipu0dma->qwc > 0) && (ipu0dma->chcr & 0x100)) IPU_INT0_FROM(); if ((ipu0dma->qwc > 0) && (CHCR::STR(ipu0dma))) IPU_INT0_FROM();
s_routine = NULL; s_routine = NULL;
if (ipuRegs->ctrl.SCD || ipuRegs->ctrl.ECD) hwIntcIrq(INTC_IPU); if (ipuRegs->ctrl.SCD || ipuRegs->ctrl.ECD) hwIntcIrq(INTC_IPU);
return; return;
@ -1328,6 +1328,7 @@ int FIFOto_read(void *value)
// wait until enough data // wait until enough data
if (g_BP.IFC == 0) if (g_BP.IFC == 0)
{ {
// This is the only spot that wants a return value for IPU1dma.
if (IPU1dma() == 0) return 0; if (IPU1dma() == 0) return 0;
assert(g_BP.IFC > 0); assert(g_BP.IFC > 0);
} }
@ -1365,11 +1366,12 @@ int FIFOto_write(u32* pMem, int size)
return firsttrans; return firsttrans;
} }
static __forceinline bool IPU1chain(u32* &pMem, int &totalqwc) static __forceinline bool IPU1chain(int &totalqwc)
{ {
if (ipu1dma->qwc > 0) if (ipu1dma->qwc > 0)
{ {
int qwc = ipu1dma->qwc; int qwc = ipu1dma->qwc;
u32 *pMem;
pMem = (u32*)dmaGetAddr(ipu1dma->madr); pMem = (u32*)dmaGetAddr(ipu1dma->madr);
@ -1455,33 +1457,37 @@ static __forceinline bool ipuDmacSrcChain(DMACh *tag, u32 *ptag)
return false; return false;
} }
int IPU1dma() static __forceinline void flushGIF()
{ {
u32 *ptag, *pMem; while(CHCR::STR(gif) && (vif1Regs->mskpath3 == 0))
bool done = FALSE;
int ipu1cycles = 0;
int totalqwc = 0;
assert(!(ipu1dma->chcr & 0x40));
if (!(ipu1dma->chcr & 0x100) || (cpuRegs.interrupt & (1 << DMAC_TO_IPU))) return 0;
assert(!(g_nDMATransfer & IPU_DMA_TIE1));
//We need to make sure GIF has flushed before sending IPU data, it seems to REALLY screw FFX videos
while(gif->chcr & 0x100 && vif1Regs->mskpath3 == 0)
{ {
GIF_LOG("Flushing gif chcr %x tadr %x madr %x qwc %x", gif->chcr, gif->tadr, gif->madr, gif->qwc); GIF_LOG("Flushing gif chcr %x tadr %x madr %x qwc %x", gif->chcr, gif->tadr, gif->madr, gif->qwc);
gsInterrupt(); gsInterrupt();
} }
}
int IPU1dma()
{
u32 *ptag;
bool done = false;
int ipu1cycles = 0, totalqwc = 0;
assert(!(CHCR::TTE(ipu1dma)));
if (!(CHCR::STR(ipu1dma)) || (cpuRegs.interrupt & (1 << DMAC_TO_IPU))) return 0;
assert(!(g_nDMATransfer & IPU_DMA_TIE1));
//We need to make sure GIF has flushed before sending IPU data, it seems to REALLY screw FFX videos
flushGIF();
// in kh, qwc == 0 when dma_actv1 is set // in kh, qwc == 0 when dma_actv1 is set
if ((g_nDMATransfer & IPU_DMA_ACTV1) && ipu1dma->qwc > 0) if ((g_nDMATransfer & IPU_DMA_ACTV1) && ipu1dma->qwc > 0)
{ {
if (IPU1chain(pMem, totalqwc)) return totalqwc; if (IPU1chain(totalqwc)) return totalqwc;
//Check TIE bit of CHCR and IRQ bit of tag //Check TIE bit of CHCR and IRQ bit of tag
if ((ipu1dma->chcr & 0x80) && (g_nDMATransfer & IPU_DMA_DOTIE1)) if (CHCR::TIE(ipu1dma) && (g_nDMATransfer & IPU_DMA_DOTIE1))
{ {
Console::WriteLn("IPU1 TIE"); Console::WriteLn("IPU1 TIE");
@ -1491,22 +1497,24 @@ int IPU1dma()
return totalqwc; return totalqwc;
} }
if (!(ipu1dma->chcr & 0xc)) if (CHCR::MOD(ipu1dma) == NORMAL_MODE) // If mode is normal mode.
{ {
IPU_INT_TO(totalqwc * BIAS); IPU_INT_TO(totalqwc * BIAS);
return totalqwc; return totalqwc;
} }
else else
{ {
// Chain mode.
u32 tag = ipu1dma->chcr; // upper bits describe current tag u32 tag = ipu1dma->chcr; // upper bits describe current tag
if ((ipu1dma->chcr & 0x80) && (tag & 0x80000000)) if (CHCR::TIE(ipu1dma) && ChainTags::IRQ(tag))
{ {
ptag = (u32*)dmaGetAddr(ipu1dma->tadr); ptag = (u32*)dmaGetAddr(ipu1dma->tadr);
IncreaseTadr(tag); IncreaseTadr(tag);
ipu1dma->chcr = (ipu1dma->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); UpperTagTransfer(ipu1dma, ptag);
IPU_LOG("IPU dmaIrq Set"); IPU_LOG("IPU dmaIrq Set");
IPU_INT_TO(totalqwc * BIAS); IPU_INT_TO(totalqwc * BIAS);
g_nDMATransfer |= IPU_DMA_TIE1; g_nDMATransfer |= IPU_DMA_TIE1;
@ -1523,7 +1531,8 @@ int IPU1dma()
g_nDMATransfer &= ~(IPU_DMA_ACTV1 | IPU_DMA_DOTIE1); g_nDMATransfer &= ~(IPU_DMA_ACTV1 | IPU_DMA_DOTIE1);
} }
if (((ipu1dma->chcr & 0xc) == 0) && (ipu1dma->qwc == 0)) // Normal Mode // Normal Mode & qwc is finished
if ((CHCR::MOD(ipu1dma) == NORMAL_MODE) && (ipu1dma->qwc == 0))
{ {
//Console::WriteLn("ipu1 normal empty qwc?"); //Console::WriteLn("ipu1 normal empty qwc?");
return totalqwc; return totalqwc;
@ -1535,7 +1544,7 @@ int IPU1dma()
IPU_LOG("dmaIPU1 Normal size=%d, addr=%lx, fifosize=%x", IPU_LOG("dmaIPU1 Normal size=%d, addr=%lx, fifosize=%x",
ipu1dma->qwc, ipu1dma->madr, 8 - g_BP.IFC); ipu1dma->qwc, ipu1dma->madr, 8 - g_BP.IFC);
if (!IPU1chain(pMem, totalqwc)) IPU_INT_TO((ipu1cycles + totalqwc) * BIAS); if (!IPU1chain(totalqwc)) IPU_INT_TO((ipu1cycles + totalqwc) * BIAS);
return totalqwc; return totalqwc;
} }
@ -1543,25 +1552,19 @@ int IPU1dma()
{ {
// Chain Mode & ipu1dma->qwc is 0 // Chain Mode & ipu1dma->qwc is 0
ptag = (u32*)dmaGetAddr(ipu1dma->tadr); //Set memory pointer to TADR ptag = (u32*)dmaGetAddr(ipu1dma->tadr); //Set memory pointer to TADR
if (ptag == NULL) //Is ptag empty?
{ // Transfer the tag.
Console::Error("IPU1 BUSERR"); if (!(TransferTag("IPU1", ipu1dma, ptag))) return totalqwc;
ipu1dma->chcr = (ipu1dma->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); //Transfer upper part of tag to CHCR bits 31-15
psHu32(DMAC_STAT) |= DMAC_STAT_BEIS; //If yes, set BEIS (BUSERR) in DMAC_STAT register
return totalqwc;
}
ipu1cycles += 1; // Add 1 cycles from the QW read for the tag ipu1cycles += 1; // Add 1 cycles from the QW read for the tag
ipu1dma->chcr = (ipu1dma->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); //Transfer upper part of tag to CHCR bits 31-15
ipu1dma->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag
done = ipuDmacSrcChain(ipu1dma, ptag); done = ipuDmacSrcChain(ipu1dma, ptag);
IPU_LOG("dmaIPU1 dmaChain %8.8x_%8.8x size=%d, addr=%lx, fifosize=%x", IPU_LOG("dmaIPU1 dmaChain %8.8x_%8.8x size=%d, addr=%lx, fifosize=%x",
ptag[1], ptag[0], ipu1dma->qwc, ipu1dma->madr, 8 - g_BP.IFC); ptag[1], ptag[0], ipu1dma->qwc, ipu1dma->madr, 8 - g_BP.IFC);
if ((ipu1dma->chcr & 0x80) && ptag[0] & 0x80000000)
if (CHCR::TIE(ipu1dma) && ChainTags::IRQ(ptag))
g_nDMATransfer |= IPU_DMA_DOTIE1; g_nDMATransfer |= IPU_DMA_DOTIE1;
else else
g_nDMATransfer &= ~IPU_DMA_DOTIE1; g_nDMATransfer &= ~IPU_DMA_DOTIE1;
@ -1573,7 +1576,7 @@ int IPU1dma()
{ {
Console::WriteLn("IPU1 TIE"); Console::WriteLn("IPU1 TIE");
if (IPU1chain(pMem, totalqwc)) return totalqwc; if (IPU1chain(totalqwc)) return totalqwc;
if (done) if (done)
{ {
@ -1581,7 +1584,8 @@ int IPU1dma()
IncreaseTadr(ptag[0]); IncreaseTadr(ptag[0]);
ipu1dma->chcr = (ipu1dma->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); // Transfer the last of ptag into chcr.
UpperTagTransfer(ipu1dma, ptag);
} }
IPU_INT_TO(ipu1cycles + totalqwc * BIAS); // Should it be (ipu1cycles + totalqwc) * BIAS? IPU_INT_TO(ipu1cycles + totalqwc * BIAS); // Should it be (ipu1cycles + totalqwc) * BIAS?
@ -1592,14 +1596,14 @@ int IPU1dma()
{ {
//Britney Dance beat does a blank NEXT tag, for some odd reason the fix doesnt work if after IPU1Chain O_o //Britney Dance beat does a blank NEXT tag, for some odd reason the fix doesnt work if after IPU1Chain O_o
if (!done) IPU1dma(); if (!done) IPU1dma();
if (IPU1chain(pMem, totalqwc)) return totalqwc; if (IPU1chain(totalqwc)) return totalqwc;
} }
IncreaseTadr(ptag[0]); IncreaseTadr(ptag[0]);
} }
else else
{ {
if (IPU1chain(pMem, totalqwc)) return totalqwc; if (IPU1chain(totalqwc)) return totalqwc;
} }
} }
@ -1677,10 +1681,10 @@ int IPU0dma()
int readsize; int readsize;
void* pMem; void* pMem;
if ((!(ipu0dma->chcr & 0x100) || (cpuRegs.interrupt & (1 << DMAC_FROM_IPU))) || (ipu0dma->qwc == 0)) if ((!(CHCR::STR(ipu0dma)) || (cpuRegs.interrupt & (1 << DMAC_FROM_IPU))) || (ipu0dma->qwc == 0))
return 0; return 0;
assert(!(ipu0dma->chcr&0x40)); assert(!(CHCR::TTE(ipu0dma)));
IPU_LOG("dmaIPU0 chcr = %lx, madr = %lx, qwc = %lx", IPU_LOG("dmaIPU0 chcr = %lx, madr = %lx, qwc = %lx",
ipu0dma->chcr, ipu0dma->madr, ipu0dma->qwc); ipu0dma->chcr, ipu0dma->madr, ipu0dma->qwc);
@ -1739,22 +1743,22 @@ void ipu0Interrupt()
{ {
// gif // gif
g_nDMATransfer &= ~IPU_DMA_GIFSTALL; g_nDMATransfer &= ~IPU_DMA_GIFSTALL;
if (((DMACh*)&PS2MEM_HW[0xA000])->chcr & 0x100) GIFdma(); if (CHCR::STR(gif)) GIFdma();
} }
if (g_nDMATransfer & IPU_DMA_VIFSTALL) if (g_nDMATransfer & IPU_DMA_VIFSTALL)
{ {
// vif // vif
g_nDMATransfer &= ~IPU_DMA_VIFSTALL; g_nDMATransfer &= ~IPU_DMA_VIFSTALL;
if (((DMACh*)&PS2MEM_HW[0x9000])->chcr & 0x100)dmaVIF1(); if (CHCR::STR(vif1ch)) dmaVIF1();
} }
if (g_nDMATransfer & IPU_DMA_TIE0) if (g_nDMATransfer & IPU_DMA_TIE0)
{ {
g_nDMATransfer &= ~IPU_DMA_TIE0; g_nDMATransfer &= ~IPU_DMA_TIE0;
} }
ipu0dma->chcr &= ~0x100; CHCR::setSTR(ipu0dma);
hwDmacIrq(DMAC_FROM_IPU); hwDmacIrq(DMAC_FROM_IPU);
} }
@ -1772,7 +1776,7 @@ IPU_FORCEINLINE void ipu1Interrupt()
if (g_nDMATransfer & IPU_DMA_TIE1) if (g_nDMATransfer & IPU_DMA_TIE1)
g_nDMATransfer &= ~IPU_DMA_TIE1; g_nDMATransfer &= ~IPU_DMA_TIE1;
else else
ipu1dma->chcr &= ~0x100; CHCR::setSTR(ipu1dma);
hwDmacIrq(DMAC_TO_IPU); hwDmacIrq(DMAC_TO_IPU);
} }

View File

@ -28,21 +28,37 @@ enum TransferMode
UNDEFINED_MODE UNDEFINED_MODE
}; };
template <class T>
static __forceinline void UpperTagTransfer(T tag, u32* ptag)
{
// Transfer upper part of tag to CHCR bits 31-15
tag->chcr = (tag->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000);
}
template <class T>
static __forceinline void LowerTagTransfer(T tag, u32* ptag)
{
//QWC set to lower 16bits of the tag
tag->qwc = (u16)ptag[0];
}
// Transfer a tag. // Transfer a tag.
template <class T> template <class T>
static __forceinline bool TransferTag(const char *s, T tag, u32* &ptag) static __forceinline bool TransferTag(const char *s, T tag, u32* ptag)
{ {
if (ptag == NULL) // Is ptag empty? if (ptag == NULL) // Is ptag empty?
{ {
Console::Error("%s BUSERR", params s); Console::Error("%s BUSERR", params s);
tag->chcr = (tag->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); // Transfer upper part of tag to CHCR bits 31-15 UpperTagTransfer(tag, ptag);
psHu32(DMAC_STAT) |= DMAC_STAT_BEIS; // Set BEIS (BUSERR) in DMAC_STAT register
// Set BEIS (BUSERR) in DMAC_STAT register
psHu32(DMAC_STAT) |= DMAC_STAT_BEIS;
return false; return false;
} }
else else
{ {
tag->chcr = (tag->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); //Transfer upper part of tag to CHCR bits 31-15 UpperTagTransfer(tag, ptag);
tag->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag LowerTagTransfer(tag, ptag);
return true; return true;
} }
} }
@ -90,6 +106,11 @@ namespace ChainTags
{ {
return (tag[0] & 0x8000000); return (tag[0] & 0x8000000);
} }
static __forceinline bool IRQ(u32 tag)
{
return (tag & 0x8000000);
}
} }
enum chcr_flags enum chcr_flags
@ -97,8 +118,10 @@ enum chcr_flags
CHCR_DIR = 0x0, CHCR_DIR = 0x0,
CHCR_MOD1 = 0x4, CHCR_MOD1 = 0x4,
CHCR_MOD2 = 0x8, CHCR_MOD2 = 0x8,
CHCR_MOD = 0xC, // MOD1 & MOD2
CHCR_ASP1 = 0x10, CHCR_ASP1 = 0x10,
CHCR_ASP2 = 0x20, CHCR_ASP2 = 0x20,
CHCR_ASP = 0x30, // ASP1 & ASP2
CHCR_TTE = 0x40, CHCR_TTE = 0x40,
CHCR_TIE = 0x80, CHCR_TIE = 0x80,
CHCR_STR = 0x100 CHCR_STR = 0x100
@ -122,19 +145,13 @@ namespace CHCR
template <class T> template <class T>
static __forceinline TransferMode MOD(T tag) static __forceinline TransferMode MOD(T tag)
{ {
u8 temp = 0; return (TransferMode)((tag->chcr & CHCR_MOD) >> 2);
if (tag->chcr & CHCR_MOD1) temp |= (1 << 0);
if (tag->chcr & CHCR_MOD2) temp |= (1 << 1);
return (TransferMode)temp;
} }
template <class T> template <class T>
static __forceinline u8 ASP(T tag) static __forceinline u8 ASP(T tag)
{ {
u8 temp = 0; return (TransferMode)((tag->chcr & CHCR_ASP) >> 2);
if (tag->chcr & CHCR_ASP1) temp |= (1 << 0);
if (tag->chcr & CHCR_ASP2) temp |= (1 << 1);
return temp;
} }
// Set the individual flags. Untested. // Set the individual flags. Untested.