/[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 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (9 years, 10 months ago) by william
File size: 10354 byte(s)
committing r3113 initial commit again...
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     __forceinline void vif1FLUSH()
25     {
26     if (!(VU0.VI[REG_VPU_STAT].UL & 0x100)) return;
27     int _cycles = VU1.cycle;
28     vu1Finish();
29     g_vifCycles += (VU1.cycle - _cycles) * BIAS;
30     }
31    
32     void vif1TransferToMemory()
33     {
34     u32 size;
35     u64* pMem = (u64*)dmaGetAddr(vif1ch->madr, false);
36    
37     // VIF from gsMemory
38     if (pMem == NULL) //Is vif0ptag empty?
39     {
40     Console.WriteLn("Vif1 Tag BUSERR");
41     dmacRegs->stat.BEIS = true; //Bus Error
42     vif1Regs->stat.FQC = 0;
43    
44     vif1ch->qwc = 0;
45     vif1.done = true;
46     CPU_INT(DMAC_VIF1, 0);
47     return; //An error has occurred.
48     }
49    
50     // MTGS concerns: The MTGS is inherently disagreeable with the idea of downloading
51     // stuff from the GS. The *only* way to handle this case safely is to flush the GS
52     // completely and execute the transfer there-after.
53     //Console.Warning("Real QWC %x", vif1ch->qwc);
54     XMMRegisters::Freeze();
55    
56     size = min((u32)vif1ch->qwc, vif1.GSLastDownloadSize);
57    
58     if (GSreadFIFO2 == NULL)
59     {
60     for (;size > 0; --size)
61     {
62     GetMTGS().WaitGS();
63     GSreadFIFO(&psHu64(VIF1_FIFO));
64    
65     pMem[0] = psHu64(VIF1_FIFO);
66     pMem[1] = psHu64(VIF1_FIFO + 8);
67     pMem += 2;
68     }
69     if(vif1ch->qwc > vif1.GSLastDownloadSize)
70     {
71     DevCon.Warning("GS Transfer < VIF QWC, Clearing end of space");
72     for (size = vif1ch->qwc - vif1.GSLastDownloadSize; size > 0; --size)
73     {
74     psHu64(VIF1_FIFO) = 0;
75     psHu64(VIF1_FIFO + 8) = 0;
76     pMem[0] = psHu64(VIF1_FIFO);
77     pMem[1] = psHu64(VIF1_FIFO + 8);
78     pMem += 2;
79     }
80     }
81     }
82     else
83     {
84     GetMTGS().WaitGS();
85     GSreadFIFO2(pMem, size);
86    
87     // set incase read
88     psHu64(VIF1_FIFO) = pMem[2*size-2];
89     psHu64(VIF1_FIFO + 8) = pMem[2*size-1];
90     pMem += size * 2;
91     if(vif1ch->qwc > vif1.GSLastDownloadSize)
92     {
93     DevCon.Warning("GS Transfer < VIF QWC, Clearing end of space");
94     for (size = vif1ch->qwc - vif1.GSLastDownloadSize; size > 0; --size)
95     {
96     psHu64(VIF1_FIFO) = 0;
97     psHu64(VIF1_FIFO + 8) = 0;
98     pMem[0] = psHu64(VIF1_FIFO);
99     pMem[1] = psHu64(VIF1_FIFO + 8);
100     pMem += 2;
101     }
102     }
103     }
104    
105    
106     XMMRegisters::Thaw();
107    
108     g_vifCycles += vif1ch->qwc * 2;
109     vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes
110     if(vif1.GSLastDownloadSize >= vif1ch->qwc)
111     {
112     vif1.GSLastDownloadSize -= vif1ch->qwc;
113     vif1Regs->stat.FQC = min((u32)16, vif1.GSLastDownloadSize);
114     }
115     else
116     {
117     vif1Regs->stat.FQC = 0;
118     vif1.GSLastDownloadSize = 0;
119     }
120    
121     vif1ch->qwc = 0;
122     }
123    
124     bool _VIF1chain()
125     {
126     u32 *pMem;
127    
128     if (vif1ch->qwc == 0)
129     {
130     vif1.inprogress = 0;
131     return true;
132     }
133    
134     // Clarification - this is TO memory mode, for some reason i used the other way round >.<
135     if (vif1.dmamode == VIF_NORMAL_TO_MEM_MODE)
136     {
137     vif1TransferToMemory();
138     vif1.inprogress = 0;
139     return true;
140     }
141    
142     pMem = (u32*)dmaGetAddr(vif1ch->madr, !vif1ch->chcr.DIR);
143     if (pMem == NULL)
144     {
145     vif1.cmd = 0;
146     vif1.tag.size = 0;
147     vif1ch->qwc = 0;
148     return true;
149     }
150    
151     VIF_LOG("VIF1chain size=%d, madr=%lx, tadr=%lx",
152     vif1ch->qwc, vif1ch->madr, vif1ch->tadr);
153    
154     if (vif1.vifstalled)
155     return VIF1transfer(pMem + vif1.irqoffset, vif1ch->qwc * 4 - vif1.irqoffset, false);
156     else
157     return VIF1transfer(pMem, vif1ch->qwc * 4, false);
158     }
159    
160     __forceinline void vif1SetupTransfer()
161     {
162     tDMA_TAG *ptag;
163    
164     switch (vif1.dmamode)
165     {
166     case VIF_NORMAL_TO_MEM_MODE:
167     case VIF_NORMAL_FROM_MEM_MODE:
168     vif1.inprogress = 1;
169     vif1.done = true;
170     g_vifCycles = 2;
171     break;
172    
173     case VIF_CHAIN_MODE:
174     ptag = dmaGetAddr(vif1ch->tadr, false); //Set memory pointer to TADR
175    
176     if (!(vif1ch->transfer("Vif1 Tag", ptag))) return;
177    
178     vif1ch->madr = ptag[1]._u32; //MADR = ADDR field + SPR
179     g_vifCycles += 1; // Add 1 g_vifCycles from the QW read for the tag
180    
181     // Transfer dma tag if tte is set
182    
183     VIF_LOG("VIF1 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n",
184     ptag[1]._u32, ptag[0]._u32, vif1ch->qwc, ptag->ID, vif1ch->madr, vif1ch->tadr);
185    
186     if (!vif1.done && ((dmacRegs->ctrl.STD == STD_VIF1) && (ptag->ID == TAG_REFS))) // STD == VIF1
187     {
188     // there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall
189     if ((vif1ch->madr + vif1ch->qwc * 16) >= dmacRegs->stadr.ADDR)
190     {
191     // stalled
192     hwDmacIrq(DMAC_STALL_SIS);
193     return;
194     }
195     }
196    
197     vif1.inprogress = 1;
198    
199     if (vif1ch->chcr.TTE)
200     {
201     bool ret;
202    
203     if (vif1.vifstalled)
204     ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset, true); //Transfer Tag on stall
205     else
206     ret = VIF1transfer((u32*)ptag + 2, 2, true); //Transfer Tag
207    
208     if ((ret == false) && vif1.irqoffset < 2)
209     {
210     vif1.inprogress = 0; //Better clear this so it has to do it again (Jak 1)
211     return; //There has been an error or an interrupt
212     }
213     }
214    
215     vif1.irqoffset = 0;
216     vif1.done |= hwDmacSrcChainWithStack(vif1ch, ptag->ID);
217    
218     //Check TIE bit of CHCR and IRQ bit of tag
219     if (vif1ch->chcr.TIE && ptag->IRQ)
220     {
221     VIF_LOG("dmaIrq Set");
222    
223     //End Transfer
224     vif1.done = true;
225     return;
226     }
227     break;
228     }
229     }
230    
231     __forceinline void vif1Interrupt()
232     {
233     VIF_LOG("vif1Interrupt: %8.8x", cpuRegs.cycle);
234    
235     g_vifCycles = 0;
236    
237     //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.
238     if (dmacRegs->ctrl.MFD == MFD_VIF1) // VIF MFIFO
239     {
240     //Console.WriteLn("VIFMFIFO\n");
241     // Test changed because the Final Fantasy 12 opening somehow has the tag in *Undefined* mode, which is not in the documentation that I saw.
242     if (vif1ch->chcr.MOD == NORMAL_MODE) Console.WriteLn("MFIFO mode is normal (which isn't normal here)! %x", vif1ch->chcr._u32);
243     vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc);
244     vifMFIFOInterrupt();
245     return;
246     }
247    
248     //We need to check the direction, if it is downloading from the GS, we handle that seperately (KH2 for testing)
249     if (vif1ch->chcr.DIR)vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16);
250     //Simulated GS transfer time done, clear the flags
251     if(gifRegs->stat.APATH == GIF_APATH2 && (vif1.cmd & 0x70) != 0x50)
252     {
253     gifRegs->stat.APATH = GIF_APATH_IDLE;
254     }
255    
256     if (schedulepath3msk & 0x10) Vif1MskPath3();
257    
258     if ((vif1Regs->stat.VGW))
259     {
260     if (GSTransferStatus.PTH3 < STOPPED_MODE || GSTransferStatus.PTH1 != STOPPED_MODE)
261     {
262     CPU_INT(DMAC_VIF1, 4);
263     return;
264     }
265     else
266     {
267     vif1Regs->stat.VGW = false;
268     }
269     }
270    
271     if (!(vif1ch->chcr.STR)) Console.WriteLn("Vif1 running when CHCR == %x", vif1ch->chcr._u32);
272    
273     if (vif1.irq && vif1.tag.size == 0)
274     {
275     vif1Regs->stat.INT = true;
276     hwIntcIrq(VIF1intc);
277     --vif1.irq;
278     if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS))
279     {
280     //vif1Regs->stat.FQC = 0;
281    
282     // One game doesn't like vif stalling at end, can't remember what. Spiderman isn't keen on it tho
283     vif1ch->chcr.STR = false;
284     return;
285     }
286     else if ((vif1ch->qwc > 0) || (vif1.irqoffset > 0))
287     {
288     if (vif1.stallontag)
289     vif1SetupTransfer();
290     else
291     _VIF1chain();//CPU_INT(DMAC_STALL_SIS, vif1ch->qwc * BIAS);
292     }
293     }
294    
295     if (vif1.inprogress & 0x1)
296     {
297     _VIF1chain();
298     // VIF_NORMAL_FROM_MEM_MODE is a very slow operation.
299     // Timesplitters 2 depends on this beeing a bit higher than 128.
300     if (vif1ch->chcr.DIR) vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16);
301     // Refraction - Removing voodoo timings for now, completely messes a lot of Path3 masked games.
302     /*if (vif1.dmamode == VIF_NORMAL_FROM_MEM_MODE ) CPU_INT(DMAC_VIF1, 1024);
303     else */CPU_INT(DMAC_VIF1, g_vifCycles /*VifCycleVoodoo*/);
304     return;
305     }
306    
307     if (!vif1.done)
308     {
309    
310     if (!(dmacRegs->ctrl.DMAE))
311     {
312     Console.WriteLn("vif1 dma masked");
313     return;
314     }
315    
316     if ((vif1.inprogress & 0x1) == 0) vif1SetupTransfer();
317     if (vif1ch->chcr.DIR) vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16);
318     CPU_INT(DMAC_VIF1, g_vifCycles);
319     return;
320     }
321    
322     if (vif1.vifstalled && vif1.irq)
323     {
324     DevCon.WriteLn("VIF1 looping on stall\n");
325     CPU_INT(DMAC_VIF1, 0);
326     return; //Dont want to end if vif is stalled.
327     }
328     #ifdef PCSX2_DEVBUILD
329     if (vif1ch->qwc > 0) Console.WriteLn("VIF1 Ending with %x QWC left");
330     if (vif1.cmd != 0) Console.WriteLn("vif1.cmd still set %x tag size %x", vif1.cmd, vif1.tag.size);
331     #endif
332    
333     vif1Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands;
334     if((vif1ch->chcr.DIR == VIF_NORMAL_TO_MEM_MODE) && vif1.GSLastDownloadSize <= 16)
335     { //Reverse fifo has finished and nothing is left, so lets clear the outputting flag
336     gifRegs->stat.OPH = false;
337     }
338     vif1ch->chcr.STR = false;
339     g_vifCycles = 0;
340     VIF_LOG("VIF1 End");
341     hwDmacIrq(DMAC_VIF1);
342    
343     }
344    
345     void dmaVIF1()
346     {
347     VIF_LOG("dmaVIF1 chcr = %lx, madr = %lx, qwc = %lx\n"
348     " tadr = %lx, asr0 = %lx, asr1 = %lx",
349     vif1ch->chcr._u32, vif1ch->madr, vif1ch->qwc,
350     vif1ch->tadr, vif1ch->asr0, vif1ch->asr1);
351    
352     vif1.done = false;
353     g_vifCycles = 0;
354     vif1.inprogress = 0;
355    
356     #ifdef PCSX2_DEVBUILD
357     if (dmacRegs->ctrl.STD == STD_VIF1)
358     {
359     //DevCon.WriteLn("VIF Stall Control Source = %x, Drain = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3);
360     }
361     #endif
362    
363     if ((vif1ch->chcr.MOD == NORMAL_MODE) || vif1ch->qwc > 0) // Normal Mode
364     {
365    
366     if (dmacRegs->ctrl.STD == STD_VIF1)
367     Console.WriteLn("DMA Stall Control on VIF1 normal");
368    
369     if (vif1ch->chcr.DIR) // to Memory
370     vif1.dmamode = VIF_NORMAL_FROM_MEM_MODE;
371     else
372     vif1.dmamode = VIF_NORMAL_TO_MEM_MODE;
373    
374     if(vif1ch->chcr.MOD == CHAIN_MODE && vif1ch->qwc > 0) DevCon.Warning(L"VIF1 QWC on Chain CHCR " + vif1ch->chcr.desc());
375     }
376     else
377     {
378     vif1.dmamode = VIF_CHAIN_MODE;
379     }
380    
381     if (vif1ch->chcr.DIR) vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc);
382    
383     // Chain Mode
384     vif1Interrupt();
385     }

  ViewVC Help
Powered by ViewVC 1.1.22