/[pcsx2_0.9.7]/trunk/pcsx2/Gif.cpp
ViewVC logotype

Annotation of /trunk/pcsx2/Gif.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (9 years, 5 months ago) by william
File size: 17070 byte(s)
committing r3113 initial commit again...
1 william 31 /* PCSX2 - PS2 Emulator for PCs
2     * Copyright (C) 2002-2010 PCSX2 Dev Team
3     *
4     * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5     * of the GNU Lesser General Public License as published by the Free Software Found-
6     * ation, either version 3 of the License, or (at your option) any later version.
7     *
8     * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10     * PURPOSE. See the GNU General Public License for more details.
11     *
12     * You should have received a copy of the GNU General Public License along with PCSX2.
13     * If not, see <http://www.gnu.org/licenses/>.
14     */
15    
16     #include "PrecompiledHeader.h"
17     #include "Common.h"
18    
19     #include "GS.h"
20     #include "Gif.h"
21     #include "Vif_Dma.h"
22    
23     #include "iR5900.h"
24    
25     using std::min;
26    
27     // A three-way toggle used to determine if the GIF is stalling (transferring) or done (finished).
28     // Should be a gifstate_t rather then int, but I don't feel like possibly interfering with savestates right now.
29     static int gifstate = GIF_STATE_READY;
30     static bool gifempty = false;
31    
32     static bool gspath3done = false;
33    
34     static u32 gscycles = 0, prevcycles = 0, mfifocycles = 0;
35     static u32 gifqwc = 0;
36     static bool gifmfifoirq = false;
37    
38     static __forceinline void clearFIFOstuff(bool full)
39     {
40     GSCSRr &= ~0xC000; //Clear FIFO stuff
41    
42     if (full)
43     GSCSRr |= 0x8000; //FIFO full
44     else
45     GSCSRr |= 0x4000; //FIFO empty
46     }
47    
48     __forceinline void gsInterrupt()
49     {
50     GIF_LOG("gsInterrupt: %8.8x", cpuRegs.cycle);
51    
52     if (!(gif->chcr.STR))
53     {
54     //Console.WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", gif->chcr._u32, gif->qwc, done);
55     return;
56     }
57    
58    
59     if (GSTransferStatus.PTH3 == STOPPED_MODE)
60     {
61     gifRegs->stat.clear_flags(GIF_STAT_APATH3);
62     }
63    
64     if ((gif->qwc > 0) || (!gspath3done))
65     {
66     if (!dmacRegs->ctrl.DMAE)
67     {
68     Console.Warning("gs dma masked, re-scheduling...");
69     // re-raise the int shortly in the future
70     CPU_INT( DMAC_GIF, 64 );
71     return;
72     }
73    
74     GIFdma();
75     return;
76     }
77    
78     gspath3done = false;
79     gscycles = 0;
80     gif->chcr.STR = false;
81     vif1Regs->stat.VGW = false;
82     if(GSTransferStatus.PTH3 == 3) GSTransferStatus.PTH3 = STOPPED_MODE;
83     gifRegs->stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_FQC);
84    
85     clearFIFOstuff(false);
86     hwDmacIrq(DMAC_GIF);
87     GIF_LOG("GIF DMA end");
88     }
89    
90     static u32 WRITERING_DMA(u32 *pMem, u32 qwc)
91     {
92     int size = GetMTGS().PrepDataPacket(GIF_PATH_3, pMem, qwc);
93     u8* pgsmem = GetMTGS().GetDataPacketPtr();
94    
95     memcpy_aligned(pgsmem, pMem, size<<4);
96    
97     GetMTGS().SendDataPacket();
98     return size;
99     }
100    
101     static u32 WRITERING_DMA(tDMA_TAG *pMem, u32 qwc)
102     {
103     return WRITERING_DMA((u32*)pMem, qwc);
104     }
105    
106     int _GIFchain()
107     {
108     tDMA_TAG *pMem;
109    
110     pMem = dmaGetAddr(gif->madr, false);
111     if (pMem == NULL)
112     {
113     // reset path3, fixes dark cloud 2
114     GIFPath_Clear( GIF_PATH_3 );
115    
116     //must increment madr and clear qwc, else it loops
117     gif->madr += gif->qwc * 16;
118     gif->qwc = 0;
119     Console.Warning( "Hackfix - NULL GIFchain" );
120     return -1;
121     }
122    
123     return WRITERING_DMA(pMem, gif->qwc);
124     }
125    
126     static __forceinline void GIFchain()
127     {
128     Registers::Freeze();
129     // qwc check now done outside this function
130     // Voodoocycles
131     // >> 2 so Drakan and Tekken 5 don't mess up in some PATH3 transfer. Cycles to interrupt were getting huge..
132     /*if (gif->qwc)*/ gscycles+= ( _GIFchain() >> 2 ); /* guessing */
133     Registers::Thaw();
134     }
135    
136     static __forceinline bool checkTieBit(tDMA_TAG* &ptag)
137     {
138     if (gif->chcr.TIE && ptag->IRQ)
139     {
140     GIF_LOG("dmaIrq Set");
141     gspath3done = true;
142     return true;
143     }
144    
145     return false;
146     }
147    
148     static __forceinline tDMA_TAG* ReadTag()
149     {
150     tDMA_TAG* ptag = dmaGetAddr(gif->tadr, false); //Set memory pointer to TADR
151    
152     if (!(gif->transfer("Gif", ptag))) return NULL;
153    
154     gif->madr = ptag[1]._u32; //MADR = ADDR field + SPR
155     gscycles += 2; // Add 1 cycles from the QW read for the tag
156    
157     gspath3done = hwDmacSrcChainWithStack(gif, ptag->ID);
158     return ptag;
159     }
160    
161     static __forceinline tDMA_TAG* ReadTag2()
162     {
163     tDMA_TAG* ptag = dmaGetAddr(gif->tadr, false); //Set memory pointer to TADR
164    
165     gif->unsafeTransfer(ptag);
166     gif->madr = ptag[1]._u32;
167    
168     gspath3done = hwDmacSrcChainWithStack(gif, ptag->ID);
169     return ptag;
170     }
171    
172     void GIFdma()
173     {
174     tDMA_TAG *ptag;
175    
176     gscycles = prevcycles;
177    
178     if (gifRegs->ctrl.PSE) // temporarily stop
179     {
180     Console.WriteLn("Gif dma temp paused?");
181     return;
182     }
183    
184     if ((dmacRegs->ctrl.STD == STD_GIF) && (prevcycles != 0))
185     {
186     Console.WriteLn("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3, gif->madr, psHu32(DMAC_STADR));
187    
188     if ((gif->madr + (gif->qwc * 16)) > dmacRegs->stadr.ADDR)
189     {
190     CPU_INT(DMAC_GIF, 4);
191     gscycles = 0;
192     return;
193     }
194    
195     prevcycles = 0;
196     gif->qwc = 0;
197     }
198    
199     clearFIFOstuff(true);
200     gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
201    
202     //Path2 gets priority in intermittent mode
203     if (GSTransferStatus.PTH1 != STOPPED_MODE || GSTransferStatus.PTH2 != STOPPED_MODE)
204     {
205     // We are in image mode doing DIRECTHL, Path 1 is in queue, and in intermittant mode.
206     //GIF_LOG("Waiting VU %x, PATH2 %x, GIFMODE %x Progress %x", gifRegs->stat.P1Q, (vif1.cmd & 0x7f), gifRegs->mode._u32, GSTransferStatus.PTH3);
207     gifRegs->stat.set_flags(GIF_STAT_P3Q);
208     CPU_INT(DMAC_GIF, 16);
209     return;
210     }
211     gifRegs->stat.clear_flags(GIF_STAT_P3Q);
212     gifRegs->stat.APATH = GIF_APATH3;
213    
214     if (vif1Regs->mskpath3 || gifRegs->mode.M3R)
215     {
216     if (gif->qwc == 0)
217     {
218     if ((gif->chcr.MOD == CHAIN_MODE) && gif->chcr.STR)
219     {
220     ptag = ReadTag();
221     gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
222     if (ptag == NULL) return;
223     GIF_LOG("PTH3 MASK gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr);
224    
225     //Check TIE bit of CHCR and IRQ bit of tag
226     if (checkTieBit(ptag)) GIF_LOG("PATH3 MSK dmaIrq Set");
227     }
228     }
229    
230     if (GSTransferStatus.PTH3 == STOPPED_MODE) /*|| (vif1Regs->stat._u32 |= VIF1_STAT_VGW) == 0*/
231     {
232     GIF_LOG("PTH3 MASK Paused by VIF");
233     vif1Regs->stat.VGW = false;
234     if (gif->qwc == 0) CPU_INT(DMAC_GIF, 16);
235     return;
236     }
237     gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
238     //Check with Path3 masking games
239     if (gif->qwc > 0) {
240     GIF_LOG("PTH3 MASK Transferring");
241     GIFchain();
242     }//else DevCon.WriteLn("GIFdma() case 1, but qwc = 0!"); //Don't do 0 GIFchain and then return
243     CPU_INT(DMAC_GIF, gscycles * BIAS);
244     return;
245    
246     }
247    
248     // Transfer Dn_QWC from Dn_MADR to GIF
249     if ((gif->chcr.MOD == NORMAL_MODE) || (gif->qwc > 0)) // Normal Mode
250     {
251    
252     if ((dmacRegs->ctrl.STD == STD_GIF) && (gif->chcr.MOD == NORMAL_MODE))
253     {
254     Console.WriteLn("DMA Stall Control on GIF normal");
255     }
256     gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
257     //Check with Path3 masking games
258     if (gif->qwc > 0) {
259     GIFchain(); //Transfers the data set by the switch
260     CPU_INT(DMAC_GIF, gscycles * BIAS);
261     return;
262     } else { //Else it really is a normal transfer and we want to quit, else it gets confused with chains
263     gspath3done = 1;
264     }
265    
266     //else DevCon.WriteLn("GIFdma() case 2, but qwc = 0!"); //Don't do 0 GIFchain and then return, fixes Dual Hearts
267     }
268    
269     if ((gif->chcr.MOD == CHAIN_MODE) && (!gspath3done)) // Chain Mode
270     {
271     ptag = ReadTag();
272     if (ptag == NULL) return;
273     GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr);
274     gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
275     if (dmacRegs->ctrl.STD == STD_GIF)
276     {
277     // there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall
278     if (!gspath3done && ((gif->madr + (gif->qwc * 16)) > dmacRegs->stadr.ADDR) && (ptag->ID == TAG_REFS))
279     {
280     // stalled.
281     // We really need to test this. Pay attention to prevcycles, as it used to trigger GIFchains in the code above. (rama)
282     Console.WriteLn("GS Stall Control start Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gif->madr, psHu32(DMAC_STADR));
283     prevcycles = gscycles;
284     //gif->tadr -= 16;
285     hwDmacIrq(DMAC_STALL_SIS);
286     CPU_INT(DMAC_GIF, gscycles);
287     gscycles = 0;
288     return;
289     }
290     }
291    
292     checkTieBit(ptag);
293     }
294    
295     prevcycles = 0;
296    
297     if ((!gspath3done) && (gif->qwc == 0))
298     {
299     ptag = dmaGetAddr(gif->tadr, false); //Set memory pointer to TADR
300     gif->unsafeTransfer(ptag);
301     gif->madr = ptag[1]._u32;
302    
303     gspath3done = hwDmacSrcChainWithStack(gif, ptag->ID);
304    
305     checkTieBit(ptag);
306    
307     GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr);
308     CPU_INT(DMAC_GIF, gscycles * BIAS);
309     }
310     else
311     {
312     CPU_INT(DMAC_GIF, gscycles * BIAS);
313     gscycles = 0;
314     }
315     gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
316     }
317    
318     void dmaGIF()
319     {
320     //We used to add wait time for the buffer to fill here, fixing some timing problems in path 3 masking
321     //It takes the time of 24 QW for the BUS to become ready - The Punisher And Streetball
322     GIF_LOG("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gif->chcr._u32, gif->madr, gif->qwc, gif->tadr, gif->asr0, gif->asr1);
323    
324     //GSTransferStatus.PTH3 = STOPPED_MODE;
325     gspath3done = false; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :)
326    
327     gifRegs->stat.P3Q = true;
328     gifRegs->stat.FQC |= 0x10; // hack ;)
329    
330     clearFIFOstuff(true);
331    
332     if (dmacRegs->ctrl.MFD == MFD_GIF) // GIF MFIFO
333     {
334     //Console.WriteLn("GIF MFIFO");
335     gifMFIFOInterrupt();
336     return;
337     }
338    
339     if ((gif->qwc == 0) && (gif->chcr.MOD != NORMAL_MODE))
340     {
341     tDMA_TAG* ptag = ReadTag2();
342     GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr);
343    
344     checkTieBit(ptag);
345     GIFdma();
346     return;
347     }
348    
349     //Halflife sets a QWC amount in chain mode, no tadr set.
350     if (gif->qwc > 0) gspath3done = true;
351     if(gif->chcr.MOD == CHAIN_MODE && gif->qwc > 0) DevCon.Warning(L"GIF QWC on Chain " + gif->chcr.desc());
352    
353     GIFdma();
354     }
355    
356     // called from only one location, so forceinline it:
357     static __forceinline bool mfifoGIFrbTransfer()
358     {
359     u32 mfifoqwc = min(gifqwc, (u32)gif->qwc);
360     u32 *src;
361    
362     /* Check if the transfer should wrap around the ring buffer */
363     if ((gif->madr + mfifoqwc * 16) > (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK + 16))
364     {
365     uint s1 = ((dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK + 16) - gif->madr) >> 4;
366     uint s2 = (mfifoqwc - s1);
367     // fixme - I don't think these should use WRITERING_DMA, since our source
368     // isn't the DmaGetAddr(gif->madr) address that WRITERING_DMA expects.
369    
370     /* it does (wrap around), so first copy 's1' bytes from 'addr' to 'data' */
371     src = (u32*)PSM(gif->madr);
372     if (src == NULL) return false;
373     s1 = WRITERING_DMA(src, s1);
374    
375     if (s1 == (mfifoqwc - s2))
376     {
377     /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */
378     src = (u32*)PSM(dmacRegs->rbor.ADDR);
379     if (src == NULL) return false;
380     s2 = WRITERING_DMA(src, s2);
381     }
382     else
383     {
384     s2 = 0;
385     }
386    
387     mfifoqwc = s1 + s2;
388     }
389     else
390     {
391     /* it doesn't, so just transfer 'qwc*16' words from 'gif->madr' to GS */
392     src = (u32*)PSM(gif->madr);
393     if (src == NULL) return false;
394     mfifoqwc = WRITERING_DMA(src, mfifoqwc);
395     gif->madr = dmacRegs->rbor.ADDR + (gif->madr & dmacRegs->rbsr.RMSK);
396     }
397    
398     gifqwc -= mfifoqwc;
399    
400     return true;
401     }
402    
403     // called from only one location, so forceinline it:
404     static __forceinline bool mfifoGIFchain()
405     {
406     /* Is QWC = 0? if so there is nothing to transfer */
407     if (gif->qwc == 0) return true;
408    
409     if (gif->madr >= dmacRegs->rbor.ADDR &&
410     gif->madr <= (dmacRegs->rbor.ADDR + dmacRegs->rbsr.RMSK))
411     {
412     if (!mfifoGIFrbTransfer()) return false;
413     }
414     else
415     {
416     int mfifoqwc;
417    
418     tDMA_TAG *pMem = dmaGetAddr(gif->madr, false);
419     if (pMem == NULL) return false;
420    
421     mfifoqwc = WRITERING_DMA(pMem, gif->qwc);
422     mfifocycles += (mfifoqwc) * 2; /* guessing */
423     }
424    
425     return true;
426     }
427    
428     static u32 qwctag(u32 mask)
429     {
430     return (dmacRegs->rbor.ADDR + (mask & dmacRegs->rbsr.RMSK));
431     }
432    
433     void mfifoGIFtransfer(int qwc)
434     {
435     tDMA_TAG *ptag;
436    
437     mfifocycles = 0;
438     gifmfifoirq = false;
439    
440     if(qwc > 0 )
441     {
442     gifqwc += qwc;
443    
444     if (!(gifstate & GIF_STATE_EMPTY)) return;
445     // if (gifempty == false) return;
446     gifstate &= ~GIF_STATE_EMPTY;
447     gifempty = false;
448     }
449    
450     GIF_LOG("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr);
451    
452     if (gif->qwc == 0)
453     {
454     if (gif->tadr == spr0->madr)
455     {
456     //if( gifqwc > 1 ) DevCon.WriteLn("gif mfifo tadr==madr but qwc = %d", gifqwc);
457     hwDmacIrq(DMAC_MFIFO_EMPTY);
458     gifstate |= GIF_STATE_EMPTY;
459     gifempty = true;
460     return;
461     }
462    
463     gif->tadr = qwctag(gif->tadr);
464    
465     ptag = dmaGetAddr(gif->tadr, false);
466     gif->unsafeTransfer(ptag);
467     gif->madr = ptag[1]._u32;
468    
469     mfifocycles += 2;
470    
471     GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x",
472     ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr, gifqwc, spr0->madr);
473    
474     gifqwc--;
475    
476     switch (ptag->ID)
477     {
478     case TAG_REFE: // Refe - Transfer Packet According to ADDR field
479     gif->tadr = qwctag(gif->tadr + 16);
480     gifstate = GIF_STATE_DONE; //End Transfer
481     break;
482    
483     case TAG_CNT: // CNT - Transfer QWC following the tag.
484     gif->madr = qwctag(gif->tadr + 16); //Set MADR to QW after Tag
485     gif->tadr = qwctag(gif->madr + (gif->qwc << 4)); //Set TADR to QW following the data
486     gifstate = GIF_STATE_READY;
487     break;
488    
489     case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
490     {
491     u32 temp = gif->madr; //Temporarily Store ADDR
492     gif->madr = qwctag(gif->tadr + 16); //Set MADR to QW following the tag
493     gif->tadr = temp; //Copy temporarily stored ADDR to Tag
494     gifstate = GIF_STATE_READY;
495     break;
496     }
497    
498     case TAG_REF: // Ref - Transfer QWC from ADDR field
499     case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control)
500     gif->tadr = qwctag(gif->tadr + 16); //Set TADR to next tag
501     gifstate = GIF_STATE_READY;
502     break;
503    
504     case TAG_END: // End - Transfer QWC following the tag
505     gif->madr = qwctag(gif->tadr + 16); //Set MADR to data following the tag
506     gif->tadr = qwctag(gif->madr + (gif->qwc << 4)); //Set TADR to QW following the data
507     gifstate = GIF_STATE_DONE; //End Transfer
508     break;
509     }
510    
511     if ((gif->chcr.TIE) && (ptag->IRQ))
512     {
513     SPR_LOG("dmaIrq Set");
514     gifstate = GIF_STATE_DONE;
515     gifmfifoirq = true;
516     }
517     }
518    
519     Registers::Freeze();
520     if (!mfifoGIFchain())
521     {
522     Console.WriteLn("GIF dmaChain error size=%d, madr=%lx, tadr=%lx", gif->qwc, gif->madr, gif->tadr);
523     gifstate = GIF_STATE_STALL;
524     }
525     Registers::Thaw();
526    
527     if ((gif->qwc == 0) && (gifstate & GIF_STATE_DONE)) gifstate = GIF_STATE_STALL;
528     CPU_INT(11,mfifocycles);
529    
530     SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr);
531     }
532    
533     void gifMFIFOInterrupt()
534     {
535     //Console.WriteLn("gifMFIFOInterrupt");
536     mfifocycles = 0;
537    
538     if (GSTransferStatus.PTH3 == STOPPED_MODE)
539     {
540     gifRegs->stat.APATH = GIF_APATH_IDLE;
541     }
542    
543     if ((spr0->chcr.STR) && (spr0->qwc == 0))
544     {
545     spr0->chcr.STR = false;
546     hwDmacIrq(DMAC_FROM_SPR);
547     }
548    
549     if (!(gif->chcr.STR))
550     {
551     Console.WriteLn("WTF GIFMFIFO");
552     cpuRegs.interrupt &= ~(1 << 11);
553     return;
554     }
555    
556     if ((gifRegs->stat.P1Q || (vif1.cmd & 0x7f) == 0x50) && gifRegs->mode.IMT && GSTransferStatus.PTH3 == IMAGE_MODE) //Path2 gets priority in intermittent mode
557     {
558     //GIF_LOG("Waiting VU %x, PATH2 %x, GIFMODE %x Progress %x", psHu32(GIF_STAT) & 0x100, (vif1.cmd & 0x7f), psHu32(GIF_MODE), GSTransferStatus.PTH3);
559     CPU_INT(11,mfifocycles);
560     return;
561     }
562    
563     if (!(gifstate & GIF_STATE_STALL))
564     {
565     if (gifqwc <= 0)
566     {
567     //Console.WriteLn("Empty");
568     hwDmacIrq(DMAC_MFIFO_EMPTY);
569     gifstate |= GIF_STATE_EMPTY;
570     gifempty = true;
571    
572     gifRegs->stat.IMT = false;
573     return;
574     }
575     mfifoGIFtransfer(0);
576     return;
577     }
578    
579     #ifdef PCSX2_DEVBUILD
580     if ((gifstate & GIF_STATE_READY) || (gif->qwc > 0))
581     {
582     Console.Error("gifMFIFO Panic > Shouldn't go here!");
583     return;
584     }
585     #endif
586     //if(gifqwc > 0) Console.WriteLn("GIF MFIFO ending with stuff in it %x", gifqwc);
587     if (!gifmfifoirq) gifqwc = 0;
588    
589     gspath3done = false;
590     gscycles = 0;
591    
592     gifRegs->stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_P3Q | GIF_STAT_FQC); // APATH, P3Q, FQC = 0
593    
594     vif1Regs->stat.VGW = false;
595     gif->chcr.STR = false;
596     gifstate = GIF_STATE_READY;
597     hwDmacIrq(DMAC_GIF);
598     clearFIFOstuff(false);
599     }
600    
601     void SaveStateBase::gifFreeze()
602     {
603     FreezeTag( "GIFdma" );
604    
605     Freeze( gifstate );
606     Freeze( gifqwc );
607     Freeze( gspath3done );
608     Freeze( gscycles );
609     //Freeze(gifempty);
610     // Note: mfifocycles is not a persistent var, so no need to save it here.
611     }

  ViewVC Help
Powered by ViewVC 1.1.22