mirror of https://github.com/PCSX2/pcsx2.git
GIF: Implement GIF FIFO - Enabled as hack as it is slow
-Fixes DJ Hero, Wallace & Gromit (properly), Hot Wheels (closer)
This commit is contained in:
parent
d89b09427f
commit
0b83b849e7
|
@ -55,7 +55,7 @@ enum GamefixId
|
||||||
Fix_DMABusy,
|
Fix_DMABusy,
|
||||||
Fix_VIFFIFO,
|
Fix_VIFFIFO,
|
||||||
Fix_VIF1Stall,
|
Fix_VIF1Stall,
|
||||||
Fix_GIFReverse,
|
Fix_GIFFIFO,
|
||||||
Fix_FMVinSoftware,
|
Fix_FMVinSoftware,
|
||||||
Fix_GoemonTlbMiss,
|
Fix_GoemonTlbMiss,
|
||||||
Fix_ScarfaceIbit,
|
Fix_ScarfaceIbit,
|
||||||
|
@ -343,7 +343,7 @@ struct Pcsx2Config
|
||||||
DMABusyHack :1, // Denies writes to the DMAC when it's busy. This is correct behaviour but bad timing can cause problems.
|
DMABusyHack :1, // Denies writes to the DMAC when it's busy. This is correct behaviour but bad timing can cause problems.
|
||||||
VIFFIFOHack :1, // Pretends to fill the non-existant VIF FIFO Buffer.
|
VIFFIFOHack :1, // Pretends to fill the non-existant VIF FIFO Buffer.
|
||||||
VIF1StallHack :1, // Like above, processes FIFO data before the stall is allowed (to make sure data goes over).
|
VIF1StallHack :1, // Like above, processes FIFO data before the stall is allowed (to make sure data goes over).
|
||||||
GIFReverseHack :1, // Allows PATH3 to continue even if the FIFO is reversed.
|
GIFFIFOHack :1, // Enabled the GIF FIFO (more correct but slower)
|
||||||
FMVinSoftwareHack:1, // Toggle in and out of software rendering when an FMV runs.
|
FMVinSoftwareHack:1, // Toggle in and out of software rendering when an FMV runs.
|
||||||
GoemonTlbHack :1, // Gomeon tlb miss hack. The game need to access unmapped virtual address. Instead to handle it as exception, tlb are preloaded at startup
|
GoemonTlbHack :1, // Gomeon tlb miss hack. The game need to access unmapped virtual address. Instead to handle it as exception, tlb are preloaded at startup
|
||||||
ScarfaceIbit :1; // Scarface I bit hack. Needed to stop constant VU recompilation
|
ScarfaceIbit :1; // Scarface I bit hack. Needed to stop constant VU recompilation
|
||||||
|
@ -525,7 +525,7 @@ TraceLogFilters& SetTraceConfig();
|
||||||
#define CHECK_DMABUSYHACK (EmuConfig.Gamefixes.DMABusyHack) // Denies writes to the DMAC when it's busy. This is correct behaviour but bad timing can cause problems.
|
#define CHECK_DMABUSYHACK (EmuConfig.Gamefixes.DMABusyHack) // Denies writes to the DMAC when it's busy. This is correct behaviour but bad timing can cause problems.
|
||||||
#define CHECK_VIFFIFOHACK (EmuConfig.Gamefixes.VIFFIFOHack) // Pretends to fill the non-existant VIF FIFO Buffer.
|
#define CHECK_VIFFIFOHACK (EmuConfig.Gamefixes.VIFFIFOHack) // Pretends to fill the non-existant VIF FIFO Buffer.
|
||||||
#define CHECK_VIF1STALLHACK (EmuConfig.Gamefixes.VIF1StallHack) // Like above, processes FIFO data before the stall is allowed (to make sure data goes over).
|
#define CHECK_VIF1STALLHACK (EmuConfig.Gamefixes.VIF1StallHack) // Like above, processes FIFO data before the stall is allowed (to make sure data goes over).
|
||||||
#define CHECK_GIFREVERSEHACK (EmuConfig.Gamefixes.GIFReverseHack) // Allows PATH3 to continue even if the FIFO is reversed.
|
#define CHECK_GIFFIFOHACK (EmuConfig.Gamefixes.GIFFIFOHack) // Enabled the GIF FIFO (more correct but slower)
|
||||||
#define CHECK_FMVINSOFTWAREHACK (EmuConfig.Gamefixes.FMVinSoftwareHack) // Toggle in and out of software rendering when an FMV runs.
|
#define CHECK_FMVINSOFTWAREHACK (EmuConfig.Gamefixes.FMVinSoftwareHack) // Toggle in and out of software rendering when an FMV runs.
|
||||||
//------------ Advanced Options!!! ---------------
|
//------------ Advanced Options!!! ---------------
|
||||||
#define CHECK_VU_OVERFLOW (EmuConfig.Cpu.Recompiler.vuOverflow)
|
#define CHECK_VU_OVERFLOW (EmuConfig.Cpu.Recompiler.vuOverflow)
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
#include "GS.h"
|
#include "GS.h"
|
||||||
|
#include "Gif.h"
|
||||||
#include "Gif_Unit.h"
|
#include "Gif_Unit.h"
|
||||||
#include "Vif.h"
|
#include "Vif.h"
|
||||||
#include "Vif_Dma.h"
|
#include "Vif_Dma.h"
|
||||||
|
@ -128,20 +129,28 @@ void __fastcall WriteFIFO_VIF1(const mem128_t *value)
|
||||||
void __fastcall WriteFIFO_GIF(const mem128_t *value)
|
void __fastcall WriteFIFO_GIF(const mem128_t *value)
|
||||||
{
|
{
|
||||||
GUNIT_LOG("WriteFIFO_GIF()");
|
GUNIT_LOG("WriteFIFO_GIF()");
|
||||||
gifUnit.TransferGSPacketData(GIF_TRANS_FIFO, (u8*)value, 16);
|
if (CHECK_GIFFIFOHACK) {
|
||||||
|
gif_fifo.write((u32*)value, 1);
|
||||||
|
|
||||||
if(gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT)
|
gif_fifo.read(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gifUnit.TransferGSPacketData(GIF_TRANS_FIFO, (u8*)value, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT)
|
||||||
gifUnit.gifPath[GIF_PATH_3].state = GIF_PATH_IDLE;
|
gifUnit.gifPath[GIF_PATH_3].state = GIF_PATH_IDLE;
|
||||||
|
|
||||||
if( gifRegs.stat.APATH == 3 )
|
if (gifRegs.stat.APATH == 3)
|
||||||
{
|
{
|
||||||
gifRegs.stat.APATH = 0;
|
gifRegs.stat.APATH = 0;
|
||||||
gifRegs.stat.OPH = 0;
|
gifRegs.stat.OPH = 0;
|
||||||
|
|
||||||
if(gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE || gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT)
|
if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE || gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT)
|
||||||
{
|
{
|
||||||
if(gifUnit.checkPaths(1,1,0)) gifUnit.Execute(false, true);
|
if (gifUnit.checkPaths(1, 1, 0)) gifUnit.Execute(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
167
pcsx2/Gif.cpp
167
pcsx2/Gif.cpp
|
@ -31,10 +31,86 @@ static u32 gscycles = 0, prevcycles = 0, mfifocycles = 0;
|
||||||
static u32 gifqwc = 0;
|
static u32 gifqwc = 0;
|
||||||
static bool gifmfifoirq = false;
|
static bool gifmfifoirq = false;
|
||||||
|
|
||||||
|
__aligned16 GIF_Fifo gif_fifo;
|
||||||
|
|
||||||
static __fi void clearFIFOstuff(bool full) {
|
static __fi void clearFIFOstuff(bool full) {
|
||||||
CSRreg.FIFO = full ? CSR_FIFO_FULL : CSR_FIFO_EMPTY;
|
CSRreg.FIFO = full ? CSR_FIFO_FULL : CSR_FIFO_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GIF_Fifo::init()
|
||||||
|
{
|
||||||
|
readpos = 0;
|
||||||
|
writepos = 0;
|
||||||
|
memzero(data);
|
||||||
|
memzero(readdata);
|
||||||
|
gifRegs.stat.FQC = 0;
|
||||||
|
CSRreg.FIFO = CSR_FIFO_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int GIF_Fifo::write(u32* pMem, int size)
|
||||||
|
{
|
||||||
|
int transsize;
|
||||||
|
int firsttrans = std::min(size, 16 - (int)gifRegs.stat.FQC);
|
||||||
|
|
||||||
|
gifRegs.stat.FQC += firsttrans;
|
||||||
|
transsize = firsttrans;
|
||||||
|
|
||||||
|
|
||||||
|
while (transsize-- > 0)
|
||||||
|
{
|
||||||
|
CopyQWC(&data[writepos], pMem);
|
||||||
|
writepos = (writepos + 4) & 63;
|
||||||
|
pMem += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return firsttrans;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GIF_Fifo::read(bool calledFromDMA)
|
||||||
|
{
|
||||||
|
int valueWritePos = 0;
|
||||||
|
uint sizeRead;
|
||||||
|
uint fifoSize = gifRegs.stat.FQC;
|
||||||
|
int oldReadPos = readpos;
|
||||||
|
|
||||||
|
if (!gifUnit.CanDoPath3())
|
||||||
|
{
|
||||||
|
//DevCon.Warning("P3 Masked");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (gifRegs.stat.FQC == 0)
|
||||||
|
{
|
||||||
|
//If the GIF isn't stalled and it is waiting to go, fire it off (usually after a path3 mask)
|
||||||
|
if (gifch.chcr.STR == true && !(cpuRegs.interrupt & (1 << DMAC_GIF)) && calledFromDMA == false) {
|
||||||
|
CPU_INT(DMAC_GIF, 16);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
valueWritePos = 0;
|
||||||
|
|
||||||
|
while (gifRegs.stat.FQC) {
|
||||||
|
CopyQWC(&readdata[valueWritePos], &data[readpos]);
|
||||||
|
readpos = (readpos + 4) & 63;
|
||||||
|
valueWritePos = (valueWritePos + 4) & 63;
|
||||||
|
gifRegs.stat.FQC--;
|
||||||
|
}
|
||||||
|
|
||||||
|
sizeRead = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, (u8*)&readdata[0], fifoSize * 16) / 16; //returns the size actually read
|
||||||
|
|
||||||
|
if (sizeRead < fifoSize) {
|
||||||
|
readpos = (oldReadPos + (sizeRead * 4)) & 63; //if we read less than what was in the fifo, move the read position back
|
||||||
|
gifRegs.stat.FQC = fifoSize - sizeRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (calledFromDMA == false) {
|
||||||
|
CPU_INT(DMAC_GIF, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
return gifRegs.stat.FQC;
|
||||||
|
}
|
||||||
|
|
||||||
void incGifChAddr(u32 qwc) {
|
void incGifChAddr(u32 qwc) {
|
||||||
if (gifch.chcr.STR) {
|
if (gifch.chcr.STR) {
|
||||||
gifch.madr += qwc * 16;
|
gifch.madr += qwc * 16;
|
||||||
|
@ -44,23 +120,26 @@ void incGifChAddr(u32 qwc) {
|
||||||
else DevCon.Error("incGifAddr() Error!");
|
else DevCon.Error("incGifAddr() Error!");
|
||||||
}
|
}
|
||||||
|
|
||||||
__fi void gifInterrupt()
|
__fi void gifCheckPathStatus() {
|
||||||
{
|
if (gifRegs.stat.APATH == 3)
|
||||||
GIF_LOG("gifInterrupt caught!");
|
|
||||||
if( gifRegs.stat.APATH == 3 )
|
|
||||||
{
|
{
|
||||||
gifRegs.stat.APATH = 0;
|
gifRegs.stat.APATH = 0;
|
||||||
gifRegs.stat.OPH = 0;
|
gifRegs.stat.OPH = 0;
|
||||||
if(gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE || gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT)
|
if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE || gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT)
|
||||||
{
|
{
|
||||||
if(gifUnit.checkPaths(1,1,0)) gifUnit.Execute(false, true);
|
if (gifUnit.checkPaths(1, 1, 0)) gifUnit.Execute(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Required for Path3 Masking timing!
|
//Required for Path3 Masking timing!
|
||||||
if(gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT)
|
if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT)
|
||||||
gifUnit.gifPath[GIF_PATH_3].state = GIF_PATH_IDLE;
|
gifUnit.gifPath[GIF_PATH_3].state = GIF_PATH_IDLE;
|
||||||
|
}
|
||||||
|
__fi void gifInterrupt()
|
||||||
|
{
|
||||||
|
GIF_LOG("gifInterrupt caught!");
|
||||||
|
gifCheckPathStatus();
|
||||||
|
|
||||||
if(gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE)
|
if(gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE)
|
||||||
{
|
{
|
||||||
|
@ -85,8 +164,26 @@ __fi void gifInterrupt()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CHECK_GIFFIFOHACK) {
|
||||||
|
|
||||||
|
if (gif_fifo.read(true)) {
|
||||||
|
CPU_INT(DMAC_GIF, 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gifUnit.CanDoPath3() && gifRegs.stat.FQC == 16)
|
||||||
|
{
|
||||||
|
if (gifch.qwc > 0 || gspath3done == false) {
|
||||||
|
if (!gifUnit.Path3Masked()) {
|
||||||
|
CPU_INT(DMAC_GIF, 128);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (gifUnit.gsSIGNAL.queued) {
|
if (gifUnit.gsSIGNAL.queued) {
|
||||||
//DevCon.WriteLn("Path 3 Paused");
|
GIF_LOG("Path 3 Paused");
|
||||||
CPU_INT(DMAC_GIF, 128);
|
CPU_INT(DMAC_GIF, 128);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -101,16 +198,30 @@ __fi void gifInterrupt()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GIFdma();
|
GIFdma();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gifRegs.stat.FQC = 0;
|
//Double check as we might have read the fifo as it's ending the DMA
|
||||||
|
gifCheckPathStatus();
|
||||||
|
|
||||||
|
if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE)
|
||||||
|
{
|
||||||
|
if (vif1Regs.stat.VGW)
|
||||||
|
{
|
||||||
|
//Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back.
|
||||||
|
if (!(cpuRegs.interrupt & (1 << DMAC_VIF1))) {
|
||||||
|
CPU_INT(DMAC_VIF1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!CHECK_GIFFIFOHACK)gifRegs.stat.FQC = 0;
|
||||||
gscycles = 0;
|
gscycles = 0;
|
||||||
gspath3done = false;
|
gspath3done = false;
|
||||||
gifch.chcr.STR = false;
|
gifch.chcr.STR = false;
|
||||||
clearFIFOstuff(false);
|
clearFIFOstuff(false);
|
||||||
hwDmacIrq(DMAC_GIF);
|
hwDmacIrq(DMAC_GIF);
|
||||||
DMA_LOG("GIF DMA End");
|
GIF_LOG("GIF DMA End QWC in fifo %x APATH = %x OPH = %x state = %x", gifRegs.stat.FQC, gifRegs.stat.APATH, gifRegs.stat.OPH, gifUnit.gifPath[GIF_PATH_3].state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 WRITERING_DMA(u32 *pMem, u32 qwc) {
|
static u32 WRITERING_DMA(u32 *pMem, u32 qwc) {
|
||||||
|
@ -124,7 +235,13 @@ static u32 WRITERING_DMA(u32 *pMem, u32 qwc) {
|
||||||
else
|
else
|
||||||
qwc = std::min(qwc, 8u);
|
qwc = std::min(qwc, 8u);
|
||||||
}
|
}
|
||||||
uint size = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, (u8*)pMem, qwc*16) / 16;
|
uint size;
|
||||||
|
if (CHECK_GIFFIFOHACK) {
|
||||||
|
size = gif_fifo.write(pMem, qwc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
size = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, (u8*)pMem, qwc * 16) / 16;
|
||||||
|
}
|
||||||
incGifChAddr(size);
|
incGifChAddr(size);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
@ -194,12 +311,15 @@ static __fi tDMA_TAG* ReadTag2()
|
||||||
|
|
||||||
bool CheckPaths(EE_EventType Channel) {
|
bool CheckPaths(EE_EventType Channel) {
|
||||||
// Can't do Path 3, so try dma again later...
|
// Can't do Path 3, so try dma again later...
|
||||||
if(!gifUnit.CanDoPath3()) {
|
if (!CHECK_GIFFIFOHACK) {
|
||||||
if(!gifUnit.Path3Masked())
|
if (!gifUnit.CanDoPath3()) {
|
||||||
{
|
if (!gifUnit.Path3Masked())
|
||||||
CPU_INT(Channel, 128);
|
{
|
||||||
|
GIF_LOG("Path3 stalled");
|
||||||
|
CPU_INT(Channel, 128);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -232,7 +352,7 @@ void GIFdma()
|
||||||
if (ptag == NULL) return;
|
if (ptag == NULL) return;
|
||||||
//DevCon.Warning("GIF Reading Tag MSK = %x", vif1Regs.mskpath3);
|
//DevCon.Warning("GIF Reading Tag MSK = %x", vif1Regs.mskpath3);
|
||||||
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr);
|
GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr);
|
||||||
gifRegs.stat.FQC = std::min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
if (!CHECK_GIFFIFOHACK)gifRegs.stat.FQC = std::min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||||
if (dmacRegs.ctrl.STD == STD_GIF)
|
if (dmacRegs.ctrl.STD == STD_GIF)
|
||||||
{
|
{
|
||||||
// there are still bugs, need to also check if gifch.madr +16*qwc >= stadr, if not, stall
|
// there are still bugs, need to also check if gifch.madr +16*qwc >= stadr, if not, stall
|
||||||
|
@ -259,7 +379,7 @@ void GIFdma()
|
||||||
}
|
}
|
||||||
|
|
||||||
clearFIFOstuff(true);
|
clearFIFOstuff(true);
|
||||||
gifRegs.stat.FQC = std::min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
if (!CHECK_GIFFIFOHACK)gifRegs.stat.FQC = std::min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||||
|
|
||||||
#if USE_OLD_GIF == 1 // ...
|
#if USE_OLD_GIF == 1 // ...
|
||||||
if (vif1Regs.mskpath3 || gifRegs.mode.M3R) {
|
if (vif1Regs.mskpath3 || gifRegs.mode.M3R) {
|
||||||
|
@ -276,7 +396,7 @@ void GIFdma()
|
||||||
// Transfer Dn_QWC from Dn_MADR to GIF
|
// Transfer Dn_QWC from Dn_MADR to GIF
|
||||||
if (gifch.qwc > 0) // Normal Mode
|
if (gifch.qwc > 0) // Normal Mode
|
||||||
{
|
{
|
||||||
gifRegs.stat.FQC = std::min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
if (!CHECK_GIFFIFOHACK)gifRegs.stat.FQC = std::min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||||
|
|
||||||
if (!CheckPaths(DMAC_GIF)) return;
|
if (!CheckPaths(DMAC_GIF)) return;
|
||||||
|
|
||||||
|
@ -287,7 +407,7 @@ void GIFdma()
|
||||||
|
|
||||||
prevcycles = 0;
|
prevcycles = 0;
|
||||||
CPU_INT(DMAC_GIF, gscycles);
|
CPU_INT(DMAC_GIF, gscycles);
|
||||||
gifRegs.stat.FQC = std::min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3]
|
if (!CHECK_GIFFIFOHACK)gifRegs.stat.FQC = std::min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3]
|
||||||
}
|
}
|
||||||
|
|
||||||
void dmaGIF()
|
void dmaGIF()
|
||||||
|
@ -298,7 +418,7 @@ void dmaGIF()
|
||||||
|
|
||||||
gspath3done = false; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :)
|
gspath3done = false; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :)
|
||||||
|
|
||||||
gifRegs.stat.FQC |= 0x10; // hack ;)
|
if (!CHECK_GIFFIFOHACK)gifRegs.stat.FQC |= 0x10; // hack ;)
|
||||||
|
|
||||||
if (gifch.chcr.MOD == NORMAL_MODE) { //Else it really is a normal transfer and we want to quit, else it gets confused with chains
|
if (gifch.chcr.MOD == NORMAL_MODE) { //Else it really is a normal transfer and we want to quit, else it gets confused with chains
|
||||||
gspath3done = true;
|
gspath3done = true;
|
||||||
|
@ -437,7 +557,7 @@ void mfifoGIFtransfer(int qwc)
|
||||||
tDMA_TAG *ptag;
|
tDMA_TAG *ptag;
|
||||||
mfifocycles = 0;
|
mfifocycles = 0;
|
||||||
gifmfifoirq = false;
|
gifmfifoirq = false;
|
||||||
|
DevCon.Warning("GIF MFIFO");
|
||||||
if (qwc > 0 ) {
|
if (qwc > 0 ) {
|
||||||
if ((gifstate & GIF_STATE_EMPTY)) {
|
if ((gifstate & GIF_STATE_EMPTY)) {
|
||||||
if(gifch.chcr.STR && !(cpuRegs.interrupt & (1<<DMAC_MFIFO_GIF)))
|
if(gifch.chcr.STR && !(cpuRegs.interrupt & (1<<DMAC_MFIFO_GIF)))
|
||||||
|
@ -606,4 +726,5 @@ void SaveStateBase::gifDmaFreeze() {
|
||||||
Freeze(gifqwc);
|
Freeze(gifqwc);
|
||||||
Freeze(gspath3done);
|
Freeze(gspath3done);
|
||||||
Freeze(gscycles);
|
Freeze(gscycles);
|
||||||
|
Freeze(gif_fifo);
|
||||||
}
|
}
|
||||||
|
|
14
pcsx2/Gif.h
14
pcsx2/Gif.h
|
@ -93,6 +93,20 @@ enum gifstate_t {
|
||||||
GIF_STATE_EMPTY = 0x10
|
GIF_STATE_EMPTY = 0x10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GIF_Fifo
|
||||||
|
{
|
||||||
|
unsigned int data[64]; //16 QW FIFO
|
||||||
|
unsigned int readdata[64]; //16 QW Inline for reading
|
||||||
|
int readpos, writepos;
|
||||||
|
|
||||||
|
int write(u32* pMem, int size);
|
||||||
|
int read(bool calledFromDMA = false);
|
||||||
|
|
||||||
|
void init();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern GIF_Fifo gif_fifo;
|
||||||
|
|
||||||
union tGIF_CTRL
|
union tGIF_CTRL
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -593,6 +593,9 @@ struct Gif_Unit {
|
||||||
}
|
}
|
||||||
//DevCon.WriteLn("Adding GS Packet for path %d", stat.APATH);
|
//DevCon.WriteLn("Adding GS Packet for path %d", stat.APATH);
|
||||||
AddCompletedGSPacket(gsPack, (GIF_PATH)(stat.APATH-1));
|
AddCompletedGSPacket(gsPack, (GIF_PATH)(stat.APATH-1));
|
||||||
|
/*if (path.curSize == path.curOffset)
|
||||||
|
curPath = 0;*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gsSIGNAL.queued && !gifPath[0].isDone()) {
|
if (!gsSIGNAL.queued && !gifPath[0].isDone()) {
|
||||||
|
@ -650,13 +653,13 @@ struct Gif_Unit {
|
||||||
bool CanDoPath2HL() const {
|
bool CanDoPath2HL() const {
|
||||||
return (stat.APATH == 0 || stat.APATH == 2) && CanDoGif();
|
return (stat.APATH == 0 || stat.APATH == 2) && CanDoGif();
|
||||||
}
|
}
|
||||||
// Gif DMA - CHECK_GIFREVERSEHACK is a hack for Hot Wheels.
|
// Gif DMA
|
||||||
bool CanDoPath3() const {
|
bool CanDoPath3() const {
|
||||||
return((stat.APATH == 0 && !Path3Masked()) || stat.APATH == 3) && CanDoGif();
|
return((stat.APATH == 0 && !Path3Masked()) || stat.APATH == 3) && CanDoGif();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanDoP3Slice()const { return stat.IMT == 1 && gifPath[GIF_PATH_3].state == GIF_PATH_IMAGE; }
|
bool CanDoP3Slice()const { return stat.IMT == 1 && gifPath[GIF_PATH_3].state == GIF_PATH_IMAGE; }
|
||||||
bool CanDoGif() const { return stat.PSE == 0 && (CHECK_GIFREVERSEHACK ? 1 : stat.DIR == 0) && gsSIGNAL.queued == 0; }
|
bool CanDoGif() const { return stat.PSE == 0 && stat.DIR == 0 && gsSIGNAL.queued == 0; }
|
||||||
//Mask stops the next packet which hasnt started from transferring
|
//Mask stops the next packet which hasnt started from transferring
|
||||||
bool Path3Masked() const { return ((stat.M3R || stat.M3P) && (gifPath[GIF_PATH_3].state == GIF_PATH_IDLE || gifPath[GIF_PATH_3].state == GIF_PATH_WAIT)); }
|
bool Path3Masked() const { return ((stat.M3R || stat.M3P) && (gifPath[GIF_PATH_3].state == GIF_PATH_IDLE || gifPath[GIF_PATH_3].state == GIF_PATH_WAIT)); }
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ void hwReset()
|
||||||
ipuReset();
|
ipuReset();
|
||||||
vif0Reset();
|
vif0Reset();
|
||||||
vif1Reset();
|
vif1Reset();
|
||||||
|
gif_fifo.init();
|
||||||
// needed for legacy DMAC
|
// needed for legacy DMAC
|
||||||
ipuDmaReset();
|
ipuDmaReset();
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,14 +185,14 @@ mem32_t __fastcall _hwRead32(u32 mem)
|
||||||
if(mem == (D1_CHCR + 0x10) && CHECK_VIFFIFOHACK)
|
if(mem == (D1_CHCR + 0x10) && CHECK_VIFFIFOHACK)
|
||||||
return psHu32(mem) + (vif1ch.qwc * 16);
|
return psHu32(mem) + (vif1ch.qwc * 16);
|
||||||
|
|
||||||
if((mem == GIF_CHCR) && !vif1ch.chcr.STR && gifRegs.stat.M3P && gifRegs.stat.APATH != 3)
|
/*if((mem == GIF_CHCR) && !vif1ch.chcr.STR && gifRegs.stat.M3P && gifRegs.stat.APATH != 3)
|
||||||
{
|
{
|
||||||
//Hack for Wallace and Gromit Curse Project Zoo - Enabled the mask, then starts a new
|
//Hack for Wallace and Gromit Curse Project Zoo - Enabled the mask, then starts a new
|
||||||
//GIF DMA, the mask never comes off and it won't proceed until this is unset.
|
//GIF DMA, the mask never comes off and it won't proceed until this is unset.
|
||||||
//Unsetting it works too but messes up other PATH3 games.
|
//Unsetting it works too but messes up other PATH3 games.
|
||||||
//If STR is already unset, it won't make the slightest difference.
|
//If STR is already unset, it won't make the slightest difference.
|
||||||
return (psHu32(mem) & ~0x100);
|
return (psHu32(mem) & ~0x100);
|
||||||
}
|
}*/
|
||||||
return psHu32(mem);
|
return psHu32(mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -249,7 +249,7 @@ const wxChar *const tbl_GamefixNames[] =
|
||||||
L"DMABusy",
|
L"DMABusy",
|
||||||
L"VIFFIFO",
|
L"VIFFIFO",
|
||||||
L"VIF1Stall",
|
L"VIF1Stall",
|
||||||
L"GIFReverse",
|
L"GIFFIFO",
|
||||||
L"FMVinSoftware",
|
L"FMVinSoftware",
|
||||||
L"GoemonTlb",
|
L"GoemonTlb",
|
||||||
L"ScarfaceIbit"
|
L"ScarfaceIbit"
|
||||||
|
@ -312,7 +312,7 @@ void Pcsx2Config::GamefixOptions::Set( GamefixId id, bool enabled )
|
||||||
case Fix_DMABusy: DMABusyHack = enabled; break;
|
case Fix_DMABusy: DMABusyHack = enabled; break;
|
||||||
case Fix_VIFFIFO: VIFFIFOHack = enabled; break;
|
case Fix_VIFFIFO: VIFFIFOHack = enabled; break;
|
||||||
case Fix_VIF1Stall: VIF1StallHack = enabled; break;
|
case Fix_VIF1Stall: VIF1StallHack = enabled; break;
|
||||||
case Fix_GIFReverse: GIFReverseHack = enabled; break;
|
case Fix_GIFFIFO: GIFFIFOHack = enabled; break;
|
||||||
case Fix_FMVinSoftware: FMVinSoftwareHack = enabled; break;
|
case Fix_FMVinSoftware: FMVinSoftwareHack = enabled; break;
|
||||||
case Fix_GoemonTlbMiss: GoemonTlbHack = enabled; break;
|
case Fix_GoemonTlbMiss: GoemonTlbHack = enabled; break;
|
||||||
case Fix_ScarfaceIbit: ScarfaceIbit = enabled; break;
|
case Fix_ScarfaceIbit: ScarfaceIbit = enabled; break;
|
||||||
|
@ -338,7 +338,7 @@ bool Pcsx2Config::GamefixOptions::Get( GamefixId id ) const
|
||||||
case Fix_DMABusy: return DMABusyHack;
|
case Fix_DMABusy: return DMABusyHack;
|
||||||
case Fix_VIFFIFO: return VIFFIFOHack;
|
case Fix_VIFFIFO: return VIFFIFOHack;
|
||||||
case Fix_VIF1Stall: return VIF1StallHack;
|
case Fix_VIF1Stall: return VIF1StallHack;
|
||||||
case Fix_GIFReverse: return GIFReverseHack;
|
case Fix_GIFFIFO: return GIFFIFOHack;
|
||||||
case Fix_FMVinSoftware: return FMVinSoftwareHack;
|
case Fix_FMVinSoftware: return FMVinSoftwareHack;
|
||||||
case Fix_GoemonTlbMiss: return GoemonTlbHack;
|
case Fix_GoemonTlbMiss: return GoemonTlbHack;
|
||||||
case Fix_ScarfaceIbit: return ScarfaceIbit;
|
case Fix_ScarfaceIbit: return ScarfaceIbit;
|
||||||
|
@ -364,7 +364,7 @@ void Pcsx2Config::GamefixOptions::LoadSave( IniInterface& ini )
|
||||||
IniBitBool( DMABusyHack );
|
IniBitBool( DMABusyHack );
|
||||||
IniBitBool( VIFFIFOHack );
|
IniBitBool( VIFFIFOHack );
|
||||||
IniBitBool( VIF1StallHack );
|
IniBitBool( VIF1StallHack );
|
||||||
IniBitBool( GIFReverseHack );
|
IniBitBool( GIFFIFOHack );
|
||||||
IniBitBool( FMVinSoftwareHack );
|
IniBitBool( FMVinSoftwareHack );
|
||||||
IniBitBool( GoemonTlbHack );
|
IniBitBool( GoemonTlbHack );
|
||||||
IniBitBool( ScarfaceIbit );
|
IniBitBool( ScarfaceIbit );
|
||||||
|
|
|
@ -220,29 +220,7 @@ vifOp(vifCode_FlushA) {
|
||||||
vif1.vifstalled.value = VIF_TIMING_BREAK;
|
vif1.vifstalled.value = VIF_TIMING_BREAK;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
//gifUnit.PrintInfo();
|
|
||||||
/*if (p3.state != GIF_PATH_IDLE && !p1or2) { // Only path 3 left...
|
|
||||||
GUNIT_WARN("Vif FlushA - Getting path3 to finish!");
|
|
||||||
if (gifUnit.lastTranType == GIF_TRANS_FIFO
|
|
||||||
&& p3.state != GIF_PATH_IDLE && !p3.hasDataRemaining()) {
|
|
||||||
//p3.state= GIF_PATH_IDLE; // Does any game need this anymore?
|
|
||||||
DevCon.Warning("Vif FlushA - path3 has no more data, but didn't EOP");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p3.state != GIF_PATH_IDLE) {
|
|
||||||
doStall = true; // If path3 still isn't finished...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else doStall = true;*/
|
|
||||||
}
|
}
|
||||||
/*if (doStall) {
|
|
||||||
vif1Regs.stat.VGW = true;
|
|
||||||
vifX.vifstalled.enabled = VifStallEnable(vifXch);
|
|
||||||
vifX.vifstalled.value = VIF_TIMING_BREAK;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else*/
|
|
||||||
//Didn't need to stall!
|
|
||||||
vif1.cmd = 0;
|
vif1.cmd = 0;
|
||||||
vif1.pass = 0;
|
vif1.pass = 0;
|
||||||
}
|
}
|
||||||
|
@ -432,7 +410,9 @@ vifOp(vifCode_MskPath3) {
|
||||||
if(!vif1Regs.mskpath3) {
|
if(!vif1Regs.mskpath3) {
|
||||||
//if(!gifUnit.gifPath[GIF_PATH_3].isDone() || gifRegs.stat.P3Q || gifRegs.stat.IP3) {
|
//if(!gifUnit.gifPath[GIF_PATH_3].isDone() || gifRegs.stat.P3Q || gifRegs.stat.IP3) {
|
||||||
GUNIT_WARN("Path3 triggering!");
|
GUNIT_WARN("Path3 triggering!");
|
||||||
gifInterrupt();
|
if(CHECK_GIFFIFOHACK)gif_fifo.read(false);
|
||||||
|
else gifInterrupt();
|
||||||
|
GIF_LOG("GIF state on mskpth3 QWC in fifo %x APATH = %x OPH = %x state = %x", gifRegs.stat.FQC, gifRegs.stat.APATH, gifRegs.stat.OPH, gifUnit.gifPath[GIF_PATH_3].state);
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
vif1.cmd = 0;
|
vif1.cmd = 0;
|
||||||
|
@ -457,7 +437,7 @@ vifOp(vifCode_Nop) {
|
||||||
|
|
||||||
if (GetVifX.vifpacketsize > 1)
|
if (GetVifX.vifpacketsize > 1)
|
||||||
{
|
{
|
||||||
if(((data[1] >> 24) & 0x7f) == 0x6) //is mskpath3 next
|
if(((data[1] >> 24) & 0x7f) == 0x6 && (data[1] & 0x1)) //is mskpath3 next
|
||||||
{
|
{
|
||||||
GetVifX.vifstalled.enabled = VifStallEnable(vifXch);
|
GetVifX.vifstalled.enabled = VifStallEnable(vifXch);
|
||||||
GetVifX.vifstalled.value = VIF_TIMING_BREAK;
|
GetVifX.vifstalled.value = VIF_TIMING_BREAK;
|
||||||
|
|
|
@ -93,7 +93,7 @@ Panels::GameFixesPanel::GameFixesPanel( wxWindow* parent )
|
||||||
wxEmptyString
|
wxEmptyString
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
_("Ignore Bus Direction on Path3 Transfer - Used for Hotwheels"),
|
_("Enable the GIF FIFO (slower but needed for Hotwheels, Wallace & Gromit, DJ Hero)"),
|
||||||
wxEmptyString
|
wxEmptyString
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue