mirror of https://github.com/PCSX2/pcsx2.git
Vif:
- Deleted old vif transfer code. - Deleted Vif_Commands.cpp - Added Vif_Transfer.cpp git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2622 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
a7507d6e4a
commit
c144913ede
|
@ -230,6 +230,3 @@ extern void mfifoVIF1transfer(int qwc);
|
||||||
extern bool VIF0transfer(u32 *data, int size, bool istag);
|
extern bool VIF0transfer(u32 *data, int size, bool istag);
|
||||||
extern bool VIF1transfer(u32 *data, int size, bool istag);
|
extern bool VIF1transfer(u32 *data, int size, bool istag);
|
||||||
extern void vifMFIFOInterrupt();
|
extern void vifMFIFOInterrupt();
|
||||||
|
|
||||||
extern bool vifTransfer0(u32 *data, int size, bool isTag);
|
|
||||||
extern bool vifTransfer1(u32 *data, int size, bool isTag);
|
|
||||||
|
|
|
@ -28,120 +28,6 @@ __forceinline void vif0FLUSH()
|
||||||
g_vifCycles += (VU0.cycle - _cycles) * BIAS;
|
g_vifCycles += (VU0.cycle - _cycles) * BIAS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VIF0transfer(u32 *data, int size, bool istag)
|
|
||||||
{
|
|
||||||
return vifTransfer0(data, size, istag);
|
|
||||||
int ret;
|
|
||||||
int transferred = vif0.vifstalled ? vif0.irqoffset : 0; // irqoffset necessary to add up the right qws, or else will spin (spiderman)
|
|
||||||
VIF_LOG("VIF0transfer: size %x (vif0.cmd %x)", size, vif0.cmd);
|
|
||||||
|
|
||||||
vif0.stallontag = false;
|
|
||||||
vif0.vifstalled = false;
|
|
||||||
vif0.vifpacketsize = size;
|
|
||||||
|
|
||||||
while (vif0.vifpacketsize > 0)
|
|
||||||
{
|
|
||||||
if (vif0.cmd)
|
|
||||||
{
|
|
||||||
vif0Regs->stat.VPS = VPS_TRANSFERRING; //Decompression has started
|
|
||||||
|
|
||||||
ret = Vif0TransTLB[(vif0.cmd & 0x7f)](data);
|
|
||||||
data += ret;
|
|
||||||
vif0.vifpacketsize -= ret;
|
|
||||||
if (vif0.cmd == 0) vif0Regs->stat.VPS = VPS_IDLE; //We are once again waiting for a new vifcode as the command has cleared
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vif0.tag.size != 0) Console.WriteLn("no vif0 cmd but tag size is left last cmd read %x", vif0Regs->code);
|
|
||||||
|
|
||||||
// if interrupt and new cmd is NOT MARK
|
|
||||||
if (vif0.irq) break;
|
|
||||||
|
|
||||||
vif0.cmd = (data[0] >> 24);
|
|
||||||
vif0Regs->code = data[0];
|
|
||||||
|
|
||||||
vif0Regs->stat.VPS |= VPS_DECODING; //We need to set these (Onimusha needs it)
|
|
||||||
|
|
||||||
if ((vif0.cmd & 0x60) == 0x60)
|
|
||||||
{
|
|
||||||
vif0UnpackSetup(data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
VIF_LOG("VIFtransfer: cmd %x, num %x, imm %x, size %x", vif0.cmd, (data[0] >> 16) & 0xff, data[0] & 0xffff, size);
|
|
||||||
|
|
||||||
if ((vif0.cmd & 0x7f) > 0x4A)
|
|
||||||
{
|
|
||||||
if (!(vif0Regs->err.ME1)) //Ignore vifcode and tag mismatch error
|
|
||||||
{
|
|
||||||
Console.WriteLn("UNKNOWN VifCmd: %x", vif0.cmd);
|
|
||||||
vif0Regs->stat.ER1 = true;
|
|
||||||
vif0.irq++;
|
|
||||||
}
|
|
||||||
vif0.cmd = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Vif0CMDTLB[(vif0.cmd & 0x7f)]();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++data;
|
|
||||||
--vif0.vifpacketsize;
|
|
||||||
|
|
||||||
if ((vif0.cmd & 0x80))
|
|
||||||
{
|
|
||||||
vif0.cmd &= 0x7f;
|
|
||||||
|
|
||||||
if (!(vif0Regs->err.MII)) //i bit on vifcode and not masked by VIF0_ERR
|
|
||||||
{
|
|
||||||
VIF_LOG("Interrupt on VIFcmd: %x (INTC_MASK = %x)", vif0.cmd, psHu32(INTC_MASK));
|
|
||||||
|
|
||||||
++vif0.irq;
|
|
||||||
|
|
||||||
if (istag && vif0.tag.size <= vif0.vifpacketsize) vif0.stallontag = true;
|
|
||||||
|
|
||||||
if (vif0.tag.size == 0) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} //End of Transfer loop
|
|
||||||
|
|
||||||
transferred += size - vif0.vifpacketsize;
|
|
||||||
g_vifCycles += (transferred >> 2) * BIAS; /* guessing */
|
|
||||||
// use tag.size because some game doesn't like .cmd
|
|
||||||
|
|
||||||
if (vif0.irq && (vif0.tag.size == 0))
|
|
||||||
{
|
|
||||||
vif0.vifstalled = true;
|
|
||||||
|
|
||||||
if (((vif0Regs->code >> 24) & 0x7f) != 0x7) vif0Regs->stat.VIS = true;
|
|
||||||
//else Console.WriteLn("VIF0 IRQ on MARK");
|
|
||||||
|
|
||||||
// spiderman doesn't break on qw boundaries
|
|
||||||
vif0.irqoffset = transferred % 4; // cannot lose the offset
|
|
||||||
|
|
||||||
if (!istag)
|
|
||||||
{
|
|
||||||
transferred = transferred >> 2;
|
|
||||||
vif0ch->madr += (transferred << 4);
|
|
||||||
vif0ch->qwc -= transferred;
|
|
||||||
}
|
|
||||||
//else Console.WriteLn("Stall on vif0, FromSPR = %x, Vif0MADR = %x Sif0MADR = %x STADR = %x", psHu32(0x1000d010), vif0ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
vif0Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands;
|
|
||||||
if (vif0.cmd) vif0Regs->stat.VPS |= VPS_WAITING; //Otherwise we wait for the data
|
|
||||||
|
|
||||||
if (!istag)
|
|
||||||
{
|
|
||||||
transferred = transferred >> 2;
|
|
||||||
vif0ch->madr +=(transferred << 4);
|
|
||||||
vif0ch->qwc -= transferred;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _VIF0chain()
|
bool _VIF0chain()
|
||||||
{
|
{
|
||||||
u32 *pMem;
|
u32 *pMem;
|
||||||
|
|
|
@ -34,137 +34,6 @@ __forceinline void vif1FLUSH()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VIF1transfer(u32 *data, int size, bool istag)
|
|
||||||
{
|
|
||||||
return vifTransfer1(data, size, istag);
|
|
||||||
|
|
||||||
int ret;
|
|
||||||
int transferred = vif1.vifstalled ? vif1.irqoffset : 0; // irqoffset necessary to add up the right qws, or else will spin (spiderman)
|
|
||||||
|
|
||||||
// Fixme:
|
|
||||||
// VIF1 chain mode seems to be pretty buggy. Keep it in synch with a INTC (page 28, ee user manual) fixes Transformers.
|
|
||||||
// Test chain mode with Harry Potter, Def Jam Fight for New York (+many others, look for flickering graphics).
|
|
||||||
// Mentioned games break by doing this, but they barely work anyway
|
|
||||||
// if ( vif1.vifstalled ) hwIntcIrq(VIF1intc);
|
|
||||||
VIF_LOG("VIF1transfer: size %x (vif1.cmd %x)", size, vif1.cmd);
|
|
||||||
|
|
||||||
vif1.irqoffset = 0;
|
|
||||||
vif1.vifstalled = false;
|
|
||||||
vif1.stallontag = false;
|
|
||||||
vif1.vifpacketsize = size;
|
|
||||||
|
|
||||||
while (vif1.vifpacketsize > 0)
|
|
||||||
{
|
|
||||||
if(vif1Regs->stat.VGW) break;
|
|
||||||
|
|
||||||
if (vif1.cmd)
|
|
||||||
{
|
|
||||||
vif1Regs->stat.VPS = VPS_TRANSFERRING; //Decompression has started
|
|
||||||
|
|
||||||
ret = Vif1TransTLB[vif1.cmd](data);
|
|
||||||
data += ret;
|
|
||||||
vif1.vifpacketsize -= ret;
|
|
||||||
|
|
||||||
//We are once again waiting for a new vifcode as the command has cleared
|
|
||||||
if (vif1.cmd == 0) vif1Regs->stat.VPS = VPS_IDLE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vif1.tag.size != 0) DevCon.Error("no vif1 cmd but tag size is left last cmd read %x", vif1Regs->code);
|
|
||||||
|
|
||||||
if (vif1.irq) break;
|
|
||||||
|
|
||||||
vif1.cmd = (data[0] >> 24);
|
|
||||||
vif1Regs->code = data[0];
|
|
||||||
vif1Regs->stat.VPS |= VPS_DECODING;
|
|
||||||
|
|
||||||
if ((vif1.cmd & 0x60) == 0x60)
|
|
||||||
{
|
|
||||||
vif1UnpackSetup(data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
VIF_LOG("VIFtransfer: cmd %x, num %x, imm %x, size %x", vif1.cmd, (data[0] >> 16) & 0xff, data[0] & 0xffff, vif1.vifpacketsize);
|
|
||||||
|
|
||||||
if ((vif1.cmd & 0x7f) > 0x51)
|
|
||||||
{
|
|
||||||
if (!(vif0Regs->err.ME1)) //Ignore vifcode and tag mismatch error
|
|
||||||
{
|
|
||||||
Console.WriteLn("UNKNOWN VifCmd: %x", vif1.cmd);
|
|
||||||
vif1Regs->stat.ER1 = true;
|
|
||||||
vif1.irq++;
|
|
||||||
}
|
|
||||||
vif1.cmd = 0;
|
|
||||||
}
|
|
||||||
else Vif1CMDTLB[(vif1.cmd & 0x7f)]();
|
|
||||||
}
|
|
||||||
|
|
||||||
++data;
|
|
||||||
--vif1.vifpacketsize;
|
|
||||||
|
|
||||||
if ((vif1.cmd & 0x80))
|
|
||||||
{
|
|
||||||
vif1.cmd &= 0x7f;
|
|
||||||
|
|
||||||
if (!(vif1Regs->err.MII)) //i bit on vifcode and not masked by VIF1_ERR
|
|
||||||
{
|
|
||||||
// Fixme: This seems to be an important part of the VIF1 chain mode issue (see Fixme above :p )
|
|
||||||
//Console.Warning("Interrupt on VIFcmd: %x (INTC_MASK = %x)", vif1.cmd, psHu32(INTC_MASK));
|
|
||||||
VIF_LOG("Interrupt on VIFcmd: %x (INTC_MASK = %x)", vif1.cmd, psHu32(INTC_MASK));
|
|
||||||
++vif1.irq;
|
|
||||||
|
|
||||||
if (istag && vif1.tag.size <= vif1.vifpacketsize) vif1.stallontag = true;
|
|
||||||
|
|
||||||
if (vif1.tag.size == 0) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!vif1.cmd) vif1Regs->stat.VPS = VPS_IDLE;
|
|
||||||
|
|
||||||
if((vif1Regs->stat.VGW) || vif1.vifstalled == true) break;
|
|
||||||
} // End of Transfer loop
|
|
||||||
|
|
||||||
transferred += size - vif1.vifpacketsize;
|
|
||||||
g_vifCycles += (transferred >> 2) * BIAS; /* guessing */
|
|
||||||
vif1.irqoffset = transferred % 4; // cannot lose the offset
|
|
||||||
|
|
||||||
if (vif1.irq && vif1.cmd == 0)
|
|
||||||
{
|
|
||||||
vif1.vifstalled = true;
|
|
||||||
|
|
||||||
if (((vif1Regs->code >> 24) & 0x7f) != 0x7) vif1Regs->stat.VIS = true; // Note: commenting this out fixes WALL-E
|
|
||||||
|
|
||||||
if (vif1ch->qwc == 0 && (vif1.irqoffset == 0 || istag == 1)) vif1.inprogress &= ~0x1;
|
|
||||||
|
|
||||||
// spiderman doesn't break on qw boundaries
|
|
||||||
if (istag) return false;
|
|
||||||
|
|
||||||
transferred = transferred >> 2;
|
|
||||||
vif1ch->madr += (transferred << 4);
|
|
||||||
vif1ch->qwc -= transferred;
|
|
||||||
|
|
||||||
if ((vif1ch->qwc == 0) && (vif1.irqoffset == 0)) vif1.inprogress = 0;
|
|
||||||
//Console.WriteLn("Stall on vif1, FromSPR = %x, Vif1MADR = %x Sif0MADR = %x STADR = %x", psHu32(0x1000d010), vif1ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
vif1Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands;
|
|
||||||
if (vif1.cmd) vif1Regs->stat.VPS = VPS_WAITING; //Otherwise we wait for the data
|
|
||||||
|
|
||||||
if (!istag)
|
|
||||||
{
|
|
||||||
transferred = transferred >> 2;
|
|
||||||
vif1ch->madr +=(transferred << 4);
|
|
||||||
vif1ch->qwc -= transferred;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vif1Regs->stat.VGW) vif1.vifstalled = true;
|
|
||||||
|
|
||||||
if (vif1ch->qwc == 0 && (vif1.irqoffset == 0 || istag == 1)) vif1.inprogress &= ~0x1;
|
|
||||||
|
|
||||||
return (!(vif1.vifstalled));
|
|
||||||
}
|
|
||||||
|
|
||||||
void vif1TransferFromMemory()
|
void vif1TransferFromMemory()
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
|
@ -255,11 +124,6 @@ bool _VIF1chain()
|
||||||
return VIF1transfer(pMem, vif1ch->qwc * 4, false);
|
return VIF1transfer(pMem, vif1ch->qwc * 4, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _chainVIF1()
|
|
||||||
{
|
|
||||||
return vif1.done; // Return Done
|
|
||||||
}
|
|
||||||
|
|
||||||
__forceinline void vif1SetupTransfer()
|
__forceinline void vif1SetupTransfer()
|
||||||
{
|
{
|
||||||
tDMA_TAG *ptag;
|
tDMA_TAG *ptag;
|
||||||
|
|
|
@ -69,6 +69,24 @@ static _f void vuExecMicro(int idx, u32 addr) {
|
||||||
else vu1ExecMicro(addr);
|
else vu1ExecMicro(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 schedulepath3msk = 0;
|
||||||
|
|
||||||
|
void Vif1MskPath3() {
|
||||||
|
|
||||||
|
vif1Regs->mskpath3 = schedulepath3msk & 0x1;
|
||||||
|
//Console.WriteLn("VIF MSKPATH3 %x", vif1Regs->mskpath3);
|
||||||
|
|
||||||
|
if (!vif1Regs->mskpath3) {
|
||||||
|
//Let the Gif know it can transfer again (making sure any vif stall isnt unset prematurely)
|
||||||
|
Path3progress = TRANSFER_MODE;
|
||||||
|
gifRegs->stat.IMT = false;
|
||||||
|
CPU_INT(DMAC_GIF, 4);
|
||||||
|
}
|
||||||
|
else gifRegs->stat.M3P = true;
|
||||||
|
|
||||||
|
schedulepath3msk = 0;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// Vif0/Vif1 Code Implementations
|
// Vif0/Vif1 Code Implementations
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
@ -80,7 +98,6 @@ vifOp(vifCode_Base) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int idx> int __fastcall vifTrans_DirectHL(u32 *data);
|
|
||||||
template<int idx> _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) {
|
template<int idx> _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) {
|
||||||
pass1 {
|
pass1 {
|
||||||
vif1Only();
|
vif1Only();
|
||||||
|
@ -447,107 +464,3 @@ int (__fastcall *vif1Code[128])(int pass, u32 *data) = {
|
||||||
vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Null<1>, /*0x70*/
|
vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Null<1>, /*0x70*/
|
||||||
vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Null<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> /*0x78*/
|
vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Null<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> /*0x78*/
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
// Vif0/Vif1 Code Transfer Interpreter
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Runs the next vifCode if its the Mark command
|
|
||||||
_vifT void runMark(u32* &data) {
|
|
||||||
if (vifX.vifpacketsize && (((data[0]>>24)&0x7f)==7)) {
|
|
||||||
vifX.vifpacketsize--;
|
|
||||||
vifXCode[7](0, data++);
|
|
||||||
DevCon.WriteLn("Vif%d: Running Mark on I-bit", idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns 1 if i-bit && finished vifcode && i-bit not masked && next vifcode != MARK
|
|
||||||
_vifT bool analyzeIbit(u32* &data, int iBit, bool isTag) {
|
|
||||||
if (iBit && !vifX.cmd && !vifXRegs->err.MII) {
|
|
||||||
//DevCon.WriteLn("Vif I-Bit IRQ");
|
|
||||||
vifX.irq++;
|
|
||||||
if (isTag) {
|
|
||||||
//DevCon.WriteLn("Vif isTag Hack!?");
|
|
||||||
vifX.stallontag = true;
|
|
||||||
}
|
|
||||||
runMark<idx>(data);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interprets packet
|
|
||||||
_vifT void vifTransferLoop(u32* &data, bool isTag) {
|
|
||||||
u32& tSize = vifX.tag.size;
|
|
||||||
u32& pSize = vifX.vifpacketsize;
|
|
||||||
int iBit = vifX.cmd >> 7;
|
|
||||||
|
|
||||||
vifXRegs->stat.VPS |= VPS_TRANSFERRING;
|
|
||||||
vifXRegs->stat.ER1 = false;
|
|
||||||
|
|
||||||
while (pSize > 0 && !vifX.vifstalled) {
|
|
||||||
|
|
||||||
if(!vifX.cmd) { // Get new VifCode
|
|
||||||
vifXRegs->code = data[0];
|
|
||||||
vifX.cmd = data[0] >> 24;
|
|
||||||
iBit = data[0] >> 31;
|
|
||||||
|
|
||||||
vifXCode[vifX.cmd & 0x7f](0, data);
|
|
||||||
data++; pSize--;
|
|
||||||
if (analyzeIbit<idx>(data, iBit, isTag)) break;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ret = vifXCode[vifX.cmd & 0x7f](1, data);
|
|
||||||
data += ret;
|
|
||||||
pSize -= ret;
|
|
||||||
if (analyzeIbit<idx>(data, iBit, isTag)) break;
|
|
||||||
}
|
|
||||||
if (vifX.cmd) vifXRegs->stat.VPS = VPS_WAITING;
|
|
||||||
else vifXRegs->stat.VPS = VPS_IDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT _f bool vifTransfer(u32 *data, int size, bool isTag) {
|
|
||||||
// irqoffset necessary to add up the right qws, or else will spin (spiderman)
|
|
||||||
int transferred = vifX.vifstalled ? vifX.irqoffset : 0;
|
|
||||||
|
|
||||||
vifX.irqoffset = 0;
|
|
||||||
vifX.vifstalled = false;
|
|
||||||
vifX.stallontag = false;
|
|
||||||
vifX.vifpacketsize = size;
|
|
||||||
|
|
||||||
vifTransferLoop<idx>(data, isTag);
|
|
||||||
|
|
||||||
transferred += size - vifX.vifpacketsize;
|
|
||||||
g_vifCycles +=(transferred >> 2) * BIAS; /* guessing */
|
|
||||||
vifX.irqoffset = transferred % 4; // cannot lose the offset
|
|
||||||
|
|
||||||
if (!isTag) {
|
|
||||||
transferred = transferred >> 2;
|
|
||||||
vifXch->madr +=(transferred << 4);
|
|
||||||
vifXch->qwc -= transferred;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vifXch->qwc && (!vifX.irqoffset || isTag)) vifX.inprogress &= ~0x1;
|
|
||||||
|
|
||||||
if (vifX.irq && vifX.cmd == 0) {
|
|
||||||
//DevCon.WriteLn("Vif IRQ!");
|
|
||||||
vifX.vifstalled = true;
|
|
||||||
vifXRegs->stat.VIS = true; // Note: commenting this out fixes WALL-E?
|
|
||||||
|
|
||||||
// spiderman doesn't break on qw boundaries
|
|
||||||
if (isTag) return false;
|
|
||||||
|
|
||||||
if (!vifXch->qwc && !vifX.irqoffset) vifX.inprogress = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !vifX.vifstalled;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool vifTransfer0(u32 *data, int size, bool isTag) {
|
|
||||||
return vifTransfer<0>(data, size, isTag);
|
|
||||||
}
|
|
||||||
bool vifTransfer1(u32 *data, int size, bool isTag) {
|
|
||||||
return vifTransfer<1>(data, size, isTag);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,514 +0,0 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
|
||||||
* Copyright (C) 2002-2009 PCSX2 Dev Team
|
|
||||||
*
|
|
||||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
|
||||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
|
||||||
* ation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE. See the GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
|
||||||
* If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "PrecompiledHeader.h"
|
|
||||||
#include "Common.h"
|
|
||||||
#include "GS.h"
|
|
||||||
#include "Gif.h"
|
|
||||||
#include "Vif_Dma.h"
|
|
||||||
#include "newVif.h"
|
|
||||||
#include "VUmicro.h"
|
|
||||||
|
|
||||||
#define vif1Only() { if (!idx) { vifCMD_Null<idx>(); return; } }
|
|
||||||
#define vif1Only_() { if (!idx) { return vifTrans_Null<idx>(NULL); } }
|
|
||||||
|
|
||||||
_vifT void vifCMD_Null();
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
// Vif0/Vif1 Misc Functions
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
|
|
||||||
static _f void vifFlush(int idx) {
|
|
||||||
if (!idx) vif0FLUSH();
|
|
||||||
else vif1FLUSH();
|
|
||||||
}
|
|
||||||
|
|
||||||
static _f void vuExecMicro(int idx, u32 addr) {
|
|
||||||
VURegs* VU = nVif[idx].VU;
|
|
||||||
vifFlush(idx);
|
|
||||||
|
|
||||||
if (VU->vifRegs->itops > (idx ? 0x3ffu : 0xffu)) {
|
|
||||||
Console.WriteLn("VIF%d ITOP overrun! %x", idx, VU->vifRegs->itops);
|
|
||||||
VU->vifRegs->itops &= (idx ? 0x3ffu : 0xffu);
|
|
||||||
}
|
|
||||||
|
|
||||||
VU->vifRegs->itop = VU->vifRegs->itops;
|
|
||||||
|
|
||||||
if (idx) {
|
|
||||||
// in case we're handling a VIF1 execMicro, set the top with the tops value
|
|
||||||
VU->vifRegs->top = VU->vifRegs->tops & 0x3ff;
|
|
||||||
|
|
||||||
// is DBF flag set in VIF_STAT?
|
|
||||||
if (VU->vifRegs->stat.DBF) {
|
|
||||||
// it is, so set tops with base, and clear the stat DBF flag
|
|
||||||
VU->vifRegs->tops = VU->vifRegs->base;
|
|
||||||
VU->vifRegs->stat.DBF = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// it is not, so set tops with base + offset, and set stat DBF flag
|
|
||||||
VU->vifRegs->tops = VU->vifRegs->base + VU->vifRegs->ofst;
|
|
||||||
VU->vifRegs->stat.DBF = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!idx) vu0ExecMicro(addr);
|
|
||||||
else vu1ExecMicro(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 schedulepath3msk = 0;
|
|
||||||
|
|
||||||
void Vif1MskPath3() {
|
|
||||||
|
|
||||||
vif1Regs->mskpath3 = schedulepath3msk & 0x1;
|
|
||||||
//Console.WriteLn("VIF MSKPATH3 %x", vif1Regs->mskpath3);
|
|
||||||
|
|
||||||
if (vif1Regs->mskpath3) {
|
|
||||||
gifRegs->stat.M3P = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//Let the Gif know it can transfer again (making sure any vif stall isnt unset prematurely)
|
|
||||||
Path3progress = TRANSFER_MODE;
|
|
||||||
gifRegs->stat.IMT = false;
|
|
||||||
CPU_INT(DMAC_GIF, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
schedulepath3msk = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
// Vif0/Vif1 Data Transfer Commands
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
|
|
||||||
_vifT int __fastcall vifTrans_Null(u32 *data)
|
|
||||||
{
|
|
||||||
Console.WriteLn("VIF%d Shouldn't go here CMD = %x", idx, vifXRegs->code);
|
|
||||||
vifX.cmd = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT int __fastcall vifTrans_STMask(u32 *data)
|
|
||||||
{
|
|
||||||
vifXRegs->mask = data[0];
|
|
||||||
VIF_LOG("STMASK == %x", vifXRegs->mask);
|
|
||||||
|
|
||||||
vifX.tag.size = 0;
|
|
||||||
vifX.cmd = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT int __fastcall vifTrans_STRow(u32 *data)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
u32* rows = idx ? g_vifmask.Row1 : g_vifmask.Row0;
|
|
||||||
u32* pmem = &vifXRegs->r0 + (vifX.tag.addr << 2);
|
|
||||||
u32* pmem2 = rows + vifX.tag.addr;
|
|
||||||
|
|
||||||
ret = min(4 - vifX.tag.addr, vifX.vifpacketsize);
|
|
||||||
pxAssume(vifX.tag.addr < 4);
|
|
||||||
pxAssume(ret > 0);
|
|
||||||
|
|
||||||
switch (ret) {
|
|
||||||
case 4:
|
|
||||||
pmem[12] = data[3];
|
|
||||||
pmem2[3] = data[3];
|
|
||||||
case 3:
|
|
||||||
pmem[8] = data[2];
|
|
||||||
pmem2[2] = data[2];
|
|
||||||
case 2:
|
|
||||||
pmem[4] = data[1];
|
|
||||||
pmem2[1] = data[1];
|
|
||||||
case 1:
|
|
||||||
pmem[0] = data[0];
|
|
||||||
pmem2[0] = data[0];
|
|
||||||
break;
|
|
||||||
jNO_DEFAULT
|
|
||||||
}
|
|
||||||
|
|
||||||
vifX.tag.addr += ret;
|
|
||||||
vifX.tag.size -= ret;
|
|
||||||
if (!vifX.tag.size) vifX.cmd = 0;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT int __fastcall vifTrans_STCol(u32 *data)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
u32* cols = idx ? g_vifmask.Col1 : g_vifmask.Col0;
|
|
||||||
u32* pmem = &vifXRegs->c0 + (vifX.tag.addr << 2);
|
|
||||||
u32* pmem2 = cols + vifX.tag.addr;
|
|
||||||
ret = min(4 - vifX.tag.addr, vifX.vifpacketsize);
|
|
||||||
|
|
||||||
switch (ret) {
|
|
||||||
case 4:
|
|
||||||
pmem[12] = data[3];
|
|
||||||
pmem2[3] = data[3];
|
|
||||||
case 3:
|
|
||||||
pmem[8] = data[2];
|
|
||||||
pmem2[2] = data[2];
|
|
||||||
case 2:
|
|
||||||
pmem[4] = data[1];
|
|
||||||
pmem2[1] = data[1];
|
|
||||||
case 1:
|
|
||||||
pmem[0] = data[0];
|
|
||||||
pmem2[0] = data[0];
|
|
||||||
break;
|
|
||||||
jNO_DEFAULT
|
|
||||||
}
|
|
||||||
|
|
||||||
vifX.tag.addr += ret;
|
|
||||||
vifX.tag.size -= ret;
|
|
||||||
if (!vifX.tag.size) vifX.cmd = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
_f void _vifTrans_MPG(int idx, u32 addr, u32 *data, int size)
|
|
||||||
{
|
|
||||||
VURegs& VUx = idx ? VU1 : VU0;
|
|
||||||
pxAssume(VUx.Micro > 0);
|
|
||||||
|
|
||||||
if (memcmp(VUx.Micro + addr, data, size << 2)) {
|
|
||||||
if (!idx) CpuVU0->Clear(addr, size << 2); // Clear before writing!
|
|
||||||
else CpuVU1->Clear(addr, size << 2); // Clear before writing!
|
|
||||||
memcpy_fast(VUx.Micro + addr, data, size << 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT int __fastcall vifTrans_MPG(u32 *data)
|
|
||||||
{
|
|
||||||
if (vifX.vifpacketsize < vifX.tag.size) {
|
|
||||||
if((vifX.tag.addr + vifX.vifpacketsize) > (idx ? 0x4000 : 0x1000)) {
|
|
||||||
DevCon.Warning("Vif%d MPG Split Overflow", idx);
|
|
||||||
}
|
|
||||||
_vifTrans_MPG(idx, vifX.tag.addr, data, vifX.vifpacketsize);
|
|
||||||
vifX.tag.addr += vifX.vifpacketsize << 2;
|
|
||||||
vifX.tag.size -= vifX.vifpacketsize;
|
|
||||||
return vifX.vifpacketsize;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int ret;
|
|
||||||
if((vifX.tag.addr + vifX.tag.size) > (idx ? 0x4000 : 0x1000)) {
|
|
||||||
DevCon.Warning("Vif%d MPG Split Overflow", idx);
|
|
||||||
}
|
|
||||||
_vifTrans_MPG(idx, vifX.tag.addr, data, vifX.tag.size);
|
|
||||||
ret = vifX.tag.size;
|
|
||||||
vifX.tag.size = 0;
|
|
||||||
vifX.cmd = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT int __fastcall vifTrans_Unpack(u32 *data)
|
|
||||||
{
|
|
||||||
return nVifUnpack(idx, (u8*)data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dummy GIF-TAG Packet to Guarantee Count = 1
|
|
||||||
extern __aligned16 u32 nloop0_packet[4];
|
|
||||||
static __aligned16 u32 splittransfer[4];
|
|
||||||
static u32 splitptr = 0;
|
|
||||||
|
|
||||||
_vifT int __fastcall vifTrans_DirectHL(u32 *data)
|
|
||||||
{
|
|
||||||
vif1Only_();
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if ((vif1.cmd & 0x7f) == 0x51) {
|
|
||||||
if (gif->chcr.STR && (!vif1Regs->mskpath3 && (Path3progress == IMAGE_MODE))) {
|
|
||||||
vif1Regs->stat.VGW = true; // PATH3 is in image mode, so wait for end of transfer
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gifRegs->stat.APATH |= GIF_APATH2;
|
|
||||||
gifRegs->stat.OPH = true;
|
|
||||||
|
|
||||||
if (splitptr > 0) { // Leftover data from the last packet, filling the rest and sending to the GS
|
|
||||||
|
|
||||||
if ((splitptr < 4) && (vif1.vifpacketsize >= (4 - splitptr))) {
|
|
||||||
while (splitptr < 4) {
|
|
||||||
splittransfer[splitptr++] = (u32)data++;
|
|
||||||
ret++;
|
|
||||||
vif1.tag.size--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Registers::Freeze();
|
|
||||||
// copy 16 bytes the fast way:
|
|
||||||
const u64* src = (u64*)splittransfer[0];
|
|
||||||
GetMTGS().PrepDataPacket(GIF_PATH_2, nloop0_packet, 1);
|
|
||||||
u64* dst = (u64*)GetMTGS().GetDataPacketPtr();
|
|
||||||
dst[0] = src[0];
|
|
||||||
dst[1] = src[1];
|
|
||||||
|
|
||||||
GetMTGS().SendDataPacket();
|
|
||||||
Registers::Thaw();
|
|
||||||
|
|
||||||
if (vif1.tag.size == 0) vif1.cmd = 0;
|
|
||||||
splitptr = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vif1.vifpacketsize < vif1.tag.size) {
|
|
||||||
if (vif1.vifpacketsize < 4 && splitptr != 4) {
|
|
||||||
ret = vif1.vifpacketsize;
|
|
||||||
while (ret > 0) { // Not a full QW left in the buffer, saving left over data
|
|
||||||
splittransfer[splitptr++] = (u32)data++;
|
|
||||||
vif1.tag.size--;
|
|
||||||
ret--;
|
|
||||||
}
|
|
||||||
return vif1.vifpacketsize;
|
|
||||||
}
|
|
||||||
vif1.tag.size -= vif1.vifpacketsize;
|
|
||||||
ret = vif1.vifpacketsize;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gifRegs->stat.clear_flags(GIF_STAT_APATH2 | GIF_STAT_OPH);
|
|
||||||
ret = vif1.tag.size;
|
|
||||||
vif1.tag.size = 0;
|
|
||||||
vif1.cmd = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToDo: ret is guaranteed to be qword aligned ?
|
|
||||||
Registers::Freeze();
|
|
||||||
|
|
||||||
// Round ret up, just in case it's not 128bit aligned.
|
|
||||||
const uint count = GetMTGS().PrepDataPacket(GIF_PATH_2, data, (ret + 3) >> 2);
|
|
||||||
memcpy_fast(GetMTGS().GetDataPacketPtr(), data, count << 4);
|
|
||||||
GetMTGS().SendDataPacket();
|
|
||||||
|
|
||||||
Registers::Thaw();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
// Vif0/Vif1 Commands (VifCodes)
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
|
|
||||||
_vifT void vifCMD_Base()
|
|
||||||
{
|
|
||||||
vif1Only();
|
|
||||||
vif1Regs->base = vif1Regs->code & 0x3ff;
|
|
||||||
vif1.cmd &= ~0x7f;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_DirectHL()
|
|
||||||
{
|
|
||||||
vif1Only();
|
|
||||||
int vifImm = (u16)vif1Regs->code;
|
|
||||||
if(!vifImm) vif1.tag.size = 65536 << 2;
|
|
||||||
else vif1.tag.size = vifImm << 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_FlushE()
|
|
||||||
{
|
|
||||||
vifFlush(idx);
|
|
||||||
vifX.cmd &= ~0x7f;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_Flush()
|
|
||||||
{
|
|
||||||
vif1Only();
|
|
||||||
vifFlush(idx);
|
|
||||||
vifX.cmd &= ~0x7f;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_FlushA()
|
|
||||||
{
|
|
||||||
vif1Only();
|
|
||||||
vifFlush(idx);
|
|
||||||
|
|
||||||
// Gif is already transferring so wait for it.
|
|
||||||
if (((Path3progress != STOPPED_MODE) || !vif1Regs->mskpath3) && gif->chcr.STR) {
|
|
||||||
vif1Regs->stat.VGW = true;
|
|
||||||
CPU_INT(DMAC_GIF, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
vifX.cmd &= ~0x7f;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_ITop()
|
|
||||||
{
|
|
||||||
vifXRegs->itops = vifXRegs->code & 0x3ff;
|
|
||||||
vifX.cmd &= ~0x7f;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_Mark()
|
|
||||||
{
|
|
||||||
vifXRegs->mark = (u16)vifXRegs->code;
|
|
||||||
vifXRegs->stat.MRK = true;
|
|
||||||
vifX.cmd &= ~0x7f;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_MPG()
|
|
||||||
{
|
|
||||||
vifFlush(idx);
|
|
||||||
int vifNum = (u8)(vifXRegs->code >> 16);
|
|
||||||
if(!vifNum) vifNum = 256;
|
|
||||||
|
|
||||||
vifX.tag.addr = (u16)((vifXRegs->code) << 3) & (idx ? 0x3fff : 0xfff);
|
|
||||||
vifX.tag.size = vifNum * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_MSCALF()
|
|
||||||
{
|
|
||||||
vuExecMicro(idx, (u16)(vifXRegs->code) << 3);
|
|
||||||
vifX.cmd &= ~0x7f;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_MSCNT()
|
|
||||||
{
|
|
||||||
vuExecMicro(idx, -1);
|
|
||||||
vifX.cmd &= ~0x7f;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_MskPath3()
|
|
||||||
{
|
|
||||||
vif1Only();
|
|
||||||
if (vif1ch->chcr.STR) {
|
|
||||||
schedulepath3msk = 0x10 | ((vif1Regs->code >> 15) & 0x1);
|
|
||||||
vif1.vifstalled = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
schedulepath3msk = (vif1Regs->code >> 15) & 0x1;
|
|
||||||
Vif1MskPath3();
|
|
||||||
}
|
|
||||||
vif1.cmd &= ~0x7f;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_Nop()
|
|
||||||
{
|
|
||||||
vifX.cmd &= ~0x7f;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_Null() // invalid opcode
|
|
||||||
{
|
|
||||||
// if ME1, then force the vif to interrupt
|
|
||||||
if (!(vifXRegs->err.ME1)) //Ignore vifcode and tag mismatch error
|
|
||||||
{
|
|
||||||
Console.WriteLn("Vif%d: Unknown VifCmd! [%x]", idx, vifX.cmd);
|
|
||||||
vifXRegs->stat.ER1 = true;
|
|
||||||
vifX.irq++;
|
|
||||||
}
|
|
||||||
if (!idx) vifX.cmd &= ~0x7f; // FixMe: vif0/vif1 should do the same thing!?
|
|
||||||
else vifX.cmd = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_Offset()
|
|
||||||
{
|
|
||||||
vif1Only();
|
|
||||||
vif1Regs->stat.DBF = false;
|
|
||||||
vif1Regs->ofst = vif1Regs->code & 0x3ff;
|
|
||||||
vif1Regs->tops = vif1Regs->base;
|
|
||||||
vif1.cmd &= ~0x7f;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_STCycl()
|
|
||||||
{
|
|
||||||
vifXRegs->cycle.cl = (u8)(vifXRegs->code);
|
|
||||||
vifXRegs->cycle.wl = (u8)(vifXRegs->code >> 8);
|
|
||||||
vifX.cmd &= ~0x7f;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_STMask()
|
|
||||||
{
|
|
||||||
vifX.tag.size = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_STMod()
|
|
||||||
{
|
|
||||||
vifXRegs->mode = vifXRegs->code & 0x3;
|
|
||||||
vifX.cmd &= ~0x7f;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vifT void vifCMD_STRowCol() // STROW / STCOL
|
|
||||||
{
|
|
||||||
vifX.tag.addr = 0;
|
|
||||||
vifX.tag.size = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
// Vif0/Vif1 Data Transfer Tables
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
|
|
||||||
int (__fastcall *Vif0TransTLB[128])(u32 *data) = {
|
|
||||||
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x00*/
|
|
||||||
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x08*/
|
|
||||||
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x10*/
|
|
||||||
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x18*/
|
|
||||||
vifTrans_STMask<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x20*/
|
|
||||||
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x28*/
|
|
||||||
vifTrans_STRow<0> , vifTrans_STCol<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x30*/
|
|
||||||
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x38*/
|
|
||||||
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x40*/
|
|
||||||
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_MPG<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x48*/
|
|
||||||
vifTrans_DirectHL<0>, vifTrans_DirectHL<0>, vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x50*/
|
|
||||||
vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0> , vifTrans_Null<0>, /*0x58*/
|
|
||||||
vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Null<0>, /*0x60*/
|
|
||||||
vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0>, /*0x68*/
|
|
||||||
vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Null<0>, /*0x70*/
|
|
||||||
vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Null<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> , vifTrans_Unpack<0> /*0x78*/
|
|
||||||
};
|
|
||||||
|
|
||||||
int (__fastcall *Vif1TransTLB[128])(u32 *data) = {
|
|
||||||
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x00*/
|
|
||||||
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x08*/
|
|
||||||
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x10*/
|
|
||||||
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x18*/
|
|
||||||
vifTrans_STMask<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x20*/
|
|
||||||
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x28*/
|
|
||||||
vifTrans_STRow<1> , vifTrans_STCol<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x30*/
|
|
||||||
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x38*/
|
|
||||||
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x40*/
|
|
||||||
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_MPG<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x48*/
|
|
||||||
vifTrans_DirectHL<1>, vifTrans_DirectHL<1>, vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x50*/
|
|
||||||
vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1> , vifTrans_Null<1>, /*0x58*/
|
|
||||||
vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Null<1>, /*0x60*/
|
|
||||||
vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1>, /*0x68*/
|
|
||||||
vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Null<1>, /*0x70*/
|
|
||||||
vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Null<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> , vifTrans_Unpack<1> /*0x78*/
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
// Vif0/Vif1 CMD Tables
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
|
|
||||||
void (*Vif0CMDTLB[82])() = {
|
|
||||||
vifCMD_Nop<0> , vifCMD_STCycl<0> , vifCMD_Offset<0>, vifCMD_Base<0> , vifCMD_ITop<0> , vifCMD_STMod<0> , vifCMD_MskPath3<0>, vifCMD_Mark<0> , /*0x00*/
|
|
||||||
vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , /*0x08*/
|
|
||||||
vifCMD_FlushE<0> , vifCMD_Flush<0> , vifCMD_Null<0> , vifCMD_FlushA<0>, vifCMD_MSCALF<0>, vifCMD_MSCALF<0>, vifCMD_Null<0> , vifCMD_MSCNT<0>, /*0x10*/
|
|
||||||
vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , /*0x18*/
|
|
||||||
vifCMD_STMask<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , /*0x20*/
|
|
||||||
vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , /*0x28*/
|
|
||||||
vifCMD_STRowCol<0>, vifCMD_STRowCol<0>, vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , /*0x30*/
|
|
||||||
vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , /*0x38*/
|
|
||||||
vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , /*0x40*/
|
|
||||||
vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_MPG<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , vifCMD_Null<0> , /*0x48*/
|
|
||||||
vifCMD_DirectHL<0>, vifCMD_DirectHL<0>
|
|
||||||
};
|
|
||||||
|
|
||||||
void (*Vif1CMDTLB[82])() = {
|
|
||||||
vifCMD_Nop<1> , vifCMD_STCycl<1> , vifCMD_Offset<1>, vifCMD_Base<1> , vifCMD_ITop<1> , vifCMD_STMod<1> , vifCMD_MskPath3<1>, vifCMD_Mark<1> , /*0x00*/
|
|
||||||
vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , /*0x08*/
|
|
||||||
vifCMD_FlushE<1> , vifCMD_Flush<1> , vifCMD_Null<1> , vifCMD_FlushA<1>, vifCMD_MSCALF<1>, vifCMD_MSCALF<1>, vifCMD_Null<1> , vifCMD_MSCNT<1>, /*0x10*/
|
|
||||||
vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , /*0x18*/
|
|
||||||
vifCMD_STMask<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , /*0x20*/
|
|
||||||
vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , /*0x28*/
|
|
||||||
vifCMD_STRowCol<1>, vifCMD_STRowCol<1>, vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , /*0x30*/
|
|
||||||
vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , /*0x38*/
|
|
||||||
vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , /*0x40*/
|
|
||||||
vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_MPG<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , vifCMD_Null<1> , /*0x48*/
|
|
||||||
vifCMD_DirectHL<1>, vifCMD_DirectHL<1>
|
|
||||||
};
|
|
|
@ -60,10 +60,8 @@ extern void Vif1MskPath3();
|
||||||
extern void vif1Write32(u32 mem, u32 value);
|
extern void vif1Write32(u32 mem, u32 value);
|
||||||
extern void vif1Reset();
|
extern void vif1Reset();
|
||||||
|
|
||||||
extern void (*Vif0CMDTLB[82])();
|
extern int (__fastcall *vif0Code[128])(int pass, u32 *data);
|
||||||
extern void (*Vif1CMDTLB[82])();
|
extern int (__fastcall *vif1Code[128])(int pass, u32 *data);
|
||||||
extern int (__fastcall *Vif0TransTLB[128])(u32 *data);
|
|
||||||
extern int (__fastcall *Vif1TransTLB[128])(u32 *data);
|
|
||||||
|
|
||||||
__forceinline static int _limit(int a, int max)
|
__forceinline static int _limit(int a, int max)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
|
* Copyright (C) 2002-2009 PCSX2 Dev Team
|
||||||
|
*
|
||||||
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||||
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||||
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PrecompiledHeader.h"
|
||||||
|
#include "Common.h"
|
||||||
|
#include "Vif_Dma.h"
|
||||||
|
#include "newVif.h"
|
||||||
|
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
// VifCode Transfer Interpreter (Vif0/Vif1)
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Runs the next vifCode if its the Mark command
|
||||||
|
_vifT void runMark(u32* &data) {
|
||||||
|
if (vifX.vifpacketsize && (((data[0]>>24)&0x7f)==7)) {
|
||||||
|
vifX.vifpacketsize--;
|
||||||
|
vifXCode[7](0, data++);
|
||||||
|
DevCon.WriteLn("Vif%d: Running Mark on I-bit", idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns 1 if i-bit && finished vifcode && i-bit not masked && next vifcode != MARK
|
||||||
|
_vifT bool analyzeIbit(u32* &data, int iBit, bool isTag) {
|
||||||
|
if (iBit && !vifX.cmd && !vifXRegs->err.MII) {
|
||||||
|
//DevCon.WriteLn("Vif I-Bit IRQ");
|
||||||
|
vifX.irq++;
|
||||||
|
if (isTag) {
|
||||||
|
//DevCon.WriteLn("Vif isTag Hack!?");
|
||||||
|
vifX.stallontag = true;
|
||||||
|
}
|
||||||
|
runMark<idx>(data);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interprets packet
|
||||||
|
_vifT void vifTransferLoop(u32* &data, bool isTag) {
|
||||||
|
u32& tSize = vifX.tag.size;
|
||||||
|
u32& pSize = vifX.vifpacketsize;
|
||||||
|
int iBit = vifX.cmd >> 7;
|
||||||
|
|
||||||
|
vifXRegs->stat.VPS |= VPS_TRANSFERRING;
|
||||||
|
vifXRegs->stat.ER1 = false;
|
||||||
|
|
||||||
|
while (pSize > 0 && !vifX.vifstalled) {
|
||||||
|
|
||||||
|
if(!vifX.cmd) { // Get new VifCode
|
||||||
|
vifXRegs->code = data[0];
|
||||||
|
vifX.cmd = data[0] >> 24;
|
||||||
|
iBit = data[0] >> 31;
|
||||||
|
|
||||||
|
vifXCode[vifX.cmd & 0x7f](0, data);
|
||||||
|
data++; pSize--;
|
||||||
|
if (analyzeIbit<idx>(data, iBit, isTag)) break;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = vifXCode[vifX.cmd & 0x7f](1, data);
|
||||||
|
data += ret;
|
||||||
|
pSize -= ret;
|
||||||
|
if (analyzeIbit<idx>(data, iBit, isTag)) break;
|
||||||
|
}
|
||||||
|
if (vifX.cmd) vifXRegs->stat.VPS = VPS_WAITING;
|
||||||
|
else vifXRegs->stat.VPS = VPS_IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_vifT _f bool vifTransfer(u32 *data, int size, bool isTag) {
|
||||||
|
// irqoffset necessary to add up the right qws, or else will spin (spiderman)
|
||||||
|
int transferred = vifX.vifstalled ? vifX.irqoffset : 0;
|
||||||
|
|
||||||
|
vifX.irqoffset = 0;
|
||||||
|
vifX.vifstalled = false;
|
||||||
|
vifX.stallontag = false;
|
||||||
|
vifX.vifpacketsize = size;
|
||||||
|
|
||||||
|
vifTransferLoop<idx>(data, isTag);
|
||||||
|
|
||||||
|
transferred += size - vifX.vifpacketsize;
|
||||||
|
g_vifCycles +=(transferred >> 2) * BIAS; /* guessing */
|
||||||
|
vifX.irqoffset = transferred % 4; // cannot lose the offset
|
||||||
|
|
||||||
|
if (!isTag) {
|
||||||
|
transferred = transferred >> 2;
|
||||||
|
vifXch->madr +=(transferred << 4);
|
||||||
|
vifXch->qwc -= transferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vifXch->qwc && (!vifX.irqoffset || isTag)) vifX.inprogress &= ~0x1;
|
||||||
|
|
||||||
|
if (vifX.irq && vifX.cmd == 0) {
|
||||||
|
//DevCon.WriteLn("Vif IRQ!");
|
||||||
|
vifX.vifstalled = true;
|
||||||
|
vifXRegs->stat.VIS = true; // Note: commenting this out fixes WALL-E?
|
||||||
|
|
||||||
|
// spiderman doesn't break on qw boundaries
|
||||||
|
if (isTag) return false;
|
||||||
|
|
||||||
|
if (!vifXch->qwc && !vifX.irqoffset) vifX.inprogress = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !vifX.vifstalled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VIF0transfer(u32 *data, int size, bool istag) {
|
||||||
|
return vifTransfer<0>(data, size, istag);
|
||||||
|
}
|
||||||
|
bool VIF1transfer(u32 *data, int size, bool istag) {
|
||||||
|
return vifTransfer<1>(data, size, istag);
|
||||||
|
}
|
|
@ -829,11 +829,11 @@
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\Vif_Commands.cpp"
|
RelativePath="..\..\Vif_Dma.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\Vif_Dma.h"
|
RelativePath="..\..\Vif_Transfer.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<Filter
|
<Filter
|
||||||
|
|
Loading…
Reference in New Issue