From b6cce7c560d393980fbbfc03cc380e8456a2c9b4 Mon Sep 17 00:00:00 2001 From: arcum42 Date: Sat, 15 Aug 2009 09:51:23 +0000 Subject: [PATCH] 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 --- pcsx2/IPU/IPU.cpp | 110 ++++++++++++++++++++++++---------------------- pcsx2/Tags.h | 43 ++++++++++++------ 2 files changed, 87 insertions(+), 66 deletions(-) diff --git a/pcsx2/IPU/IPU.cpp b/pcsx2/IPU/IPU.cpp index 91d57e28ef..7e3f07c27b 100644 --- a/pcsx2/IPU/IPU.cpp +++ b/pcsx2/IPU/IPU.cpp @@ -37,7 +37,7 @@ using namespace std; // for min / max //#define IPU_INT0_FROM() CPU_INT( DMAC_FROM_IPU, 0 ) // 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 # define IPU_INT_TO( cycles ) ipu1Interrupt() @@ -811,7 +811,7 @@ void IPUCMD_WRITE(u32 val) 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", - 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; if (ipuFDEC(val)) return; ipuRegs->cmd.BUSY = 0x80000000; @@ -840,7 +840,7 @@ void IPUCMD_WRITE(u32 val) 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; } break; @@ -855,7 +855,7 @@ void IPUCMD_WRITE(u32 val) if (ipuIDEC(val)) { // 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; } ipuRegs->topbusy = 0x80000000; @@ -867,7 +867,7 @@ void IPUCMD_WRITE(u32 val) case SCE_IPU_BDEC: 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); return; } @@ -931,7 +931,7 @@ void IPUWorker() hwIntcIrq(INTC_IPU); return; } - if ((ipu0dma->qwc > 0) && (ipu0dma->chcr & 0x100)) IPU_INT0_FROM(); + if ((ipu0dma->qwc > 0) && (CHCR::STR(ipu0dma))) IPU_INT0_FROM(); break; case SCE_IPU_PACK: @@ -957,7 +957,7 @@ void IPUWorker() ipuCurCmd = 0xffffffff; // 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; break; @@ -974,7 +974,7 @@ void IPUWorker() ipuRegs->cmd.BUSY = 0; 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; if (ipuRegs->ctrl.SCD || ipuRegs->ctrl.ECD) hwIntcIrq(INTC_IPU); return; @@ -1328,6 +1328,7 @@ int FIFOto_read(void *value) // wait until enough data if (g_BP.IFC == 0) { + // This is the only spot that wants a return value for IPU1dma. if (IPU1dma() == 0) return 0; assert(g_BP.IFC > 0); } @@ -1365,11 +1366,12 @@ int FIFOto_write(u32* pMem, int size) return firsttrans; } -static __forceinline bool IPU1chain(u32* &pMem, int &totalqwc) +static __forceinline bool IPU1chain(int &totalqwc) { if (ipu1dma->qwc > 0) { int qwc = ipu1dma->qwc; + u32 *pMem; pMem = (u32*)dmaGetAddr(ipu1dma->madr); @@ -1455,33 +1457,37 @@ static __forceinline bool ipuDmacSrcChain(DMACh *tag, u32 *ptag) return false; } -int IPU1dma() +static __forceinline void flushGIF() { - u32 *ptag, *pMem; - 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) + while(CHCR::STR(gif) && (vif1Regs->mskpath3 == 0)) { GIF_LOG("Flushing gif chcr %x tadr %x madr %x qwc %x", gif->chcr, gif->tadr, gif->madr, gif->qwc); 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 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 - if ((ipu1dma->chcr & 0x80) && (g_nDMATransfer & IPU_DMA_DOTIE1)) + if (CHCR::TIE(ipu1dma) && (g_nDMATransfer & IPU_DMA_DOTIE1)) { Console::WriteLn("IPU1 TIE"); @@ -1491,22 +1497,24 @@ int IPU1dma() return totalqwc; } - if (!(ipu1dma->chcr & 0xc)) + if (CHCR::MOD(ipu1dma) == NORMAL_MODE) // If mode is normal mode. { IPU_INT_TO(totalqwc * BIAS); return totalqwc; } else { + // Chain mode. 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); IncreaseTadr(tag); - ipu1dma->chcr = (ipu1dma->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); + UpperTagTransfer(ipu1dma, ptag); + IPU_LOG("IPU dmaIrq Set"); IPU_INT_TO(totalqwc * BIAS); g_nDMATransfer |= IPU_DMA_TIE1; @@ -1523,7 +1531,8 @@ int IPU1dma() 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?"); return totalqwc; @@ -1535,7 +1544,7 @@ int IPU1dma() IPU_LOG("dmaIPU1 Normal size=%d, addr=%lx, fifosize=%x", 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; } @@ -1543,25 +1552,19 @@ int IPU1dma() { // Chain Mode & ipu1dma->qwc is 0 ptag = (u32*)dmaGetAddr(ipu1dma->tadr); //Set memory pointer to TADR - if (ptag == NULL) //Is ptag empty? - { - Console::Error("IPU1 BUSERR"); - 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; - } - + + // Transfer the tag. + if (!(TransferTag("IPU1", ipu1dma, ptag))) return totalqwc; + 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); 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); - if ((ipu1dma->chcr & 0x80) && ptag[0] & 0x80000000) + + if (CHCR::TIE(ipu1dma) && ChainTags::IRQ(ptag)) g_nDMATransfer |= IPU_DMA_DOTIE1; else g_nDMATransfer &= ~IPU_DMA_DOTIE1; @@ -1573,7 +1576,7 @@ int IPU1dma() { Console::WriteLn("IPU1 TIE"); - if (IPU1chain(pMem, totalqwc)) return totalqwc; + if (IPU1chain(totalqwc)) return totalqwc; if (done) { @@ -1581,7 +1584,8 @@ int IPU1dma() 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? @@ -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 if (!done) IPU1dma(); - if (IPU1chain(pMem, totalqwc)) return totalqwc; + if (IPU1chain(totalqwc)) return totalqwc; } IncreaseTadr(ptag[0]); } else { - if (IPU1chain(pMem, totalqwc)) return totalqwc; + if (IPU1chain(totalqwc)) return totalqwc; } } @@ -1677,10 +1681,10 @@ int IPU0dma() int readsize; 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; - assert(!(ipu0dma->chcr&0x40)); + assert(!(CHCR::TTE(ipu0dma))); IPU_LOG("dmaIPU0 chcr = %lx, madr = %lx, qwc = %lx", ipu0dma->chcr, ipu0dma->madr, ipu0dma->qwc); @@ -1739,22 +1743,22 @@ void ipu0Interrupt() { // gif g_nDMATransfer &= ~IPU_DMA_GIFSTALL; - if (((DMACh*)&PS2MEM_HW[0xA000])->chcr & 0x100) GIFdma(); + if (CHCR::STR(gif)) GIFdma(); } if (g_nDMATransfer & IPU_DMA_VIFSTALL) { // vif g_nDMATransfer &= ~IPU_DMA_VIFSTALL; - if (((DMACh*)&PS2MEM_HW[0x9000])->chcr & 0x100)dmaVIF1(); + if (CHCR::STR(vif1ch)) dmaVIF1(); } if (g_nDMATransfer & IPU_DMA_TIE0) { g_nDMATransfer &= ~IPU_DMA_TIE0; } - - ipu0dma->chcr &= ~0x100; + + CHCR::setSTR(ipu0dma); hwDmacIrq(DMAC_FROM_IPU); } @@ -1772,7 +1776,7 @@ IPU_FORCEINLINE void ipu1Interrupt() if (g_nDMATransfer & IPU_DMA_TIE1) g_nDMATransfer &= ~IPU_DMA_TIE1; else - ipu1dma->chcr &= ~0x100; + CHCR::setSTR(ipu1dma); hwDmacIrq(DMAC_TO_IPU); } diff --git a/pcsx2/Tags.h b/pcsx2/Tags.h index 1cbb86f359..1b27479966 100644 --- a/pcsx2/Tags.h +++ b/pcsx2/Tags.h @@ -28,21 +28,37 @@ enum TransferMode UNDEFINED_MODE }; +template +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 +static __forceinline void LowerTagTransfer(T tag, u32* ptag) +{ + //QWC set to lower 16bits of the tag + tag->qwc = (u16)ptag[0]; +} + // Transfer a tag. template -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? { Console::Error("%s BUSERR", params s); - tag->chcr = (tag->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); // Transfer upper part of tag to CHCR bits 31-15 - psHu32(DMAC_STAT) |= DMAC_STAT_BEIS; // Set BEIS (BUSERR) in DMAC_STAT register + UpperTagTransfer(tag, ptag); + + // Set BEIS (BUSERR) in DMAC_STAT register + psHu32(DMAC_STAT) |= DMAC_STAT_BEIS; return false; } else { - tag->chcr = (tag->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); //Transfer upper part of tag to CHCR bits 31-15 - tag->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + UpperTagTransfer(tag, ptag); + LowerTagTransfer(tag, ptag); return true; } } @@ -90,6 +106,11 @@ namespace ChainTags { return (tag[0] & 0x8000000); } + + static __forceinline bool IRQ(u32 tag) + { + return (tag & 0x8000000); + } } enum chcr_flags @@ -97,8 +118,10 @@ enum chcr_flags CHCR_DIR = 0x0, CHCR_MOD1 = 0x4, CHCR_MOD2 = 0x8, + CHCR_MOD = 0xC, // MOD1 & MOD2 CHCR_ASP1 = 0x10, CHCR_ASP2 = 0x20, + CHCR_ASP = 0x30, // ASP1 & ASP2 CHCR_TTE = 0x40, CHCR_TIE = 0x80, CHCR_STR = 0x100 @@ -122,19 +145,13 @@ namespace CHCR template static __forceinline TransferMode MOD(T tag) { - u8 temp = 0; - if (tag->chcr & CHCR_MOD1) temp |= (1 << 0); - if (tag->chcr & CHCR_MOD2) temp |= (1 << 1); - return (TransferMode)temp; + return (TransferMode)((tag->chcr & CHCR_MOD) >> 2); } template static __forceinline u8 ASP(T tag) { - u8 temp = 0; - if (tag->chcr & CHCR_ASP1) temp |= (1 << 0); - if (tag->chcr & CHCR_ASP2) temp |= (1 << 1); - return temp; + return (TransferMode)((tag->chcr & CHCR_ASP) >> 2); } // Set the individual flags. Untested.