mirror of https://github.com/PCSX2/pcsx2.git
GIF: Reimplement GIF FIFO to kick in only when it is needed.
Need to adjust GameDB entries for to remove ones no longer required, added EE Timing fix for SOCOM as that seems to fix it up like its sequel. Some misc changes too which are inconsequential (mostly formatting)
This commit is contained in:
parent
35c50e01e1
commit
fd1305e4da
|
@ -31,8 +31,6 @@ GUST-00009:
|
|||
region: "NTSC-J"
|
||||
roundModes:
|
||||
eeRoundMode: 0 # Fixes jump issue.
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes flickering sprites.
|
||||
PAPX-90203:
|
||||
name: "Gran Turismo 2000 [Trial]"
|
||||
region: "NTSC-J"
|
||||
|
@ -2210,8 +2208,6 @@ SCES-50928:
|
|||
region: "PAL-M6"
|
||||
clampModes:
|
||||
vuClampMode: 2 # Fixes bad shadows.
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Resolves random sprite/HUD corruption.
|
||||
SCES-50934:
|
||||
name: "WRC II Extreme"
|
||||
region: "PAL-M7"
|
||||
|
@ -2419,8 +2415,6 @@ SCES-51618:
|
|||
region: "PAL-M5"
|
||||
clampModes:
|
||||
vuClampMode: 2 # Fixes bad shadows.
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Resolves random sprite/HUD corruption.
|
||||
SCES-51635:
|
||||
name: "Brave - The Search for Spirit Dancer"
|
||||
region: "PAL-M5"
|
||||
|
@ -3678,8 +3672,6 @@ SCKA-24008:
|
|||
region: "NTSC-K"
|
||||
clampModes:
|
||||
vuClampMode: 2 # Fixes bad shadows.
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Resolves random sprite/HUD corruption.
|
||||
SCKA-30001:
|
||||
name: "Gran Turismo 4"
|
||||
region: "NTSC-K"
|
||||
|
@ -3997,8 +3989,6 @@ SCPS-15044:
|
|||
region: "NTSC-J"
|
||||
clampModes:
|
||||
vuClampMode: 2 # Fixes bad shadows.
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Resolves random sprite/HUD corruption.
|
||||
SCPS-15045:
|
||||
name: "Ka (Mosquito) - Let's Go Hawaiian"
|
||||
region: "NTSC-J"
|
||||
|
@ -5077,8 +5067,6 @@ SCUS-97134:
|
|||
compat: 5
|
||||
clampModes:
|
||||
vuClampMode: 2 # Fixes bad shadows.
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Resolves random sprite/HUD corruption.
|
||||
SCUS-97136:
|
||||
name: "NCAA Final Four 2002"
|
||||
region: "NTSC-U"
|
||||
|
@ -5314,8 +5302,6 @@ SCUS-97205:
|
|||
region: "NTSC-U"
|
||||
clampModes:
|
||||
vuClampMode: 2 # Fixes bad shadows.
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Resolves random sprite/HUD corruption.
|
||||
SCUS-97206:
|
||||
name: "PlayStation Underground Jampack Summer 2002"
|
||||
region: "NTSC-U"
|
||||
|
@ -5399,8 +5385,6 @@ SCUS-97230:
|
|||
region: "NTSC-U"
|
||||
clampModes:
|
||||
vuClampMode: 2 # Fixes bad shadows.
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Resolves random sprite/HUD corruption.
|
||||
SCUS-97231:
|
||||
name: "Arc the Lad - Twilight of the Spirits"
|
||||
region: "NTSC-U"
|
||||
|
@ -8786,13 +8770,9 @@ SLES-51011:
|
|||
SLES-51013:
|
||||
name: "Blade II"
|
||||
region: "PAL-E"
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes flickering HUD. (originally was EE Timing Hack but required since r4821)
|
||||
SLES-51014:
|
||||
name: "Blade II"
|
||||
region: "PAL-F"
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes flickering HUD. (originally was EE Timing Hack but required since r4821)
|
||||
SLES-51017:
|
||||
name: "Scooby-Doo! and The Night of 100 Frights"
|
||||
region: "PAL-E"
|
||||
|
@ -9537,8 +9517,6 @@ SLES-51372:
|
|||
compat: 5
|
||||
clampModes:
|
||||
vuClampMode: 3 # Fixes minor SPS on characters.
|
||||
gameFixes:
|
||||
- GIFFIFOHack
|
||||
SLES-51374:
|
||||
name: "RoboCop"
|
||||
region: "PAL-M5"
|
||||
|
@ -10409,8 +10387,6 @@ SLES-51877:
|
|||
SLES-51879:
|
||||
name: "Hot Wheels World Race"
|
||||
region: "PAL-E"
|
||||
gameFixes:
|
||||
- GIFFIFOHack
|
||||
SLES-51881:
|
||||
name: "Mercedes Bens World Racing"
|
||||
region: "PAL-F-G"
|
||||
|
@ -10649,8 +10625,6 @@ SLES-51989:
|
|||
compat: 5
|
||||
clampModes:
|
||||
vuClampMode: 3 # Fixes minor SPS on characters.
|
||||
gameFixes:
|
||||
- GIFFIFOHack
|
||||
SLES-51991:
|
||||
name: "Dance UK"
|
||||
region: "PAL-E"
|
||||
|
@ -10726,8 +10700,6 @@ SLES-52026:
|
|||
compat: 5
|
||||
clampModes:
|
||||
vuClampMode: 3 # Fixes minor SPS on characters.
|
||||
gameFixes:
|
||||
- GIFFIFOHack
|
||||
SLES-52028:
|
||||
name: "Junior Sports Basketball"
|
||||
region: "PAL-M5"
|
||||
|
@ -14518,7 +14490,6 @@ SLES-53904:
|
|||
name: "DT Racer"
|
||||
region: "PAL-M5"
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes corrupted graphics in the menus.
|
||||
- VUKickstartHack # Fixes TLB misses and collision bugs.
|
||||
SLES-53906:
|
||||
name: "50cent - Bulletproof"
|
||||
|
@ -14668,8 +14639,6 @@ SLES-53979:
|
|||
SLES-53982:
|
||||
name: "Fight Night Round 3"
|
||||
region: "PAL-E-F"
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes corrupt textures.
|
||||
SLES-53984:
|
||||
name: "Ice Age 2 - The Meltdown"
|
||||
region: "PAL-M6"
|
||||
|
@ -15533,8 +15502,6 @@ SLES-54396:
|
|||
SLES-54400:
|
||||
name: "SpongeBob SquarePants - Creature from the Krusty Krab"
|
||||
region: "PAL-M7"
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes bad graphics.
|
||||
SLES-54402:
|
||||
name: "Need for Speed - Carbon [Collector's Edition]"
|
||||
region: "PAL-F"
|
||||
|
@ -16803,8 +16770,6 @@ SLES-54995:
|
|||
name: "Puzzle Quest - Challenge of the Warlords"
|
||||
region: "PAL-M5"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes flickering black and white sprites.
|
||||
SLES-54996:
|
||||
name: "Golden Compass, The"
|
||||
region: "PAL-M5"
|
||||
|
@ -17669,8 +17634,6 @@ SLES-55443:
|
|||
compat: 5
|
||||
roundModes:
|
||||
eeRoundMode: 0 # Fixes jump issue.
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes flickering sprites.
|
||||
SLES-55444:
|
||||
name: "Ar tonelico II: Melody of Metafalica"
|
||||
region: "PAL-E"
|
||||
|
@ -17876,8 +17839,6 @@ SLES-55576:
|
|||
SLES-55577:
|
||||
name: "DJ Hero"
|
||||
region: "PAL-M5"
|
||||
gameFixes:
|
||||
- GIFFIFOHack
|
||||
SLES-55578:
|
||||
name: "Band Hero"
|
||||
region: "PAL-M5"
|
||||
|
@ -18908,8 +18869,6 @@ SLPM-20436:
|
|||
SLPM-55005:
|
||||
name: "Mana Khemia 2: Ochita Gakuen to Renkinjutsushi Tachi"
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes flickering sprites.
|
||||
SLPM-55008:
|
||||
name: "Sengoku Basara X"
|
||||
region: "NTSC-J"
|
||||
|
@ -18954,8 +18913,6 @@ SLPM-55110:
|
|||
SLPM-55114:
|
||||
name: "Mana Khemia 2: Ochita Gakuen to Renkinjutsushi Tachi"
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes flickering sprites.
|
||||
SLPM-55118:
|
||||
name: "Galaxy Angel II - Eigou Kaiki no Koku [Disc1of2]"
|
||||
region: "NTSC-J"
|
||||
|
@ -26303,8 +26260,6 @@ SLPM-66693:
|
|||
SLPM-66694:
|
||||
name: "Spongebob"
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes bad graphics.
|
||||
SLPM-66695:
|
||||
name: "Kono Aozora ni Yakusoku o - Melody of the Sun and Sea"
|
||||
region: "NTSC-J"
|
||||
|
@ -33407,8 +33362,6 @@ SLUS-20360:
|
|||
name: "Blade II"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes flickering HUD. (originally was EE Timing Hack but required since r4821)
|
||||
SLUS-20361:
|
||||
name: "Rally Fusion - Race of Champions"
|
||||
region: "NTSC-U"
|
||||
|
@ -34666,8 +34619,6 @@ SLUS-20647:
|
|||
compat: 5
|
||||
clampModes:
|
||||
vuClampMode: 3 # Fixes minor SPS on characters.
|
||||
gameFixes:
|
||||
- GIFFIFOHack
|
||||
SLUS-20648:
|
||||
name: "NBA Jam 2004"
|
||||
region: "NTSC-U"
|
||||
|
@ -35018,8 +34969,6 @@ SLUS-20737:
|
|||
name: "Hot Wheels - World Race"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- GIFFIFOHack
|
||||
SLUS-20738:
|
||||
name: "Van Helsing"
|
||||
region: "NTSC-U"
|
||||
|
@ -36564,7 +36513,6 @@ SLUS-21095:
|
|||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes corrupted graphics in the menus.
|
||||
- VUKickstartHack # Fixes TLB misses and collision bugs.
|
||||
SLUS-21096:
|
||||
name: "Ape Escape - Pumped & Primed"
|
||||
|
@ -37880,8 +37828,6 @@ SLUS-21383:
|
|||
name: "Fight Night - Round 3"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes corrupt textures.
|
||||
SLUS-21384:
|
||||
name: "Cabela's Alaskan Adventures"
|
||||
region: "NTSC-U"
|
||||
|
@ -37917,8 +37863,6 @@ SLUS-21391:
|
|||
name: "SpongeBob SquarePants - Creature from the Krusty Krab"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes bad graphics.
|
||||
SLUS-21392:
|
||||
name: "Shrek Smash and Crash"
|
||||
region: "NTSC-U"
|
||||
|
@ -39083,8 +39027,6 @@ SLUS-21692:
|
|||
name: "Puzzle Quest - Challenge of the Warlords"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes flickering black and white sprites.
|
||||
SLUS-21693:
|
||||
name: "7 Wonders of the Ancient World"
|
||||
region: "NTSC-U"
|
||||
|
@ -39271,8 +39213,6 @@ SLUS-21735:
|
|||
compat: 5
|
||||
roundModes:
|
||||
eeRoundMode: 0 # Fixes jump issue.
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes flickering sprites.
|
||||
SLUS-21736:
|
||||
name: "Wall-E"
|
||||
region: "NTSC-U"
|
||||
|
@ -39878,8 +39818,6 @@ SLUS-21890:
|
|||
name: "Mana Khemia 2: Fall Of Alchemy"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes flickering sprites.
|
||||
SLUS-21891:
|
||||
name: "G-Force"
|
||||
region: "NTSC-U"
|
||||
|
@ -39952,8 +39890,6 @@ SLUS-21908:
|
|||
SLUS-21909:
|
||||
name: "DJ Hero"
|
||||
region: "NTSC-U"
|
||||
gameFixes:
|
||||
- GIFFIFOHack
|
||||
SLUS-21910:
|
||||
name: "Marvel Super Hero Squad"
|
||||
region: "NTSC-U"
|
||||
|
|
|
@ -125,10 +125,10 @@ void __fastcall WriteFIFO_VIF1(const mem128_t *value)
|
|||
void __fastcall WriteFIFO_GIF(const mem128_t *value)
|
||||
{
|
||||
GUNIT_LOG("WriteFIFO_GIF()");
|
||||
if (CHECK_GIFFIFOHACK) {
|
||||
gif_fifo.write((u32*)value, 1);
|
||||
|
||||
gif_fifo.read(true);
|
||||
if ((!gifUnit.CanDoPath3() || gif_fifo.fifoSize > 0)) {
|
||||
//DevCon.Warning("GIF FIFO HW Write");
|
||||
gif_fifo.write_fifo((u32*)value, 1);
|
||||
gif_fifo.read_fifo();
|
||||
}
|
||||
else {
|
||||
gifUnit.TransferGSPacketData(GIF_TRANS_FIFO, (u8*)value, 16);
|
||||
|
|
507
pcsx2/Gif.cpp
507
pcsx2/Gif.cpp
|
@ -57,12 +57,24 @@ static __fi void CalculateFIFOCSR() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
bool CheckPaths() {
|
||||
// Can't do Path 3, so try dma again later...
|
||||
if (!gifUnit.CanDoPath3()) {
|
||||
if (!gifUnit.Path3Masked())
|
||||
{
|
||||
//DevCon.Warning("Path3 stalled APATH %x PSE %x DIR %x Signal %x", gifRegs.stat.APATH, gifRegs.stat.PSE, gifRegs.stat.DIR, gifUnit.gsSIGNAL.queued);
|
||||
GifDMAInt(128);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GIF_Fifo::init()
|
||||
{
|
||||
readpos = 0;
|
||||
writepos = 0;
|
||||
memzero(data);
|
||||
memzero(readdata);
|
||||
fifoSize = 0;
|
||||
gifRegs.stat.FQC = 0;
|
||||
CSRreg.FIFO = CSR_FIFO_EMPTY;
|
||||
gif.gifstate = GIF_STATE_READY;
|
||||
|
@ -71,73 +83,81 @@ void GIF_Fifo::init()
|
|||
gif.gscycles = 0;
|
||||
gif.prevcycles = 0;
|
||||
gif.mfifocycles = 0;
|
||||
gif.gifqwc = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int GIF_Fifo::write(u32* pMem, int size)
|
||||
int GIF_Fifo::write_fifo(u32* pMem, int size)
|
||||
{
|
||||
if (gifRegs.stat.FQC == 16) {
|
||||
//DevCon.Warning("Full");
|
||||
if (fifoSize == 16) {
|
||||
//GIF_LOG("GIF FIFO Full");
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
int transferSize = std::min(size, 16 - (int)fifoSize);
|
||||
|
||||
int writePos = fifoSize * 4;
|
||||
|
||||
GIF_LOG("GIF FIFO Adding %d QW to GIF FIFO at offset %d FIFO now contains %d QW", transferSize, writePos, fifoSize);
|
||||
|
||||
memcpy(&data[writePos], pMem, transferSize * 16);
|
||||
|
||||
fifoSize += transferSize;
|
||||
gifRegs.stat.FQC = fifoSize;
|
||||
CalculateFIFOCSR();
|
||||
return firsttrans;
|
||||
|
||||
return transferSize;
|
||||
}
|
||||
|
||||
int GIF_Fifo::read(bool calledFromDMA)
|
||||
int GIF_Fifo::read_fifo()
|
||||
{
|
||||
|
||||
if (!gifUnit.CanDoPath3() || gifRegs.stat.FQC == 0)
|
||||
if (!fifoSize || !gifUnit.CanDoPath3())
|
||||
{
|
||||
//DevCon.Warning("Path3 not masked");
|
||||
if (gifch.chcr.STR == true && !(cpuRegs.interrupt & (1 << DMAC_GIF)) && calledFromDMA == false) {
|
||||
GifDMAInt(16);
|
||||
gifRegs.stat.FQC = fifoSize;
|
||||
CalculateFIFOCSR();
|
||||
if (fifoSize)
|
||||
{
|
||||
GIF_LOG("GIF FIFO Can't read, GIF paused/busy. Waiting");
|
||||
GifDMAInt(128);
|
||||
}
|
||||
//DevCon.Warning("P3 Masked");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int valueWritePos = 0;
|
||||
uint sizeRead;
|
||||
uint fifoSize = gifRegs.stat.FQC;
|
||||
int oldReadPos = readpos;
|
||||
int readpos = 0;
|
||||
int sizeRead = 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*)&data, fifoSize * 16) / 16; //returns the size actually read
|
||||
|
||||
sizeRead = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, (u8*)&readdata[0], fifoSize * 16) / 16; //returns the size actually read
|
||||
GIF_LOG("GIF FIFO Read %d QW from FIFO Current Size %d", sizeRead, fifoSize);
|
||||
|
||||
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 (sizeRead > 0)
|
||||
{
|
||||
int copyAmount = fifoSize - sizeRead;
|
||||
readpos = sizeRead * 4;
|
||||
|
||||
for (int i = 0; i < copyAmount; i++)
|
||||
CopyQWC(&data[i * 4], &data[readpos + (i * 4)]);
|
||||
|
||||
fifoSize = copyAmount;
|
||||
|
||||
GIF_LOG("GIF FIFO rearranged to now only contain %d QW", fifoSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
GIF_LOG("GIF FIFO not read");
|
||||
}
|
||||
}
|
||||
|
||||
if (calledFromDMA == false) {
|
||||
GifDMAInt(sizeRead * BIAS);
|
||||
else
|
||||
{
|
||||
GIF_LOG("GIF FIFO now empty");
|
||||
fifoSize = 0;
|
||||
}
|
||||
|
||||
gifRegs.stat.FQC = fifoSize;
|
||||
CalculateFIFOCSR();
|
||||
return gifRegs.stat.FQC;
|
||||
|
||||
return sizeRead;
|
||||
}
|
||||
|
||||
void incGifChAddr(u32 qwc) {
|
||||
|
@ -161,7 +181,7 @@ __fi void gifCheckPathStatus() {
|
|||
}
|
||||
}
|
||||
|
||||
//Required for Path3 Masking timing!
|
||||
// Required for Path3 Masking timing!
|
||||
if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT)
|
||||
gifUnit.gifPath[GIF_PATH_3].state = GIF_PATH_IDLE;
|
||||
}
|
||||
|
@ -175,143 +195,132 @@ __fi void gifInterrupt()
|
|||
{
|
||||
if(vif1Regs.stat.VGW)
|
||||
{
|
||||
//Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back.
|
||||
// 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);
|
||||
|
||||
//Make sure it loops if the GIF packet is empty to prepare for the next packet
|
||||
//or end if it was the end of a packet.
|
||||
//This must trigger after VIF retriggers as VIf might instantly mask Path3
|
||||
// Make sure it loops if the GIF packet is empty to prepare for the next packet
|
||||
// or end if it was the end of a packet.
|
||||
// This must trigger after VIF retriggers as VIf might instantly mask Path3
|
||||
if (!gifUnit.Path3Masked() || gifch.qwc == 0) {
|
||||
GifDMAInt(16);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (dmacRegs.ctrl.MFD == MFD_GIF) { // GIF MFIFO
|
||||
//Console.WriteLn("GIF MFIFO");
|
||||
gifMFIFOInterrupt();
|
||||
return;
|
||||
}
|
||||
|
||||
if (CHECK_GIFFIFOHACK) {
|
||||
|
||||
if (int amtRead = gif_fifo.read(true)) {
|
||||
|
||||
if (!gifUnit.Path3Masked() || gifRegs.stat.FQC < 16) {
|
||||
GifDMAInt(amtRead * BIAS);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if (!gifUnit.CanDoPath3() && gifRegs.stat.FQC == 16)
|
||||
{
|
||||
if (gifch.qwc > 0 || gif.gspath3done == false) {
|
||||
if (!gifUnit.Path3Masked()) {
|
||||
GifDMAInt(128);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (gifUnit.gsSIGNAL.queued) {
|
||||
GIF_LOG("Path 3 Paused");
|
||||
GifDMAInt(128);
|
||||
return;
|
||||
if(gif_fifo.fifoSize == 16)
|
||||
return;
|
||||
}
|
||||
|
||||
gifCheckPathStatus();
|
||||
|
||||
//Double check as we might have read the fifo as it's ending the DMA
|
||||
if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE)
|
||||
// If there's something in the FIFO and we can do PATH3, empty the FIFO.
|
||||
if (gif_fifo.fifoSize > 0)
|
||||
{
|
||||
if (vif1Regs.stat.VGW)
|
||||
const int readSize = gif_fifo.read_fifo();
|
||||
|
||||
if (readSize)
|
||||
GifDMAInt(readSize * BIAS);
|
||||
|
||||
gifCheckPathStatus();
|
||||
// Double check as we might have read the fifo as it's ending the DMA
|
||||
if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE)
|
||||
{
|
||||
//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 (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 (((gifch.qwc > 0) || (!gif.gspath3done)) && gif_fifo.fifoSize)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!(gifch.chcr.STR)) return;
|
||||
|
||||
if ((gifch.qwc > 0) || (!gif.gspath3done)) {
|
||||
if (!dmacRegs.ctrl.DMAE) {
|
||||
Console.Warning("gs dma masked, re-scheduling...");
|
||||
// re-raise the int shortly in the future
|
||||
// Re-raise the int shortly in the future
|
||||
GifDMAInt( 64 );
|
||||
return;
|
||||
}
|
||||
GIFdma();
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!CHECK_GIFFIFOHACK)
|
||||
{
|
||||
gifRegs.stat.FQC = 0;
|
||||
clearFIFOstuff(false);
|
||||
}
|
||||
gif.gscycles = 0;
|
||||
gifch.chcr.STR = false;
|
||||
|
||||
gifRegs.stat.FQC = gif_fifo.fifoSize;
|
||||
CalculateFIFOCSR();
|
||||
hwDmacIrq(DMAC_GIF);
|
||||
|
||||
if(gif_fifo.fifoSize)
|
||||
GifDMAInt(8 * BIAS);
|
||||
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) {
|
||||
u32 originalQwc = qwc;
|
||||
|
||||
if (gifRegs.stat.IMT)
|
||||
{
|
||||
//Splitting by 8qw can be really slow, so on bigger packets be less picky.
|
||||
//Some games like Wallace & Gromit like smaller packets to be split correctly, hopefully with little impact on speed.
|
||||
//68 works for W&G but 128 is more of a safe point.
|
||||
// Splitting by 8qw can be really slow, so on bigger packets be less picky.
|
||||
// Some games like Wallace & Gromit like smaller packets to be split correctly, hopefully with little impact on speed.
|
||||
// 68 works for W&G but 128 is more of a safe point.
|
||||
if (qwc > 128)
|
||||
qwc = std::min(qwc, 1024u);
|
||||
else
|
||||
qwc = std::min(qwc, 8u);
|
||||
}
|
||||
|
||||
uint size;
|
||||
if (CHECK_GIFFIFOHACK) {
|
||||
size = gif_fifo.write(pMem, qwc);
|
||||
}
|
||||
else {
|
||||
size = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, (u8*)pMem, qwc * 16) / 16;
|
||||
|
||||
if (CheckPaths() == false || ((qwc < 8 || gif_fifo.fifoSize > 0) && CHECK_GIFFIFOHACK))
|
||||
{
|
||||
if (gif_fifo.fifoSize < 16)
|
||||
{
|
||||
size = gif_fifo.write_fifo((u32*)pMem, originalQwc); // Use original QWC here, the intermediate mode is for the GIF unit, not DMA
|
||||
incGifChAddr(size);
|
||||
return size;
|
||||
}
|
||||
return 4; // Arbitrary value, probably won't schedule a DMA anwyay since the FIFO is full and GIF is paused
|
||||
}
|
||||
|
||||
size = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, (u8*)pMem, qwc * 16) / 16;
|
||||
incGifChAddr(size);
|
||||
return size;
|
||||
}
|
||||
|
||||
int _GIFchain()
|
||||
{
|
||||
tDMA_TAG *pMem;
|
||||
static __fi void GIFchain() {
|
||||
tDMA_TAG* pMem;
|
||||
|
||||
pMem = dmaGetAddr(gifch.madr, false);
|
||||
if (pMem == NULL) {
|
||||
//must increment madr and clear qwc, else it loops
|
||||
// Must increment madr and clear qwc, else it loops
|
||||
gifch.madr += gifch.qwc * 16;
|
||||
gifch.qwc = 0;
|
||||
Console.Warning("Hackfix - NULL GIFchain");
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
return WRITERING_DMA((u32*)pMem, gifch.qwc);
|
||||
}
|
||||
int transferred= WRITERING_DMA((u32*)pMem, gifch.qwc);
|
||||
gif.gscycles += transferred * BIAS;
|
||||
|
||||
static __fi void GIFchain() {
|
||||
// qwc check now done outside this function
|
||||
// Voodoocycles
|
||||
// >> 2 so Drakan and Tekken 5 don't mess up in some PATH3 transfer. Cycles to interrupt were getting huge..
|
||||
/*if (gifch.qwc)*/
|
||||
gif.gscycles+= _GIFchain() * BIAS; /* guessing */
|
||||
if (!gifUnit.Path3Masked() || (gif_fifo.fifoSize < 16))
|
||||
GifDMAInt(gif.gscycles);
|
||||
}
|
||||
|
||||
static __fi bool checkTieBit(tDMA_TAG* &ptag)
|
||||
|
@ -326,12 +335,12 @@ static __fi bool checkTieBit(tDMA_TAG* &ptag)
|
|||
|
||||
static __fi tDMA_TAG* ReadTag()
|
||||
{
|
||||
tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); //Set memory pointer to TADR
|
||||
tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); // Set memory pointer to TADR
|
||||
|
||||
if (!(gifch.transfer("Gif", ptag))) return NULL;
|
||||
|
||||
gifch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
|
||||
gif.gscycles += 2; // Add 1 cycles from the QW read for the tag
|
||||
gifch.madr = ptag[1]._u32; // MADR = ADDR field + SPR
|
||||
gif.gscycles += 2; // Add 1 cycles from the QW read for the tag
|
||||
|
||||
gif.gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
|
||||
return ptag;
|
||||
|
@ -339,7 +348,7 @@ static __fi tDMA_TAG* ReadTag()
|
|||
|
||||
static __fi tDMA_TAG* ReadTag2()
|
||||
{
|
||||
tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); //Set memory pointer to TADR
|
||||
tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); // Set memory pointer to TADR
|
||||
|
||||
gifch.unsafeTransfer(ptag);
|
||||
gifch.madr = ptag[1]._u32;
|
||||
|
@ -348,28 +357,13 @@ static __fi tDMA_TAG* ReadTag2()
|
|||
return ptag;
|
||||
}
|
||||
|
||||
bool CheckPaths() {
|
||||
// Can't do Path 3, so try dma again later...
|
||||
if (!CHECK_GIFFIFOHACK) {
|
||||
if (!gifUnit.CanDoPath3()) {
|
||||
if (!gifUnit.Path3Masked())
|
||||
{
|
||||
GIF_LOG("Path3 stalled");
|
||||
GifDMAInt(128);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GIFdma()
|
||||
{
|
||||
while (gifch.qwc > 0 || !gif.gspath3done) {
|
||||
tDMA_TAG* ptag;
|
||||
gif.gscycles = gif.prevcycles;
|
||||
|
||||
if (gifRegs.ctrl.PSE) { // temporarily stop
|
||||
if (gifRegs.ctrl.PSE) { // Temporarily stop
|
||||
Console.WriteLn("Gif dma temp paused? (non MFIFO GIF)");
|
||||
GifDMAInt(16);
|
||||
return;
|
||||
|
@ -392,7 +386,9 @@ void GIFdma()
|
|||
if (ptag == NULL) return;
|
||||
//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);
|
||||
if (!CHECK_GIFFIFOHACK)gifRegs.stat.FQC = std::min((u32)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
gifRegs.stat.FQC = std::min((u32)0x10, gifch.qwc);
|
||||
CalculateFIFOCSR();
|
||||
|
||||
if (dmacRegs.ctrl.STD == STD_GIF)
|
||||
{
|
||||
// there are still bugs, need to also check if gifch.madr +16*qwc >= stadr, if not, stall
|
||||
|
@ -418,48 +414,28 @@ void GIFdma()
|
|||
Console.WriteLn("GIF DMA Stall in Normal mode not implemented - Report which game to PCSX2 Team");
|
||||
}
|
||||
|
||||
|
||||
if (!CHECK_GIFFIFOHACK) {
|
||||
gifRegs.stat.FQC = std::min((u32)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
|
||||
clearFIFOstuff(true);
|
||||
}
|
||||
|
||||
// Transfer Dn_QWC from Dn_MADR to GIF
|
||||
if (gifch.qwc > 0) // Normal Mode
|
||||
{
|
||||
if (CheckPaths() == false) return;
|
||||
|
||||
GIFchain(); //Transfers the data set by the switch
|
||||
//if (gscycles < 8) DevCon.Warning("GSCycles = %d", gscycles);
|
||||
GifDMAInt(gif.gscycles);
|
||||
GIFchain(); // Transfers the data set by the switch
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//QWC == 0 && gspath3done == true - End of DMA
|
||||
gif.prevcycles = 0;
|
||||
//if (gscycles < 8) DevCon.Warning("1 GSCycles = %d", gscycles);
|
||||
GifDMAInt(16);
|
||||
}
|
||||
|
||||
void dmaGIF()
|
||||
{
|
||||
//We used to add wait time for the buffer to fill here, fixing some timing problems in path 3 masking
|
||||
//It takes the time of 24 QW for the BUS to become ready - The Punisher And Streetball
|
||||
//DevCon.Warning("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gifch.chcr._u32, gifch.madr, gifch.qwc, gifch.tadr, gifch.asr0, gifch.asr1);
|
||||
// DevCon.Warning("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gifch.chcr._u32, gifch.madr, gifch.qwc, gifch.tadr, gifch.asr0, gifch.asr1);
|
||||
|
||||
gif.gspath3done = false; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :)
|
||||
|
||||
if (!CHECK_GIFFIFOHACK) {
|
||||
gifRegs.stat.FQC |= 0x10; // hack ;)
|
||||
clearFIFOstuff(true);
|
||||
}
|
||||
|
||||
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
|
||||
gif.gspath3done = true;
|
||||
}
|
||||
|
||||
|
||||
if(gifch.chcr.MOD == CHAIN_MODE && gifch.qwc > 0) {
|
||||
//DevCon.Warning(L"GIF QWC on Chain " + gifch.chcr.desc());
|
||||
if ((gifch.chcr.tag().ID == TAG_REFE) || (gifch.chcr.tag().ID == TAG_END) || (gifch.chcr.tag().IRQ && gifch.chcr.TIE)) {
|
||||
|
@ -475,19 +451,19 @@ static u32 QWCinGIFMFIFO(u32 DrainADDR)
|
|||
u32 ret;
|
||||
|
||||
SPR_LOG("GIF MFIFO Requesting %x QWC from the MFIFO Base %x, SPR MADR %x Drain %x", gifch.qwc, dmacRegs.rbor.ADDR, spr0ch.madr, DrainADDR);
|
||||
//Calculate what we have in the fifo.
|
||||
// Calculate what we have in the fifo.
|
||||
if (DrainADDR <= spr0ch.madr) {
|
||||
//Drain is below the write position, calculate the difference between them
|
||||
// Drain is below the write position, calculate the difference between them
|
||||
ret = (spr0ch.madr - DrainADDR) >> 4;
|
||||
}
|
||||
else {
|
||||
u32 limit = dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16;
|
||||
//Drain is higher than SPR so it has looped round,
|
||||
//calculate from base to the SPR tag addr and what is left in the top of the ring
|
||||
// Drain is higher than SPR so it has looped round,
|
||||
// calculate from base to the SPR tag addr and what is left in the top of the ring
|
||||
ret = ((spr0ch.madr - dmacRegs.rbor.ADDR) + (limit - DrainADDR)) >> 4;
|
||||
}
|
||||
if (ret == 0)
|
||||
gif.gifstate |= GIF_STATE_EMPTY;
|
||||
gif.gifstate = GIF_STATE_EMPTY;
|
||||
|
||||
SPR_LOG("%x Available of the %x requested", ret, gifch.qwc);
|
||||
return ret;
|
||||
|
@ -496,9 +472,9 @@ static u32 QWCinGIFMFIFO(u32 DrainADDR)
|
|||
static __fi bool mfifoGIFrbTransfer()
|
||||
{
|
||||
u32 qwc = std::min(QWCinGIFMFIFO(gifch.madr), gifch.qwc);
|
||||
if (qwc == 0) {
|
||||
DevCon.Warning("GIF FIFO EMPTY before transfer (how?)");
|
||||
}
|
||||
|
||||
if (qwc == 0) // Either gifch.qwc is 0 (shouldn't get here) or the FIFO is empty.
|
||||
return true;
|
||||
|
||||
u8* src = (u8*)PSM(gifch.madr);
|
||||
if (src == NULL) return false;
|
||||
|
@ -508,84 +484,76 @@ static __fi bool mfifoGIFrbTransfer()
|
|||
u32 firstTransQWC = needWrap ? MFIFOUntilEnd : qwc;
|
||||
u32 transferred;
|
||||
|
||||
if (!CHECK_GIFFIFOHACK)
|
||||
{
|
||||
transferred = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, src, firstTransQWC * 16) / 16; // First part
|
||||
}
|
||||
else
|
||||
{
|
||||
transferred = gif_fifo.write((u32*)src, firstTransQWC);
|
||||
}
|
||||
|
||||
incGifChAddr(transferred);
|
||||
transferred = WRITERING_DMA((u32*)src, firstTransQWC); // First part
|
||||
|
||||
gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK);
|
||||
gifch.tadr = dmacRegs.rbor.ADDR + (gifch.tadr & dmacRegs.rbsr.RMSK);
|
||||
|
||||
if (needWrap && transferred == MFIFOUntilEnd)
|
||||
{ // Need to do second transfer to wrap around
|
||||
if (needWrap && transferred == MFIFOUntilEnd)
|
||||
{
|
||||
// Need to do second transfer to wrap around
|
||||
u32 transferred2;
|
||||
uint secondTransQWC = qwc - MFIFOUntilEnd;
|
||||
|
||||
src = (u8*)PSM(dmacRegs.rbor.ADDR);
|
||||
if (src == NULL) return false;
|
||||
|
||||
if (!CHECK_GIFFIFOHACK) {
|
||||
transferred2 = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, src, secondTransQWC * 16) / 16; // Second part
|
||||
}
|
||||
else {
|
||||
transferred2 = gif_fifo.write((u32*)src, secondTransQWC);
|
||||
}
|
||||
transferred2 = WRITERING_DMA((u32*)src, secondTransQWC); // Second part
|
||||
|
||||
incGifChAddr(transferred2);
|
||||
gif.mfifocycles += (transferred2 + transferred) * 2; // guessing
|
||||
}
|
||||
else
|
||||
{
|
||||
gif.mfifocycles += transferred * 2; // guessing
|
||||
gif.mfifocycles += (transferred2 + transferred) * 2;
|
||||
}
|
||||
else
|
||||
gif.mfifocycles += transferred * 2;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static __fi bool mfifoGIFchain()
|
||||
static __fi void mfifoGIFchain()
|
||||
{
|
||||
/* Is QWC = 0? if so there is nothing to transfer */
|
||||
if (gifch.qwc == 0) return true;
|
||||
// Is QWC = 0? if so there is nothing to transfer
|
||||
if (gifch.qwc == 0)
|
||||
{
|
||||
gif.mfifocycles += 4;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((gifch.madr & ~dmacRegs.rbsr.RMSK) == dmacRegs.rbor.ADDR)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (QWCinGIFMFIFO(gifch.madr) == 0) {
|
||||
SPR_LOG("GIF FIFO EMPTY before transfer");
|
||||
gif.gifstate = GIF_STATE_EMPTY;
|
||||
gif.mfifocycles += 4;
|
||||
if (CHECK_GIFFIFOHACK)
|
||||
GifDMAInt(128);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mfifoGIFrbTransfer()) ret = false;
|
||||
if (!mfifoGIFrbTransfer())
|
||||
{
|
||||
gif.mfifocycles += 4;
|
||||
gifch.qwc = 0;
|
||||
gif.gspath3done = true;
|
||||
return;
|
||||
}
|
||||
|
||||
//This ends up being done more often but it's safer :P
|
||||
//Make sure we wrap the addresses, dont want it being stuck outside the ring when reading from the ring!
|
||||
// This ends up being done more often but it's safer :P
|
||||
// Make sure we wrap the addresses, dont want it being stuck outside the ring when reading from the ring!
|
||||
gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK);
|
||||
gifch.tadr = gifch.madr;
|
||||
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
int mfifoqwc;
|
||||
SPR_LOG("Non-MFIFO Location transfer doing %x Total QWC", gifch.qwc);
|
||||
tDMA_TAG *pMem = dmaGetAddr(gifch.madr, false);
|
||||
if (pMem == NULL) return false;
|
||||
if (pMem == NULL)
|
||||
{
|
||||
gif.mfifocycles += 4;
|
||||
gifch.qwc = 0;
|
||||
gif.gspath3done = true;
|
||||
return;
|
||||
}
|
||||
|
||||
mfifoqwc = WRITERING_DMA((u32*)pMem, gifch.qwc);
|
||||
gif.mfifocycles += (mfifoqwc) * 2; /* guessing */
|
||||
gif.mfifocycles += WRITERING_DMA((u32*)pMem, gifch.qwc) * 2;
|
||||
}
|
||||
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
static u32 qwctag(u32 mask) {
|
||||
|
@ -595,25 +563,25 @@ static u32 qwctag(u32 mask) {
|
|||
void mfifoGifMaskMem(int id)
|
||||
{
|
||||
switch (id) {
|
||||
//These five transfer data following the tag, need to check its within the buffer (Front Mission 4)
|
||||
// These five transfer data following the tag, need to check its within the buffer (Front Mission 4)
|
||||
case TAG_CNT:
|
||||
case TAG_NEXT:
|
||||
case TAG_CALL:
|
||||
case TAG_RET:
|
||||
case TAG_END:
|
||||
if(gifch.madr < dmacRegs.rbor.ADDR) //probably not needed but we will check anyway.
|
||||
if(gifch.madr < dmacRegs.rbor.ADDR) // Probably not needed but we will check anyway.
|
||||
{
|
||||
SPR_LOG("GIF MFIFO MADR below bottom of ring buffer, wrapping GIF MADR = %x Ring Bottom %x", gifch.madr, dmacRegs.rbor.ADDR);
|
||||
gifch.madr = qwctag(gifch.madr);
|
||||
} else
|
||||
if(gifch.madr > (dmacRegs.rbor.ADDR + (u32)dmacRegs.rbsr.RMSK)) //Usual scenario is the tag is near the end (Front Mission 4)
|
||||
if(gifch.madr > (dmacRegs.rbor.ADDR + (u32)dmacRegs.rbsr.RMSK)) // Usual scenario is the tag is near the end (Front Mission 4)
|
||||
{
|
||||
SPR_LOG("GIF MFIFO MADR outside top of ring buffer, wrapping GIF MADR = %x Ring Top %x", gifch.madr, (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK)+16);
|
||||
gifch.madr = qwctag(gifch.madr);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//Do nothing as the MADR could be outside
|
||||
// Do nothing as the MADR could be outside
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -622,9 +590,8 @@ void mfifoGIFtransfer()
|
|||
{
|
||||
tDMA_TAG *ptag;
|
||||
gif.mfifocycles = 0;
|
||||
|
||||
|
||||
if (gifRegs.ctrl.PSE) { // temporarily stop
|
||||
if (gifRegs.ctrl.PSE) { // Temporarily stop
|
||||
Console.WriteLn("Gif dma temp paused?");
|
||||
CPU_INT(DMAC_MFIFO_GIF, 16);
|
||||
return;
|
||||
|
@ -637,8 +604,6 @@ void mfifoGIFtransfer()
|
|||
SPR_LOG("GIF FIFO EMPTY before tag read");
|
||||
gif.gifstate = GIF_STATE_EMPTY;
|
||||
GifDMAInt(4);
|
||||
if (CHECK_GIFFIFOHACK)
|
||||
GifDMAInt(128);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -646,6 +611,9 @@ void mfifoGIFtransfer()
|
|||
gifch.unsafeTransfer(ptag);
|
||||
gifch.madr = ptag[1]._u32;
|
||||
|
||||
gifRegs.stat.FQC = std::min((u32)0x10, gifch.qwc);
|
||||
CalculateFIFOCSR();
|
||||
|
||||
gif.mfifocycles += 2;
|
||||
|
||||
GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x",
|
||||
|
@ -667,12 +635,8 @@ void mfifoGIFtransfer()
|
|||
}
|
||||
}
|
||||
|
||||
if (!mfifoGIFchain()) {
|
||||
Console.WriteLn("mfifoGIF dmaChain error size=%d, madr=%lx, tadr=%lx", gifch.qwc, gifch.madr, gifch.tadr);
|
||||
gif.gspath3done = true;
|
||||
gifch.qwc = 0; //Sanity
|
||||
}
|
||||
|
||||
mfifoGIFchain();
|
||||
|
||||
GifDMAInt(std::max(gif.mfifocycles, (u32)4));
|
||||
|
||||
SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x", gifch.chcr._u32, gifch.madr, gifch.tadr);
|
||||
|
@ -680,7 +644,7 @@ void mfifoGIFtransfer()
|
|||
|
||||
void gifMFIFOInterrupt()
|
||||
{
|
||||
GIF_LOG("gifMFIFOInterrupt");
|
||||
//DevCon.Warning("gifMFIFOInterrupt");
|
||||
gif.mfifocycles = 0;
|
||||
|
||||
if (dmacRegs.ctrl.MFD != MFD_GIF) { // GIF not in MFIFO anymore, come out.
|
||||
|
@ -695,19 +659,18 @@ void gifMFIFOInterrupt()
|
|||
{
|
||||
if (vif1Regs.stat.VGW)
|
||||
{
|
||||
//Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back.
|
||||
// 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);
|
||||
|
||||
//Make sure it loops if the GIF packet is empty to prepare for the next packet
|
||||
//or end if it was the end of a packet.
|
||||
//This must trigger after VIF retriggers as VIf might instantly mask Path3
|
||||
// Make sure it loops if the GIF packet is empty to prepare for the next packet
|
||||
// or end if it was the end of a packet.
|
||||
// This must trigger after VIF retriggers as VIf might instantly mask Path3
|
||||
if (!gifUnit.Path3Masked() || gifch.qwc == 0) {
|
||||
GifDMAInt(16);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (gifUnit.gsSIGNAL.queued) {
|
||||
|
@ -715,40 +678,19 @@ void gifMFIFOInterrupt()
|
|||
return;
|
||||
}
|
||||
|
||||
if (CHECK_GIFFIFOHACK)
|
||||
{
|
||||
if (int amtRead = gif_fifo.read(true))
|
||||
{
|
||||
if (!gifUnit.Path3Masked() || gifRegs.stat.FQC < 16) {
|
||||
GifDMAInt(amtRead * BIAS);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!gifUnit.CanDoPath3() && gifRegs.stat.FQC == 16)
|
||||
{
|
||||
if (gifch.qwc > 0 || gif.gspath3done == false) {
|
||||
if (!gifUnit.Path3Masked()) {
|
||||
GifDMAInt(128);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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.
|
||||
// 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);
|
||||
|
||||
//Make sure it loops if the GIF packet is empty to prepare for the next packet
|
||||
//or end if it was the end of a packet.
|
||||
//This must trigger after VIF retriggers as VIf might instantly mask Path3
|
||||
// Make sure it loops if the GIF packet is empty to prepare for the next packet
|
||||
// or end if it was the end of a packet.
|
||||
// This must trigger after VIF retriggers as VIf might instantly mask Path3
|
||||
if (!gifUnit.Path3Masked() || gifch.qwc == 0) {
|
||||
GifDMAInt(16);
|
||||
}
|
||||
|
@ -756,41 +698,58 @@ void gifMFIFOInterrupt()
|
|||
}
|
||||
}
|
||||
|
||||
if (!gifch.chcr.STR) {
|
||||
Console.WriteLn("WTF GIFMFIFO");
|
||||
cpuRegs.interrupt &= ~(1 << 11);
|
||||
return;
|
||||
// If there's something in the FIFO and we can do PATH3, empty the FIFO.
|
||||
if (gif_fifo.fifoSize > 0)
|
||||
{
|
||||
const int readSize = gif_fifo.read_fifo();
|
||||
|
||||
if (readSize)
|
||||
GifDMAInt(readSize * BIAS);
|
||||
|
||||
gifCheckPathStatus();
|
||||
// Double check as we might have read the fifo as it's ending the DMA
|
||||
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 (((gifch.qwc > 0) || (!gif.gspath3done)) && gif_fifo.fifoSize)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((gif.gifstate & GIF_STATE_EMPTY)) {
|
||||
FireMFIFOEmpty();
|
||||
if (CHECK_GIFFIFOHACK)
|
||||
GifDMAInt(128);
|
||||
if (!gifch.chcr.STR)
|
||||
return;
|
||||
|
||||
if (spr0ch.madr == gifch.tadr || (gif.gifstate & GIF_STATE_EMPTY)) {
|
||||
gif.gifstate = GIF_STATE_EMPTY; // In case of madr = tadr we need to set it
|
||||
FireMFIFOEmpty();
|
||||
|
||||
if (gifch.qwc > 0 || !gif.gspath3done)
|
||||
return;
|
||||
}
|
||||
|
||||
if (gifch.qwc > 0 || !gif.gspath3done) {
|
||||
|
||||
if (!CheckPaths()) return;
|
||||
mfifoGIFtransfer();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CHECK_GIFFIFOHACK)
|
||||
{
|
||||
gifRegs.stat.FQC = 0;
|
||||
clearFIFOstuff(false);
|
||||
}
|
||||
|
||||
if (spr0ch.madr == gifch.tadr) {
|
||||
FireMFIFOEmpty();
|
||||
}
|
||||
|
||||
gif.gscycles = 0;
|
||||
|
||||
gifch.chcr.STR = false;
|
||||
gif.gifstate = GIF_STATE_READY;
|
||||
gifRegs.stat.FQC = gif_fifo.fifoSize;
|
||||
CalculateFIFOCSR();
|
||||
hwDmacIrq(DMAC_GIF);
|
||||
|
||||
if (gif_fifo.fifoSize)
|
||||
GifDMAInt(8 * BIAS);
|
||||
DMA_LOG("GIF MFIFO DMA End");
|
||||
}
|
||||
|
||||
|
|
|
@ -80,11 +80,10 @@ extern __aligned16 gifStruct gif;
|
|||
struct GIF_Fifo
|
||||
{
|
||||
unsigned int data[64]; //16 QW FIFO
|
||||
unsigned int readdata[64]; //16 QW Inline for reading
|
||||
int readpos, writepos;
|
||||
unsigned int fifoSize;
|
||||
|
||||
int write(u32* pMem, int size);
|
||||
int read(bool calledFromDMA = false);
|
||||
int write_fifo(u32* pMem, int size);
|
||||
int read_fifo();
|
||||
|
||||
void init();
|
||||
};
|
||||
|
|
|
@ -538,6 +538,7 @@ struct Gif_Unit
|
|||
gifRegs.stat.reset();
|
||||
gifRegs.ctrl.reset();
|
||||
gifRegs.mode.reset();
|
||||
gif_fifo.init();
|
||||
}
|
||||
|
||||
// Adds a finished GS Packet to the MTGS ring buffer
|
||||
|
|
|
@ -216,12 +216,6 @@ __ri void hwMFIFOResume(u32 transferred) {
|
|||
CPU_INT(DMAC_MFIFO_GIF, transferred * BIAS);
|
||||
gif.gifstate = GIF_STATE_READY;
|
||||
}
|
||||
if (!CHECK_GIFFIFOHACK)
|
||||
{
|
||||
gifRegs.stat.FQC = 16;
|
||||
//GIF FIFO
|
||||
clearFIFOstuff(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -111,9 +111,8 @@ void __fastcall _hwWrite32( u32 mem, u32 value )
|
|||
icase(GIF_MODE)
|
||||
{
|
||||
gifRegs.mode.write(value);
|
||||
|
||||
//Need to kickstart the GIF if the M3R mask comes off
|
||||
if (gifRegs.stat.M3R == 1 && gifRegs.mode.M3R == 0 && gifch.chcr.STR)
|
||||
if (gifRegs.stat.M3R == 1 && gifRegs.mode.M3R == 0 && (gifch.chcr.STR || gif_fifo.fifoSize))
|
||||
{
|
||||
DevCon.Warning("GIF Mode cancelling P3 Disable");
|
||||
CPU_INT(DMAC_GIF, 8);
|
||||
|
|
|
@ -313,12 +313,13 @@ void SPRFROMinterrupt()
|
|||
spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK);
|
||||
//Console.WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr);
|
||||
hwMFIFOResume(mfifotransferred);
|
||||
mfifotransferred = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mfifotransferred = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
@ -31,7 +31,7 @@ enum class FreezeAction
|
|||
// 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.
|
||||
|
||||
static const u32 g_SaveVersion = (0x9A21 << 16) | 0x0000;
|
||||
static const u32 g_SaveVersion = (0x9A22 << 16) | 0x0000;
|
||||
|
||||
// the freezing data between submodules and core
|
||||
// an interesting thing to note is that this dates back from before plugin
|
||||
|
|
|
@ -222,14 +222,14 @@ __fi void vif1FBRST(u32 value) {
|
|||
case MFD_VIF1:
|
||||
//Console.WriteLn("MFIFO Stall");
|
||||
//MFIFO active and not empty
|
||||
if(vif1ch.chcr.STR) CPU_INT(DMAC_MFIFO_VIF, 0);
|
||||
if(vif1ch.chcr.STR && !vif1Regs.stat.test(VIF1_STAT_FDR)) CPU_INT(DMAC_MFIFO_VIF, 0);
|
||||
break;
|
||||
|
||||
case NO_MFD:
|
||||
case MFD_RESERVED:
|
||||
case MFD_GIF: // Wonder if this should be with VIF?
|
||||
// Gets the timing right - Flatout
|
||||
if(vif1ch.chcr.STR) CPU_INT(DMAC_VIF1, 0);
|
||||
if(vif1ch.chcr.STR && !vif1Regs.stat.test(VIF1_STAT_FDR)) CPU_INT(DMAC_VIF1, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -256,6 +256,8 @@ __fi void vif1STAT(u32 value) {
|
|||
//position, as we clear it and set it to the end well before the interrupt, the game assumes it's finished,
|
||||
//then proceeds to reverse the dma before we have even done it ourselves. So lets just make sure VIF is ready :)
|
||||
if (vif1ch.qwc > 0 || isStalled == false){
|
||||
vif1ch.qwc = 0;
|
||||
hwDmacIrq(DMAC_VIF1);
|
||||
vif1ch.chcr.STR = false;
|
||||
cpuRegs.interrupt &= ~((1 << DMAC_VIF1) | (1 << DMAC_MFIFO_VIF));
|
||||
}
|
||||
|
|
|
@ -288,7 +288,7 @@ __fi void vif1Interrupt()
|
|||
|
||||
g_vif1Cycles = 0;
|
||||
|
||||
if( gifRegs.stat.APATH == 2 && gifUnit.gifPath[GIF_PATH_2].isDone())
|
||||
if( gifRegs.stat.APATH == 2 && gifUnit.gifPath[GIF_PATH_2].isDone())
|
||||
{
|
||||
gifRegs.stat.APATH = 0;
|
||||
gifRegs.stat.OPH = 0;
|
||||
|
@ -427,7 +427,7 @@ __fi void vif1Interrupt()
|
|||
vif1.irqoffset.enabled = false;
|
||||
if(vif1.queued_program) vifExecQueue(1);
|
||||
g_vif1Cycles = 0;
|
||||
DMA_LOG("VIF1 DMA End");
|
||||
VIF_LOG("VIF1 DMA End");
|
||||
hwDmacIrq(DMAC_VIF1);
|
||||
|
||||
}
|
||||
|
|
|
@ -422,14 +422,13 @@ vifOp(vifCode_MSCNT) {
|
|||
// ToDo: FixMe
|
||||
vifOp(vifCode_MskPath3) {
|
||||
vif1Only();
|
||||
pass1 {
|
||||
pass1 {
|
||||
vif1Regs.mskpath3 = (vif1Regs.code >> 15) & 0x1;
|
||||
gifRegs.stat.M3P = (vif1Regs.code >> 15) & 0x1;
|
||||
GUNIT_LOG("Vif1 - MskPath3 [p3 = %s]", vif1Regs.mskpath3 ? "masked" : "enabled");
|
||||
if(!vif1Regs.mskpath3) {
|
||||
GUNIT_WARN("Path3 triggering!");
|
||||
if(CHECK_GIFFIFOHACK)gif_fifo.read(false);
|
||||
else gifInterrupt();
|
||||
GUNIT_WARN("VIF MSKPATH3 off Path3 triggering!");
|
||||
gifInterrupt();
|
||||
}
|
||||
vif1.cmd = 0;
|
||||
vif1.pass = 0;
|
||||
|
|
|
@ -81,7 +81,7 @@ Panels::GameFixesPanel::GameFixesPanel( wxWindow* parent )
|
|||
wxEmptyString
|
||||
},
|
||||
{
|
||||
_("Enable the GIF FIFO (slower but needed for Hotwheels, Wallace and Gromit, DJ Hero)"),
|
||||
_("Force GIF PATH3 transfers through FIFO (Fifa Street 2)"),
|
||||
wxEmptyString
|
||||
},
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue