/[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 401 - (hide 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 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    
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 william 62 //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 william 31 {
44     if (full)
45 william 62 CSRreg.FIFO = CSR_FIFO_FULL;
46 william 31 else
47 william 62 CSRreg.FIFO = CSR_FIFO_EMPTY;
48 william 31 }
49 william 280 extern bool SIGNAL_IMR_Pending;
50 william 62 void gsPath1Interrupt()
51 william 31 {
52 william 62 //DevCon.Warning("Path1 flush W %x, R %x", Path1WritePos, Path1ReadPos);
53    
54    
55    
56 william 401 if((gifRegs.stat.APATH <= GIF_APATH1 || (gifRegs.stat.IP3 == true)) && Path1WritePos > 0 && !gifRegs.stat.PSE && SIGNAL_IMR_Pending == false)
57 william 62 {
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 william 280 while(size > 0 && SIGNAL_IMR_Pending == false)
65 william 62 {
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 william 280 }
82     else
83     {
84     //DevCon.Warning("Queue quitting early due to signal or EOP %x", size);
85     gifRegs.stat.P1Q = true;
86 william 62 }
87     }
88     }
89     else
90     {
91     if(gifRegs.stat.PSE) DevCon.Warning("Path1 paused by GIF_CTRL");
92 william 401 if(gifRegs.stat.P1Q == false && Path1ReadPos != Path1WritePos)
93     {
94     DevCon.Warning("Wa's Goin on ere then?");
95     gifRegs.stat.P1Q = true;
96     }
97 william 280 //DevCon.Warning("Looping??? IP3 %x APATH %x OPH %x", gifRegs.stat.IP3, gifRegs.stat.APATH, gifRegs.stat.OPH);
98 william 62 //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 william 283 GIF_LOG("gsInterrupt caught!");
108 william 31
109 william 280 if (dmacRegs.ctrl.MFD == MFD_GIF) // GIF MFIFO
110     {
111     //Console.WriteLn("GIF MFIFO");
112     gifMFIFOInterrupt();
113     return;
114     }
115    
116 william 62 if(SIGNAL_IMR_Pending == true)
117 william 31 {
118 william 62 //DevCon.Warning("Path 3 Paused");
119     CPU_INT(DMAC_GIF, 128);
120 william 31 return;
121     }
122    
123 william 401 if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE)
124     {
125 william 62 GSTransferStatus.PTH3 = STOPPED_MODE;
126 william 401
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 william 62 }
134    
135 william 31
136 william 62 if (!(gifch.chcr.STR))
137 william 31 {
138 william 62 //Console.WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", gifch.chcr._u32, gifch.qwc, done);
139     return;
140 william 31 }
141    
142 william 62
143     if ((gifch.qwc > 0) || (!gspath3done))
144 william 31 {
145 william 62 if (!dmacRegs.ctrl.DMAE)
146 william 31 {
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 william 62 gifch.chcr.STR = false;
160 william 31
161 william 62 ////
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 william 31 clearFIFOstuff(false);
168     hwDmacIrq(DMAC_GIF);
169 william 401 DMA_LOG("GIF DMA End");
170 william 31 }
171    
172     static u32 WRITERING_DMA(u32 *pMem, u32 qwc)
173     {
174 william 62 GetMTGS().PrepDataPacket(GIF_PATH_3, qwc);
175     uint size = GIFPath_CopyTag(GIF_PATH_3, (u128*)pMem, qwc );
176 william 31 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 william 62 pMem = dmaGetAddr(gifch.madr, false);
190 william 31 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 william 62 gifch.madr += gifch.qwc * 16;
197     gifch.qwc = 0;
198 william 31 Console.Warning( "Hackfix - NULL GIFchain" );
199     return -1;
200     }
201    
202 william 62 return WRITERING_DMA(pMem, gifch.qwc);
203 william 31 }
204    
205 william 62 static __fi void GIFchain()
206 william 31 {
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 william 62 /*if (gifch.qwc)*/ gscycles+= ( _GIFchain() * BIAS); /* guessing */
211 william 31 }
212    
213 william 62 static __fi bool checkTieBit(tDMA_TAG* &ptag)
214 william 31 {
215 william 62 if (gifch.chcr.TIE && ptag->IRQ)
216 william 31 {
217     GIF_LOG("dmaIrq Set");
218     gspath3done = true;
219     return true;
220     }
221    
222     return false;
223     }
224    
225 william 62 static __fi tDMA_TAG* ReadTag()
226 william 31 {
227 william 62 tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); //Set memory pointer to TADR
228 william 31
229 william 62 if (!(gifch.transfer("Gif", ptag))) return NULL;
230 william 31
231 william 62 gifch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
232 william 31 gscycles += 2; // Add 1 cycles from the QW read for the tag
233    
234 william 62 gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
235 william 31 return ptag;
236     }
237    
238 william 62 static __fi tDMA_TAG* ReadTag2()
239 william 31 {
240 william 62 tDMA_TAG* ptag = dmaGetAddr(gifch.tadr, false); //Set memory pointer to TADR
241 william 31
242 william 62 gifch.unsafeTransfer(ptag);
243     gifch.madr = ptag[1]._u32;
244 william 31
245 william 62 gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
246 william 31 return ptag;
247     }
248    
249 william 62 bool CheckPaths(int Channel)
250     {
251 william 401 if((GSTransferStatus.PTH3 == IMAGE_MODE && gifRegs.mode.IMT) /*|| GSTransferStatus.PTH3 == WAITING_MODE*/)
252 william 62 {
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 william 280 //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 william 62 gifRegs.stat.IP3 = true;
259     if(gifRegs.stat.P1Q) gsPath1Interrupt();
260     CPU_INT(DMAC_GIF, 16);
261     return false;
262     }
263     }
264     }
265 william 401 else if(GSTransferStatus.PTH3 == STOPPED_MODE)
266 william 62 {
267     //This should cover both scenarios, as DIRECTHL doesn't gain priority when image mode is running (PENDINGIMAGE_MODE == fininshed).
268 william 401 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 william 62 {
270 william 280 //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 william 62 gifRegs.stat.IP3 = true;
272 william 401 if(gifRegs.stat.P1Q) gsPath1Interrupt();
273 william 62 CPU_INT(DMAC_GIF, 16);
274     return false;
275     }
276     }
277    
278     gifRegs.stat.IP3 = false;
279     return true;
280     }
281    
282 william 31 void GIFdma()
283     {
284     tDMA_TAG *ptag;
285    
286     gscycles = prevcycles;
287    
288 william 62 if (gifRegs.ctrl.PSE) // temporarily stop
289 william 31 {
290 william 62 Console.WriteLn("Gif dma temp paused? (non MFIFO GIF)");
291     CPU_INT(DMAC_GIF, 16);
292 william 31 return;
293     }
294    
295 william 62 if ((dmacRegs.ctrl.STD == STD_GIF) && (prevcycles != 0))
296 william 31 {
297 william 62 //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 william 31
299 william 62 if ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR)
300 william 31 {
301     CPU_INT(DMAC_GIF, 4);
302     gscycles = 0;
303     return;
304     }
305    
306     prevcycles = 0;
307 william 62 gifch.qwc = 0;
308 william 31 }
309    
310 william 62
311    
312 william 401 if ((gifch.chcr.MOD == CHAIN_MODE) && (!gspath3done) && gifch.qwc == 0) // Chain Mode
313 william 31 {
314     ptag = ReadTag();
315     if (ptag == NULL) return;
316 william 62 //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 william 31 {
321 william 62 // 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 william 31 {
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 william 62 //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 william 31 prevcycles = gscycles;
328 william 62 gifch.tadr -= 16;
329     gifch.qwc = 0;
330 william 31 hwDmacIrq(DMAC_STALL_SIS);
331     CPU_INT(DMAC_GIF, gscycles);
332     gscycles = 0;
333     return;
334     }
335     }
336    
337     checkTieBit(ptag);
338 william 401 }
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 william 62 {
347 william 401 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 william 62 return;
352 william 401 }
353 william 31 }
354    
355 william 401 // 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 william 31 prevcycles = 0;
373 william 62 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 william 31 }
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 william 62 //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 william 31
383     gspath3done = false; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :)
384    
385 william 62 gifRegs.stat.FQC |= 0x10; // hack ;)
386 william 31
387 william 62 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 william 31 clearFIFOstuff(true);
391    
392 william 62 if(gifch.chcr.MOD == CHAIN_MODE && gifch.qwc > 0)
393 william 31 {
394 william 62 //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 william 31 }
400    
401 william 280
402 william 31
403 william 280 gsInterrupt();
404 william 31 }
405    
406 william 280 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 william 31 // called from only one location, so forceinline it:
431 william 62 static __fi bool mfifoGIFrbTransfer()
432 william 31 {
433 william 280 u16 mfifoqwc = min(QWCinGIFMFIFO(gifch.madr), gifch.qwc);
434 william 31 u32 *src;
435    
436 william 280 if(mfifoqwc == 0) return true; //Lets skip all this, we don't have the data
437    
438 william 62 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 william 280 GIF_LOG("MFIFO QWC to Transfer %x", mfifoqwc);
444 william 31 /* Check if the transfer should wrap around the ring buffer */
445 william 280 if ( (gifch.madr + (mfifoqwc * 16)) > (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16))
446 william 31 {
447 william 62 uint s1 = ((dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16) - gifch.madr) >> 4;
448 william 31 uint s2 = (mfifoqwc - s1);
449 william 280 GIF_LOG("Split transfer doing %x QWC of %x Total QWC", s1, mfifoqwc);
450 william 31 /* it does (wrap around), so first copy 's1' bytes from 'addr' to 'data' */
451 william 62 /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */
452 william 280
453     gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK);
454 william 62 src = (u32*)PSM(gifch.madr);
455 william 31 if (src == NULL) return false;
456 william 62 uint copied = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s1);
457 william 31
458 william 62 if (copied == s1) // but only copy second if first didn't abort prematurely for some reason.
459 william 31 {
460 william 280 GIF_LOG("Transferring last %x QWC", s2);
461 william 62 src = (u32*)PSM(dmacRegs.rbor.ADDR);
462 william 280 gifch.madr = dmacRegs.rbor.ADDR;
463 william 31 if (src == NULL) return false;
464 william 62 copied += GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s2);
465 william 31 }
466    
467 william 62 mfifoqwc = copied;
468 william 280 GIF_LOG("Copied %x QWC, %x QWC Left", mfifoqwc, gifch.qwc);
469 william 31 }
470     else
471     {
472 william 280 GIF_LOG("Direct MFIFO transfer doing %x Total QWC", mfifoqwc);
473 william 62 /* it doesn't, so just transfer 'qwc*16' words from 'gifch.madr' to GS */
474 william 280
475     gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK);
476 william 62 src = (u32*)PSM(gifch.madr);
477 william 31 if (src == NULL) return false;
478 william 62 mfifoqwc = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, mfifoqwc);
479 william 280 GIF_LOG("%X QWC Copied direct %x QWC Left", mfifoqwc, gifch.qwc);
480 william 31 }
481    
482 william 62 GetMTGS().SendDataPacket();
483 william 280 //gifqwc -= mfifoqwc;
484     mfifocycles += (mfifoqwc) * 2; /* guessing */
485 william 31
486     return true;
487     }
488    
489     // called from only one location, so forceinline it:
490 william 62 static __fi bool mfifoGIFchain()
491 william 31 {
492     /* Is QWC = 0? if so there is nothing to transfer */
493 william 62 if (gifch.qwc == 0) return true;
494 william 31
495 william 62 if (gifch.madr >= dmacRegs.rbor.ADDR &&
496 william 280 gifch.madr <= (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16))
497 william 31 {
498 william 280 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 william 401
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 william 280 return ret;
508    
509 william 31 }
510     else
511     {
512     int mfifoqwc;
513 william 280 GIF_LOG("Non-MFIFO Location transfer doing %x Total QWC", gifch.qwc);
514 william 62 tDMA_TAG *pMem = dmaGetAddr(gifch.madr, false);
515 william 31 if (pMem == NULL) return false;
516    
517 william 62 mfifoqwc = WRITERING_DMA(pMem, gifch.qwc);
518 william 31 mfifocycles += (mfifoqwc) * 2; /* guessing */
519     }
520    
521     return true;
522     }
523    
524     static u32 qwctag(u32 mask)
525     {
526 william 62 return (dmacRegs.rbor.ADDR + (mask & dmacRegs.rbsr.RMSK));
527 william 31 }
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 william 401 if ((gifstate & GIF_STATE_EMPTY))
539 william 280 {
540 william 401 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 william 280 }
545 william 401
546 william 280 gifRegs.stat.FQC = 16;
547     return;
548 william 31 }
549    
550 william 62 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 william 31
557 william 62 if (gifch.qwc == 0)
558 william 31 {
559 william 62 gifch.tadr = qwctag(gifch.tadr);
560 william 31
561 william 62 ptag = dmaGetAddr(gifch.tadr, false);
562     gifch.unsafeTransfer(ptag);
563     gifch.madr = ptag[1]._u32;
564 william 31
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 william 62 ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr, gifqwc, spr0ch.madr);
569 william 31
570 william 280 gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
571 william 31
572 william 280 if(gspath3done == true) gifstate = GIF_STATE_DONE;
573     else gifstate = GIF_STATE_READY;
574 william 31
575 william 62 if ((gifch.chcr.TIE) && (ptag->IRQ))
576 william 31 {
577     SPR_LOG("dmaIrq Set");
578     gifstate = GIF_STATE_DONE;
579     gifmfifoirq = true;
580     }
581 william 280 if (QWCinGIFMFIFO(gifch.tadr) == 0) gifstate |= GIF_STATE_EMPTY;
582     }
583 william 31
584 william 401 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 william 31 if (!mfifoGIFchain())
598     {
599 william 62 Console.WriteLn("GIF dmaChain error size=%d, madr=%lx, tadr=%lx", gifch.qwc, gifch.madr, gifch.tadr);
600 william 31 gifstate = GIF_STATE_STALL;
601     }
602    
603 william 280 if ((gifch.qwc == 0) && (gifstate & GIF_STATE_DONE)) gifstate |= GIF_STATE_STALL;
604 william 62 CPU_INT(DMAC_MFIFO_GIF,mfifocycles);
605 william 31
606 william 62 SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x", gifch.chcr._u32, gifch.madr, gifch.tadr);
607 william 31 }
608    
609     void gifMFIFOInterrupt()
610     {
611 william 280 GIF_LOG("gifMFIFOInterrupt");
612 william 31 mfifocycles = 0;
613    
614 william 280 if (dmacRegs.ctrl.MFD != MFD_GIF)
615     {
616     DevCon.Warning("Not in GIF MFIFO mode! Stopping GIF MFIFO");
617     return;
618     }
619    
620 william 62 if(SIGNAL_IMR_Pending == true)
621 william 31 {
622 william 62 //DevCon.Warning("Path 3 Paused");
623     CPU_INT(DMAC_MFIFO_GIF, 128);
624     return;
625 william 31 }
626    
627 william 401 if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE)
628     {
629 william 280 GSTransferStatus.PTH3 = STOPPED_MODE;
630 william 401
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 william 31 }
638    
639 william 280 if((gifstate & GIF_STATE_EMPTY))
640     {
641     FireMFIFOEmpty();
642     if(!(gifstate & GIF_STATE_STALL)) return;
643     }
644    
645 william 62 if(CheckPaths(11) == false) return;
646    
647     if (!(gifch.chcr.STR))
648 william 31 {
649     Console.WriteLn("WTF GIFMFIFO");
650     cpuRegs.interrupt &= ~(1 << 11);
651     return;
652     }
653    
654     if (!(gifstate & GIF_STATE_STALL))
655     {
656 william 280 if (QWCinGIFMFIFO(gifch.tadr) == 0)
657 william 31 {
658     gifstate |= GIF_STATE_EMPTY;
659 william 280 CPU_INT(DMAC_MFIFO_GIF, 4);
660 william 31 return;
661     }
662 william 280
663 william 31 mfifoGIFtransfer(0);
664     return;
665     }
666    
667     #ifdef PCSX2_DEVBUILD
668 william 62 if ((gifstate & GIF_STATE_READY) || (gifch.qwc > 0))
669 william 31 {
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 william 62 gifRegs.stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_P3Q | GIF_STAT_FQC); // APATH, P3Q, FQC = 0
681 william 31
682 william 62 vif1Regs.stat.VGW = false;
683     gifch.chcr.STR = false;
684 william 31 gifstate = GIF_STATE_READY;
685     hwDmacIrq(DMAC_GIF);
686 william 401 DMA_LOG("GIF MFIFO DMA End");
687 william 31 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 william 62
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 william 31 }

  ViewVC Help
Powered by ViewVC 1.1.22