mirror of https://github.com/PCSX2/pcsx2.git
Gif/VIF:
-Path3 Masking Changes, Gif Unit now rolls the DMA back (Path3 only) if it is using the Masking and finishes mid DMA packet. -Vif modified to be simpler in the transfer loop and fixes issues where Flushes are called at the end of a DMA packet. Game fixes from changes: Outrun 2006 - Water textures and general flickering fixed, also SW mode not required for half screen issue. Caused by GIF Path 3 stopping in the wrong place. Star Wars Episode 3: Revenge of the Sith - DMA timeouts caused by Flush at end of packet. Had to break savestates (version change!), sorry :( git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5224 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
e4e2366bce
commit
9bb28d3fec
|
@ -249,7 +249,7 @@ void GIFdma()
|
||||||
GIFchain(); //Transfers the data set by the switch
|
GIFchain(); //Transfers the data set by the switch
|
||||||
CPU_INT(DMAC_GIF, gscycles);
|
CPU_INT(DMAC_GIF, gscycles);
|
||||||
return;
|
return;
|
||||||
} else if(gspath3done == false) GIFdma();
|
} else if(gspath3done == false) GIFdma(); //Loop round if there was a blank tag, causes hell otherwise with P3 masking games.
|
||||||
|
|
||||||
prevcycles = 0;
|
prevcycles = 0;
|
||||||
CPU_INT(DMAC_GIF, gscycles);
|
CPU_INT(DMAC_GIF, gscycles);
|
||||||
|
|
|
@ -145,6 +145,7 @@ struct Gif_Path {
|
||||||
u32 buffLimit; // Cut off limit to wrap around
|
u32 buffLimit; // Cut off limit to wrap around
|
||||||
u32 curSize; // Used buffer in bytes
|
u32 curSize; // Used buffer in bytes
|
||||||
u32 curOffset; // Offset of current gifTag
|
u32 curOffset; // Offset of current gifTag
|
||||||
|
u32 dmaRewind; // Used by path3 when only part of a DMA chain is used
|
||||||
Gif_Tag gifTag; // Current GS Primitive tag
|
Gif_Tag gifTag; // Current GS Primitive tag
|
||||||
GS_Packet gsPack; // Current GS Packet info
|
GS_Packet gsPack; // Current GS Packet info
|
||||||
GIF_PATH idx; // Gif Path Index
|
GIF_PATH idx; // Gif Path Index
|
||||||
|
@ -296,14 +297,29 @@ struct Gif_Path {
|
||||||
GS_Packet t = gsPack;
|
GS_Packet t = gsPack;
|
||||||
t.done = 1;
|
t.done = 1;
|
||||||
|
|
||||||
//Path 3 Masking is timing sensitive, we need to simulate its length! (NFSU2)
|
|
||||||
if((gifRegs.stat.APATH-1) == GIF_PATH_3)
|
dmaRewind = 0;
|
||||||
state = GIF_PATH_WAIT;
|
|
||||||
else
|
|
||||||
state = GIF_PATH_IDLE;
|
|
||||||
|
|
||||||
gsPack.Reset();
|
gsPack.Reset();
|
||||||
gsPack.offset = curOffset;
|
gsPack.offset = curOffset;
|
||||||
|
|
||||||
|
//Path 3 Masking is timing sensitive, we need to simulate its length! (NFSU2/Outrun 2006)
|
||||||
|
|
||||||
|
if((gifRegs.stat.APATH-1) == GIF_PATH_3)
|
||||||
|
{
|
||||||
|
state = GIF_PATH_WAIT;
|
||||||
|
|
||||||
|
if(curSize - curOffset > 0 && (gifRegs.stat.M3R || gifRegs.stat.M3P))
|
||||||
|
{
|
||||||
|
//Including breaking packets early (Rewind DMA to pick up where left off)
|
||||||
|
//but only do this when the path is masked, else we're pointlessly slowing things down.
|
||||||
|
dmaRewind = curSize - curOffset;
|
||||||
|
curSize = curOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
state = GIF_PATH_IDLE;
|
||||||
|
|
||||||
return t; // Complete GS packet
|
return t; // Complete GS packet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -486,7 +502,7 @@ struct Gif_Unit {
|
||||||
}
|
}
|
||||||
|
|
||||||
gifPath[tranType&3].CopyGSPacketData(pMem, size, aligned);
|
gifPath[tranType&3].CopyGSPacketData(pMem, size, aligned);
|
||||||
Execute();
|
size -= Execute();
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,10 +540,12 @@ struct Gif_Unit {
|
||||||
|
|
||||||
// Processes gif packets and performs path arbitration
|
// Processes gif packets and performs path arbitration
|
||||||
// on EOPs or on Path 3 Images when IMT is set.
|
// on EOPs or on Path 3 Images when IMT is set.
|
||||||
void Execute() {
|
int Execute() {
|
||||||
if (!CanDoGif()) { DevCon.Error("Gif Unit - Signal or PSE Set or Dir = GS to EE"); return; }
|
if (!CanDoGif()) { DevCon.Error("Gif Unit - Signal or PSE Set or Dir = GS to EE"); return 0; }
|
||||||
bool didPath3 = false;
|
bool didPath3 = false;
|
||||||
|
int curPath = stat.APATH-1;
|
||||||
stat.OPH = 1;
|
stat.OPH = 1;
|
||||||
|
gifPath[curPath].dmaRewind = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if (stat.APATH) { // Some Transfer is happening
|
if (stat.APATH) { // Some Transfer is happening
|
||||||
Gif_Path& path = gifPath[stat.APATH-1];
|
Gif_Path& path = gifPath[stat.APATH-1];
|
||||||
|
@ -568,7 +586,9 @@ struct Gif_Unit {
|
||||||
else { stat.APATH = 0; stat.OPH = 0; break; }
|
else { stat.APATH = 0; stat.OPH = 0; break; }
|
||||||
}
|
}
|
||||||
Gif_FinishIRQ();
|
Gif_FinishIRQ();
|
||||||
//DevCon.WriteLn("APATH = %d [%d,%d,%d]", stat.APATH, !!checkPaths(1,0,0,0),!!checkPaths(0,1,0,0),!!checkPaths(0,0,1,0));
|
|
||||||
|
//Path3 can rewind the DMA, so we send back the amount we go back!
|
||||||
|
return gifPath[curPath].dmaRewind;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XGkick
|
// XGkick
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
// the lower 16 bit value. IF the change is breaking of all compatibility with old
|
// the lower 16 bit value. IF the change is breaking of all compatibility with old
|
||||||
// states, increment the upper 16 bit value, and clear the lower 16 bits to 0.
|
// states, increment the upper 16 bit value, and clear the lower 16 bits to 0.
|
||||||
|
|
||||||
static const u32 g_SaveVersion = (0x9A07 << 16) | 0x0000;
|
static const u32 g_SaveVersion = (0x9A08 << 16) | 0x0000;
|
||||||
|
|
||||||
// this function is meant to be used in the place of GSfreeze, and provides a safe layer
|
// this function is meant to be used in the place of GSfreeze, and provides a safe layer
|
||||||
// between the GS saving function and the MTGS's needs. :)
|
// between the GS saving function and the MTGS's needs. :)
|
||||||
|
|
|
@ -92,11 +92,13 @@ void ExecuteVU(int idx)
|
||||||
{
|
{
|
||||||
vuExecMicro(idx, -1);
|
vuExecMicro(idx, -1);
|
||||||
vifX.cmd = 0;
|
vifX.cmd = 0;
|
||||||
|
vifX.pass = 0;
|
||||||
}
|
}
|
||||||
else if((vifX.cmd & 0x7f) == 0x14 || (vifX.cmd & 0x7f) == 0x15)
|
else if((vifX.cmd & 0x7f) == 0x14 || (vifX.cmd & 0x7f) == 0x15)
|
||||||
{
|
{
|
||||||
vuExecMicro(idx, (u16)(vifXRegs.code) << 3);
|
vuExecMicro(idx, (u16)(vifXRegs.code) << 3);
|
||||||
vifX.cmd = 0;
|
vifX.cmd = 0;
|
||||||
|
vifX.pass = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,9 +108,9 @@ void ExecuteVU(int idx)
|
||||||
|
|
||||||
vifOp(vifCode_Base) {
|
vifOp(vifCode_Base) {
|
||||||
vif1Only();
|
vif1Only();
|
||||||
pass1 { vif1Regs.base = vif1Regs.code & 0x3ff; vif1.cmd = 0; }
|
pass1 { vif1Regs.base = vif1Regs.code & 0x3ff; vif1.cmd = 0; vif1.pass = 0; }
|
||||||
pass3 { VifCodeLog("Base"); }
|
pass3 { VifCodeLog("Base"); }
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDirectHL) {
|
template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDirectHL) {
|
||||||
|
@ -116,7 +118,8 @@ template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDire
|
||||||
pass1 {
|
pass1 {
|
||||||
int vifImm = (u16)vif1Regs.code;
|
int vifImm = (u16)vif1Regs.code;
|
||||||
vif1.tag.size = vifImm ? (vifImm*4) : (65536*4);
|
vif1.tag.size = vifImm ? (vifImm*4) : (65536*4);
|
||||||
return 0;
|
vif1.pass = 1;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
pass2 {
|
pass2 {
|
||||||
const char* name = isDirectHL ? "DirectHL" : "Direct";
|
const char* name = isDirectHL ? "DirectHL" : "Direct";
|
||||||
|
@ -134,9 +137,11 @@ template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDire
|
||||||
//gifUnit.PrintInfo();
|
//gifUnit.PrintInfo();
|
||||||
vif1.vifstalled = true;
|
vif1.vifstalled = true;
|
||||||
vif1Regs.stat.VGW = true;
|
vif1Regs.stat.VGW = true;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
if (vif1.tag.size == 0) {
|
if (vif1.tag.size == 0) {
|
||||||
vif1.cmd = 0;
|
vif1.cmd = 0;
|
||||||
|
vif1.pass = 0;
|
||||||
}
|
}
|
||||||
return ret / 4;
|
return ret / 4;
|
||||||
}
|
}
|
||||||
|
@ -164,11 +169,13 @@ vifOp(vifCode_Flush) {
|
||||||
//gifUnit.PrintInfo();
|
//gifUnit.PrintInfo();
|
||||||
vif1Regs.stat.VGW = true;
|
vif1Regs.stat.VGW = true;
|
||||||
vifX.vifstalled = true;
|
vifX.vifstalled = true;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else vifX.cmd = 0;
|
else vifX.cmd = 0;
|
||||||
|
vifX.pass = 0;
|
||||||
}
|
}
|
||||||
pass3 { VifCodeLog("Flush"); }
|
pass3 { VifCodeLog("Flush"); }
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vifOp(vifCode_FlushA) {
|
vifOp(vifCode_FlushA) {
|
||||||
|
@ -207,25 +214,27 @@ vifOp(vifCode_FlushA) {
|
||||||
if (doStall) {
|
if (doStall) {
|
||||||
vif1Regs.stat.VGW = true;
|
vif1Regs.stat.VGW = true;
|
||||||
vifX.vifstalled = true;
|
vifX.vifstalled = true;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else vifX.cmd = 0;
|
else vifX.cmd = 0;
|
||||||
|
vifX.pass = 0;
|
||||||
}
|
}
|
||||||
pass3 { VifCodeLog("FlushA"); }
|
pass3 { VifCodeLog("FlushA"); }
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToDo: FixMe
|
// ToDo: FixMe
|
||||||
vifOp(vifCode_FlushE) {
|
vifOp(vifCode_FlushE) {
|
||||||
vifStruct& vifX = GetVifX;
|
vifStruct& vifX = GetVifX;
|
||||||
pass1 { vifFlush(idx); vifX.cmd = 0; }
|
pass1 { vifFlush(idx); vifX.cmd = 0; vifX.pass = 0;}
|
||||||
pass3 { VifCodeLog("FlushE"); }
|
pass3 { VifCodeLog("FlushE"); }
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vifOp(vifCode_ITop) {
|
vifOp(vifCode_ITop) {
|
||||||
pass1 { vifXRegs.itops = vifXRegs.code & 0x3ff; GetVifX.cmd = 0; }
|
pass1 { vifXRegs.itops = vifXRegs.code & 0x3ff; GetVifX.cmd = 0; GetVifX.pass = 0; }
|
||||||
pass3 { VifCodeLog("ITop"); }
|
pass3 { VifCodeLog("ITop"); }
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vifOp(vifCode_Mark) {
|
vifOp(vifCode_Mark) {
|
||||||
|
@ -234,9 +243,10 @@ vifOp(vifCode_Mark) {
|
||||||
vifXRegs.mark = (u16)vifXRegs.code;
|
vifXRegs.mark = (u16)vifXRegs.code;
|
||||||
vifXRegs.stat.MRK = true;
|
vifXRegs.stat.MRK = true;
|
||||||
vifX.cmd = 0;
|
vifX.cmd = 0;
|
||||||
|
vifX.pass = 0;
|
||||||
}
|
}
|
||||||
pass3 { VifCodeLog("Mark"); }
|
pass3 { VifCodeLog("Mark"); }
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __fi void _vifCode_MPG(int idx, u32 addr, const u32 *data, int size) {
|
static __fi void _vifCode_MPG(int idx, u32 addr, const u32 *data, int size) {
|
||||||
|
@ -262,8 +272,13 @@ vifOp(vifCode_MPG) {
|
||||||
vifX.tag.addr = (u16)(vifXRegs.code << 3) & (idx ? 0x3fff : 0xfff);
|
vifX.tag.addr = (u16)(vifXRegs.code << 3) & (idx ? 0x3fff : 0xfff);
|
||||||
vifX.tag.size = vifNum ? (vifNum*2) : 512;
|
vifX.tag.size = vifNum ? (vifNum*2) : 512;
|
||||||
vifFlush(idx);
|
vifFlush(idx);
|
||||||
|
if(vifX.vifstalled == true) return 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vifX.pass = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pass2 {
|
pass2 {
|
||||||
if (vifX.vifpacketsize < vifX.tag.size) { // Partial Transfer
|
if (vifX.vifpacketsize < vifX.tag.size) { // Partial Transfer
|
||||||
if((vifX.tag.addr + vifX.vifpacketsize*4) > (idx ? 0x4000 : 0x1000)) {
|
if((vifX.tag.addr + vifX.vifpacketsize*4) > (idx ? 0x4000 : 0x1000)) {
|
||||||
|
@ -282,6 +297,7 @@ vifOp(vifCode_MPG) {
|
||||||
int ret = vifX.tag.size;
|
int ret = vifX.tag.size;
|
||||||
vifX.tag.size = 0;
|
vifX.tag.size = 0;
|
||||||
vifX.cmd = 0;
|
vifX.cmd = 0;
|
||||||
|
vifX.pass = 0;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,10 +314,11 @@ vifOp(vifCode_MSCAL) {
|
||||||
{
|
{
|
||||||
vuExecMicro(idx, (u16)(vifXRegs.code) << 3);
|
vuExecMicro(idx, (u16)(vifXRegs.code) << 3);
|
||||||
vifX.cmd = 0;
|
vifX.cmd = 0;
|
||||||
|
vifX.pass = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pass3 { VifCodeLog("MSCAL"); }
|
pass3 { VifCodeLog("MSCAL"); }
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vifOp(vifCode_MSCALF) {
|
vifOp(vifCode_MSCALF) {
|
||||||
|
@ -318,10 +335,11 @@ vifOp(vifCode_MSCALF) {
|
||||||
{
|
{
|
||||||
vuExecMicro(idx, (u16)(vifXRegs.code) << 3);
|
vuExecMicro(idx, (u16)(vifXRegs.code) << 3);
|
||||||
vifX.cmd = 0;
|
vifX.cmd = 0;
|
||||||
|
vifX.pass = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pass3 { VifCodeLog("MSCALF"); }
|
pass3 { VifCodeLog("MSCALF"); }
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vifOp(vifCode_MSCNT) {
|
vifOp(vifCode_MSCNT) {
|
||||||
|
@ -332,10 +350,11 @@ vifOp(vifCode_MSCNT) {
|
||||||
{
|
{
|
||||||
vuExecMicro(idx, -1);
|
vuExecMicro(idx, -1);
|
||||||
vifX.cmd = 0;
|
vifX.cmd = 0;
|
||||||
|
vifX.pass = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pass3 { VifCodeLog("MSCNT"); }
|
pass3 { VifCodeLog("MSCNT"); }
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToDo: FixMe
|
// ToDo: FixMe
|
||||||
|
@ -352,14 +371,16 @@ vifOp(vifCode_MskPath3) {
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
vif1.cmd = 0;
|
vif1.cmd = 0;
|
||||||
|
vif1.pass = 0;
|
||||||
}
|
}
|
||||||
pass3 { VifCodeLog("MskPath3"); }
|
pass3 { VifCodeLog("MskPath3"); }
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vifOp(vifCode_Nop) {
|
vifOp(vifCode_Nop) {
|
||||||
pass1 {
|
pass1 {
|
||||||
GetVifX.cmd = 0;
|
GetVifX.cmd = 0;
|
||||||
|
GetVifX.pass = 0;
|
||||||
/*if(idx && vif1ch.chcr.STR == true)
|
/*if(idx && vif1ch.chcr.STR == true)
|
||||||
{
|
{
|
||||||
//Some games use a huge stream of NOPS to wait for a GIF packet to start, alas the way PCSX2 works it never starts
|
//Some games use a huge stream of NOPS to wait for a GIF packet to start, alas the way PCSX2 works it never starts
|
||||||
|
@ -370,7 +391,7 @@ vifOp(vifCode_Nop) {
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
pass3 { VifCodeLog("Nop"); }
|
pass3 { VifCodeLog("Nop"); }
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToDo: Review Flags
|
// ToDo: Review Flags
|
||||||
|
@ -385,10 +406,11 @@ vifOp(vifCode_Null) {
|
||||||
//vifX.irq++;
|
//vifX.irq++;
|
||||||
}
|
}
|
||||||
vifX.cmd = 0;
|
vifX.cmd = 0;
|
||||||
|
vifX.pass = 0;
|
||||||
}
|
}
|
||||||
pass2 { Console.Error("Vif%d bad vifcode! [CMD = %x]", idx, vifX.cmd); }
|
pass2 { Console.Error("Vif%d bad vifcode! [CMD = %x]", idx, vifX.cmd); }
|
||||||
pass3 { VifCodeLog("Null"); }
|
pass3 { VifCodeLog("Null"); }
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vifOp(vifCode_Offset) {
|
vifOp(vifCode_Offset) {
|
||||||
|
@ -398,9 +420,10 @@ vifOp(vifCode_Offset) {
|
||||||
vif1Regs.ofst = vif1Regs.code & 0x3ff;
|
vif1Regs.ofst = vif1Regs.code & 0x3ff;
|
||||||
vif1Regs.tops = vif1Regs.base;
|
vif1Regs.tops = vif1Regs.base;
|
||||||
vif1.cmd = 0;
|
vif1.cmd = 0;
|
||||||
|
vif1.pass = 0;
|
||||||
}
|
}
|
||||||
pass3 { VifCodeLog("Offset"); }
|
pass3 { VifCodeLog("Offset"); }
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int idx> static __fi int _vifCode_STColRow(const u32* data, u32* pmem2) {
|
template<int idx> static __fi int _vifCode_STColRow(const u32* data, u32* pmem2) {
|
||||||
|
@ -421,7 +444,13 @@ template<int idx> static __fi int _vifCode_STColRow(const u32* data, u32* pmem2)
|
||||||
|
|
||||||
vifX.tag.addr += ret;
|
vifX.tag.addr += ret;
|
||||||
vifX.tag.size -= ret;
|
vifX.tag.size -= ret;
|
||||||
if (!vifX.tag.size) vifX.cmd = 0;
|
if (!vifX.tag.size)
|
||||||
|
{
|
||||||
|
vifX.pass = 0;
|
||||||
|
vifX.cmd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -431,6 +460,7 @@ vifOp(vifCode_STCol) {
|
||||||
pass1 {
|
pass1 {
|
||||||
vifX.tag.addr = 0;
|
vifX.tag.addr = 0;
|
||||||
vifX.tag.size = 4;
|
vifX.tag.size = 4;
|
||||||
|
vifX.pass = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
pass2 {
|
pass2 {
|
||||||
|
@ -447,6 +477,7 @@ vifOp(vifCode_STRow) {
|
||||||
pass1 {
|
pass1 {
|
||||||
vifX.tag.addr = 0;
|
vifX.tag.addr = 0;
|
||||||
vifX.tag.size = 4;
|
vifX.tag.size = 4;
|
||||||
|
vifX.pass = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
pass2 {
|
pass2 {
|
||||||
|
@ -455,7 +486,7 @@ vifOp(vifCode_STRow) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
pass3 { VifCodeLog("STRow"); }
|
pass3 { VifCodeLog("STRow"); }
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vifOp(vifCode_STCycl) {
|
vifOp(vifCode_STCycl) {
|
||||||
|
@ -464,23 +495,24 @@ vifOp(vifCode_STCycl) {
|
||||||
vifXRegs.cycle.cl = (u8)(vifXRegs.code);
|
vifXRegs.cycle.cl = (u8)(vifXRegs.code);
|
||||||
vifXRegs.cycle.wl = (u8)(vifXRegs.code >> 8);
|
vifXRegs.cycle.wl = (u8)(vifXRegs.code >> 8);
|
||||||
vifX.cmd = 0;
|
vifX.cmd = 0;
|
||||||
|
vifX.pass = 0;
|
||||||
}
|
}
|
||||||
pass3 { VifCodeLog("STCycl"); }
|
pass3 { VifCodeLog("STCycl"); }
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vifOp(vifCode_STMask) {
|
vifOp(vifCode_STMask) {
|
||||||
vifStruct& vifX = GetVifX;
|
vifStruct& vifX = GetVifX;
|
||||||
pass1 { vifX.tag.size = 1; }
|
pass1 { vifX.tag.size = 1; vifX.pass = 1; return 1; }
|
||||||
pass2 { vifXRegs.mask = data[0]; vifX.tag.size = 0; vifX.cmd = 0; }
|
pass2 { vifXRegs.mask = data[0]; vifX.tag.size = 0; vifX.cmd = 0; vifX.pass = 0;}
|
||||||
pass3 { VifCodeLog("STMask"); }
|
pass3 { VifCodeLog("STMask"); }
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vifOp(vifCode_STMod) {
|
vifOp(vifCode_STMod) {
|
||||||
pass1 { vifXRegs.mode = vifXRegs.code & 0x3; GetVifX.cmd = 0; }
|
pass1 { vifXRegs.mode = vifXRegs.code & 0x3; GetVifX.cmd = 0; GetVifX.pass = 0;}
|
||||||
pass3 { VifCodeLog("STMod"); }
|
pass3 { VifCodeLog("STMod"); }
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< uint idx >
|
template< uint idx >
|
||||||
|
@ -496,6 +528,7 @@ static uint calc_addr(bool flg)
|
||||||
vifOp(vifCode_Unpack) {
|
vifOp(vifCode_Unpack) {
|
||||||
pass1 {
|
pass1 {
|
||||||
vifUnpackSetup<idx>(data);
|
vifUnpackSetup<idx>(data);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
pass2 {
|
pass2 {
|
||||||
|
|
|
@ -62,6 +62,7 @@ struct vifStruct {
|
||||||
struct { // These must be together for MTVU
|
struct { // These must be together for MTVU
|
||||||
vifCode tag;
|
vifCode tag;
|
||||||
int cmd;
|
int cmd;
|
||||||
|
int pass;
|
||||||
int cl;
|
int cl;
|
||||||
u8 usn;
|
u8 usn;
|
||||||
u8 StructEnd; // Address of this is used to calculate end of struct
|
u8 StructEnd; // Address of this is used to calculate end of struct
|
||||||
|
|
|
@ -38,31 +38,6 @@ _vifT bool analyzeIbit(u32* &data, int iBit) {
|
||||||
//DevCon.WriteLn("Vif I-Bit IRQ");
|
//DevCon.WriteLn("Vif I-Bit IRQ");
|
||||||
vifX.irq++;
|
vifX.irq++;
|
||||||
|
|
||||||
// Okay did some testing with Max Payne, it does this:
|
|
||||||
// VifMark value = 0x666 (i know, evil!)
|
|
||||||
// NOP with I Bit
|
|
||||||
// VifMark value = 0
|
|
||||||
//
|
|
||||||
// If you break after the 2nd Mark has run, the game reports invalid mark 0 and the game dies.
|
|
||||||
// So it has to occur here, testing a theory that it only doesn't stall if the command with
|
|
||||||
// the iBit IS mark, but still sends the IRQ to let the cpu know the mark is there. (Refraction)
|
|
||||||
//
|
|
||||||
// --------------------------
|
|
||||||
//
|
|
||||||
// This is how it probably works: i-bit sets the IRQ flag, and VIF keeps running until it encounters
|
|
||||||
// a non-MARK instruction. This includes the *current* instruction. ie, execution only continues
|
|
||||||
// unimpeded if MARK[i] is specified, and keeps executing unimpeded until any non-MARK command.
|
|
||||||
// Any other command with an I bit should stall immediately.
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// VifMark[i] value = 0x321 (with I bit)
|
|
||||||
// VifMark value = 0
|
|
||||||
// VifMark value = 0x333
|
|
||||||
// NOP
|
|
||||||
//
|
|
||||||
// ... the VIF should not stall and raise the interrupt until after the NOP is processed.
|
|
||||||
// So the final value for MARK as the game sees it will be 0x333. --air
|
|
||||||
|
|
||||||
if(CHECK_VIF1STALLHACK) return 0;
|
if(CHECK_VIF1STALLHACK) return 0;
|
||||||
else return 1;
|
else return 1;
|
||||||
}
|
}
|
||||||
|
@ -75,6 +50,7 @@ _vifT void vifTransferLoop(u32* &data) {
|
||||||
|
|
||||||
u32& pSize = vifX.vifpacketsize;
|
u32& pSize = vifX.vifpacketsize;
|
||||||
int iBit = vifX.cmd >> 7;
|
int iBit = vifX.cmd >> 7;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
vifXRegs.stat.VPS |= VPS_TRANSFERRING;
|
vifXRegs.stat.VPS |= VPS_TRANSFERRING;
|
||||||
vifXRegs.stat.ER1 = false;
|
vifXRegs.stat.ER1 = false;
|
||||||
|
@ -92,14 +68,9 @@ _vifT void vifTransferLoop(u32* &data) {
|
||||||
// Pass 2 means "log it"
|
// Pass 2 means "log it"
|
||||||
vifCmdHandler[idx][vifX.cmd & 0x7f](2, data);
|
vifCmdHandler[idx][vifX.cmd & 0x7f](2, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
vifCmdHandler[idx][vifX.cmd & 0x7f](0, data);
|
|
||||||
data++; pSize--;
|
|
||||||
if (analyzeIbit<idx>(data, iBit)) break;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = vifCmdHandler[idx][vifX.cmd & 0x7f](1, data);
|
ret = vifCmdHandler[idx][vifX.cmd & 0x7f](vifX.pass, data);
|
||||||
data += ret;
|
data += ret;
|
||||||
pSize -= ret;
|
pSize -= ret;
|
||||||
if (analyzeIbit<idx>(data, iBit)) break;
|
if (analyzeIbit<idx>(data, iBit)) break;
|
||||||
|
@ -127,18 +98,6 @@ _vifT static __fi bool vifTransfer(u32 *data, int size, bool TTE) {
|
||||||
if (!idx) g_vif0Cycles += max(1, (int)((transferred * BIAS) >> 2));
|
if (!idx) g_vif0Cycles += max(1, (int)((transferred * BIAS) >> 2));
|
||||||
else g_vif1Cycles += max(1, (int)((transferred * BIAS) >> 2));
|
else g_vif1Cycles += max(1, (int)((transferred * BIAS) >> 2));
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
if(!idx && g_vu0Cycles > 0) {
|
|
||||||
if (g_vif0Cycles < g_vu0Cycles) g_vu0Cycles -= g_vif0Cycles;
|
|
||||||
elif(g_vif0Cycles >= g_vu0Cycles) g_vu0Cycles = 0;
|
|
||||||
}
|
|
||||||
if (idx && g_vu1Cycles > 0) {
|
|
||||||
if (g_vif1Cycles < g_vu1Cycles) g_vu1Cycles -= g_vif1Cycles;
|
|
||||||
elif(g_vif1Cycles >= g_vu1Cycles) g_vu1Cycles = 0;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
vifX.irqoffset = transferred % 4; // cannot lose the offset
|
vifX.irqoffset = transferred % 4; // cannot lose the offset
|
||||||
|
|
||||||
if (!TTE) {// *WARNING* - Tags CAN have interrupts! so lets just ignore the dma modifying stuffs (GT4)
|
if (!TTE) {// *WARNING* - Tags CAN have interrupts! so lets just ignore the dma modifying stuffs (GT4)
|
||||||
|
|
|
@ -230,6 +230,7 @@ _vifT void vifUnpackSetup(const u32 *data) {
|
||||||
|
|
||||||
vifX.cl = 0;
|
vifX.cl = 0;
|
||||||
vifX.tag.cmd = vifX.cmd;
|
vifX.tag.cmd = vifX.cmd;
|
||||||
|
GetVifX.pass = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template void vifUnpackSetup<0>(const u32 *data);
|
template void vifUnpackSetup<0>(const u32 *data);
|
||||||
|
|
|
@ -133,6 +133,7 @@ _vifT int nVifUnpack(const u8* data) {
|
||||||
}
|
}
|
||||||
else vu1Thread.VifUnpack(vif, vifRegs, (u8*)data, size);
|
else vu1Thread.VifUnpack(vif, vifRegs, (u8*)data, size);
|
||||||
|
|
||||||
|
vif.pass = 0;
|
||||||
vif.tag.size = 0;
|
vif.tag.size = 0;
|
||||||
vif.cmd = 0;
|
vif.cmd = 0;
|
||||||
vifRegs.num = 0;
|
vifRegs.num = 0;
|
||||||
|
|
Loading…
Reference in New Issue