From 490d996abc75a02050643036d30a6d9aa6019622 Mon Sep 17 00:00:00 2001 From: arcum42 Date: Wed, 19 Aug 2009 12:08:50 +0000 Subject: [PATCH] Tags.h meets SPR.cpp. Plus some more work on Tags.h and Misc... git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1653 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Hw.cpp | 43 +++++--- pcsx2/SPR.cpp | 258 ++++++++++++++++++++++++----------------------- pcsx2/Tags.h | 62 +++++++++++- pcsx2/VifDma.cpp | 8 +- 4 files changed, 226 insertions(+), 145 deletions(-) diff --git a/pcsx2/Hw.cpp b/pcsx2/Hw.cpp index fc3e1ccdd1..4ef9d27c8e 100644 --- a/pcsx2/Hw.cpp +++ b/pcsx2/Hw.cpp @@ -177,37 +177,52 @@ bool hwDmacSrcChainWithStack(DMACh *dma, int id) { dma->madr = dma->tadr + 16; //Set MADR to data following the tag - if ((dma->chcr & 0x30) == 0x0) { //Check if ASR0 is empty + switch(CHCR::ASP(dma)) + { + case 0: { //Check if ASR0 is empty dma->asr0 = dma->madr + (dma->qwc << 4); //If yes store Succeeding tag dma->chcr = (dma->chcr & 0xffffffcf) | 0x10; //1 Address in call stack + break; } - else if((dma->chcr & 0x30) == 0x10){ + case 1: { dma->chcr = (dma->chcr & 0xffffffcf) | 0x20; //2 Addresses in call stack dma->asr1 = dma->madr + (dma->qwc << 4); //If no store Succeeding tag in ASR1 - }else { + break; + } + default: { Console::Notice("Call Stack Overflow (report if it fixes/breaks anything)"); return true; //Return done } + } dma->tadr = temp; //Set TADR to temporarily stored ADDR return false; } case TAG_RET: // Ret - Transfer QWC following the tag, load next tag dma->madr = dma->tadr + 16; //Set MADR to data following the tag - - if ((dma->chcr & 0x30) == 0x20) { //If ASR1 is NOT equal to 0 (Contains address) + switch(CHCR::ASP(dma)) + { + case 2: { //If ASR1 is NOT equal to 0 (Contains address) dma->chcr = (dma->chcr & 0xffffffcf) | 0x10; //1 Address left in call stack dma->tadr = dma->asr1; //Read ASR1 as next tag dma->asr1 = 0; //Clear ASR1 - } - else { //If ASR1 is empty (No address held) - if((dma->chcr & 0x30) == 0x10) { //Check if ASR0 is NOT equal to 0 (Contains address) - dma->chcr = (dma->chcr & 0xffffffcf); //No addresses left in call stack - dma->tadr = dma->asr0; //Read ASR0 as next tag - dma->asr0 = 0; //Clear ASR0 - } else { //Else if ASR1 and ASR0 are empty - //dma->tadr += 16; //Clear tag address - Kills Klonoa 2 - return true; //End Transfer + break; + } + //If ASR1 is empty (No address held) + case 1:{ //Check if ASR0 is NOT equal to 0 (Contains address) + dma->chcr = (dma->chcr & 0xffffffcf); //No addresses left in call stack + dma->tadr = dma->asr0; //Read ASR0 as next tag + dma->asr0 = 0; //Clear ASR0 + break; + } + case 0: { //Else if ASR1 and ASR0 are empty + //dma->tadr += 16; //Clear tag address - Kills Klonoa 2 + return true; //End Transfer + } + default: { //Else if ASR1 and ASR0 are messed up + //Console::Error("TAG_RET: ASR 1 & 0 == 1. This shouldn't happen!"); + //dma->tadr += 16; //Clear tag address - Kills Klonoa 2 + return true; //End Transfer } } return false; diff --git a/pcsx2/SPR.cpp b/pcsx2/SPR.cpp index cb607ef85e..10b0b14b6d 100644 --- a/pcsx2/SPR.cpp +++ b/pcsx2/SPR.cpp @@ -22,6 +22,7 @@ #include "SPR.h" #include "iR5900.h" #include "VUmicro.h" +#include "Tags.h" extern void mfifoGIFtransfer(int); @@ -139,78 +140,82 @@ static __forceinline void _dmaSPR0() } // Transfer Dn_QWC from SPR to Dn_MADR - if ((spr0->chcr & 0xc) == 0x0) // Normal Mode + switch(CHCR::MOD(spr0)) { - SPR0chain(); - spr0finished = 1; - return; - } - else if ((spr0->chcr & 0xc) == 0x4) - { - u32 *ptag; - int id; - bool done = FALSE; - - if (spr0->qwc > 0) + case NORMAL_MODE: { SPR0chain(); spr0finished = 1; return; } - // Destination Chain Mode - ptag = (u32*) & PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; - spr0->sadr += 16; - - // Transfer dma tag if tte is set - spr0->chcr = (spr0->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); //Transfer upper part of tag to CHCR bits 31-15 - - id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag - spr0->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag - spr0->madr = ptag[1]; //MADR = ADDR field - - SPR_LOG("spr0 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx", - ptag[1], ptag[0], spr0->qwc, id, spr0->madr, spr0->sadr); - - if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) // STS == fromSPR + case CHAIN_MODE: { - Console::WriteLn("SPR stall control"); - } + u32 *ptag; + int id; + bool done = FALSE; - switch (id) - { - case 0: // CNTS - Transfer QWC following the tag (Stall Control) - if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) psHu32(DMAC_STADR) = spr0->madr + (spr0->qwc * 16); //Copy MADR to DMAC_STADR stall addr register - break; - - case 1: // CNT - Transfer QWC following the tag. - done = FALSE; - break; - - case 7: // End - Transfer QWC following the tag - done = TRUE; - break; - } - SPR0chain(); - if (spr0->chcr & 0x80 && ptag[0] >> 31) //Check TIE bit of CHCR and IRQ bit of tag - { - //Console::WriteLn("SPR0 TIE"); - done = TRUE; - } + if (spr0->qwc > 0) + { + SPR0chain(); + spr0finished = 1; + return; + } + // Destination Chain Mode + ptag = (u32*) & PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; + spr0->sadr += 16; - spr0finished = (done) ? 1 : 0; - - if (!done) - { - ptag = (u32*) & PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; //Set memory pointer to SADR - CPU_INT(8, ((u16)ptag[0]) / BIAS); // the lower 16bits of the tag / BIAS); - return; + Tag::UnsafeTransfer(spr0, ptag); + id = Tag::Id(ptag); + + spr0->madr = ptag[1]; //MADR = ADDR field + + SPR_LOG("spr0 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx", + ptag[1], ptag[0], spr0->qwc, id, spr0->madr, spr0->sadr); + + if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) // STS == fromSPR + { + Console::WriteLn("SPR stall control"); + } + + switch (id) + { + case TAG_CNTS: // CNTS - Transfer QWC following the tag (Stall Control) + if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) psHu32(DMAC_STADR) = spr0->madr + (spr0->qwc * 16); //Copy MADR to DMAC_STADR stall addr register + break; + + case TAG_CNT: // CNT - Transfer QWC following the tag. + done = FALSE; + break; + + case TAG_END: // End - Transfer QWC following the tag + done = TRUE; + break; + } + SPR0chain(); + if (CHCR::TIE(spr0) && Tag::IRQ(ptag)) //Check TIE bit of CHCR and IRQ bit of tag + { + //Console::WriteLn("SPR0 TIE"); + done = TRUE; + } + + spr0finished = (done) ? 1 : 0; + + if (!done) + { + ptag = (u32*) & PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; //Set memory pointer to SADR + CPU_INT(8, ((u16)ptag[0]) / BIAS); // the lower 16bits of the tag / BIAS); + return; + } + SPR_LOG("spr0 dmaChain complete %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx", + ptag[1], ptag[0], spr0->qwc, id, spr0->madr); + break; + } + //case INTERLEAVE_MODE: + default: + { + _SPR0interleave(); + break; } - SPR_LOG("spr0 dmaChain complete %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx", - ptag[1], ptag[0], spr0->qwc, id, spr0->madr); - } - else // Interleave Mode - { - _SPR0interleave(); } } @@ -227,7 +232,7 @@ void SPRFROMinterrupt() //Console::WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", params gif->chcr, gif->madr, gif->tadr); mfifoGIFtransfer(mfifotransferred); mfifotransferred = 0; - if(gif->chcr & 0x100)return; + if (CHCR::STR(gif)) return; } else if ((psHu32(DMAC_CTRL) & 0xC) == 0x8) // VIF1 MFIFO { @@ -236,11 +241,11 @@ void SPRFROMinterrupt() //Console::WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", params vif1ch->chcr, vif1ch->madr, vif1ch->tadr); mfifoVIF1transfer(mfifotransferred); mfifotransferred = 0; - if(vif1ch->chcr & 0x100)return; + if (CHCR::STR(vif1ch)) return; } } if (spr0finished == 0) return; - spr0->chcr &= ~0x100; + CHCR::clearSTR(spr0); hwDmacIrq(DMAC_FROM_SPR); } @@ -250,7 +255,7 @@ void dmaSPR0() // fromSPR SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx", spr0->chcr, spr0->madr, spr0->qwc, spr0->sadr); - if ((spr0->chcr & 0xc) == 0x4 && spr0->qwc == 0) + if ((CHCR::MOD(spr0) == CHAIN_MODE) && spr0->qwc == 0) { u32 *ptag; ptag = (u32*) & PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; //Set memory pointer to SADR @@ -319,76 +324,77 @@ void _SPR1interleave() void _dmaSPR1() // toSPR work function { - if ((spr1->chcr & 0xc) == 0) // Normal Mode + switch(CHCR::MOD(spr1)) { - //int cycles = 0; - // Transfer Dn_QWC from Dn_MADR to SPR1 - SPR1chain(); - spr1finished = 1; - return; - } - else if ((spr1->chcr & 0xc) == 0x4) - { - u32 *ptag; - int id; - bool done = FALSE; - - if (spr1->qwc > 0) + case NORMAL_MODE: { + //int cycles = 0; // Transfer Dn_QWC from Dn_MADR to SPR1 SPR1chain(); spr1finished = 1; return; } - // Chain Mode - - ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR - if (ptag == NULL) //Is ptag empty? + case CHAIN_MODE: { - Console::WriteLn("SPR1 Tag BUSERR"); - spr1->chcr = (spr1->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 - done = TRUE; - spr1finished = (done) ? 1: 0; - return; - } - spr1->chcr = (spr1->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); //Transfer upper part of tag to CHCR bits 31-15 + u32 *ptag; + int id; + bool done = FALSE; - id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag - spr1->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag until SPR1chain is called in a few lines. - spr1->madr = ptag[1]; //MADR = ADDR field + if (spr1->qwc > 0) + { + // Transfer Dn_QWC from Dn_MADR to SPR1 + SPR1chain(); + spr1finished = 1; + return; + } + // Chain Mode - // Transfer dma tag if tte is set - if (spr1->chcr & 0x40) - { - SPR_LOG("SPR TTE: %x_%x\n", ptag[3], ptag[2]); - SPR1transfer(ptag, 4); //Transfer Tag - } - - SPR_LOG("spr1 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx", - ptag[1], ptag[0], spr1->qwc, id, spr1->madr); - - done = (hwDmacSrcChain(spr1, id) == 1); - SPR1chain(); //Transfers the data set by the switch - - if (spr1->chcr & 0x80 && ptag[0] >> 31) //Check TIE bit of CHCR and IRQ bit of tag - { - SPR_LOG("dmaIrq Set"); - - //Console::WriteLn("SPR1 TIE"); - done = TRUE; - } - - spr1finished = done; - if (!done) - { ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR - CPU_INT(9, (((u16)ptag[0]) / BIAS));// the lower 16 bits of the tag / BIAS); + + if (!(Tag::Transfer("SPR1 Tag", spr1, ptag))) + { + done = TRUE; + spr1finished = (done) ? 1: 0; + } + + id = Tag::Id(ptag); + spr1->madr = ptag[1]; //MADR = ADDR field + + // Transfer dma tag if tte is set + if (CHCR::TTE(spr1)) + { + SPR_LOG("SPR TTE: %x_%x\n", ptag[3], ptag[2]); + SPR1transfer(ptag, 4); //Transfer Tag + } + + SPR_LOG("spr1 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx", + ptag[1], ptag[0], spr1->qwc, id, spr1->madr); + + done = (hwDmacSrcChain(spr1, id) == 1); + SPR1chain(); //Transfers the data set by the switch + + if (CHCR::TIE(spr1) && Tag::IRQ(ptag)) //Check TIE bit of CHCR and IRQ bit of tag + { + SPR_LOG("dmaIrq Set"); + + //Console::WriteLn("SPR1 TIE"); + done = TRUE; + } + + spr1finished = done; + if (!done) + { + ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR + CPU_INT(9, (((u16)ptag[0]) / BIAS));// the lower 16 bits of the tag / BIAS); + } + break; + } + //case INTERLEAVE_MODE: + default: + { + _SPR1interleave(); + break; } - } - else // Interleave Mode - { - _SPR1interleave(); } } @@ -400,7 +406,7 @@ void dmaSPR1() // toSPR spr1->chcr, spr1->madr, spr1->qwc, spr1->tadr, spr1->sadr); - if (((spr1->chcr & 0xc) == 0x4) && (spr1->qwc == 0)) + if ((CHCR::MOD(spr1) == CHAIN_MODE) && (spr1->qwc == 0)) { u32 *ptag; ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR @@ -417,7 +423,7 @@ void SPRTOinterrupt() { _dmaSPR1(); if (spr1finished == 0) return; - spr1->chcr &= ~0x100; + CHCR::clearSTR(spr1); hwDmacIrq(DMAC_TO_SPR); } diff --git a/pcsx2/Tags.h b/pcsx2/Tags.h index 74a8f8d3f4..0de3f9ff3f 100644 --- a/pcsx2/Tags.h +++ b/pcsx2/Tags.h @@ -22,6 +22,42 @@ // Actually, looks like I didn't need templates after all... :) +enum mfd_type +{ + NO_MFD, + MFD_RESERVED, + MFD_VIF1, + MFD_GIF +}; + +enum sts_type +{ + NO_STS, + STS_SIF0, + STS_fromSPR, + STS_fromIPU +}; + +enum std_type +{ + NO_STD, + STD_VIF1, + STD_GIF, + STD_SIF1 +}; + +enum d_ctrl_flags +{ + CTRL_DMAE = 0x1, // 0/1 - disables/enables all DMAs + CTRL_RELE = 0x2, // 0/1 - cycle stealing off/on + CTRL_MFD = 0xC, // Memory FIFO drain channel (mfd_type) + CTRL_STS = 0x30, // Stall Control source channel (sts type) + CTRL_STD = 0xC0, // Stall Controll drain channel (std_type) + CTRL_RCYC = 0x100 // Release cycle (8/16/32/64/128/256) + // When cycle stealing is on, the release cycle sets the period to release + // the bus to EE. +}; + enum pce_values { PCE_NOTHING = 0, @@ -32,6 +68,7 @@ enum pce_values enum tag_id { + TAG_CNTS = 0, TAG_REFE = 0, // Transfer Packet According to ADDR field, clear STR, and end TAG_CNT, // Transfer QWC following the tag. TAG_NEXT, // Transfer QWC following tag. TADR = ADDR @@ -171,7 +208,8 @@ namespace CHCR static __forceinline u8 ASP(DMACh *tag) { - return (TransferMode)((tag->chcr & CHCR_ASP) >> 2); + + return (TransferMode)((tag->chcr & CHCR_ASP) >> 4); } // Clear the individual flags. @@ -250,3 +288,25 @@ namespace QWC tag->qwc = 0; } } + +namespace D_CTRL +{ + static __forceinline bool DMAE() { return !!(psHu32(DMAC_CTRL) & CTRL_DMAE); } + static __forceinline bool RELE() { return !!(psHu32(DMAC_CTRL) & CTRL_RELE); } + static __forceinline bool MFD() + { + return (mfd_type)((psHu32(DMAC_CTRL) & CTRL_MFD) >> 2); + } + static __forceinline bool STS() + { + return (sts_type)((psHu32(DMAC_CTRL) & CTRL_STS) >> 2); + } + static __forceinline bool STD() + { + return (std_type)((psHu32(DMAC_CTRL) & CTRL_STD) >> 2); + } + static __forceinline bool RCLC() + { + return ((((psHu32(DMAC_CTRL) & CTRL_RCYC) >> 3) + 1) * 8); + } +} diff --git a/pcsx2/VifDma.cpp b/pcsx2/VifDma.cpp index a068d00f7b..bfa39930a2 100644 --- a/pcsx2/VifDma.cpp +++ b/pcsx2/VifDma.cpp @@ -1426,7 +1426,7 @@ void vif0Interrupt() if (vif0Regs->stat & (VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS)) { vif0Regs->stat &= ~0xF000000; // FQC=0 - vif0ch->chcr &= ~0x100; + CHCR::clearSTR(vif0ch); return; } @@ -1608,7 +1608,7 @@ void vif0Write32(u32 mem, u32 value) else _VIF0chain(); - vif0ch->chcr |= 0x100; + CHCR::setSTR(vif0ch); CPU_INT(0, g_vifCycles); // Gets the timing right - Flatout } } @@ -2535,7 +2535,7 @@ __forceinline void vif1Interrupt() vif1Regs->stat &= ~0x1F000000; // FQC=0 // One game doesnt like vif stalling at end, cant remember what. Spiderman isnt keen on it tho - vif1ch->chcr &= ~0x100; + CHCR::clearSTR(vif1ch); return; } else if ((vif1ch->qwc > 0) || (vif1.irqoffset > 0)) @@ -2580,7 +2580,7 @@ __forceinline void vif1Interrupt() #endif vif1Regs->stat &= ~VIF1_STAT_VPS; //Vif goes idle as the stall happened between commands; - vif1ch->chcr &= ~0x100; + CHCR::clearSTR(vif1ch); g_vifCycles = 0; hwDmacIrq(DMAC_VIF1);