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

Contents of /trunk/pcsx2/Gif.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (9 years, 9 months ago) by william
File size: 17070 byte(s)
committing r3113 initial commit again...
1 /* 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