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

Annotation of /trunk/pcsx2/Vif1_Dma.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (hide annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (9 years, 10 months ago) by william
File size: 13883 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     #include "Vif_Dma.h"
19     #include "GS.h"
20     #include "Gif.h"
21     #include "VUmicro.h"
22     #include "newVif.h"
23    
24 william 62
25     __fi void vif1FLUSH()
26 william 31 {
27 william 62 if(g_packetsizeonvu > vif1.vifpacketsize && g_vu1Cycles > 0)
28     {
29     //DevCon.Warning("Adding on same packet");
30     if( ((g_packetsizeonvu - vif1.vifpacketsize) >> 1) > g_vu1Cycles)
31     g_vu1Cycles -= (g_packetsizeonvu - vif1.vifpacketsize) >> 1;
32     else g_vu1Cycles = 0;
33     }
34     if(g_vu1Cycles > 0)
35     {
36     //DevCon.Warning("Adding %x cycles to VIF1", g_vu1Cycles * BIAS);
37     g_vifCycles += g_vu1Cycles;
38     g_vu1Cycles = 0;
39    
40     }
41     g_vu1Cycles = 0;//else DevCon.Warning("VIF1 Different Packet, how can i work this out :/");
42     if (VU0.VI[REG_VPU_STAT].UL & 0x100)
43     {
44     int _cycles = VU1.cycle;
45     vu1Finish();
46     //DevCon.Warning("VIF1 adding %x cycles", (VU1.cycle - _cycles) * BIAS);
47     g_vifCycles += (VU1.cycle - _cycles) * BIAS;
48     }
49     if(gifRegs.stat.P1Q && ((vif1.cmd & 0x7f) != 0x14) && ((vif1.cmd & 0x7f) != 0x17))
50     {
51     vif1.vifstalled = true;
52     vif1Regs.stat.VGW = true;
53     vif1.GifWaitState = 2;
54     }
55    
56 william 31 }
57    
58     void vif1TransferToMemory()
59     {
60     u32 size;
61 william 62 u64* pMem = (u64*)dmaGetAddr(vif1ch.madr, false);
62 william 31
63     // VIF from gsMemory
64     if (pMem == NULL) //Is vif0ptag empty?
65     {
66     Console.WriteLn("Vif1 Tag BUSERR");
67 william 62 dmacRegs.stat.BEIS = true; //Bus Error
68     vif1Regs.stat.FQC = 0;
69 william 31
70 william 62 vif1ch.qwc = 0;
71 william 31 vif1.done = true;
72     CPU_INT(DMAC_VIF1, 0);
73     return; //An error has occurred.
74     }
75    
76     // MTGS concerns: The MTGS is inherently disagreeable with the idea of downloading
77     // stuff from the GS. The *only* way to handle this case safely is to flush the GS
78     // completely and execute the transfer there-after.
79 william 62 //Console.Warning("Real QWC %x", vif1ch.qwc);
80     size = min((u32)vif1ch.qwc, vif1.GSLastDownloadSize);
81 william 31
82     if (GSreadFIFO2 == NULL)
83     {
84     for (;size > 0; --size)
85     {
86     GetMTGS().WaitGS();
87     GSreadFIFO(&psHu64(VIF1_FIFO));
88    
89     pMem[0] = psHu64(VIF1_FIFO);
90     pMem[1] = psHu64(VIF1_FIFO + 8);
91     pMem += 2;
92     }
93 william 62 if(vif1ch.qwc > vif1.GSLastDownloadSize)
94 william 31 {
95     DevCon.Warning("GS Transfer < VIF QWC, Clearing end of space");
96 william 62 for (size = vif1ch.qwc - vif1.GSLastDownloadSize; size > 0; --size)
97 william 31 {
98     psHu64(VIF1_FIFO) = 0;
99     psHu64(VIF1_FIFO + 8) = 0;
100     pMem[0] = psHu64(VIF1_FIFO);
101     pMem[1] = psHu64(VIF1_FIFO + 8);
102     pMem += 2;
103     }
104     }
105     }
106     else
107     {
108     GetMTGS().WaitGS();
109     GSreadFIFO2(pMem, size);
110    
111     // set incase read
112     psHu64(VIF1_FIFO) = pMem[2*size-2];
113     psHu64(VIF1_FIFO + 8) = pMem[2*size-1];
114     pMem += size * 2;
115 william 62 if(vif1ch.qwc > vif1.GSLastDownloadSize)
116 william 31 {
117     DevCon.Warning("GS Transfer < VIF QWC, Clearing end of space");
118 william 62 for (size = vif1ch.qwc - vif1.GSLastDownloadSize; size > 0; --size)
119 william 31 {
120     psHu64(VIF1_FIFO) = 0;
121     psHu64(VIF1_FIFO + 8) = 0;
122     pMem[0] = psHu64(VIF1_FIFO);
123     pMem[1] = psHu64(VIF1_FIFO + 8);
124     pMem += 2;
125     }
126     }
127     }
128    
129    
130 william 62 g_vifCycles += vif1ch.qwc * 2;
131     vif1ch.madr += vif1ch.qwc * 16; // mgs3 scene changes
132     if(vif1.GSLastDownloadSize >= vif1ch.qwc)
133 william 31 {
134 william 62 vif1.GSLastDownloadSize -= vif1ch.qwc;
135     vif1Regs.stat.FQC = min((u32)16, vif1.GSLastDownloadSize);
136 william 31 }
137     else
138     {
139 william 62 vif1Regs.stat.FQC = 0;
140 william 31 vif1.GSLastDownloadSize = 0;
141     }
142    
143 william 62 vif1ch.qwc = 0;
144 william 31 }
145    
146     bool _VIF1chain()
147     {
148     u32 *pMem;
149    
150 william 62 if (vif1ch.qwc == 0)
151 william 31 {
152 william 62 vif1.inprogress &= ~1;
153     vif1.irqoffset = 0;
154 william 31 return true;
155     }
156    
157     // Clarification - this is TO memory mode, for some reason i used the other way round >.<
158     if (vif1.dmamode == VIF_NORMAL_TO_MEM_MODE)
159     {
160     vif1TransferToMemory();
161 william 62 vif1.inprogress &= ~1;
162 william 31 return true;
163     }
164    
165 william 62 pMem = (u32*)dmaGetAddr(vif1ch.madr, !vif1ch.chcr.DIR);
166 william 31 if (pMem == NULL)
167     {
168     vif1.cmd = 0;
169     vif1.tag.size = 0;
170 william 62 vif1ch.qwc = 0;
171 william 31 return true;
172     }
173    
174     VIF_LOG("VIF1chain size=%d, madr=%lx, tadr=%lx",
175 william 62 vif1ch.qwc, vif1ch.madr, vif1ch.tadr);
176 william 31
177     if (vif1.vifstalled)
178 william 62 return VIF1transfer(pMem + vif1.irqoffset, vif1ch.qwc * 4 - vif1.irqoffset);
179 william 31 else
180 william 62 return VIF1transfer(pMem, vif1ch.qwc * 4);
181 william 31 }
182    
183 william 62 __fi void vif1SetupTransfer()
184 william 31 {
185     tDMA_TAG *ptag;
186 william 62
187 william 31 switch (vif1.dmamode)
188     {
189     case VIF_NORMAL_TO_MEM_MODE:
190     case VIF_NORMAL_FROM_MEM_MODE:
191 william 62 vif1.inprogress |= 1;
192 william 31 vif1.done = true;
193     g_vifCycles = 2;
194 william 62 break;
195 william 31
196     case VIF_CHAIN_MODE:
197 william 62 ptag = dmaGetAddr(vif1ch.tadr, false); //Set memory pointer to TADR
198 william 31
199 william 62 if (!(vif1ch.transfer("Vif1 Tag", ptag))) return;
200 william 31
201 william 62 vif1ch.madr = ptag[1]._u32; //MADR = ADDR field + SPR
202 william 31 g_vifCycles += 1; // Add 1 g_vifCycles from the QW read for the tag
203    
204 william 62 VIF_LOG("VIF1 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx",
205     ptag[1]._u32, ptag[0]._u32, vif1ch.qwc, ptag->ID, vif1ch.madr, vif1ch.tadr);
206 william 31
207 william 62 if (!vif1.done && ((dmacRegs.ctrl.STD == STD_VIF1) && (ptag->ID == TAG_REFS))) // STD == VIF1
208 william 31 {
209     // there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall
210 william 62 if ((vif1ch.madr + vif1ch.qwc * 16) >= dmacRegs.stadr.ADDR)
211 william 31 {
212     // stalled
213     hwDmacIrq(DMAC_STALL_SIS);
214     return;
215     }
216     }
217    
218 william 62
219     vif1.inprogress &= ~1;
220 william 31
221 william 62 if (vif1ch.chcr.TTE)
222 william 31 {
223 william 62 // Transfer dma tag if tte is set
224    
225 william 31 bool ret;
226    
227     if (vif1.vifstalled)
228 william 62 {
229     ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset); //Transfer Tag on stall
230     }
231 william 31 else
232 william 62 ret = VIF1transfer((u32*)ptag + 2, 2); //Transfer Tag
233    
234     if (!ret && vif1.irqoffset < 2)
235 william 31 {
236 william 62 vif1.inprogress &= ~1; //Better clear this so it has to do it again (Jak 1)
237     return; //IRQ set by VIFTransfer
238    
239     } //else vif1.vifstalled = false;
240 william 31 }
241 william 62 vif1.irqoffset = 0;
242 william 31
243     vif1.done |= hwDmacSrcChainWithStack(vif1ch, ptag->ID);
244    
245 william 62 if(vif1ch.qwc > 0) vif1.inprogress |= 1;
246    
247 william 31 //Check TIE bit of CHCR and IRQ bit of tag
248 william 62 if (vif1ch.chcr.TIE && ptag->IRQ)
249 william 31 {
250     VIF_LOG("dmaIrq Set");
251    
252     //End Transfer
253     vif1.done = true;
254     return;
255     }
256 william 62 break;
257 william 31 }
258     }
259    
260 william 62 extern bool SIGNAL_IMR_Pending;
261    
262     bool CheckPath2GIF(EE_EventType channel)
263 william 31 {
264 william 62 if ((vif1Regs.stat.VGW))
265     {
266     if( vif1.GifWaitState == 0 ) //DIRECT/HL Check
267     {
268     if(GSTransferStatus.PTH3 < IDLE_MODE || gifRegs.stat.P1Q)
269     {
270     if(gifRegs.stat.IMT && GSTransferStatus.PTH3 <= IMAGE_MODE && (vif1.cmd & 0x7f) == 0x50 && gifRegs.stat.P1Q == false)
271     {
272     vif1Regs.stat.VGW = false;
273     }
274     else
275     {
276     //DevCon.Warning("VIF1-0 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
277     CPU_INT(channel, 128);
278     return false;
279     }
280     }
281     else
282     {
283     vif1Regs.stat.VGW = false;
284     }
285     }
286     else if( vif1.GifWaitState == 1 ) // Else we're flushing path3 :), but of course waiting for the microprogram to finish
287     {
288     if (gifRegs.stat.P1Q)
289     {
290     //DevCon.Warning("VIF1-1 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
291     CPU_INT(channel, 128);
292     return false;
293     }
294    
295     if (GSTransferStatus.PTH3 < IDLE_MODE)
296     {
297     //DevCon.Warning("VIF1-11 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
298     //DevCon.Warning("PTH3 %x P1Q %x P3Q %x IP3 %x", GSTransferStatus.PTH3, gifRegs.stat.P1Q, gifRegs.stat.P3Q, gifRegs.stat.IP3 );
299     CPU_INT(channel, 8);
300     return false;
301     }
302     else
303     {
304     vif1Regs.stat.VGW = false;
305     }
306     }
307     else if( vif1.GifWaitState == 3 ) // Else we're flushing path3 :), but of course waiting for the microprogram to finish
308     {
309     if (gifRegs.ctrl.PSE)
310     {
311     //DevCon.Warning("VIF1-1 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
312     CPU_INT(channel, 128);
313     return false;
314     }
315     else
316     {
317     vif1Regs.stat.VGW = false;
318     }
319     }
320     else //Normal Flush
321     {
322     if (gifRegs.stat.P1Q)
323     {
324     //DevCon.Warning("VIF1-2 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
325     CPU_INT(channel, 128);
326     return false;
327     }
328     else
329     {
330     vif1Regs.stat.VGW = false;
331     }
332     }
333     }
334     if(SIGNAL_IMR_Pending == true && (vif1.cmd & 0x7e) == 0x50)
335     {
336     //DevCon.Warning("Path 2 Paused");
337     CPU_INT(channel, 128);
338     return false;
339     }
340     return true;
341     }
342     __fi void vif1Interrupt()
343     {
344 william 31 VIF_LOG("vif1Interrupt: %8.8x", cpuRegs.cycle);
345    
346     g_vifCycles = 0;
347    
348 william 62 if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH2)
349     {
350     gifRegs.stat.OPH = false;
351     gifRegs.stat.APATH = GIF_APATH_IDLE;
352     if(gifRegs.stat.P1Q) gsPath1Interrupt();
353     }
354    
355     if (schedulepath3msk & 0x10)
356     {
357     Vif1MskPath3();
358     CPU_INT(DMAC_VIF1, 8);
359     return;
360     }
361 william 31 //Some games (Fahrenheit being one) start vif first, let it loop through blankness while it sets MFIFO mode, so we need to check it here.
362 william 62 if (dmacRegs.ctrl.MFD == MFD_VIF1)
363 william 31 {
364     //Console.WriteLn("VIFMFIFO\n");
365     // Test changed because the Final Fantasy 12 opening somehow has the tag in *Undefined* mode, which is not in the documentation that I saw.
366 william 62 if (vif1ch.chcr.MOD == NORMAL_MODE) Console.WriteLn("MFIFO mode is normal (which isn't normal here)! %x", vif1ch.chcr._u32);
367     vif1Regs.stat.FQC = min((u16)0x10, vif1ch.qwc);
368 william 31 vifMFIFOInterrupt();
369     return;
370     }
371    
372 william 62 //We need to check the direction, if it is downloading from the GS, we handle that separately (KH2 for testing)
373     if (vif1ch.chcr.DIR)
374 william 31 {
375 william 62 if (!CheckPath2GIF(DMAC_VIF1)) return;
376    
377     vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
378     //Simulated GS transfer time done, clear the flags
379 william 31 }
380 william 62
381     if (!vif1ch.chcr.STR) Console.WriteLn("Vif1 running when CHCR == %x", vif1ch.chcr._u32);
382 william 31
383 william 62 if (vif1.cmd)
384 william 31 {
385 william 62 if (vif1.done && (vif1ch.qwc == 0)) vif1Regs.stat.VPS = VPS_WAITING;
386 william 31 }
387 william 62 else
388     {
389     vif1Regs.stat.VPS = VPS_IDLE;
390     }
391 william 31
392     if (vif1.irq && vif1.tag.size == 0)
393     {
394 william 62 vif1Regs.stat.INT = true;
395 william 31 hwIntcIrq(VIF1intc);
396     --vif1.irq;
397 william 62 if (vif1Regs.stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
398 william 31 {
399 william 62 //vif1Regs.stat.FQC = 0;
400 william 31
401 william 62 //NFSHPS stalls when the whole packet has gone across (it stalls in the last 32bit cmd)
402     //In this case VIF will end
403     if(vif1ch.qwc > 0 || !vif1.done) return;
404 william 31 }
405     }
406    
407     if (vif1.inprogress & 0x1)
408     {
409     _VIF1chain();
410     // VIF_NORMAL_FROM_MEM_MODE is a very slow operation.
411     // Timesplitters 2 depends on this beeing a bit higher than 128.
412 william 62 if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
413 william 31 // Refraction - Removing voodoo timings for now, completely messes a lot of Path3 masked games.
414     /*if (vif1.dmamode == VIF_NORMAL_FROM_MEM_MODE ) CPU_INT(DMAC_VIF1, 1024);
415     else */CPU_INT(DMAC_VIF1, g_vifCycles /*VifCycleVoodoo*/);
416     return;
417     }
418    
419     if (!vif1.done)
420     {
421    
422 william 62 if (!(dmacRegs.ctrl.DMAE))
423 william 31 {
424     Console.WriteLn("vif1 dma masked");
425     return;
426     }
427    
428     if ((vif1.inprogress & 0x1) == 0) vif1SetupTransfer();
429 william 62 if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
430 william 31 CPU_INT(DMAC_VIF1, g_vifCycles);
431     return;
432     }
433    
434     if (vif1.vifstalled && vif1.irq)
435     {
436     DevCon.WriteLn("VIF1 looping on stall\n");
437     CPU_INT(DMAC_VIF1, 0);
438     return; //Dont want to end if vif is stalled.
439     }
440     #ifdef PCSX2_DEVBUILD
441 william 62 if (vif1ch.qwc > 0) Console.WriteLn("VIF1 Ending with %x QWC left", vif1ch.qwc);
442 william 31 if (vif1.cmd != 0) Console.WriteLn("vif1.cmd still set %x tag size %x", vif1.cmd, vif1.tag.size);
443     #endif
444    
445 william 62 if((vif1ch.chcr.DIR == VIF_NORMAL_TO_MEM_MODE) && vif1.GSLastDownloadSize <= 16)
446     {
447     //Reverse fifo has finished and nothing is left, so lets clear the outputting flag
448     gifRegs.stat.OPH = false;
449 william 31 }
450 william 62
451     vif1ch.chcr.STR = false;
452     vif1.vifstalled = false;
453 william 31 g_vifCycles = 0;
454 william 62 g_vu1Cycles = 0;
455 william 31 VIF_LOG("VIF1 End");
456     hwDmacIrq(DMAC_VIF1);
457    
458     }
459    
460     void dmaVIF1()
461     {
462     VIF_LOG("dmaVIF1 chcr = %lx, madr = %lx, qwc = %lx\n"
463     " tadr = %lx, asr0 = %lx, asr1 = %lx",
464 william 62 vif1ch.chcr._u32, vif1ch.madr, vif1ch.qwc,
465     vif1ch.tadr, vif1ch.asr0, vif1ch.asr1);
466 william 31
467 william 62 // vif1.done = false;
468    
469     //if(vif1.irqoffset != 0 && vif1.vifstalled == true) DevCon.Warning("Offset on VIF1 start! offset %x, Progress %x", vif1.irqoffset, vif1.vifstalled);
470     /*vif1.irqoffset = 0;
471     vif1.vifstalled = false;
472     vif1.inprogress = 0;*/
473 william 31 g_vifCycles = 0;
474 william 62 g_vu1Cycles = 0;
475 william 31
476     #ifdef PCSX2_DEVBUILD
477 william 62 if (dmacRegs.ctrl.STD == STD_VIF1)
478 william 31 {
479     //DevCon.WriteLn("VIF Stall Control Source = %x, Drain = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3);
480     }
481     #endif
482    
483 william 62 if ((vif1ch.chcr.MOD == NORMAL_MODE) || vif1ch.qwc > 0) // Normal Mode
484 william 31 {
485    
486 william 62 if (dmacRegs.ctrl.STD == STD_VIF1)
487 william 31 Console.WriteLn("DMA Stall Control on VIF1 normal");
488    
489 william 62 if (vif1ch.chcr.DIR) // to Memory
490 william 31 vif1.dmamode = VIF_NORMAL_FROM_MEM_MODE;
491     else
492     vif1.dmamode = VIF_NORMAL_TO_MEM_MODE;
493    
494 william 62 vif1.done = false;
495    
496     // ignore tag if it's a GS download (Def Jam Fight for NY)
497     if(vif1ch.chcr.MOD == CHAIN_MODE && vif1.dmamode != VIF_NORMAL_TO_MEM_MODE)
498     {
499     vif1.dmamode = VIF_CHAIN_MODE;
500     DevCon.Warning(L"VIF1 QWC on Chain CHCR " + vif1ch.chcr.desc());
501    
502     if ((vif1ch.chcr.tag().ID == TAG_REFE) || (vif1ch.chcr.tag().ID == TAG_END))
503     {
504     vif1.done = true;
505     }
506     }
507 william 31 }
508     else
509     {
510     vif1.dmamode = VIF_CHAIN_MODE;
511 william 62 vif1.done = false;
512 william 31 }
513    
514 william 62 if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min((u16)0x10, vif1ch.qwc);
515 william 31
516     // Chain Mode
517 william 62 CPU_INT(DMAC_VIF1, 4);
518 william 31 }

  ViewVC Help
Powered by ViewVC 1.1.22