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
This commit is contained in:
arcum42 2009-08-19 12:08:50 +00:00
parent 0587cdc210
commit 490d996abc
4 changed files with 226 additions and 145 deletions

View File

@ -177,37 +177,52 @@ bool hwDmacSrcChainWithStack(DMACh *dma, int id) {
dma->madr = dma->tadr + 16; //Set MADR to data following the tag 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->asr0 = dma->madr + (dma->qwc << 4); //If yes store Succeeding tag
dma->chcr = (dma->chcr & 0xffffffcf) | 0x10; //1 Address in call stack 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->chcr = (dma->chcr & 0xffffffcf) | 0x20; //2 Addresses in call stack
dma->asr1 = dma->madr + (dma->qwc << 4); //If no store Succeeding tag in ASR1 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)"); Console::Notice("Call Stack Overflow (report if it fixes/breaks anything)");
return true; //Return done return true; //Return done
} }
}
dma->tadr = temp; //Set TADR to temporarily stored ADDR dma->tadr = temp; //Set TADR to temporarily stored ADDR
return false; return false;
} }
case TAG_RET: // Ret - Transfer QWC following the tag, load next tag case TAG_RET: // Ret - Transfer QWC following the tag, load next tag
dma->madr = dma->tadr + 16; //Set MADR to data following the tag dma->madr = dma->tadr + 16; //Set MADR to data following the tag
switch(CHCR::ASP(dma))
if ((dma->chcr & 0x30) == 0x20) { //If ASR1 is NOT equal to 0 (Contains address) {
case 2: { //If ASR1 is NOT equal to 0 (Contains address)
dma->chcr = (dma->chcr & 0xffffffcf) | 0x10; //1 Address left in call stack dma->chcr = (dma->chcr & 0xffffffcf) | 0x10; //1 Address left in call stack
dma->tadr = dma->asr1; //Read ASR1 as next tag dma->tadr = dma->asr1; //Read ASR1 as next tag
dma->asr1 = 0; //Clear ASR1 dma->asr1 = 0; //Clear ASR1
} break;
else { //If ASR1 is empty (No address held) }
if((dma->chcr & 0x30) == 0x10) { //Check if ASR0 is NOT equal to 0 (Contains address) //If ASR1 is empty (No address held)
dma->chcr = (dma->chcr & 0xffffffcf); //No addresses left in call stack case 1:{ //Check if ASR0 is NOT equal to 0 (Contains address)
dma->tadr = dma->asr0; //Read ASR0 as next tag dma->chcr = (dma->chcr & 0xffffffcf); //No addresses left in call stack
dma->asr0 = 0; //Clear ASR0 dma->tadr = dma->asr0; //Read ASR0 as next tag
} else { //Else if ASR1 and ASR0 are empty dma->asr0 = 0; //Clear ASR0
//dma->tadr += 16; //Clear tag address - Kills Klonoa 2 break;
return true; //End Transfer }
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; return false;

View File

@ -22,6 +22,7 @@
#include "SPR.h" #include "SPR.h"
#include "iR5900.h" #include "iR5900.h"
#include "VUmicro.h" #include "VUmicro.h"
#include "Tags.h"
extern void mfifoGIFtransfer(int); extern void mfifoGIFtransfer(int);
@ -139,78 +140,82 @@ static __forceinline void _dmaSPR0()
} }
// Transfer Dn_QWC from SPR to Dn_MADR // Transfer Dn_QWC from SPR to Dn_MADR
if ((spr0->chcr & 0xc) == 0x0) // Normal Mode switch(CHCR::MOD(spr0))
{ {
SPR0chain(); case NORMAL_MODE:
spr0finished = 1;
return;
}
else if ((spr0->chcr & 0xc) == 0x4)
{
u32 *ptag;
int id;
bool done = FALSE;
if (spr0->qwc > 0)
{ {
SPR0chain(); SPR0chain();
spr0finished = 1; spr0finished = 1;
return; return;
} }
// Destination Chain Mode case 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
{ {
Console::WriteLn("SPR stall control"); u32 *ptag;
} int id;
bool done = FALSE;
switch (id) if (spr0->qwc > 0)
{ {
case 0: // CNTS - Transfer QWC following the tag (Stall Control) SPR0chain();
if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) psHu32(DMAC_STADR) = spr0->madr + (spr0->qwc * 16); //Copy MADR to DMAC_STADR stall addr register spr0finished = 1;
break; return;
}
case 1: // CNT - Transfer QWC following the tag. // Destination Chain Mode
done = FALSE; ptag = (u32*) & PS2MEM_SCRATCH[spr0->sadr & 0x3fff];
break; spr0->sadr += 16;
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;
}
spr0finished = (done) ? 1 : 0; Tag::UnsafeTransfer(spr0, ptag);
id = Tag::Id(ptag);
if (!done)
{ spr0->madr = ptag[1]; //MADR = ADDR field
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); SPR_LOG("spr0 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx",
return; 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); //Console::WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", params gif->chcr, gif->madr, gif->tadr);
mfifoGIFtransfer(mfifotransferred); mfifoGIFtransfer(mfifotransferred);
mfifotransferred = 0; mfifotransferred = 0;
if(gif->chcr & 0x100)return; if (CHCR::STR(gif)) return;
} }
else if ((psHu32(DMAC_CTRL) & 0xC) == 0x8) // VIF1 MFIFO 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); //Console::WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", params vif1ch->chcr, vif1ch->madr, vif1ch->tadr);
mfifoVIF1transfer(mfifotransferred); mfifoVIF1transfer(mfifotransferred);
mfifotransferred = 0; mfifotransferred = 0;
if(vif1ch->chcr & 0x100)return; if (CHCR::STR(vif1ch)) return;
} }
} }
if (spr0finished == 0) return; if (spr0finished == 0) return;
spr0->chcr &= ~0x100; CHCR::clearSTR(spr0);
hwDmacIrq(DMAC_FROM_SPR); hwDmacIrq(DMAC_FROM_SPR);
} }
@ -250,7 +255,7 @@ void dmaSPR0() // fromSPR
SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx", SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx",
spr0->chcr, spr0->madr, spr0->qwc, spr0->sadr); 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; u32 *ptag;
ptag = (u32*) & PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; //Set memory pointer to SADR ptag = (u32*) & PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; //Set memory pointer to SADR
@ -319,76 +324,77 @@ void _SPR1interleave()
void _dmaSPR1() // toSPR work function void _dmaSPR1() // toSPR work function
{ {
if ((spr1->chcr & 0xc) == 0) // Normal Mode switch(CHCR::MOD(spr1))
{ {
//int cycles = 0; case NORMAL_MODE:
// 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)
{ {
//int cycles = 0;
// Transfer Dn_QWC from Dn_MADR to SPR1 // Transfer Dn_QWC from Dn_MADR to SPR1
SPR1chain(); SPR1chain();
spr1finished = 1; spr1finished = 1;
return; return;
} }
// Chain Mode case CHAIN_MODE:
ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR
if (ptag == NULL) //Is ptag empty?
{ {
Console::WriteLn("SPR1 Tag BUSERR"); u32 *ptag;
spr1->chcr = (spr1->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); //Transfer upper part of tag to CHCR bits 31-15 int id;
psHu32(DMAC_STAT) |= DMAC_STAT_BEIS; //If yes, set BEIS (BUSERR) in DMAC_STAT register bool done = FALSE;
done = TRUE;
spr1finished = (done) ? 1: 0;
return;
}
spr1->chcr = (spr1->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 if (spr1->qwc > 0)
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 // 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 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->chcr, spr1->madr, spr1->qwc,
spr1->tadr, spr1->sadr); spr1->tadr, spr1->sadr);
if (((spr1->chcr & 0xc) == 0x4) && (spr1->qwc == 0)) if ((CHCR::MOD(spr1) == CHAIN_MODE) && (spr1->qwc == 0))
{ {
u32 *ptag; u32 *ptag;
ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR
@ -417,7 +423,7 @@ void SPRTOinterrupt()
{ {
_dmaSPR1(); _dmaSPR1();
if (spr1finished == 0) return; if (spr1finished == 0) return;
spr1->chcr &= ~0x100; CHCR::clearSTR(spr1);
hwDmacIrq(DMAC_TO_SPR); hwDmacIrq(DMAC_TO_SPR);
} }

View File

@ -22,6 +22,42 @@
// Actually, looks like I didn't need templates after all... :) // 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 enum pce_values
{ {
PCE_NOTHING = 0, PCE_NOTHING = 0,
@ -32,6 +68,7 @@ enum pce_values
enum tag_id enum tag_id
{ {
TAG_CNTS = 0,
TAG_REFE = 0, // Transfer Packet According to ADDR field, clear STR, and end TAG_REFE = 0, // Transfer Packet According to ADDR field, clear STR, and end
TAG_CNT, // Transfer QWC following the tag. TAG_CNT, // Transfer QWC following the tag.
TAG_NEXT, // Transfer QWC following tag. TADR = ADDR TAG_NEXT, // Transfer QWC following tag. TADR = ADDR
@ -171,7 +208,8 @@ namespace CHCR
static __forceinline u8 ASP(DMACh *tag) static __forceinline u8 ASP(DMACh *tag)
{ {
return (TransferMode)((tag->chcr & CHCR_ASP) >> 2);
return (TransferMode)((tag->chcr & CHCR_ASP) >> 4);
} }
// Clear the individual flags. // Clear the individual flags.
@ -250,3 +288,25 @@ namespace QWC
tag->qwc = 0; 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);
}
}

View File

@ -1426,7 +1426,7 @@ void vif0Interrupt()
if (vif0Regs->stat & (VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS)) if (vif0Regs->stat & (VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS))
{ {
vif0Regs->stat &= ~0xF000000; // FQC=0 vif0Regs->stat &= ~0xF000000; // FQC=0
vif0ch->chcr &= ~0x100; CHCR::clearSTR(vif0ch);
return; return;
} }
@ -1608,7 +1608,7 @@ void vif0Write32(u32 mem, u32 value)
else else
_VIF0chain(); _VIF0chain();
vif0ch->chcr |= 0x100; CHCR::setSTR(vif0ch);
CPU_INT(0, g_vifCycles); // Gets the timing right - Flatout CPU_INT(0, g_vifCycles); // Gets the timing right - Flatout
} }
} }
@ -2535,7 +2535,7 @@ __forceinline void vif1Interrupt()
vif1Regs->stat &= ~0x1F000000; // FQC=0 vif1Regs->stat &= ~0x1F000000; // FQC=0
// One game doesnt like vif stalling at end, cant remember what. Spiderman isnt keen on it tho // One game doesnt like vif stalling at end, cant remember what. Spiderman isnt keen on it tho
vif1ch->chcr &= ~0x100; CHCR::clearSTR(vif1ch);
return; return;
} }
else if ((vif1ch->qwc > 0) || (vif1.irqoffset > 0)) else if ((vif1ch->qwc > 0) || (vif1.irqoffset > 0))
@ -2580,7 +2580,7 @@ __forceinline void vif1Interrupt()
#endif #endif
vif1Regs->stat &= ~VIF1_STAT_VPS; //Vif goes idle as the stall happened between commands; vif1Regs->stat &= ~VIF1_STAT_VPS; //Vif goes idle as the stall happened between commands;
vif1ch->chcr &= ~0x100; CHCR::clearSTR(vif1ch);
g_vifCycles = 0; g_vifCycles = 0;
hwDmacIrq(DMAC_VIF1); hwDmacIrq(DMAC_VIF1);