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

  ViewVC Help
Powered by ViewVC 1.1.22