General cleanup in Gif.cpp && IPU.cpp. Did a bit of refactoring in Gif.cpp. Moved the path3hack to patches.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@850 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
arcum42 2009-03-28 06:53:18 +00:00
parent 2a570c5f91
commit 0feb9de523
8 changed files with 303 additions and 337 deletions

View File

@ -0,0 +1,4 @@
gametitle= Flinstones Bedrock Racing (SLES)
comment=Path 3 Hack
// Moved from Elfheader.cpp
patch=path3hack

View File

@ -0,0 +1,4 @@
gametitle= Sprint Cars (SLUS)
comment=Path 3 Hack
// Moved from Elfheader.cpp
patch=path3hack

View File

@ -52,6 +52,10 @@ EXPORT_C(char*) PS2EgetLibName(void);
// Intended for them to get the ini and plugin paths, but could allow for other things as well.
EXPORT_C_(void) PS2EpassConfig(PcsxConfig Config);
// Alternately, this function serves the same purpose, but would work for emulators outside
// of pcsx2.
EXPORT_C_(void) PS2EpassIniPath(const char *path);
// PS2EgetLibType returns (may be OR'd)
enum {
PS2E_LT_GS = 0x01,

View File

@ -27,6 +27,7 @@ typedef u32 (CALLBACK* _PS2EgetLibType)(void);
typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type);
typedef char*(CALLBACK* _PS2EgetLibName)(void);
typedef void (CALLBACK* _PS2EpassConfig)(PcsxConfig *Config);
typedef void (CALLBACK* _PS2EpassIniPath)(const char *path);
// GS
// NOTE: GSreadFIFOX/GSwriteCSR functions CANNOT use XMM/MMX regs

View File

@ -584,9 +584,9 @@ void LoadGameSpecificSettings()
case 0xb99379b7: // erementar gerad (discolored chars)
g_VUGameFixes |= VUFIX_XGKICKDELAY2; // Tested - still needed - arcum42
break;
case 0xa08c4057: //Sprint Cars (SLUS)
case 0x8b0725d5: //Flinstones Bedrock Racing (SLES)
path3hack = 1; // We can move this to patch files right now
break;
//case 0xa08c4057: //Sprint Cars (SLUS)
//case 0x8b0725d5: //Flinstones Bedrock Racing (SLES)
//path3hack = 1; // We can move this to patch files right now
//break;
}
}

View File

@ -32,13 +32,6 @@ using namespace std;
using namespace R5900;
// This should be done properly with the other logs.
#ifdef DEBUG
#define MTGS_LOG SysPrintf
#else
#define MTGS_LOG 0&&
#endif
static bool m_gsOpened = false;
#ifdef PCSX2_DEVBUILD

View File

@ -28,12 +28,24 @@
using std::min;
#define gif ((DMACh*)&psH[0xA000])
enum gifstate_t
{
GIF_STATE_EMPTY = 0,
GIF_STATE_STALL,
GIF_STATE_DONE
};
// A three-way toggle used to determine if the GIF is stalling (transferring) or done (finished).
static gifstate_t gifstate = GIF_STATE_EMPTY;
//int gscount = 0;
static u64 s_gstag = 0; // used for querying the last tag
static int gspath3done=0;
static int gscycles = 0;
static int gspath3done = 0;
static u32 gscycles = 0, prevcycles = 0, mfifocycles = 0;
static u32 gifqwc = 0;
__forceinline void gsInterrupt() {
GIF_LOG("gsInterrupt: %8.8x", cpuRegs.cycle);
@ -103,10 +115,10 @@ static void WRITERING_DMA(u32 *pMem, u32 qwc)
else
{
GSGIFTRANSFER3(pMem, qwc);
if( GSgetLastTag != NULL )
if (GSgetLastTag != NULL)
{
GSgetLastTag(&s_gstag);
if( s_gstag == 1 ) Path3transfer = 0; /* fixes SRS and others */
if (s_gstag == 1) Path3transfer = 0; /* fixes SRS and others */
}
}
}
@ -119,12 +131,9 @@ int _GIFchain() {
#endif
u32 *pMem;
//if (gif->qwc == 0) return 0;
pMem = (u32*)dmaGetAddr(gif->madr);
if (pMem == NULL) {
// reset path3, fixes dark cloud 2
gsGIFSoftReset(4);
//must increment madr and clear qwc, else it loops
@ -135,19 +144,44 @@ int _GIFchain() {
}
WRITERING_DMA(pMem, qwc);
//if((psHu32(GIF_MODE) & 0x4)) amount -= qwc;
gif->madr+= qwc*16;
gif->qwc -= qwc;
return (qwc)*2;
}
#define GIFchain() \
if (gif->qwc) { \
gscycles+= _GIFchain(); /* guessing */ \
}
__forceinline void GIFchain()
{
FreezeRegs(1);
if (gif->qwc) gscycles+= _GIFchain(); /* guessing */ \
FreezeRegs(0);
}
int gscount = 0;
static int prevcycles = 0;
static __forceinline void dmaGIFend()
{
if ((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0)
{
CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/);
}
else
{
CPU_INT(2, gif->qwc /** BIAS*/);
}
}
// These could probably be consolidated into one function,
// but I wasn't absolutely sure if there was a good reason
// not to do the gif->qwc != 0 check. --arcum42
static __forceinline void GIFdmaEnd()
{
if (psHu32(GIF_MODE) & 0x4)
{
CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/);
}
else
{
CPU_INT(2, gif->qwc /** BIAS*/);
}
}
void GIFdma()
{
@ -188,8 +222,7 @@ void GIFdma()
GSCSRr &= ~0xC000; //Clear FIFO stuff
GSCSRr |= 0x8000; //FIFO full
//psHu32(GIF_STAT)|= 0xE00; // OPH=1 | APATH=3
psHu32(GIF_STAT)|= 0x10000000; // FQC=31, hack ;)
psHu32(GIF_STAT)|= 0x10000000; // FQC=31, hack ;) [ used to be 0xE00; // OPH=1 | APATH=3]
#ifdef GSPATH3FIX
if (vif1Regs->mskpath3 || psHu32(GIF_MODE) & 0x1) {
@ -203,7 +236,7 @@ void GIFdma()
}
gscycles += 2;
gif->chcr = ( gif->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
id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag
gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag
gif->madr = ptag[1]; //MADR = ADDR field
gspath3done = hwDmacSrcChainWithStack(gif, id);
@ -219,9 +252,8 @@ void GIFdma()
// When MTGS is enabled, Gifchain calls WRITERING_DMA, which calls GSRINGBUF_DONECOPY, which freezes
// the registers inside of the FreezeXMMRegs calls here and in the other two below..
// I'm not really sure that is intentional. --arcum42
FreezeRegs(1);
GIFchain();
FreezeRegs(0); // Theres a comment below that says not to unfreeze the xmm regs, so not sure about this.
// Theres a comment below that says not to unfreeze the xmm regs, so not sure about freezing and unfreezing in GIFchain.
if((gspath3done == 1 || (gif->chcr & 0xc) == 0) && gif->qwc == 0){
if(gif->qwc > 0) Console::WriteLn("Hurray!");
@ -238,23 +270,19 @@ void GIFdma()
return;
}
#endif
//gscycles = 0;
// Transfer Dn_QWC from Dn_MADR to GIF
if ((gif->chcr & 0xc) == 0 || gif->qwc > 0) { // Normal Mode
//gscount++;
if ((psHu32(DMAC_CTRL) & 0xC0) == 0x80 && (gif->chcr & 0xc) == 0) {
Console::WriteLn("DMA Stall Control on GIF normal");
}
FreezeRegs(1);
GIFchain(); //Transfers the data set by the switch
FreezeRegs(0);
if(gif->qwc == 0 && (gif->chcr & 0xc) == 0) gspath3done = 1;
if (gif->qwc == 0 && (gif->chcr & 0xc) == 0)
{
gspath3done = 1;
}
else
{
if(psHu32(GIF_MODE) & 0x4)
CPU_INT(2, min( 8, (int)gif->qwc )/** BIAS*/);
else
CPU_INT(2, gif->qwc/* * BIAS*/);
GIFdmaEnd();
}
return;
}
@ -268,19 +296,11 @@ void GIFdma()
}
gscycles+=2; // Add 1 cycles from the QW read for the tag
// Transfer dma tag if tte is set
if (gif->chcr & 0x40) {
//u32 temptag[4] = {0};
//Console::WriteLn("GIF TTE: %x_%x", params ptag[3], ptag[2]);
//temptag[0] = ptag[2];
//temptag[1] = ptag[3];
//GSGIFTRANSFER3(ptag, 1);
}
// We used to transfer dma tags if tte is set here
gif->chcr = ( gif->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
id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag
gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag
gif->madr = ptag[1]; //MADR = ADDR field
@ -300,14 +320,11 @@ void GIFdma()
return;
}
}
FreezeRegs(1);
GIFchain(); //Transfers the data set by the switch
FreezeRegs(0);
if ((gif->chcr & 0x80) && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag
GIF_LOG("dmaIrq Set");
gspath3done = 1;
//gif->qwc = 0;
}
}
}
@ -326,25 +343,19 @@ void GIFdma()
gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag
gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15
if(psHu32(GIF_MODE) & 0x4)
CPU_INT(2, min( 8, (int)gif->qwc )/** BIAS*/);
else
CPU_INT(2, gif->qwc /** BIAS*/);
GIFdmaEnd();
gif->qwc = 0;
return;
}
}
//CPU_INT(2, gif->qwc /** BIAS*/);
gscycles = 0;
}
}
void dmaGIF() {
//if(vif1Regs->mskpath3 || (psHu32(GIF_MODE) & 0x1)){
// CPU_INT(2, 48); //Wait time for the buffer to fill, fixes some timing problems in path 3 masking
//} //It takes the time of 24 QW for the BUS to become ready - The Punisher, And1 Streetball
//else
//We used to addd wait time for the buffer to fill here, fixing some timing problems in path 3 masking
//It takes the time of 24 QW for the BUS to become ready - The Punisher, And1 Streetball
if ((psHu32(DMAC_CTRL) & 0xC) == 0xC ) { // GIF MFIFO
Console::WriteLn("GIF MFIFO");
gifMFIFOInterrupt();
@ -355,66 +366,33 @@ void dmaGIF() {
GSCSRr &= ~0xC000; //Clear FIFO stuff
GSCSRr |= 0x8000; //FIFO full
//psHu32(GIF_STAT)|= 0xE00; // OPH=1 | APATH=3
psHu32(GIF_STAT)|= 0x10000000; // FQC=31, hack ;)
psHu32(GIF_STAT)|= 0x10000000; // FQC=31, hack ;) [used to be 0xE00; // OPH=1 | APATH=3]
if ((gif->chcr & 0xc) != 0 && gif->qwc == 0){
u32 *ptag;
ptag = (u32*)dmaGetAddr(gif->tadr);
gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag
gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15
if((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0)
{
CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/);
}
else
{
CPU_INT(2, gif->qwc /** BIAS*/);
}
dmaGIFend();
gif->qwc = 0;
return;
}
if(gif->qwc > 0 && (gif->chcr & 0x4) == 0x4) {
//Console::WriteLn("HL Hack");
gspath3done = 1; //Halflife sets a QWC amount in chain mode, no tadr set.
if((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0)
{
CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/);
}
else
{
CPU_INT(2, gif->qwc /** BIAS*/);
}
return;
gspath3done = 1; //Halflife sets a QWC amount in chain mode, no tadr set.
// Since this is all that's done after this if statement ends, anyways no need to have
// this code in here.
//dmaGIFend();
//return;
}
//GIFdma();
if((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0)
{
CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/);
}
else
{
CPU_INT(2, gif->qwc /** BIAS*/);
}
dmaGIFend();
}
#define spr0 ((DMACh*)&PS2MEM_HW[0xD000])
enum gifstate_t
{
GIF_STATE_EMPTY = 0,
GIF_STATE_STALL,
GIF_STATE_DONE
};
static unsigned int mfifocycles;
static unsigned int gifqwc = 0;
// A three-way toggle used to determine if the GIF is stalling (transferring) or done (finished).
static gifstate_t gifstate = GIF_STATE_EMPTY;
// called from only one location, so forceinline it:
static __forceinline int mfifoGIFrbTransfer() {
u32 qwc = (psHu32(GIF_MODE) & 0x4 && vif1Regs->mskpath3) ? min(8, (int)gif->qwc) : gif->qwc;
@ -485,7 +463,7 @@ static __forceinline int mfifoGIFchain() {
return 0;
}
int gifmfifoirq = 0;
bool gifmfifoirq = FALSE;
void mfifoGIFtransfer(int qwc) {
u32 *ptag;
@ -493,76 +471,73 @@ void mfifoGIFtransfer(int qwc) {
u32 temp = 0;
mfifocycles = 0;
gifmfifoirq = 0;
gifmfifoirq = FALSE;
if(qwc > 0 ) {
gifqwc += qwc;
if(!(gif->chcr & 0x100))return;
if(gifstate == GIF_STATE_STALL) return;
}
gifqwc += qwc;
if(!(gif->chcr & 0x100))return;
if(gifstate == GIF_STATE_STALL) return;
}
SPR_LOG("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr, gif->madr, gif->tadr);
if(gif->qwc == 0){
if(gif->tadr == spr0->madr) {
#ifdef PCSX2_DEVBUILD
/*if( gifqwc > 1 )
Console::WriteLn("gif mfifo tadr==madr but qwc = %d", params gifqwc);*/
#endif
//hwDmacIrq(14);
if(gif->tadr == spr0->madr) {
//if( gifqwc > 1 ) DevCon::WriteLn("gif mfifo tadr==madr but qwc = %d", params gifqwc);
//hwDmacIrq(14);
return;
return;
}
gif->tadr = psHu32(DMAC_RBOR) + (gif->tadr & psHu32(DMAC_RBSR));
ptag = (u32*)dmaGetAddr(gif->tadr);
id = (ptag[0] >> 28) & 0x7;
gif->qwc = (ptag[0] & 0xffff);
gif->madr = ptag[1];
mfifocycles += 2;
gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 );
SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x",
ptag[1], ptag[0], gif->qwc, id, gif->madr, gif->tadr, gifqwc, spr0->madr);
gifqwc--;
switch (id) {
case 0: // Refe - Transfer Packet According to ADDR field
gif->tadr = psHu32(DMAC_RBOR) + ((gif->tadr + 16) & psHu32(DMAC_RBSR));
gifstate = GIF_STATE_DONE; //End Transfer
break;
case 1: // CNT - Transfer QWC following the tag.
gif->madr = psHu32(DMAC_RBOR) + ((gif->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to QW after Tag
gif->tadr = psHu32(DMAC_RBOR) + ((gif->madr + (gif->qwc << 4)) & psHu32(DMAC_RBSR)); //Set TADR to QW following the data
gifstate = GIF_STATE_EMPTY;
break;
case 2: // Next - Transfer QWC following tag. TADR = ADDR
temp = gif->madr; //Temporarily Store ADDR
gif->madr = psHu32(DMAC_RBOR) + ((gif->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to QW following the tag
gif->tadr = temp; //Copy temporarily stored ADDR to Tag
gifstate = GIF_STATE_EMPTY;
break;
case 3: // Ref - Transfer QWC from ADDR field
case 4: // Refs - Transfer QWC from ADDR field (Stall Control)
gif->tadr = psHu32(DMAC_RBOR) + ((gif->tadr + 16) & psHu32(DMAC_RBSR)); //Set TADR to next tag
gifstate = GIF_STATE_EMPTY;
break;
case 7: // End - Transfer QWC following the tag
gif->madr = psHu32(DMAC_RBOR) + ((gif->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to data following the tag
gif->tadr = psHu32(DMAC_RBOR) + ((gif->madr + (gif->qwc << 4)) & psHu32(DMAC_RBSR)); //Set TADR to QW following the data
gifstate = GIF_STATE_DONE; //End Transfer
break;
}
gif->tadr = psHu32(DMAC_RBOR) + (gif->tadr & psHu32(DMAC_RBSR));
ptag = (u32*)dmaGetAddr(gif->tadr);
id = (ptag[0] >> 28) & 0x7;
gif->qwc = (ptag[0] & 0xffff);
gif->madr = ptag[1];
mfifocycles += 2;
gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 );
SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x",
ptag[1], ptag[0], gif->qwc, id, gif->madr, gif->tadr, gifqwc, spr0->madr);
gifqwc--;
switch (id) {
case 0: // Refe - Transfer Packet According to ADDR field
gif->tadr = psHu32(DMAC_RBOR) + ((gif->tadr + 16) & psHu32(DMAC_RBSR));
gifstate = GIF_STATE_DONE; //End Transfer
break;
case 1: // CNT - Transfer QWC following the tag.
gif->madr = psHu32(DMAC_RBOR) + ((gif->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to QW after Tag
gif->tadr = psHu32(DMAC_RBOR) + ((gif->madr + (gif->qwc << 4)) & psHu32(DMAC_RBSR)); //Set TADR to QW following the data
gifstate = GIF_STATE_EMPTY;
break;
case 2: // Next - Transfer QWC following tag. TADR = ADDR
temp = gif->madr; //Temporarily Store ADDR
gif->madr = psHu32(DMAC_RBOR) + ((gif->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to QW following the tag
gif->tadr = temp; //Copy temporarily stored ADDR to Tag
gifstate = GIF_STATE_EMPTY;
break;
case 3: // Ref - Transfer QWC from ADDR field
case 4: // Refs - Transfer QWC from ADDR field (Stall Control)
gif->tadr = psHu32(DMAC_RBOR) + ((gif->tadr + 16) & psHu32(DMAC_RBSR)); //Set TADR to next tag
gifstate = GIF_STATE_EMPTY;
break;
case 7: // End - Transfer QWC following the tag
gif->madr = psHu32(DMAC_RBOR) + ((gif->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to data following the tag
gif->tadr = psHu32(DMAC_RBOR) + ((gif->madr + (gif->qwc << 4)) & psHu32(DMAC_RBSR)); //Set TADR to QW following the data
gifstate = GIF_STATE_DONE; //End Transfer
break;
}
if ((gif->chcr & 0x80) && (ptag[0] >> 31)) {
SPR_LOG("dmaIrq Set");
gifstate = GIF_STATE_DONE;
gifmfifoirq = 1;
}
if ((gif->chcr & 0x80) && (ptag[0] >> 31)) {
SPR_LOG("dmaIrq Set");
gifstate = GIF_STATE_DONE;
gifmfifoirq = TRUE;
}
}
FreezeRegs(1);
if (mfifoGIFchain() == -1) {
@ -580,11 +555,15 @@ void mfifoGIFtransfer(int qwc) {
void gifMFIFOInterrupt()
{
if(!(gif->chcr & 0x100)) { Console::WriteLn("WTF GIFMFIFO");cpuRegs.interrupt &= ~(1 << 11); return ; }
if (!(gif->chcr & 0x100)) {
Console::WriteLn("WTF GIFMFIFO");
cpuRegs.interrupt &= ~(1 << 11);
return ;
}
if(gifstate != GIF_STATE_STALL) {
if(gifqwc <= 0) {
//Console::WriteLn("Empty");
//Console::WriteLn("Empty");
psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0
hwDmacIrq(14);
return;
@ -599,7 +578,7 @@ void gifMFIFOInterrupt()
}
#endif
//if(gifqwc > 0) Console::WriteLn("GIF MFIFO ending with stuff in it %x", params gifqwc);
if( gifmfifoirq == 0) gifqwc = 0;
if (!gifmfifoirq) gifqwc = 0;
gifstate = GIF_STATE_EMPTY;
gif->chcr &= ~0x100;
hwDmacIrq(DMAC_GIF);

View File

@ -388,7 +388,7 @@ __forceinline void ipuWrite64(u32 mem, u64 value)
switch( mem )
{
case 0x10:
IPU_LOG("Ipu write64: IPU_CMD=0x%08X",value);
IPU_LOG("Ipu write64: IPU_CMD=0x%08X",value);
IPUCMD_WRITE((u32)value);
break;
@ -419,42 +419,51 @@ static __forceinline BOOL ipuIDEC(u32 val)
{
tIPU_CMD_IDEC idec( val );
IPU_LOG("IPU IDEC command.");
IPU_LOG("IPU IDEC command.");
if (idec.FB){ IPU_LOG(" Skip %d bits.",idec.FB);}
IPU_LOG(" Quantizer step code=0x%X.",idec.QSC);
if (idec.DTD==0){ IPU_LOG(" Does not decode DT.");
}else{ IPU_LOG(" Decodes DT.");}
if (idec.SGN==0){ IPU_LOG(" No bias.");
}else{ IPU_LOG(" Bias=128.");}
if (idec.DTE==1){ IPU_LOG(" Dither Enabled.");}
if (idec.OFM==0){ IPU_LOG(" Output format is RGB32.");
}else{ IPU_LOG(" Output format is RGB16.");}
IPU_LOG("");
if (idec.FB) IPU_LOG(" Skip %d bits.",idec.FB);
IPU_LOG(" Quantizer step code=0x%X.",idec.QSC);
if (idec.DTD==0)
IPU_LOG(" Does not decode DT.");
else
IPU_LOG(" Decodes DT.");
if (idec.SGN==0)
IPU_LOG(" No bias.");
else
IPU_LOG(" Bias=128.");
if (idec.DTE==1) IPU_LOG(" Dither Enabled.");
if (idec.OFM==0)
IPU_LOG(" Output format is RGB32.");
else
IPU_LOG(" Output format is RGB16.");
IPU_LOG("");
g_BP.BP+= idec.FB;//skip FB bits
//from IPU_CTRL
ipuRegs->ctrl.PCT = I_TYPE; //Intra DECoding;)
g_decoder.coding_type =ipuRegs->ctrl.PCT;
g_decoder.mpeg1 =ipuRegs->ctrl.MP1;
g_decoder.q_scale_type =ipuRegs->ctrl.QST;
g_decoder.intra_vlc_format=ipuRegs->ctrl.IVF;
g_decoder.scan =ipuRegs->ctrl.AS ? mpeg2_scan_alt: mpeg2_scan_norm;
g_decoder.intra_dc_precision=ipuRegs->ctrl.IDP;
g_decoder.coding_type = ipuRegs->ctrl.PCT;
g_decoder.mpeg1 = ipuRegs->ctrl.MP1;
g_decoder.q_scale_type = ipuRegs->ctrl.QST;
g_decoder.intra_vlc_format = ipuRegs->ctrl.IVF;
g_decoder.scan = ipuRegs->ctrl.AS ? mpeg2_scan_alt: mpeg2_scan_norm;
g_decoder.intra_dc_precision = ipuRegs->ctrl.IDP;
//from IDEC value
g_decoder.quantizer_scale =idec.QSC;
g_decoder.frame_pred_frame_dct=!idec.DTD;
g_decoder.sgn =idec.SGN;
g_decoder.dte =idec.DTE;
g_decoder.ofm =idec.OFM;
g_decoder.quantizer_scale = idec.QSC;
g_decoder.frame_pred_frame_dct = !idec.DTD;
g_decoder.sgn = idec.SGN;
g_decoder.dte = idec.DTE;
g_decoder.ofm = idec.OFM;
//other stuff
g_decoder.dcr =1;//resets DC prediction value
g_decoder.dcr = 1;//resets DC prediction value
s_routine = so_create(mpeg2sliceIDEC, &s_RoutineDone, s_tempstack, sizeof(s_tempstack));
assert( s_routine != NULL );
so_call(s_routine);
if(s_RoutineDone)
s_routine = NULL;
if(s_RoutineDone) s_routine = NULL;
return s_RoutineDone;
}
@ -469,15 +478,26 @@ static __forceinline BOOL ipuBDEC(u32 val)
{
tIPU_CMD_BDEC bdec( val );
IPU_LOG("IPU BDEC(macroblock decode) command %x, num: 0x%x",cpuRegs.pc, s_bdec);
if (bdec.FB){ IPU_LOG(" Skip 0x%X bits.", bdec.FB);}
if (bdec.MBI){ IPU_LOG(" Intra MB.");}
else{ IPU_LOG(" Non-intra MB.");}
if (bdec.DCR){ IPU_LOG(" Resets DC prediction value.");}
else{ IPU_LOG(" Doesn't reset DC prediction value.");}
if (bdec.DT){ IPU_LOG(" Use field DCT.");}
else{ IPU_LOG(" Use frame DCT.");}
IPU_LOG(" Quantizer step=0x%X",bdec.QSC);
IPU_LOG("IPU BDEC(macroblock decode) command %x, num: 0x%x",cpuRegs.pc, s_bdec);
if (bdec.FB) IPU_LOG(" Skip 0x%X bits.", bdec.FB);
if (bdec.MBI)
IPU_LOG(" Intra MB.");
else
IPU_LOG(" Non-intra MB.");
if (bdec.DCR)
IPU_LOG(" Resets DC prediction value.");
else
IPU_LOG(" Doesn't reset DC prediction value.");
if (bdec.DT)
IPU_LOG(" Use field DCT.");
else
IPU_LOG(" Use frame DCT.");
IPU_LOG(" Quantizer step=0x%X",bdec.QSC);
#ifdef _DEBUG
s_bdec++;
#endif
@ -502,8 +522,8 @@ static __forceinline BOOL ipuBDEC(u32 val)
s_routine = so_create(mpeg2_slice, &s_RoutineDone, s_tempstack, sizeof(s_tempstack));
assert( s_routine != NULL );
so_call(s_routine);
if(s_RoutineDone)
s_routine = NULL;
if(s_RoutineDone) s_routine = NULL;
return s_RoutineDone;
}
@ -512,32 +532,31 @@ static BOOL __fastcall ipuVDEC(u32 val) {
switch( g_nCmdPos[0] ) {
case 0:
ipuRegs->cmd.DATA = 0;
if( !getBits32((u8*)&g_decoder.bitstream_buf, 0) )
return FALSE;
if (!getBits32((u8*)&g_decoder.bitstream_buf, 0)) return FALSE;
g_decoder.bitstream_bits = -16;
BigEndian(g_decoder.bitstream_buf, g_decoder.bitstream_buf);
switch((val >> 26) & 3){
case 0://Macroblock Address Increment
g_decoder.mpeg1 =ipuRegs->ctrl.MP1;
g_decoder.mpeg1 = ipuRegs->ctrl.MP1;
ipuRegs->cmd.DATA = get_macroblock_address_increment(&g_decoder);
break;
case 1://Macroblock Type //known issues: no error detected
g_decoder.frame_pred_frame_dct=1;//prevent DCT_TYPE_INTERLACED
g_decoder.coding_type =ipuRegs->ctrl.PCT;
ipuRegs->cmd.DATA=get_macroblock_modes(&g_decoder);
g_decoder.frame_pred_frame_dct = 1;//prevent DCT_TYPE_INTERLACED
g_decoder.coding_type = ipuRegs->ctrl.PCT;
ipuRegs->cmd.DATA = get_macroblock_modes(&g_decoder);
break;
case 2://Motion Code //known issues: no error detected
ipuRegs->cmd.DATA=get_motion_delta(&g_decoder,0);
ipuRegs->cmd.DATA = get_motion_delta(&g_decoder,0);
break;
case 3://DMVector
ipuRegs->cmd.DATA=get_dmv(&g_decoder);
ipuRegs->cmd.DATA = get_dmv(&g_decoder);
break;
}
g_BP.BP+=(g_decoder.bitstream_bits+16);
if((int)g_BP.BP < 0) {
if ((int)g_BP.BP < 0) {
g_BP.BP += 128;
ReorderBitstream();
}
@ -575,7 +594,7 @@ static BOOL ipuFDEC(u32 val)
BigEndian(ipuRegs->cmd.DATA, ipuRegs->cmd.DATA);
ipuRegs->top = ipuRegs->cmd.DATA;
IPU_LOG("FDEC read: 0x%8.8x", ipuRegs->top);
IPU_LOG("FDEC read: 0x%8.8x", ipuRegs->top);
return TRUE;
}
@ -584,7 +603,8 @@ static __forceinline BOOL ipuSETIQ(u32 val)
{
int i;
if ((val >> 27) & 1){
if ((val >> 27) & 1)
{
g_nCmdPos[0] += getBits((u8*)niq + g_nCmdPos[0], 512-8*g_nCmdPos[0], 1); // 8*8*8
IPU_LOG("Read non-intra quantization matrix from IPU FIFO.");
@ -593,8 +613,11 @@ static __forceinline BOOL ipuSETIQ(u32 val)
niq[i*8+0], niq[i*8+1], niq[i*8+2], niq[i*8+3],
niq[i*8+4], niq[i*8+5], niq[i*8+6], niq[i*8+7]);
}
}else{
}
else
{
g_nCmdPos[0] += getBits((u8*)iq+8*g_nCmdPos[0], 512-8*g_nCmdPos[0], 1);
IPU_LOG("Read intra quantization matrix from IPU FIFO.");
for (i=0; i<8; i++){
IPU_LOG("%02X %02X %02X %02X %02X %02X %02X %02X",
@ -658,13 +681,10 @@ static BOOL __fastcall ipuCSC(u32 val)
if( g_nCmdPos[0] < 3072/8 ) {
g_nCmdPos[0] += getBits((u8*)&mb8+g_nCmdPos[0], 3072-8*g_nCmdPos[0], 1);
if( g_nCmdPos[0] < 3072/8 )
return FALSE;
if (g_nCmdPos[0] < 3072/8) return FALSE;
ipu_csc(&mb8, &rgb32, 0);
if (csc.OFM){
ipu_dither2(&rgb32, &rgb16, csc.DTE);
}
if (csc.OFM) ipu_dither2(&rgb32, &rgb16, csc.DTE);
}
if (csc.OFM){
@ -672,8 +692,7 @@ static BOOL __fastcall ipuCSC(u32 val)
{
g_nCmdPos[1] += FIFOfrom_write(((u32*)&rgb16)+4*g_nCmdPos[1], 32-g_nCmdPos[1]);
if( g_nCmdPos[1] <= 0 )
return FALSE;
if( g_nCmdPos[1] <= 0 ) return FALSE;
}
}
else {
@ -681,8 +700,7 @@ static BOOL __fastcall ipuCSC(u32 val)
{
g_nCmdPos[1] += FIFOfrom_write(((u32*)&rgb32)+4*g_nCmdPos[1], 64-g_nCmdPos[1]);
if( g_nCmdPos[1] <= 0 )
return FALSE;
if( g_nCmdPos[1] <= 0 ) return FALSE;
}
}
@ -699,9 +717,14 @@ static BOOL ipuPACK(u32 val)
tIPU_CMD_CSC csc( val );
IPU_LOG("IPU PACK (Colorspace conversion from RGB32) command.");
if (csc.OFM){ IPU_LOG("Output format is RGB16. ");}
else{ IPU_LOG("Output format is INDX4. ");}
if (csc.DTE){ IPU_LOG("Dithering enabled."); }
if (csc.OFM)
IPU_LOG("Output format is RGB16. ");
else
IPU_LOG("Output format is INDX4. ");
if (csc.DTE) IPU_LOG("Dithering enabled.");
IPU_LOG("Number of macroblocks to be converted: %d", csc.MBC);
for (;g_nCmdIndex<(int)csc.MBC; g_nCmdIndex++){
@ -714,22 +737,18 @@ static BOOL ipuPACK(u32 val)
ipu_csc(&mb8, &rgb32, 0);
ipu_dither2(&rgb32, &rgb16, csc.DTE);
if (csc.OFM){
ipu_vq(&rgb16, indx4);
}
if (csc.OFM) ipu_vq(&rgb16, indx4);
}
if (csc.OFM) {
g_nCmdPos[1] += FIFOfrom_write(((u32*)&rgb16)+4*g_nCmdPos[1], 32-g_nCmdPos[1]);
if( g_nCmdPos[1] < 32 )
return FALSE;
if( g_nCmdPos[1] < 32 ) return FALSE;
}
else {
g_nCmdPos[1] += FIFOfrom_write(((u32*)indx4)+4*g_nCmdPos[1], 8-g_nCmdPos[1]);
if( g_nCmdPos[1] < 8 )
return FALSE;
if( g_nCmdPos[1] < 8 ) return FALSE;
}
g_nCmdPos[0] = 0;
@ -791,9 +810,7 @@ void IPUCMD_WRITE(u32 val) {
g_BP.BP+= val & 0x3F;
if( ipuFDEC(val) ) {
return;
}
if (ipuFDEC(val)) return;
ipuRegs->cmd.BUSY = 0x80000000;
ipuRegs->topbusy = 0x80000000;
@ -813,24 +830,19 @@ void IPUCMD_WRITE(u32 val) {
g_BP.BP+= val & 0x3F;
if( ipuSETIQ(ipuRegs->cmd.DATA) ) {
return;
}
if (ipuSETIQ(ipuRegs->cmd.DATA)) return;
break;
case SCE_IPU_SETVQ:
if( ipuSETVQ(ipuRegs->cmd.DATA) ) {
return;
}
if (ipuSETVQ(ipuRegs->cmd.DATA)) return;
break;
case SCE_IPU_CSC:
g_nCmdPos[1] = 0;
g_nCmdIndex = 0;
if( ipuCSC(ipuRegs->cmd.DATA) ) {
if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100))
IPU_INT0_FROM();
if (ipuCSC(ipuRegs->cmd.DATA)) {
if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) IPU_INT0_FROM();
return;
}
@ -840,17 +852,14 @@ void IPUCMD_WRITE(u32 val) {
g_nCmdPos[1] = 0;
g_nCmdIndex = 0;
if( ipuPACK(ipuRegs->cmd.DATA) ) {
return;
}
if (ipuPACK(ipuRegs->cmd.DATA)) return;
break;
case SCE_IPU_IDEC:
if( ipuIDEC(val) ) {
if (ipuIDEC(val)) {
// idec done, ipu0 done too
if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100))
IPU_INT0_FROM();
if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) IPU_INT0_FROM();
return;
}
@ -863,11 +872,8 @@ void IPUCMD_WRITE(u32 val) {
case SCE_IPU_BDEC:
if( ipuBDEC(val)) {
if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100))
IPU_INT0_FROM();
if (ipuRegs->ctrl.SCD || ipuRegs->ctrl.ECD)
hwIntcIrq(INTC_IPU);
if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) IPU_INT0_FROM();
if (ipuRegs->ctrl.SCD || ipuRegs->ctrl.ECD) hwIntcIrq(INTC_IPU);
return;
}
@ -890,7 +896,7 @@ void IPUWorker()
switch (ipuCurCmd) {
case SCE_IPU_VDEC:
if( !ipuVDEC(ipuRegs->cmd.DATA) )
if (!ipuVDEC(ipuRegs->cmd.DATA))
{
hwIntcIrq(INTC_IPU);
return;
@ -902,7 +908,7 @@ void IPUWorker()
break;
case SCE_IPU_FDEC:
if( !ipuFDEC(ipuRegs->cmd.DATA) )
if (!ipuFDEC(ipuRegs->cmd.DATA))
{
hwIntcIrq(INTC_IPU);
return;
@ -914,7 +920,7 @@ void IPUWorker()
break;
case SCE_IPU_SETIQ:
if( !ipuSETIQ(ipuRegs->cmd.DATA) )
if (!ipuSETIQ(ipuRegs->cmd.DATA))
{
hwIntcIrq(INTC_IPU);
return;
@ -922,7 +928,7 @@ void IPUWorker()
break;
case SCE_IPU_SETVQ:
if( !ipuSETVQ(ipuRegs->cmd.DATA) )
if (!ipuSETVQ(ipuRegs->cmd.DATA))
{
hwIntcIrq(INTC_IPU);
return;
@ -930,7 +936,7 @@ void IPUWorker()
break;
case SCE_IPU_CSC:
if( !ipuCSC(ipuRegs->cmd.DATA) )
if (!ipuCSC(ipuRegs->cmd.DATA))
{
hwIntcIrq(INTC_IPU);
return;
@ -940,7 +946,7 @@ void IPUWorker()
IPU_INT0_FROM();
break;
case SCE_IPU_PACK:
if( !ipuPACK(ipuRegs->cmd.DATA) )
if (!ipuPACK(ipuRegs->cmd.DATA))
{
hwIntcIrq(INTC_IPU);
return;
@ -950,7 +956,7 @@ void IPUWorker()
case SCE_IPU_IDEC:
so_call(s_routine);
if( !s_RoutineDone ) {
if (!s_RoutineDone) {
hwIntcIrq(INTC_IPU);
return;
}
@ -961,13 +967,12 @@ void IPUWorker()
ipuRegs->cmd.BUSY = 0;
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 && (ipu0dma->chcr & 0x100)) IPU_INT0_FROM();
s_routine = NULL;
break;
case SCE_IPU_BDEC:
so_call(s_routine);
so_call(s_routine);
if(!s_RoutineDone)
{
hwIntcIrq(INTC_IPU);
@ -978,11 +983,9 @@ void IPUWorker()
ipuRegs->topbusy = 0;
ipuRegs->cmd.BUSY = 0;
ipuCurCmd = 0xffffffff;
if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100))
IPU_INT0_FROM();
if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) IPU_INT0_FROM();
s_routine = NULL;
if (ipuRegs->ctrl.SCD || ipuRegs->ctrl.ECD)
hwIntcIrq(INTC_IPU);
if (ipuRegs->ctrl.SCD || ipuRegs->ctrl.ECD) hwIntcIrq(INTC_IPU);
return;
default:
@ -1003,7 +1006,6 @@ __forceinline void inc_readbits()
{
readbits += 16;
if( readbits >= _readbits+64 ) {
// move back
*(u64*)(_readbits) = *(u64*)(_readbits+64);
*(u64*)(_readbits+8) = *(u64*)(_readbits+72);
@ -1020,9 +1022,7 @@ __forceinline u8* next_readbits()
// returns the pointer of readbits moved by 1 qword
u8* prev_readbits()
{
if( readbits < _readbits+16 ) {
return _readbits+48-(readbits-_readbits);
}
if( readbits < _readbits+16 ) return _readbits+48-(readbits-_readbits);
return readbits-16;
}
@ -1042,28 +1042,21 @@ u16 __fastcall FillInternalBuffer(u32 * pointer, u32 advance, u32 size)
{
if(g_BP.FP == 0)
{
if( FIFOto_read(next_readbits()) == 0 )
return 0;
if (FIFOto_read(next_readbits()) == 0) return 0;
inc_readbits();
g_BP.FP = 1;
}
else if(g_BP.FP < 2 && (*(int*)pointer+size) >= 128)
{
if( FIFOto_read(next_readbits()) )
{
g_BP.FP += 1;
}
if (FIFOto_read(next_readbits())) g_BP.FP += 1;
}
if(*(int*)pointer >= 128)
{
assert( g_BP.FP >= 1);
if(g_BP.FP > 1)
{
inc_readbits();
}
if(g_BP.FP > 1) inc_readbits();
if(advance)
{
@ -1083,13 +1076,11 @@ u8 __fastcall getBits32(u8 *address, u32 advance)
u8* readpos;
// Check if the current BP has exceeded or reached the limit of 128
if( FillInternalBuffer(&g_BP.BP,1,32) < 32 )
return 0;
if (FillInternalBuffer(&g_BP.BP,1,32) < 32) return 0;
readpos = readbits+(int)g_BP.BP/8;
if (g_BP.BP & 7) {
shift = g_BP.BP&7;
mask = (0xff>>shift);
mask = mask|(mask<<8)|(mask<<16)|(mask<<24);
@ -1097,10 +1088,11 @@ u8 __fastcall getBits32(u8 *address, u32 advance)
*(u32*)address = ((~mask&*(u32*)(readpos+1))>>(8-shift)) | (((mask)&*(u32*)readpos)<<shift);
}
else
{
*(u32*)address = *(u32*)readpos;
}
if (advance)
g_BP.BP+=32;
if (advance) g_BP.BP += 32;
return 1;
}
@ -1111,15 +1103,11 @@ __forceinline u8 __fastcall getBits16(u8 *address, u32 advance)
u8* readpos;
// Check if the current BP has exceeded or reached the limit of 128
if( FillInternalBuffer(&g_BP.BP,1,16) < 16 )
{
return 0;
}
if( FillInternalBuffer(&g_BP.BP,1,16) < 16 ) return 0;
readpos = readbits+(int)g_BP.BP/8;
if (g_BP.BP & 7) {
shift = g_BP.BP&7;
mask = (0xff>>shift);
mask = mask|(mask<<8);
@ -1127,10 +1115,11 @@ __forceinline u8 __fastcall getBits16(u8 *address, u32 advance)
*(u16*)address = ((~mask&*(u16*)(readpos+1))>>(8-shift)) | (((mask)&*(u16*)readpos)<<shift);
}
else
{
*(u16*)address = *(u16*)readpos;
}
if (advance)
g_BP.BP+=16;
if (advance) g_BP.BP+=16;
return 1;
}
@ -1147,17 +1136,17 @@ u8 __fastcall getBits8(u8 *address, u32 advance)
readpos = readbits+(int)g_BP.BP/8;
if (g_BP.BP & 7) {
shift = g_BP.BP&7;
mask = (0xff>>shift);
*(u8*)address = (((~mask)&readpos[1])>>(8-shift)) | (((mask)&*readpos)<<shift);
}
else
{
*(u8*)address = *(u8*)readpos;
}
if (advance)
g_BP.BP+=8;
if (advance) g_BP.BP+=8;
return 1;
}
@ -1169,8 +1158,7 @@ int __fastcall getBits(u8 *address, u32 size, u32 advance)
u32 pointer = 0;
// Check if the current BP has exceeded or reached the limit of 128
if( FillInternalBuffer(&g_BP.BP,1,8) < 8 )
return 0;
if( FillInternalBuffer(&g_BP.BP,1,8) < 8 ) return 0;
oldbits = readbits;
// Backup the current BP in case of VDEC/FDEC
@ -1187,28 +1175,22 @@ int __fastcall getBits(u8 *address, u32 size, u32 advance)
shift=8;
}
howmuch = min(min(8-(pointer&7), 128-pointer),
min(size, shift));
howmuch = min(min(8-(pointer&7), 128-pointer), min(size, shift));
if( FillInternalBuffer(&pointer,advance,8) < 8 )
{
if(advance)
{
g_BP.BP = pointer;
}
if(advance) g_BP.BP = pointer;
return address-oldaddr;
}
mask = ((0xFF >> (pointer&7)) <<
(8-howmuch-(pointer&7))) & 0xFF;
mask &= readbits[((pointer)>>3)];
mask >>= 8-howmuch-(pointer&7);
pointer += howmuch;
size -= howmuch;
shift -= howmuch;
mask= ((0xFF >> (pointer&7)) << (8-howmuch-(pointer&7))) & 0xFF;
mask &= readbits[((pointer)>>3)];
mask >>= 8-howmuch-(pointer&7);
pointer += howmuch;
size -= howmuch;
shift -= howmuch;
*address |= mask << shift;
}
++address;
}
else
@ -1218,15 +1200,12 @@ int __fastcall getBits(u8 *address, u32 size, u32 advance)
{
if( FillInternalBuffer(&pointer,advance,8) < 8 )
{
if(advance)
{
g_BP.BP = pointer;
}
if(advance) g_BP.BP = pointer;
return address-oldaddr;
}
howmuch = min(128-pointer, size);
size -= howmuch;
howmuch = min(128-pointer, size);
size -= howmuch;
readmem = readbits + (pointer>>3);
pointer += howmuch;
@ -1610,13 +1589,14 @@ int FIFOfrom_write(const u32 *value,int size)
int transsize;
int firsttrans;
if((int)ipuRegs->ctrl.OFC >= 8)
{
if(IPU0dma() == 0)
{
//if((int)ipuRegs->ctrl.OFC >= 8)
//{
// if(IPU0dma() == 0)
// {
// ipuRegs->ctrl.OFC = 0;
}
}
// }
//}
if ((int)ipuRegs->ctrl.OFC >= 8) IPU0dma();
transsize = min(size,8-(int)ipuRegs->ctrl.OFC);
firsttrans = transsize;
@ -1722,8 +1702,7 @@ void dmaIPU1() // toIPU
{
//g_nDMATransfer &= ~(IPU_DMA_ACTV1|IPU_DMA_DOTIE1);
IPU1dma();
if( ipuRegs->ctrl.BUSY )
IPUWorker();
if (ipuRegs->ctrl.BUSY) IPUWorker();
}
extern void GIFdma();
@ -1767,8 +1746,10 @@ IPU_FORCEINLINE void ipu1Interrupt() {
if( g_nDMATransfer & IPU_DMA_TIE1 ) {
g_nDMATransfer &= ~IPU_DMA_TIE1;
}else
}
else {
ipu1dma->chcr &= ~0x100;
}
hwDmacIrq(DMAC_TO_IPU);
}