/[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 401 - (show annotations) (download)
Fri Feb 25 17:31:09 2011 UTC (8 years, 11 months ago) by william
File size: 19736 byte(s)
Auto Commited Import of: pcsx2-0.9.7-DEBUG (upstream: v0.9.7.4358 local: v0.9.7.313-latest) in ./trunk
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
31 static bool gspath3done = false;
32
33 static u32 gscycles = 0, prevcycles = 0, mfifocycles = 0;
34 static u32 gifqwc = 0;
35 static bool gifmfifoirq = false;
36
37 //Just some temporary bits to store Path1 transfers if another is in progress.
38 __aligned16 u8 Path1Buffer[0x1000000];
39 u32 Path1WritePos = 0;
40 u32 Path1ReadPos = 0;
41
42 static __fi void clearFIFOstuff(bool full)
43 {
44 if (full)
45 CSRreg.FIFO = CSR_FIFO_FULL;
46 else
47 CSRreg.FIFO = CSR_FIFO_EMPTY;
48 }
49 extern bool SIGNAL_IMR_Pending;
50 void gsPath1Interrupt()
51 {
52 //DevCon.Warning("Path1 flush W %x, R %x", Path1WritePos, Path1ReadPos);
53
54
55
56 if((gifRegs.stat.APATH <= GIF_APATH1 || (gifRegs.stat.IP3 == true)) && Path1WritePos > 0 && !gifRegs.stat.PSE && SIGNAL_IMR_Pending == false)
57 {
58 gifRegs.stat.P1Q = false;
59
60 if (uint size = (Path1WritePos - Path1ReadPos))
61 {
62 GetMTGS().PrepDataPacket(GIF_PATH_1, size);
63 //DevCon.Warning("Flush Size = %x", size);
64 while(size > 0 && SIGNAL_IMR_Pending == false)
65 {
66 uint count = GIFPath_CopyTag(GIF_PATH_1, ((u128*)Path1Buffer) + Path1ReadPos, size);
67 Path1ReadPos += count;
68 size -= count;
69
70 if(GSTransferStatus.PTH1 == STOPPED_MODE)
71 {
72 gifRegs.stat.OPH = false;
73 gifRegs.stat.APATH = GIF_APATH_IDLE;
74 }
75 }
76 GetMTGS().SendDataPacket();
77
78 if(Path1ReadPos == Path1WritePos)
79 {
80 Path1WritePos = Path1ReadPos = 0;
81 }
82 else
83 {
84 //DevCon.Warning("Queue quitting early due to signal or EOP %x", size);
85 gifRegs.stat.P1Q = true;
86 }
87 }
88 }
89 else
90 {
91 if(gifRegs.stat.PSE) DevCon.Warning("Path1 paused by GIF_CTRL");
92 if(gifRegs.stat.P1Q == false && Path1ReadPos != Path1WritePos)
93 {
94 DevCon.Warning("Wa's Goin on ere then?");
95 gifRegs.stat.P1Q = true;
96 }
97 //DevCon.Warning("Looping??? IP3 %x APATH %x OPH %x", gifRegs.stat.IP3, gifRegs.stat.APATH, gifRegs.stat.OPH);
98 //if(!(cpuRegs.interrupt & (1<<28)) && Path1WritePos > 0)CPU_INT(28, 128);
99 }
100
101 }
102
103 extern bool SIGNAL_IMR_Pending;
104
105 __fi void gsInterrupt()
106 {
107 GIF_LOG("gsInterrupt caught!");
108
109 if (dmacRegs.ctrl.MFD == MFD_GIF) // GIF MFIFO
110 {
111 //Console.WriteLn("GIF MFIFO");
112 gifMFIFOInterrupt();
113 return;
114 }
115
116 if(SIGNAL_IMR_Pending == true)
117 {
118 //DevCon.Warning("Path 3 Paused");
119 CPU_INT(DMAC_GIF, 128);
120 return;
121 }
122
123 if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE)
124 {
125 GSTransferStatus.PTH3 = STOPPED_MODE;
126
127 if(gifRegs.stat.APATH == GIF_APATH3)
128 {
129 gifRegs.stat.APATH = GIF_APATH_IDLE;
130 gifRegs.stat.OPH = false;
131 if(gifRegs.stat.P1Q) gsPath1Interrupt();
132 }
133 }
134
135
136 if (!(gifch.chcr.STR))
137 {
138 //Console.WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", gifch.chcr._u32, gifch.qwc, done);
139 return;
140 }
141
142
143 if ((gifch.qwc > 0) || (!gspath3done))
144 {
145 if (!dmacRegs.ctrl.DMAE)
146 {
147 Console.Warning("gs dma masked, re-scheduling...");
148 // re-raise the int shortly in the future
149 CPU_INT( DMAC_GIF, 64 );
150 return;
151 }
152
153 GIFdma();
154 return;
155 }
156
157 gspath3done = false;
158 gscycles = 0;
159 gifch.chcr.STR = false;
160
161 ////
162 /*gifRegs.stat.OPH = false;
163 GSTransferStatus.PTH3 = STOPPED_MODE;
164 gifRegs.stat.APATH = GIF_APATH_IDLE;*/
165 ////
166 gifRegs.stat.clear_flags(GIF_STAT_FQC);
167 clearFIFOstuff(false);
168 hwDmacIrq(DMAC_GIF);
169 DMA_LOG("GIF DMA End");
170 }
171
172 static u32 WRITERING_DMA(u32 *pMem, u32 qwc)
173 {
174 GetMTGS().PrepDataPacket(GIF_PATH_3, qwc);
175 uint size = GIFPath_CopyTag(GIF_PATH_3, (u128*)pMem, qwc );
176 GetMTGS().SendDataPacket();
177 return size;
178 }
179
180 static u32 WRITERING_DMA(tDMA_TAG *pMem, u32 qwc)
181 {
182 return WRITERING_DMA((u32*)pMem, qwc);
183 }
184
185 int _GIFchain()
186 {
187 tDMA_TAG *pMem;
188
189 pMem = dmaGetAddr(gifch.madr, false);
190 if (pMem == NULL)
191 {
192 // reset path3, fixes dark cloud 2
193 GIFPath_Clear( GIF_PATH_3 );
194
195 //must increment madr and clear qwc, else it loops
196 gifch.madr += gifch.qwc * 16;
197 gifch.qwc = 0;
198 Console.Warning( "Hackfix - NULL GIFchain" );
199 return -1;
200 }
201
202 return WRITERING_DMA(pMem, gifch.qwc);
203 }
204
205 static __fi void GIFchain()
206 {
207 // qwc check now done outside this function
208 // Voodoocycles
209 // >> 2 so Drakan and Tekken 5 don't mess up in some PATH3 transfer. Cycles to interrupt were getting huge..
210 /*if (gifch.qwc)*/ gscycles+= ( _GIFchain() * BIAS); /* guessing */
211 }
212
213 static __fi bool checkTieBit(tDMA_TAG* &ptag)
214 {
215 if (gifch.chcr.TIE && ptag->IRQ)
216 {
217 GIF_LOG("dmaIrq Set");
218 gspath3done = true;
219 return true;
220 }
221
222 return false;
223 }
224
225 static __fi tDMA_TAG* ReadTag()
226 {
227 tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); //Set memory pointer to TADR
228
229 if (!(gifch.transfer("Gif", ptag))) return NULL;
230
231 gifch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
232 gscycles += 2; // Add 1 cycles from the QW read for the tag
233
234 gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
235 return ptag;
236 }
237
238 static __fi tDMA_TAG* ReadTag2()
239 {
240 tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); //Set memory pointer to TADR
241
242 gifch.unsafeTransfer(ptag);
243 gifch.madr = ptag[1]._u32;
244
245 gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
246 return ptag;
247 }
248
249 bool CheckPaths(int Channel)
250 {
251 if((GSTransferStatus.PTH3 == IMAGE_MODE && gifRegs.mode.IMT) /*|| GSTransferStatus.PTH3 == WAITING_MODE*/)
252 {
253 if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3))
254 {
255 if((vif1.cmd & 0x7f) != 0x51 || gifRegs.stat.P1Q == true)
256 {
257 //DevCon.Warning("GIF Stall 1 P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
258 gifRegs.stat.IP3 = true;
259 if(gifRegs.stat.P1Q) gsPath1Interrupt();
260 CPU_INT(DMAC_GIF, 16);
261 return false;
262 }
263 }
264 }
265 else if(GSTransferStatus.PTH3 == STOPPED_MODE)
266 {
267 //This should cover both scenarios, as DIRECTHL doesn't gain priority when image mode is running (PENDINGIMAGE_MODE == fininshed).
268 if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3) || vif1Regs.stat.VGW == true)
269 {
270 //DevCon.Warning("GIF Stall 2 P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
271 gifRegs.stat.IP3 = true;
272 if(gifRegs.stat.P1Q) gsPath1Interrupt();
273 CPU_INT(DMAC_GIF, 16);
274 return false;
275 }
276 }
277
278 gifRegs.stat.IP3 = false;
279 return true;
280 }
281
282 void GIFdma()
283 {
284 tDMA_TAG *ptag;
285
286 gscycles = prevcycles;
287
288 if (gifRegs.ctrl.PSE) // temporarily stop
289 {
290 Console.WriteLn("Gif dma temp paused? (non MFIFO GIF)");
291 CPU_INT(DMAC_GIF, 16);
292 return;
293 }
294
295 if ((dmacRegs.ctrl.STD == STD_GIF) && (prevcycles != 0))
296 {
297 //Console.WriteLn("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3, gifch.madr, psHu32(DMAC_STADR));
298
299 if ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR)
300 {
301 CPU_INT(DMAC_GIF, 4);
302 gscycles = 0;
303 return;
304 }
305
306 prevcycles = 0;
307 gifch.qwc = 0;
308 }
309
310
311
312 if ((gifch.chcr.MOD == CHAIN_MODE) && (!gspath3done) && gifch.qwc == 0) // Chain Mode
313 {
314 ptag = ReadTag();
315 if (ptag == NULL) return;
316 //DevCon.Warning("GIF Reading Tag MSK = %x", vif1Regs.mskpath3);
317 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);
318 gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
319 if (dmacRegs.ctrl.STD == STD_GIF)
320 {
321 // there are still bugs, need to also check if gifch.madr +16*qwc >= stadr, if not, stall
322 if (!gspath3done && ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR) && (ptag->ID == TAG_REFS))
323 {
324 // stalled.
325 // We really need to test this. Pay attention to prevcycles, as it used to trigger GIFchains in the code above. (rama)
326 //Console.WriteLn("GS Stall Control start Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gifch.madr, psHu32(DMAC_STADR));
327 prevcycles = gscycles;
328 gifch.tadr -= 16;
329 gifch.qwc = 0;
330 hwDmacIrq(DMAC_STALL_SIS);
331 CPU_INT(DMAC_GIF, gscycles);
332 gscycles = 0;
333 return;
334 }
335 }
336
337 checkTieBit(ptag);
338 }
339
340 clearFIFOstuff(true);
341 gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
342
343 if (vif1Regs.mskpath3 || gifRegs.mode.M3R)
344 {
345 if (GSTransferStatus.PTH3 == STOPPED_MODE)
346 {
347 MSKPATH3_LOG("Path3 Paused by VIF QWC %x", gifch.qwc);
348
349 if(gifch.qwc == 0) CPU_INT(DMAC_GIF, 4);
350 else gifRegs.stat.set_flags(GIF_STAT_P3Q);
351 return;
352 }
353 }
354
355 // Transfer Dn_QWC from Dn_MADR to GIF
356 if (gifch.qwc > 0) // Normal Mode
357 {
358 gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
359
360 gifRegs.stat.set_flags(GIF_STAT_P3Q);
361
362 if(CheckPaths(DMAC_GIF) == false)
363 return;
364
365 gifRegs.stat.clear_flags(GIF_STAT_P3Q);
366
367 GIFchain(); //Transfers the data set by the switch
368 CPU_INT(DMAC_GIF, gscycles);
369 return;
370 }
371
372 prevcycles = 0;
373 CPU_INT(DMAC_GIF, gscycles);
374 gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3]
375 }
376
377 void dmaGIF()
378 {
379 //We used to add wait time for the buffer to fill here, fixing some timing problems in path 3 masking
380 //It takes the time of 24 QW for the BUS to become ready - The Punisher And Streetball
381 //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);
382
383 gspath3done = false; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :)
384
385 gifRegs.stat.FQC |= 0x10; // hack ;)
386
387 if (gifch.chcr.MOD == NORMAL_MODE) { //Else it really is a normal transfer and we want to quit, else it gets confused with chains
388 gspath3done = true;
389 }
390 clearFIFOstuff(true);
391
392 if(gifch.chcr.MOD == CHAIN_MODE && gifch.qwc > 0)
393 {
394 //DevCon.Warning(L"GIF QWC on Chain " + gifch.chcr.desc());
395 if ((gifch.chcr.tag().ID == TAG_REFE) || (gifch.chcr.tag().ID == TAG_END))
396 {
397 gspath3done = true;
398 }
399 }
400
401
402
403 gsInterrupt();
404 }
405
406 static u16 QWCinGIFMFIFO(u32 DrainADDR)
407 {
408 u32 ret;
409
410
411 GIF_LOG("GIF MFIFO Requesting %x QWC from the MFIFO Base %x, SPR MADR %x Drain %x", gifch.qwc, dmacRegs.rbor.ADDR, spr0ch.madr, DrainADDR);
412 //Calculate what we have in the fifo.
413 if(DrainADDR <= spr0ch.madr)
414 {
415 //Drain is below the tadr, calculate the difference between them
416 ret = (spr0ch.madr - DrainADDR) >> 4;
417 }
418 else
419 {
420 u32 limit = dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16;
421 //Drain is higher than SPR so it has looped round,
422 //calculate from base to the SPR tag addr and what is left in the top of the ring
423 ret = ((spr0ch.madr - dmacRegs.rbor.ADDR) + (limit - DrainADDR)) >> 4;
424 }
425 GIF_LOG("%x Available of the %x requested", ret, gifch.qwc);
426 if((s32)ret < 0) DevCon.Warning("GIF Returning %x!", ret);
427 return ret;
428 }
429
430 // called from only one location, so forceinline it:
431 static __fi bool mfifoGIFrbTransfer()
432 {
433 u16 mfifoqwc = min(QWCinGIFMFIFO(gifch.madr), gifch.qwc);
434 u32 *src;
435
436 if(mfifoqwc == 0) return true; //Lets skip all this, we don't have the data
437
438 GetMTGS().PrepDataPacket(GIF_PATH_3, mfifoqwc);
439
440 // TODO (minor optimization): The new GIFpath parser can do rather efficient wrapping of
441 // its own internally now. We just need to groom a version of it that can wrap around MFIFO
442 // memory similarly to how it wraps VU1 memory on PATH1.
443 GIF_LOG("MFIFO QWC to Transfer %x", mfifoqwc);
444 /* Check if the transfer should wrap around the ring buffer */
445 if ( (gifch.madr + (mfifoqwc * 16)) > (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16))
446 {
447 uint s1 = ((dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16) - gifch.madr) >> 4;
448 uint s2 = (mfifoqwc - s1);
449 GIF_LOG("Split transfer doing %x QWC of %x Total QWC", s1, mfifoqwc);
450 /* it does (wrap around), so first copy 's1' bytes from 'addr' to 'data' */
451 /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */
452
453 gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK);
454 src = (u32*)PSM(gifch.madr);
455 if (src == NULL) return false;
456 uint copied = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s1);
457
458 if (copied == s1) // but only copy second if first didn't abort prematurely for some reason.
459 {
460 GIF_LOG("Transferring last %x QWC", s2);
461 src = (u32*)PSM(dmacRegs.rbor.ADDR);
462 gifch.madr = dmacRegs.rbor.ADDR;
463 if (src == NULL) return false;
464 copied += GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s2);
465 }
466
467 mfifoqwc = copied;
468 GIF_LOG("Copied %x QWC, %x QWC Left", mfifoqwc, gifch.qwc);
469 }
470 else
471 {
472 GIF_LOG("Direct MFIFO transfer doing %x Total QWC", mfifoqwc);
473 /* it doesn't, so just transfer 'qwc*16' words from 'gifch.madr' to GS */
474
475 gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK);
476 src = (u32*)PSM(gifch.madr);
477 if (src == NULL) return false;
478 mfifoqwc = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, mfifoqwc);
479 GIF_LOG("%X QWC Copied direct %x QWC Left", mfifoqwc, gifch.qwc);
480 }
481
482 GetMTGS().SendDataPacket();
483 //gifqwc -= mfifoqwc;
484 mfifocycles += (mfifoqwc) * 2; /* guessing */
485
486 return true;
487 }
488
489 // called from only one location, so forceinline it:
490 static __fi bool mfifoGIFchain()
491 {
492 /* Is QWC = 0? if so there is nothing to transfer */
493 if (gifch.qwc == 0) return true;
494
495 if (gifch.madr >= dmacRegs.rbor.ADDR &&
496 gifch.madr <= (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16))
497 {
498 bool ret = true;
499 // if(gifch.madr == (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) DevCon.Warning("Edge GIF");
500 if (!mfifoGIFrbTransfer()) ret = false;
501 if(QWCinGIFMFIFO(gifch.madr) == 0) gifstate |= GIF_STATE_EMPTY;
502
503 //Make sure we wrap the addresses, dont want it being stuck outside the ring when reading from the ring!
504 gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK);
505 gifch.tadr = dmacRegs.rbor.ADDR + (gifch.tadr & dmacRegs.rbsr.RMSK); //Check this too, tadr can suffer the same issue.
506
507 return ret;
508
509 }
510 else
511 {
512 int mfifoqwc;
513 GIF_LOG("Non-MFIFO Location transfer doing %x Total QWC", gifch.qwc);
514 tDMA_TAG *pMem = dmaGetAddr(gifch.madr, false);
515 if (pMem == NULL) return false;
516
517 mfifoqwc = WRITERING_DMA(pMem, gifch.qwc);
518 mfifocycles += (mfifoqwc) * 2; /* guessing */
519 }
520
521 return true;
522 }
523
524 static u32 qwctag(u32 mask)
525 {
526 return (dmacRegs.rbor.ADDR + (mask & dmacRegs.rbsr.RMSK));
527 }
528
529 void mfifoGIFtransfer(int qwc)
530 {
531 tDMA_TAG *ptag;
532
533 mfifocycles = 0;
534 gifmfifoirq = false;
535
536 if(qwc > 0 )
537 {
538 if ((gifstate & GIF_STATE_EMPTY))
539 {
540 if(gifch.chcr.STR == true && !(cpuRegs.interrupt & (1<<DMAC_MFIFO_GIF)))
541 CPU_INT(DMAC_MFIFO_GIF, 4);
542
543 gifstate &= ~GIF_STATE_EMPTY;
544 }
545
546 gifRegs.stat.FQC = 16;
547 return;
548 }
549
550 if (gifRegs.ctrl.PSE) // temporarily stop
551 {
552 Console.WriteLn("Gif dma temp paused?");
553 CPU_INT(DMAC_MFIFO_GIF, 16);
554 return;
555 }
556
557 if (gifch.qwc == 0)
558 {
559 gifch.tadr = qwctag(gifch.tadr);
560
561 ptag = dmaGetAddr(gifch.tadr, false);
562 gifch.unsafeTransfer(ptag);
563 gifch.madr = ptag[1]._u32;
564
565 mfifocycles += 2;
566
567 GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x",
568 ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr, gifqwc, spr0ch.madr);
569
570 gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
571
572 if(gspath3done == true) gifstate = GIF_STATE_DONE;
573 else gifstate = GIF_STATE_READY;
574
575 if ((gifch.chcr.TIE) && (ptag->IRQ))
576 {
577 SPR_LOG("dmaIrq Set");
578 gifstate = GIF_STATE_DONE;
579 gifmfifoirq = true;
580 }
581 if (QWCinGIFMFIFO(gifch.tadr) == 0) gifstate |= GIF_STATE_EMPTY;
582 }
583
584 if (vif1Regs.mskpath3 || gifRegs.mode.M3R)
585 {
586 if ((gifch.qwc == 0) && (gifstate & GIF_STATE_DONE)) gifstate |= GIF_STATE_STALL;
587
588 if (GSTransferStatus.PTH3 == STOPPED_MODE)
589 {
590 DevCon.Warning("GIFMFIFO PTH3 MASK Paused by VIF QWC %x");
591
592 MSKPATH3_LOG("Path3 Paused by VIF Idling");
593 gifRegs.stat.set_flags(GIF_STAT_P3Q);
594 return;
595 }
596 }
597 if (!mfifoGIFchain())
598 {
599 Console.WriteLn("GIF dmaChain error size=%d, madr=%lx, tadr=%lx", gifch.qwc, gifch.madr, gifch.tadr);
600 gifstate = GIF_STATE_STALL;
601 }
602
603 if ((gifch.qwc == 0) && (gifstate & GIF_STATE_DONE)) gifstate |= GIF_STATE_STALL;
604 CPU_INT(DMAC_MFIFO_GIF,mfifocycles);
605
606 SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x", gifch.chcr._u32, gifch.madr, gifch.tadr);
607 }
608
609 void gifMFIFOInterrupt()
610 {
611 GIF_LOG("gifMFIFOInterrupt");
612 mfifocycles = 0;
613
614 if (dmacRegs.ctrl.MFD != MFD_GIF)
615 {
616 DevCon.Warning("Not in GIF MFIFO mode! Stopping GIF MFIFO");
617 return;
618 }
619
620 if(SIGNAL_IMR_Pending == true)
621 {
622 //DevCon.Warning("Path 3 Paused");
623 CPU_INT(DMAC_MFIFO_GIF, 128);
624 return;
625 }
626
627 if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE)
628 {
629 GSTransferStatus.PTH3 = STOPPED_MODE;
630
631 if(gifRegs.stat.APATH == GIF_APATH3)
632 {
633 gifRegs.stat.APATH = GIF_APATH_IDLE;
634 gifRegs.stat.OPH = false;
635 if(gifRegs.stat.P1Q) gsPath1Interrupt();
636 }
637 }
638
639 if((gifstate & GIF_STATE_EMPTY))
640 {
641 FireMFIFOEmpty();
642 if(!(gifstate & GIF_STATE_STALL)) return;
643 }
644
645 if(CheckPaths(11) == false) return;
646
647 if (!(gifch.chcr.STR))
648 {
649 Console.WriteLn("WTF GIFMFIFO");
650 cpuRegs.interrupt &= ~(1 << 11);
651 return;
652 }
653
654 if (!(gifstate & GIF_STATE_STALL))
655 {
656 if (QWCinGIFMFIFO(gifch.tadr) == 0)
657 {
658 gifstate |= GIF_STATE_EMPTY;
659 CPU_INT(DMAC_MFIFO_GIF, 4);
660 return;
661 }
662
663 mfifoGIFtransfer(0);
664 return;
665 }
666
667 #ifdef PCSX2_DEVBUILD
668 if ((gifstate & GIF_STATE_READY) || (gifch.qwc > 0))
669 {
670 Console.Error("gifMFIFO Panic > Shouldn't go here!");
671 return;
672 }
673 #endif
674 //if(gifqwc > 0) Console.WriteLn("GIF MFIFO ending with stuff in it %x", gifqwc);
675 if (!gifmfifoirq) gifqwc = 0;
676
677 gspath3done = false;
678 gscycles = 0;
679
680 gifRegs.stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_P3Q | GIF_STAT_FQC); // APATH, P3Q, FQC = 0
681
682 vif1Regs.stat.VGW = false;
683 gifch.chcr.STR = false;
684 gifstate = GIF_STATE_READY;
685 hwDmacIrq(DMAC_GIF);
686 DMA_LOG("GIF MFIFO DMA End");
687 clearFIFOstuff(false);
688 }
689
690 void SaveStateBase::gifFreeze()
691 {
692 FreezeTag( "GIFdma" );
693
694 Freeze( gifstate );
695 Freeze( gifqwc );
696 Freeze( gspath3done );
697 Freeze( gscycles );
698 // Note: mfifocycles is not a persistent var, so no need to save it here.
699
700 int bufsize = Path1WritePos - Path1ReadPos;
701 Freeze(bufsize);
702
703 if (IsSaving())
704 {
705 // We can just load the queued Path1 data into the front of the buffer, and
706 // reset the ReadPos and WritePos accordingly.
707 FreezeMem(Path1Buffer, bufsize);
708 Path1ReadPos = 0;
709 Path1WritePos = bufsize;
710 }
711 else
712 {
713 // Only want to save the actual Path1 data between readpos and writepos. The
714 // rest of the buffer is just unused-ness!
715 FreezeMem(&Path1Buffer[Path1ReadPos], bufsize);
716 }
717 }

  ViewVC Help
Powered by ViewVC 1.1.22