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

Contents of /trunk/pcsx2/Vif1_Dma.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 4 months ago) by william
File size: 10354 byte(s)
committing r3113 initial commit again...
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 #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